1- import  {  GoogleAuth  }  from  "google-auth-library" 
21
3- import  {  env  }  from  "../../config/env" 
42
5- import  {  baseLogger  }  from  "@/services/logger" 
63
7- import  {  recordExceptionInCurrentSpan  }  from  "@/services/tracing" 
8- 
9- import  {  ErrorLevel  }  from  "@/domain/shared" 
10- 
11- // Based on https://cloud.google.com/resource-manager/reference/rest/v1/Policy 
12- interface  Policy  { 
13-   bindings ?: Binding [ ] 
14-   etag ?: string 
15-   version ?: number 
16- } 
17- 
18- interface  Binding  { 
19-   role ?: string 
20-   members ?: string [ ] 
21-   condition ?: { 
22-     title ?: string 
23-     description ?: string 
24-     expression ?: string 
25-   } 
26- } 
274
285export  enum  AdminRole  { 
296  VIEWER  =  "roles/adminPanelViewer" , 
307  SUPPORT  =  "roles/adminPanelSupport" , 
318  ADMIN  =  "roles/adminPanelAdmin" , 
329} 
3310
34- export  enum  AdminFeature  { 
11+ export  enum  AdminAccessRight  { 
3512  VIEW_ACCOUNTS  =  "VIEW_ACCOUNTS" , 
3613  MODIFY_ACCOUNTS  =  "MODIFY_ACCOUNTS" , 
3714  DELETE_ACCOUNTS  =  "DELETE_ACCOUNTS" , 
@@ -40,76 +17,31 @@ export enum AdminFeature {
4017  SYSTEM_CONFIG  =  "SYSTEM_CONFIG" , 
4118} 
4219
43- const  ROLE_FEATURES  =  { 
44-   [ AdminRole . VIEWER ] : [ AdminFeature . VIEW_ACCOUNTS ,  AdminFeature . VIEW_TRANSACTIONS ] , 
45-   [ AdminRole . SUPPORT ] : [ 
46-     AdminFeature . VIEW_ACCOUNTS , 
47-     AdminFeature . MODIFY_ACCOUNTS , 
48-     AdminFeature . VIEW_TRANSACTIONS , 
49-     AdminFeature . SEND_NOTIFICATIONS , 
20+ // String-based role values from options.ts 
21+ export  type  AdminRoleString  =  "VIEWER"  |  "SUPPORT"  |  "ADMIN" 
22+ 
23+ // String-based role access rights mapping 
24+ const  STRING_ROLE_ACCESS_RIGHTS  =  { 
25+   VIEWER : [ AdminAccessRight . VIEW_ACCOUNTS ,  AdminAccessRight . VIEW_TRANSACTIONS ] , 
26+   SUPPORT : [ 
27+     AdminAccessRight . VIEW_ACCOUNTS , 
28+     AdminAccessRight . MODIFY_ACCOUNTS , 
29+     AdminAccessRight . VIEW_TRANSACTIONS , 
30+     AdminAccessRight . SEND_NOTIFICATIONS , 
5031  ] , 
51-   [ AdminRole . ADMIN ] : Object . values ( AdminFeature ) , 
32+   ADMIN : Object . values ( AdminAccessRight ) , 
5233} 
5334
54- const  auth  =  new  GoogleAuth ( { 
55-   scopes : [ "https://www.googleapis.com/auth/cloud-platform" ] , 
56-   keyFilename : env . GCP_IAM_SERVICE_ACCOUNT_PATH , 
57- } ) 
58- 
59- export  const  getUserRoles  =  async  ( userEmail : string ) : Promise < AdminRole [ ] >  =>  { 
60-   // Only bypass in development/test environments 
61-   if  ( 
62-     ( env . NODE_ENV  ===  "development"  ||  env . NODE_ENV  ===  "test" )  && 
63-     env . BYPASS_ROLE_CHECK 
64-   )  { 
65-     return  Object . values ( AdminRole ) 
66-   } 
67- 
68-   // Production uses real role checking 
69-   try  { 
70-     const  client  =  await  auth . getClient ( ) 
71-     const  projectId  =  process . env . GCP_PROJECT_ID 
72-     if  ( ! projectId )  { 
73-       throw  new  Error ( "GCP_PROJECT_ID environment variable is required for role checking" ) 
74-     } 
7535
76-     const  response  =  await  client . request ( { 
77-       url : `https://cloudresourcemanager.googleapis.com/v1/projects/${ projectId }  , 
78-       method : "POST" , 
79-     } ) 
80- 
81-     const  policy  =  response . data  as  Policy 
82-     const  bindings  =  policy . bindings  ||  [ ] 
83-     const  userRoles  =  bindings . reduce < AdminRole [ ] > ( ( roles ,  binding )  =>  { 
84-       if  ( binding . members ?. includes ( `user:${ userEmail }  ) )  { 
85-         if  ( 
86-           binding . role  && 
87-           Object . values ( AdminRole ) . includes ( binding . role  as  AdminRole ) 
88-         )  { 
89-           roles . push ( binding . role  as  AdminRole ) 
90-         } 
91-       } 
92-       return  roles 
93-     } ,  [ ] ) 
94- 
95-     return  userRoles 
96-   }  catch  ( error )  { 
97-     baseLogger . error ( "Failed to get user roles:" ,  error ) 
98-     recordExceptionInCurrentSpan ( { 
99-       error, 
100-       level : ErrorLevel . Critical , 
101-       attributes : { 
102-         "getUserRoles.error.userEmail" : userEmail , 
103-       } , 
104-     } ) 
105-     return  [ ] 
106-   } 
107- } 
108- 
109- export  const  hasFeature  =  async  ( 
110-   userEmail : string , 
111-   feature : AdminFeature , 
36+ export  const  hasAccessRight  =  async  ( 
37+   role : AdminRoleString , 
38+   accessRight : AdminAccessRight , 
11239) : Promise < boolean >  =>  { 
113-   const  roles  =  await  getUserRoles ( userEmail ) 
114-   return  roles . some ( ( role )  =>  ROLE_FEATURES [ role ] ?. includes ( feature ) ) 
40+   return  STRING_ROLE_ACCESS_RIGHTS [ role ] ?. includes ( accessRight )  ||  false 
11541} 
42+ 
43+ // Backward compatibility - deprecated, use AdminAccessRight instead 
44+ export  const  AdminFeature  =  AdminAccessRight 
45+ 
46+ // Backward compatibility - deprecated, use hasAccessRight instead 
47+ export  const  hasFeature  =  hasAccessRight 
0 commit comments