Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
3ac1d96
feat(auth): migrate OAuth 2.0 / OIDC provider from plugin to core
swicken Apr 17, 2026
03152da
docs(auth): add dotAuth phase-2 design doc and implementation plan
swicken Apr 20, 2026
177c8f5
refactor(auth): rename AppSecrets key dotOAuth -> dotAuth
swicken Apr 20, 2026
f0602ce
chore(auth): remove dotOAuth apps YAML; portlet is the sole editor
swicken Apr 20, 2026
b48d00a
feat(auth): add dotAuth REST DTOs
swicken Apr 20, 2026
309aa67
feat(auth): add DotAuthResource REST endpoints
swicken Apr 20, 2026
c6b067b
feat(auth): wire /v1/dotauth into DotRestApplication
swicken Apr 20, 2026
9ed5876
feat(auth): register dotAuth portlet in portlet.xml
swicken Apr 20, 2026
6745059
feat(auth): add dotAuth i18n keys
swicken Apr 20, 2026
1674d6a
feat(dot-auth): scaffold Nx library libs/portlets/dot-auth
swicken Apr 20, 2026
808df65
feat(dot-auth): data-access service and models
swicken Apr 20, 2026
8c87444
feat(dot-auth): list SignalStore
swicken Apr 20, 2026
ce9d4a8
feat(dot-auth): list component, edit dialog, shell and routes
swicken Apr 20, 2026
9daa8c3
feat(dot-auth): register dotAuth route in app shell
swicken Apr 20, 2026
130a292
feat(dot-auth): add startup task to register dotAuth portlet in Setti…
swicken Apr 20, 2026
205a0eb
fix(dot-auth): rename p-inputSwitch to p-toggleswitch; apply lint aut…
swicken Apr 20, 2026
0a89ddc
fix(auth): lowercase host identifiers when looking up in appKeysByHos…
swicken Apr 20, 2026
379a44f
fix(auth): lowercase APP_KEY lookup in listSites; add temp /v1/dotaut…
swicken Apr 20, 2026
51fc0e0
docs(auth): add dotAuth phase-3 SAML integration design
swicken Apr 20, 2026
3aef4e1
docs(auth): add dotAuth phase-3 implementation plan
swicken Apr 20, 2026
31ce6cc
feat(auth): add DotAuthProtocol enum
swicken Apr 20, 2026
683f6cc
feat(auth): add ProtocolHandler strategy interface
swicken Apr 20, 2026
efe0966
refactor(auth): extract OAuthProtocolHandler from DotAuthResource
swicken Apr 20, 2026
3399f61
feat(auth): add SamlProtocolHandler with SAML_SECRET_KEYS
swicken Apr 20, 2026
a259643
feat(auth): add protocol field to DotAuth REST DTOs
swicken Apr 20, 2026
4bdb84a
chore(auth): update phase-3 tasks.json — tasks 0-4,6 complete
swicken Apr 21, 2026
12cd8b7
feat(auth): DotAuthResource dispatches on protocol; dual-key read/wri…
swicken Apr 21, 2026
0f4e5af
feat(dot-auth): widen models to discriminated union on protocol
swicken Apr 21, 2026
ff20890
feat(dot-auth): protocol column + composed status tag in list
swicken Apr 21, 2026
def81da
feat(dot-auth): protocol toggle + SAML fieldsets in edit dialog
swicken Apr 21, 2026
3055a22
feat(dot-auth): i18n keys for SAML protocol + fieldsets
swicken Apr 21, 2026
35aa006
test(dot-auth): SAML coverage for list component + storeAlso fix stor…
swicken Apr 21, 2026
ae691bd
test(dot-auth): SAML + protocol-switch coverage for edit component
swicken Apr 21, 2026
c6924c3
fix(auth): correct HostAPI import in DotAuthResourceTest
swicken Apr 21, 2026
5288d1b
fix(dot-auth): use TextareaModule + pTextarea; stabilize list/store s…
swicken Apr 21, 2026
01f881f
fix(dot-auth): drop unused store variable in list component spec
swicken Apr 21, 2026
5ca02a3
feat(dot-auth): SAML custom attributes + metadata download button
swicken Apr 21, 2026
31e8b0a
feat(dot-auth): widen edit dialog to min(96vw, 1040px) for SAML density
swicken Apr 21, 2026
75f4108
feat(dot-auth): redirect /apps/dotsaml-config to the dotAuth portlet
swicken Apr 21, 2026
0041d19
feat(dot-auth): hide dotsaml-config from the Apps grid
swicken Apr 21, 2026
7531f15
chore(auth): remove temp /v1/dotauth/debug endpoint
swicken Apr 21, 2026
c432637
chore(auth): finalize phase-3 tasks.json — all tasks complete
swicken Apr 21, 2026
c905a57
refactor(dot-auth): address PR review findings
swicken Apr 22, 2026
f146891
style(dot-auth): prettier-format shell template and route callback
swicken Apr 22, 2026
faee8ae
fix(oauth): harden OAuth/OIDC flow against PR-review security findings
swicken Apr 22, 2026
d2beb50
fix(dotauth): harden REST endpoints, startup task, and plugin path-co…
swicken Apr 22, 2026
cd68a70
refactor(dot-auth): align components with ANGULAR_STANDARDS
swicken Apr 22, 2026
9de4e9d
test(dot-auth): close PR-review coverage gaps in the dotAuth spec suite
swicken Apr 22, 2026
1538be5
chore(dot-auth): remove planning docs from PR scope
swicken Apr 22, 2026
76396c2
fix(oauth): tighten OIDC/OAuth flow against alg, mode, session, and V…
swicken Apr 22, 2026
5eed05b
fix(dotauth): save-first atomicity, case-insensitive SYSTEM_HOST, SAM…
swicken Apr 22, 2026
ca33e01
test(dotauth): normalize new backend tests to JUnit 5
swicken Apr 22, 2026
7eaae9b
fix(dot-auth): @for track order, loadSites recovery, edit-component e…
swicken Apr 22, 2026
ee34125
fix(dot-apps): scope import-success Subject and rename export-button …
swicken Apr 22, 2026
09262b3
feat(oauth): add BuildRolesStrategy and extract resolveOrProvisionUser
swicken Apr 23, 2026
4b45d7d
feat(oidc): expose validateIdTokenAndExtractClaims returning full cla…
swicken Apr 23, 2026
e30f5a6
feat(dotauth): add DotAuthSession model and cache for session-ref bea…
swicken Apr 23, 2026
bd774c0
feat(dotauth): add OAuth exchange endpoint and session-ref credential…
swicken Apr 23, 2026
00fb186
chore(justfile): add dev-run-headless recipes for oauth exchange flag
swicken Apr 23, 2026
34e287b
fix(dotauth): tighten OIDC iss check + stop leaking exception detail
swicken Apr 24, 2026
ee516c1
test(dotauth): cover the exchange guard paths, role-strategy, and OID…
swicken Apr 24, 2026
9d7b778
docs(dotauth): flag OAuth role-wipe default and logout-via-bearer tra…
swicken Apr 24, 2026
802ede3
fix(dotauth): close role-sync race and clampExpirationDays misconfig …
swicken Apr 24, 2026
12da3a3
fix(auth): address dotAuth review findings
swicken Apr 24, 2026
ae83275
fix(auth): address jsanca review feedback
swicken Apr 24, 2026
b05465c
fix(auth): avoid leaking OIDC validation details
swicken Apr 24, 2026
6a2c8a0
fix(oauth): sync JIT user profile names
swicken Apr 24, 2026
1433663
Hash OAuth user ids
swicken Apr 27, 2026
f9fa514
feat(dotauth): add OAuth role sync strategy option
swicken Apr 28, 2026
fd48d1e
proper error handling
swicken Apr 28, 2026
31bdfe8
make things required
swicken Apr 29, 2026
019288b
initial redesign commit
swicken Apr 29, 2026
bf63b5c
dotAuth UI redesign + headless security wiring
swicken Apr 30, 2026
9d9e815
refactor(dotauth): extract config into child components and clean up …
swicken Apr 30, 2026
1af9edd
chore(dotauth): remove legacy dot-auth-edit component
swicken Apr 30, 2026
a0a641b
fix(dotauth): wire SAML metadata fetch button with placeholder toast
swicken Apr 30, 2026
151ddaf
fix(dotauth): rename change outputs to fieldChange to avoid native ev…
swicken Apr 30, 2026
dfc36a5
fix(dotauth): save headless config when no SSO protocol is selected
swicken Apr 30, 2026
4aa9f1f
refactor(dotauth): separate headless config into own app key (system-…
swicken Apr 30, 2026
3d5ed74
refactor(dotauth): split SSO and headless into separate config pages
swicken Apr 30, 2026
0697fe8
fix(dotauth): update specs after dialog-to-routed-config refactor
swicken Apr 30, 2026
8a7354a
style(dotauth): apply formatter fixes from pre-commit hook
swicken Apr 30, 2026
6db8120
chore(dotauth): remove dead code, extract i18n, improve accessibility
swicken May 1, 2026
253e32a
chore(dotauth): refresh headless dev reload flow
swicken May 1, 2026
2f17e2d
feat(dotauth): handle unauthorized SSO users
swicken May 1, 2026
b5004fc
feat(dotauth): refine SSO configuration UI
swicken May 1, 2026
10377e8
feat(dotauth): add config bundle import export
swicken May 1, 2026
4be948a
fix(dotauth): harden export endpoint and fix i18n gaps
swicken May 1, 2026
346875a
fix(dotauth): replace per-call ObjectMapper with static singleton
swicken May 1, 2026
c4ce983
fix(dotauth): remove unused stats computed from list store
swicken May 1, 2026
f6eb438
fix(dotauth): surface URL validation rejections in standard logs
swicken May 1, 2026
c1d1b68
chore(dotauth): apply formatter whitespace cleanup
swicken May 1, 2026
8aca43c
fix(dotauth): eliminate SSRF DNS rebinding and require admin for sess…
swicken May 4, 2026
f9113fb
fix(dotauth): deduplicate auth utilities and harden config parsing
swicken May 4, 2026
ed62a4f
fix(dotauth): fix ConfirmationService crash, i18n gaps, and dead code
swicken May 4, 2026
f3da69b
fix(dotauth): auto-derive OAuth callback URL from request like SAML does
swicken May 4, 2026
2480815
fix(build): add missing <name> to docker imagesMap in child POM
swicken May 4, 2026
30c043d
fix(dotauth): add missing TOC i18n keys, fix ACS URL and section spacing
swicken May 4, 2026
c345eb5
chore(dotauth): apply auto-formatting and add structuredClone polyfill
swicken May 4, 2026
40091dc
test(dotauth): add mapper unit tests for config view/payload round-trip
swicken May 4, 2026
8a83617
fix(dotauth): map OIDC autoProvision from its own field instead of th…
swicken May 4, 2026
2a4e9ca
fix(dotauth): address code review findings across OAuth/OIDC layer
swicken May 4, 2026
187e586
refactor(dotauth): remove unused CORE_REST_PATHS OSGI conflict guard
swicken May 4, 2026
b9a6f07
fix(dotauth): add missing @ApiResponses and register session cache wi…
swicken May 4, 2026
6d11716
fix(dotauth): let non-OAuth logout requests fall through to LogoutRes…
swicken May 4, 2026
94e8db4
feat(dotauth): auto-generate SAML SP signing keypair on save
swicken May 4, 2026
0d82d16
feat(dotauth): add SAML metadata fetch and restructure IdP section
swicken May 4, 2026
5eb737a
refactor(dotauth): remove dead imports from DotAuthResource
swicken May 4, 2026
d3baf26
refactor(dotauth): use UtilMethods.isSet() for null/blank guards in D…
swicken May 4, 2026
f414fef
refactor(dotauth): promote SecureRandom to static field and use UtilM…
swicken May 4, 2026
d05f9b2
refactor(dotauth): use UtilMethods.isSet() for blank check in SamlPro…
swicken May 4, 2026
591fc29
refactor(dotauth): extract duplicate isInternalHost() SSRF guard to s…
swicken May 4, 2026
e50d838
ci: re-trigger PR checks after cancelled run
swicken May 5, 2026
c65c038
refactor(dotauth): extract SQL to static constants in startup task to…
swicken May 5, 2026
f4d1e74
fix(dotauth): align unit tests with listSites search() API and new po…
swicken May 5, 2026
4e6639e
fix(dotauth): enforce autoProvision, honor per-IdP config, fix logout…
swicken May 5, 2026
b6725f4
fix(dotauth): add SSRF guard to proxy endpoints, namespace users by i…
swicken May 5, 2026
48cb704
fix(dotauth): translate IdP role behavior, validate IdP issuer, conso…
swicken May 5, 2026
1ce3214
fix(dotauth): harden OIDC token validation — JWKS refresh, at_hash, n…
swicken May 5, 2026
6a52a7e
add to justfile
swicken May 6, 2026
e204b0a
fix SAML generation
swicken May 7, 2026
00c2817
undo launch.json change
swicken May 7, 2026
7717ad0
stuff
swicken May 8, 2026
2a3ac1f
fix(dotauth): deterministic protocol resolution, toast timing, save c…
swicken May 8, 2026
b93cc0a
fix(security): harden OAuth callback, response size limits, redirect …
swicken May 8, 2026
b425f68
Visual changes
swicken May 29, 2026
2a7fb89
fix(saml): gate only back-end SAML logins through the no-access role …
swicken Jun 3, 2026
8dcd594
fix(dotauth): address adversarial security review findings
swicken Jun 3, 2026
4349831
fix(dotauth): resolve merge-blocking review findings
swicken Jun 10, 2026
db33908
chore(dotauth): apply Tailwind v4 var-shorthand normalization from li…
swicken Jun 10, 2026
f94854b
fix(dotauth): fail closed on id_token replay fingerprint
swicken Jun 16, 2026
d34d32c
fix(dotauth): allow 60s clock skew on OIDC id_token exp check
swicken Jun 16, 2026
1bb0b50
chore(core-web): sync pnpm-lock after yarn→pnpm rebase
swicken Jun 18, 2026
956eb42
style(dot-auth): apply prettier formatting to two templates
swicken Jun 18, 2026
4749f7c
test(portal): bump expected portlet count to 55 for dotAuth portlet
swicken Jun 22, 2026
5e7b6c7
fix(dotauth): derive OAuth callback URL from request when not configured
swicken Jun 22, 2026
c8794e3
fix(dotauth): remove non-functional View audit log link from emergenc…
swicken Jun 22, 2026
a5a2642
fix(dotauth): return to originally-requested page after front-end OAu…
swicken Jun 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .mvn/maven-build-cache-config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ https://maven.apache.org/extensions/maven-build-cache-extension/maven-build-cach
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/BUILD-CACHE-CONFIG/1.0.0 https://maven.apache.org/xsd/build-cache-config-1.0.0.xsd">
<configuration>
<enabled>true</enabled>
<enabled>false</enabled>
<hashAlgorithm>SHA-256</hashAlgorithm>
<validateXml>true</validateXml>
<local>
Expand Down
8 changes: 8 additions & 0 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,14 @@
<version>0.9.1</version>
</dependency>

<!-- Nimbus JOSE+JWT: id_token JWKS signature verification for the OIDC flow. -->
<!-- jjwt 0.9.x only handles HMAC; nimbus adds RS256/ES256 + RemoteJWKSet. -->
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>9.37.4</version>
</dependency>

<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
Expand Down
7 changes: 7 additions & 0 deletions core-web/apps/dotcms-ui/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,13 @@ const PORTLETS_ANGULAR: Route[] = [
loadChildren: () =>
import('@dotcms/portlets/dot-es-search/portlet').then((m) => m.dotEsSearchRoutes)
},
{
path: 'dotAuth',
canActivate: [MenuGuardService],
canActivateChild: [MenuGuardService],
data: { reuseRoute: false },
loadChildren: () => import('@dotcms/portlets/dot-auth/portlet').then((m) => m.dotAuthRoutes)
},
{
path: 'tags',
canActivate: [MenuGuardService],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ const initialState: DotAppsImportExportDialogState = {
errorMessage: null
};

// Subject to emit when import succeeds
const importSuccessSubject = new Subject<void>();

export const DotAppsImportExportDialogStore = signalStore(
{ providedIn: 'root' },
withState(initialState),
Expand All @@ -63,12 +60,14 @@ export const DotAppsImportExportDialogStore = signalStore(
return '';
})
})),
withProps(() => ({
/**
* Observable that emits when import succeeds
*/
importSuccess$: importSuccessSubject.asObservable()
})),
withProps(() => {
const importSuccessSubject = new Subject<void>();

return {
_importSuccessSubject: importSuccessSubject,
importSuccess$: importSuccessSubject.asObservable()
};
}),
withMethods((store) => {
const dotAppsService = inject(DotAppsService);
const dotMessageService = inject(DotMessageService);
Expand All @@ -77,7 +76,7 @@ export const DotAppsImportExportDialogStore = signalStore(
/**
* Open the export dialog
*/
openExport: (app: DotApp, site?: DotAppsSite) => {
openExport: (app: DotApp | null, site?: DotAppsSite) => {
patchState(store, {
visible: true,
action: dialogAction.EXPORT,
Expand Down Expand Up @@ -185,7 +184,7 @@ export const DotAppsImportExportDialogStore = signalStore(
next: (status: string) => {
if (status !== '400') {
patchState(store, initialState);
importSuccessSubject.next();
store._importSuccessSubject.next();
} else {
patchState(store, {
status: ComponentStatus.ERROR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<button
(click)="openExportDialog()"
[label]="'apps.confirmation.export.all.button' | dm"
[disabled]="!isExportButtonDisabled()"
[disabled]="!hasExportableApps()"
class="dot-apps-configuration__action_export_button"
pButton
link
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ describe('DotAppsListComponent', () => {
describe('Export Button State', () => {
it('should enable export button when apps have configurations', () => {
// appsResponse has one app with configurationsCount: 1
expect(spectator.component.isExportButtonDisabled()).toBe(true);
expect(spectator.component.hasExportableApps()).toBe(true);
});

it('should disable export button when no apps have configurations', () => {
Expand All @@ -133,7 +133,32 @@ describe('DotAppsListComponent', () => {
spectator.component.reloadAppsData();
spectator.detectChanges();

expect(spectator.component.isExportButtonDisabled()).toBe(false);
expect(spectator.component.hasExportableApps()).toBe(false);
});

it('should enable export when only hidden SAML app has configurations', () => {
const appsWithOnlyHiddenConfig: DotApp[] = [
{ ...appsResponse[0], configurationsCount: 0 },
{ ...appsResponse[1], configurationsCount: 0 },
{
allowExtraParams: true,
configurationsCount: 1,
key: 'dotsaml-config',
name: 'SAML',
description: 'SAML config'
}
];
mockDotAppsService.get.mockReturnValue(of(appsWithOnlyHiddenConfig));

spectator.component.reloadAppsData();
spectator.detectChanges();

expect(spectator.component.hasExportableApps()).toBe(true);
expect(
spectator.component.state
.displayedApps()
.some((app) => app.key === 'dotsaml-config')
).toBe(false);
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { patchState, signalState } from '@ngrx/signals';
import { fromEvent as observableFromEvent } from 'rxjs';

import { Component, DestroyRef, ElementRef, AfterViewInit, inject, viewChild } from '@angular/core';
import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
DestroyRef,
ElementRef,
inject,
viewChild
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router';

Expand All @@ -25,6 +33,16 @@ interface DotAppsListState {
displayedApps: DotApp[];
}

/**
* App keys whose config is edited through a dedicated portlet rather than the
* generic Apps UI. The cards are hidden from the grid; navigation to
* `/apps/<key>` is separately redirected by {@link dotAppsSamlRedirectGuard}.
*/
const HIDDEN_APP_KEYS: ReadonlySet<string> = new Set(['dotsaml-config']);

const withoutHiddenApps = (apps: DotApp[]): DotApp[] =>
apps.filter((app) => !HIDDEN_APP_KEYS.has(app.key));

@Component({
selector: 'dot-apps-list',
templateUrl: './dot-apps-list.component.html',
Expand All @@ -36,7 +54,8 @@ interface DotAppsListState {
DotAppsImportExportDialogComponent,
DotPortletBaseComponent,
DotMessagePipe
]
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DotAppsListComponent implements AfterViewInit {
readonly #route = inject(ActivatedRoute);
Expand Down Expand Up @@ -88,15 +107,16 @@ export class DotAppsListComponent implements AfterViewInit {
* Opens the Export dialog for all configurations
*/
openExportDialog(): void {
// For export all, we don't pass an app - the store handles this
this.#dialogStore.openExport(null as unknown as DotApp);
// For export all, we don't pass an app the store handles null to mean "all apps".
this.#dialogStore.openExport(null);
}

/**
* Checks if export button is disabled based on existing configurations
* True when at least one app has a saved configuration — the export button is
* enabled only in that case.
*/
isExportButtonDisabled(): boolean {
return this.state.allApps().filter((app: DotApp) => app.configurationsCount).length > 0;
hasExportableApps(): boolean {
return this.state.allApps().some((app: DotApp) => !!app.configurationsCount);
}

/**
Expand All @@ -114,7 +134,7 @@ export class DotAppsListComponent implements AfterViewInit {
private initAppsState(apps: DotApp[]): void {
patchState(this.state, {
allApps: apps,
displayedApps: apps
displayedApps: withoutHiddenApps(apps)
});

this.attachFilterEvents();
Expand All @@ -134,10 +154,13 @@ export class DotAppsListComponent implements AfterViewInit {
}

private filterApps(searchCriteria?: string): void {
this.#dotAppsService.get(searchCriteria).subscribe((apps: DotApp[]) => {
patchState(this.state, {
displayedApps: apps
this.#dotAppsService
.get(searchCriteria)
.pipe(take(1), takeUntilDestroyed(this.#destroyRef))
.subscribe((apps: DotApp[]) => {
patchState(this.state, {
displayedApps: withoutHiddenApps(apps)
});
});
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { DotAiConfigDetailComponent } from './components/dot-ai-config-detail/do
import { DotAppsConfigurationComponent } from './components/dot-apps-configuration/dot-apps-configuration.component';
import { DotAppsConfigurationDetailComponent } from './components/dot-apps-configuration-detail/dot-apps-configuration-detail.component';
import { DotAppsListComponent } from './dot-apps-list/dot-apps-list.component';
import { dotAppsSamlRedirectGuard } from './guards/dot-apps-saml-redirect.guard';
import { DotAppsConfigurationDetailResolver } from './services/dot-apps-configuration-detail-resolver/dot-apps-configuration-detail-resolver.service';
import { DotAppsConfigurationResolver } from './services/dot-apps-configuration-resolver/dot-apps-configuration-resolver.service';
import { DotAppsListResolver } from './services/dot-apps-list-resolver/dot-apps-list-resolver.service';
Expand All @@ -31,6 +32,7 @@ export const dotAppsRoutes: Routes = [
{
component: DotAppsConfigurationDetailComponent,
path: ':appKey/create/:id',
canActivate: [dotAppsSamlRedirectGuard],
resolve: {
data: DotAppsConfigurationDetailResolver
},
Expand All @@ -39,6 +41,7 @@ export const dotAppsRoutes: Routes = [
{
component: DotAppsConfigurationDetailComponent,
path: ':appKey/edit/:id',
canActivate: [dotAppsSamlRedirectGuard],
resolve: {
data: DotAppsConfigurationDetailResolver
},
Expand All @@ -47,6 +50,7 @@ export const dotAppsRoutes: Routes = [
{
component: DotAppsConfigurationComponent,
path: ':appKey',
canActivate: [dotAppsSamlRedirectGuard],
resolve: {
data: DotAppsConfigurationResolver
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { inject } from '@angular/core';
import { CanActivateFn, Router, UrlTree } from '@angular/router';

/** AppSecrets key for SAML, mirrors `DotSamlProxyFactory.SAML_APP_CONFIG_KEY`. */
const SAML_APP_KEY = 'dotsaml-config';

/** Shell path of the dotAuth portlet, registered in `app.routes.ts`. */
const DOT_AUTH_PATH = '/dotAuth';

/**
* Guards the `/apps/:appKey` routes (list, create, edit): if a user lands on
* a SAML path — typically from a bookmark or an old docs link — route them to
* the dotAuth portlet, which is the sole editor for SAML config since phase-3.
*
* `dotsaml-config.yml` is kept in place so the SAML runtime's Apps descriptor
* lookup keeps working; the redirect only affects user navigation.
*/
export const dotAppsSamlRedirectGuard: CanActivateFn = (route): boolean | UrlTree => {
const appKey = route.paramMap.get('appKey');
if (appKey === SAML_APP_KEY) {
return inject(Router).parseUrl(DOT_AUTH_PATH);
}
return true;
};
1 change: 1 addition & 0 deletions core-web/libs/data-access/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './lib/add-to-bundle/add-to-bundle.service';
export * from './lib/can-deactivate/can-deactivate-guard.service';
export * from './lib/dot-ai/dot-ai.service';
export * from './lib/dot-alert-confirm/dot-alert-confirm.service';
export * from './lib/dot-auth/dot-auth.service';
export * from './lib/dot-analytics-search/dot-analytics-search.service';
export * from './lib/dot-analytics-tracker/dot-analytics-tracker.service';
export * from './lib/dot-apps/dot-apps.service';
Expand Down
Loading
Loading