Example #1
0
from typing import Optional

from fastapi import Security, HTTPException
from fastapi.security import APIKeyQuery, APIKeyHeader, HTTPBearer, HTTPAuthorizationCredentials
from starlette.status import HTTP_403_FORBIDDEN

api_key_query = APIKeyQuery(name='apikey', auto_error=False)
api_key_header = APIKeyHeader(name='X-API-Key', auto_error=False)
bearer_header = HTTPBearer(auto_error=False)


async def get_api_key(
    api_key_query_param: Optional[str] = Security(api_key_query),
    api_key_header_param: str = Security(api_key_header),
    bearer_header_param: Optional[HTTPAuthorizationCredentials] = Security(
        bearer_header),
):
    if api_key_query_param is not None:
        return api_key_query_param
    elif api_key_header_param is not None:
        return api_key_header_param
    elif bearer_header_param and bearer_header_param.scheme.lower(
    ) == "bearer":
        return bearer_header_param.credentials
    else:
        raise HTTPException(status_code=HTTP_403_FORBIDDEN,
                            detail="No credentials given")
Example #2
0
from typing import Optional

from fastapi import Depends, FastAPI, Security
from fastapi.security import APIKeyQuery
from pydantic import BaseModel
from starlette.testclient import TestClient

app = FastAPI()

api_key = APIKeyQuery(name="key", auto_error=False)


class User(BaseModel):
    username: str


def get_current_user(oauth_header: Optional[str] = Security(api_key)):
    if oauth_header is None:
        return None
    user = User(username=oauth_header)
    return user


@app.get("/users/me")
def read_current_user(
        current_user: Optional[User] = Depends(get_current_user)):
    if current_user is None:
        return {"msg": "Create an account first"}
    return current_user

from fastapi import Security
from fastapi.security import APIKeyQuery, APIKeyHeader
from starlette.exceptions import HTTPException
from starlette.status import HTTP_403_FORBIDDEN

from fastapi_simple_security._sqlite_access import sqlite_access

API_KEY_NAME = "api_key"

api_key_query = APIKeyQuery(name=API_KEY_NAME,
                            scheme_name="API key query",
                            auto_error=False)
api_key_header = APIKeyHeader(name=API_KEY_NAME,
                              scheme_name="API key header",
                              auto_error=False)


async def api_key_security(
        query_param: str = Security(api_key_query),
        header_param: str = Security(api_key_header),
):
    if not query_param and not header_param:
        raise HTTPException(
            status_code=HTTP_403_FORBIDDEN,
            detail="An API key must be passed as query or header")

    elif query_param and sqlite_access.check_key(query_param):
        return query_param

    elif header_param and sqlite_access.check_key(header_param):
        return header_param
from fastapi import Depends, FastAPI, Security
from fastapi.security import APIKeyQuery
from pydantic import BaseModel
from starlette.testclient import TestClient

app = FastAPI()

api_key = APIKeyQuery(name="key")


class User(BaseModel):
    username: str


def get_current_user(oauth_header: str = Security(api_key)):
    user = User(username=oauth_header)
    return user


@app.get("/users/me")
def read_current_user(current_user: User = Depends(get_current_user)):
    return current_user


client = TestClient(app)

