1
1
from collections .abc import Callable
2
- from datetime import UTC , datetime
2
+ from datetime import UTC , datetime , timedelta
3
3
from enum import Enum
4
4
from functools import wraps
5
5
from typing import Optional
8
8
from flask_login import user_logged_in # type: ignore
9
9
from flask_restful import Resource # type: ignore
10
10
from pydantic import BaseModel
11
+ from sqlalchemy import select , update
12
+ from sqlalchemy .orm import Session
11
13
from werkzeug .exceptions import Forbidden , Unauthorized
12
14
13
15
from extensions .ext_database import db
@@ -174,7 +176,7 @@ def decorated(*args, **kwargs):
174
176
return decorator
175
177
176
178
177
- def validate_and_get_api_token (scope = None ):
179
+ def validate_and_get_api_token (scope : str | None = None ):
178
180
"""
179
181
Validate and get API token.
180
182
"""
@@ -188,20 +190,25 @@ def validate_and_get_api_token(scope=None):
188
190
if auth_scheme != "bearer" :
189
191
raise Unauthorized ("Authorization scheme must be 'Bearer'" )
190
192
191
- api_token = (
192
- db .session .query (ApiToken )
193
- .filter (
194
- ApiToken .token == auth_token ,
195
- ApiToken .type == scope ,
193
+ current_time = datetime .now (UTC ).replace (tzinfo = None )
194
+ cutoff_time = current_time - timedelta (minutes = 1 )
195
+ with Session (db .engine , expire_on_commit = False ) as session :
196
+ update_stmt = (
197
+ update (ApiToken )
198
+ .where (ApiToken .token == auth_token , ApiToken .last_used_at < cutoff_time , ApiToken .type == scope )
199
+ .values (last_used_at = current_time )
200
+ .returning (ApiToken )
196
201
)
197
- .first ()
198
- )
199
-
200
- if not api_token :
201
- raise Unauthorized ("Access token is invalid" )
202
-
203
- api_token .last_used_at = datetime .now (UTC ).replace (tzinfo = None )
204
- db .session .commit ()
202
+ result = session .execute (update_stmt )
203
+ api_token = result .scalar_one_or_none ()
204
+
205
+ if not api_token :
206
+ stmt = select (ApiToken ).where (ApiToken .token == auth_token , ApiToken .type == scope )
207
+ api_token = session .scalar (stmt )
208
+ if not api_token :
209
+ raise Unauthorized ("Access token is invalid" )
210
+ else :
211
+ session .commit ()
205
212
206
213
return api_token
207
214
0 commit comments