Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ACL-based auth policy and the @permission_required_for_context decora…
…tor. For now used with /users API (#234) * first implementation of ACL-based auth policy and the @permission_required_for_context decorator. Used for one /user endpoint (GET /user/<id>) * make GET /users and PATCH /user/<id> work. Inn the process simplifying /users to work for one account only, and moving API context factories to a common location * resolve circular import * always log the authorization failure for debugging purposes * adapt UI crud so it lists users from all accounts again after API simplification * check for valid permissions and allow the ADMIN_READER role to read * separate checking admin access and principals within policy, add tests for principals matching * changelog entry * fix test * Add test for multiple roles and multiple account roles * smaller haul from review * replace deprecated marshmallow parameters * explicitly require marshmallow>3 as we use recent parameters (app.txt already pins it >3) * replace load_account with Marshmallow field; enable the permission-checking decorator to get the resource from keyword args * move load_user factory to marshmallow field, as well; refactor permission decorator a bit * update documentation * permissions: use update over write (-> CRUD) * use @auth_required in place of @login_required in non-user-facing endpoints * doc improvements from review * nicer way to state conditions for account roles decorators * Typo * Auth decorators raise 403/401, simplify invalid_sender * Add type annotation * nicer error messages in auth decorators Co-authored-by: F.N. Claessen <felix@seita.nl>
- Loading branch information
Showing
23 changed files
with
510 additions
and
192 deletions.
There are no files selected for viewing
This file contains 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 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 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 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 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 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,47 @@ | ||
from flask import abort | ||
from flask_security import current_user | ||
from marshmallow import fields | ||
|
||
from flexmeasures.data.models.user import User, Account | ||
|
||
|
||
class AccountIdField(fields.Integer): | ||
""" | ||
Field that represents an account ID. It de-serializes from the account id to an account instance. | ||
""" | ||
|
||
def __init__(self, *args, **kwargs): | ||
kwargs["load_default"] = ( | ||
lambda: current_user.account if not current_user.is_anonymous else None | ||
) | ||
super().__init__(*args, **kwargs) | ||
|
||
def _deserialize(self, account_id: int, attr, obj, **kwargs) -> Account: | ||
account: Account = Account.query.filter_by(id=int(account_id)).one_or_none() | ||
if account is None: | ||
raise abort(404, f"Account {id} not found") | ||
return account | ||
|
||
def _serialize(self, account: Account, attr, data, **kwargs) -> int: | ||
return account.id | ||
|
||
|
||
class UserIdField(fields.Integer): | ||
""" | ||
Field that represents a user ID. It de-serializes from the user id to a user instance. | ||
""" | ||
|
||
def __init__(self, *args, **kwargs): | ||
kwargs["load_default"] = ( | ||
lambda: current_user if not current_user.is_anonymous else None | ||
) | ||
super().__init__(*args, **kwargs) | ||
|
||
def _deserialize(self, user_id: int, attr, obj, **kwargs) -> User: | ||
user: User = User.query.filter_by(id=int(user_id)).one_or_none() | ||
if user is None: | ||
raise abort(404, f"User {id} not found") | ||
return user | ||
|
||
def _serialize(self, user: User, attr, data, **kwargs) -> int: | ||
return user.id |
This file contains 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 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
Oops, something went wrong.