1- import React from 'react' ;
2- import { Title , SimpleGrid , Container } from '@mantine/core' ;
1+ import React , { useState } from 'react' ;
2+ import { Title , SimpleGrid , Container , Select , Group , Stack , Text } from '@mantine/core' ;
33import { AuthGuard } from '@ui/components/AuthGuard' ;
44import { useApi } from '@ui/util/api' ;
55import { AppRoles } from '@common/roles' ;
66import UserInvitePanel from './UserInvitePanel' ;
77import GroupMemberManagement from './GroupMemberManagement' ;
8- import {
9- EntraActionResponse ,
10- GroupMemberGetResponse ,
11- GroupModificationPatchRequest ,
12- } from '@common/types/iam' ;
8+ import { EntraActionResponse , GroupMemberGetResponse } from '@common/types/iam' ;
139import { transformCommaSeperatedName } from '@common/utils' ;
14- import { getRunEnvironmentConfig } from '@ui/config' ;
10+ import { getRunEnvironmentConfig , KnownGroups } from '@ui/config' ;
11+
12+ const userGroupMappings : KnownGroups = {
13+ Exec : 'Executive Council' ,
14+ CommChairs : 'Committee Chairs' ,
15+ StripeLinkCreators : 'Stripe Link Creators' ,
16+ } ;
1517
1618export const ManageIamPage = ( ) => {
1719 const api = useApi ( 'core' ) ;
18- const groupId = getRunEnvironmentConfig ( ) . KnownGroupMappings . Exec ;
20+ const groupMappings = getRunEnvironmentConfig ( ) . KnownGroupMappings ;
21+ const groupOptions = Object . entries ( groupMappings ) . map ( ( [ key , value ] ) => ( {
22+ label : userGroupMappings [ key as keyof KnownGroups ] || key ,
23+ value : `${ key } _${ value } ` , // to ensure that the same group for multiple roles still renders
24+ } ) ) ;
25+
26+ const [ selectedGroup , setSelectedGroup ] = useState ( groupOptions [ 0 ] ?. value || '' ) ;
1927
2028 const handleInviteSubmit = async ( emailList : string [ ] ) => {
2129 try {
2230 const response = await api . post ( '/api/v1/iam/inviteUsers' , {
2331 emails : emailList ,
2432 } ) ;
25- return response . data ;
33+ return response . data as EntraActionResponse ;
2634 } catch ( error : any ) {
2735 console . error ( 'Failed to invite users:' , error ) ;
2836 return {
@@ -35,32 +43,36 @@ export const ManageIamPage = () => {
3543 }
3644 } ;
3745
38- const getExecMembers = async ( ) => {
46+ const getGroupMembers = async ( selectedGroup : string ) => {
3947 try {
40- const response = await api . get ( `/api/v1/iam/groups/${ groupId } ` ) ;
41- const responseMapped = response . data
42- . map ( ( x : any ) => ( {
48+ const response = await api . get ( `/api/v1/iam/groups/${ selectedGroup . split ( '_' ) [ 1 ] } ` ) ;
49+ const data = response . data as GroupMemberGetResponse ;
50+ const responseMapped = data
51+ . map ( ( x ) => ( {
4352 ...x ,
4453 name : transformCommaSeperatedName ( x . name ) ,
4554 } ) )
46- . sort ( ( x : any , y : any ) => ( x . name > y . name ? 1 : x . name < y . name ? - 1 : 0 ) ) ;
47- return responseMapped as GroupMemberGetResponse ;
48- } catch ( error : any ) {
55+ . sort ( ( a , b ) => ( a . name > b . name ? 1 : a . name < b . name ? - 1 : 0 ) ) ;
56+ return responseMapped ;
57+ } catch ( error ) {
4958 console . error ( 'Failed to get users:' , error ) ;
5059 return [ ] ;
5160 }
5261 } ;
5362
54- const updateExecMembers = async ( toAdd : string [ ] , toRemove : string [ ] ) => {
55- const allMembers = toAdd . concat ( toRemove ) ;
63+ const updateGroupMembers = async ( toAdd : string [ ] , toRemove : string [ ] ) => {
64+ const allMembers = [ ... toAdd , ... toRemove ] ;
5665 try {
57- const response = await api . patch ( `/api/v1/iam/groups/${ groupId } ` , {
66+ const response = await api . patch ( `/api/v1/iam/groups/${ selectedGroup . split ( '_' ) [ 1 ] } ` , {
5867 remove : toRemove ,
5968 add : toAdd ,
60- } as GroupModificationPatchRequest ) ;
61- return response . data as EntraActionResponse ;
62- } catch ( error : any ) {
63- console . error ( 'Failed to get users:' , error ) ;
69+ } ) ;
70+ return response . data ;
71+ } catch ( error ) {
72+ if ( ! ( error instanceof Error ) ) {
73+ throw error ;
74+ }
75+ console . error ( 'Failed to modify group members:' , error ) ;
6476 return {
6577 success : [ ] ,
6678 failure : allMembers . map ( ( email ) => ( {
@@ -82,9 +94,26 @@ export const ManageIamPage = () => {
8294 resourceDef = { { service : 'core' , validRoles : [ AppRoles . IAM_ADMIN ] } }
8395 isAppShell = { false }
8496 >
85- < GroupMemberManagement fetchMembers = { getExecMembers } updateMembers = { updateExecMembers } />
97+ < Stack >
98+ < Text fw = { 500 } mb = { 4 } size = "lg" >
99+ Group Management
100+ </ Text >
101+ < Select
102+ label = "Select Group"
103+ data = { groupOptions }
104+ value = { selectedGroup }
105+ clearable = { false }
106+ onChange = { ( value ) => value && setSelectedGroup ( value ) }
107+ placeholder = "Choose a group to manage"
108+ />
109+ < GroupMemberManagement
110+ fetchMembers = { ( ) => {
111+ return getGroupMembers ( selectedGroup ) ;
112+ } }
113+ updateMembers = { updateGroupMembers }
114+ />
115+ </ Stack >
86116 </ AuthGuard >
87- { /* For future panels, make sure to add an auth guard if not every IAM role can see it. */ }
88117 </ SimpleGrid >
89118 </ AuthGuard >
90119 ) ;
0 commit comments