import * as plugins from '../plugins.js'; import * as interfaces from '../../ts_interfaces/index.js'; import { appState } from './shared.js'; import { getActionContext } from './login.js'; // ============================================================================ // Users State (read-only list of OpsServer user accounts) // ============================================================================ export interface IUser { id: string; username: string; email?: string; name?: string; role: string; status?: 'active' | 'disabled'; authSources?: Array<'local' | 'idp.global'>; } export interface IUsersState { users: IUser[]; isLoading: boolean; error: string | null; lastUpdated: number; } export const usersStatePart = await appState.getStatePart( 'users', { users: [], isLoading: false, error: null, lastUpdated: 0, }, 'soft', ); export const fetchUsersAction = usersStatePart.createAction(async (statePartArg): Promise => { const context = getActionContext(); const currentState = statePartArg.getState()!; if (!context.identity) return currentState; try { const request = new plugins.domtools.plugins.typedrequest.TypedRequest< interfaces.requests.IReq_ListUsers >('/typedrequest', 'listUsers'); const response = await request.fire({ identity: context.identity, }); return { ...currentState, users: response.users, error: null, lastUpdated: Date.now(), }; } catch (error) { return { ...currentState, error: error instanceof Error ? error.message : 'Failed to fetch users', }; } }); export const createUserAction = usersStatePart.createAction<{ email: string; name?: string; role: interfaces.requests.TUserManagementRole; password: string; enableIdpGlobalAuth?: boolean; }>(async (statePartArg, dataArg, actionContext): Promise => { const context = getActionContext(); const currentState = statePartArg.getState()!; if (!context.identity) return currentState; try { const request = new plugins.domtools.plugins.typedrequest.TypedRequest< interfaces.requests.IReq_CreateUser >('/typedrequest', 'createUser'); const response = await request.fire({ identity: context.identity, email: dataArg.email, name: dataArg.name, role: dataArg.role, password: dataArg.password, enableIdpGlobalAuth: dataArg.enableIdpGlobalAuth, }); if (!response.success) { throw new Error(response.message || 'Failed to create user'); } return await actionContext!.dispatch(fetchUsersAction, null); } catch (error) { return { ...currentState, error: error instanceof Error ? error.message : 'Failed to create user', }; } }); export const deleteUserAction = usersStatePart.createAction( async (statePartArg, userIdArg, actionContext): Promise => { const context = getActionContext(); const currentState = statePartArg.getState()!; if (!context.identity) return currentState; try { const request = new plugins.domtools.plugins.typedrequest.TypedRequest< interfaces.requests.IReq_DeleteUser >('/typedrequest', 'deleteUser'); const response = await request.fire({ identity: context.identity, id: userIdArg, }); if (!response.success) { throw new Error(response.message || 'Failed to delete user'); } return await actionContext!.dispatch(fetchUsersAction, null); } catch (error) { return { ...currentState, error: error instanceof Error ? error.message : 'Failed to delete user', }; } }, );