Seth commited on
Commit ·
0997ef3
1
Parent(s): 766e766
update
Browse files
backend/app/auth_routes.py
CHANGED
|
@@ -240,6 +240,13 @@ async def auth_me(request: Request, db: Session = Depends(get_db)):
|
|
| 240 |
if cur_tid is not None and int(cur_tid) == tid:
|
| 241 |
current_role = m.role
|
| 242 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
return {
|
| 244 |
**profile,
|
| 245 |
"user_id": uid,
|
|
|
|
| 240 |
if cur_tid is not None and int(cur_tid) == tid:
|
| 241 |
current_role = m.role
|
| 242 |
|
| 243 |
+
# Keep session aligned with DB when current_tenant_id is missing or no longer valid.
|
| 244 |
+
if current_role is None and memberships:
|
| 245 |
+
m0, t0 = min(memberships, key=lambda mt: (int(mt[1].id), int(mt[0].id)))
|
| 246 |
+
request.session["current_tenant_id"] = int(t0.id)
|
| 247 |
+
cur_tid = int(t0.id)
|
| 248 |
+
current_role = m0.role
|
| 249 |
+
|
| 250 |
return {
|
| 251 |
**profile,
|
| 252 |
"user_id": uid,
|
backend/app/tenant_deps.py
CHANGED
|
@@ -22,20 +22,32 @@ async def get_tenant_context(request: Request, db: Session = Depends(get_db)) ->
|
|
| 22 |
uid = request.session.get("user_id")
|
| 23 |
if uid is None:
|
| 24 |
raise HTTPException(status_code=401, detail="Sign in required")
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
m = (
|
| 29 |
db.query(TenantMembership)
|
| 30 |
-
.filter(
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
)
|
| 34 |
-
.first()
|
| 35 |
)
|
| 36 |
-
if not
|
| 37 |
-
raise HTTPException(
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
|
| 41 |
async def require_tenant_admin(tc: TenantContext = Depends(get_tenant_context)) -> TenantContext:
|
|
|
|
| 22 |
uid = request.session.get("user_id")
|
| 23 |
if uid is None:
|
| 24 |
raise HTTPException(status_code=401, detail="Sign in required")
|
| 25 |
+
uid_i = int(uid)
|
| 26 |
+
|
| 27 |
+
memberships = (
|
|
|
|
| 28 |
db.query(TenantMembership)
|
| 29 |
+
.filter(TenantMembership.user_id == uid_i)
|
| 30 |
+
.order_by(TenantMembership.id)
|
| 31 |
+
.all()
|
|
|
|
|
|
|
| 32 |
)
|
| 33 |
+
if not memberships:
|
| 34 |
+
raise HTTPException(
|
| 35 |
+
status_code=400,
|
| 36 |
+
detail="No workspace membership. Sign out and sign in again, or use an invite link.",
|
| 37 |
+
)
|
| 38 |
+
|
| 39 |
+
tid_session = request.session.get("current_tenant_id")
|
| 40 |
+
m = None
|
| 41 |
+
if tid_session is not None:
|
| 42 |
+
tid_i = int(tid_session)
|
| 43 |
+
m = next((x for x in memberships if int(x.tenant_id) == tid_i), None)
|
| 44 |
+
|
| 45 |
+
# Session pointed at a tenant the user no longer belongs to (stale cookie / DB reset / HF volume).
|
| 46 |
+
if m is None:
|
| 47 |
+
m = memberships[0]
|
| 48 |
+
request.session["current_tenant_id"] = int(m.tenant_id)
|
| 49 |
+
|
| 50 |
+
return TenantContext(tenant_id=int(m.tenant_id), user_id=uid_i, role=m.role, db=db)
|
| 51 |
|
| 52 |
|
| 53 |
async def require_tenant_admin(tc: TenantContext = Depends(get_tenant_context)) -> TenantContext:
|
frontend/src/components/layout/AppShell.jsx
CHANGED
|
@@ -42,7 +42,7 @@ export default function AppShell({ title, subtitle, rightContent, children }) {
|
|
| 42 |
};
|
| 43 |
syncSettingsNav();
|
| 44 |
window.addEventListener('emailout-auth-changed', syncSettingsNav);
|
| 45 |
-
return () => window.removeEventListener('emailout-auth-changed',
|
| 46 |
}, []);
|
| 47 |
|
| 48 |
const navItems = useMemo(
|
|
|
|
| 42 |
};
|
| 43 |
syncSettingsNav();
|
| 44 |
window.addEventListener('emailout-auth-changed', syncSettingsNav);
|
| 45 |
+
return () => window.removeEventListener('emailout-auth-changed', syncSettingsNav);
|
| 46 |
}, []);
|
| 47 |
|
| 48 |
const navItems = useMemo(
|