diff --git a/app/routers/api.py b/app/routers/api.py index d15ed81..e53694b 100644 --- a/app/routers/api.py +++ b/app/routers/api.py @@ -21,10 +21,21 @@ router = APIRouter() # --- 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): """Request model for site-based passcode authentication.""" 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) async def authenticate_passcode( @@ -54,10 +65,11 @@ async def authenticate_passcode( except Exception as 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 - for role, code in access_codes.items(): - if str(code) == str(passcode): + for role in ROLE_PRIORITY: + code = access_codes.get(role) + if code and str(code) == str(passcode): matched_role = role break @@ -70,22 +82,25 @@ async def authenticate_passcode( if account_id_int := record.get('account_id'): 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 = { - 'account_id': account_id_random, + 'account_id': account_id_random, + 'super': (matched_role == 'super'), + 'manager': (matched_role == 'manager'), 'administrator': (matched_role == 'administrator'), - 'manager': (matched_role == 'manager'), - 'super': (matched_role == 'super'), + 'trusted': (matched_role == 'trusted'), + 'public': (matched_role == 'public'), + 'authenticated': (matched_role == 'authenticated'), 'json_str': json.dumps({ 'auth_type': 'passcode', - 'site_id': site_id, - 'role': matched_role + 'site_id': site_id, + 'role': matched_role }) } token = sign_jwt( secret_key=settings.JWT_KEY, - ttl=3600 * 24, # 24 hour session + ttl=ROLE_TTL[matched_role], **payload )