1
0
forked from baron/baron-sso
Files
baron-sso/devfront/src/lib/devApi.ts

640 lines
14 KiB
TypeScript

import apiClient from "./apiClient";
export type ClientStatus = "active" | "inactive";
export type ClientType = "private" | "pkce";
export type ClientSummary = {
id: string;
name: string;
type: ClientType;
status: ClientStatus;
createdAt?: string;
clientSecret?: string;
tokenEndpointAuthMethod?: string;
jwksUri?: string;
backchannelLogoutUri?: string;
backchannelLogoutSessionRequired?: boolean;
redirectUris: string[];
scopes: string[];
metadata?: Record<string, unknown>;
};
export type ClientListResponse = {
items: ClientSummary[];
limit: number;
offset: number;
};
export type TenantSummary = {
id: string;
type: string;
parentId?: string | null;
name: string;
slug: string;
description: string;
status: string;
domains?: string[];
config?: Record<string, unknown>;
memberCount: number;
createdAt: string;
updatedAt: string;
};
export type TenantListResponse = {
items: TenantSummary[];
limit: number;
offset: number;
total: number;
};
export type DevStats = {
total_clients: number;
active_sessions: number;
auth_failures_24h: number;
};
export type RPUsageDailyMetric = {
date: string;
tenantId: string;
tenantType: string;
tenantName?: string;
clientId: string;
clientName: string;
loginRequests: number;
otherRequests: number;
uniqueSubjects: number;
};
export type RPUsagePeriod = "day" | "week" | "month";
export type RPUsageDailyResponse = {
items: RPUsageDailyMetric[];
days: number;
period: RPUsagePeriod;
tenantId?: string;
};
export type DevAuditLog = {
event_id: string;
timestamp: string;
user_id: string;
event_type: string;
status: string;
ip_address: string;
user_agent: string;
device_id?: string;
details?: string;
};
export type DevAuditLogListResponse = {
items: DevAuditLog[];
limit: number;
cursor?: string;
next_cursor?: string;
};
export type ClientEndpoints = {
discovery: string;
issuer: string;
authorization: string;
token: string;
userinfo: string;
};
export type ClientDetailResponse = {
client: ClientSummary & {
clientSecret?: string;
metadata?: Record<string, unknown>;
};
endpoints: ClientEndpoints;
headlessJwksCache?: {
clientId: string;
jwksUri: string;
cachedAt: string;
expiresAt: string;
lastCheckedAt?: string;
lastSuccessfulVerificationAt?: string;
lastRefreshStatus?: "success" | "failure" | "pending";
lastError?: string;
consecutiveFailures?: number;
cachedKids?: string[];
etag?: string;
lastModified?: string;
parsedKeys?: Array<{
kid?: string;
kty?: string;
use?: string;
alg?: string;
n?: string;
}>;
};
};
export type ClientUpsertRequest = {
id?: string;
name?: string;
type?: ClientType;
status?: ClientStatus;
redirectUris?: string[];
scopes?: string[];
grantTypes?: string[];
responseTypes?: string[];
tokenEndpointAuthMethod?: string;
jwksUri?: string;
backchannelLogoutUri?: string;
backchannelLogoutSessionRequired?: boolean;
metadata?: Record<string, unknown>;
};
export type ClientRelation = {
relation: string;
subject: string;
subjectType: string;
subjectId: string;
userName?: string;
userEmail?: string;
userLoginId?: string;
};
export type ClientRelationListResponse = {
items: ClientRelation[];
};
export type ClientRelationUpsertRequest = {
relation: string;
subject?: string;
userId?: string;
};
export type DevAssignableUser = {
id: string;
name: string;
email: string;
loginId?: string;
};
export type DevAssignableUserListResponse = {
items: DevAssignableUser[];
};
export type DevUserSummary = {
id: string;
email: string;
loginId?: string;
name: string;
phone?: string;
role: string;
status: string;
tenantSlug?: string;
companyCode?: string;
tenant?: TenantSummary;
joinedTenants?: TenantSummary[];
metadata?: Record<string, unknown>;
department?: string;
grade?: string;
position?: string;
jobTitle?: string;
createdAt: string;
updatedAt: string;
};
export type ConsentSummary = {
subject: string;
userName?: string;
clientId: string;
clientName?: string;
grantedScopes: string[];
authenticatedAt?: string;
createdAt: string;
deletedAt?: string;
status: "active" | "revoked";
tenantId?: string;
tenantName?: string;
rpMetadata?: Record<string, unknown>;
};
export type ConsentListResponse = {
items: ConsentSummary[];
};
export type RPUserMetadataResponse = {
clientId: string;
userId: string;
metadata: Record<string, unknown>;
};
// --- Federation / IdP Config Types ---
export type ProviderType = "oidc" | "saml";
export type IdpConfig = {
id: string;
client_id: string; // Changed from tenant_id
provider_type: ProviderType;
display_name: string;
status: "active" | "inactive";
issuer_url?: string;
// OIDC specific fields
oidc_client_id?: string;
oidc_client_secret?: string;
scopes?: string;
// SAML specific fields
metadata_url?: string;
metadata_xml?: string;
entity_id?: string;
acs_url?: string;
createdAt: string;
updatedAt: string;
};
export type IdpConfigCreateRequest = Omit<
IdpConfig,
"id" | "createdAt" | "updatedAt"
>;
export type IdpConfigUpdateRequest = Partial<IdpConfigCreateRequest>;
// --- End Federation Types ---
export async function fetchClients() {
const { data } = await apiClient.get<ClientListResponse>("/dev/clients");
return data;
}
export async function fetchDevStats() {
const { data } = await apiClient.get<DevStats>("/dev/stats");
return data;
}
export async function fetchDevRPUsageDaily({
days = 14,
period = "day",
}: {
days?: number;
period?: RPUsagePeriod;
} = {}) {
const { data } = await apiClient.get<RPUsageDailyResponse>(
"/dev/rp-usage/daily",
{
params: { days, period },
},
);
return data;
}
export async function fetchTenants(
limit = 1000,
offset = 0,
parentId?: string,
) {
const { data } = await apiClient.get<TenantListResponse>("/tenants", {
params: { limit, offset, parentId },
});
return data;
}
export async function fetchClient(clientId: string) {
const { data } = await apiClient.get<ClientDetailResponse>(
`/dev/clients/${clientId}`,
);
return data;
}
export async function fetchClientRelations(clientId: string) {
const { data } = await apiClient.get<ClientRelationListResponse>(
`/dev/clients/${clientId}/relations`,
);
return data;
}
export async function fetchRPUserMetadata(clientId: string, userId: string) {
const { data } = await apiClient.get<RPUserMetadataResponse>(
`/dev/clients/${clientId}/users/${userId}/metadata`,
);
return data;
}
export async function updateRPUserMetadata(
clientId: string,
userId: string,
metadata: Record<string, unknown>,
) {
const { data } = await apiClient.put<RPUserMetadataResponse>(
`/dev/clients/${clientId}/users/${userId}/metadata`,
{ metadata },
);
return data;
}
export async function fetchDevUsers(
search: string,
limit = 10,
clientId?: string,
) {
const { data } = await apiClient.get<DevAssignableUserListResponse>(
"/dev/users",
{
params: { search, limit, clientId },
},
);
return data;
}
export async function fetchDevUser(userId: string) {
const { data } = await apiClient.get<DevUserSummary>(
`/admin/users/${userId}`,
);
return data;
}
export async function addClientRelation(
clientId: string,
payload: ClientRelationUpsertRequest,
) {
const { data } = await apiClient.post<ClientRelation>(
`/dev/clients/${clientId}/relations`,
payload,
);
return data;
}
export async function removeClientRelation(
clientId: string,
relation: string,
subject: string,
) {
await apiClient.delete(`/dev/clients/${clientId}/relations`, {
params: { relation, subject },
});
}
export async function updateClientStatus(
clientId: string,
status: ClientStatus,
) {
const { data } = await apiClient.patch<ClientDetailResponse>(
`/dev/clients/${clientId}/status`,
{ status },
);
return data;
}
export async function createClient(payload: ClientUpsertRequest) {
const { data } = await apiClient.post<ClientDetailResponse>(
"/dev/clients",
payload,
);
return data;
}
export async function updateClient(
clientId: string,
payload: ClientUpsertRequest,
) {
const { data } = await apiClient.put<ClientDetailResponse>(
`/dev/clients/${clientId}`,
payload,
);
return data;
}
export async function rotateClientSecret(clientId: string) {
const { data } = await apiClient.post<ClientDetailResponse>(
`/dev/clients/${clientId}/secret/rotate`,
);
return data;
}
export async function refreshHeadlessJwksCache(clientId: string) {
const { data } = await apiClient.post<ClientDetailResponse>(
`/dev/clients/${clientId}/headless-jwks/refresh`,
);
return data;
}
export async function revokeHeadlessJwksCache(clientId: string) {
await apiClient.delete(`/dev/clients/${clientId}/headless-jwks/cache`);
}
export async function deleteClient(clientId: string) {
await apiClient.delete(`/dev/clients/${clientId}`);
}
export async function fetchConsents(
subject: string,
clientId?: string,
status?: string,
) {
const params: Record<string, string> = { subject };
if (clientId) {
params.client_id = clientId;
}
if (status && status !== "all") {
params.status = status;
}
const { data } = await apiClient.get<ConsentListResponse>("/dev/consents", {
params,
});
return data;
}
export async function revokeConsent(subject: string, clientId?: string) {
const params: Record<string, string> = { subject };
if (clientId) {
params.client_id = clientId;
}
await apiClient.delete("/dev/consents", { params });
}
// --- Federation / IdP Config API Calls ---
export async function listIdpConfigsForClient(clientId: string) {
const { data } = await apiClient.get<IdpConfig[]>(
`/dev/clients/${clientId}/idps`,
);
return data;
}
export async function createIdpConfigForClient(
payload: IdpConfigCreateRequest,
) {
const { data } = await apiClient.post<IdpConfig>(
`/dev/clients/${payload.client_id}/idps`,
payload,
);
return data;
}
export async function updateIdpConfig(
clientId: string,
idpId: string,
payload: IdpConfigUpdateRequest,
) {
const { data } = await apiClient.put<IdpConfig>(
`/dev/clients/${clientId}/idps/${idpId}`,
payload,
);
return data;
}
export async function deleteIdpConfig(clientId: string, idpId: string) {
await apiClient.delete(`/dev/clients/${clientId}/idps/${idpId}`);
}
export async function fetchDevAuditLogs(
limit = 50,
cursor?: string,
filters?: {
action?: string;
client_id?: string;
status?: string;
tenant_id?: string;
},
) {
const { data } = await apiClient.get<DevAuditLogListResponse>(
"/dev/audit-logs",
{
params: {
limit,
cursor,
action: filters?.action,
client_id: filters?.client_id,
status: filters?.status,
tenant_id: filters?.tenant_id,
},
},
);
return data;
}
export type MyTenantSummary = Pick<TenantSummary, "id" | "name" | "slug"> &
Partial<TenantSummary>;
export async function fetchMyTenants() {
const { data } = await apiClient.get<MyTenantSummary[]>("/dev/my-tenants");
return data;
}
// --- Developer Request API ---
export type DeveloperRequestStatus =
| "pending"
| "approved"
| "rejected"
| "cancelled"
| "none";
export type DeveloperRequest = {
id: number;
userId: string;
tenantId: string;
name: string;
organization: string;
email?: string;
phone?: string;
role?: string;
reason: string;
accessPages?: string[];
status: DeveloperRequestStatus;
adminNotes?: string;
createdAt: string;
updatedAt: string;
};
export type DeveloperGrant = DeveloperRequest;
export type DeveloperAccessStatus = {
status: DeveloperRequestStatus | "none";
approvedPages?: string[];
pendingPages?: string[];
};
export async function fetchDeveloperRequestStatus(tenantId?: string) {
const { data } = await apiClient.get<DeveloperAccessStatus>(
"/dev/developer-request/status",
{
params: { tenantId },
},
);
return data;
}
export async function requestDeveloperAccess(payload: {
name: string;
organization: string;
reason: string;
tenantId: string;
accessPages: string[];
}) {
const { data } = await apiClient.post<{ status: string }>(
"/dev/developer-request",
payload,
);
return data;
}
export async function fetchDeveloperRequests(status?: string) {
const { data } = await apiClient.get<DeveloperRequest[]>(
"/dev/developer-request/list",
{
params: { status },
},
);
return data;
}
export async function approveDeveloperRequest(id: number, adminNotes: string) {
const { data } = await apiClient.post<{ status: string }>(
`/dev/developer-request/${id}/approve`,
{ adminNotes },
);
return data;
}
export async function rejectDeveloperRequest(id: number, adminNotes: string) {
const { data } = await apiClient.post<{ status: string }>(
`/dev/developer-request/${id}/reject`,
{ adminNotes },
);
return data;
}
export async function cancelDeveloperRequestApproval(
id: number,
adminNotes: string,
) {
const { data } = await apiClient.post<{ status: string }>(
`/dev/developer-request/${id}/cancel-approval`,
{ adminNotes },
);
return data;
}
export async function fetchDeveloperGrants(tenantId?: string) {
const { data } = await apiClient.get<DeveloperGrant[]>(
"/dev/developer-grants",
{
params: { tenantId },
},
);
return data;
}
export async function createDeveloperGrant(payload: {
userId: string;
tenantId: string;
reason?: string;
adminNotes?: string;
accessPages: string[];
}) {
const { data } = await apiClient.post<DeveloperGrant>(
"/dev/developer-grants",
payload,
);
return data;
}
export async function revokeDeveloperGrant(id: number, adminNotes: string) {
const { data } = await apiClient.post<{ status: string }>(
`/dev/developer-grants/${id}/revoke`,
{ adminNotes },
);
return data;
}