diff --git a/docs/en/UI/Angular/Account-Module.md b/docs/en/UI/Angular/Account-Module.md index 3670a14f73..1b6be08f16 100644 --- a/docs/en/UI/Angular/Account-Module.md +++ b/docs/en/UI/Angular/Account-Module.md @@ -95,6 +95,24 @@ export class AppRoutingModule {} Before v4.3, the "My account" link in the current user dropdown on the top bar redirected the user to MVC's profile management page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account module instead. +### Personal Info Page Confirm Message + +When the user changes their own data on the personal settings tab in My Account, The data can not update the CurrentUser key of Application-Configuration. The information of the user is stored in claims. The only way to apply this information to the CurrentUser of Application-Configuration is user should log out and log in. When the Refresh-Token feature is implemented, it will be fixed. So We've added a confirmation alert. + +If you want to disable these warning, You should set `isPersonalSettingsChangedConfirmationActive` false + +```js +// app-routing.module.ts +const routes: Routes = [ + //... + { + path: 'account', + loadChildren: () => import('@volo/abp.ng.account/public').then(m => m.AccountPublicModule.forLazy({ isPersonalSettingsChangedConfirmationActive:false })), + }, + //... +export class AppRoutingModule {} +``` + ### Security Logs Page [COMMERCIAL] Before v4.3, the "Security Logs" link in the current user dropdown on the top bar redirected the user to MVC's security logs page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account public module instead. diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json index 17f05fe29b..9dafae13f3 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json @@ -34,6 +34,8 @@ "DisplayName:PhoneNumber": "Phone number", "PersonalSettings": "Personal settings", "PersonalSettingsSaved": "Personal settings saved", + "PersonalSettingsChangedConfirmationModalTitle": "Personal info changed", + "PersonalSettingsChangedConfirmationModalDescription": "If you want to apply these changes, you have to login. Do you want to log out?", "PasswordChanged": "Password changed", "NewPasswordConfirmFailed": "Please confirm the new password.", "Manage": "Manage", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json index 6edaf2c1c4..d7d2454b6f 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json @@ -34,6 +34,8 @@ "DisplayName:PhoneNumber": "Telefon numarası", "PersonalSettings": "Kişisel ayarlar", "PersonalSettingsSaved": "Kişisel ayarlar kaydedildi", + "PersonalSettingsChangedConfirmationModalTitle": "Personal info changed", + "PersonalSettingsChangedConfirmationModalDescription": "If you want to apply these changes, you have to login. Do you want to log out?", "PasswordChanged": "Şifre değiştirildi", "NewPasswordConfirmFailed": "Lütfen yeni şifreyi onaylayın.", "Manage": "Manage", diff --git a/npm/ng-packs/packages/account/src/lib/account.module.ts b/npm/ng-packs/packages/account/src/lib/account.module.ts index bfa37d4bfa..d04f931a0f 100644 --- a/npm/ng-packs/packages/account/src/lib/account.module.ts +++ b/npm/ng-packs/packages/account/src/lib/account.module.ts @@ -15,6 +15,7 @@ import { accountConfigOptionsFactory } from './utils/factory-utils'; import { AuthenticationFlowGuard } from './guards/authentication-flow.guard'; import { ForgotPasswordComponent } from './components/forgot-password/forgot-password.component'; import { ResetPasswordComponent } from './components/reset-password/reset-password.component'; +import { RE_LOGIN_CONFIRMATION_TOKEN } from './tokens'; const declarations = [ LoginComponent, @@ -49,6 +50,10 @@ export class AccountModule { useFactory: accountConfigOptionsFactory, deps: [ACCOUNT_CONFIG_OPTIONS], }, + { + provide: RE_LOGIN_CONFIRMATION_TOKEN, + useValue: options.isPersonalSettingsChangedConfirmationActive ?? true, + }, ], }; } diff --git a/npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts b/npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts index d15df99878..ec75ab96ef 100644 --- a/npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts +++ b/npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts @@ -1,10 +1,12 @@ -import { ProfileService } from '@abp/ng.account.core/proxy'; -import { ToasterService } from '@abp/ng.theme.shared'; -import { Component, OnInit } from '@angular/core'; +import { ProfileDto, ProfileService } from '@abp/ng.account.core/proxy'; +import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared'; +import { Component, Inject, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { finalize } from 'rxjs/operators'; +import { finalize, filter } from 'rxjs/operators'; import { Account } from '../../models/account'; import { ManageProfileStateService } from '../../services/manage-profile.state.service'; +import { AuthService } from '@abp/ng.core'; +import { RE_LOGIN_CONFIRMATION_TOKEN } from '../../tokens'; const { maxLength, required, email } = Validators; @@ -22,12 +24,17 @@ export class PersonalSettingsComponent form: FormGroup; inProgress: boolean; + private profile: ProfileDto; constructor( private fb: FormBuilder, private toasterService: ToasterService, private profileService: ProfileService, private manageProfileState: ManageProfileStateService, + private readonly authService: AuthService, + private confirmationService: ConfirmationService, + @Inject(RE_LOGIN_CONFIRMATION_TOKEN) + private isPersonalSettingsChangedConfirmationActive: boolean, ) {} ngOnInit() { @@ -35,18 +42,19 @@ export class PersonalSettingsComponent } buildForm() { - const profile = this.manageProfileState.getProfile(); + this.profile = this.manageProfileState.getProfile(); this.form = this.fb.group({ - userName: [profile.userName, [required, maxLength(256)]], - email: [profile.email, [required, email, maxLength(256)]], - name: [profile.name || '', [maxLength(64)]], - surname: [profile.surname || '', [maxLength(64)]], - phoneNumber: [profile.phoneNumber || '', [maxLength(16)]], + userName: [this.profile.userName, [required, maxLength(256)]], + email: [this.profile.email, [required, email, maxLength(256)]], + name: [this.profile.name || '', [maxLength(64)]], + surname: [this.profile.surname || '', [maxLength(64)]], + phoneNumber: [this.profile.phoneNumber || '', [maxLength(16)]], }); } submit() { if (this.form.invalid) return; + const isLogOutConfirmMessageVisible = this.isLogoutConfirmMessageActive(); this.inProgress = true; this.profileService .update(this.form.value) @@ -54,6 +62,39 @@ export class PersonalSettingsComponent .subscribe(profile => { this.manageProfileState.setProfile(profile); this.toasterService.success('AbpAccount::PersonalSettingsSaved', 'Success', { life: 5000 }); + if (isLogOutConfirmMessageVisible) { + this.showLogoutConfirmMessage(); + } }); } + + isDataSame(oldValue, newValue) { + return Object.entries(oldValue).some(([key, value]) => { + if (key in newValue) { + return value !== newValue[key]; + } + return false; + }); + } + + logoutConfirmation = () => { + this.authService.logout().subscribe(); + }; + + private isLogoutConfirmMessageActive() { + if (!this.isPersonalSettingsChangedConfirmationActive) { + return false; + } + return this.isDataSame(this.profile, this.form.value); + } + + private showLogoutConfirmMessage() { + this.confirmationService + .info( + 'AbpAccount::PersonalSettingsChangedConfirmationModalDescription', + 'AbpAccount::PersonalSettingsChangedConfirmationModalTitle', + ) + .pipe(filter(status => status === Confirmation.Status.confirm)) + .subscribe(this.logoutConfirmation); + } } diff --git a/npm/ng-packs/packages/account/src/lib/models/config-options.ts b/npm/ng-packs/packages/account/src/lib/models/config-options.ts index 898021b04e..1f6a15641d 100644 --- a/npm/ng-packs/packages/account/src/lib/models/config-options.ts +++ b/npm/ng-packs/packages/account/src/lib/models/config-options.ts @@ -1,3 +1,4 @@ export interface AccountConfigOptions { redirectUrl?: string; + isPersonalSettingsChangedConfirmationActive?: boolean; } diff --git a/npm/ng-packs/packages/account/src/lib/tokens/index.ts b/npm/ng-packs/packages/account/src/lib/tokens/index.ts index 0a88318130..9e126a7a1f 100644 --- a/npm/ng-packs/packages/account/src/lib/tokens/index.ts +++ b/npm/ng-packs/packages/account/src/lib/tokens/index.ts @@ -1 +1,2 @@ export * from './config-options.token'; +export * from './re-login-confirmation.token'; diff --git a/npm/ng-packs/packages/account/src/lib/tokens/re-login-confirmation.token.ts b/npm/ng-packs/packages/account/src/lib/tokens/re-login-confirmation.token.ts new file mode 100644 index 0000000000..8ca5375bab --- /dev/null +++ b/npm/ng-packs/packages/account/src/lib/tokens/re-login-confirmation.token.ts @@ -0,0 +1,5 @@ +import { InjectionToken } from '@angular/core'; + +export const RE_LOGIN_CONFIRMATION_TOKEN = new InjectionToken( + 'RE_LOGIN_CONFIRMATION_TOKEN', +);