88from fastapi import APIRouter , Depends
99from fastapi .encoders import jsonable_encoder
1010from fastapi .exceptions import HTTPException
11+ from sqlalchemy import and_
1112from sqlalchemy .orm import Session
1213
1314from mavedb import deps
1718from mavedb .lib .logging .context import logging_context , save_to_logging_context
1819from mavedb .models .access_key import AccessKey
1920from mavedb .models .enums .user_role import UserRole
21+ from mavedb .routers .shared import ACCESS_CONTROL_ERROR_RESPONSES , PUBLIC_ERROR_RESPONSES , ROUTER_BASE_PREFIX
2022from mavedb .view_models import access_key
2123
24+ TAG_NAME = "Access Keys"
25+
2226router = APIRouter (
23- prefix = "/api/v1 " ,
24- tags = ["access keys" ],
25- responses = {404 : { "description" : "Not found" } },
27+ prefix = f" { ROUTER_BASE_PREFIX } " ,
28+ tags = [TAG_NAME ],
29+ responses = {** PUBLIC_ERROR_RESPONSES },
2630 route_class = LoggedRoute ,
2731)
2832
33+ metadata = {
34+ "name" : TAG_NAME ,
35+ "description" : "Manage API access keys for programmatic access to the MaveDB API." ,
36+ "externalDocs" : {
37+ "description" : "Access Keys Documentation" ,
38+ "url" : "https://mavedb.org/docs/mavedb/accounts.html#api-access-tokens" ,
39+ },
40+ }
41+
2942logger = logging .getLogger (__name__ )
3043
3144
@@ -49,7 +62,8 @@ def generate_key_pair():
4962 "/users/me/access-keys" ,
5063 status_code = 200 ,
5164 response_model = list [access_key .AccessKey ],
52- responses = {404 : {}, 500 : {}},
65+ responses = {** ACCESS_CONTROL_ERROR_RESPONSES },
66+ summary = "List my access keys" ,
5367)
5468def list_my_access_keys (* , user_data : UserData = Depends (require_current_user )) -> Any :
5569 """
@@ -62,7 +76,8 @@ def list_my_access_keys(*, user_data: UserData = Depends(require_current_user))
6276 "/users/me/access-keys" ,
6377 status_code = 200 ,
6478 response_model = access_key .NewAccessKey ,
65- responses = {404 : {}, 500 : {}},
79+ responses = {** ACCESS_CONTROL_ERROR_RESPONSES },
80+ summary = "Create a new access key for myself" ,
6681)
6782def create_my_access_key (
6883 * ,
@@ -88,7 +103,8 @@ def create_my_access_key(
88103 "/users/me/access-keys/{role}" ,
89104 status_code = 200 ,
90105 response_model = access_key .NewAccessKey ,
91- responses = {404 : {}, 500 : {}},
106+ responses = {** ACCESS_CONTROL_ERROR_RESPONSES },
107+ summary = "Create a new access key for myself with a specified role" ,
92108)
93109async def create_my_access_key_with_role (
94110 * ,
@@ -125,7 +141,12 @@ async def create_my_access_key_with_role(
125141 return response_item
126142
127143
128- @router .delete ("/users/me/access-keys/{key_id}" , status_code = 200 , responses = {404 : {}, 500 : {}})
144+ @router .delete (
145+ "/users/me/access-keys/{key_id}" ,
146+ status_code = 200 ,
147+ responses = {** ACCESS_CONTROL_ERROR_RESPONSES },
148+ summary = "Delete one of my access keys" ,
149+ )
129150def delete_my_access_key (
130151 * ,
131152 key_id : str ,
@@ -135,8 +156,20 @@ def delete_my_access_key(
135156 """
136157 Delete one of the current user's access keys.
137158 """
138- item = db .query (AccessKey ).filter (AccessKey .key_id == key_id ).one_or_none ()
139- if item and item .user .id == user_data .user .id :
140- db .delete (item )
141- db .commit ()
142- logger .debug (msg = "Successfully deleted provided API key." , extra = logging_context ())
159+ item = (
160+ db .query (AccessKey )
161+ .filter (and_ (AccessKey .key_id == key_id , AccessKey .user_id == user_data .user .id ))
162+ .one_or_none ()
163+ )
164+
165+ if not item :
166+ logger .warning (
167+ msg = "Could not delete API key; Provided key ID does not exist and/or does not belong to the current user." ,
168+ extra = logging_context (),
169+ )
170+ # Never acknowledge the existence of an access key that doesn't belong to the user.
171+ raise HTTPException (status_code = 404 , detail = f"Access key with ID { key_id } not found." )
172+
173+ db .delete (item )
174+ db .commit ()
175+ logger .debug (msg = "Successfully deleted provided API key." , extra = logging_context ())
0 commit comments