Implemented rbac

This commit is contained in:
2026-10-11 11:16:08 +02:00
parent 45a6c0aca0
commit 1142cfd94e
24 changed files with 3033 additions and 432 deletions
+108 -30
View File
@@ -92,8 +92,18 @@ import {
Notification,
NotificationPlatform,
NotificationStatus,
Role,
Claim,
CreateUserRequest,
AddUserClaimRequest,
} from '../types';
import {
encodeIdNumberHex,
encodeEntityId,
toSafeInt64String,
} from '../utils/hashids';
import {
parseFriendlyError,
FriendlyError,
@@ -1364,6 +1374,90 @@ export const updateUserStatus = async (userId: string, status: ActivityStatus |
await apiClient.get(`/v1/api/users/${userId}/status/${status}`);
};
export const createUser = async (
tenantId: number | string,
idNumber: string,
payload: CreateUserRequest
): Promise<void> => {
const encodedTenant = encodeEntityId(tenantId) || String(tenantId);
const encodedIdNumber = encodeIdNumberHex(idNumber);
await apiClient.post(`/v1/api/users/${encodeURIComponent(encodedTenant)}/${encodeURIComponent(encodedIdNumber)}`, {
id: payload.id || null,
userName: payload.userName || null,
email: payload.email || null,
emailConfirmed: payload.emailConfirmed ?? true,
phoneNumber: payload.phoneNumber || null,
phoneNumberConfirmed: payload.phoneNumberConfirmed ?? false,
LockoutEnabled: payload.LockoutEnabled ?? false,
twoFactorEnabled: payload.twoFactorEnabled ?? false,
accessFailedCount: payload.accessFailedCount !== undefined ? Number(payload.accessFailedCount) : 0,
lockoutEnd: payload.lockoutEnd || null,
});
};
import {
fetchAndCacheSystemRoles,
fetchAndCacheRoleClaims,
getSystemClaims,
getCachedSystemRoles,
getCachedRoleClaims,
preloadAndCacheAllRoleClaims,
} from './roleClaimsCache';
export {
getSystemClaims,
getCachedSystemRoles,
getCachedRoleClaims,
preloadAndCacheAllRoleClaims,
};
export const getSystemRoles = async (): Promise<Role[]> => {
return await fetchAndCacheSystemRoles();
};
export const getUserRoles = async (userId: string): Promise<Role[]> => {
const res = await apiClient.get<Role[]>(`/v1/api/users/${userId}/roles`);
return res.data || [];
};
export const assignUserRole = async (userId: string, roleId: string): Promise<void> => {
await apiClient.patch(`/v1/api/users/${userId}/roles/${roleId}`);
};
export const removeUserRole = async (userId: string, roleId: string): Promise<void> => {
await apiClient.delete(`/v1/api/users/${userId}/roles/${roleId}`);
};
export const getRoleClaims = async (roleId: string, roleName?: string): Promise<Claim[]> => {
return await fetchAndCacheRoleClaims(roleId, roleName);
};
export const getUserClaims = async (userId: string): Promise<Claim[]> => {
const res = await apiClient.get<Claim[]>(`/v1/api/users/${userId}/claims`);
return res.data || [];
};
export const addUserClaim = async (payload: AddUserClaimRequest): Promise<void> => {
await apiClient.patch('/v1/api/users/user/claims', {
userId: payload.userId,
claimId: Number(payload.claimId),
claimType: payload.claimType,
claimValue: payload.claimValue,
});
};
export const deleteUserClaim = async (targetUserId: string, claimId: string | number): Promise<void> => {
await apiClient.delete(`/v1/api/users/${targetUserId}/claims/${claimId}`);
};
export const forceLogoutUser = async (userId: string): Promise<void> => {
await apiClient.put(`/v1/api/users/${userId}/session/logout`);
};
export const setUserLockout = async (userId: string, disable: boolean): Promise<void> => {
await apiClient.put(`/v1/api/users/${userId}/session/lockout/${disable}`);
};
import {
syncUserAccount,
ensureUserSynced,
@@ -1421,29 +1515,21 @@ export const sendInvite = async (payload: InviteRequest): Promise<Invite> => {
const tenantId = getCurrentUserTenantId();
const hostOrgId =
payload.organisationId !== undefined && payload.organisationId !== '' && payload.organisationId !== null
? toIntegerId(payload.organisationId)
: (tenantId !== null ? tenantId : 0);
? toSafeInt64String(payload.organisationId)
: (tenantId !== null ? String(tenantId) : '0');
const body = {
organisationId: hostOrgId,
invitedOrganisationId: toIntegerId(payload.invitedOrganisationId),
awardId: toIntegerId(payload.awardId),
contractId: toIntegerId(payload.contractId),
invitedOrganisationId: toSafeInt64String(payload.invitedOrganisationId),
awardId: toSafeInt64String(payload.awardId),
contractId: toSafeInt64String(payload.contractId),
recipient: payload.recipient,
message: payload.message,
platform: payload.platform !== undefined ? Number(payload.platform) : 1,
};
try {
const res = await apiClient.post<Invite>('/v1/api/communications/invites', body);
return res.data;
} catch (err: any) {
if (err?.response?.status === 404) {
const res = await apiClient.post<Invite>('/v1/api/communications/invite', body);
return res.data;
}
throw err;
}
const res = await apiClient.post<Invite>('/v1/api/communications/invites', body);
return res.data;
};
export const getInvites = async (page = 1, pageSize = 100): Promise<Invite[]> => {
@@ -1451,6 +1537,11 @@ export const getInvites = async (page = 1, pageSize = 100): Promise<Invite[]> =>
return res.data || [];
};
export const getApplicantData = async (applicantUserId: string): Promise<Invite> => {
const res = await apiClient.get<Invite>(`/v1/api/communications/applicants/${applicantUserId}/all`);
return res.data;
};
export const getApplicantInvite = async (applicantUserId: string): Promise<Invite> => {
try {
const res = await apiClient.get<Invite>(`/v1/api/communications/invites/applicants/${applicantUserId}`);
@@ -1481,26 +1572,13 @@ export const getNotifications = async (organisationId?: string | number): Promis
const hashedOrgId = await toolsService.resolveOrganisationId(targetOrgId);
try {
const res = await apiClient.get<Notification[]>(
`/v1/api/communications/norifications/${encodeURIComponent(hashedOrgId)}`
`/v1/api/communications/notifications/${encodeURIComponent(hashedOrgId)}`
);
if (res.data && Array.isArray(res.data)) {
return res.data;
}
} catch (err: any) {
if (err?.response?.status === 404) {
try {
const fallbackRes = await apiClient.get<Notification[]>(
`/v1/api/communications/notifications/${encodeURIComponent(hashedOrgId)}`
);
if (fallbackRes.data && Array.isArray(fallbackRes.data)) {
return fallbackRes.data;
}
} catch (fallbackErr) {
console.warn('[getNotifications] Notification fallback route error:', fallbackErr);
}
} else {
console.warn('[getNotifications] API error fetching notifications:', err);
}
console.warn('[getNotifications] API error fetching notifications:', err);
}
return [];