@c8y/login 1023.97.8 → 1024.0.0
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.
- package/jest.config.js +1 -1
- package/package.json +13 -12
- package/src/app/app.config.ts +2 -1
- package/src/app/login/credentials-from-query-params.service.ts +7 -6
- package/src/app/login/login.component.ts +1 -1
- package/src/app/login/login.service.ts +18 -22
- package/src/app/login/tenant-id-setup/tenant-id-setup.component.ts +4 -3
- /package/src/app/login/{login.component.less → login.component.scss} +0 -0
package/jest.config.js
CHANGED
|
@@ -14,5 +14,5 @@ module.exports = {
|
|
|
14
14
|
'../ngx-components/test/fail-on-console-error-configuration.ts'
|
|
15
15
|
],
|
|
16
16
|
testRunner: 'jest-jasmine2',
|
|
17
|
-
transformIgnorePatterns: ['/!node_modules\\/lodash-es/', 'node_modules/(
|
|
17
|
+
transformIgnorePatterns: ['/!node_modules\\/lodash-es/', 'node_modules/(?!gridstack|.*\\.mjs$)']
|
|
18
18
|
};
|
package/package.json
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c8y/login",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1024.0.0",
|
|
4
4
|
"description": "This package is used to scaffold a login application for Cumulocity IoT.",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@angular/animations": "^
|
|
7
|
-
"@angular/cdk": "^
|
|
8
|
-
"@c8y/bootstrap": "
|
|
9
|
-
"@c8y/client": "
|
|
10
|
-
"@c8y/ngx-components": "
|
|
11
|
-
"@c8y/style": "
|
|
6
|
+
"@angular/animations": "^21.2.0",
|
|
7
|
+
"@angular/cdk": "^21.2.0",
|
|
8
|
+
"@c8y/bootstrap": "1024.0.0",
|
|
9
|
+
"@c8y/client": "1024.0.0",
|
|
10
|
+
"@c8y/ngx-components": "1024.0.0",
|
|
11
|
+
"@c8y/style": "1024.0.0",
|
|
12
12
|
"monaco-editor": "~0.53.0",
|
|
13
|
-
"ngx-bootstrap": "
|
|
14
|
-
"rxjs": "7.8.2"
|
|
13
|
+
"ngx-bootstrap": "21.0.1",
|
|
14
|
+
"rxjs": "7.8.2",
|
|
15
|
+
"zone.js": "~0.15.1"
|
|
15
16
|
},
|
|
16
17
|
"devDependencies": {
|
|
17
|
-
"@c8y/devkit": "
|
|
18
|
-
"@c8y/options": "
|
|
18
|
+
"@c8y/devkit": "1024.0.0",
|
|
19
|
+
"@c8y/options": "1024.0.0"
|
|
19
20
|
},
|
|
20
21
|
"peerDependencies": {
|
|
21
|
-
"@angular/common": ">=
|
|
22
|
+
"@angular/common": ">=21 <22"
|
|
22
23
|
},
|
|
23
24
|
"author": "Cumulocity GmbH",
|
|
24
25
|
"license": "Apache-2.0"
|
package/src/app/app.config.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
|
|
1
|
+
import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core';
|
|
2
2
|
import { provideAnimations } from '@angular/platform-browser/animations';
|
|
3
3
|
import { CoreModule, RouterModule } from '@c8y/ngx-components';
|
|
4
4
|
|
|
5
5
|
export const appConfig: ApplicationConfig = {
|
|
6
6
|
providers: [
|
|
7
|
+
provideZoneChangeDetection(),
|
|
7
8
|
provideAnimations(),
|
|
8
9
|
importProvidersFrom(RouterModule.forRoot()),
|
|
9
10
|
importProvidersFrom(CoreModule.forRoot())
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
1
|
+
import { DOCUMENT, inject, Injectable } from '@angular/core';
|
|
2
2
|
import { ICredentials } from '@c8y/client';
|
|
3
3
|
|
|
4
4
|
@Injectable({ providedIn: 'root' })
|
|
5
5
|
export class CredentialsFromQueryParamsService {
|
|
6
6
|
private readonly queryParamsToHandle: Array<keyof ICredentials> = ['tenant', 'user'];
|
|
7
|
+
private readonly document = inject(DOCUMENT);
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Retrieves any subset of credentials provided via queryParams
|
|
@@ -12,14 +13,14 @@ export class CredentialsFromQueryParamsService {
|
|
|
12
13
|
getCredentialsFromQueryParams(): ICredentials {
|
|
13
14
|
const credentials: ICredentials = {};
|
|
14
15
|
try {
|
|
15
|
-
const params = new URLSearchParams(
|
|
16
|
+
const params = new URLSearchParams(this.document.location.search);
|
|
16
17
|
this.queryParamsToHandle.forEach(param => {
|
|
17
18
|
const value = this.getParameterFromQueryParams(params, param);
|
|
18
19
|
if (value) {
|
|
19
20
|
credentials[param] = value;
|
|
20
21
|
}
|
|
21
22
|
});
|
|
22
|
-
} catch
|
|
23
|
+
} catch {
|
|
23
24
|
// URLSearchParams probably not available in all browsers (https://caniuse.com/urlsearchparams)
|
|
24
25
|
}
|
|
25
26
|
return credentials;
|
|
@@ -32,15 +33,15 @@ export class CredentialsFromQueryParamsService {
|
|
|
32
33
|
*/
|
|
33
34
|
removeCredentialsFromQueryParams(): boolean {
|
|
34
35
|
try {
|
|
35
|
-
const params = new URLSearchParams(
|
|
36
|
+
const params = new URLSearchParams(this.document.location.search);
|
|
36
37
|
const hasRemovedAtLeastOneParam = this.queryParamsToHandle
|
|
37
38
|
.map(param => this.removeParameterFromQueryParameters(params, param))
|
|
38
39
|
.reduceRight((prev, curr) => prev || curr, false);
|
|
39
40
|
if (hasRemovedAtLeastOneParam) {
|
|
40
|
-
|
|
41
|
+
this.document.location.search = params.toString();
|
|
41
42
|
return true;
|
|
42
43
|
}
|
|
43
|
-
} catch
|
|
44
|
+
} catch {
|
|
44
45
|
// URLSearchParams probably not available in all browsers (https://caniuse.com/urlsearchparams)
|
|
45
46
|
}
|
|
46
47
|
return false;
|
|
@@ -33,7 +33,7 @@ import { MissingApplicationAccessComponent } from './missing-application-access/
|
|
|
33
33
|
@Component({
|
|
34
34
|
selector: 'c8y-login',
|
|
35
35
|
templateUrl: './login.component.html',
|
|
36
|
-
styleUrls: ['./login.component.
|
|
36
|
+
styleUrls: ['./login.component.scss'],
|
|
37
37
|
encapsulation: ViewEncapsulation.None,
|
|
38
38
|
standalone: true,
|
|
39
39
|
imports: [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { inject, Injectable } from '@angular/core';
|
|
1
|
+
import { DOCUMENT, inject, Injectable } from '@angular/core';
|
|
2
2
|
import {
|
|
3
3
|
ApplicationService,
|
|
4
4
|
BearerAuthFromSessionStorage,
|
|
@@ -22,13 +22,7 @@ import { BehaviorSubject, EMPTY } from 'rxjs';
|
|
|
22
22
|
import { isEmpty } from 'lodash-es';
|
|
23
23
|
import { TranslateService } from '@ngx-translate/core';
|
|
24
24
|
import { LoginEvent, SsoData } from './login.model';
|
|
25
|
-
import {
|
|
26
|
-
getStoredToken,
|
|
27
|
-
getStoredTfaToken,
|
|
28
|
-
TOKEN_KEY,
|
|
29
|
-
TFATOKEN_KEY,
|
|
30
|
-
isLocal
|
|
31
|
-
} from '@c8y/bootstrap';
|
|
25
|
+
import { getStoredToken, getStoredTfaToken, TOKEN_KEY, TFATOKEN_KEY } from '@c8y/bootstrap';
|
|
32
26
|
|
|
33
27
|
/**
|
|
34
28
|
* Service to manage the login.
|
|
@@ -102,6 +96,7 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
102
96
|
private tenantLoginOptionsService = inject(TenantLoginOptionsService);
|
|
103
97
|
private modalService = inject(ModalService);
|
|
104
98
|
private applicationService = inject(ApplicationService);
|
|
99
|
+
private document = inject(DOCUMENT);
|
|
105
100
|
|
|
106
101
|
constructor() {
|
|
107
102
|
super();
|
|
@@ -150,7 +145,7 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
150
145
|
redirectToOauth() {
|
|
151
146
|
const idpHint = this.getIdpHintFromQueryParams();
|
|
152
147
|
const { initRequest, flowControlledByUI } = this.oauthOptions;
|
|
153
|
-
const fullPath = `${
|
|
148
|
+
const fullPath = `${this.document.location.origin}${this.document.location.pathname}`;
|
|
154
149
|
const redirectUrl = encodeURIComponent(fullPath);
|
|
155
150
|
const originUriParam = `${initRequest.includes('?') ? '&' : '?'}originUri=${redirectUrl}`;
|
|
156
151
|
const urlObject = new URL(initRequest);
|
|
@@ -160,12 +155,12 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
160
155
|
.fetch(`/tenant/oauth${urlObject.search}${originUriParam}`)
|
|
161
156
|
.then(res => this.handleErrorStatusCodes(res))
|
|
162
157
|
.then(res => res.json())
|
|
163
|
-
.then((res: any) => (
|
|
158
|
+
.then((res: any) => (this.document.location.href = res.redirectTo))
|
|
164
159
|
.catch(ex => this.showSsoError(ex));
|
|
165
160
|
} else if (idpHint) {
|
|
166
|
-
|
|
161
|
+
this.document.location.href = `${initRequest}${originUriParam}&${this.IDP_HINT_QUERY_PARAM}=${idpHint}`;
|
|
167
162
|
} else {
|
|
168
|
-
|
|
163
|
+
this.document.location.href = `${initRequest}${originUriParam}`;
|
|
169
164
|
}
|
|
170
165
|
}
|
|
171
166
|
|
|
@@ -252,7 +247,7 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
252
247
|
const authStrategy = new BearerAuthFromSessionStorage();
|
|
253
248
|
console.log(`Using BearerAuthFromSessionStorage`);
|
|
254
249
|
return authStrategy;
|
|
255
|
-
} catch
|
|
250
|
+
} catch {
|
|
256
251
|
// do nothing
|
|
257
252
|
}
|
|
258
253
|
let authStrategy: IAuthentication = this.cookieAuth;
|
|
@@ -350,14 +345,14 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
350
345
|
const userHasAccessToApp =
|
|
351
346
|
// in case of local development we do not need to verify if the user has access to the app
|
|
352
347
|
// This way developers do not need to create the application in the tenant before developing
|
|
353
|
-
|
|
348
|
+
this.document.location.hostname === 'localhost' ||
|
|
354
349
|
(await this.userHasAccessToApp(user, redirectPath));
|
|
355
350
|
|
|
356
351
|
if (!userHasAccessToApp) {
|
|
357
352
|
return false;
|
|
358
353
|
}
|
|
359
354
|
|
|
360
|
-
|
|
355
|
+
this.document.location.href = redirectPath;
|
|
361
356
|
return true;
|
|
362
357
|
}
|
|
363
358
|
|
|
@@ -368,7 +363,7 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
368
363
|
if (redirectPathFromSessionStorage.includes('?')) {
|
|
369
364
|
const { hash, searchParams, pathname } = new URL(
|
|
370
365
|
redirectPathFromSessionStorage,
|
|
371
|
-
|
|
366
|
+
this.document.location.origin
|
|
372
367
|
);
|
|
373
368
|
for (const param of this.queryParamsToRemove) {
|
|
374
369
|
searchParams.delete(param);
|
|
@@ -406,7 +401,7 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
406
401
|
try {
|
|
407
402
|
await this.applicationService.getManifestOfContextPath(contextPathOfApp);
|
|
408
403
|
return redirectPath;
|
|
409
|
-
} catch
|
|
404
|
+
} catch {
|
|
410
405
|
return false;
|
|
411
406
|
}
|
|
412
407
|
}
|
|
@@ -535,9 +530,9 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
535
530
|
}
|
|
536
531
|
|
|
537
532
|
redirectToDomain(domain) {
|
|
538
|
-
const originUrl = new URL(
|
|
533
|
+
const originUrl = new URL(this.document.location.href);
|
|
539
534
|
const redirectUrl = originUrl.href.replace(originUrl.hostname, domain);
|
|
540
|
-
|
|
535
|
+
this.document.location.href = redirectUrl;
|
|
541
536
|
}
|
|
542
537
|
|
|
543
538
|
showSsoError(error): void {
|
|
@@ -610,7 +605,8 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
610
605
|
* Running on localhost means development mode.
|
|
611
606
|
*/
|
|
612
607
|
private isLocal(): boolean {
|
|
613
|
-
|
|
608
|
+
const hostname = this.document.location.hostname;
|
|
609
|
+
return /127\.0\.0\.1/.test(hostname) || /localhost/.test(hostname);
|
|
614
610
|
}
|
|
615
611
|
|
|
616
612
|
/**
|
|
@@ -630,7 +626,7 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
630
626
|
}
|
|
631
627
|
|
|
632
628
|
private isShowTenant(): boolean {
|
|
633
|
-
return this.showTenantRegExp.test(
|
|
629
|
+
return this.showTenantRegExp.test(this.document.location.href);
|
|
634
630
|
}
|
|
635
631
|
|
|
636
632
|
/**
|
|
@@ -710,7 +706,7 @@ export class LoginService extends SimplifiedAuthService {
|
|
|
710
706
|
}
|
|
711
707
|
|
|
712
708
|
private getIdpHintFromQueryParams(): string | null {
|
|
713
|
-
const params = new URLSearchParams(
|
|
709
|
+
const params = new URLSearchParams(this.document.location.search);
|
|
714
710
|
return params.get(this.IDP_HINT_QUERY_PARAM) || null;
|
|
715
711
|
}
|
|
716
712
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, Output, EventEmitter } from '@angular/core';
|
|
1
|
+
import { Component, DOCUMENT, Inject, Output, EventEmitter } from '@angular/core';
|
|
2
2
|
import { LoginEvent, LoginViews } from '../login.model';
|
|
3
3
|
import { FetchClient } from '@c8y/client';
|
|
4
4
|
import {
|
|
@@ -46,7 +46,8 @@ export class TenantIdSetupComponent {
|
|
|
46
46
|
private ui: AppStateService,
|
|
47
47
|
private loginService: LoginService,
|
|
48
48
|
private alert: AlertService,
|
|
49
|
-
private translateService: TranslateService
|
|
49
|
+
private translateService: TranslateService,
|
|
50
|
+
@Inject(DOCUMENT) private document: Document
|
|
50
51
|
) {}
|
|
51
52
|
|
|
52
53
|
/**
|
|
@@ -78,7 +79,7 @@ export class TenantIdSetupComponent {
|
|
|
78
79
|
redirectToCorrectDomain() {
|
|
79
80
|
const loginRedirectDomain = this.loginService.loginMode.loginRedirectDomain;
|
|
80
81
|
if (loginRedirectDomain) {
|
|
81
|
-
const alreadyOnCorrectDomain =
|
|
82
|
+
const alreadyOnCorrectDomain = this.document.location.href.includes(loginRedirectDomain);
|
|
82
83
|
if (!alreadyOnCorrectDomain) {
|
|
83
84
|
this.loginService.redirectToDomain(loginRedirectDomain);
|
|
84
85
|
} else {
|
|
File without changes
|