diff --git a/ui-ngx/src/app/core/http/user.service.ts b/ui-ngx/src/app/core/http/user.service.ts index 1d5ce28998..695bae3cc1 100644 --- a/ui-ngx/src/app/core/http/user.service.ts +++ b/ui-ngx/src/app/core/http/user.service.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; -import { User, UserEmailInfo } from '@shared/models/user.model'; +import { ActivationLinkInfo, User, UserEmailInfo } from '@shared/models/user.model'; import { Observable } from 'rxjs'; import { HttpClient, HttpParams } from '@angular/common/http'; import { PageLink } from '@shared/models/page/page-link'; @@ -77,6 +77,10 @@ export class UserService { {...{responseType: 'text'}, ...defaultHttpOptionsFromConfig(config)}); } + public getActivationLinkInfo(userId: string, config?: RequestConfig): Observable { + return this.http.get(`/api/user/${userId}/activationLinkInfo`, defaultHttpOptionsFromConfig(config)); + } + public sendActivationEmail(email: string, config?: RequestConfig) { const encodeEmail = encodeURIComponent(email); return this.http.post(`/api/user/sendActivationMail?email=${encodeEmail}`, null, defaultHttpOptionsFromConfig(config)); diff --git a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html index cabb688525..d03b50418d 100644 --- a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html @@ -30,7 +30,7 @@
- +
{{ activationLink }}
+ + +
diff --git a/ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss new file mode 100644 index 0000000000..323437e66b --- /dev/null +++ b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss @@ -0,0 +1,32 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@import '../../../../../scss/constants'; + +:host { + display: flex; + flex: 1 1 0; + .tb-expired-link-content { + background-color: #eee; + .tb-expired-link-card { + letter-spacing: 0.15px; + line-height: 24px; + padding: 24px; + @media #{$mat-gt-xs} { + width: 486px !important; + } + } + } +} diff --git a/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts new file mode 100644 index 0000000000..d394e426dd --- /dev/null +++ b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts @@ -0,0 +1,47 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { PageComponent } from '@shared/components/page.component'; +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + selector: 'tb-link-expired', + templateUrl: './link-expired.component.html', + styleUrls: ['./link-expired.component.scss'] +}) +export class LinkExpiredComponent extends PageComponent { + + isPasswordLinkExpired: boolean; + title: string; + message: string; + + constructor(protected store: Store, + private route: ActivatedRoute, + private router: Router) { + super(store); + this.isPasswordLinkExpired = this.route.snapshot.data.passwordLinkExpired; + this.title = this.isPasswordLinkExpired ? 'login.reset-password-link-expired' : 'login.activation-link-expired'; + this.message = this.isPasswordLinkExpired ? 'login.reset-password-link-expired-message' : + 'login.activation-link-expired-message'; + } + + navigateToLoginPage() { + this.router.navigateByUrl('login'); + } +} diff --git a/ui-ngx/src/app/shared/models/user.model.ts b/ui-ngx/src/app/shared/models/user.model.ts index 5b2cdec08b..a17cf040a8 100644 --- a/ui-ngx/src/app/shared/models/user.model.ts +++ b/ui-ngx/src/app/shared/models/user.model.ts @@ -44,6 +44,11 @@ export const activationMethodTranslations = new Map( ] ); +export interface ActivationLinkInfo { + value: string; + ttlMs: number; +} + export interface AuthUser { sub: string; scopes: string[]; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 24d2ab5511..204e44f7be 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4009,7 +4009,11 @@ "email-auth-description": "A security code has been sent to your email address at {{contact}}.", "email-auth-placeholder": "Email code", "backup-code-auth-description": "Please enter one of your backup codes.", - "backup-code-auth-placeholder": "Backup code" + "backup-code-auth-placeholder": "Backup code", + "activation-link-expired": "Activation link has expired", + "activation-link-expired-message": "The link to activate your profile has expired. You can return to the login page to receive a new email.", + "reset-password-link-expired": "Password reset link has expired", + "reset-password-link-expired-message": "The link to reset your password has expired. You can return to the login page to receive a new email." }, "markdown": { "edit": "Edit", @@ -5629,7 +5633,7 @@ "display-activation-link": "Display activation link", "send-activation-mail": "Send activation mail", "activation-link": "User activation link", - "activation-link-text": "In order to activate user use the following activation link :", + "activation-link-text": "In order to activate user use the following activation link (expires in {{activationLinkTtl}}) :", "copy-activation-link": "Copy activation link", "activation-link-copied-message": "User activation link has been copied to clipboard", "details": "Details",