feat: add customer authentication and scoped RBAC
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type {
|
||||
ApiEnvelope,
|
||||
AdminUser,
|
||||
AccessQuery,
|
||||
AccessSummary,
|
||||
AccessThresholdConfig,
|
||||
@@ -41,6 +42,8 @@ import type {
|
||||
RealtimeLocationRow,
|
||||
SourceReadinessPlan,
|
||||
SessionInfo,
|
||||
LoginResponse,
|
||||
CustomerUserInput,
|
||||
TrackPlaybackResponse,
|
||||
VehicleRealtimeRow,
|
||||
VehicleCoverageRow,
|
||||
@@ -171,6 +174,20 @@ function withTraceID(message: string, traceID?: string) {
|
||||
|
||||
export const api = {
|
||||
session: (signal?: AbortSignal) => request<SessionInfo>('/api/v2/session', withSignal(undefined, signal)),
|
||||
login: (credentials: { username: string; password: string }) => request<LoginResponse>('/api/v2/auth/login', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials)
|
||||
}),
|
||||
logout: () => request<{ loggedOut: boolean }>('/api/v2/auth/logout', { method: 'POST' }),
|
||||
changePassword: (input: { currentPassword: string; newPassword: string }) => request<{ changed: boolean }>('/api/v2/auth/password', {
|
||||
method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(input)
|
||||
}),
|
||||
adminUsers: (signal?: AbortSignal) => request<AdminUser[]>('/api/v2/admin/users', withSignal(undefined, signal)),
|
||||
createCustomerUser: (input: CustomerUserInput) => request<{ id: number }>('/api/v2/admin/users', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(input)
|
||||
}),
|
||||
updateCustomerUser: (id: number, input: CustomerUserInput) => request<{ id: number }>(`/api/v2/admin/users/${id}`, {
|
||||
method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(input)
|
||||
}),
|
||||
monitorSummary: (params = new URLSearchParams(), signal?: AbortSignal) => request<MonitorSummary>(`/api/v2/monitor/summary?${params.toString()}`, signal ? { signal } : undefined),
|
||||
monitorMap: (params = new URLSearchParams(), signal?: AbortSignal) => request<MonitorMapResponse>(`/api/v2/monitor/map?${params.toString()}`, signal ? { signal } : undefined),
|
||||
monitorWorkspace: (params = new URLSearchParams(), signal?: AbortSignal) => request<MonitorWorkspaceResponse>(`/api/v2/monitor/workspace?${params.toString()}`, signal ? { signal } : undefined),
|
||||
|
||||
@@ -5,11 +5,53 @@ export interface ApiEnvelope<T> {
|
||||
}
|
||||
|
||||
export interface SessionInfo {
|
||||
subjectId?: string;
|
||||
name: string;
|
||||
role: 'viewer' | 'operator' | 'admin';
|
||||
username?: string;
|
||||
role: 'viewer' | 'operator' | 'admin' | 'customer';
|
||||
userType?: 'viewer' | 'operator' | 'admin' | 'customer';
|
||||
authProvider?: 'local' | 'legacy-token' | 'disabled' | string;
|
||||
menuKeys?: string[];
|
||||
vehicleCount?: number;
|
||||
customerRef?: string;
|
||||
tenantRef?: string;
|
||||
authMode: 'disabled' | 'enforce';
|
||||
}
|
||||
|
||||
export interface LoginResponse {
|
||||
accessToken: string;
|
||||
expiresAt: string;
|
||||
session: Omit<SessionInfo, 'authMode'>;
|
||||
}
|
||||
|
||||
export interface AdminUser {
|
||||
id: number;
|
||||
username: string;
|
||||
displayName: string;
|
||||
userType: 'admin' | 'customer';
|
||||
status: 'enabled' | 'disabled';
|
||||
customerRef: string;
|
||||
tenantRef: string;
|
||||
authProvider: string;
|
||||
externalSubject?: string;
|
||||
menuKeys: string[];
|
||||
vehicleVins: string[];
|
||||
lastLoginAt?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface CustomerUserInput {
|
||||
username?: string;
|
||||
displayName: string;
|
||||
password?: string;
|
||||
status: 'enabled' | 'disabled';
|
||||
customerRef: string;
|
||||
tenantRef: string;
|
||||
menuKeys: string[];
|
||||
vehicleVins: string[];
|
||||
}
|
||||
|
||||
export interface MonitorSummary {
|
||||
totalVehicles: number;
|
||||
onlineVehicles: number;
|
||||
|
||||
Reference in New Issue
Block a user