Checks whether a session’s auth state is valid. This method effectively performs a combined authentication and authorization check (short: “auth”), while taking into account whether the system requires any auth check at all. Optionally and additionally, it checks whether the session
(satisfies_role=None)
| 46 | |
| 47 | |
| 48 | def is_auth_valid(satisfies_role=None): |
| 49 | """Checks whether a session’s auth state is valid. |
| 50 | |
| 51 | This method effectively performs a combined authentication and |
| 52 | authorization check (short: “auth”), while taking into account whether the |
| 53 | system requires any auth check at all. Optionally and additionally, it |
| 54 | checks whether the session satisfies a certain role requirement in order to |
| 55 | proceed with the request. |
| 56 | |
| 57 | On a high-level, our auth policy is this: |
| 58 | -> Is authentication generally required to use the system? |
| 59 | - If no: ALLOW! |
| 60 | - If yes -> is the session logged-in? |
| 61 | - If no: DENY! |
| 62 | - If yes -> is there a role requirement and does the user’s assigned |
| 63 | role satisfy it? |
| 64 | - If no: DENY! |
| 65 | - If yes: ALLOW! |
| 66 | |
| 67 | Note: this method aims to encapsulate the aforementioned rules as strongly |
| 68 | as sensibly possible, and tries to boil down the question “is the user |
| 69 | allowed to proceed” to a binary yes/no outcome. That way, we free the |
| 70 | call-side from conditional logic and combinatorial complexity, at the |
| 71 | expense of slightly unconventional internal semantics (e.g., treating all |
| 72 | sessions as having ADMIN privileges if - yet only if! - the auth |
| 73 | requirement is turned off). |
| 74 | |
| 75 | Args: |
| 76 | satisfies_role: (auth.Role) Optional. |
| 77 | |
| 78 | Returns: |
| 79 | Bool |
| 80 | """ |
| 81 | # If the auth requirement is turned off, then no users exist in the system. |
| 82 | # In this case, the question of authentication is obsolete: every visitor |
| 83 | # practically has full access to the system, just so as if they had a |
| 84 | # dedicated user account with `auth.Role.ADMIN` explicitly granted to them. |
| 85 | if not auth.is_authentication_required(): |
| 86 | return True |
| 87 | |
| 88 | # If the session does not contain any user information, it means the user |
| 89 | # didn’t authenticate albeit they are required to. We deny access. |
| 90 | username = get_username() |
| 91 | credentials_last_changed = _get_credentials_last_changed() |
| 92 | if not username or not credentials_last_changed: |
| 93 | return False |
| 94 | |
| 95 | # If the user does not exist in the database, deny access. (This may occur |
| 96 | # when the user account had been deleted in the meantime, i.e., after they |
| 97 | # had logged in initially.) |
| 98 | try: |
| 99 | user = auth.get_account(username) |
| 100 | except db.users.UserDoesNotExistError: |
| 101 | return False |
| 102 | |
| 103 | # If the user’s credentials have changed in the meantime (i.e., since their |
| 104 | # initial log-in), deny access. |
| 105 | if user.credentials_last_changed != credentials_last_changed: |
nothing calls this directly
no test coverage detected