openapi_schema = {
    "openapi": "3.0.2",
    "info": {
        "title": "FastAPI",
        "version": "0.1.0"
Example #5
0
File: api.py Project: cosmicc/pyark
from modules.asyncdb import asyncDB
from modules.redis import globalvar, instancestate, instancevar, redis
from modules.servertools import stripansi, asyncglobalbuffer
from starlette.responses import Response
from fastapi.security import APIKeyQuery
from starlette.status import HTTP_401_UNAUTHORIZED

app = FastAPI(openapi_prefix="/pyarkapi",
              title="Galaxy Cluster API",
              description="Ark: Galaxy Cluster Server API",
              version="2.0.1",
              redoc_url=None)

db = asyncDB()

security = APIKeyQuery(name='key')
"""
async def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None
        if 'X-API-KEY' in request.headers:
            token = request.headers['X-API-KEY']
        if not token:
            apilog.warning(f'API request without a token')
            return {'message': 'Not Authorized'}, 401
        pkeys = dbquery("SELECT * FROM players WHERE apikey = '%s'" % (token,), fmt='dict', fetch='one')
        if pkeys is None:
            apilog.warning(f'API request invalid token: {token}')
            return {'message': 'Invalid Token'}, 401
        if pkeys['banned'] == 'True':
from fastapi import Depends, FastAPI, Security
from fastapi.security import APIKeyQuery
from fastapi.testclient import TestClient
from pydantic import BaseModel

app = FastAPI()

api_key = APIKeyQuery(name="key", description="API Key Query")


class User(BaseModel):
    username: str


def get_current_user(oauth_header: str = Security(api_key)):
    user = User(username=oauth_header)
    return user


@app.get("/users/me")
def read_current_user(current_user: User = Depends(get_current_user)):
    return current_user


client = TestClient(app)

openapi_schema = {
    "openapi": "3.0.2",
    "info": {
        "title": "FastAPI",
        "version": "0.1.0"
Example #7
0
from fastapi import HTTPException

from fastapi import Security
from fastapi.routing import APIRouter
from fastapi.security import APIKeyQuery, APIKeyHeader
from starlette.status import HTTP_403_FORBIDDEN

API_KEY = "abcdefghijklmnopqrstuvxz"
API_KEY_NAME = "access_token"

api_key_query = APIKeyQuery(name=API_KEY_NAME, auto_error=False)
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)

router = APIRouter()


async def get_api_key(
        key_query: str = Security(api_key_query),
        key_header: str = Security(api_key_header),
) -> str:
    if key_query == API_KEY:
        return key_query
    elif key_header == API_KEY:
        return key_header
    else:
        raise HTTPException(status_code=HTTP_403_FORBIDDEN,
                            detail="Could not validate credentials")
Example #8
0
class Server:
    api_key_name = "access-token"
    key_query = Security(APIKeyQuery(name=api_key_name, auto_error=False))
    key_header = Security(APIKeyHeader(name=api_key_name, auto_error=False))
    key_cookie = Security(APIKeyCookie(name=api_key_name, auto_error=False))

    def __init__(self, app: BaseApp, telegram: BaseTelegram,
                 routers: list[AppRouter], templates: Templates):
        self.app = app
        self.telegram = telegram
        self.server = FastAPI(
            title=app.app_config.app_name,
            docs_url=None,
            redoc_url=None,
            openapi_url=None,
            openapi_tags=app.app_config.tags_metadata,
        )
        self.templates = templates
        self._configure_server()
        self._configure_openapi()
        self._configure_routers(routers)
        telegram.start()

    def get_server(self) -> FastAPI:
        return self.server

    def _configure_routers(self, routers: list[AppRouter]):
        base_routers = [
            AppRouter(dconfig_router.init(self.app), "dconfig",
                      "/api/dconfigs"),
            AppRouter(dvalue_router.init(self.app), "dvalue", "/api/dvalues"),
            AppRouter(dlog_router.init(self.app), "dlog", "/api/dlogs"),
            AppRouter(system_router.init(self.app, self.telegram), "system",
                      "/api/system"),
            AppRouter(
                base_ui_router.init(self.app, self.templates, self.telegram),
                "base-ui"),
        ]

        for r in base_routers + routers:
            self.server.include_router(
                r.router,
                prefix=r.prefix,
                dependencies=[Depends(self._get_api_key())],
                tags=[r.tag])

    def _configure_server(self):
        @self.server.exception_handler(Exception)
        async def exception_handler(_request: Request, err: Exception):
            code = getattr(err, "code", None)

            message = str(err)

            hide_stacktrace = isinstance(err, UserError)
            if code in [400, 401, 403, 404, 405]:
                hide_stacktrace = True

            if not hide_stacktrace:
                self.app.logger.exception(err)
                message += "\n\n" + traceback.format_exc()

            if not self.app.app_config.debug:
                message = "error"

            return PlainTextResponse(message, status_code=500)

        @self.server.on_event("shutdown")
        def shutdown_server():
            self.telegram.stop()
            self.app.shutdown()

        current_dir = Path(__file__).parent.absolute()
        self.server.mount(
            "/static",
            StaticFiles(directory=current_dir.joinpath("static")),
            name="static")

    def _configure_openapi(self):
        @self.server.get("/openapi.json",
                         tags=["openapi"],
                         include_in_schema=False)
        async def get_open_api_endpoint(_api_key: APIKey = Depends(
            self._get_api_key())):
            response = JSONResponse(
                get_openapi(
                    title=self.app.app_config.app_name,
                    version=self.app.app_config.app_version,
                    routes=self.server.routes,
                    tags=self.app.app_config.tags_metadata,
                ), )
            return response

        @self.server.get("/api", tags=["openapi"], include_in_schema=False)
        async def get_documentation(api_key: APIKey = Depends(
            self._get_api_key())):
            response = get_swagger_ui_html(openapi_url="/openapi.json",
                                           title=self.app.app_config.app_name)
            # noinspection PyTypeChecker
            response.set_cookie(
                self.api_key_name,
                value=api_key,
                domain=self.app.app_config.domain,
                httponly=True,
                max_age=60 * 60 * 24 * 30,
                expires=60 * 60 * 24 * 30,
            )
            return response

        @self.server.get("/login", tags=["auth"])
        async def route_login_page():
            return self.templates.render("login.j2")

        @self.server.post("/login", tags=["auth"])
        async def route_login_action(access_token: str = Form(...)):
            response = RedirectResponse(url="/",
                                        status_code=status.HTTP_303_SEE_OTHER)
            response.set_cookie(
                self.api_key_name,
                value=access_token,
                domain=self.app.app_config.domain,
                httponly=True,
                max_age=60 * 60 * 24 * 30,
                expires=60 * 60 * 24 * 30,
            )
            return response

        @self.server.get("/logout", tags=["auth"])
        async def route_logout_and_remove_cookie():
            response = RedirectResponse(url="/")
            response.delete_cookie(self.api_key_name,
                                   domain=self.app.app_config.domain)
            return response

        @self.server.get("/api-link")
        def api_redirect(
                request: Request,
                url: str,
                method: str,
                data: Optional[str] = None,
                api_key: APIKey = Depends(self._get_api_key()),
        ):
            method = method.lower()
            headers = {self.api_key_name: api_key}
            url = str(request.base_url).removesuffix("/") + url
            if self.app.app_config.use_https:
                url = url.replace("http://", "https://", 1)

            params = None
            if data:
                params = json.loads(data)
            res = hrequest(url,
                           method=method,
                           headers=headers,
                           params=params,
                           json_params=True,
                           timeout=600)
            if res.json:
                return res.json
            return res.body

    def _get_api_key(self) -> Callable:
        async def _get_api_key(
            query: str = Server.key_query,
            header: str = Server.key_header,
            cookie: str = Server.key_cookie,
        ):
            if query == self.app.app_config.access_token:
                return query
            elif header == self.app.app_config.access_token:
                return header
            elif cookie == self.app.app_config.access_token:
                return cookie
            else:
                raise HTTPException(status_code=HTTP_403_FORBIDDEN,
                                    detail="access denied")

        return _get_api_key
Example #9
0
from fastapi import Security, HTTPException
from fastapi import status
from fastapi.security import APIKeyQuery, APIKeyHeader, APIKeyCookie

from settings import settings

api_key = settings.api_key
api_key_name = settings.api_key_name

api_key_query = APIKeyQuery(name=api_key_name, auto_error=False)
api_key_header = APIKeyHeader(name=api_key_name, auto_error=False)
api_key_cookie = APIKeyCookie(name=api_key_name, auto_error=False)


async def check_api_key(
        api_key_query: str = Security(api_key_query),
        api_key_header: str = Security(api_key_header),
        api_key_cookie: str = Security(api_key_cookie),
):
    if api_key not in (api_key_query, api_key_header, api_key_cookie):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Could not validate credentials",
        )
Example #10
0
from fastapi.openapi.models import APIKey
from fastapi.security import APIKeyHeader, APIKeyQuery

from core.patreon_api import PatreonApi
from core.patreon_response import PatreonModel
from core.settings import environment_config

from fastapi_cache import FastAPICache, Coder
from fastapi_cache.backends.inmemory import InMemoryBackend
from fastapi_cache.decorator import cache

patreon_pledge_checker = FastAPI()

environment_config()
x_api_key_valid = os.environ.get('X-API-Key-Valid', None)
X_API_KEY_QUERY = APIKeyQuery(name="X-API-Key")
X_API_KEY_HEADER = APIKeyHeader(name="X-API-Key")
patreonApi = PatreonApi()


def check_api_key(
        api_key_query: str = Security(X_API_KEY_QUERY),
        api_key_header: str = Security(X_API_KEY_HEADER),
):
    if api_key_query == x_api_key_valid:
        return api_key_query
    elif api_key_header == x_api_key_valid:
        return api_key_header
    else:
        raise HTTPException(
            status_code=401,
Example #11
0
class Server:
    api_key_name = "access_token"

    key_query = Security(APIKeyQuery(name=api_key_name, auto_error=False))
    key_header = Security(APIKeyHeader(name=api_key_name, auto_error=False))
    key_cookie = Security(APIKeyCookie(name=api_key_name, auto_error=False))

    def __init__(self, core: Core, telegram: Telegram):
        self.core = core
        self.telegram = telegram
        self.app = FastAPI(
            title=core.config.app_name,
            docs_url=None,
            redoc_url=None,
            openapi_url=None,
            openapi_tags=core.config.tags_metadata,
        )
        self.templates = configure_jinja(core)
        self._configure_app()
        self._configure_openapi()
        self._configure_routers()
        telegram.start()

    def get_app(self) -> FastAPI:
        return self.app

    def _configure_routers(self):
        self.app.include_router(
            worker_router.init(self.core),
            prefix="/api/workers",
            dependencies=[Depends(self._get_api_key())],
            tags=["workers"],
        )
        self.app.include_router(
            data_router.init(self.core),
            prefix="/api/data",
            dependencies=[Depends(self._get_api_key())],
            tags=["data"],
        )
        self.app.include_router(
            system_router.init(self.core),
            prefix="/api/system",
            dependencies=[Depends(self._get_api_key())],
            tags=["system"],
        )
        self.app.include_router(
            telegram_router.init(self.telegram),
            prefix="/api/telegram",
            dependencies=[Depends(self._get_api_key())],
            tags=["telegram"],
        )
        self.app.include_router(
            ui_router.init(self.core, self.templates),
            prefix="/ui",
            dependencies=[Depends(self._get_api_key())],
            tags=["ui"],
        )

    def _configure_app(self):
        @self.app.exception_handler(Exception)
        async def exception_handler(_request: Request, err: Exception):
            code = getattr(err, "code", None)

            message = str(err)

            hide_stacktrace = isinstance(err, UserError)
            if code in [400, 401, 403, 404, 405]:
                hide_stacktrace = True

            if not hide_stacktrace:
                self.core.log.exception(err)
                message += "\n\n" + traceback.format_exc()

            if not self.core.config.debug:
                message = "error"

            return PlainTextResponse(message, status_code=500)

        @self.app.on_event("shutdown")
        def shutdown_server():
            self.telegram.stop()
            self.core.shutdown()

        current_dir = Path(__file__).parent.absolute()
        self.app.mount("/static", StaticFiles(directory=current_dir.joinpath("static")), name="static")

    def _configure_openapi(self):
        @self.app.get("/openapi.json", tags=["openapi"], include_in_schema=False)
        async def get_open_api_endpoint(_api_key: APIKey = Depends(self._get_api_key())):
            response = JSONResponse(
                get_openapi(
                    title=self.core.config.app_name,
                    version=self.core.config.version,
                    routes=self.app.routes,
                    tags=self.core.config.tags_metadata,
                ),
            )
            return response

        @self.app.get("/api", tags=["openapi"], include_in_schema=False)
        async def get_documentation(api_key: APIKey = Depends(self._get_api_key())):
            response = get_swagger_ui_html(openapi_url="/openapi.json", title=self.core.config.app_name)
            # noinspection PyTypeChecker
            response.set_cookie(
                self.api_key_name,
                value=api_key,
                domain=self.core.config.domain,
                httponly=True,
                max_age=60 * 60 * 24 * 30,
                expires=60 * 60 * 24 * 30,
            )
            return response

        @self.app.get("/logout", tags=["auth"])
        async def route_logout_and_remove_cookie():
            response = RedirectResponse(url="/")
            response.delete_cookie(self.api_key_name, domain=self.core.config.domain)
            return response

        @self.app.get("/")
        async def redirect_to_api():
            return RedirectResponse(url="/ui")

    def _get_api_key(self) -> Callable:
        async def _get_api_key(
            query: str = Server.key_query,
            header: str = Server.key_header,
            cookie: str = Server.key_cookie,
        ):
            if query == self.core.config.access_token:
                return query
            elif header == self.core.config.access_token:
                return header
            elif cookie == self.core.config.access_token:
                return cookie
            else:
                raise HTTPException(status_code=HTTP_403_FORBIDDEN, detail="access denied")

        return _get_api_key