@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 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/(?!.*\\.mjs$)']
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": "1023.97.8",
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": "^20.3.24",
7
- "@angular/cdk": "^20.2.14",
8
- "@c8y/bootstrap": "1023.97.8",
9
- "@c8y/client": "1023.97.8",
10
- "@c8y/ngx-components": "1023.97.8",
11
- "@c8y/style": "1023.97.8",
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": "20.0.2",
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": "1023.97.8",
18
- "@c8y/options": "1023.97.8"
18
+ "@c8y/devkit": "1024.0.0",
19
+ "@c8y/options": "1024.0.0"
19
20
  },
20
21
  "peerDependencies": {
21
- "@angular/common": ">=20 <21"
22
+ "@angular/common": ">=21 <22"
22
23
  },
23
24
  "author": "Cumulocity GmbH",
24
25
  "license": "Apache-2.0"
@@ -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(window.location.search);
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 (e) {
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(window.location.search);
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
- window.location.search = params.toString();
41
+ this.document.location.search = params.toString();
41
42
  return true;
42
43
  }
43
- } catch (e) {
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.less'],
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 = `${window.location.origin}${window.location.pathname}`;
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) => (window.location.href = res.redirectTo))
158
+ .then((res: any) => (this.document.location.href = res.redirectTo))
164
159
  .catch(ex => this.showSsoError(ex));
165
160
  } else if (idpHint) {
166
- window.location.href = `${initRequest}${originUriParam}&${this.IDP_HINT_QUERY_PARAM}=${idpHint}`;
161
+ this.document.location.href = `${initRequest}${originUriParam}&${this.IDP_HINT_QUERY_PARAM}=${idpHint}`;
167
162
  } else {
168
- window.location.href = `${initRequest}${originUriParam}`;
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 (e) {
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
- window.location.hostname === 'localhost' ||
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
- window.location.href = redirectPath;
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
- window.location.origin
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 (e) {
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(window.location.href);
533
+ const originUrl = new URL(this.document.location.href);
539
534
  const redirectUrl = originUrl.href.replace(originUrl.hostname, domain);
540
- window.location.href = redirectUrl;
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
- return isLocal();
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(window.location.href);
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(window.location.search);
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 = window.location.href.includes(loginRedirectDomain);
82
+ const alreadyOnCorrectDomain = this.document.location.href.includes(loginRedirectDomain);
82
83
  if (!alreadyOnCorrectDomain) {
83
84
  this.loginService.redirectToDomain(loginRedirectDomain);
84
85
  } else {