1- from typing import Optional
2- from fastapi import APIRouter , Depends , Request
1+ from typing import Optional , List
2+ from fastapi import APIRouter , Depends , Request , Response
33from fastapi .templating import Jinja2Templates
4- from utils .core .dependencies import get_user_with_relations
5- from utils .core .models import User
4+ from sqlmodel import Session , select
5+ from utils .core .dependencies import get_user_with_relations , get_session
6+ from utils .core .models import User , Organization
7+ from utils .core .enums import ValidPermissions
8+ from utils .app .models import OrganizationResource
69
710router = APIRouter (prefix = "/dashboard" , tags = ["dashboard" ])
811templates = Jinja2Templates (directory = "templates" )
1417@router .get ("/" )
1518async def read_dashboard (
1619 request : Request ,
17- user : Optional [User ] = Depends (get_user_with_relations )
20+ user : User = Depends (get_user_with_relations ),
21+ session : Session = Depends (get_session ),
1822):
23+ organizations = user .organizations
24+ selected_org : Optional [Organization ] = None
25+ resources : List [OrganizationResource ] = []
26+ can_read = False
27+ can_write = False
28+ can_delete = False
29+
30+ if organizations :
31+ # Read selected org from cookie, fall back to first org
32+ selected_org_id_str = request .cookies .get ("selected_organization_id" )
33+ if selected_org_id_str :
34+ try :
35+ selected_org_id = int (selected_org_id_str )
36+ selected_org = next (
37+ (o for o in organizations if o .id == selected_org_id ), None
38+ )
39+ except ValueError :
40+ pass
41+
42+ if not selected_org :
43+ selected_org = organizations [0 ]
44+
45+ # Load organization resources for the selected org
46+ if selected_org and selected_org .id is not None :
47+ resources = list (session .exec (
48+ select (OrganizationResource )
49+ .where (OrganizationResource .organization_id == selected_org .id )
50+ .order_by (OrganizationResource .created_at .desc ()) # type: ignore[union-attr]
51+ ).all ())
52+ can_read = user .has_permission (
53+ ValidPermissions .READ_ORGANIZATION_RESOURCES , selected_org
54+ )
55+ can_write = user .has_permission (
56+ ValidPermissions .WRITE_ORGANIZATION_RESOURCES , selected_org
57+ )
58+ can_delete = user .has_permission (
59+ ValidPermissions .DELETE_ORGANIZATION_RESOURCES , selected_org
60+ )
61+
1962 return templates .TemplateResponse (
2063 request ,
2164 "dashboard/index.html" ,
22- {"user" : user }
23- )
65+ {
66+ "user" : user ,
67+ "organizations" : organizations ,
68+ "selected_org" : selected_org ,
69+ "resources" : resources ,
70+ "can_read" : can_read ,
71+ "can_write" : can_write ,
72+ "can_delete" : can_delete ,
73+ }
74+ )
75+
76+
77+ @router .post ("/select-organization/{org_id}" )
78+ async def select_organization (
79+ request : Request ,
80+ org_id : int ,
81+ user : User = Depends (get_user_with_relations ),
82+ ):
83+ """Set the selected organization cookie and redirect back to dashboard."""
84+ # Verify user is a member of this organization
85+ org = next ((o for o in user .organizations if o .id == org_id ), None )
86+ if not org :
87+ # Fall back to dashboard without changing cookie
88+ response = Response (status_code = 200 )
89+ response .headers ["HX-Redirect" ] = str (request .url_for ("read_dashboard" ))
90+ return response
91+
92+ response = Response (status_code = 200 )
93+ response .set_cookie (
94+ key = "selected_organization_id" ,
95+ value = str (org_id ),
96+ httponly = True ,
97+ samesite = "strict" ,
98+ max_age = 60 * 60 * 24 * 365 , # 1 year
99+ )
100+ response .headers ["HX-Redirect" ] = str (request .url_for ("read_dashboard" ))
101+ return response
0 commit comments