diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index cb6986f7..c4bdd9cd 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -24,16 +24,7 @@ export class AppComponent implements OnInit, OnDestroy {
private readonly router: Router
) {}
- ngOnInit(): void {
- this.authService
- .getCurrentUser()
- .pipe(untilDestroyed(this))
- .subscribe((user) => {
- if (user != null) {
- this.isAuthenticated = true;
- }
- });
- }
+ ngOnInit(): void {}
ngOnDestroy(): void {}
}
diff --git a/src/app/components/admin-navbar/admin-navbar.component.ts b/src/app/components/admin-navbar/admin-navbar.component.ts
index 883f34d9..b1016efb 100644
--- a/src/app/components/admin-navbar/admin-navbar.component.ts
+++ b/src/app/components/admin-navbar/admin-navbar.component.ts
@@ -94,8 +94,16 @@ export class AdminNavbarComponent {
title: "Инструменты",
links: [
{
- title: "Хз как назвать",
- url: "/admin/background-jobs",
+ title: "Общее",
+ url: "/admin/tools/background-jobs",
+ },
+ {
+ title: "Курсы валют",
+ url: "/admin/tools/currencies",
+ },
+ {
+ title: "QR код",
+ url: "/admin/tools/generate-qr",
},
],
},
diff --git a/src/app/components/navbar/navbar.component.ts b/src/app/components/navbar/navbar.component.ts
index 12f3236b..14592576 100644
--- a/src/app/components/navbar/navbar.component.ts
+++ b/src/app/components/navbar/navbar.component.ts
@@ -37,35 +37,20 @@ export class NavbarComponent implements OnInit, OnDestroy {
constructor(
private readonly authService: AuthService,
- private readonly spinner: SpinnerService,
- private readonly healthService: HealthCheckService
+ private readonly spinner: SpinnerService
) {}
ngOnInit(): void {
this.setupSubscribers();
- this.authService
- .getCurrentUser()
- //.pipe(untilDestroyed(this))
- .subscribe((currentUser) => {
- if (currentUser != null) {
- this.currentUser = currentUser;
- }
+ this.loginButtonAvailable = true;
+ this.authService
+ .getCurrentUserFromStorage()
+ .pipe(untilDestroyed(this))
+ .subscribe((user) => {
+ this.currentUser = user;
this.renderNavbar();
});
-
- this.healthService
- .appHealth()
- .pipe(untilDestroyed(this))
- .subscribe(
- (result) => {
- this.loginButtonAvailable = true;
- },
- (err) => {
- console.error(err);
- this.healthCheckError = true;
- }
- );
}
private setupSubscribers(): void {
diff --git a/src/app/models/application-user.ts b/src/app/models/application-user.ts
index b2f184ff..82b7d536 100644
--- a/src/app/models/application-user.ts
+++ b/src/app/models/application-user.ts
@@ -10,6 +10,7 @@ export interface ApplicationUser {
salariesCount: number;
emailConfirmed: boolean;
identityId: number | null;
+ isMfaEnabled: boolean;
deletedAt: Date | null;
createdAt: Date;
updatedAt: Date;
diff --git a/src/app/models/extended/application-user-extended.ts b/src/app/models/extended/application-user-extended.ts
index f63735a3..893d1350 100644
--- a/src/app/models/extended/application-user-extended.ts
+++ b/src/app/models/extended/application-user-extended.ts
@@ -58,6 +58,10 @@ export class ApplicationUserExtended implements ApplicationUser {
return this.instance.roles;
}
+ get isMfaEnabled(): boolean {
+ return this.instance.isMfaEnabled;
+ }
+
constructor(public readonly instance: ApplicationUser) {
Assertion.notNull(instance, "instance", ApplicationUserExtended.name);
diff --git a/src/app/modules/admin/admin-routing.module.ts b/src/app/modules/admin/admin-routing.module.ts
index af29c419..253b951f 100644
--- a/src/app/modules/admin/admin-routing.module.ts
+++ b/src/app/modules/admin/admin-routing.module.ts
@@ -13,6 +13,8 @@ import { TelegramBotUsagesComponent } from "./components/telegram/telegram-bot-u
import { TelegramUserSettingsComponent } from "./components/telegram/telegram-user-settings/telegram-user-settings.component";
import { SourcedSalariesAdminPageComponent } from "./components/salaries/sourced-salaries-admin-page/sourced-salaries-admin-page.component";
import { StatDataCacheRecordsComponent } from "./components/telegram/stat-data-change-subscriptions/stat-data-cache-records.component";
+import { CurrenciesPageComponent } from "./components/currencies-page/currencies-page.component";
+import { GenerateQrPageComponent } from "./components/generate-qr-code-page/generate-qr-page.component";
const routes: Routes = [
{ path: "", component: AdminStartPageComponent },
@@ -21,7 +23,6 @@ const routes: Routes = [
path: "interview-templates",
component: InterviewTemplatesAdminPageComponent,
},
- { path: "background-jobs", component: BackgroundJobsComponent },
{ path: "skills", component: SkillsPaginatedTableComponent },
{ path: "work-industries", component: WorkIndustriesPaginatedTableComponent },
{ path: "professions", component: ProfessionsPaginatedTableComponent },
@@ -40,6 +41,10 @@ const routes: Routes = [
path: "telegram/stat-data-change-subscriptions",
component: StatDataCacheRecordsComponent,
},
+
+ { path: "tools/background-jobs", component: BackgroundJobsComponent },
+ { path: "tools/currencies", component: CurrenciesPageComponent },
+ { path: "tools/generate-qr", component: GenerateQrPageComponent },
];
@NgModule({
diff --git a/src/app/modules/admin/admin.module.ts b/src/app/modules/admin/admin.module.ts
index a7768ee0..beb21a9b 100644
--- a/src/app/modules/admin/admin.module.ts
+++ b/src/app/modules/admin/admin.module.ts
@@ -20,6 +20,8 @@ import { TelegramBotUsagesComponent } from "./components/telegram/telegram-bot-u
import { TelegramUserSettingsComponent } from "./components/telegram/telegram-user-settings/telegram-user-settings.component";
import { SourcedSalariesAdminPageComponent } from "./components/salaries/sourced-salaries-admin-page/sourced-salaries-admin-page.component";
import { StatDataCacheRecordsComponent } from "./components/telegram/stat-data-change-subscriptions/stat-data-cache-records.component";
+import { GenerateQrPageComponent } from "./components/generate-qr-code-page/generate-qr-page.component";
+import { CurrenciesPageComponent } from "./components/currencies-page/currencies-page.component";
@NgModule({
declarations: [
@@ -39,6 +41,8 @@ import { StatDataCacheRecordsComponent } from "./components/telegram/stat-data-c
TelegramBotUsagesComponent,
TelegramUserSettingsComponent,
StatDataCacheRecordsComponent,
+ CurrenciesPageComponent,
+ GenerateQrPageComponent,
],
imports: [
CommonModule,
diff --git a/src/app/modules/admin/components/background-jobs/background-jobs.component.html b/src/app/modules/admin/components/background-jobs/background-jobs.component.html
index 99d2f385..3ee4fea7 100644
--- a/src/app/modules/admin/components/background-jobs/background-jobs.component.html
+++ b/src/app/modules/admin/components/background-jobs/background-jobs.component.html
@@ -10,25 +10,6 @@
>
-
-
-
-
- | Валюта |
- Курс |
- Дата |
-
-
-
-
- | {{ item.currencyString }} |
- {{ item.value }} kzt |
- {{ item.pubDate | date : "yyyy-MM-dd" }} |
-
-
-
-
-
Конфиги
{{ configs }}
diff --git a/src/app/modules/admin/components/background-jobs/background-jobs.component.ts b/src/app/modules/admin/components/background-jobs/background-jobs.component.ts
index 161403ef..a808cb60 100644
--- a/src/app/modules/admin/components/background-jobs/background-jobs.component.ts
+++ b/src/app/modules/admin/components/background-jobs/background-jobs.component.ts
@@ -5,7 +5,6 @@ import { AuthService } from "@shared/services/auth/auth.service";
import { HealthCheckItem } from "../health-check-table/health-check-item";
import { AdminToolsService } from "@services/admin-tools.service";
import { untilDestroyed } from "@shared/subscriptions/until-destroyed";
-import { CurrencyItem } from "./currency-item";
@Component({
selector: "app-background-jobs",
@@ -16,7 +15,6 @@ export class BackgroundJobsComponent implements OnInit, OnDestroy {
authorizationToken: string | null = null;
configs: string | null = null;
healthCheckItems: Array
= [];
- currencies: Array = [];
constructor(
private readonly authService: AuthService,
@@ -38,13 +36,6 @@ export class BackgroundJobsComponent implements OnInit, OnDestroy {
this.checkHealth();
- this.adminToolsService
- .getCurrencies()
- .pipe(untilDestroyed(this))
- .subscribe((currencies) => {
- this.currencies = currencies.map((x) => new CurrencyItem(x));
- });
-
this.adminToolsService
.getConfigs()
.pipe(untilDestroyed(this))
diff --git a/src/app/modules/admin/components/currencies-page/currencies-page.component.html b/src/app/modules/admin/components/currencies-page/currencies-page.component.html
new file mode 100644
index 00000000..8e3d2ce6
--- /dev/null
+++ b/src/app/modules/admin/components/currencies-page/currencies-page.component.html
@@ -0,0 +1,26 @@
+Курсы валюты
+
+
+
+
+
+
+
+
+ | Валюта |
+ Курс |
+ Дата |
+
+
+
+
+ | {{ item.currencyString }} |
+ {{ item.value }} kzt |
+ {{ item.pubDate | date : "yyyy-MM-dd" }} |
+
+
+
+
+
+
+
diff --git a/src/app/modules/admin/components/currencies-page/currencies-page.component.scss b/src/app/modules/admin/components/currencies-page/currencies-page.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/modules/admin/components/currencies-page/currencies-page.component.spec.ts b/src/app/modules/admin/components/currencies-page/currencies-page.component.spec.ts
new file mode 100644
index 00000000..e562c8c4
--- /dev/null
+++ b/src/app/modules/admin/components/currencies-page/currencies-page.component.spec.ts
@@ -0,0 +1,34 @@
+import { ComponentFixture, TestBed } from "@angular/core/testing";
+import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
+import {
+ mostUsedImports,
+ mostUsedServices,
+ testUtilStubs,
+} from "@shared/test-utils";
+
+import { AdminToolsService } from "@services/admin-tools.service";
+import { CurrenciesPageComponent } from "./currencies-page.component";
+
+describe("CurrenciesPageComponent", () => {
+ let component: CurrenciesPageComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [CurrenciesPageComponent],
+ imports: [...mostUsedImports],
+ providers: [...testUtilStubs, ...mostUsedServices, AdminToolsService],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ }).compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CurrenciesPageComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should create", () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/modules/admin/components/currencies-page/currencies-page.component.ts b/src/app/modules/admin/components/currencies-page/currencies-page.component.ts
new file mode 100644
index 00000000..b4afa230
--- /dev/null
+++ b/src/app/modules/admin/components/currencies-page/currencies-page.component.ts
@@ -0,0 +1,37 @@
+import { Component, OnDestroy, OnInit } from "@angular/core";
+import { TitleService } from "@services/title.service";
+import { HealthCheckItem } from "../health-check-table/health-check-item";
+import { AdminToolsService } from "@services/admin-tools.service";
+import { untilDestroyed } from "@shared/subscriptions/until-destroyed";
+import { CurrencyItem } from "./currency-item";
+
+@Component({
+ templateUrl: "./currencies-page.component.html",
+ styleUrls: ["./currencies-page.component.scss"],
+})
+export class CurrenciesPageComponent implements OnInit, OnDestroy {
+ authorizationToken: string | null = null;
+ configs: string | null = null;
+ healthCheckItems: Array = [];
+ currencies: Array = [];
+
+ constructor(
+ private readonly titleService: TitleService,
+ private readonly adminToolsService: AdminToolsService
+ ) {
+ this.titleService.setTitle("Курсы валют");
+ }
+
+ ngOnInit(): void {
+ this.adminToolsService
+ .getCurrencies()
+ .pipe(untilDestroyed(this))
+ .subscribe((currencies) => {
+ this.currencies = currencies.map((x) => new CurrencyItem(x));
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.titleService.resetTitle();
+ }
+}
diff --git a/src/app/modules/admin/components/background-jobs/currency-item.ts b/src/app/modules/admin/components/currencies-page/currency-item.ts
similarity index 100%
rename from src/app/modules/admin/components/background-jobs/currency-item.ts
rename to src/app/modules/admin/components/currencies-page/currency-item.ts
diff --git a/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.html b/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.html
new file mode 100644
index 00000000..d22fcfbb
--- /dev/null
+++ b/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.html
@@ -0,0 +1,36 @@
+QR код
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![QR code]()
+
+
+
diff --git a/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.scss b/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.spec.ts b/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.spec.ts
new file mode 100644
index 00000000..ba404c60
--- /dev/null
+++ b/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.spec.ts
@@ -0,0 +1,34 @@
+import { ComponentFixture, TestBed } from "@angular/core/testing";
+import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
+import {
+ mostUsedImports,
+ mostUsedServices,
+ testUtilStubs,
+} from "@shared/test-utils";
+
+import { AdminToolsService } from "@services/admin-tools.service";
+import { GenerateQrPageComponent } from "./generate-qr-page.component";
+
+describe("GenerateQrPageComponent", () => {
+ let component: GenerateQrPageComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [GenerateQrPageComponent],
+ imports: [...mostUsedImports],
+ providers: [...testUtilStubs, ...mostUsedServices, AdminToolsService],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ }).compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(GenerateQrPageComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should create", () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.ts b/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.ts
new file mode 100644
index 00000000..75c3bad5
--- /dev/null
+++ b/src/app/modules/admin/components/generate-qr-code-page/generate-qr-page.component.ts
@@ -0,0 +1,44 @@
+import { Component, OnDestroy } from "@angular/core";
+import { TitleService } from "@services/title.service";
+import { AdminToolsService } from "@services/admin-tools.service";
+import { untilDestroyed } from "@shared/subscriptions/until-destroyed";
+
+@Component({
+ templateUrl: "./generate-qr-page.component.html",
+ styleUrls: ["./generate-qr-page.component.scss"],
+})
+export class GenerateQrPageComponent implements OnDestroy {
+ shoQrCodeDialog = false;
+ qrCodeSource: string | null = null;
+ generatedQRBase64: string | null = null;
+
+ constructor(
+ private readonly titleService: TitleService,
+ private readonly adminToolsService: AdminToolsService
+ ) {
+ this.titleService.setTitle("Генерация QR-кода");
+ }
+
+ generateQrCode(): void {
+ if (this.qrCodeSource == null) {
+ return;
+ }
+
+ this.adminToolsService
+ .generateQR(this.qrCodeSource)
+ .pipe(untilDestroyed(this))
+ .subscribe((r) => {
+ this.generatedQRBase64 = "data:image/jpg;base64," + r.imageBase64;
+ this.shoQrCodeDialog = true;
+ });
+ }
+
+ onQrModalDlgClose(): void {
+ this.shoQrCodeDialog = false;
+ this.generatedQRBase64 = null;
+ }
+
+ ngOnDestroy(): void {
+ this.titleService.resetTitle();
+ }
+}
diff --git a/src/app/modules/home/components/auth-callback/auth-callback.component.html b/src/app/modules/home/components/auth-callback/auth-callback.component.html
index 653fb18b..358667de 100644
--- a/src/app/modules/home/components/auth-callback/auth-callback.component.html
+++ b/src/app/modules/home/components/auth-callback/auth-callback.component.html
@@ -1,16 +1,41 @@
-
-
+
+
-
- Oops, there was an error, please try to login again.
+
+ Произошла ошибка. Попробуйте позднее.
-
-
-
-
-
-
Please wait for a while...
-
We are preparing some awesome features for you
+
+
Добро пожаловать
+
Загружаем данные
+
+
+
+
+
+
Введите код MFA (TOTP)
+
+
+
+
+
+
+
+
+
diff --git a/src/app/modules/home/components/auth-callback/auth-callback.component.ts b/src/app/modules/home/components/auth-callback/auth-callback.component.ts
index cb930036..0b0daddd 100644
--- a/src/app/modules/home/components/auth-callback/auth-callback.component.ts
+++ b/src/app/modules/home/components/auth-callback/auth-callback.component.ts
@@ -1,22 +1,30 @@
-import { Component, OnInit } from "@angular/core";
+import { Component, OnDestroy, OnInit } from "@angular/core";
import { AuthService } from "@shared/services/auth/auth.service";
import { Router, ActivatedRoute } from "@angular/router";
import { CookieService } from "ngx-cookie-service";
+import { TotpService } from "@services/totp.service";
+import { untilDestroyed } from "@shared/subscriptions/until-destroyed";
@Component({
templateUrl: "./auth-callback.component.html",
})
-export class AuthCallbackComponent implements OnInit {
+export class AuthCallbackComponent implements OnInit, OnDestroy {
private readonly urlToRedirectAfterLogin = "/me";
showErrorBlock = false;
showInfoblock = true;
+ showMfaBlock = false;
+
+ showTotpInvalid = false;
+ totpCode = "";
+ totpCodeSent = false;
constructor(
private readonly authService: AuthService,
private readonly router: Router,
private readonly route: ActivatedRoute,
- private readonly cookieService: CookieService
+ private readonly cookieService: CookieService,
+ private readonly totpService: TotpService
) {}
async ngOnInit(): Promise
{
@@ -27,23 +35,66 @@ export class AuthCallbackComponent implements OnInit {
this.route.snapshot.fragment.indexOf("error") >= 0
) {
this.showErrorBlock = true;
+ this.showMfaBlock = false;
this.showInfoblock = false;
return Promise.resolve();
}
- this.authService.completeAuthentication().subscribe((x) => {
- if (this.cookieService.check("url")) {
- const url = this.cookieService.get("url") ?? "";
- this.cookieService.delete("url");
-
- if (url.includes("?")) {
- this.router.navigateByUrl(url);
+ this.authService
+ .completeAuthentication()
+ .pipe(untilDestroyed(this))
+ .subscribe((x) => {
+ if (x.isMfaEnabled) {
+ this.showMfaBlock = true;
+ this.showInfoblock = false;
} else {
- this.router.navigate([url]);
+ this.showInfoblock = true;
+
+ this.authService.getCurrentUser().subscribe((user) => {
+ this.redirectToMainPageOrUrl();
+ });
}
- } else {
- this.router.navigate([this.urlToRedirectAfterLogin]);
+ });
+ }
+
+ validateTotp(): void {
+ if (this.totpCode == null || this.totpCode.length !== 6) {
+ this.showTotpInvalid = true;
+ this.totpCodeSent = false;
+ return;
+ }
+
+ this.totpService.verifyTotp(this.totpCode).subscribe((result) => {
+ if (result.result) {
+ this.showTotpInvalid = false;
+ this.showInfoblock = true;
+ this.totpCodeSent = true;
+
+ this.authService.getCurrentUser().subscribe((user) => {
+ this.redirectToMainPageOrUrl();
+ });
}
+
+ this.showInfoblock = false;
+ this.showTotpInvalid = true;
+ this.totpCodeSent = false;
});
}
+
+ private redirectToMainPageOrUrl(): void {
+ if (this.cookieService.check("url")) {
+ const url = this.cookieService.get("url") ?? "";
+ this.cookieService.delete("url");
+
+ if (url.includes("?")) {
+ this.router.navigateByUrl(url);
+ } else {
+ this.router.navigate([url]);
+ }
+ } else {
+ this.router.navigate([this.urlToRedirectAfterLogin]);
+ }
+ }
+
+ ngOnDestroy(): void {}
}
diff --git a/src/app/modules/home/components/me/me.component.html b/src/app/modules/home/components/me/me.component.html
index bc9b275f..91a7b2c8 100644
--- a/src/app/modules/home/components/me/me.component.html
+++ b/src/app/modules/home/components/me/me.component.html
@@ -1,7 +1,85 @@
{{ user?.fullName }}
-
+
+
+
+
+
+
Пока работаем над этим.
+
+
+
@@ -9,3 +87,19 @@
+
+
+
+
![QR code]()
+
+
+
+
diff --git a/src/app/modules/home/components/me/me.component.ts b/src/app/modules/home/components/me/me.component.ts
index b5f4fdb9..fb6101dc 100644
--- a/src/app/modules/home/components/me/me.component.ts
+++ b/src/app/modules/home/components/me/me.component.ts
@@ -4,29 +4,78 @@ import { ApplicationUserExtended } from "@models/extended";
import { TitleService } from "@services/title.service";
import { untilDestroyed } from "@shared/subscriptions/until-destroyed";
import { AuthService } from "@shared/services/auth/auth.service";
+import { TotpService } from "@services/totp.service";
+import { DialogMessage } from "@shared/components/dialogs/models/dialog-message";
+import { ConfirmMsg } from "@shared/components/dialogs/models/confirm-msg";
+import { UserRole } from "@models/enums";
@Component({
templateUrl: "./me.component.html",
})
export class MeComponent implements OnInit, OnDestroy {
user: ApplicationUserExtended | null = null;
+ mfaQrCodeImage: string | null = null;
+ confirmDisablingMfaMessage: DialogMessage | null = null;
+ showEnableMfaBlock = false;
constructor(
private readonly authorizationService: AuthorizationService,
- private readonly auth: AuthService,
- private readonly titleService: TitleService
- ) {}
+ private readonly titleService: TitleService,
+ private readonly totpService: TotpService
+ ) {
+ this.titleService.setTitle("Мой профиль");
+ }
ngOnInit(): void {
+ this.reloadUser();
+ }
+
+ openMfaSetupDialog(): void {
+ if (this.user?.isMfaEnabled) {
+ return;
+ }
+
+ this.totpService
+ .enableMfa()
+ .pipe(untilDestroyed(this))
+ .subscribe((response) => {
+ this.mfaQrCodeImage =
+ "data:image/jpg;base64," + response.totpSetupQRBase64;
+ });
+ }
+
+ openDisableMfaDialog(): void {
+ this.confirmDisablingMfaMessage = new DialogMessage(
+ new ConfirmMsg(
+ "Отключить мультфакторную авторизацию",
+ "Вы уверены?",
+ () => {
+ this.totpService
+ .disableMfa()
+ .pipe(untilDestroyed(this))
+ .subscribe(() => {
+ this.confirmDisablingMfaMessage = null;
+ this.reloadUser();
+ });
+ }
+ )
+ );
+ }
+
+ onQrModalDlgClose(): void {
+ this.mfaQrCodeImage = null;
+ this.reloadUser();
+ }
+
+ ngOnDestroy(): void {}
+
+ private reloadUser(): void {
this.authorizationService
.getMe()
.pipe(untilDestroyed(this))
.subscribe((user) => {
this.user = new ApplicationUserExtended(user);
+ this.showEnableMfaBlock = this.user.hasRole(UserRole.Admin);
});
-
- this.titleService.setTitle("My profile");
}
-
- ngOnDestroy(): void {}
}
diff --git a/src/app/modules/home/home.module.ts b/src/app/modules/home/home.module.ts
index 19eed961..74728ee5 100644
--- a/src/app/modules/home/home.module.ts
+++ b/src/app/modules/home/home.module.ts
@@ -13,6 +13,7 @@ import { PrivacyPolicyPageComponent } from "./components/privacy-policy-page/pri
import { AboutUsComponent } from "./components/about-us/about-us.component";
import { LogoutCallbackComponent } from "./components/logout-callback/logout-callback.component";
import { TelegramBotABoutComponent } from "./components/telegram-bot/telegram-bot.component";
+import { FormsModule } from "@angular/forms";
@NgModule({
declarations: [
@@ -28,6 +29,6 @@ import { TelegramBotABoutComponent } from "./components/telegram-bot/telegram-bo
LogoutCallbackComponent,
TelegramBotABoutComponent,
],
- imports: [CommonModule, SharedModule, HomeRoutingModule],
+ imports: [CommonModule, SharedModule, HomeRoutingModule, FormsModule],
})
export class HomeModule {}
diff --git a/src/app/modules/salaries/components/historical-charts-page/historical-survey-chart/historical-survey-chart.component.html b/src/app/modules/salaries/components/historical-charts-page/historical-survey-chart/historical-survey-chart.component.html
index 7c013f2f..3bb15c5a 100644
--- a/src/app/modules/salaries/components/historical-charts-page/historical-survey-chart/historical-survey-chart.component.html
+++ b/src/app/modules/salaries/components/historical-charts-page/historical-survey-chart/historical-survey-chart.component.html
@@ -67,7 +67,7 @@
Польза статистики по мнению тех, кто работает на удаленке
-
+