async def destroy( api_token_id: int, api_token_repo: ApiTokenRepo = Depends(ApiTokenRepo()), token: TokenPayload = Depends(ScopedTo("api-token:destroy")), ): messages = [{"text": "Deactivation Succesful", "type": "success"}] if not api_token_repo.exists(api_token_id): return BaseResponse(messages=messages) api_token_repo.deactivate(api_token_id) return BaseResponse(messages=messages)
async def index( sort_qs: SortQS = Depends(SortQS), pagination: PaginationQS = Depends(PaginationQS), api_token_repo: ApiTokenRepo = Depends(ApiTokenRepo()), token: TokenPayload = Depends(ScopedTo("api-token:list")), includes: List[str] = Query(None), ): includes = only(includes, ["dns_server", "http_server"], values=True) pg, items = (api_token_repo.loads(includes).strict().sort( sort_qs).paginate(pagination).includes(includes).data()) return ApiTokensResponse(pagination=pg, api_tokens=items)
async def store( form: ApiTokenCreateForm, api_token_repo: ApiTokenRepo = Depends(ApiTokenRepo()), dns_server_repo: DnsServerRepo = Depends(DnsServerRepo()), http_server_repo: HttpServerRepo = Depends(HttpServerRepo()), token: TokenPayload = Depends(ScopedTo("api-token:create")), user: User = Depends(current_user), ): if form.dns_server_id and form.dns_server_id > 0: dns_server_name = (dns_server_repo.first_or_fail( id=form.dns_server_id).results().name) if form.http_server_id and form.http_server_id > 0: http_server_name = (http_server_repo.first_or_fail( id=form.http_server_id).results().name) scopes = [] for requested_scope in form.scopes.split(" "): request_scope_satisfied = False for user_token in token.scopes: # TODO: double check this, pretty lenient # if a:b in a:b:c if user_token in requested_scope: request_scope_satisfied = True if not request_scope_satisfied: logger.warning( f"[email protected]: Attempt to create unauthorized scope {requested_scope}" ) raise HTTPException(403, detail="unauthorized") else: scopes.append(requested_scope) # TODO: use better randomness token = create_bearer_token( data={ "sub": user.id, "scopes": " ".join(scopes), "dns_server_name": dns_server_name, "http_server_name": http_server_name, }) data = { "scopes": " ".join(scopes), "token": str(token), "expires_at": form.expires_at, "dns_server_id": form.dns_server_id, "http_server_id": form.http_server_id, } api_token = api_token_repo.create(data).data() return ApiTokenResponse(api_token=api_token)
async def show( api_token_id: int, api_token_repo: ApiTokenRepo = Depends(ApiTokenRepo()), token: TokenPayload = Depends(ScopedTo("api-token:read")), includes: List[str] = Query(None), ): includes = only(includes, ["dns_server", "http_server"], values=True) if (not api_token_repo.loads(includes).strict().includes(includes).exists( api_token_id)): raise HTTPException(404, detail="Not found") api_token = api_token_repo.data() return ApiTokenResponse(api_token=api_token)
async def sensitive( api_token_id: int, api_token_repo: ApiTokenRepo = Depends(ApiTokenRepo()), token: TokenPayload = Depends(ScopedTo("api-token:read")), includes: List[str] = Query(None), ): includes = only(includes, ["dns_server", "http_server"], values=True) # TODO: require stronger scope if not api_token_repo.exists(api_token_id): raise HTTPException(404, detail="Not found") api_token = (api_token_repo.loads(includes).set_data_model( SensitiveApiTokenData).includes(includes).data()) return SensitiveApiTokenResponse(api_token=api_token)
async def sync( api_token_repo: ApiTokenRepo = Depends(ApiTokenRepo()), dns_server_repo: DnsServerRepo = Depends(DnsServerRepo()), http_server_repo: HttpServerRepo = Depends(HttpServerRepo()), token: TokenPayload = Depends(ScopedTo("api-token:syncable")), ): if "api-token" in token.scopes or "api-token:syncable" in token.scopes: abort_for_no_server_names(token) if (len(token.payload.dns_server_name) > 0 and len(token.payload.http_server_name) > 0): dns_server = create_or_get_dns_server(token, dns_server_repo) http_server = create_or_get_http_server(token, http_server_repo) api_token_data = create_or_get_api_token_for_all_nodes( token, api_token_repo, dns_server, http_server) elif len(token.payload.dns_server_name) > 0: dns_server = create_or_get_dns_server(token, dns_server_repo) api_token_data = create_or_get_api_token_for_dns_server( token, api_token_repo, dns_server) elif len(token.payload.http_server_name) > 0: http_server = create_or_get_http_server(token, http_server_repo) api_token_data = create_or_get_api_token_for_http_server( token, api_token_repo, http_server) else: # something went wrong, should not hit raise HTTPException(403, detail="Not found") return ApiTokenResponse(api_token=api_token_data) else: raise HTTPException(403, detail="Not found")
def create_or_get_api_token_for_dns_server( token: TokenPayload, api_token_repo: ApiTokenRepo, dns_server: DnsServer) -> ApiTokenData: scopes = token.scopes if not api_token_repo.exists(token=token.token): api_token_repo.clear() logger.info( "[email protected] - Saving api token from auth token for dns node") return api_token_repo.create( dict( token=token.token, scopes=" ".join(scopes), dns_server=dns_server, expires_at=datetime.utcfromtimestamp(float(token.exp)), )).data() else: logger.info("[email protected] - token already exists in database") return api_token_repo.loads("dns_server").includes("dns_server").data()