forked from baron/baron-sso
640 lines
14 KiB
TypeScript
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;
|
|
}
|