@syndew/oluso-plugin-scim 0.0.0-stage → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syndew-oluso-plugin-scim.mjs","sources":["../../../../../libs/plugins/scim/src/lib/scim.routes.ts","../../../../../libs/plugins/scim/src/lib/scim.plugin.ts","../../../../../libs/plugins/scim/src/lib/services/scim.service.ts","../../../../../libs/plugins/scim/src/lib/pages/scim-clients/scim-clients.component.ts","../../../../../libs/plugins/scim/src/lib/pages/scim-client-detail/scim-client-detail.component.ts","../../../../../libs/plugins/scim/src/lib/pages/scim-mappings/scim-mappings.component.ts","../../../../../libs/plugins/scim/src/lib/pages/scim-providers/scim-providers.component.ts","../../../../../libs/plugins/scim/src/lib/pages/scim-provider-detail/scim-provider-detail.component.ts","../../../../../libs/plugins/scim/src/index.ts","../../../../../libs/plugins/scim/src/syndew-oluso-plugin-scim.ts"],"sourcesContent":["import { Routes } from '@angular/router';\n\nexport const SCIM_ROUTES: Routes = [\n {\n path: '',\n redirectTo: 'clients',\n pathMatch: 'full',\n },\n {\n path: 'clients',\n loadComponent: () =>\n import('./pages/scim-clients/scim-clients.component').then((m) => m.ScimClientsComponent),\n data: { title: 'SCIM Clients' },\n },\n {\n path: 'clients/:id',\n loadComponent: () =>\n import('./pages/scim-client-detail/scim-client-detail.component').then(\n (m) => m.ScimClientDetailComponent\n ),\n data: { title: 'SCIM Client Details' },\n },\n {\n path: 'clients/:clientId/mappings',\n loadComponent: () =>\n import('./pages/scim-mappings/scim-mappings.component').then((m) => m.ScimMappingsComponent),\n data: { title: 'Attribute Mappings' },\n },\n {\n path: 'providers',\n loadComponent: () =>\n import('./pages/scim-providers/scim-providers.component').then((m) => m.ScimProvidersComponent),\n data: { title: 'SCIM Providers' },\n },\n {\n path: 'providers/:id',\n loadComponent: () =>\n import('./pages/scim-provider-detail/scim-provider-detail.component').then(\n (m) => m.ScimProviderDetailComponent\n ),\n data: { title: 'SCIM Provider Details' },\n },\n];\n","import { AdminPlugin, NavItem } from '@syndew/oluso-ui-core';\nimport { SCIM_ROUTES } from './scim.routes';\n\n/**\n * SCIM Admin Plugin\n *\n * Provides SCIM provisioning management functionality:\n * - SCIM client management (CRUD): identity providers that push into us\n * - Token management and rotation\n * - Attribute mapping configuration\n * - Provisioning activity logs\n * - SCIM providers: downstream systems we push users and groups to\n */\nexport const SCIM_PLUGIN: AdminPlugin = {\n name: 'oluso-scim',\n version: '1.0.0',\n\n // Plugin routes - will be automatically added under /scim path\n routes: [\n {\n path: 'scim',\n children: SCIM_ROUTES,\n },\n ],\n\n navItems: [\n {\n id: 'scim',\n label: 'SCIM Provisioning',\n path: '/scim',\n icon: 'cloud-upload',\n order: 30,\n permission: 'scim.read',\n mergeIntoPath: '/identity-providers',\n children: [\n { label: 'Clients', path: '/scim/clients', icon: 'cloud-upload', order: 0 },\n { label: 'Providers', path: '/scim/providers', icon: 'cloud-upload', order: 1 },\n ],\n } as NavItem,\n ],\n};\n\n/**\n * Helper function to get SCIM navigation items\n */\nexport function getScimNavItems(): NavItem[] {\n return SCIM_PLUGIN.navItems ?? [];\n}\n","import { Injectable, inject } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { ApiService } from '@syndew/oluso-admin-ui';\nimport type { PaginatedResponse } from '@syndew/oluso-ui-core';\nimport {\n ScimClient,\n CreateScimClientRequest,\n CreateScimClientResponse,\n ScimProvisioningLog,\n ScimAttributeMapping,\n SaveScimAttributeMappingRequest,\n ScimMappingOptions,\n ScimMappingPreview,\n ScimAttributeSuggestion,\n InternalPropertyOption,\n TransformationOption,\n} from '../models/scim.model';\nimport {\n ScimProvider,\n ScimProviderOptions,\n CreateScimProviderRequest,\n UpdateScimProviderRequest,\n ScimProviderAttributeMapping,\n SaveScimProviderAttributeMappingRequest,\n ScimProviderTestResult,\n ScimProviderReconcileResult,\n ScimProviderQueueResponse,\n ScimProviderLog,\n ScimProviderResource,\n ScimProviderPreview,\n} from '../models/scim-provider.model';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class ScimService {\n private readonly api = inject(ApiService);\n\n // ============================================\n // Client Operations\n // ============================================\n\n getClients(): Observable<ScimClient[]> {\n return this.api.get<ScimClient[]>('/scim/clients');\n }\n\n getClient(id: string): Observable<ScimClient> {\n return this.api.get<ScimClient>(`/scim/clients/${id}`);\n }\n\n createClient(request: CreateScimClientRequest): Observable<CreateScimClientResponse> {\n return this.api.post<CreateScimClientResponse>('/scim/clients', request);\n }\n\n updateClient(id: string, request: ScimClient): Observable<ScimClient> {\n return this.api.put<ScimClient>(`/scim/clients/${id}`, request);\n }\n\n deleteClient(id: string): Observable<void> {\n return this.api.delete<void>(`/scim/clients/${id}`);\n }\n\n rotateToken(id: string): Observable<{ token: string }> {\n return this.api.post<{ token: string }>(`/scim/clients/${id}/rotate-token`, {});\n }\n\n getLogs(\n clientId: string,\n page = 1,\n pageSize = 50,\n ): Observable<PaginatedResponse<ScimProvisioningLog>> {\n return this.api.getPaginated<ScimProvisioningLog>(`/scim/clients/${clientId}/logs`, {\n page,\n pageSize,\n });\n }\n\n // ============================================\n // Attribute Mapping Operations\n // ============================================\n\n getMappings(clientId: string): Observable<ScimAttributeMapping[]> {\n return this.api.get<ScimAttributeMapping[]>(`/scim/clients/${clientId}/mappings`);\n }\n\n getMapping(clientId: string, mappingId: string): Observable<ScimAttributeMapping> {\n return this.api.get<ScimAttributeMapping>(`/scim/clients/${clientId}/mappings/${mappingId}`);\n }\n\n getMappingOptions(): Observable<ScimMappingOptions> {\n return this.api.get<ScimMappingOptions>('/scim/clients/mapping-options');\n }\n\n previewMappings(\n clientId: string,\n resource: Record<string, unknown>,\n mode: 'create' | 'replace' | 'patch' = 'create',\n ): Observable<ScimMappingPreview> {\n return this.api.post<ScimMappingPreview>(`/scim/clients/${clientId}/mappings/preview`, {\n resource,\n mode,\n });\n }\n\n createMapping(\n clientId: string,\n request: SaveScimAttributeMappingRequest,\n ): Observable<ScimAttributeMapping> {\n return this.api.post<ScimAttributeMapping>(`/scim/clients/${clientId}/mappings`, request);\n }\n\n updateMapping(\n clientId: string,\n mappingId: string,\n request: SaveScimAttributeMappingRequest,\n ): Observable<ScimAttributeMapping> {\n return this.api.put<ScimAttributeMapping>(\n `/scim/clients/${clientId}/mappings/${mappingId}`,\n request,\n );\n }\n\n deleteMapping(clientId: string, mappingId: string): Observable<void> {\n return this.api.delete<void>(`/scim/clients/${clientId}/mappings/${mappingId}`);\n }\n\n applyDefaultMappings(clientId: string, provider?: string): Observable<ScimAttributeMapping[]> {\n return this.api.post<ScimAttributeMapping[]>(`/scim/clients/${clientId}/mappings/defaults`, {\n provider,\n });\n }\n\n // ============================================\n // Outbound providers (we push to them)\n // ============================================\n\n getProviderOptions(): Observable<ScimProviderOptions> {\n return this.api.get<ScimProviderOptions>('/scim/providers/options');\n }\n\n getProviders(): Observable<ScimProvider[]> {\n return this.api.get<ScimProvider[]>('/scim/providers');\n }\n\n getProvider(id: string): Observable<ScimProvider> {\n return this.api.get<ScimProvider>(`/scim/providers/${id}`);\n }\n\n createProvider(request: CreateScimProviderRequest): Observable<ScimProvider> {\n return this.api.post<ScimProvider>('/scim/providers', request);\n }\n\n updateProvider(id: string, request: UpdateScimProviderRequest): Observable<ScimProvider> {\n return this.api.put<ScimProvider>(`/scim/providers/${id}`, request);\n }\n\n deleteProvider(id: string): Observable<void> {\n return this.api.delete<void>(`/scim/providers/${id}`);\n }\n\n setProviderSecret(id: string, secret: string): Observable<ScimProvider> {\n return this.api.put<ScimProvider>(`/scim/providers/${id}/secret`, { secret });\n }\n\n testProvider(id: string): Observable<ScimProviderTestResult> {\n return this.api.post<ScimProviderTestResult>(`/scim/providers/${id}/test`, {});\n }\n\n reconcileProvider(id: string): Observable<ScimProviderReconcileResult> {\n return this.api.post<ScimProviderReconcileResult>(`/scim/providers/${id}/reconcile`, {});\n }\n\n previewProvider(id: string, userId: string): Observable<ScimProviderPreview> {\n return this.api.post<ScimProviderPreview>(`/scim/providers/${id}/preview`, { userId });\n }\n\n getProviderQueue(\n id: string,\n status?: string,\n skip = 0,\n take = 50,\n ): Observable<ScimProviderQueueResponse> {\n const params: Record<string, string | number> = { skip, take };\n if (status) params['status'] = status;\n return this.api.get<ScimProviderQueueResponse>(`/scim/providers/${id}/queue`, params);\n }\n\n retryProviderQueue(id: string): Observable<{ requeued: number }> {\n return this.api.post<{ requeued: number }>(`/scim/providers/${id}/queue/retry`, {});\n }\n\n /** A provider's calls, newest first; `success` false returns only the failed ones. */\n getProviderLogs(\n id: string,\n page = 1,\n pageSize = 50,\n success?: boolean,\n ): Observable<PaginatedResponse<ScimProviderLog>> {\n return this.api.getPaginated<ScimProviderLog>(\n `/scim/providers/${id}/logs`,\n { page, pageSize },\n success === undefined ? undefined : { success },\n );\n }\n\n getProviderResources(\n id: string,\n type?: 'User' | 'Group',\n page = 1,\n pageSize = 50,\n ): Observable<PaginatedResponse<ScimProviderResource>> {\n return this.api.getPaginated<ScimProviderResource>(\n `/scim/providers/${id}/resources`,\n { page, pageSize },\n type ? { type } : undefined,\n );\n }\n\n getProviderMappings(id: string): Observable<ScimProviderAttributeMapping[]> {\n return this.api.get<ScimProviderAttributeMapping[]>(`/scim/providers/${id}/mappings`);\n }\n\n createProviderMapping(\n id: string,\n request: SaveScimProviderAttributeMappingRequest,\n ): Observable<ScimProviderAttributeMapping> {\n return this.api.post<ScimProviderAttributeMapping>(`/scim/providers/${id}/mappings`, request);\n }\n\n updateProviderMapping(\n id: string,\n mappingId: string,\n request: SaveScimProviderAttributeMappingRequest,\n ): Observable<ScimProviderAttributeMapping> {\n return this.api.put<ScimProviderAttributeMapping>(\n `/scim/providers/${id}/mappings/${mappingId}`,\n request,\n );\n }\n\n deleteProviderMapping(id: string, mappingId: string): Observable<void> {\n return this.api.delete<void>(`/scim/providers/${id}/mappings/${mappingId}`);\n }\n\n applyProviderDefaultMappings(id: string): Observable<ScimProviderAttributeMapping[]> {\n return this.api.post<ScimProviderAttributeMapping[]>(\n `/scim/providers/${id}/mappings/defaults`,\n {},\n );\n }\n\n // ============================================\n // Suggestions and Options (static data)\n // ============================================\n\n getScimAttributeSuggestions(): ScimAttributeSuggestion[] {\n return [\n // Core SCIM User attributes\n { attribute: 'userName', description: 'Unique username for the user', provider: 'standard' },\n { attribute: 'name.givenName', description: 'First name', provider: 'standard' },\n { attribute: 'name.familyName', description: 'Last name', provider: 'standard' },\n { attribute: 'name.formatted', description: 'Full formatted name', provider: 'standard' },\n { attribute: 'displayName', description: 'Display name', provider: 'standard' },\n {\n attribute: 'emails[type eq \"work\"].value',\n description: 'Work email address',\n provider: 'standard',\n },\n {\n attribute: 'emails[primary eq true].value',\n description: 'Primary email address',\n provider: 'standard',\n },\n {\n attribute: 'phoneNumbers[type eq \"work\"].value',\n description: 'Work phone number',\n provider: 'standard',\n },\n {\n attribute: 'phoneNumbers[type eq \"mobile\"].value',\n description: 'Mobile phone number',\n provider: 'standard',\n },\n { attribute: 'active', description: 'Whether the user is active', provider: 'standard' },\n { attribute: 'title', description: 'Job title', provider: 'standard' },\n { attribute: 'preferredLanguage', description: 'Preferred language', provider: 'standard' },\n { attribute: 'locale', description: 'Locale', provider: 'standard' },\n { attribute: 'timezone', description: 'Timezone', provider: 'standard' },\n\n // Enterprise User extension\n {\n attribute: 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:employeeNumber',\n description: 'Employee number',\n provider: 'standard',\n },\n {\n attribute: 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department',\n description: 'Department',\n provider: 'standard',\n },\n {\n attribute: 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:manager.value',\n description: 'Manager user ID',\n provider: 'standard',\n },\n {\n attribute: 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:organization',\n description: 'Organization',\n provider: 'standard',\n },\n {\n attribute: 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:costCenter',\n description: 'Cost center',\n provider: 'standard',\n },\n {\n attribute: 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:division',\n description: 'Division',\n provider: 'standard',\n },\n\n // Azure AD specific\n {\n attribute: 'urn:ietf:params:scim:schemas:extension:azure:2.0:User:objectId',\n description: 'Azure AD Object ID',\n provider: 'azure',\n },\n {\n attribute: 'urn:ietf:params:scim:schemas:extension:azure:2.0:User:immutableId',\n description: 'Azure AD Immutable ID',\n provider: 'azure',\n },\n\n // Okta specific\n {\n attribute: 'urn:ietf:params:scim:schemas:extension:okta:2.0:User:secondEmail',\n description: 'Okta secondary email',\n provider: 'okta',\n },\n ];\n }\n\n // ============================================\n // Helper to get SCIM endpoint URL\n // ============================================\n\n /**\n * The tenant-specific SCIM base URL to configure in an upstream provisioning\n * client. Resolved server-side from the tenant's issuer (custom domain /\n * subdomain), not the admin portal's origin.\n */\n getScimEndpointUrl(): Observable<{ url: string }> {\n return this.api.get<{ url: string }>('/scim/clients/endpoint-url');\n }\n}\n\n/** Labels for the inbound target properties the server lists in mapping-options. */\nconst INTERNAL_PROPERTY_LABELS: Record<string, string> = {\n UserName: 'Username',\n Email: 'Email',\n FirstName: 'First name',\n LastName: 'Last name',\n DisplayName: 'Display name',\n PhoneNumber: 'Phone number',\n Locale: 'Locale',\n TimeZone: 'Time zone',\n IsActive: 'Active',\n ProfilePictureUrl: 'Profile picture URL',\n};\n\n/** Labels for the transformations the server lists in mapping-options. */\nconst TRANSFORMATION_LABELS: Record<string, string> = {\n none: 'No transformation',\n lowercase: 'Convert to lowercase',\n uppercase: 'Convert to uppercase',\n trim: 'Trim whitespace',\n normalize_email: 'Normalize email address',\n normalize_phone: 'Normalize phone number',\n extract_domain: 'Extract domain from email',\n format_name: 'Format as proper name (Title Case)',\n};\n\n/** The server's inbound target properties, labelled; one without a label shows its name. */\nexport function internalPropertyOptions(names: readonly string[]): InternalPropertyOption[] {\n return names.map((name) => ({ name, displayName: INTERNAL_PROPERTY_LABELS[name] ?? name }));\n}\n\n/** The server's transformations, labelled; one without a label shows its name. */\nexport function transformationOptions(names: readonly string[]): TransformationOption[] {\n return names.map((name) => ({ name, description: TRANSFORMATION_LABELS[name] ?? name }));\n}\n","import { Component, inject, signal, OnInit } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { RouterLink } from '@angular/router';\nimport { FormsModule } from '@angular/forms';\nimport { IconComponent, ModalComponent } from '@syndew/oluso-ui-core';\nimport { ScimService } from '../../services/scim.service';\nimport { ScimClient } from '../../models/scim.model';\n\n@Component({\n selector: 'lib-scim-clients',\n standalone: true,\n imports: [CommonModule, RouterLink, FormsModule, IconComponent, ModalComponent],\n template: `\n <div class=\"space-y-6\">\n <!-- Header -->\n <div class=\"flex justify-between items-start\">\n <div>\n <h1 class=\"text-2xl font-semibold text-gray-900\">SCIM Provisioning</h1>\n <p class=\"text-gray-500 mt-1\">\n Manage SCIM clients for automated user provisioning from external identity providers\n </p>\n </div>\n <button\n (click)=\"showCreateModal.set(true)\"\n class=\"inline-flex items-center px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 transition-colors\"\n >\n <ui-icon name=\"plus\" class=\"h-5 w-5 mr-2\" />\n Add SCIM Client\n </button>\n </div>\n\n <!-- Token Display Modal -->\n <ui-modal\n [open]=\"!!newToken()\"\n title=\"SCIM API Token\"\n size=\"lg\"\n [closeOnBackdrop]=\"false\"\n (closed)=\"newToken.set(null)\"\n >\n <p class=\"text-sm text-gray-600 mb-4\">\n Copy this token now. You won't be able to see it again.\n </p>\n <div class=\"bg-gray-100 p-4 rounded-md font-mono text-sm break-all mb-4\">\n {{ newToken() }}\n </div>\n <div class=\"flex justify-end gap-2\">\n <button\n (click)=\"copyToken()\"\n class=\"inline-flex items-center px-4 py-2 bg-gray-100 rounded-md hover:bg-gray-200 transition-colors\"\n >\n @if (copiedToken()) {\n <ui-icon name=\"check\" class=\"h-5 w-5 mr-2 text-green-600\" />\n Copied!\n } @else {\n <ui-icon name=\"clipboard-document\" class=\"h-5 w-5 mr-2\" />\n Copy\n }\n </button>\n <button\n (click)=\"newToken.set(null)\"\n class=\"px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 transition-colors\"\n >\n Done\n </button>\n </div>\n </ui-modal>\n\n <!-- Create Modal -->\n <ui-modal\n [open]=\"showCreateModal()\"\n title=\"Create SCIM Client\"\n size=\"md\"\n (closed)=\"showCreateModal.set(false)\"\n >\n <form (ngSubmit)=\"handleCreate()\">\n <div class=\"mb-4\">\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Name</label>\n <input\n type=\"text\"\n [(ngModel)]=\"createForm.name\"\n name=\"name\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n placeholder=\"e.g., HR System, Identity Directory\"\n required\n />\n </div>\n <div class=\"mb-4\">\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Description (optional)</label>\n <input\n type=\"text\"\n [(ngModel)]=\"createForm.description\"\n name=\"description\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n placeholder=\"Optional description\"\n />\n </div>\n <div class=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n (click)=\"showCreateModal.set(false)\"\n class=\"px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n class=\"px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 transition-colors\"\n >\n Create\n </button>\n </div>\n </form>\n </ui-modal>\n\n @if (error()) {\n <div class=\"bg-red-50 text-red-700 p-4 rounded-md\">{{ error() }}</div>\n }\n\n <!-- SCIM Endpoint Info -->\n <div class=\"bg-blue-50 border border-blue-200 rounded-md p-4\">\n <h3 class=\"font-medium text-blue-900 mb-2\">SCIM Endpoint URL</h3>\n <code class=\"text-sm text-blue-700\">{{ scimEndpointUrl }}</code>\n <p class=\"text-sm text-blue-600 mt-2\">\n Use this URL as the SCIM 2.0 base endpoint when configuring an upstream provisioning client.\n </p>\n </div>\n\n <!-- Clients Table -->\n <div class=\"bg-white shadow rounded-lg overflow-hidden\">\n @if (loading()) {\n <div class=\"p-8 text-center text-gray-500\">Loading...</div>\n } @else {\n <table class=\"min-w-full divide-y divide-gray-200\">\n <thead class=\"bg-gray-50\">\n <tr>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Name</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Status</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Last Activity</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Stats</th>\n <th class=\"px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase\">Actions</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200\">\n @if (clients().length === 0) {\n <tr>\n <td colspan=\"5\" class=\"px-6 py-8 text-center text-gray-500\">\n No SCIM clients configured. Create one to enable provisioning.\n </td>\n </tr>\n } @else {\n @for (client of clients(); track client.id) {\n <tr>\n <td class=\"px-6 py-4\">\n <a\n [routerLink]=\"['/scim/clients', client.id]\"\n class=\"text-primary-600 hover:underline font-medium\"\n >\n {{ client.name }}\n </a>\n @if (client.description) {\n <p class=\"text-sm text-gray-500\">{{ client.description }}</p>\n }\n </td>\n <td class=\"px-6 py-4\">\n <span\n class=\"inline-flex px-2 py-1 text-xs rounded-full\"\n [class.bg-green-100]=\"client.isEnabled\"\n [class.text-green-800]=\"client.isEnabled\"\n [class.bg-gray-100]=\"!client.isEnabled\"\n [class.text-gray-800]=\"!client.isEnabled\"\n >\n {{ client.isEnabled ? 'Enabled' : 'Disabled' }}\n </span>\n </td>\n <td class=\"px-6 py-4 text-sm text-gray-500\">\n {{ client.lastActivityAt ? formatDate(client.lastActivityAt) : 'Never' }}\n </td>\n <td class=\"px-6 py-4 text-sm\">\n <span class=\"text-green-600\">{{ client.successCount }} ok</span>\n /\n <span class=\"text-red-600\">{{ client.errorCount }} errors</span>\n </td>\n <td class=\"px-6 py-4 text-right\">\n <button\n (click)=\"handleRotateToken(client.id)\"\n class=\"text-gray-600 hover:text-gray-900 p-1\"\n title=\"Rotate Token\"\n >\n <ui-icon name=\"refresh\" class=\"h-5 w-5\" />\n </button>\n <button\n (click)=\"handleDelete(client.id)\"\n class=\"text-red-600 hover:text-red-900 p-1 ml-2\"\n title=\"Delete\"\n >\n <ui-icon name=\"trash\" class=\"h-5 w-5\" />\n </button>\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n `,\n})\nexport class ScimClientsComponent implements OnInit {\n private readonly scimService = inject(ScimService);\n\n clients = signal<ScimClient[]>([]);\n loading = signal(true);\n error = signal<string | null>(null);\n showCreateModal = signal(false);\n newToken = signal<string | null>(null);\n copiedToken = signal(false);\n\n createForm = {\n name: '',\n description: '',\n };\n\n scimEndpointUrl = '';\n\n ngOnInit(): void {\n this.scimService.getScimEndpointUrl().subscribe({\n next: (res) => this.scimEndpointUrl = res.url,\n error: (err) => console.error('Failed to load SCIM endpoint URL:', err),\n });\n this.loadClients();\n }\n\n loadClients(): void {\n this.loading.set(true);\n this.scimService.getClients().subscribe({\n next: (data) => {\n this.clients.set(data);\n this.loading.set(false);\n },\n error: (err) => {\n this.error.set('Failed to load SCIM clients');\n console.error(err);\n this.loading.set(false);\n },\n });\n }\n\n handleCreate(): void {\n this.scimService\n .createClient({\n name: this.createForm.name,\n description: this.createForm.description || undefined,\n })\n .subscribe({\n next: (response) => {\n this.newToken.set(response.token);\n this.clients.update((clients) => [...clients, response.client]);\n this.showCreateModal.set(false);\n this.createForm = { name: '', description: '' };\n },\n error: (err) => {\n console.error('Failed to create client:', err);\n },\n });\n }\n\n handleDelete(id: string): void {\n if (!confirm('Are you sure you want to delete this SCIM client?')) return;\n\n this.scimService.deleteClient(id).subscribe({\n next: () => {\n this.clients.update((clients) => clients.filter((c) => c.id !== id));\n },\n error: (err) => {\n console.error('Failed to delete client:', err);\n },\n });\n }\n\n handleRotateToken(id: string): void {\n if (!confirm('Rotate the API token? The old token will stop working immediately.')) return;\n\n this.scimService.rotateToken(id).subscribe({\n next: (response) => {\n this.newToken.set(response.token);\n },\n error: (err) => {\n console.error('Failed to rotate token:', err);\n },\n });\n }\n\n copyToken(): void {\n const token = this.newToken();\n if (token) {\n navigator.clipboard.writeText(token);\n this.copiedToken.set(true);\n setTimeout(() => this.copiedToken.set(false), 2000);\n }\n }\n\n formatDate(dateString: string): string {\n return new Date(dateString).toLocaleString();\n }\n}\n","import { Component, inject, signal, OnInit } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ActivatedRoute, Router, RouterLink } from '@angular/router';\nimport { FormsModule } from '@angular/forms';\nimport { IconComponent } from '@syndew/oluso-ui-core';\nimport { ClientService } from '@syndew/oluso-admin-ui';\nimport { ScimService } from '../../services/scim.service';\nimport { ScimClient, ScimProvisioningLog, ScimAttributeMapping } from '../../models/scim.model';\n\n@Component({\n selector: 'lib-scim-client-detail',\n standalone: true,\n imports: [CommonModule, RouterLink, FormsModule, IconComponent],\n template: `\n <div class=\"space-y-6\">\n <!-- Back button -->\n <button\n (click)=\"goBack()\"\n class=\"inline-flex items-center text-gray-600 hover:text-gray-900 transition-colors\"\n >\n <ui-icon name=\"arrow-left\" class=\"h-4 w-4 mr-2\" />\n Back to SCIM Clients\n </button>\n\n @if (loading()) {\n <div class=\"p-6 text-center text-gray-500\">Loading...</div>\n } @else if (!client()) {\n <div class=\"p-6 text-center text-gray-500\">Client not found</div>\n } @else {\n <h1 class=\"text-2xl font-semibold text-gray-900\">{{ client()!.name }}</h1>\n\n <!-- Two column layout -->\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <!-- Left column - Settings -->\n <div class=\"lg:col-span-2 space-y-6\">\n <!-- Settings Form -->\n <div class=\"bg-white shadow rounded-lg p-6\">\n <h2 class=\"text-lg font-medium mb-4\">Settings</h2>\n\n <div class=\"grid grid-cols-2 gap-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Name</label>\n <input\n type=\"text\"\n [(ngModel)]=\"formData.name\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Description</label>\n <input\n type=\"text\"\n [(ngModel)]=\"formData.description\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Allowed IP Ranges</label>\n <input\n type=\"text\"\n [(ngModel)]=\"formData.allowedIpRanges\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n placeholder=\"Leave empty to allow all\"\n />\n <p class=\"text-xs text-gray-500 mt-1\">\n Comma-separated IPs or ranges (e.g., 192.168.1.*, 10.0.0.1)\n </p>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Rate Limit (requests/min)</label>\n <input\n type=\"number\"\n [(ngModel)]=\"formData.rateLimitPerMinute\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n min=\"0\"\n />\n </div>\n\n <div class=\"col-span-2\">\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">OAuth Client (client credentials)</label>\n <select\n [(ngModel)]=\"formData.oauthClientId\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n >\n <option value=\"\">None — static token only</option>\n @for (oc of oauthClients(); track oc.clientId) {\n <option [value]=\"oc.clientId\">{{ oc.clientName }} ({{ oc.clientId }})</option>\n }\n </select>\n <p class=\"text-xs text-gray-500 mt-1\">\n Link a confidential OAuth client that allows the client_credentials grant to let\n identity providers authenticate with a platform-issued access token instead of the\n static bearer token. Only client-credentials clients are listed.\n </p>\n </div>\n </div>\n\n <!-- Permissions -->\n <h3 class=\"text-sm font-medium text-gray-700 mt-6 mb-3\">Permissions</h3>\n <div class=\"grid grid-cols-2 gap-3\">\n <label class=\"flex items-center\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"formData.isEnabled\"\n class=\"rounded border-gray-300 text-primary-600 mr-2\"\n />\n <span class=\"text-sm\">Enabled</span>\n </label>\n <label class=\"flex items-center\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"formData.canCreateUsers\"\n class=\"rounded border-gray-300 text-primary-600 mr-2\"\n />\n <span class=\"text-sm\">Can Create Users</span>\n </label>\n <label class=\"flex items-center\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"formData.canUpdateUsers\"\n class=\"rounded border-gray-300 text-primary-600 mr-2\"\n />\n <span class=\"text-sm\">Can Update Users</span>\n </label>\n <label class=\"flex items-center\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"formData.canDeleteUsers\"\n class=\"rounded border-gray-300 text-primary-600 mr-2\"\n />\n <span class=\"text-sm\">Can Delete Users</span>\n </label>\n <label class=\"flex items-center\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"formData.canManageGroups\"\n class=\"rounded border-gray-300 text-primary-600 mr-2\"\n />\n <span class=\"text-sm\">Can Manage Groups</span>\n </label>\n </div>\n\n @if (saveError()) {\n <div class=\"mt-4 bg-red-50 text-red-700 p-3 rounded-md text-sm\">{{ saveError() }}</div>\n }\n\n <div class=\"mt-6 flex justify-end\">\n <button\n (click)=\"handleSave()\"\n [disabled]=\"saving()\"\n class=\"px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 disabled:opacity-50 transition-colors\"\n >\n {{ saving() ? 'Saving...' : 'Save Changes' }}\n </button>\n </div>\n </div>\n\n <!-- Statistics -->\n <div class=\"bg-white shadow rounded-lg p-6\">\n <h2 class=\"text-lg font-medium mb-4\">Statistics</h2>\n <div class=\"grid grid-cols-4 gap-4\">\n <div class=\"text-center\">\n <div class=\"text-2xl font-bold text-gray-900\">{{ client()!.successCount }}</div>\n <div class=\"text-sm text-gray-500\">Successful Operations</div>\n </div>\n <div class=\"text-center\">\n <div class=\"text-2xl font-bold text-red-600\">{{ client()!.errorCount }}</div>\n <div class=\"text-sm text-gray-500\">Failed Operations</div>\n </div>\n <div class=\"text-center\">\n <div class=\"text-sm font-medium text-gray-900\">\n {{ client()!.tokenCreatedAt ? formatDateShort(client()!.tokenCreatedAt) : '-' }}\n </div>\n <div class=\"text-sm text-gray-500\">Token Created</div>\n </div>\n <div class=\"text-center\">\n <div class=\"text-sm font-medium text-gray-900\">\n {{ client()!.lastActivityAt ? formatDate(client()!.lastActivityAt!) : 'Never' }}\n </div>\n <div class=\"text-sm text-gray-500\">Last Activity</div>\n </div>\n </div>\n </div>\n\n <!-- Recent Logs -->\n <div class=\"bg-white shadow rounded-lg p-6\">\n <div class=\"flex justify-between items-center mb-4\">\n <h2 class=\"text-lg font-medium\">Recent Activity</h2>\n <button\n (click)=\"loadLogs()\"\n class=\"text-gray-600 hover:text-gray-900 transition-colors\"\n >\n <ui-icon name=\"refresh\" class=\"h-5 w-5\" />\n </button>\n </div>\n\n @if (logs().length === 0) {\n <p class=\"text-gray-500 text-center py-4\">No activity recorded yet</p>\n } @else {\n <div class=\"space-y-2\">\n @for (log of logs(); track log.id) {\n <div class=\"flex items-center justify-between py-2 border-b last:border-0\">\n <div class=\"flex items-center\">\n @if (log.success) {\n <ui-icon name=\"check-circle\" class=\"h-5 w-5 text-green-500 mr-3\" />\n } @else {\n <ui-icon name=\"x-circle\" class=\"h-5 w-5 text-red-500 mr-3\" />\n }\n <div>\n <span class=\"font-mono text-sm\">{{ log.method }} {{ log.path }}</span>\n @if (log.errorMessage) {\n <p class=\"text-sm text-red-600\">{{ log.errorMessage }}</p>\n }\n </div>\n </div>\n <div class=\"text-right text-sm text-gray-500\">\n <div>{{ log.statusCode }} - {{ log.durationMs }}ms</div>\n <div>{{ formatDate(log.timestamp) }}</div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Right column - Attribute Mappings -->\n <div class=\"lg:col-span-1\">\n <div class=\"bg-white shadow rounded-lg p-6 sticky top-6\">\n <div class=\"flex justify-between items-center mb-4\">\n <h2 class=\"text-lg font-medium\">Attribute Mappings</h2>\n <a\n [routerLink]=\"['/scim/clients', clientId, 'mappings']\"\n class=\"text-sm text-primary-600 hover:text-primary-700\"\n >\n Edit\n </a>\n </div>\n\n @if (loadingMappings()) {\n <p class=\"text-gray-500 text-center py-4\">Loading...</p>\n } @else if (mappings().length === 0) {\n <div class=\"text-center py-6\">\n <ui-icon name=\"clipboard\" class=\"mx-auto h-12 w-12 text-gray-300\" />\n <p class=\"mt-2 text-sm text-gray-500\">No mappings configured</p>\n <a\n [routerLink]=\"['/scim/clients', clientId, 'mappings']\"\n class=\"mt-2 inline-flex items-center text-sm text-primary-600 hover:text-primary-700\"\n >\n Configure mappings\n <ui-icon name=\"chevron-right\" class=\"ml-1 h-4 w-4\" />\n </a>\n </div>\n } @else {\n <div class=\"space-y-3 max-h-96 overflow-y-auto\">\n @for (mapping of mappings(); track mapping.id) {\n <div class=\"border border-gray-200 rounded-md p-3 text-sm\" [class.opacity-50]=\"!mapping.isEnabled\">\n <div class=\"flex items-center justify-between mb-1\">\n <span class=\"font-medium text-gray-900 truncate\" [title]=\"mapping.scimAttribute\">\n {{ mapping.scimAttribute }}\n </span>\n @if (mapping.isRequired) {\n <span class=\"text-xs bg-red-100 text-red-700 px-1.5 py-0.5 rounded\">Required</span>\n }\n </div>\n <div class=\"flex items-center text-gray-500\">\n <ui-icon name=\"arrow-right\" class=\"h-3 w-3 mr-1\" />\n <span class=\"truncate\" [title]=\"mapping.internalProperty\">{{ mapping.internalProperty }}</span>\n </div>\n @if (mapping.transformation) {\n <div class=\"mt-1 text-xs text-gray-400\">\n Transform: {{ mapping.transformation }}\n </div>\n }\n </div>\n }\n </div>\n <div class=\"mt-4 pt-3 border-t text-xs text-gray-500 text-center\">\n {{ mappings().length }} mapping{{ mappings().length !== 1 ? 's' : '' }} configured\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n `,\n})\nexport class ScimClientDetailComponent implements OnInit {\n private readonly scimService = inject(ScimService);\n private readonly clientService = inject(ClientService);\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n\n client = signal<ScimClient | null>(null);\n logs = signal<ScimProvisioningLog[]>([]);\n mappings = signal<ScimAttributeMapping[]>([]);\n oauthClients = signal<{ clientId: string; clientName: string }[]>([]);\n loading = signal(true);\n loadingMappings = signal(true);\n saving = signal(false);\n saveError = signal<string | null>(null);\n clientId = '';\n\n formData = {\n name: '',\n description: '',\n isEnabled: true,\n allowedIpRanges: '',\n rateLimitPerMinute: 60,\n canCreateUsers: true,\n canUpdateUsers: true,\n canDeleteUsers: true,\n canManageGroups: true,\n oauthClientId: '',\n };\n\n ngOnInit(): void {\n this.clientId = this.route.snapshot.paramMap.get('id') || '';\n if (this.clientId) {\n this.loadClient();\n this.loadLogs();\n this.loadMappings();\n this.loadOAuthClients();\n }\n }\n\n loadOAuthClients(): void {\n this.clientService.getClients().subscribe({\n next: (clients) => {\n this.oauthClients.set(\n clients\n .filter((c) => c.allowedGrantTypes?.includes('client_credentials'))\n .map((c) => ({ clientId: c.clientId, clientName: c.clientName || c.clientId }))\n );\n },\n error: (err) => console.error('Failed to load OAuth clients:', err),\n });\n }\n\n loadClient(): void {\n this.scimService.getClient(this.clientId).subscribe({\n next: (data) => {\n this.client.set(data);\n this.formData = {\n name: data.name,\n description: data.description || '',\n isEnabled: data.isEnabled,\n allowedIpRanges: data.allowedIpRanges || '',\n rateLimitPerMinute: data.rateLimitPerMinute,\n canCreateUsers: data.canCreateUsers,\n canUpdateUsers: data.canUpdateUsers,\n canDeleteUsers: data.canDeleteUsers,\n canManageGroups: data.canManageGroups,\n oauthClientId: data.oauthClientId || '',\n };\n this.loading.set(false);\n },\n error: (err) => {\n console.error('Failed to load client:', err);\n this.loading.set(false);\n },\n });\n }\n\n loadLogs(): void {\n this.scimService.getLogs(this.clientId, 1, 20).subscribe({\n next: (response) => {\n this.logs.set(response.items);\n },\n error: (err) => {\n console.error('Failed to load logs:', err);\n },\n });\n }\n\n loadMappings(): void {\n this.loadingMappings.set(true);\n this.scimService.getMappings(this.clientId).subscribe({\n next: (data) => {\n this.mappings.set(data);\n this.loadingMappings.set(false);\n },\n error: (err) => {\n console.error('Failed to load mappings:', err);\n this.loadingMappings.set(false);\n },\n });\n }\n\n handleSave(): void {\n this.saving.set(true);\n this.saveError.set(null);\n const payload = {\n ...this.client()!,\n ...this.formData,\n oauthClientId: this.formData.oauthClientId || undefined,\n } as ScimClient;\n this.scimService.updateClient(this.clientId, payload).subscribe({\n next: (updated) => {\n this.client.set(updated);\n this.saving.set(false);\n },\n error: (err) => {\n this.saveError.set(\n typeof err?.error === 'string' ? err.error : 'Failed to save changes'\n );\n this.saving.set(false);\n },\n });\n }\n\n goBack(): void {\n this.router.navigate(['/scim/clients']);\n }\n\n formatDate(dateString: string): string {\n return new Date(dateString).toLocaleString();\n }\n\n formatDateShort(dateString: string): string {\n return new Date(dateString).toLocaleDateString();\n }\n}\n","import { Component, computed, inject, signal, OnInit } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ActivatedRoute, RouterLink } from '@angular/router';\nimport { FormsModule } from '@angular/forms';\nimport { forkJoin } from 'rxjs';\nimport { IconComponent } from '@syndew/oluso-ui-core';\nimport {\n ScimService,\n internalPropertyOptions,\n transformationOptions,\n} from '../../services/scim.service';\nimport {\n ScimClient,\n ScimAttributeMapping,\n SaveScimAttributeMappingRequest,\n ScimAttributeSuggestion,\n ScimMappingOptions,\n ScimMappingPreview,\n} from '../../models/scim.model';\n\ninterface MappingFormData {\n scimAttribute: string;\n internalProperty: string;\n source: 'attribute' | 'expression';\n expression: string;\n condition: string;\n isRequired: boolean;\n defaultValue: string;\n transformation: string;\n priority: number;\n isEnabled: boolean;\n}\n\nconst initialFormData: MappingFormData = {\n scimAttribute: '',\n internalProperty: '',\n source: 'attribute',\n expression: '',\n condition: '',\n isRequired: false,\n defaultValue: '',\n transformation: 'none',\n priority: 0,\n isEnabled: true,\n};\n\nconst SAMPLE_RESOURCE = {\n schemas: [\n 'urn:ietf:params:scim:schemas:core:2.0:User',\n 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User',\n ],\n externalId: '3f2c1a0e-0000-4000-8000-000000000001',\n userName: 'jane.doe@example.org',\n name: { givenName: 'Jane', familyName: 'Doe' },\n displayName: 'Jane Doe',\n title: 'Finance Manager',\n userType: 'Employee',\n active: true,\n emails: [{ value: 'jane.doe@example.org', type: 'work', primary: true }],\n phoneNumbers: [{ value: '+44 20 1234 5678', type: 'work' }],\n locale: 'en-GB',\n timezone: 'Europe/London',\n 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User': {\n department: 'Finance',\n employeeNumber: 'E-1042',\n manager: { value: '3f2c1a0e-0000-4000-8000-000000000099' },\n },\n};\n\n@Component({\n selector: 'lib-scim-mappings',\n standalone: true,\n imports: [CommonModule, RouterLink, FormsModule, IconComponent],\n template: `\n <div class=\"space-y-6\">\n <!-- Header -->\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center space-x-4\">\n <a\n [routerLink]=\"['/scim/clients', clientId]\"\n class=\"text-gray-500 hover:text-gray-700 transition-colors\"\n >\n <ui-icon name=\"arrow-left\" class=\"h-5 w-5\" />\n </a>\n <div>\n <h1 class=\"text-2xl font-semibold text-gray-900\">Attribute Mappings</h1>\n @if (client()) {\n <p class=\"text-sm text-gray-500\">\n How attributes sent by\n <span class=\"font-medium text-gray-700\">{{ client()!.name }}</span>\n are written onto users. userName, email and active always apply; extension\n attributes such as department can be stored as custom properties.\n </p>\n }\n </div>\n </div>\n <div class=\"flex items-center space-x-3\">\n <button\n (click)=\"showDefaultsModal.set(true)\"\n class=\"inline-flex items-center px-3 py-2 border border-gray-300 rounded-lg text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 transition-colors\"\n >\n <ui-icon name=\"sparkles\" class=\"h-4 w-4 mr-2\" />\n Apply Preset\n </button>\n <button\n (click)=\"openCreateForm()\"\n class=\"inline-flex items-center px-4 py-2 bg-primary-600 hover:bg-primary-700 text-white text-sm font-medium rounded-lg transition-colors\"\n >\n <ui-icon name=\"plus\" class=\"h-4 w-4 mr-2\" />\n Add Mapping\n </button>\n </div>\n </div>\n\n @if (error()) {\n <div class=\"bg-red-50 border border-red-200 rounded-lg p-4 text-red-700\">\n {{ error() }}\n </div>\n }\n\n <!-- Mappings Table -->\n <div class=\"bg-white rounded-lg border border-gray-200 overflow-x-auto shadow-sm\">\n @if (loading()) {\n <div class=\"flex items-center justify-center h-64\">\n <svg\n class=\"h-8 w-8 animate-spin text-gray-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n </div>\n } @else if (mappings().length === 0) {\n <div class=\"p-6\">\n <div class=\"text-center mb-6\">\n <ui-icon name=\"arrows-right-left\" class=\"h-12 w-12 text-gray-400 mx-auto mb-4\" />\n <h3 class=\"text-lg font-medium text-gray-900 mb-2\">Using the standard mappings</h3>\n <p class=\"text-gray-500\">\n No mappings are configured, so the rows below apply. Add a mapping or apply a preset\n to take over.\n </p>\n </div>\n @if (options(); as o) {\n <table class=\"min-w-full divide-y divide-gray-200 text-sm\">\n <tbody class=\"divide-y divide-gray-100\">\n @for (d of o.defaults; track d.scimAttribute + d.internalProperty) {\n <tr class=\"text-gray-600\">\n <td class=\"px-4 py-2 font-mono text-xs\">{{ d.scimAttribute }}</td>\n <td class=\"px-4 py-2 font-mono text-xs\">→ {{ d.internalProperty }}</td>\n <td class=\"px-4 py-2 font-mono text-xs text-purple-700\">\n {{ d.expression || '' }}\n </td>\n <td class=\"px-4 py-2 text-xs\">{{ d.isRequired ? 'required' : '' }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n } @else {\n <table class=\"min-w-full divide-y divide-gray-200\">\n <thead class=\"bg-gray-50\">\n <tr>\n <th\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\"\n >\n Status\n </th>\n <th\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\"\n >\n SCIM Attribute\n </th>\n <th\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\"\n >\n Internal Property\n </th>\n <th\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\"\n >\n Expression / Condition\n </th>\n <th\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\"\n >\n Transform\n </th>\n <th\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\"\n >\n Required\n </th>\n <th\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\"\n >\n Priority\n </th>\n <th\n class=\"px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider\"\n >\n Actions\n </th>\n </tr>\n </thead>\n <tbody class=\"bg-white divide-y divide-gray-200\">\n @for (mapping of mappings(); track mapping.id) {\n <tr [class.opacity-50]=\"!mapping.isEnabled\" [class.bg-gray-50]=\"!mapping.isEnabled\">\n <td class=\"px-4 py-4 whitespace-nowrap\">\n <button\n (click)=\"handleToggleEnabled(mapping)\"\n class=\"focus:outline-none\"\n [title]=\"mapping.isEnabled ? 'Disable mapping' : 'Enable mapping'\"\n >\n @if (mapping.isEnabled) {\n <ui-icon name=\"check-circle\" class=\"h-5 w-5 text-green-500\" />\n } @else {\n <ui-icon name=\"x-circle\" class=\"h-5 w-5 text-gray-400\" />\n }\n </button>\n </td>\n <td class=\"px-4 py-4\">\n <code class=\"text-sm text-blue-700 bg-blue-50 px-2 py-1 rounded break-all\">\n {{ mapping.scimAttribute }}\n </code>\n </td>\n <td class=\"px-4 py-4\">\n <code class=\"text-sm text-green-700 bg-green-50 px-2 py-1 rounded\">\n {{ mapping.internalProperty }}\n </code>\n </td>\n <td class=\"px-4 py-4 text-xs font-mono\">\n @if (mapping.expression) {\n <div class=\"text-purple-700 break-all\">{{ mapping.expression }}</div>\n }\n @if (mapping.condition) {\n <div class=\"text-gray-500 break-all\">if {{ mapping.condition }}</div>\n }\n @if (!mapping.expression && !mapping.condition) {\n <span class=\"text-gray-400\">-</span>\n }\n </td>\n <td class=\"px-4 py-4 whitespace-nowrap text-sm text-gray-500\">\n {{ mapping.transformation || '-' }}\n @if (mapping.defaultValue) {\n <div class=\"text-xs text-gray-400\">default: {{ mapping.defaultValue }}</div>\n }\n </td>\n <td class=\"px-4 py-4 whitespace-nowrap\">\n @if (mapping.isRequired) {\n <span\n class=\"inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-orange-100 text-orange-700\"\n >\n Required\n </span>\n } @else {\n <span class=\"text-gray-400 text-sm\">Optional</span>\n }\n </td>\n <td class=\"px-4 py-4 whitespace-nowrap text-sm text-gray-500\">\n {{ mapping.priority }}\n </td>\n <td class=\"px-4 py-4 whitespace-nowrap text-right text-sm font-medium\">\n <button\n (click)=\"handleEdit(mapping)\"\n class=\"text-blue-600 hover:text-blue-800 mr-3\"\n >\n <ui-icon name=\"pencil\" class=\"h-4 w-4\" />\n </button>\n <button\n (click)=\"handleDelete(mapping.id)\"\n class=\"text-red-600 hover:text-red-800\"\n >\n <ui-icon name=\"trash\" class=\"h-4 w-4\" />\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n\n <!-- Preview -->\n <div class=\"bg-white rounded-lg border border-gray-200 shadow-sm p-6\">\n <div class=\"flex items-center justify-between mb-2\">\n <h2 class=\"text-lg font-medium text-gray-900\">Try it with a sample request</h2>\n <div class=\"flex items-center gap-2\">\n <select\n [(ngModel)]=\"previewMode\"\n class=\"border border-gray-300 rounded-md px-2 py-1 text-sm\"\n >\n <option value=\"create\">Create (POST)</option>\n <option value=\"replace\">Replace (PUT)</option>\n <option value=\"patch\">Patch result</option>\n </select>\n <button\n (click)=\"runPreview()\"\n [disabled]=\"previewing()\"\n class=\"inline-flex items-center px-3 py-1.5 bg-gray-100 hover:bg-gray-200 rounded-md text-sm disabled:opacity-50\"\n >\n <ui-icon name=\"play-circle\" class=\"h-4 w-4 mr-1\" />\n {{ previewing() ? 'Running...' : 'Preview' }}\n </button>\n </div>\n </div>\n <p class=\"text-xs text-gray-500 mb-3\">\n Paste a SCIM User as the identity provider sends it. Nothing is stored. Expressions can\n read\n <code>scim.*</code>, <code>enterprise.*</code>, <code>attr \"path\"</code> and\n <code>client.name</code>.\n </p>\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\n <textarea\n [(ngModel)]=\"previewJson\"\n rows=\"14\"\n spellcheck=\"false\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 font-mono text-xs\"\n ></textarea>\n <div>\n @if (previewError()) {\n <div class=\"bg-red-50 text-red-700 p-3 rounded-md text-xs\">{{ previewError() }}</div>\n } @else if (preview(); as pv) {\n @if (!pv.success) {\n <div class=\"bg-red-50 text-red-700 p-3 rounded-md text-xs\">{{ pv.error }}</div>\n } @else {\n @if (pv.usingDefaults) {\n <p class=\"text-xs text-gray-500 mb-2\">\n Using the standard mappings (none configured).\n </p>\n }\n <table class=\"min-w-full text-sm\">\n <tbody class=\"divide-y divide-gray-100\">\n @for (f of previewFields(); track f.key) {\n <tr>\n <td class=\"py-1.5 pr-4 font-mono text-xs text-green-700\">{{ f.key }}</td>\n <td\n class=\"py-1.5 font-mono text-xs\"\n [class.text-gray-400]=\"f.value === null\"\n >\n {{ f.value === null ? '(cleared)' : f.value }}\n </td>\n </tr>\n }\n </tbody>\n </table>\n }\n } @else {\n <p class=\"text-sm text-gray-400\">Run a preview to see what would be written.</p>\n }\n </div>\n </div>\n </div>\n\n <!-- Mapping Form Modal -->\n @if (showForm()) {\n <div class=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div\n class=\"bg-white rounded-lg shadow-xl p-6 max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto\"\n >\n <h2 class=\"text-xl font-semibold text-gray-900 mb-6\">\n {{ editingMapping() ? 'Edit Mapping' : 'Add Mapping' }}\n </h2>\n\n <form (ngSubmit)=\"handleSubmit()\" class=\"space-y-6\">\n <div class=\"grid grid-cols-2 gap-6\">\n <!-- SCIM Attribute -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-2\">SCIM Attribute</label>\n <input\n type=\"text\"\n list=\"scim-suggestions\"\n [(ngModel)]=\"formData.scimAttribute\"\n name=\"scimAttribute\"\n class=\"w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-gray-900 font-mono text-sm focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n placeholder='e.g., userName, emails[type eq \"work\"].value'\n required\n />\n <datalist id=\"scim-suggestions\">\n @for (s of scimSuggestions; track s.attribute) {\n <option [value]=\"s.attribute\">{{ s.description }}</option>\n }\n </datalist>\n <p class=\"mt-1 text-xs text-gray-500\">\n The attribute path in the incoming request. Also names the mapping when an\n expression is used.\n </p>\n </div>\n\n <!-- Internal Property -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-2\"\n >Internal Property</label\n >\n <input\n type=\"text\"\n list=\"internal-property-suggestions\"\n [(ngModel)]=\"formData.internalProperty\"\n name=\"internalProperty\"\n class=\"w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-gray-900 font-mono text-sm focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n placeholder=\"Email, FirstName, custom:department\"\n required\n />\n <datalist id=\"internal-property-suggestions\">\n @for (p of internalProperties(); track p.name) {\n <option [value]=\"p.name\">{{ p.displayName }}</option>\n }\n </datalist>\n <p class=\"mt-1 text-xs text-gray-500\">\n The user property to write. <code>custom:&lt;key&gt;</code> stores into custom\n properties.\n </p>\n </div>\n\n <!-- Value source -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-2\"\n >Value comes from</label\n >\n <select\n [(ngModel)]=\"formData.source\"\n name=\"source\"\n class=\"w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-gray-900 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n >\n <option value=\"attribute\">The SCIM attribute</option>\n <option value=\"expression\">An expression</option>\n </select>\n </div>\n\n <!-- Transformation -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-2\">Transformation</label>\n <select\n [(ngModel)]=\"formData.transformation\"\n name=\"transformation\"\n class=\"w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-gray-900 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n >\n @for (t of transformations(); track t.name) {\n <option [value]=\"t.name\">{{ t.description }}</option>\n }\n </select>\n </div>\n\n @if (formData.source === 'expression') {\n <div class=\"col-span-2\">\n <label class=\"block text-sm font-medium text-gray-700 mb-2\"\n >Expression (Scriban)</label\n >\n <input\n type=\"text\"\n [(ngModel)]=\"formData.expression\"\n name=\"expression\"\n class=\"w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-gray-900 font-mono text-sm focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n placeholder=\"{{ '{{' }} scim.name.givenName {{ '}}' }} {{\n '{{'\n }} scim.name.familyName {{ '}}' }}\"\n />\n <p class=\"mt-1 text-xs text-gray-500\">\n Model: <code>scim</code> (the resource), <code>enterprise</code> (the\n enterprise extension), <code>attr \"path\"</code>, <code>client.name</code>.\n </p>\n </div>\n }\n\n <!-- Condition -->\n <div class=\"col-span-2\">\n <label class=\"block text-sm font-medium text-gray-700 mb-2\"\n >Condition (optional)</label\n >\n <input\n type=\"text\"\n [(ngModel)]=\"formData.condition\"\n name=\"condition\"\n class=\"w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-gray-900 font-mono text-sm focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n placeholder='scim.userType == \"Employee\"'\n />\n <p class=\"mt-1 text-xs text-gray-500\">\n Scriban boolean expression. The mapping is skipped when it is false.\n </p>\n </div>\n\n <!-- Default Value -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-2\">Default Value</label>\n <input\n type=\"text\"\n [(ngModel)]=\"formData.defaultValue\"\n name=\"defaultValue\"\n class=\"w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-gray-900 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n placeholder=\"Used when nothing resolves\"\n />\n </div>\n\n <!-- Priority -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-2\">Priority</label>\n <input\n type=\"number\"\n [(ngModel)]=\"formData.priority\"\n name=\"priority\"\n class=\"w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-gray-900 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n min=\"-100\"\n max=\"100\"\n />\n <p class=\"mt-1 text-xs text-gray-500\">\n When several mappings write the same property, the highest priority with a value\n wins.\n </p>\n </div>\n </div>\n\n <!-- Checkboxes -->\n <div class=\"flex items-center space-x-6\">\n <label class=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"formData.isRequired\"\n name=\"isRequired\"\n class=\"h-4 w-4 border-gray-300 rounded text-primary-600 focus:ring-primary-500\"\n />\n <span class=\"text-sm text-gray-700\">Required for user creation</span>\n </label>\n <label class=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"formData.isEnabled\"\n name=\"isEnabled\"\n class=\"h-4 w-4 border-gray-300 rounded text-primary-600 focus:ring-primary-500\"\n />\n <span class=\"text-sm text-gray-700\">Enabled</span>\n </label>\n </div>\n\n @if (formError()) {\n <div class=\"bg-red-50 text-red-700 p-3 rounded-md text-sm\">{{ formError() }}</div>\n }\n\n <!-- Form Actions -->\n <div class=\"flex justify-end space-x-3 pt-4 border-t border-gray-200\">\n <button\n type=\"button\"\n (click)=\"closeForm()\"\n class=\"px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n [disabled]=\"saving()\"\n class=\"px-4 py-2 text-sm font-medium text-white bg-primary-600 hover:bg-primary-700 rounded-lg disabled:opacity-50 transition-colors\"\n >\n {{\n saving() ? 'Saving...' : editingMapping() ? 'Update Mapping' : 'Create Mapping'\n }}\n </button>\n </div>\n </form>\n </div>\n </div>\n }\n\n <!-- Apply Preset Modal -->\n @if (showDefaultsModal()) {\n <div class=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div class=\"bg-white rounded-lg shadow-xl p-6 max-w-md w-full mx-4\">\n <h2 class=\"text-xl font-semibold text-gray-900 mb-4\">Apply Preset Mappings</h2>\n <p class=\"text-gray-600 mb-6\">\n Adds the preset's rows without removing existing ones. Attributes that already have a\n mapping are skipped.\n </p>\n\n <div class=\"mb-6\">\n <label class=\"block text-sm font-medium text-gray-700 mb-2\">Identity provider</label>\n <select\n [(ngModel)]=\"selectedProvider\"\n class=\"w-full px-3 py-2 bg-white border border-gray-300 rounded-lg text-gray-900 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n >\n <option value=\"standard\">Standard SCIM 2.0</option>\n <option value=\"azure\">Microsoft Entra ID</option>\n <option value=\"okta\">Okta</option>\n <option value=\"google\">Google Workspace</option>\n </select>\n </div>\n\n <div class=\"flex justify-end space-x-3\">\n <button\n (click)=\"showDefaultsModal.set(false)\"\n class=\"px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors\"\n >\n Cancel\n </button>\n <button\n (click)=\"handleApplyDefaults()\"\n [disabled]=\"saving()\"\n class=\"px-4 py-2 text-sm font-medium text-white bg-primary-600 hover:bg-primary-700 rounded-lg disabled:opacity-50 transition-colors\"\n >\n {{ saving() ? 'Applying...' : 'Apply' }}\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n `,\n})\nexport class ScimMappingsComponent implements OnInit {\n private readonly scimService = inject(ScimService);\n private readonly route = inject(ActivatedRoute);\n\n client = signal<ScimClient | null>(null);\n mappings = signal<ScimAttributeMapping[]>([]);\n options = signal<ScimMappingOptions | null>(null);\n loading = signal(true);\n error = signal<string | null>(null);\n formError = signal<string | null>(null);\n showForm = signal(false);\n editingMapping = signal<ScimAttributeMapping | null>(null);\n saving = signal(false);\n showDefaultsModal = signal(false);\n selectedProvider = 'standard';\n clientId = '';\n\n previewJson = JSON.stringify(SAMPLE_RESOURCE, null, 2);\n previewMode: 'create' | 'replace' | 'patch' = 'create';\n previewing = signal(false);\n preview = signal<ScimMappingPreview | null>(null);\n previewError = signal<string | null>(null);\n previewFields = signal<{ key: string; value: string | null }[]>([]);\n\n formData: MappingFormData = { ...initialFormData };\n\n scimSuggestions: ScimAttributeSuggestion[] = [];\n /** The server's mapping-options decide which properties and transformations are offered. */\n internalProperties = computed(() =>\n internalPropertyOptions(this.options()?.internalProperties ?? []),\n );\n transformations = computed(() => transformationOptions(this.options()?.transformations ?? []));\n\n ngOnInit(): void {\n this.clientId = this.route.snapshot.paramMap.get('clientId') || '';\n this.scimSuggestions = this.scimService.getScimAttributeSuggestions();\n\n this.scimService.getMappingOptions().subscribe({\n next: (o) => this.options.set(o),\n error: (err) => console.error('Failed to load mapping options:', err),\n });\n\n if (this.clientId) {\n this.loadData();\n }\n }\n\n loadData(): void {\n this.loading.set(true);\n this.error.set(null);\n\n forkJoin({\n client: this.scimService.getClient(this.clientId),\n mappings: this.scimService.getMappings(this.clientId),\n }).subscribe({\n next: ({ client, mappings }) => {\n this.client.set(client);\n this.mappings.set(mappings);\n this.loading.set(false);\n },\n error: (err) => {\n this.error.set(this.messageOf(err, 'Failed to load data'));\n this.loading.set(false);\n },\n });\n }\n\n openCreateForm(): void {\n this.editingMapping.set(null);\n this.formData = { ...initialFormData };\n this.formError.set(null);\n this.showForm.set(true);\n }\n\n closeForm(): void {\n this.showForm.set(false);\n this.editingMapping.set(null);\n this.formData = { ...initialFormData };\n }\n\n handleEdit(mapping: ScimAttributeMapping): void {\n this.editingMapping.set(mapping);\n this.formError.set(null);\n this.formData = {\n scimAttribute: mapping.scimAttribute,\n internalProperty: mapping.internalProperty,\n source: mapping.expression ? 'expression' : 'attribute',\n expression: mapping.expression || '',\n condition: mapping.condition || '',\n isRequired: mapping.isRequired,\n defaultValue: mapping.defaultValue || '',\n transformation: mapping.transformation || 'none',\n priority: mapping.priority,\n isEnabled: mapping.isEnabled,\n };\n this.showForm.set(true);\n }\n\n handleSubmit(): void {\n this.saving.set(true);\n this.formError.set(null);\n\n const request = this.toRequest(this.formData);\n const editing = this.editingMapping();\n const operation = editing\n ? this.scimService.updateMapping(this.clientId, editing.id, request)\n : this.scimService.createMapping(this.clientId, request);\n\n operation.subscribe({\n next: () => {\n this.saving.set(false);\n this.closeForm();\n this.loadData();\n },\n error: (err) => {\n this.formError.set(this.messageOf(err, 'Failed to save mapping'));\n this.saving.set(false);\n },\n });\n }\n\n handleDelete(mappingId: string): void {\n if (!confirm('Are you sure you want to delete this mapping?')) return;\n\n this.error.set(null);\n this.scimService.deleteMapping(this.clientId, mappingId).subscribe({\n next: () => this.loadData(),\n error: (err) => {\n this.error.set(this.messageOf(err, 'Failed to delete mapping'));\n },\n });\n }\n\n handleToggleEnabled(mapping: ScimAttributeMapping): void {\n const request: SaveScimAttributeMappingRequest = {\n scimAttribute: mapping.scimAttribute,\n internalProperty: mapping.internalProperty,\n expression: mapping.expression,\n condition: mapping.condition,\n isRequired: mapping.isRequired,\n defaultValue: mapping.defaultValue,\n transformation: mapping.transformation,\n priority: mapping.priority,\n isEnabled: !mapping.isEnabled,\n };\n this.scimService.updateMapping(this.clientId, mapping.id, request).subscribe({\n next: () => this.loadData(),\n error: (err) => {\n this.error.set(this.messageOf(err, 'Failed to update mapping'));\n },\n });\n }\n\n handleApplyDefaults(): void {\n this.saving.set(true);\n this.error.set(null);\n\n this.scimService.applyDefaultMappings(this.clientId, this.selectedProvider).subscribe({\n next: () => {\n this.showDefaultsModal.set(false);\n this.loadData();\n this.saving.set(false);\n },\n error: (err) => {\n this.error.set(this.messageOf(err, 'Failed to apply preset mappings'));\n this.saving.set(false);\n },\n });\n }\n\n runPreview(): void {\n this.previewError.set(null);\n this.preview.set(null);\n let resource: Record<string, unknown>;\n try {\n resource = JSON.parse(this.previewJson);\n } catch (e) {\n this.previewError.set(`Sample is not valid JSON: ${(e as Error).message}`);\n return;\n }\n\n this.previewing.set(true);\n this.scimService.previewMappings(this.clientId, resource, this.previewMode).subscribe({\n next: (pv) => {\n this.preview.set(pv);\n this.previewFields.set(\n Object.entries(pv.fields ?? {})\n .map(([key, value]) => ({ key, value }))\n .sort((a, b) => a.key.localeCompare(b.key)),\n );\n this.previewing.set(false);\n },\n error: (err) => {\n this.previewError.set(this.messageOf(err, 'Preview failed'));\n this.previewing.set(false);\n },\n });\n }\n\n private toRequest(f: MappingFormData): SaveScimAttributeMappingRequest {\n return {\n scimAttribute: f.scimAttribute.trim(),\n internalProperty: f.internalProperty.trim(),\n expression: f.source === 'expression' ? f.expression || undefined : undefined,\n condition: f.condition || undefined,\n isRequired: f.isRequired,\n defaultValue: f.defaultValue || undefined,\n transformation: f.transformation === 'none' ? undefined : f.transformation,\n priority: Number(f.priority) || 0,\n isEnabled: f.isEnabled,\n };\n }\n\n private messageOf(err: unknown, fallback: string): string {\n const e = err as { error?: unknown; message?: string };\n if (typeof e?.error === 'string') return e.error;\n if (e instanceof Error && e.message) return e.message;\n return fallback;\n }\n}\n","import { Component, inject, signal, computed, OnInit } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Router, RouterLink } from '@angular/router';\nimport { FormsModule } from '@angular/forms';\nimport { Subscription } from 'rxjs';\nimport { IconComponent, ModalComponent } from '@syndew/oluso-ui-core';\nimport { ScimService } from '../../services/scim.service';\nimport {\n ScimProvider,\n ScimProviderLog,\n ScimProviderFlavor,\n ScimProviderOptions,\n ScimProviderAuthType,\n} from '../../models/scim-provider.model';\n\n@Component({\n selector: 'lib-scim-providers',\n standalone: true,\n imports: [CommonModule, RouterLink, FormsModule, IconComponent, ModalComponent],\n template: `\n <div class=\"space-y-6\">\n <!-- Header -->\n <div class=\"flex justify-between items-start\">\n <div>\n <h1 class=\"text-2xl font-semibold text-gray-900\">SCIM Providers</h1>\n <p class=\"text-gray-500 mt-1\">\n Downstream systems this tenant pushes its users and groups to over SCIM 2.0.\n For identity providers that push into this tenant, see\n <a routerLink=\"/scim/clients\" class=\"text-primary-600 hover:underline\">SCIM Clients</a>.\n </p>\n </div>\n <button\n (click)=\"openCreate()\"\n class=\"inline-flex items-center px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 transition-colors\"\n >\n <ui-icon name=\"plus\" class=\"h-5 w-5 mr-2\" />\n Add Provider\n </button>\n </div>\n\n @if (error()) {\n <div class=\"bg-red-50 text-red-700 p-4 rounded-md\">{{ error() }}</div>\n }\n\n <!-- Create Modal -->\n <ui-modal\n [open]=\"showCreateModal()\"\n title=\"Add SCIM Provider\"\n size=\"lg\"\n [scrollable]=\"true\"\n (closed)=\"showCreateModal.set(false)\"\n >\n <form (ngSubmit)=\"handleCreate()\">\n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Name</label>\n <input\n type=\"text\"\n [(ngModel)]=\"createForm.name\"\n name=\"name\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n placeholder=\"e.g., Mail server, Wiki\"\n required\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Type</label>\n <select\n [(ngModel)]=\"createForm.flavor\"\n name=\"flavor\"\n (ngModelChange)=\"onFlavorChange($event)\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n >\n @for (f of flavors(); track f.key) {\n <option [value]=\"f.key\">{{ f.displayName }}</option>\n }\n </select>\n @if (selectedFlavor(); as f) {\n <p class=\"text-xs text-gray-500 mt-1\">{{ f.description }}</p>\n @if (f.notes) {\n <div class=\"mt-2 bg-blue-50 border border-blue-200 text-blue-800 text-xs rounded-md p-3\">{{ f.notes }}</div>\n }\n }\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">SCIM base URL</label>\n <input\n type=\"url\"\n [(ngModel)]=\"createForm.baseUrl\"\n name=\"baseUrl\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent font-mono text-sm\"\n placeholder=\"https://mail.example.org/scim/v2\"\n required\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Authentication</label>\n <select\n [(ngModel)]=\"createForm.authType\"\n name=\"authType\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n >\n <option value=\"bearer\">Bearer token / API key</option>\n <option value=\"oauth_client_credentials\">OAuth 2.0 client credentials</option>\n </select>\n </div>\n\n @if (createForm.authType === 'oauth_client_credentials') {\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Token endpoint</label>\n <input\n type=\"url\"\n [(ngModel)]=\"createForm.oauthTokenEndpoint\"\n name=\"oauthTokenEndpoint\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent font-mono text-sm\"\n placeholder=\"https://idp.example.org/connect/token\"\n />\n </div>\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Client ID</label>\n <input\n type=\"text\"\n [(ngModel)]=\"createForm.oauthClientId\"\n name=\"oauthClientId\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n />\n </div>\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Scope (optional)</label>\n <input\n type=\"text\"\n [(ngModel)]=\"createForm.oauthScope\"\n name=\"oauthScope\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n />\n </div>\n }\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">\n {{ createForm.authType === 'bearer' ? 'Bearer token / API key' : 'Client secret' }}\n </label>\n <div class=\"relative\">\n <input\n [type]=\"showSecret() ? 'text' : 'password'\"\n [(ngModel)]=\"createForm.secret\"\n name=\"secret\"\n autocomplete=\"new-password\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 pr-10 focus:ring-2 focus:ring-primary-500 focus:border-transparent font-mono text-sm\"\n placeholder=\"Can be set later from the provider page\"\n />\n <button\n type=\"button\"\n (click)=\"showSecret.set(!showSecret())\"\n class=\"absolute inset-y-0 right-0 px-3 text-gray-500 hover:text-gray-700\"\n [title]=\"showSecret() ? 'Hide' : 'Show'\"\n >\n <ui-icon [name]=\"showSecret() ? 'eye-slash' : 'eye'\" class=\"h-4 w-4\" />\n </button>\n </div>\n <p class=\"text-xs text-gray-500 mt-1\">Stored encrypted. It is never shown again after saving.</p>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Description (optional)</label>\n <input\n type=\"text\"\n [(ngModel)]=\"createForm.description\"\n name=\"description\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\"\n />\n </div>\n </div>\n\n @if (createError()) {\n <div class=\"mt-4 bg-red-50 text-red-700 p-3 rounded-md text-sm\">{{ createError() }}</div>\n }\n\n <div class=\"flex justify-end gap-2 mt-6\">\n <button\n type=\"button\"\n (click)=\"showCreateModal.set(false)\"\n class=\"px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n [disabled]=\"creating()\"\n class=\"px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 disabled:opacity-50 transition-colors\"\n >\n {{ creating() ? 'Creating...' : 'Create' }}\n </button>\n </div>\n </form>\n </ui-modal>\n\n <!-- Activity Modal -->\n <ui-modal\n [open]=\"activityProvider() !== null\"\n [title]=\"'Activity: ' + (activityProvider()?.name ?? '')\"\n size=\"xl\"\n [scrollable]=\"true\"\n (closed)=\"closeActivity()\"\n >\n <div class=\"space-y-4\">\n <div class=\"flex flex-wrap items-center justify-between gap-3\">\n <div class=\"inline-flex rounded-md border border-gray-300 p-0.5 text-sm\" role=\"group\" aria-label=\"Show\">\n <button type=\"button\" (click)=\"setActivityErrorsOnly(false)\" class=\"rounded px-3 py-1\"\n [class.bg-gray-100]=\"!activityErrorsOnly()\" [class.font-medium]=\"!activityErrorsOnly()\"\n [attr.aria-pressed]=\"!activityErrorsOnly()\">All calls</button>\n <button type=\"button\" (click)=\"setActivityErrorsOnly(true)\" class=\"rounded px-3 py-1\"\n [class.bg-gray-100]=\"activityErrorsOnly()\" [class.font-medium]=\"activityErrorsOnly()\"\n [attr.aria-pressed]=\"activityErrorsOnly()\">Errors only</button>\n </div>\n <div class=\"flex items-center gap-3\">\n <button type=\"button\" (click)=\"loadActivity()\" class=\"text-gray-600 hover:text-gray-900 p-1\" title=\"Refresh\">\n <ui-icon name=\"refresh\" class=\"h-5 w-5\" />\n </button>\n @if (activityProvider(); as ap) {\n <a [routerLink]=\"['/scim/providers', ap.id]\" class=\"text-sm text-primary-600 hover:underline\">Open provider setup</a>\n }\n </div>\n </div>\n\n @if (activityError()) {\n <div class=\"bg-red-50 text-red-700 p-3 rounded-md text-sm\">{{ activityError() }}</div>\n } @else if (activityLoading() && activityLogs().length === 0) {\n <p class=\"py-6 text-center text-sm text-gray-500\">Loading...</p>\n } @else if (activityLogs().length === 0) {\n <p class=\"py-6 text-center text-sm text-gray-500\">\n {{ activityErrorsOnly() ? 'No failed calls.' : 'No calls made yet.' }}\n </p>\n } @else {\n <div class=\"divide-y divide-gray-100\" [class.opacity-60]=\"activityLoading()\">\n @for (l of activityLogs(); track l.id) {\n <div class=\"flex items-start gap-3 py-3 text-sm\">\n <ui-icon [name]=\"l.success ? 'check-circle' : 'x-circle'\" class=\"h-5 w-5 mt-0.5 shrink-0\" [class.text-green-600]=\"l.success\" [class.text-red-600]=\"!l.success\" />\n <div class=\"flex-1 min-w-0\">\n <div class=\"font-mono text-xs break-all\">\n <span class=\"font-semibold\">{{ l.method }}</span> {{ l.path }}\n <span class=\"text-gray-400\">→ {{ l.statusCode }} · {{ l.durationMs }}ms</span>\n </div>\n <div class=\"text-xs text-gray-500\">{{ l.operation }} {{ l.resourceType || '' }} {{ l.internalId || '' }}</div>\n @if (l.errorMessage) {\n <div class=\"mt-1 whitespace-pre-wrap break-words text-xs text-red-700\">{{ l.errorMessage }}</div>\n }\n </div>\n <div class=\"text-xs text-gray-400 whitespace-nowrap\">{{ formatDate(l.timestamp) }}</div>\n </div>\n }\n </div>\n }\n\n @if (activityTotal() > 0) {\n <div class=\"flex items-center justify-between border-t border-gray-200 pt-3 text-sm text-gray-600\">\n <span>Page {{ activityPage() }} of {{ activityTotalPages() }} · {{ activityTotal() }} {{ activityTotal() === 1 ? 'call' : 'calls' }}</span>\n <div class=\"flex gap-2\">\n <button type=\"button\" (click)=\"goToActivityPage(activityPage() - 1)\" [disabled]=\"activityPage() <= 1 || activityLoading()\"\n class=\"px-3 py-1 rounded-md border border-gray-300 hover:bg-gray-50 disabled:opacity-50\">Previous</button>\n <button type=\"button\" (click)=\"goToActivityPage(activityPage() + 1)\" [disabled]=\"activityPage() >= activityTotalPages() || activityLoading()\"\n class=\"px-3 py-1 rounded-md border border-gray-300 hover:bg-gray-50 disabled:opacity-50\">Next</button>\n </div>\n </div>\n }\n </div>\n </ui-modal>\n\n <!-- Providers Table -->\n <div class=\"bg-white shadow rounded-lg overflow-hidden\">\n @if (loading()) {\n <div class=\"p-8 text-center text-gray-500\">Loading...</div>\n } @else {\n <table class=\"min-w-full divide-y divide-gray-200\">\n <thead class=\"bg-gray-50\">\n <tr>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Name</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Target</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Status</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Syncs</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Last Activity</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">Stats</th>\n <th class=\"px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase\">Actions</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200\">\n @if (providers().length === 0) {\n <tr>\n <td colspan=\"7\" class=\"px-6 py-8 text-center text-gray-500\">\n No providers configured. Add one to start pushing users to a downstream system.\n </td>\n </tr>\n } @else {\n @for (p of providers(); track p.id) {\n <tr>\n <td class=\"px-6 py-4\">\n <a [routerLink]=\"['/scim/providers', p.id]\" class=\"text-primary-600 hover:underline font-medium\">\n {{ p.name }}\n </a>\n <p class=\"text-xs text-gray-500\">{{ flavorName(p.flavor) }}</p>\n </td>\n <td class=\"px-6 py-4\">\n <code class=\"text-xs text-gray-700 break-all\">{{ p.baseUrl }}</code>\n </td>\n <td class=\"px-6 py-4\">\n <span\n class=\"inline-flex px-2 py-1 text-xs rounded-full\"\n [class.bg-green-100]=\"p.isEnabled && p.hasSecret\"\n [class.text-green-800]=\"p.isEnabled && p.hasSecret\"\n [class.bg-yellow-100]=\"p.isEnabled && !p.hasSecret\"\n [class.text-yellow-800]=\"p.isEnabled && !p.hasSecret\"\n [class.bg-gray-100]=\"!p.isEnabled\"\n [class.text-gray-800]=\"!p.isEnabled\"\n >\n {{ !p.isEnabled ? 'Disabled' : (p.hasSecret ? 'Enabled' : 'No secret') }}\n </span>\n </td>\n <td class=\"px-6 py-4 text-sm text-gray-700\">\n <span class=\"inline-flex gap-1\">\n @if (p.syncUsers) {\n <span class=\"px-2 py-0.5 text-xs rounded bg-gray-100 text-gray-700\">Users</span>\n }\n @if (p.syncGroups) {\n <span class=\"px-2 py-0.5 text-xs rounded bg-gray-100 text-gray-700\">Groups ({{ p.groupSource }})</span>\n }\n </span>\n </td>\n <td class=\"px-6 py-4 text-sm text-gray-500\">\n @if (p.lastErrorAt && (!p.lastSuccessAt || p.lastErrorAt > p.lastSuccessAt)) {\n <span class=\"text-red-600\" [title]=\"p.lastError || ''\">Error {{ formatDate(p.lastErrorAt) }}</span>\n } @else if (p.lastSuccessAt) {\n {{ formatDate(p.lastSuccessAt) }}\n } @else {\n Never\n }\n </td>\n <td class=\"px-6 py-4 text-sm\">\n <button type=\"button\" (click)=\"openActivity(p, false)\" class=\"text-green-600 hover:underline\" title=\"Show activity\">{{ p.successCount }} ok</button>\n /\n <button type=\"button\" (click)=\"openActivity(p, true)\" class=\"text-red-600 hover:underline\" title=\"Show errors\">{{ p.errorCount }} errors</button>\n </td>\n <td class=\"px-6 py-4 text-right\">\n <button (click)=\"handleDelete(p)\" class=\"text-red-600 hover:text-red-900 p-1\" title=\"Delete\">\n <ui-icon name=\"trash\" class=\"h-5 w-5\" />\n </button>\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n `,\n})\nexport class ScimProvidersComponent implements OnInit {\n private readonly scimService = inject(ScimService);\n private readonly router = inject(Router);\n\n providers = signal<ScimProvider[]>([]);\n options = signal<ScimProviderOptions | null>(null);\n flavors = computed<ScimProviderFlavor[]>(() => this.options()?.flavors ?? []);\n loading = signal(true);\n error = signal<string | null>(null);\n showCreateModal = signal(false);\n creating = signal(false);\n createError = signal<string | null>(null);\n showSecret = signal(false);\n selectedFlavorKey = signal('generic');\n selectedFlavor = computed(() => this.flavors().find((f) => f.key === this.selectedFlavorKey()) ?? null);\n\n createForm = this.emptyForm();\n\n activityProvider = signal<ScimProvider | null>(null);\n activityErrorsOnly = signal(false);\n activityLogs = signal<ScimProviderLog[]>([]);\n activityPage = signal(1);\n activityTotal = signal(0);\n activityTotalPages = signal(1);\n activityLoading = signal(false);\n activityError = signal<string | null>(null);\n private readonly activityPageSize = 25;\n private activityRequest?: Subscription;\n\n ngOnInit(): void {\n this.scimService.getProviderOptions().subscribe({\n next: (o) => this.options.set(o),\n error: (err) => console.error('Failed to load provider options:', err),\n });\n this.loadProviders();\n }\n\n loadProviders(): void {\n this.loading.set(true);\n this.scimService.getProviders().subscribe({\n next: (data) => {\n this.providers.set(data);\n this.loading.set(false);\n },\n error: (err) => {\n this.error.set('Failed to load SCIM providers');\n console.error(err);\n this.loading.set(false);\n },\n });\n }\n\n openCreate(): void {\n this.createForm = this.emptyForm();\n this.selectedFlavorKey.set(this.createForm.flavor);\n this.createError.set(null);\n this.showSecret.set(false);\n this.showCreateModal.set(true);\n }\n\n onFlavorChange(key: string): void {\n this.selectedFlavorKey.set(key);\n }\n\n handleCreate(): void {\n this.creating.set(true);\n this.createError.set(null);\n const f = this.createForm;\n this.scimService\n .createProvider({\n name: f.name,\n description: f.description || undefined,\n flavor: f.flavor,\n baseUrl: f.baseUrl,\n authType: f.authType,\n oauthTokenEndpoint: f.authType === 'oauth_client_credentials' ? f.oauthTokenEndpoint || undefined : undefined,\n oauthClientId: f.authType === 'oauth_client_credentials' ? f.oauthClientId || undefined : undefined,\n oauthScope: f.authType === 'oauth_client_credentials' ? f.oauthScope || undefined : undefined,\n secret: f.secret || undefined,\n })\n .subscribe({\n next: (created) => {\n this.creating.set(false);\n this.showCreateModal.set(false);\n this.router.navigate(['/scim/providers', created.id]);\n },\n error: (err) => {\n this.creating.set(false);\n this.createError.set(typeof err?.error === 'string' ? err.error : 'Failed to create provider');\n console.error('Failed to create provider:', err);\n },\n });\n }\n\n handleDelete(p: ScimProvider): void {\n if (!confirm(`Delete provider \"${p.name}\"? Remote accounts it created are left as they are.`)) return;\n\n this.scimService.deleteProvider(p.id).subscribe({\n next: () => this.providers.update((list) => list.filter((x) => x.id !== p.id)),\n error: (err) => {\n this.error.set('Failed to delete provider');\n console.error('Failed to delete provider:', err);\n },\n });\n }\n\n openActivity(p: ScimProvider, errorsOnly: boolean): void {\n this.activityProvider.set(p);\n this.activityErrorsOnly.set(errorsOnly);\n this.activityLogs.set([]);\n this.activityTotal.set(0);\n this.activityPage.set(1);\n this.loadActivity();\n }\n\n closeActivity(): void {\n this.activityRequest?.unsubscribe();\n this.activityProvider.set(null);\n }\n\n setActivityErrorsOnly(errorsOnly: boolean): void {\n if (this.activityErrorsOnly() === errorsOnly) return;\n this.activityErrorsOnly.set(errorsOnly);\n this.activityPage.set(1);\n this.loadActivity();\n }\n\n goToActivityPage(page: number): void {\n this.activityPage.set(page);\n this.loadActivity();\n }\n\n loadActivity(): void {\n const p = this.activityProvider();\n if (!p) return;\n this.activityRequest?.unsubscribe();\n this.activityLoading.set(true);\n this.activityError.set(null);\n this.activityRequest = this.scimService\n .getProviderLogs(p.id, this.activityPage(), this.activityPageSize, this.activityErrorsOnly() ? false : undefined)\n .subscribe({\n next: (r) => {\n this.activityLogs.set(r.items);\n this.activityTotal.set(r.totalCount);\n this.activityTotalPages.set(Math.max(1, r.totalPages));\n this.activityLoading.set(false);\n },\n error: (err) => {\n this.activityError.set('Failed to load activity');\n this.activityLoading.set(false);\n console.error('Failed to load provider activity:', err);\n },\n });\n }\n\n flavorName(key: string): string {\n return this.flavors().find((f) => f.key === key)?.displayName ?? key;\n }\n\n formatDate(dateString: string): string {\n return new Date(dateString).toLocaleString();\n }\n\n private emptyForm() {\n return {\n name: '',\n description: '',\n flavor: 'generic',\n baseUrl: '',\n authType: 'bearer' as ScimProviderAuthType,\n oauthTokenEndpoint: '',\n oauthClientId: '',\n oauthScope: '',\n secret: '',\n };\n }\n}\n","import { Component, inject, signal, computed, OnInit } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { FormsModule } from '@angular/forms';\nimport { IconComponent } from '@syndew/oluso-ui-core';\nimport { RoleService, TeamService, RoleDto, TeamSummary } from '@syndew/oluso-admin-ui';\nimport { ScimService } from '../../services/scim.service';\nimport {\n ScimProvider,\n ScimProviderOptions,\n ScimProviderFlavor,\n ScimProviderAttributeMapping,\n ScimProviderTestResult,\n ScimProviderQueueResponse,\n ScimProviderLog,\n ScimProviderPreview,\n ScimProviderAuthType,\n ScimProviderUserNameSource,\n ScimProviderDeprovisionMode,\n ScimProviderGroupSource,\n ScimQueueStatus,\n} from '../../models/scim-provider.model';\nimport { ScimClient } from '../../models/scim.model';\n\ninterface MappingForm {\n id: string | null;\n scimAttribute: string;\n source: 'property' | 'expression';\n internalProperty: string;\n expression: string;\n condition: string;\n transformation: string;\n defaultValue: string;\n isEnabled: boolean;\n}\n\n@Component({\n selector: 'lib-scim-provider-detail',\n standalone: true,\n imports: [CommonModule, FormsModule, IconComponent],\n template: `\n <div class=\"space-y-6\">\n <button (click)=\"goBack()\" class=\"inline-flex items-center text-gray-600 hover:text-gray-900 transition-colors\">\n <ui-icon name=\"arrow-left\" class=\"h-4 w-4 mr-2\" />\n Back to SCIM Providers\n </button>\n\n @if (loading()) {\n <div class=\"p-6 text-center text-gray-500\">Loading...</div>\n } @else if (!provider()) {\n <div class=\"p-6 text-center text-gray-500\">Provider not found</div>\n } @else {\n <div class=\"flex items-start justify-between\">\n <div>\n <h1 class=\"text-2xl font-semibold text-gray-900\">{{ provider()!.name }}</h1>\n <p class=\"text-sm text-gray-500 mt-1\">\n {{ flavorName(provider()!.flavor) }} ·\n <code class=\"text-xs\">{{ provider()!.baseUrl }}</code>\n </p>\n </div>\n <span\n class=\"inline-flex px-2 py-1 text-xs rounded-full\"\n [class.bg-green-100]=\"provider()!.isEnabled && provider()!.hasSecret\"\n [class.text-green-800]=\"provider()!.isEnabled && provider()!.hasSecret\"\n [class.bg-yellow-100]=\"provider()!.isEnabled && !provider()!.hasSecret\"\n [class.text-yellow-800]=\"provider()!.isEnabled && !provider()!.hasSecret\"\n [class.bg-gray-100]=\"!provider()!.isEnabled\"\n [class.text-gray-800]=\"!provider()!.isEnabled\"\n >\n {{ !provider()!.isEnabled ? 'Disabled' : (provider()!.hasSecret ? 'Enabled' : 'No secret set') }}\n </span>\n </div>\n\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <!-- Left column -->\n <div class=\"lg:col-span-2 space-y-6\">\n <!-- Settings -->\n <div class=\"bg-white shadow rounded-lg p-6\">\n <h2 class=\"text-lg font-medium mb-4\">Settings</h2>\n\n <div class=\"grid grid-cols-2 gap-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Name</label>\n <input type=\"text\" [(ngModel)]=\"form.name\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\" />\n </div>\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Description</label>\n <input type=\"text\" [(ngModel)]=\"form.description\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\" />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Type</label>\n <select [(ngModel)]=\"form.flavor\" (ngModelChange)=\"onFlavorChange($event)\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\">\n @for (f of flavors(); track f.key) {\n <option [value]=\"f.key\">{{ f.displayName }}</option>\n }\n </select>\n </div>\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">SCIM base URL</label>\n <input type=\"url\" [(ngModel)]=\"form.baseUrl\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent font-mono text-sm\" />\n </div>\n\n @if (selectedFlavor()?.notes) {\n <div class=\"col-span-2 bg-blue-50 border border-blue-200 text-blue-800 text-xs rounded-md p-3\">\n {{ selectedFlavor()!.notes }}\n </div>\n }\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Authentication</label>\n <select [(ngModel)]=\"form.authType\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\">\n <option value=\"bearer\">Bearer token / API key</option>\n <option value=\"oauth_client_credentials\">OAuth 2.0 client credentials</option>\n </select>\n </div>\n @if (form.authType === 'oauth_client_credentials') {\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Token endpoint</label>\n <input type=\"url\" [(ngModel)]=\"form.oauthTokenEndpoint\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent font-mono text-sm\" />\n </div>\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Client ID</label>\n <input type=\"text\" [(ngModel)]=\"form.oauthClientId\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\" />\n </div>\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Scope (optional)</label>\n <input type=\"text\" [(ngModel)]=\"form.oauthScope\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\" />\n </div>\n } @else {\n <div></div>\n }\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">userName comes from</label>\n <select\n [(ngModel)]=\"form.userNameSource\"\n [disabled]=\"!!selectedFlavor()?.requiresEmailUserName && form.userNameSource !== 'expression'\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:bg-gray-50\"\n >\n <option value=\"userName\">Username</option>\n <option value=\"email\">Email address</option>\n <option value=\"expression\">Expression</option>\n </select>\n @if (selectedFlavor()?.requiresEmailUserName) {\n <p class=\"text-xs text-gray-500 mt-1\">\n This type needs an email address as userName. Choose Expression to derive one.\n </p>\n }\n </div>\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">When a user is removed</label>\n <select [(ngModel)]=\"form.deprovisionMode\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\">\n <option value=\"deactivate\">Deactivate the remote account</option>\n <option value=\"delete\">Delete the remote account</option>\n </select>\n </div>\n\n @if (form.userNameSource === 'expression') {\n <div class=\"col-span-2\">\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">userName expression</label>\n <input\n type=\"text\"\n [(ngModel)]=\"form.userNameExpression\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent font-mono text-sm\"\n placeholder=\"{{ '{{' }} user.first_name | string.downcase {{ '}}' }}.{{ '{{' }} user.last_name | string.downcase {{ '}}' }}@mail.example.org\"\n />\n <p class=\"text-xs text-gray-500 mt-1\">\n Scriban template. Available: user.first_name, user.last_name, user.user_name, user.email, user.display_name, roles, teams, team_codes, custom.\n </p>\n </div>\n }\n\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Full reconcile every (minutes)</label>\n <input type=\"number\" min=\"0\" [(ngModel)]=\"form.reconcileIntervalMinutes\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\" />\n <p class=\"text-xs text-gray-500 mt-1\">0 turns scheduled reconciles off; you can still run one manually.</p>\n </div>\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Same system as inbound client</label>\n <select [(ngModel)]=\"form.linkedScimClientId\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\">\n <option value=\"\">None</option>\n @for (c of inboundClients(); track c.id) {\n <option [value]=\"c.id\">{{ c.name }}</option>\n }\n </select>\n <p class=\"text-xs text-gray-500 mt-1\">When this system also provisions into the tenant, the changes it makes are not pushed back to it.</p>\n </div>\n </div>\n\n <h3 class=\"text-sm font-medium text-gray-700 mt-6 mb-3\">What to push</h3>\n <div class=\"grid grid-cols-2 gap-3\">\n <label class=\"flex items-center\">\n <input type=\"checkbox\" [(ngModel)]=\"form.isEnabled\" class=\"rounded border-gray-300 text-primary-600 mr-2\" />\n <span class=\"text-sm\">Enabled</span>\n </label>\n <div></div>\n <label class=\"flex items-center\">\n <input type=\"checkbox\" [(ngModel)]=\"form.syncUsers\" class=\"rounded border-gray-300 text-primary-600 mr-2\" />\n <span class=\"text-sm\">Users</span>\n </label>\n <label class=\"flex items-center\" [class.opacity-50]=\"groupsUnsupported()\">\n <input type=\"checkbox\" [(ngModel)]=\"form.syncGroups\" [disabled]=\"groupsUnsupported()\" class=\"rounded border-gray-300 text-primary-600 mr-2\" />\n <span class=\"text-sm\">Groups</span>\n </label>\n @if (form.syncGroups) {\n <div class=\"col-span-2\">\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Groups are built from</label>\n <select [(ngModel)]=\"form.groupSource\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-primary-500 focus:border-transparent\">\n <option value=\"roles\">Roles</option>\n <option value=\"teams\">Teams (members include sub-teams)</option>\n <option value=\"both\">Roles and teams</option>\n </select>\n </div>\n }\n </div>\n\n <h3 class=\"text-sm font-medium text-gray-700 mt-6 mb-1\">Scope</h3>\n <p class=\"text-xs text-gray-500 mb-3\">\n Leave both empty to provision everyone in the tenant. Otherwise a user is provisioned when they hold one of\n the selected roles or belong to one of the selected teams, and only those roles and teams are pushed as groups.\n </p>\n <div class=\"grid grid-cols-2 gap-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Roles</label>\n <div class=\"border border-gray-200 rounded-md max-h-48 overflow-y-auto p-2 space-y-1\">\n @if (roles().length === 0) {\n <p class=\"text-xs text-gray-400 px-1\">No roles</p>\n }\n @for (r of roles(); track r.id) {\n <label class=\"flex items-center text-sm\">\n <input type=\"checkbox\" [checked]=\"scopeRoleIds().has(r.id)\" (change)=\"toggleScopeRole(r.id)\" class=\"rounded border-gray-300 text-primary-600 mr-2\" />\n <span>{{ r.displayName || r.name }}</span>\n </label>\n }\n </div>\n </div>\n <div>\n <label class=\"block text-sm font-medium text-gray-700 mb-1\">Teams</label>\n <div class=\"border border-gray-200 rounded-md max-h-48 overflow-y-auto p-2 space-y-1\">\n @if (teams().length === 0) {\n <p class=\"text-xs text-gray-400 px-1\">No teams</p>\n }\n @for (t of teams(); track t.id) {\n <label class=\"flex items-center text-sm\">\n <input type=\"checkbox\" [checked]=\"scopeTeamIds().has(t.id)\" (change)=\"toggleScopeTeam(t.id)\" class=\"rounded border-gray-300 text-primary-600 mr-2\" />\n <span>{{ t.name }} <span class=\"text-gray-400 text-xs\">{{ t.code }}</span></span>\n </label>\n }\n </div>\n </div>\n </div>\n\n @if (saveError()) {\n <div class=\"mt-4 bg-red-50 text-red-700 p-3 rounded-md text-sm\">{{ saveError() }}</div>\n }\n\n <div class=\"mt-6 flex justify-end\">\n <button (click)=\"handleSave()\" [disabled]=\"saving()\" class=\"px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 disabled:opacity-50 transition-colors\">\n {{ saving() ? 'Saving...' : 'Save Changes' }}\n </button>\n </div>\n </div>\n\n <!-- Attribute mappings -->\n <div class=\"bg-white shadow rounded-lg p-6\">\n <div class=\"flex items-center justify-between mb-1\">\n <h2 class=\"text-lg font-medium\">Attribute Mappings</h2>\n <div class=\"flex gap-2\">\n <button (click)=\"applyDefaults()\" class=\"text-sm px-3 py-1.5 bg-gray-100 rounded-md hover:bg-gray-200 transition-colors\">Add type defaults</button>\n <button (click)=\"startNewMapping()\" class=\"inline-flex items-center text-sm px-3 py-1.5 bg-primary-600 text-white rounded-md hover:bg-primary-700 transition-colors\">\n <ui-icon name=\"plus\" class=\"h-4 w-4 mr-1\" /> Add\n </button>\n </div>\n </div>\n <p class=\"text-xs text-gray-500 mb-4\">\n userName, externalId and active are always sent. With no rows here the type's defaults are used.\n An expression replaces the property; a condition leaves the attribute out when false.\n </p>\n\n @if (mappingForm(); as mf) {\n <div class=\"border border-primary-200 bg-primary-50/40 rounded-md p-4 mb-4\">\n <div class=\"grid grid-cols-2 gap-3\">\n <div class=\"col-span-2\">\n <label class=\"block text-xs font-medium text-gray-700 mb-1\">SCIM attribute</label>\n <input type=\"text\" [(ngModel)]=\"mf.scimAttribute\" list=\"scim-attr-suggestions\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 text-sm font-mono\" placeholder='displayName, name.givenName, emails[type eq \"work\"].value, urn:...:User:department' />\n <datalist id=\"scim-attr-suggestions\">\n @for (s of attributeSuggestions; track s) {\n <option [value]=\"s\"></option>\n }\n </datalist>\n </div>\n <div>\n <label class=\"block text-xs font-medium text-gray-700 mb-1\">Value from</label>\n <select [(ngModel)]=\"mf.source\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 text-sm\">\n <option value=\"property\">Internal property</option>\n <option value=\"expression\">Expression</option>\n </select>\n </div>\n @if (mf.source === 'property') {\n <div>\n <label class=\"block text-xs font-medium text-gray-700 mb-1\">Internal property</label>\n <input type=\"text\" [(ngModel)]=\"mf.internalProperty\" list=\"scim-prop-suggestions\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 text-sm\" placeholder=\"Email, FirstName, custom:department\" />\n <datalist id=\"scim-prop-suggestions\">\n @for (p of internalProperties(); track p) {\n <option [value]=\"p\"></option>\n }\n </datalist>\n </div>\n } @else {\n <div>\n <label class=\"block text-xs font-medium text-gray-700 mb-1\">Expression (Scriban)</label>\n <input type=\"text\" [(ngModel)]=\"mf.expression\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 text-sm font-mono\" placeholder=\"{{ '{{' }} user.first_name {{ '}}' }} {{ '{{' }} user.last_name {{ '}}' }}\" />\n </div>\n }\n <div class=\"col-span-2\">\n <label class=\"block text-xs font-medium text-gray-700 mb-1\">Condition (optional, Scriban boolean)</label>\n <input type=\"text\" [(ngModel)]=\"mf.condition\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 text-sm font-mono\" placeholder='roles | array.contains \"Manager\"' />\n </div>\n <div>\n <label class=\"block text-xs font-medium text-gray-700 mb-1\">Transformation</label>\n <select [(ngModel)]=\"mf.transformation\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 text-sm\">\n @for (t of transformations(); track t) {\n <option [value]=\"t\">{{ t }}</option>\n }\n </select>\n </div>\n <div>\n <label class=\"block text-xs font-medium text-gray-700 mb-1\">Default when empty</label>\n <input type=\"text\" [(ngModel)]=\"mf.defaultValue\" class=\"w-full border border-gray-300 rounded-md px-3 py-2 text-sm\" />\n </div>\n <label class=\"flex items-center text-sm col-span-2\">\n <input type=\"checkbox\" [(ngModel)]=\"mf.isEnabled\" class=\"rounded border-gray-300 text-primary-600 mr-2\" /> Enabled\n </label>\n </div>\n @if (mappingError()) {\n <div class=\"mt-3 bg-red-50 text-red-700 p-2 rounded-md text-xs\">{{ mappingError() }}</div>\n }\n <div class=\"flex justify-end gap-2 mt-3\">\n <button (click)=\"mappingForm.set(null)\" class=\"px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-100 rounded-md\">Cancel</button>\n <button (click)=\"saveMapping()\" [disabled]=\"savingMapping()\" class=\"px-3 py-1.5 text-sm bg-primary-600 text-white rounded-md hover:bg-primary-700 disabled:opacity-50\">\n {{ savingMapping() ? 'Saving...' : (mf.id ? 'Update' : 'Add') }}\n </button>\n </div>\n </div>\n }\n\n @if (loadingMappings()) {\n <div class=\"p-4 text-center text-gray-500 text-sm\">Loading...</div>\n } @else if (mappings().length === 0) {\n <div class=\"text-sm text-gray-500 border border-dashed border-gray-200 rounded-md p-4\">\n Using {{ selectedFlavor()?.displayName || 'type' }} defaults:\n <ul class=\"mt-2 space-y-1 font-mono text-xs text-gray-600\">\n @for (d of selectedFlavor()?.defaultUserMappings ?? []; track d.scimAttribute) {\n <li>{{ d.scimAttribute }} ← {{ d.internalProperty }}</li>\n }\n </ul>\n </div>\n } @else {\n <table class=\"min-w-full divide-y divide-gray-200 text-sm\">\n <thead class=\"bg-gray-50\">\n <tr>\n <th class=\"px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase\">Attribute</th>\n <th class=\"px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase\">Value</th>\n <th class=\"px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase\">Condition</th>\n <th class=\"px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase\">Transform</th>\n <th class=\"px-3 py-2 text-right text-xs font-medium text-gray-500 uppercase\"></th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200\">\n @for (m of mappings(); track m.id) {\n <tr [class.opacity-50]=\"!m.isEnabled\">\n <td class=\"px-3 py-2 font-mono text-xs\">{{ m.scimAttribute }}</td>\n <td class=\"px-3 py-2 font-mono text-xs\">\n @if (m.expression) {\n <span class=\"text-purple-700\">{{ m.expression }}</span>\n } @else {\n {{ m.internalProperty }}\n }\n @if (m.defaultValue) {\n <span class=\"text-gray-400\"> ?? {{ m.defaultValue }}</span>\n }\n </td>\n <td class=\"px-3 py-2 font-mono text-xs text-gray-600\">{{ m.condition || '' }}</td>\n <td class=\"px-3 py-2 text-xs text-gray-600\">{{ m.transformation || '' }}</td>\n <td class=\"px-3 py-2 text-right whitespace-nowrap\">\n <button (click)=\"editMapping(m)\" class=\"text-gray-600 hover:text-gray-900 p-1\" title=\"Edit\"><ui-icon name=\"pencil\" class=\"h-4 w-4\" /></button>\n <button (click)=\"deleteMapping(m)\" class=\"text-red-600 hover:text-red-900 p-1\" title=\"Delete\"><ui-icon name=\"trash\" class=\"h-4 w-4\" /></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n }\n\n <!-- Preview -->\n <h3 class=\"text-sm font-medium text-gray-700 mt-6 mb-2\">Preview payload for a user</h3>\n <div class=\"flex gap-2\">\n <input type=\"text\" [(ngModel)]=\"previewUserId\" class=\"flex-1 border border-gray-300 rounded-md px-3 py-2 text-sm font-mono\" placeholder=\"User id\" />\n <button (click)=\"runPreview()\" [disabled]=\"previewing() || !previewUserId\" class=\"px-3 py-2 text-sm bg-gray-100 rounded-md hover:bg-gray-200 disabled:opacity-50\">\n {{ previewing() ? 'Building...' : 'Preview' }}\n </button>\n </div>\n @if (preview(); as pv) {\n <div class=\"mt-3\">\n @if (pv.error) {\n <div class=\"bg-red-50 text-red-700 p-3 rounded-md text-xs\">{{ pv.error }}</div>\n } @else {\n <p class=\"text-xs text-gray-500 mb-1\">\n userName <code>{{ pv.userName }}</code> ·\n {{ pv.inScope ? 'in scope' : 'outside scope (would not be provisioned)' }}\n </p>\n <pre class=\"bg-gray-100 p-3 rounded-md text-xs font-mono overflow-x-auto\">{{ pv.payload | json }}</pre>\n }\n </div>\n }\n </div>\n\n <!-- Queue -->\n <div class=\"bg-white shadow rounded-lg p-6\">\n <div class=\"flex items-center justify-between mb-4\">\n <h2 class=\"text-lg font-medium\">Queue</h2>\n <div class=\"flex gap-2\">\n <button (click)=\"loadQueue()\" class=\"text-gray-600 hover:text-gray-900 p-1\" title=\"Refresh\"><ui-icon name=\"refresh\" class=\"h-5 w-5\" /></button>\n <button (click)=\"retryFailed()\" [disabled]=\"!queue() || (queue()!.summary.failed + queue()!.summary.dead) === 0\" class=\"text-sm px-3 py-1.5 bg-gray-100 rounded-md hover:bg-gray-200 disabled:opacity-50\">Retry failed</button>\n <button (click)=\"runReconcile()\" [disabled]=\"reconciling()\" class=\"text-sm px-3 py-1.5 bg-primary-600 text-white rounded-md hover:bg-primary-700 disabled:opacity-50\">\n {{ reconciling() ? 'Queuing...' : 'Run full reconcile' }}\n </button>\n </div>\n </div>\n @if (queueMessage()) {\n <div class=\"mb-3 bg-blue-50 text-blue-800 p-2 rounded-md text-xs\">{{ queueMessage() }}</div>\n }\n @if (queue(); as q) {\n <div class=\"grid grid-cols-5 gap-3 mb-4 text-center\">\n <div><div class=\"text-xl font-bold\">{{ q.summary.pending }}</div><div class=\"text-xs text-gray-500\">Pending</div></div>\n <div><div class=\"text-xl font-bold\">{{ q.summary.processing }}</div><div class=\"text-xs text-gray-500\">Processing</div></div>\n <div><div class=\"text-xl font-bold text-yellow-600\">{{ q.summary.failed }}</div><div class=\"text-xs text-gray-500\">Retrying</div></div>\n <div><div class=\"text-xl font-bold text-red-600\">{{ q.summary.dead }}</div><div class=\"text-xs text-gray-500\">Gave up</div></div>\n <div><div class=\"text-xl font-bold text-green-600\">{{ q.summary.succeededLast24h }}</div><div class=\"text-xs text-gray-500\">Done (24h)</div></div>\n </div>\n <div class=\"flex items-center gap-2 mb-2\">\n <label class=\"text-xs text-gray-500\">Show</label>\n <select [(ngModel)]=\"queueFilter\" (ngModelChange)=\"loadQueue()\" class=\"border border-gray-300 rounded-md px-2 py-1 text-xs\">\n <option value=\"failed,dead\">Problems</option>\n <option value=\"pending,processing\">Waiting</option>\n <option value=\"succeeded\">Done</option>\n <option value=\"\">Everything</option>\n </select>\n </div>\n @if (q.items.length === 0) {\n <p class=\"text-sm text-gray-500\">Nothing here.</p>\n } @else {\n <table class=\"min-w-full divide-y divide-gray-200 text-sm\">\n <thead class=\"bg-gray-50\">\n <tr>\n <th class=\"px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase\">Resource</th>\n <th class=\"px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase\">Op</th>\n <th class=\"px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase\">Status</th>\n <th class=\"px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase\">Tries</th>\n <th class=\"px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase\">Detail</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200\">\n @for (i of q.items; track i.id) {\n <tr>\n <td class=\"px-3 py-2 font-mono text-xs\">{{ i.resourceType }} {{ i.internalId }}</td>\n <td class=\"px-3 py-2 text-xs\">{{ i.operation }}</td>\n <td class=\"px-3 py-2 text-xs\">\n <span class=\"px-2 py-0.5 rounded-full\" [class]=\"statusClass(i.status)\">{{ i.status }}</span>\n </td>\n <td class=\"px-3 py-2 text-xs\">{{ i.attempts }}</td>\n <td class=\"px-3 py-2 text-xs text-gray-600\">\n @if (i.lastError) { <span class=\"text-red-700\">{{ i.lastError }}</span> }\n @else { {{ i.reason }} }\n </td>\n </tr>\n }\n </tbody>\n </table>\n }\n }\n </div>\n\n <!-- Recent activity -->\n <div class=\"bg-white shadow rounded-lg p-6\">\n <div class=\"flex items-center justify-between mb-4\">\n <h2 class=\"text-lg font-medium\">Recent Activity</h2>\n <button (click)=\"loadLogs()\" class=\"text-gray-600 hover:text-gray-900 p-1\" title=\"Refresh\"><ui-icon name=\"refresh\" class=\"h-5 w-5\" /></button>\n </div>\n @if (logs().length === 0) {\n <p class=\"text-sm text-gray-500\">No calls made yet.</p>\n } @else {\n <div class=\"space-y-2\">\n @for (l of logs(); track l.id) {\n <div class=\"flex items-start gap-3 text-sm\">\n <ui-icon [name]=\"l.success ? 'check-circle' : 'x-circle'\" class=\"h-5 w-5 mt-0.5\" [class.text-green-600]=\"l.success\" [class.text-red-600]=\"!l.success\" />\n <div class=\"flex-1 min-w-0\">\n <div class=\"font-mono text-xs truncate\">\n <span class=\"font-semibold\">{{ l.method }}</span> {{ l.path }}\n <span class=\"text-gray-400\">→ {{ l.statusCode }} · {{ l.durationMs }}ms</span>\n </div>\n <div class=\"text-xs text-gray-500\">\n {{ l.operation }} {{ l.resourceType || '' }} {{ l.internalId || '' }}\n @if (l.errorMessage) { <span class=\"text-red-600\">· {{ l.errorMessage }}</span> }\n </div>\n </div>\n <div class=\"text-xs text-gray-400 whitespace-nowrap\">{{ formatDate(l.timestamp) }}</div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Right column -->\n <div class=\"lg:col-span-1 space-y-6\">\n <!-- Credential -->\n <div class=\"bg-white shadow rounded-lg p-6\">\n <h2 class=\"text-lg font-medium mb-2\">Credential</h2>\n <p class=\"text-xs text-gray-500 mb-3\">\n @if (provider()!.hasSecret) {\n Secret set {{ formatDate(provider()!.secretUpdatedAt!) }}. Enter a new one to rotate.\n } @else {\n No secret stored. Pushes fail until one is set.\n }\n </p>\n <div class=\"relative mb-2\">\n <input\n [type]=\"showSecret() ? 'text' : 'password'\"\n [(ngModel)]=\"newSecret\"\n autocomplete=\"new-password\"\n class=\"w-full border border-gray-300 rounded-md px-3 py-2 pr-10 text-sm font-mono\"\n [placeholder]=\"form.authType === 'bearer' ? 'Bearer token / API key' : 'Client secret'\"\n />\n <button type=\"button\" (click)=\"showSecret.set(!showSecret())\" class=\"absolute inset-y-0 right-0 px-3 text-gray-500 hover:text-gray-700\">\n <ui-icon [name]=\"showSecret() ? 'eye-slash' : 'eye'\" class=\"h-4 w-4\" />\n </button>\n </div>\n @if (secretError()) {\n <div class=\"mb-2 bg-red-50 text-red-700 p-2 rounded-md text-xs\">{{ secretError() }}</div>\n }\n <button (click)=\"saveSecret()\" [disabled]=\"!newSecret || savingSecret()\" class=\"w-full px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 disabled:opacity-50 text-sm\">\n {{ savingSecret() ? 'Saving...' : (provider()!.hasSecret ? 'Rotate secret' : 'Save secret') }}\n </button>\n\n <div class=\"border-t border-gray-100 mt-4 pt-4\">\n <button (click)=\"testConnection()\" [disabled]=\"testing()\" class=\"w-full inline-flex items-center justify-center px-4 py-2 bg-gray-100 rounded-md hover:bg-gray-200 disabled:opacity-50 text-sm\">\n <ui-icon name=\"play-circle\" class=\"h-4 w-4 mr-2\" />\n {{ testing() ? 'Testing...' : 'Test connection' }}\n </button>\n @if (testResult(); as t) {\n <div class=\"mt-3 text-xs rounded-md p-3\" [class.bg-green-50]=\"t.success\" [class.text-green-800]=\"t.success\" [class.bg-red-50]=\"!t.success\" [class.text-red-800]=\"!t.success\">\n <p>{{ t.message }}</p>\n <ul class=\"mt-2 space-y-0.5 text-gray-700\">\n <li>Discovery: {{ t.discoveryReachable ? 'ok' : 'failed' }} ({{ t.discoveryStatusCode }})</li>\n <li>Authenticated list: {{ t.authenticationOk ? 'ok' : 'failed' }} ({{ t.authenticationStatusCode }})</li>\n @if (t.patchSupported !== null && t.patchSupported !== undefined) {\n <li>PATCH {{ t.patchSupported ? 'yes' : 'no' }} · Bulk {{ t.bulkSupported ? 'yes' : 'no' }} · Filter {{ t.filterSupported ? 'yes' : 'no' }}{{ t.filterMaxResults ? ' (max ' + t.filterMaxResults + ')' : '' }} · ETag {{ t.etagSupported ? 'yes' : 'no' }}</li>\n }\n @if (t.authenticationSchemes.length) {\n <li>Auth schemes: {{ t.authenticationSchemes.join(', ') }}</li>\n }\n </ul>\n </div>\n }\n </div>\n </div>\n\n <!-- Statistics -->\n <div class=\"bg-white shadow rounded-lg p-6\">\n <h2 class=\"text-lg font-medium mb-4\">Statistics</h2>\n <dl class=\"space-y-2 text-sm\">\n <div class=\"flex justify-between\"><dt class=\"text-gray-500\">Successful operations</dt><dd class=\"font-medium text-green-600\">{{ provider()!.successCount }}</dd></div>\n <div class=\"flex justify-between\"><dt class=\"text-gray-500\">Failed operations</dt><dd class=\"font-medium text-red-600\">{{ provider()!.errorCount }}</dd></div>\n <div class=\"flex justify-between\"><dt class=\"text-gray-500\">Provisioned users</dt><dd class=\"font-medium\">{{ resourceCounts().users }}</dd></div>\n <div class=\"flex justify-between\"><dt class=\"text-gray-500\">Provisioned groups</dt><dd class=\"font-medium\">{{ resourceCounts().groups }}</dd></div>\n <div class=\"flex justify-between\"><dt class=\"text-gray-500\">Last success</dt><dd>{{ provider()!.lastSuccessAt ? formatDate(provider()!.lastSuccessAt!) : 'Never' }}</dd></div>\n <div class=\"flex justify-between\"><dt class=\"text-gray-500\">Last error</dt><dd>{{ provider()!.lastErrorAt ? formatDate(provider()!.lastErrorAt!) : 'Never' }}</dd></div>\n <div class=\"flex justify-between\"><dt class=\"text-gray-500\">Last reconcile</dt><dd>{{ provider()!.lastReconcileAt ? formatDate(provider()!.lastReconcileAt!) : 'Never' }}</dd></div>\n </dl>\n @if (provider()!.lastError) {\n <p class=\"mt-3 text-xs text-red-700 break-words\">{{ provider()!.lastError }}</p>\n }\n @if (provider()!.lastReconcileSummary) {\n <p class=\"mt-3 text-xs text-gray-500\">{{ provider()!.lastReconcileSummary }}</p>\n }\n </div>\n </div>\n </div>\n }\n </div>\n `,\n})\nexport class ScimProviderDetailComponent implements OnInit {\n private readonly scimService = inject(ScimService);\n private readonly roleService = inject(RoleService);\n private readonly teamService = inject(TeamService);\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n\n providerId = '';\n provider = signal<ScimProvider | null>(null);\n options = signal<ScimProviderOptions | null>(null);\n flavors = computed<ScimProviderFlavor[]>(() => this.options()?.flavors ?? []);\n internalProperties = computed(() => this.options()?.internalProperties ?? []);\n transformations = computed(() => this.options()?.transformations ?? ['none']);\n roles = signal<RoleDto[]>([]);\n teams = signal<TeamSummary[]>([]);\n inboundClients = signal<ScimClient[]>([]);\n loading = signal(true);\n saving = signal(false);\n saveError = signal<string | null>(null);\n\n selectedFlavorKey = signal('generic');\n selectedFlavor = computed(() => this.flavors().find((f) => f.key === this.selectedFlavorKey()) ?? null);\n groupsUnsupported = computed(() => {\n const f = this.selectedFlavor();\n return !!f && !f.supportsGroups;\n });\n scopeRoleIds = signal<Set<string>>(new Set());\n scopeTeamIds = signal<Set<string>>(new Set());\n\n mappings = signal<ScimProviderAttributeMapping[]>([]);\n loadingMappings = signal(true);\n mappingForm = signal<MappingForm | null>(null);\n mappingError = signal<string | null>(null);\n savingMapping = signal(false);\n\n previewUserId = '';\n previewing = signal(false);\n preview = signal<ScimProviderPreview | null>(null);\n\n queue = signal<ScimProviderQueueResponse | null>(null);\n queueFilter = 'failed,dead';\n queueMessage = signal<string | null>(null);\n reconciling = signal(false);\n\n logs = signal<ScimProviderLog[]>([]);\n resourceCounts = signal({ users: 0, groups: 0 });\n\n newSecret = '';\n showSecret = signal(false);\n savingSecret = signal(false);\n secretError = signal<string | null>(null);\n testing = signal(false);\n testResult = signal<ScimProviderTestResult | null>(null);\n\n readonly attributeSuggestions = [\n 'displayName',\n 'name.givenName',\n 'name.familyName',\n 'name.formatted',\n 'nickName',\n 'title',\n 'preferredLanguage',\n 'locale',\n 'timezone',\n 'emails[type eq \"work\"].value',\n 'phoneNumbers[type eq \"work\"].value',\n 'phoneNumbers[type eq \"mobile\"].value',\n 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department',\n 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:employeeNumber',\n 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:organization',\n 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:costCenter',\n ];\n\n form = {\n name: '',\n description: '',\n isEnabled: true,\n flavor: 'generic',\n baseUrl: '',\n authType: 'bearer' as ScimProviderAuthType,\n oauthTokenEndpoint: '',\n oauthClientId: '',\n oauthScope: '',\n syncUsers: true,\n syncGroups: false,\n groupSource: 'roles' as ScimProviderGroupSource,\n userNameSource: 'userName' as ScimProviderUserNameSource,\n userNameExpression: '',\n deprovisionMode: 'deactivate' as ScimProviderDeprovisionMode,\n reconcileIntervalMinutes: 360,\n linkedScimClientId: '',\n };\n\n ngOnInit(): void {\n this.providerId = this.route.snapshot.paramMap.get('id') || '';\n if (!this.providerId) return;\n\n this.scimService.getProviderOptions().subscribe({\n next: (o) => this.options.set(o),\n error: (err) => console.error('Failed to load provider options:', err),\n });\n this.roleService.getAllRoles().subscribe({\n next: (r) => this.roles.set(r.filter((x) => !x.isGlobal)),\n error: (err) => console.error('Failed to load roles:', err),\n });\n this.teamService.picker().subscribe({\n next: (t) => this.teams.set(t),\n error: (err) => console.error('Failed to load teams:', err),\n });\n this.scimService.getClients().subscribe({\n next: (c) => this.inboundClients.set(c),\n error: (err) => console.error('Failed to load inbound SCIM clients:', err),\n });\n\n this.loadProvider();\n this.loadMappings();\n this.loadQueue();\n this.loadLogs();\n this.loadResourceCounts();\n }\n\n loadProvider(): void {\n this.scimService.getProvider(this.providerId).subscribe({\n next: (p) => {\n this.applyProvider(p);\n this.loading.set(false);\n },\n error: (err) => {\n console.error('Failed to load provider:', err);\n this.loading.set(false);\n },\n });\n }\n\n private applyProvider(p: ScimProvider): void {\n this.provider.set(p);\n this.selectedFlavorKey.set(p.flavor);\n this.scopeRoleIds.set(new Set(p.scopeRoleIds));\n this.scopeTeamIds.set(new Set(p.scopeTeamIds));\n this.form = {\n name: p.name,\n description: p.description || '',\n isEnabled: p.isEnabled,\n flavor: p.flavor,\n baseUrl: p.baseUrl,\n authType: p.authType,\n oauthTokenEndpoint: p.oauthTokenEndpoint || '',\n oauthClientId: p.oauthClientId || '',\n oauthScope: p.oauthScope || '',\n syncUsers: p.syncUsers,\n syncGroups: p.syncGroups,\n groupSource: p.groupSource || 'roles',\n userNameSource: p.userNameSource,\n userNameExpression: p.userNameExpression || '',\n deprovisionMode: p.deprovisionMode,\n reconcileIntervalMinutes: p.reconcileIntervalMinutes,\n linkedScimClientId: p.linkedScimClientId || '',\n };\n }\n\n onFlavorChange(key: string): void {\n this.selectedFlavorKey.set(key);\n const f = this.selectedFlavor();\n if (f?.requiresEmailUserName && this.form.userNameSource === 'userName') {\n this.form.userNameSource = 'email';\n }\n if (f && !f.supportsGroups) {\n this.form.syncGroups = false;\n }\n }\n\n toggleScopeRole(id: string): void {\n this.scopeRoleIds.update((s) => {\n const next = new Set(s);\n next.has(id) ? next.delete(id) : next.add(id);\n return next;\n });\n }\n\n toggleScopeTeam(id: string): void {\n this.scopeTeamIds.update((s) => {\n const next = new Set(s);\n next.has(id) ? next.delete(id) : next.add(id);\n return next;\n });\n }\n\n handleSave(): void {\n this.saving.set(true);\n this.saveError.set(null);\n const f = this.form;\n const oauth = f.authType === 'oauth_client_credentials';\n this.scimService\n .updateProvider(this.providerId, {\n name: f.name,\n description: f.description || undefined,\n isEnabled: f.isEnabled,\n flavor: f.flavor,\n baseUrl: f.baseUrl,\n authType: f.authType,\n oauthTokenEndpoint: oauth ? f.oauthTokenEndpoint || undefined : undefined,\n oauthClientId: oauth ? f.oauthClientId || undefined : undefined,\n oauthScope: oauth ? f.oauthScope || undefined : undefined,\n syncUsers: f.syncUsers,\n syncGroups: f.syncGroups,\n groupSource: f.groupSource,\n scopeRoleIds: [...this.scopeRoleIds()],\n scopeTeamIds: [...this.scopeTeamIds()],\n userNameSource: f.userNameSource,\n userNameExpression: f.userNameSource === 'expression' ? f.userNameExpression || undefined : undefined,\n deprovisionMode: f.deprovisionMode,\n reconcileIntervalMinutes: Number(f.reconcileIntervalMinutes) || 0,\n linkedScimClientId: f.linkedScimClientId || undefined,\n })\n .subscribe({\n next: (updated) => {\n this.applyProvider(updated);\n this.saving.set(false);\n },\n error: (err) => {\n this.saveError.set(typeof err?.error === 'string' ? err.error : 'Failed to save changes');\n this.saving.set(false);\n },\n });\n }\n\n // ── Credential / test ─────────────────────────────────────────────\n\n saveSecret(): void {\n if (!this.newSecret) return;\n this.savingSecret.set(true);\n this.secretError.set(null);\n this.scimService.setProviderSecret(this.providerId, this.newSecret).subscribe({\n next: (updated) => {\n this.applyProvider(updated);\n this.newSecret = '';\n this.showSecret.set(false);\n this.savingSecret.set(false);\n },\n error: (err) => {\n this.secretError.set(typeof err?.error === 'string' ? err.error : 'Failed to save secret');\n this.savingSecret.set(false);\n },\n });\n }\n\n testConnection(): void {\n this.testing.set(true);\n this.testResult.set(null);\n this.scimService.testProvider(this.providerId).subscribe({\n next: (r) => {\n this.testResult.set(r);\n this.testing.set(false);\n this.loadLogs();\n },\n error: (err) => {\n this.testResult.set({\n success: false,\n message: typeof err?.error === 'string' ? err.error : 'Test request failed',\n discoveryReachable: false,\n discoveryStatusCode: 0,\n authenticationOk: false,\n authenticationStatusCode: 0,\n authenticationSchemes: [],\n });\n this.testing.set(false);\n },\n });\n }\n\n // ── Mappings ──────────────────────────────────────────────────────\n\n loadMappings(): void {\n this.loadingMappings.set(true);\n this.scimService.getProviderMappings(this.providerId).subscribe({\n next: (m) => {\n this.mappings.set(m);\n this.loadingMappings.set(false);\n },\n error: (err) => {\n console.error('Failed to load mappings:', err);\n this.loadingMappings.set(false);\n },\n });\n }\n\n startNewMapping(): void {\n this.mappingError.set(null);\n this.mappingForm.set({\n id: null,\n scimAttribute: '',\n source: 'property',\n internalProperty: '',\n expression: '',\n condition: '',\n transformation: 'none',\n defaultValue: '',\n isEnabled: true,\n });\n }\n\n editMapping(m: ScimProviderAttributeMapping): void {\n this.mappingError.set(null);\n this.mappingForm.set({\n id: m.id,\n scimAttribute: m.scimAttribute,\n source: m.expression ? 'expression' : 'property',\n internalProperty: m.internalProperty || '',\n expression: m.expression || '',\n condition: m.condition || '',\n transformation: m.transformation || 'none',\n defaultValue: m.defaultValue || '',\n isEnabled: m.isEnabled,\n });\n }\n\n saveMapping(): void {\n const mf = this.mappingForm();\n if (!mf) return;\n this.savingMapping.set(true);\n this.mappingError.set(null);\n const request = {\n scimAttribute: mf.scimAttribute,\n internalProperty: mf.source === 'property' ? mf.internalProperty || undefined : undefined,\n expression: mf.source === 'expression' ? mf.expression || undefined : undefined,\n condition: mf.condition || undefined,\n transformation: mf.transformation === 'none' ? undefined : mf.transformation,\n defaultValue: mf.defaultValue || undefined,\n isEnabled: mf.isEnabled,\n };\n const call = mf.id\n ? this.scimService.updateProviderMapping(this.providerId, mf.id, request)\n : this.scimService.createProviderMapping(this.providerId, request);\n call.subscribe({\n next: () => {\n this.savingMapping.set(false);\n this.mappingForm.set(null);\n this.loadMappings();\n },\n error: (err) => {\n this.mappingError.set(typeof err?.error === 'string' ? err.error : 'Failed to save mapping');\n this.savingMapping.set(false);\n },\n });\n }\n\n deleteMapping(m: ScimProviderAttributeMapping): void {\n if (!confirm(`Remove the mapping for ${m.scimAttribute}?`)) return;\n this.scimService.deleteProviderMapping(this.providerId, m.id).subscribe({\n next: () => this.mappings.update((list) => list.filter((x) => x.id !== m.id)),\n error: (err) => console.error('Failed to delete mapping:', err),\n });\n }\n\n applyDefaults(): void {\n this.scimService.applyProviderDefaultMappings(this.providerId).subscribe({\n next: () => this.loadMappings(),\n error: (err) => console.error('Failed to apply defaults:', err),\n });\n }\n\n runPreview(): void {\n if (!this.previewUserId) return;\n this.previewing.set(true);\n this.scimService.previewProvider(this.providerId, this.previewUserId.trim()).subscribe({\n next: (pv) => {\n this.preview.set(pv);\n this.previewing.set(false);\n },\n error: (err) => {\n this.preview.set({\n userId: this.previewUserId,\n inScope: false,\n error: typeof err?.error === 'string' ? err.error : 'Preview failed',\n });\n this.previewing.set(false);\n },\n });\n }\n\n // ── Queue / logs ──────────────────────────────────────────────────\n\n loadQueue(): void {\n this.scimService.getProviderQueue(this.providerId, this.queueFilter || undefined, 0, 25).subscribe({\n next: (q) => this.queue.set(q),\n error: (err) => console.error('Failed to load queue:', err),\n });\n }\n\n retryFailed(): void {\n this.scimService.retryProviderQueue(this.providerId).subscribe({\n next: (r) => {\n this.queueMessage.set(`${r.requeued} item(s) queued again.`);\n this.loadQueue();\n },\n error: (err) => console.error('Failed to retry queue:', err),\n });\n }\n\n runReconcile(): void {\n this.reconciling.set(true);\n this.queueMessage.set(null);\n this.scimService.reconcileProvider(this.providerId).subscribe({\n next: (r) => {\n this.queueMessage.set(`Reconcile queued: ${r.summary}.`);\n this.reconciling.set(false);\n this.loadQueue();\n this.loadProvider();\n },\n error: (err) => {\n this.queueMessage.set(typeof err?.error === 'string' ? err.error : 'Failed to queue reconcile');\n this.reconciling.set(false);\n },\n });\n }\n\n loadLogs(): void {\n this.scimService.getProviderLogs(this.providerId, 1, 20).subscribe({\n next: (r) => this.logs.set(r.items),\n error: (err) => console.error('Failed to load logs:', err),\n });\n }\n\n loadResourceCounts(): void {\n this.scimService.getProviderResources(this.providerId, 'User', 1, 1).subscribe({\n next: (r) => this.resourceCounts.update((c) => ({ ...c, users: r.totalCount })),\n error: (err) => console.error('Failed to load user count:', err),\n });\n this.scimService.getProviderResources(this.providerId, 'Group', 1, 1).subscribe({\n next: (r) => this.resourceCounts.update((c) => ({ ...c, groups: r.totalCount })),\n error: (err) => console.error('Failed to load group count:', err),\n });\n }\n\n statusClass(status: ScimQueueStatus): string {\n switch (status) {\n case 'succeeded':\n return 'bg-green-100 text-green-800';\n case 'failed':\n return 'bg-yellow-100 text-yellow-800';\n case 'dead':\n return 'bg-red-100 text-red-800';\n case 'processing':\n return 'bg-blue-100 text-blue-800';\n default:\n return 'bg-gray-100 text-gray-800';\n }\n }\n\n flavorName(key: string): string {\n return this.flavors().find((f) => f.key === key)?.displayName ?? key;\n }\n\n goBack(): void {\n this.router.navigate(['/scim/providers']);\n }\n\n formatDate(dateString: string): string {\n return new Date(dateString).toLocaleString();\n }\n}\n","// SCIM Plugin\nexport { SCIM_PLUGIN, getScimNavItems } from './lib/scim.plugin';\nexport { SCIM_ROUTES } from './lib/scim.routes';\n\n// Models\nexport * from './lib/models/scim.model';\nexport * from './lib/models/scim-provider.model';\n\n// Services\nexport { ScimService } from './lib/services/scim.service';\n\n// Components\nexport { ScimClientsComponent } from './lib/pages/scim-clients/scim-clients.component';\nexport { ScimClientDetailComponent } from './lib/pages/scim-client-detail/scim-client-detail.component';\nexport { ScimMappingsComponent } from './lib/pages/scim-mappings/scim-mappings.component';\nexport { ScimProvidersComponent } from './lib/pages/scim-providers/scim-providers.component';\nexport { ScimProviderDetailComponent } from './lib/pages/scim-provider-detail/scim-provider-detail.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}