1
0
forked from baron/baron-sso

feat: update worksmobile sync and restore planning

This commit is contained in:
2026-06-01 17:01:53 +09:00
parent 6574fb54b9
commit 5c8a338085
36 changed files with 3922 additions and 243 deletions

View File

@@ -73,7 +73,12 @@ describe("adminApi endpoint contracts", () => {
await adminApi.fetchUser("user-1");
await adminApi.fetchWorksmobileOverview("tenant-1");
await adminApi.fetchWorksmobileComparison("tenant-1", true);
await adminApi.fetchWorksmobileCredentialBatches("tenant-1");
await adminApi.downloadWorksmobileInitialPasswordsCSV("tenant-1");
await adminApi.downloadWorksmobileInitialPasswordsCSV(
"tenant-1",
"credential-batch-1",
);
await adminApi.fetchPasswordPolicy();
await adminApi.fetchUserRpHistory("user-1");
await adminApi.fetchMe();
@@ -104,6 +109,16 @@ describe("adminApi endpoint contracts", () => {
"/v1/admin/tenants/tenant-1/worksmobile/comparison",
{ params: { includeMatched: true } },
);
expect(apiClient.get).toHaveBeenCalledWith(
"/v1/admin/tenants/tenant-1/worksmobile/credential-batches",
);
expect(apiClient.get).toHaveBeenCalledWith(
"/v1/admin/tenants/tenant-1/worksmobile/initial-passwords.csv",
{
params: { batchId: "credential-batch-1" },
responseType: "blob",
},
);
expect(await adminApi.exportTenantsCSV(true, "parent-1")).toMatchObject({
filename: "export.csv",
});
@@ -148,6 +163,20 @@ describe("adminApi endpoint contracts", () => {
await adminApi.enqueueWorksmobileOrgUnitSync("tenant-1", "org/unit");
await adminApi.enqueueWorksmobileOrgUnitDelete("tenant-1", "org/unit");
await adminApi.enqueueWorksmobileUserSync("tenant-1", "user-1");
await adminApi.enqueueWorksmobileUserSync(
"tenant-1",
"user-2",
"credential-batch-1",
);
await adminApi.resetWorksmobileUserPassword(
"tenant-1",
"user-2",
"credential-batch-2",
);
await adminApi.deleteWorksmobileCredentialBatchPasswords(
"tenant-1",
"credential-batch-1",
);
await adminApi.retryWorksmobileJob("tenant-1", "job-1");
await adminApi.bulkUpdateUsers({ userIds: ["user-1"], status: "inactive" });
await adminApi.bulkDeleteUsers(["user-1"]);
@@ -178,6 +207,17 @@ describe("adminApi endpoint contracts", () => {
expect(apiClient.post).toHaveBeenCalledWith(
"/v1/admin/tenants/tenant-1/worksmobile/orgunits/org%2Funit/sync",
);
expect(apiClient.post).toHaveBeenCalledWith(
"/v1/admin/tenants/tenant-1/worksmobile/users/user-2/sync",
{ credentialBatchId: "credential-batch-1" },
);
expect(apiClient.post).toHaveBeenCalledWith(
"/v1/admin/tenants/tenant-1/worksmobile/users/user-2/password/reset",
{ credentialBatchId: "credential-batch-2" },
);
expect(apiClient.delete).toHaveBeenCalledWith(
"/v1/admin/tenants/tenant-1/worksmobile/credential-batches/credential-batch-1/passwords",
);
expect(apiClient.delete).toHaveBeenCalledWith(
"/v1/admin/relying-parties/client-1/owners/User:user-1",
);

View File

@@ -676,6 +676,7 @@ export type UserCreateResponse = UserSummary & {
};
export type UserUpdateRequest = {
email?: string;
loginId?: string;
password?: string;
name?: string;
@@ -725,6 +726,7 @@ export type BulkUserAppointment = {
};
export type BulkUserItem = {
userId?: string;
email: string;
loginId?: string;
name: string;
@@ -750,6 +752,7 @@ export type BulkUserItem = {
emailDomain?: string;
};
metadata: Record<string, unknown>;
importErrors?: string[];
};
export type BulkUserResult = {
@@ -790,6 +793,30 @@ export type WorksmobileOverview = {
recentJobs: WorksmobileOutboxItem[];
};
export type WorksmobileCredentialBatch = {
batchId: string;
operation?: string;
userCount: number;
pendingCount?: number;
processingCount?: number;
processedCount?: number;
failedCount?: number;
hasPasswords: boolean;
deletedAt?: string;
failures?: WorksmobileCredentialBatchFailure[];
createdAt?: string;
updatedAt?: string;
};
export type WorksmobileCredentialBatchFailure = {
userId?: string;
email?: string;
status: string;
retryCount: number;
lastError?: string;
updatedAt?: string;
};
export type WorksmobileComparisonItem = {
resourceType: string;
baronId?: string;
@@ -823,6 +850,10 @@ export type WorksmobileComparisonItem = {
worksmobileParentName?: string;
worksmobileParentEmail?: string;
worksmobileParentExternalKey?: string;
worksmobileJobStatus?: string;
worksmobileJobRetryCount?: number;
worksmobileLastError?: string;
worksmobileLastAttemptAt?: string;
status: string;
};
@@ -906,10 +937,22 @@ export async function fetchWorksmobileComparison(
return data;
}
export async function downloadWorksmobileInitialPasswordsCSV(tenantId: string) {
export async function fetchWorksmobileCredentialBatches(tenantId: string) {
const { data } = await apiClient.get<WorksmobileCredentialBatch[]>(
`/v1/admin/tenants/${tenantId}/worksmobile/credential-batches`,
);
return data;
}
export async function downloadWorksmobileInitialPasswordsCSV(
tenantId: string,
batchId?: string,
) {
const trimmedBatchId = batchId?.trim();
const response = await apiClient.get<Blob>(
`/v1/admin/tenants/${tenantId}/worksmobile/initial-passwords.csv`,
{
...(trimmedBatchId ? { params: { batchId: trimmedBatchId } } : {}),
responseType: "blob",
},
);
@@ -924,6 +967,16 @@ export async function downloadWorksmobileInitialPasswordsCSV(tenantId: string) {
};
}
export async function deleteWorksmobileCredentialBatchPasswords(
tenantId: string,
batchId: string,
) {
const { data } = await apiClient.delete<WorksmobileCredentialBatch>(
`/v1/admin/tenants/${tenantId}/worksmobile/credential-batches/${encodeURIComponent(batchId)}/passwords`,
);
return data;
}
export async function enqueueWorksmobileBackfillDryRun(tenantId: string) {
const { data } = await apiClient.post(
`/v1/admin/tenants/${tenantId}/worksmobile/backfill/dry-run`,
@@ -954,10 +1007,30 @@ export async function enqueueWorksmobileOrgUnitDelete(
export async function enqueueWorksmobileUserSync(
tenantId: string,
userId: string,
credentialBatchId?: string,
) {
const { data } = await apiClient.post<WorksmobileOutboxItem>(
`/v1/admin/tenants/${tenantId}/worksmobile/users/${userId}/sync`,
);
const trimmedBatchId = credentialBatchId?.trim();
const path = `/v1/admin/tenants/${tenantId}/worksmobile/users/${userId}/sync`;
const { data } = trimmedBatchId
? await apiClient.post<WorksmobileOutboxItem>(path, {
credentialBatchId: trimmedBatchId,
})
: await apiClient.post<WorksmobileOutboxItem>(path);
return data;
}
export async function resetWorksmobileUserPassword(
tenantId: string,
userId: string,
credentialBatchId?: string,
) {
const trimmedBatchId = credentialBatchId?.trim();
const path = `/v1/admin/tenants/${tenantId}/worksmobile/users/${userId}/password/reset`;
const { data } = trimmedBatchId
? await apiClient.post<WorksmobileOutboxItem>(path, {
credentialBatchId: trimmedBatchId,
})
: await apiClient.post<WorksmobileOutboxItem>(path);
return data;
}