-
Notifications
You must be signed in to change notification settings - Fork 112
Convenience method to allow customizing route dependencies #295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
8aa418a
Support customizing route dependencies
alukach 369ef76
Refactor to support direct method calls
alukach c331ddd
Lint fixup
alukach ae0ce14
Reorg for legibility, code organization
alukach f7239fb
Lint fix
alukach fd768fa
Lint fix
alukach b7921e2
Add missing import
alukach fe10daf
Use app router
alukach e70248d
Lint fix
alukach 99445db
Ensure dependencies persist if attached to router
alukach 88a7ff9
Cleanup comments
alukach 7a2fb74
Merge remote-tracking branch 'upstream/master' into patch-1
alukach 146e28b
Add tests for stac_api core
alukach 8cd340b
Cleanup
alukach 6388ab9
Apply isort
alukach 842eebc
Add to changelog
alukach b7eda80
Add docstring
alukach 1ac18df
Format code
alukach fb30d2b
Merge branch 'master' into patch-1
vincentsarago File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
from fastapi import Depends, HTTPException, security, status | ||
from starlette.testclient import TestClient | ||
|
||
from stac_fastapi.api.app import StacApi | ||
from stac_fastapi.extensions.core import TokenPaginationExtension, TransactionExtension | ||
from stac_fastapi.types import config, core | ||
|
||
|
||
class TestRouteDependencies: | ||
@staticmethod | ||
def _build_api(**overrides): | ||
settings = config.ApiSettings() | ||
return StacApi( | ||
**{ | ||
"settings": settings, | ||
"client": DummyCoreClient(), | ||
"extensions": [ | ||
TransactionExtension( | ||
client=DummyTransactionsClient(), settings=settings | ||
), | ||
TokenPaginationExtension(), | ||
], | ||
**overrides, | ||
} | ||
) | ||
|
||
@staticmethod | ||
def _assert_dependency_applied(api, routes): | ||
with TestClient(api.app) as client: | ||
for route in routes: | ||
response = getattr(client, route["method"].lower())(route["path"]) | ||
assert ( | ||
response.status_code == 401 | ||
), "Unauthenticated requests should be rejected" | ||
assert response.json() == {"detail": "Not authenticated"} | ||
|
||
make_request = getattr(client, route["method"].lower()) | ||
path = route["path"].format( | ||
collectionId="test_collection", itemId="test_item" | ||
) | ||
response = make_request( | ||
path, | ||
auth=("bob", "dobbs"), | ||
data='{"dummy": "payload"}', | ||
headers={"content-type": "application/json"}, | ||
) | ||
assert ( | ||
response.status_code == 200 | ||
), "Authenticated requests should be accepted" | ||
assert response.json() == "dummy response" | ||
|
||
def test_build_api_with_route_dependencies(self): | ||
routes = [ | ||
{"path": "/collections", "method": "POST"}, | ||
{"path": "/collections", "method": "PUT"}, | ||
{"path": "/collections/{collectionId}", "method": "DELETE"}, | ||
{"path": "/collections/{collectionId}/items", "method": "POST"}, | ||
{"path": "/collections/{collectionId}/items", "method": "PUT"}, | ||
{"path": "/collections/{collectionId}/items/{itemId}", "method": "DELETE"}, | ||
] | ||
dependencies = [Depends(must_be_bob)] | ||
api = self._build_api(route_dependencies=[(routes, dependencies)]) | ||
self._assert_dependency_applied(api, routes) | ||
|
||
def test_add_route_dependencies_after_building_api(self): | ||
routes = [ | ||
{"path": "/collections", "method": "POST"}, | ||
{"path": "/collections", "method": "PUT"}, | ||
{"path": "/collections/{collectionId}", "method": "DELETE"}, | ||
{"path": "/collections/{collectionId}/items", "method": "POST"}, | ||
{"path": "/collections/{collectionId}/items", "method": "PUT"}, | ||
{"path": "/collections/{collectionId}/items/{itemId}", "method": "DELETE"}, | ||
] | ||
api = self._build_api() | ||
api.add_route_dependencies(scopes=routes, dependencies=[Depends(must_be_bob)]) | ||
self._assert_dependency_applied(api, routes) | ||
|
||
|
||
class DummyCoreClient(core.BaseCoreClient): | ||
def all_collections(self, *args, **kwargs): | ||
... | ||
|
||
def get_collection(self, *args, **kwargs): | ||
... | ||
|
||
def get_item(self, *args, **kwargs): | ||
... | ||
|
||
def get_search(self, *args, **kwargs): | ||
... | ||
|
||
def post_search(self, *args, **kwargs): | ||
... | ||
|
||
def item_collection(self, *args, **kwargs): | ||
... | ||
|
||
|
||
class DummyTransactionsClient(core.BaseTransactionsClient): | ||
"""Defines a pattern for implementing the STAC transaction extension.""" | ||
|
||
def create_item(self, *args, **kwargs): | ||
return "dummy response" | ||
|
||
def update_item(self, *args, **kwargs): | ||
return "dummy response" | ||
|
||
def delete_item(self, *args, **kwargs): | ||
return "dummy response" | ||
|
||
def create_collection(self, *args, **kwargs): | ||
return "dummy response" | ||
|
||
def update_collection(self, *args, **kwargs): | ||
return "dummy response" | ||
|
||
def delete_collection(self, *args, **kwargs): | ||
return "dummy response" | ||
|
||
|
||
def must_be_bob( | ||
credentials: security.HTTPBasicCredentials = Depends(security.HTTPBasic()), | ||
): | ||
if credentials.username == "bob": | ||
return True | ||
|
||
raise HTTPException( | ||
status_code=status.HTTP_401_UNAUTHORIZED, | ||
detail="You're not Bob", | ||
headers={"WWW-Authenticate": "Basic"}, | ||
) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.