mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
[PM-8214] New Device Verification Notice UI (#12360)
* starting * setup first page for new device verification notice * update designs for first page. rename components and files * added second page for new device verification notice * update notice page one with bit radio buttons. routing logic. user email * updated routing for new device verification notice to show before vault based on flags, and can navigate back to vault after submission * fix translations. added remind me later link and nav to page 2 * sync the design for mobile and web * update routes in desktop * updated styles for desktop * moved new device verification notice guard * update types for new device notice page one * add null check to page one * types * types for page one, page two, service, and guard * types * update component and guard for null check * add navigation to two step login btn and account email btn * remove empty file * update fill of icons to support light & dark modes * add question mark to email access verification copy * remove unused map * use links for navigation elements - an empty href is needed so the links are keyboard accessible * remove clip path from exclamation svg - No noticeable difference in the end result * inline email message into markup --------- Co-authored-by: Nick Krantz <nick@livefront.com>
This commit is contained in:
parent
23212fb9ae
commit
1d04a0a399
@ -4910,6 +4910,42 @@
|
|||||||
"beta": {
|
"beta": {
|
||||||
"message": "Beta"
|
"message": "Beta"
|
||||||
},
|
},
|
||||||
|
"importantNotice": {
|
||||||
|
"message": "Important notice"
|
||||||
|
},
|
||||||
|
"setupTwoStepLogin": {
|
||||||
|
"message": "Set up two-step login"
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticeContentPage1": {
|
||||||
|
"message": "Bitwarden will send a code to your account email to verify logins from new devices starting in February 2025."
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticeContentPage2": {
|
||||||
|
"message": "You can set up two-step login as an alternative way to protect your account or change your email to one you can access."
|
||||||
|
},
|
||||||
|
"remindMeLater": {
|
||||||
|
"message": "Remind me later"
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticePageOneFormContent": {
|
||||||
|
"message": "Do you have reliable access to your email, $EMAIL$?",
|
||||||
|
"placeholders": {
|
||||||
|
"email": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "your_name@email.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticePageOneEmailAccessNo": {
|
||||||
|
"message": "No, I do not"
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticePageOneEmailAccessYes": {
|
||||||
|
"message": "Yes, I can reliably access my email"
|
||||||
|
},
|
||||||
|
"turnOnTwoStepLogin": {
|
||||||
|
"message": "Turn on two-step login"
|
||||||
|
},
|
||||||
|
"changeAcctEmail": {
|
||||||
|
"message": "Change account email"
|
||||||
|
},
|
||||||
"extensionWidth": {
|
"extensionWidth": {
|
||||||
"message": "Extension width"
|
"message": "Extension width"
|
||||||
},
|
},
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
||||||
import { extensionRefreshRedirect } from "@bitwarden/angular/utils/extension-refresh-redirect";
|
import { extensionRefreshRedirect } from "@bitwarden/angular/utils/extension-refresh-redirect";
|
||||||
import { extensionRefreshSwap } from "@bitwarden/angular/utils/extension-refresh-swap";
|
import { extensionRefreshSwap } from "@bitwarden/angular/utils/extension-refresh-swap";
|
||||||
|
import { NewDeviceVerificationNoticeGuard } from "@bitwarden/angular/vault/guards";
|
||||||
import {
|
import {
|
||||||
AnonLayoutWrapperComponent,
|
AnonLayoutWrapperComponent,
|
||||||
AnonLayoutWrapperData,
|
AnonLayoutWrapperData,
|
||||||
@ -43,6 +44,11 @@ import {
|
|||||||
TwoFactorTimeoutIcon,
|
TwoFactorTimeoutIcon,
|
||||||
} from "@bitwarden/auth/angular";
|
} from "@bitwarden/auth/angular";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
import {
|
||||||
|
NewDeviceVerificationNoticePageOneComponent,
|
||||||
|
NewDeviceVerificationNoticePageTwoComponent,
|
||||||
|
VaultIcons,
|
||||||
|
} from "@bitwarden/vault";
|
||||||
|
|
||||||
import { twofactorRefactorSwap } from "../../../../libs/angular/src/utils/two-factor-component-refactor-route-swap";
|
import { twofactorRefactorSwap } from "../../../../libs/angular/src/utils/two-factor-component-refactor-route-swap";
|
||||||
import { fido2AuthGuard } from "../auth/guards/fido2-auth.guard";
|
import { fido2AuthGuard } from "../auth/guards/fido2-auth.guard";
|
||||||
@ -715,6 +721,33 @@ const routes: Routes = [
|
|||||||
canActivate: [authGuard],
|
canActivate: [authGuard],
|
||||||
data: { elevation: 2 } satisfies RouteDataProperties,
|
data: { elevation: 2 } satisfies RouteDataProperties,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "new-device-notice",
|
||||||
|
component: ExtensionAnonLayoutWrapperComponent,
|
||||||
|
canActivate: [],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component: NewDeviceVerificationNoticePageOneComponent,
|
||||||
|
data: {
|
||||||
|
pageIcon: VaultIcons.ExclamationTriangle,
|
||||||
|
pageTitle: {
|
||||||
|
key: "importantNotice",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "setup",
|
||||||
|
component: NewDeviceVerificationNoticePageTwoComponent,
|
||||||
|
data: {
|
||||||
|
pageIcon: VaultIcons.UserLock,
|
||||||
|
pageTitle: {
|
||||||
|
key: "setupTwoStepLogin",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
...extensionRefreshSwap(TabsComponent, TabsV2Component, {
|
...extensionRefreshSwap(TabsComponent, TabsV2Component, {
|
||||||
path: "tabs",
|
path: "tabs",
|
||||||
data: { elevation: 0 } satisfies RouteDataProperties,
|
data: { elevation: 0 } satisfies RouteDataProperties,
|
||||||
@ -734,7 +767,7 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
...extensionRefreshSwap(VaultFilterComponent, VaultV2Component, {
|
...extensionRefreshSwap(VaultFilterComponent, VaultV2Component, {
|
||||||
path: "vault",
|
path: "vault",
|
||||||
canActivate: [authGuard],
|
canActivate: [authGuard, NewDeviceVerificationNoticeGuard],
|
||||||
canDeactivate: [clearVaultStateGuard],
|
canDeactivate: [clearVaultStateGuard],
|
||||||
data: { elevation: 0 } satisfies RouteDataProperties,
|
data: { elevation: 0 } satisfies RouteDataProperties,
|
||||||
}),
|
}),
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
} from "@bitwarden/angular/auth/guards";
|
} from "@bitwarden/angular/auth/guards";
|
||||||
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
||||||
import { extensionRefreshRedirect } from "@bitwarden/angular/utils/extension-refresh-redirect";
|
import { extensionRefreshRedirect } from "@bitwarden/angular/utils/extension-refresh-redirect";
|
||||||
|
import { NewDeviceVerificationNoticeGuard } from "@bitwarden/angular/vault/guards";
|
||||||
import {
|
import {
|
||||||
AnonLayoutWrapperComponent,
|
AnonLayoutWrapperComponent,
|
||||||
AnonLayoutWrapperData,
|
AnonLayoutWrapperData,
|
||||||
@ -40,6 +41,11 @@ import {
|
|||||||
TwoFactorTimeoutIcon,
|
TwoFactorTimeoutIcon,
|
||||||
} from "@bitwarden/auth/angular";
|
} from "@bitwarden/auth/angular";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
import {
|
||||||
|
NewDeviceVerificationNoticePageOneComponent,
|
||||||
|
NewDeviceVerificationNoticePageTwoComponent,
|
||||||
|
VaultIcons,
|
||||||
|
} from "@bitwarden/vault";
|
||||||
|
|
||||||
import { twofactorRefactorSwap } from "../../../../libs/angular/src/utils/two-factor-component-refactor-route-swap";
|
import { twofactorRefactorSwap } from "../../../../libs/angular/src/utils/two-factor-component-refactor-route-swap";
|
||||||
import { AccessibilityCookieComponent } from "../auth/accessibility-cookie.component";
|
import { AccessibilityCookieComponent } from "../auth/accessibility-cookie.component";
|
||||||
@ -116,10 +122,37 @@ const routes: Routes = [
|
|||||||
} satisfies RouteDataProperties & AnonLayoutWrapperData,
|
} satisfies RouteDataProperties & AnonLayoutWrapperData,
|
||||||
},
|
},
|
||||||
{ path: "register", component: RegisterComponent },
|
{ path: "register", component: RegisterComponent },
|
||||||
|
{
|
||||||
|
path: "new-device-notice",
|
||||||
|
component: AnonLayoutWrapperComponent,
|
||||||
|
canActivate: [],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component: NewDeviceVerificationNoticePageOneComponent,
|
||||||
|
data: {
|
||||||
|
pageIcon: VaultIcons.ExclamationTriangle,
|
||||||
|
pageTitle: {
|
||||||
|
key: "importantNotice",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "setup",
|
||||||
|
component: NewDeviceVerificationNoticePageTwoComponent,
|
||||||
|
data: {
|
||||||
|
pageIcon: VaultIcons.UserLock,
|
||||||
|
pageTitle: {
|
||||||
|
key: "setupTwoStepLogin",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "vault",
|
path: "vault",
|
||||||
component: VaultComponent,
|
component: VaultComponent,
|
||||||
canActivate: [authGuard],
|
canActivate: [authGuard, NewDeviceVerificationNoticeGuard],
|
||||||
},
|
},
|
||||||
{ path: "accessibility-cookie", component: AccessibilityCookieComponent },
|
{ path: "accessibility-cookie", component: AccessibilityCookieComponent },
|
||||||
{ path: "set-password", component: SetPasswordComponent },
|
{ path: "set-password", component: SetPasswordComponent },
|
||||||
|
@ -3394,5 +3394,41 @@
|
|||||||
},
|
},
|
||||||
"fileSavedToDevice": {
|
"fileSavedToDevice": {
|
||||||
"message": "File saved to device. Manage from your device downloads."
|
"message": "File saved to device. Manage from your device downloads."
|
||||||
|
},
|
||||||
|
"importantNotice": {
|
||||||
|
"message": "Important notice"
|
||||||
|
},
|
||||||
|
"setupTwoStepLogin": {
|
||||||
|
"message": "Set up two-step login"
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticeContentPage1": {
|
||||||
|
"message": "Bitwarden will send a code to your account email to verify logins from new devices starting in February 2025."
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticeContentPage2": {
|
||||||
|
"message": "You can set up two-step login as an alternative way to protect your account or change your email to one you can access."
|
||||||
|
},
|
||||||
|
"remindMeLater": {
|
||||||
|
"message": "Remind me later"
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticePageOneFormContent": {
|
||||||
|
"message": "Do you have reliable access to your email, $EMAIL$?",
|
||||||
|
"placeholders": {
|
||||||
|
"email": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "your_name@email.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticePageOneEmailAccessNo": {
|
||||||
|
"message": "No, I do not"
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticePageOneEmailAccessYes": {
|
||||||
|
"message": "Yes, I can reliably access my email"
|
||||||
|
},
|
||||||
|
"turnOnTwoStepLogin": {
|
||||||
|
"message": "Turn on two-step login"
|
||||||
|
},
|
||||||
|
"changeAcctEmail": {
|
||||||
|
"message": "Change account email"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ config.content = [
|
|||||||
"../../libs/components/src/**/*.{html,ts}",
|
"../../libs/components/src/**/*.{html,ts}",
|
||||||
"../../libs/auth/src/**/*.{html,ts}",
|
"../../libs/auth/src/**/*.{html,ts}",
|
||||||
"../../libs/angular/src/**/*.{html,ts}",
|
"../../libs/angular/src/**/*.{html,ts}",
|
||||||
|
"../../libs/vault/src/**/*.{html,ts,mdx}",
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
||||||
import { generatorSwap } from "@bitwarden/angular/tools/generator/generator-swap";
|
import { generatorSwap } from "@bitwarden/angular/tools/generator/generator-swap";
|
||||||
import { extensionRefreshSwap } from "@bitwarden/angular/utils/extension-refresh-swap";
|
import { extensionRefreshSwap } from "@bitwarden/angular/utils/extension-refresh-swap";
|
||||||
|
import { NewDeviceVerificationNoticeGuard } from "@bitwarden/angular/vault/guards";
|
||||||
import {
|
import {
|
||||||
AnonLayoutWrapperComponent,
|
AnonLayoutWrapperComponent,
|
||||||
AnonLayoutWrapperData,
|
AnonLayoutWrapperData,
|
||||||
@ -40,6 +41,11 @@ import {
|
|||||||
LoginDecryptionOptionsComponent,
|
LoginDecryptionOptionsComponent,
|
||||||
} from "@bitwarden/auth/angular";
|
} from "@bitwarden/auth/angular";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
import {
|
||||||
|
NewDeviceVerificationNoticePageOneComponent,
|
||||||
|
NewDeviceVerificationNoticePageTwoComponent,
|
||||||
|
VaultIcons,
|
||||||
|
} from "@bitwarden/vault";
|
||||||
|
|
||||||
import { twofactorRefactorSwap } from "../../../../libs/angular/src/utils/two-factor-component-refactor-route-swap";
|
import { twofactorRefactorSwap } from "../../../../libs/angular/src/utils/two-factor-component-refactor-route-swap";
|
||||||
import { flagEnabled, Flags } from "../utils/flags";
|
import { flagEnabled, Flags } from "../utils/flags";
|
||||||
@ -695,10 +701,37 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "new-device-notice",
|
||||||
|
component: AnonLayoutWrapperComponent,
|
||||||
|
canActivate: [],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component: NewDeviceVerificationNoticePageOneComponent,
|
||||||
|
data: {
|
||||||
|
pageIcon: VaultIcons.ExclamationTriangle,
|
||||||
|
pageTitle: {
|
||||||
|
key: "importantNotice",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "setup",
|
||||||
|
component: NewDeviceVerificationNoticePageTwoComponent,
|
||||||
|
data: {
|
||||||
|
pageIcon: VaultIcons.UserLock,
|
||||||
|
pageTitle: {
|
||||||
|
key: "setupTwoStepLogin",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
component: UserLayoutComponent,
|
component: UserLayoutComponent,
|
||||||
canActivate: [deepLinkGuard(), authGuard],
|
canActivate: [deepLinkGuard(), authGuard, NewDeviceVerificationNoticeGuard],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "vault",
|
path: "vault",
|
||||||
|
@ -9888,6 +9888,42 @@
|
|||||||
"descriptorCode": {
|
"descriptorCode": {
|
||||||
"message": "Descriptor code"
|
"message": "Descriptor code"
|
||||||
},
|
},
|
||||||
|
"importantNotice": {
|
||||||
|
"message": "Important notice"
|
||||||
|
},
|
||||||
|
"setupTwoStepLogin": {
|
||||||
|
"message": "Set up two-step login"
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticeContentPage1": {
|
||||||
|
"message": "Bitwarden will send a code to your account email to verify logins from new devices starting in February 2025."
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticeContentPage2": {
|
||||||
|
"message": "You can set up two-step login as an alternative way to protect your account or change your email to one you can access."
|
||||||
|
},
|
||||||
|
"remindMeLater": {
|
||||||
|
"message": "Remind me later"
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticePageOneFormContent": {
|
||||||
|
"message": "Do you have reliable access to your email, $EMAIL$?",
|
||||||
|
"placeholders": {
|
||||||
|
"email": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "your_name@email.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticePageOneEmailAccessNo": {
|
||||||
|
"message": "No, I do not"
|
||||||
|
},
|
||||||
|
"newDeviceVerificationNoticePageOneEmailAccessYes": {
|
||||||
|
"message": "Yes, I can reliably access my email"
|
||||||
|
},
|
||||||
|
"turnOnTwoStepLogin": {
|
||||||
|
"message": "Turn on two-step login"
|
||||||
|
},
|
||||||
|
"changeAcctEmail": {
|
||||||
|
"message": "Change account email"
|
||||||
|
},
|
||||||
"removeMembers": {
|
"removeMembers": {
|
||||||
"message": "Remove members"
|
"message": "Remove members"
|
||||||
},
|
},
|
||||||
|
@ -298,6 +298,7 @@ import {
|
|||||||
IndividualVaultExportServiceAbstraction,
|
IndividualVaultExportServiceAbstraction,
|
||||||
} from "@bitwarden/vault-export-core";
|
} from "@bitwarden/vault-export-core";
|
||||||
|
|
||||||
|
import { NewDeviceVerificationNoticeService } from "../../../vault/src/services/new-device-verification-notice.service";
|
||||||
import { FormValidationErrorsService as FormValidationErrorsServiceAbstraction } from "../platform/abstractions/form-validation-errors.service";
|
import { FormValidationErrorsService as FormValidationErrorsServiceAbstraction } from "../platform/abstractions/form-validation-errors.service";
|
||||||
import { ViewCacheService } from "../platform/abstractions/view-cache.service";
|
import { ViewCacheService } from "../platform/abstractions/view-cache.service";
|
||||||
import { FormValidationErrorsService } from "../platform/services/form-validation-errors.service";
|
import { FormValidationErrorsService } from "../platform/services/form-validation-errors.service";
|
||||||
@ -1401,6 +1402,7 @@ const safeProviders: SafeProvider[] = [
|
|||||||
useClass: DefaultLoginDecryptionOptionsService,
|
useClass: DefaultLoginDecryptionOptionsService,
|
||||||
deps: [MessagingServiceAbstraction],
|
deps: [MessagingServiceAbstraction],
|
||||||
}),
|
}),
|
||||||
|
safeProvider(NewDeviceVerificationNoticeService),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: UserAsymmetricKeysRegenerationApiService,
|
provide: UserAsymmetricKeysRegenerationApiService,
|
||||||
useClass: DefaultUserAsymmetricKeysRegenerationApiService,
|
useClass: DefaultUserAsymmetricKeysRegenerationApiService,
|
||||||
|
1
libs/angular/src/vault/guards/index.ts
Normal file
1
libs/angular/src/vault/guards/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./new-device-verification-notice.guard";
|
@ -0,0 +1,51 @@
|
|||||||
|
import { inject } from "@angular/core";
|
||||||
|
import { ActivatedRouteSnapshot, CanActivateFn, Router } from "@angular/router";
|
||||||
|
import { Observable, firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
|
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
|
|
||||||
|
import { NewDeviceVerificationNoticeService } from "../../../../vault/src/services/new-device-verification-notice.service";
|
||||||
|
|
||||||
|
export const NewDeviceVerificationNoticeGuard: CanActivateFn = async (
|
||||||
|
route: ActivatedRouteSnapshot,
|
||||||
|
) => {
|
||||||
|
const router = inject(Router);
|
||||||
|
const configService = inject(ConfigService);
|
||||||
|
const newDeviceVerificationNoticeService = inject(NewDeviceVerificationNoticeService);
|
||||||
|
const accountService = inject(AccountService);
|
||||||
|
|
||||||
|
if (route.queryParams["fromNewDeviceVerification"]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tempNoticeFlag = await configService.getFeatureFlag(
|
||||||
|
FeatureFlag.NewDeviceVerificationTemporaryDismiss,
|
||||||
|
);
|
||||||
|
const permNoticeFlag = await configService.getFeatureFlag(
|
||||||
|
FeatureFlag.NewDeviceVerificationPermanentDismiss,
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentAcct$: Observable<Account | null> = accountService.activeAccount$.pipe(
|
||||||
|
map((acct) => acct),
|
||||||
|
);
|
||||||
|
const currentAcct = await firstValueFrom(currentAcct$);
|
||||||
|
|
||||||
|
if (!currentAcct) {
|
||||||
|
return router.createUrlTree(["/login"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const userItems$ = newDeviceVerificationNoticeService.noticeState$(currentAcct.id);
|
||||||
|
const userItems = await firstValueFrom(userItems$);
|
||||||
|
|
||||||
|
if (
|
||||||
|
userItems?.last_dismissal == null &&
|
||||||
|
(userItems?.permanent_dismissal == null || !userItems?.permanent_dismissal) &&
|
||||||
|
(tempNoticeFlag || permNoticeFlag)
|
||||||
|
) {
|
||||||
|
return router.createUrlTree(["/new-device-notice"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
@ -0,0 +1,30 @@
|
|||||||
|
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||||
|
<p class="tw-text-center" bitTypography="body1">
|
||||||
|
{{ "newDeviceVerificationNoticeContentPage1" | i18n }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<bit-card
|
||||||
|
class="tw-pb-0"
|
||||||
|
[ngClass]="{
|
||||||
|
'tw-flex tw-flex-col tw-items-center !tw-rounded-b-none': isDesktop,
|
||||||
|
'md:tw-flex md:tw-flex-col md:tw-items-center md:!tw-rounded-b-none': !isDesktop,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<p bitTypography="body2" class="text-muted md:tw-w-9/12">
|
||||||
|
{{ "newDeviceVerificationNoticePageOneFormContent" | i18n: this.currentEmail }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<bit-radio-group formControlName="hasEmailAccess" class="md:tw-w-9/12">
|
||||||
|
<bit-radio-button id="option_A" [value]="0">
|
||||||
|
<bit-label>{{ "newDeviceVerificationNoticePageOneEmailAccessNo" | i18n }}</bit-label>
|
||||||
|
</bit-radio-button>
|
||||||
|
<bit-radio-button id="option_B" [value]="1">
|
||||||
|
<bit-label>{{ "newDeviceVerificationNoticePageOneEmailAccessYes" | i18n }}</bit-label>
|
||||||
|
</bit-radio-button>
|
||||||
|
</bit-radio-group>
|
||||||
|
</bit-card>
|
||||||
|
|
||||||
|
<button bitButton type="submit" buttonType="primary" class="tw-w-full tw-mt-4">
|
||||||
|
{{ "continue" | i18n }}
|
||||||
|
</button>
|
||||||
|
</form>
|
@ -0,0 +1,82 @@
|
|||||||
|
import { CommonModule } from "@angular/common";
|
||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { FormBuilder, FormControl, ReactiveFormsModule } from "@angular/forms";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
import { firstValueFrom, Observable } from "rxjs";
|
||||||
|
|
||||||
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { ClientType } from "@bitwarden/common/enums";
|
||||||
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
|
import {
|
||||||
|
AsyncActionsModule,
|
||||||
|
ButtonModule,
|
||||||
|
CardComponent,
|
||||||
|
FormFieldModule,
|
||||||
|
RadioButtonModule,
|
||||||
|
TypographyModule,
|
||||||
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { NewDeviceVerificationNoticeService } from "./../../services/new-device-verification-notice.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
standalone: true,
|
||||||
|
selector: "app-new-device-verification-notice-page-one",
|
||||||
|
templateUrl: "./new-device-verification-notice-page-one.component.html",
|
||||||
|
imports: [
|
||||||
|
CardComponent,
|
||||||
|
CommonModule,
|
||||||
|
JslibModule,
|
||||||
|
TypographyModule,
|
||||||
|
ButtonModule,
|
||||||
|
RadioButtonModule,
|
||||||
|
FormFieldModule,
|
||||||
|
AsyncActionsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class NewDeviceVerificationNoticePageOneComponent implements OnInit {
|
||||||
|
protected formGroup = this.formBuilder.group({
|
||||||
|
hasEmailAccess: new FormControl(0),
|
||||||
|
});
|
||||||
|
protected isDesktop: boolean;
|
||||||
|
readonly currentAcct$: Observable<Account | null> = this.accountService.activeAccount$;
|
||||||
|
protected currentEmail: string = "";
|
||||||
|
private currentUserId: UserId | null = null;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
|
private router: Router,
|
||||||
|
private accountService: AccountService,
|
||||||
|
private newDeviceVerificationNoticeService: NewDeviceVerificationNoticeService,
|
||||||
|
private platformUtilsService: PlatformUtilsService,
|
||||||
|
) {
|
||||||
|
this.isDesktop = this.platformUtilsService.getClientType() === ClientType.Desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit() {
|
||||||
|
const currentAcct = await firstValueFrom(this.currentAcct$);
|
||||||
|
if (!currentAcct) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.currentEmail = currentAcct.email;
|
||||||
|
this.currentUserId = currentAcct.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
submit = async () => {
|
||||||
|
if (this.formGroup.controls.hasEmailAccess.value === 0) {
|
||||||
|
await this.router.navigate(["new-device-notice/setup"]);
|
||||||
|
} else if (this.formGroup.controls.hasEmailAccess.value === 1) {
|
||||||
|
await this.newDeviceVerificationNoticeService.updateNewDeviceVerificationNoticeState(
|
||||||
|
this.currentUserId,
|
||||||
|
{
|
||||||
|
last_dismissal: new Date(),
|
||||||
|
permanent_dismissal: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.router.navigate(["/vault"]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<p class="tw-text-center" bitTypography="body1">
|
||||||
|
{{ "newDeviceVerificationNoticeContentPage2" | i18n }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
bitButton
|
||||||
|
(click)="navigateToTwoStepLogin($event)"
|
||||||
|
buttonType="primary"
|
||||||
|
class="tw-w-full tw-mt-4"
|
||||||
|
>
|
||||||
|
{{ "turnOnTwoStepLogin" | i18n }}
|
||||||
|
<i
|
||||||
|
class="bwi bwi-external-link bwi-lg bwi-fw"
|
||||||
|
aria-hidden="true"
|
||||||
|
[ngClass]="{ 'md:tw-hidden': !isDesktop }"
|
||||||
|
>
|
||||||
|
</i>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
bitButton
|
||||||
|
(click)="navigateToChangeAcctEmail($event)"
|
||||||
|
buttonType="secondary"
|
||||||
|
class="tw-w-full tw-mt-4"
|
||||||
|
>
|
||||||
|
{{ "changeAcctEmail" | i18n }}
|
||||||
|
<i
|
||||||
|
class="bwi bwi-external-link bwi-lg bwi-fw"
|
||||||
|
aria-hidden="true"
|
||||||
|
[ngClass]="{ 'md:tw-hidden': !isDesktop }"
|
||||||
|
></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="tw-flex tw-justify-center tw-mt-6">
|
||||||
|
<a bitLink linkType="primary" (click)="remindMeLaterSelect()">
|
||||||
|
{{ "remindMeLater" | i18n }}
|
||||||
|
</a>
|
||||||
|
</div>
|
@ -0,0 +1,95 @@
|
|||||||
|
import { CommonModule } from "@angular/common";
|
||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
import { firstValueFrom, Observable } from "rxjs";
|
||||||
|
|
||||||
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { ClientType } from "@bitwarden/common/enums";
|
||||||
|
import {
|
||||||
|
Environment,
|
||||||
|
EnvironmentService,
|
||||||
|
} from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
|
import { ButtonModule, LinkModule, TypographyModule } from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { NewDeviceVerificationNoticeService } from "../../services/new-device-verification-notice.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
standalone: true,
|
||||||
|
selector: "app-new-device-verification-notice-page-two",
|
||||||
|
templateUrl: "./new-device-verification-notice-page-two.component.html",
|
||||||
|
imports: [CommonModule, JslibModule, TypographyModule, ButtonModule, LinkModule],
|
||||||
|
})
|
||||||
|
export class NewDeviceVerificationNoticePageTwoComponent implements OnInit {
|
||||||
|
protected isWeb: boolean;
|
||||||
|
protected isDesktop: boolean;
|
||||||
|
readonly currentAcct$: Observable<Account | null> = this.accountService.activeAccount$;
|
||||||
|
private currentUserId: UserId | null = null;
|
||||||
|
private env$: Observable<Environment> = this.environmentService.environment$;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private newDeviceVerificationNoticeService: NewDeviceVerificationNoticeService,
|
||||||
|
private router: Router,
|
||||||
|
private accountService: AccountService,
|
||||||
|
private platformUtilsService: PlatformUtilsService,
|
||||||
|
private environmentService: EnvironmentService,
|
||||||
|
) {
|
||||||
|
this.isWeb = this.platformUtilsService.getClientType() === ClientType.Web;
|
||||||
|
this.isDesktop = this.platformUtilsService.getClientType() === ClientType.Desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit() {
|
||||||
|
const currentAcct = await firstValueFrom(this.currentAcct$);
|
||||||
|
if (!currentAcct) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.currentUserId = currentAcct.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
async navigateToTwoStepLogin(event: Event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const env = await firstValueFrom(this.env$);
|
||||||
|
const url = env.getWebVaultUrl();
|
||||||
|
|
||||||
|
if (this.isWeb) {
|
||||||
|
await this.router.navigate(["/settings/security/two-factor"], {
|
||||||
|
queryParams: { fromNewDeviceVerification: true },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.platformUtilsService.launchUri(
|
||||||
|
url + "/#/settings/security/two-factor/?fromNewDeviceVerification=true",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async navigateToChangeAcctEmail(event: Event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const env = await firstValueFrom(this.env$);
|
||||||
|
const url = env.getWebVaultUrl();
|
||||||
|
if (this.isWeb) {
|
||||||
|
await this.router.navigate(["/settings/account"], {
|
||||||
|
queryParams: { fromNewDeviceVerification: true },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.platformUtilsService.launchUri(
|
||||||
|
url + "/#/settings/account/?fromNewDeviceVerification=true",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async remindMeLaterSelect() {
|
||||||
|
await this.newDeviceVerificationNoticeService.updateNewDeviceVerificationNoticeState(
|
||||||
|
this.currentUserId,
|
||||||
|
{
|
||||||
|
last_dismissal: new Date(),
|
||||||
|
permanent_dismissal: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.router.navigate(["/vault"]);
|
||||||
|
}
|
||||||
|
}
|
7
libs/vault/src/icons/exclamation-triangle.ts
Normal file
7
libs/vault/src/icons/exclamation-triangle.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { svgIcon } from "@bitwarden/components";
|
||||||
|
|
||||||
|
export const ExclamationTriangle = svgIcon`
|
||||||
|
<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M91.0871 85.1224H28.913C27.5592 85.1349 26.2271 84.7737 25.0549 84.0713C23.8828 83.3688 22.914 82.3578 22.248 81.1386C21.5868 79.9571 21.2405 78.6149 21.2502 77.2502C21.2599 75.8855 21.6207 74.5484 22.2964 73.3768L53.3835 18.7683C54.0665 17.5817 55.0352 16.6008 56.1953 15.9184C57.3554 15.2361 58.6656 14.8773 60 14.8773C61.3345 14.8773 62.6447 15.2361 63.8048 15.9184C64.9649 16.6008 65.9336 17.5817 66.6166 18.7683L97.7036 73.3768C98.3793 74.5484 98.7426 75.8855 98.7499 77.2502C98.7571 78.6149 98.4132 79.9571 97.7521 81.1386C97.0861 82.3578 96.1173 83.3713 94.9451 84.0713C93.773 84.7712 92.4409 85.1349 91.0871 85.1224ZM60 19.8972C59.5084 19.8896 59.0216 20.0176 58.5929 20.2659C58.1643 20.5143 57.8058 20.878 57.554 21.3171L26.4717 75.9256C26.2344 76.3371 26.1085 76.8087 26.1085 77.2878C26.1085 77.767 26.2344 78.2386 26.4717 78.65C26.7188 79.0991 27.0772 79.4704 27.5107 79.7263C27.9442 79.9821 28.4359 80.1126 28.9324 80.1051H91.0871C91.586 80.1126 92.0776 79.9821 92.5087 79.7263C92.9398 79.4704 93.3007 79.0991 93.5477 78.65C93.7851 78.2386 93.911 77.767 93.911 77.2878C93.911 76.8087 93.7851 76.3371 93.5477 75.9256L62.4461 21.3171C62.1943 20.878 61.8358 20.5168 61.4071 20.2659C60.9785 20.0151 60.4917 19.8896 60 19.8972ZM60 62.8705C59.3582 62.8705 58.7407 62.6071 58.2878 62.1355C57.8349 61.6639 57.5782 61.0267 57.5782 60.3619V37.4177C57.5782 36.7529 57.8325 36.1132 58.2878 35.644C58.7431 35.1749 59.3582 34.909 60 34.909C60.6418 34.909 61.2594 35.1724 61.7123 35.644C62.1652 36.1157 62.4219 36.7529 62.4219 37.4177V60.3619C62.4219 61.0267 62.1676 61.6664 61.7123 62.1355C61.257 62.6046 60.6418 62.8705 60 62.8705ZM60 75.2734C61.5864 75.2734 62.8724 73.9413 62.8724 72.2981C62.8724 70.6549 61.5864 69.3228 60 69.3228C58.4137 69.3228 57.1277 70.6549 57.1277 72.2981C57.1277 73.9413 58.4137 75.2734 60 75.2734Z" class="tw-fill-warning-600" />
|
||||||
|
</svg>
|
||||||
|
`;
|
@ -2,3 +2,5 @@ export * from "./deactivated-org";
|
|||||||
export * from "./no-folders";
|
export * from "./no-folders";
|
||||||
export * from "./vault";
|
export * from "./vault";
|
||||||
export * from "./empty-trash";
|
export * from "./empty-trash";
|
||||||
|
export * from "./exclamation-triangle";
|
||||||
|
export * from "./user-lock";
|
||||||
|
17
libs/vault/src/icons/user-lock.ts
Normal file
17
libs/vault/src/icons/user-lock.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { svgIcon } from "@bitwarden/components";
|
||||||
|
|
||||||
|
export const UserLock = svgIcon`
|
||||||
|
<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path class="tw-fill-art-primary" fill-rule="evenodd" clip-rule="evenodd" d="M0 19.6127C0 14.9806 3.71508 11.2256 8.29787 11.2256H89.5153C94.098 11.2256 97.8131 14.9806 97.8131 19.6127V28.0844H95.2599V19.6127C95.2599 16.4059 92.688 13.8062 89.5153 13.8062H8.29787C5.12517 13.8062 2.55319 16.4059 2.55319 19.6127V68.6449C2.55319 71.8518 5.12517 74.4514 8.29787 74.4514H16.2389V77.032H8.29787C3.71509 77.032 0 73.277 0 68.6449V19.6127ZM50.9015 74.4514H63.2653V77.032H50.9015V74.4514Z" />
|
||||||
|
<path class="tw-fill-art-primary" fill-rule="evenodd" clip-rule="evenodd" d="M88.7235 60.2578C97.5366 60.2578 104.681 53.0366 104.681 44.1287C104.681 35.2209 97.5366 27.9997 88.7235 27.9997C79.9105 27.9997 72.7661 35.2209 72.7661 44.1287C72.7661 53.0366 79.9105 60.2578 88.7235 60.2578ZM88.7235 62.8384C98.9467 62.8384 107.234 54.4618 107.234 44.1287C107.234 33.7957 98.9467 25.4191 88.7235 25.4191C78.5004 25.4191 70.2129 33.7957 70.2129 44.1287C70.2129 54.4618 78.5004 62.8384 88.7235 62.8384Z" />
|
||||||
|
<path class="tw-fill-art-accent" fill-rule="evenodd" clip-rule="evenodd" d="M33.8298 46.0642C28.7286 46.0642 24.2553 51.0589 24.2553 57.6771H21.7021C21.7021 50.0428 26.9452 43.4835 33.8298 43.4835C40.7144 43.4835 45.9575 50.0428 45.9575 57.6771H43.4043C43.4043 51.0589 38.931 46.0642 33.8298 46.0642Z" />
|
||||||
|
<path class="tw-fill-art-primary" fill-rule="evenodd" clip-rule="evenodd" d="M60.8742 88.6448H115.299C116.596 88.6448 117.089 88.3032 117.227 88.1603C117.3 88.0845 117.558 87.7852 117.396 86.7815C115.225 73.2724 103.259 62.8383 88.7118 62.8383C74.1651 62.8383 62.1986 73.2724 60.0274 86.7815C59.9451 87.2938 60.0532 87.888 60.2785 88.2731C60.379 88.445 60.4746 88.5285 60.5381 88.5682C60.5886 88.5998 60.6806 88.6448 60.8742 88.6448ZM60.8742 91.2254H115.299C118.653 91.2254 120.416 89.4793 119.916 86.3677C117.539 71.5724 104.473 60.2577 88.7118 60.2577C72.9505 60.2577 59.8851 71.5724 57.5073 86.3677C57.1687 88.4743 58.2526 91.2254 60.8742 91.2254Z" />
|
||||||
|
<path class="tw-fill-art-accent" fill-rule="evenodd" clip-rule="evenodd" d="M44.6808 58.9675H22.9787C20.1585 58.9675 17.8723 61.2783 17.8723 64.1288V79.6126C17.8723 82.4631 20.1585 84.7739 22.9787 84.7739H44.6808C47.501 84.7739 49.7872 82.4631 49.7872 79.6126V64.1288C49.7872 61.2783 47.501 58.9675 44.6808 58.9675ZM22.9787 56.3868C18.7484 56.3868 15.3191 59.853 15.3191 64.1288V79.6126C15.3191 83.8884 18.7484 87.3546 22.9787 87.3546H44.6808C48.9111 87.3546 52.3404 83.8884 52.3404 79.6126V64.1288C52.3404 59.853 48.9111 56.3868 44.6808 56.3868H22.9787Z"/>
|
||||||
|
<path class="tw-fill-art-accent" fill-rule="evenodd" clip-rule="evenodd" d="M33.8301 71.8707C34.5351 71.8707 35.1067 72.4484 35.1067 73.1611L35.1067 77.6923C35.1067 78.4049 34.5351 78.9826 33.8301 78.9826C33.125 78.9826 32.5535 78.4049 32.5535 77.6923L32.5535 73.1611C32.5535 72.4484 33.125 71.8707 33.8301 71.8707Z" />
|
||||||
|
<path class="tw-fill-art-accent" fill-rule="evenodd" clip-rule="evenodd" d="M78.315 18.3374C77.6099 18.3374 77.0384 17.7597 77.0384 17.0471V16.5436C77.0384 15.831 77.6099 15.2533 78.315 15.2533C79.02 15.2533 79.5916 15.831 79.5916 16.5436V17.0471C79.5916 17.7597 79.02 18.3374 78.315 18.3374Z" />
|
||||||
|
<path class="tw-fill-art-accent" fill-rule="evenodd" clip-rule="evenodd" d="M33.8299 74.3097C32.4198 74.3097 31.2767 73.1543 31.2767 71.729V71.2256C31.2767 69.8003 32.4198 68.6449 33.8299 68.6449C35.24 68.6449 36.3831 69.8003 36.3831 71.2256V71.729C36.3831 73.1543 35.24 74.3097 33.8299 74.3097Z" />
|
||||||
|
<path class="tw-fill-art-accent" fill-rule="evenodd" clip-rule="evenodd" d="M84.2903 18.3374C83.5853 18.3374 83.0137 17.7597 83.0137 17.0471V16.5436C83.0137 15.831 83.5853 15.2533 84.2903 15.2533C84.9953 15.2533 85.5669 15.831 85.5669 16.5436V17.0471C85.5669 17.7597 84.9953 18.3374 84.2903 18.3374Z" />
|
||||||
|
<path class="tw-fill-art-accent" fill-rule="evenodd" clip-rule="evenodd" d="M90.2644 18.3374C89.5594 18.3374 88.9878 17.7597 88.9878 17.0471V16.5436C88.9878 15.831 89.5594 15.2533 90.2644 15.2533C90.9695 15.2533 91.541 15.831 91.541 16.5436V17.0471C91.541 17.7597 90.9695 18.3374 90.2644 18.3374Z"/>
|
||||||
|
<path class="tw-fill-art-primary" fill-rule="evenodd" clip-rule="evenodd" d="M95.7422 22.0817H0.638428V20.7914H95.7422V22.0817Z" />
|
||||||
|
</svg>
|
||||||
|
`;
|
@ -14,5 +14,7 @@ export {
|
|||||||
|
|
||||||
export { DownloadAttachmentComponent } from "./components/download-attachment/download-attachment.component";
|
export { DownloadAttachmentComponent } from "./components/download-attachment/download-attachment.component";
|
||||||
export { PasswordHistoryViewComponent } from "./components/password-history-view/password-history-view.component";
|
export { PasswordHistoryViewComponent } from "./components/password-history-view/password-history-view.component";
|
||||||
|
export { NewDeviceVerificationNoticePageOneComponent } from "./components/new-device-verification-notice/new-device-verification-notice-page-one.component";
|
||||||
|
export { NewDeviceVerificationNoticePageTwoComponent } from "./components/new-device-verification-notice/new-device-verification-notice-page-two.component";
|
||||||
|
|
||||||
export * as VaultIcons from "./icons";
|
export * as VaultIcons from "./icons";
|
||||||
|
@ -57,7 +57,7 @@ export class NewDeviceVerificationNoticeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateNewDeviceVerificationNoticeState(
|
async updateNewDeviceVerificationNoticeState(
|
||||||
userId: UserId,
|
userId: UserId | null,
|
||||||
newState: NewDeviceVerificationNotice,
|
newState: NewDeviceVerificationNotice,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await this.noticeState(userId).update(() => {
|
await this.noticeState(userId).update(() => {
|
||||||
|
Loading…
Reference in New Issue
Block a user