fix: authenticate_passcode — priority ordering, full role flags, per-role TTL, min_length
This commit is contained in:
@@ -21,10 +21,21 @@ router = APIRouter()
|
|||||||
|
|
||||||
# --- Passcode Authentication ---
|
# --- Passcode Authentication ---
|
||||||
|
|
||||||
|
ROLE_PRIORITY = ['super', 'manager', 'administrator', 'trusted', 'public', 'authenticated']
|
||||||
|
|
||||||
|
ROLE_TTL = {
|
||||||
|
'super': 8 * 3600, # 8 hours
|
||||||
|
'manager': 24 * 3600, # 24 hours
|
||||||
|
'administrator': 48 * 3600, # 48 hours
|
||||||
|
'trusted': 48 * 3600, # 48 hours
|
||||||
|
'public': 24 * 3600, # 24 hours
|
||||||
|
'authenticated': 12 * 3600, # 12 hours
|
||||||
|
}
|
||||||
|
|
||||||
class PasscodeAuthRequest(BaseModel):
|
class PasscodeAuthRequest(BaseModel):
|
||||||
"""Request model for site-based passcode authentication."""
|
"""Request model for site-based passcode authentication."""
|
||||||
site_id: str = Field(..., description="The random string ID of the site")
|
site_id: str = Field(..., description="The random string ID of the site")
|
||||||
passcode: str = Field(..., description="The passcode to verify")
|
passcode: str = Field(..., min_length=5, description="The passcode to verify")
|
||||||
|
|
||||||
@router.post('/authenticate_passcode', response_model=Resp_Body_Base)
|
@router.post('/authenticate_passcode', response_model=Resp_Body_Base)
|
||||||
async def authenticate_passcode(
|
async def authenticate_passcode(
|
||||||
@@ -54,10 +65,11 @@ async def authenticate_passcode(
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"Failed to parse access_code_kv_json for site {site_id}: {e}")
|
log.error(f"Failed to parse access_code_kv_json for site {site_id}: {e}")
|
||||||
|
|
||||||
# 3. Verify Passcode and Resolve Role
|
# 3. Verify passcode in explicit priority order (highest privilege wins)
|
||||||
matched_role = None
|
matched_role = None
|
||||||
for role, code in access_codes.items():
|
for role in ROLE_PRIORITY:
|
||||||
if str(code) == str(passcode):
|
code = access_codes.get(role)
|
||||||
|
if code and str(code) == str(passcode):
|
||||||
matched_role = role
|
matched_role = role
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -70,22 +82,25 @@ async def authenticate_passcode(
|
|||||||
if account_id_int := record.get('account_id'):
|
if account_id_int := record.get('account_id'):
|
||||||
account_id_random = get_id_random(record_id=account_id_int, table_name='account')
|
account_id_random = get_id_random(record_id=account_id_int, table_name='account')
|
||||||
|
|
||||||
# 5. Mint JWT
|
# 5. Mint JWT with complete role flags and per-role TTL
|
||||||
payload = {
|
payload = {
|
||||||
'account_id': account_id_random,
|
'account_id': account_id_random,
|
||||||
|
'super': (matched_role == 'super'),
|
||||||
|
'manager': (matched_role == 'manager'),
|
||||||
'administrator': (matched_role == 'administrator'),
|
'administrator': (matched_role == 'administrator'),
|
||||||
'manager': (matched_role == 'manager'),
|
'trusted': (matched_role == 'trusted'),
|
||||||
'super': (matched_role == 'super'),
|
'public': (matched_role == 'public'),
|
||||||
|
'authenticated': (matched_role == 'authenticated'),
|
||||||
'json_str': json.dumps({
|
'json_str': json.dumps({
|
||||||
'auth_type': 'passcode',
|
'auth_type': 'passcode',
|
||||||
'site_id': site_id,
|
'site_id': site_id,
|
||||||
'role': matched_role
|
'role': matched_role
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
token = sign_jwt(
|
token = sign_jwt(
|
||||||
secret_key=settings.JWT_KEY,
|
secret_key=settings.JWT_KEY,
|
||||||
ttl=3600 * 24, # 24 hour session
|
ttl=ROLE_TTL[matched_role],
|
||||||
**payload
|
**payload
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user