| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| from enum import Enum |
| from typing import List, Optional, TypedDict, Union |
| |
| from flask_appbuilder.security.sqla.models import Role |
| from flask_login import AnonymousUserMixin |
| |
| |
| class GuestTokenUser(TypedDict, total=False): |
| username: str |
| first_name: str |
| last_name: str |
| |
| |
| class GuestTokenResourceType(Enum): |
| DASHBOARD = "dashboard" |
| |
| |
| class GuestTokenResource(TypedDict): |
| type: GuestTokenResourceType |
| id: Union[str, int] |
| |
| |
| GuestTokenResources = List[GuestTokenResource] |
| |
| |
| class GuestTokenRlsRule(TypedDict): |
| dataset: Optional[str] |
| clause: str |
| |
| |
| class GuestToken(TypedDict): |
| iat: float |
| exp: float |
| user: GuestTokenUser |
| resources: GuestTokenResources |
| rls_rules: List[GuestTokenRlsRule] |
| |
| |
| class GuestUser(AnonymousUserMixin): |
| """ |
| Used as the "anonymous" user in case of guest authentication (embedded) |
| """ |
| |
| is_guest_user = True |
| |
| @property |
| def is_authenticated(self) -> bool: |
| """ |
| This is set to true because guest users should be considered authenticated, |
| at least in most places. The treatment of this flag is kind of inconsistent. |
| """ |
| return True |
| |
| @property |
| def is_anonymous(self) -> bool: |
| """ |
| This is set to false because lots of code assumes that |
| if user.is_anonymous, then role = Public |
| But guest users need to have their own role independent of Public. |
| """ |
| return False |
| |
| def __init__(self, token: GuestToken, roles: List[Role]): |
| user = token["user"] |
| self.guest_token = token |
| self.username = user.get("username", "guest_user") |
| self.first_name = user.get("first_name", "Guest") |
| self.last_name = user.get("last_name", "User") |
| self.roles = roles |
| self.resources = token["resources"] |
| self.rls = token.get("rls_rules", []) |