From 74491c236291779a2acfb9f644c70b199b904779 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Wed, 14 Dec 2022 11:37:12 -0500 Subject: [PATCH 1/2] Migrate baseauth endpoint to FastAPI. --- lib/galaxy/webapps/galaxy/api/authenticate.py | 26 ++++++++++++------- lib/galaxy/webapps/galaxy/buildapp.py | 12 --------- .../webapps/galaxy/services/authenticate.py | 6 ++++- test/unit/webapps/test_routes.py | 1 - 4 files changed, 21 insertions(+), 24 deletions(-) diff --git a/lib/galaxy/webapps/galaxy/api/authenticate.py b/lib/galaxy/webapps/galaxy/api/authenticate.py index ed8c9898a8d..8c5a7d5b780 100644 --- a/lib/galaxy/webapps/galaxy/api/authenticate.py +++ b/lib/galaxy/webapps/galaxy/api/authenticate.py @@ -15,6 +15,8 @@ Returns } """ +from fastapi import Request + from galaxy.web import expose_api_anonymous_and_sessionless from galaxy.webapps.base.webapp import GalaxyWebTransaction from galaxy.webapps.galaxy.services.authenticate import ( @@ -24,8 +26,11 @@ from galaxy.webapps.galaxy.services.authenticate import ( from . import ( BaseGalaxyAPIController, depends, + Router, ) +router = Router(tags=["authenticate"]) + class AuthenticationController(BaseGalaxyAPIController): authentication_service = depends(AuthenticationService) @@ -44,15 +49,16 @@ class AuthenticationController(BaseGalaxyAPIController): # When this is actually granular, endpoints should *probably* respond appropriately. # trans.response.headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS, DELETE' - @expose_api_anonymous_and_sessionless - def get_api_key(self, trans: GalaxyWebTransaction, **kwd) -> APIKeyResponse: - """ - GET /api/authenticate/baseauth - returns an API key for authenticated user based on BaseAuth headers - :returns: api_key in json format - :rtype: dict +@router.cbv +class FastAPIAuthenticate: + authentication_service: AuthenticationService = depends(AuthenticationService) - :raises: ObjectNotFound, HTTPBadRequest - """ - return self.authentication_service.get_api_key(trans.environ, trans.request) + @router.get( + "/api/authenticate/baseauth", + summary="Returns returns an API key for authenticated user based on BaseAuth headers.", + ) + def get_api_key(self, request: Request) -> APIKeyResponse: + authorization = request.headers.get("Authorization") + auth = {"HTTP_AUTHORIZATION": authorization} + return self.authentication_service.get_api_key(auth, request) diff --git a/lib/galaxy/webapps/galaxy/buildapp.py b/lib/galaxy/webapps/galaxy/buildapp.py index 0a80232cc34..adecab36d84 100644 --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -764,18 +764,6 @@ def populate_api_routes(webapp, app): "update_step", "/steps/{step_id}", action="update_invocation_step", conditions=dict(method=["PUT"]) ) - # ============================ - # ===== AUTHENTICATE API ===== - # ============================ - - webapp.mapper.connect( - "api_key_retrieval", - "/api/authenticate/baseauth/", - controller="authenticate", - action="get_api_key", - conditions=dict(method=["GET"]), - ) - # ====================================== # ====== DISPLAY APPLICATIONS API ====== # ====================================== diff --git a/lib/galaxy/webapps/galaxy/services/authenticate.py b/lib/galaxy/webapps/galaxy/services/authenticate.py index aed0135525e..f71caf88cdb 100644 --- a/lib/galaxy/webapps/galaxy/services/authenticate.py +++ b/lib/galaxy/webapps/galaxy/services/authenticate.py @@ -4,10 +4,12 @@ from typing import ( Dict, Optional, Tuple, + Union, ) from urllib.parse import unquote from pydantic import BaseModel +from starlette.requests import Request as StartletteRequest from galaxy import exceptions from galaxy.auth import AuthManager @@ -17,7 +19,9 @@ from galaxy.util import ( smart_str, unicodify, ) -from galaxy.web.framework.base import Request +from galaxy.web.framework.base import Request as GxRequest + +Request = Union[GxRequest, StartletteRequest] class APIKeyResponse(BaseModel): diff --git a/test/unit/webapps/test_routes.py b/test/unit/webapps/test_routes.py index 36fd7143b63..699e6ed3c28 100644 --- a/test/unit/webapps/test_routes.py +++ b/test/unit/webapps/test_routes.py @@ -32,7 +32,6 @@ def test_galaxy_routes(): config = request_config() config.host = "usegalaxy.org" config.protocol = "https" - assert_url_is(url_for("api_key_retrieval", qualified=True), "https://usegalaxy.org/api/authenticate/baseauth") assert_url_is(url_for("/tool_runner/biomart", qualified=True), "https://usegalaxy.org/tool_runner/biomart") # Test previously problematic tool ids with slashes. From 44be23172059ca6e86513b4ed211bd6277697256 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Wed, 14 Dec 2022 11:39:25 -0500 Subject: [PATCH 2/2] Rebuild schema. --- client/src/schema/schema.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/client/src/schema/schema.ts b/client/src/schema/schema.ts index 3401edc4502..375ba3430fe 100644 --- a/client/src/schema/schema.ts +++ b/client/src/schema/schema.ts @@ -4,6 +4,10 @@ */ export interface paths { + "/api/authenticate/baseauth": { + /** Returns returns an API key for authenticated user based on BaseAuth headers. */ + get: operations["get_api_key_api_authenticate_baseauth_get"]; + }; "/api/configuration": { /** * Return an object containing exposable configuration settings @@ -1334,6 +1338,11 @@ export interface components { */ key: string; }; + /** APIKeyResponse */ + APIKeyResponse: { + /** Api Key */ + api_key: string; + }; /** AccessMethod */ AccessMethod: { /** @@ -7462,6 +7471,17 @@ export interface components { export type external = Record; export interface operations { + get_api_key_api_authenticate_baseauth_get: { + /** Returns returns an API key for authenticated user based on BaseAuth headers. */ + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["APIKeyResponse"]; + }; + }; + }; + }; index_api_configuration_get: { /** * Return an object containing exposable configuration settings