1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-27 10:03:23 +00:00

merging master into feature branch

This commit is contained in:
CarleyDiaz-Bitwarden
2022-08-03 14:20:15 -04:00
parent a7eaa26c74
commit e287715251
371 changed files with 16725 additions and 22348 deletions

View File

@@ -1,9 +0,0 @@
import { StateService as BaseStateService } from "@bitwarden/common/abstractions/state.service";
import { StorageOptions } from "@bitwarden/common/models/domain/storageOptions";
import { Account } from "src/models/account";
export abstract class StateService extends BaseStateService<Account> {
getRememberEmail: (options?: StorageOptions) => Promise<boolean>;
setRememberEmail: (value: boolean, options?: StorageOptions) => Promise<void>;
}

View File

@@ -13,7 +13,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout.service";
import { RouterService } from "../services/router.service";
import { RouterService } from "../core";
@Component({
selector: "app-lock",

View File

@@ -19,8 +19,7 @@ import { Policy } from "@bitwarden/common/models/domain/policy";
import { ListResponse } from "@bitwarden/common/models/response/listResponse";
import { PolicyResponse } from "@bitwarden/common/models/response/policyResponse";
import { StateService } from "../../abstractions/state.service";
import { RouterService } from "../services/router.service";
import { RouterService, StateService } from "../core";
@Component({
selector: "app-login",

View File

@@ -1,5 +1,5 @@
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { UntypedFormBuilder } from "@angular/forms";
import { ActivatedRoute, Router } from "@angular/router";
import { first } from "rxjs/operators";
@@ -20,7 +20,7 @@ import { MasterPasswordPolicyOptions } from "@bitwarden/common/models/domain/mas
import { Policy } from "@bitwarden/common/models/domain/policy";
import { ReferenceEventRequest } from "@bitwarden/common/models/request/referenceEventRequest";
import { RouterService } from "../services/router.service";
import { RouterService } from "../core";
@Component({
selector: "app-register",
@@ -36,7 +36,7 @@ export class RegisterComponent extends BaseRegisterComponent {
constructor(
formValidationErrorService: FormValidationErrorsService,
formBuilder: FormBuilder,
formBuilder: UntypedFormBuilder,
authService: AuthService,
router: Router,
i18nService: I18nService,

View File

@@ -32,11 +32,15 @@
name="MasterPasswordHash"
class="text-monospace form-control mb-1"
[(ngModel)]="masterPassword"
(input)="updatePasswordStrength()"
required
appInputVerbatim
/>
<app-password-strength [score]="masterPasswordScore" [showText]="true">
<app-password-strength
[password]="masterPassword"
[email]="email"
[showText]="true"
(passwordStrengthResult)="getStrengthResult($event)"
>
</app-password-strength>
</div>
<div>

View File

@@ -14,7 +14,7 @@ import { StateService } from "@bitwarden/common/abstractions/state.service";
import { TwoFactorService } from "@bitwarden/common/abstractions/twoFactor.service";
import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType";
import { RouterService } from "../services/router.service";
import { RouterService } from "../core";
import { TwoFactorOptionsComponent } from "./two-factor-options.component";

View File

@@ -44,13 +44,13 @@
name="NewMasterPasswordHash"
class="form-control mb-1"
[(ngModel)]="masterPassword"
(input)="updatePasswordStrength()"
required
appInputVerbatim
autocomplete="new-password"
/>
<app-password-strength
[score]="masterPasswordScore"
[password]="masterPassword"
[email]="email"
[showText]="true"
></app-password-strength>
</div>

View File

@@ -21,11 +21,14 @@
name="MasterPasswordHash"
class="text-monospace form-control mb-1"
[(ngModel)]="masterPassword"
(input)="updatePasswordStrength()"
required
appInputVerbatim
/>
<app-password-strength [score]="masterPasswordScore" [showText]="true">
<app-password-strength
[password]="masterPassword"
[email]="email"
[showText]="true"
>
</app-password-strength>
</div>
<div>

View File

@@ -26,6 +26,7 @@ import { StateService } from "@bitwarden/common/abstractions/state.service";
import { SyncService } from "@bitwarden/common/abstractions/sync.service";
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout.service";
import { PolicyListService, RouterService } from "./core";
import { DisableSendPolicy } from "./organizations/policies/disable-send.component";
import { MasterPasswordPolicy } from "./organizations/policies/master-password.component";
import { PasswordGeneratorPolicy } from "./organizations/policies/password-generator.component";
@@ -35,8 +36,6 @@ import { ResetPasswordPolicy } from "./organizations/policies/reset-password.com
import { SendOptionsPolicy } from "./organizations/policies/send-options.component";
import { SingleOrgPolicy } from "./organizations/policies/single-org.component";
import { TwoFactorAuthenticationPolicy } from "./organizations/policies/two-factor-authentication.component";
import { PolicyListService } from "./services/policy-list.service";
import { RouterService } from "./services/router.service";
const BroadcasterSubscriptionId = "AppComponent";
const IdleTimeout = 60000 * 10; // 10 minutes
@@ -152,7 +151,7 @@ export class AppComponent implements OnDestroy, OnInit {
this.i18nService.t("cancel")
);
if (premiumConfirmed) {
this.router.navigate(["settings/premium"]);
this.router.navigate(["settings/subscription/premium"]);
}
break;
}

View File

@@ -6,9 +6,9 @@ import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { InfiniteScrollModule } from "ngx-infinite-scroll";
import { AppComponent } from "./app.component";
import { CoreModule } from "./core";
import { OssRoutingModule } from "./oss-routing.module";
import { OssModule } from "./oss.module";
import { ServicesModule } from "./services/services.module";
import { WildcardRoutingModule } from "./wildcard-routing.module";
@NgModule({
@@ -16,7 +16,7 @@ import { WildcardRoutingModule } from "./wildcard-routing.module";
OssModule,
BrowserAnimationsModule,
FormsModule,
ServicesModule,
CoreModule,
InfiniteScrollModule,
DragDropModule,
LayoutModule,

View File

@@ -9,7 +9,7 @@ import { EventResponse } from "@bitwarden/common/models/response/eventResponse";
import { ListResponse } from "@bitwarden/common/models/response/listResponse";
import { EventView } from "@bitwarden/common/models/view/eventView";
import { EventService } from "src/app/services/event.service";
import { EventService } from "src/app/core";
@Directive()
export abstract class BaseEventsComponent {

View File

@@ -55,9 +55,9 @@ export abstract class BasePeopleComponent<
: 0;
}
get deactivatedCount() {
return this.statusMap.has(this.userStatusType.Deactivated)
? this.statusMap.get(this.userStatusType.Deactivated).length
get revokedCount() {
return this.statusMap.has(this.userStatusType.Revoked)
? this.statusMap.get(this.userStatusType.Revoked).length
: 0;
}
@@ -112,8 +112,8 @@ export abstract class BasePeopleComponent<
abstract edit(user: UserType): void;
abstract getUsers(): Promise<ListResponse<UserType>>;
abstract deleteUser(id: string): Promise<any>;
abstract deactivateUser(id: string): Promise<any>;
abstract activateUser(id: string): Promise<any>;
abstract revokeUser(id: string): Promise<any>;
abstract restoreUser(id: string): Promise<any>;
abstract reinviteUser(id: string): Promise<any>;
abstract confirmUser(user: UserType, publicKey: Uint8Array): Promise<any>;
@@ -133,7 +133,7 @@ export abstract class BasePeopleComponent<
} else {
this.statusMap.get(u.status).push(u);
}
if (u.status !== this.userStatusType.Deactivated) {
if (u.status !== this.userStatusType.Revoked) {
this.activeUsers.push(u);
}
});
@@ -235,9 +235,9 @@ export abstract class BasePeopleComponent<
this.actionPromise = null;
}
async deactivate(user: UserType) {
async revoke(user: UserType) {
const confirmed = await this.platformUtilsService.showDialog(
this.deactivateWarningMessage(),
this.revokeWarningMessage(),
this.i18nService.t("revokeUserId", this.userNamePipe.transform(user)),
this.i18nService.t("revokeAccess"),
this.i18nService.t("cancel"),
@@ -248,7 +248,7 @@ export abstract class BasePeopleComponent<
return false;
}
this.actionPromise = this.deactivateUser(user.id);
this.actionPromise = this.revokeUser(user.id);
try {
await this.actionPromise;
this.platformUtilsService.showToast(
@@ -263,8 +263,8 @@ export abstract class BasePeopleComponent<
this.actionPromise = null;
}
async activate(user: UserType) {
this.actionPromise = this.activateUser(user.id);
async restore(user: UserType) {
this.actionPromise = this.restoreUser(user.id);
try {
await this.actionPromise;
this.platformUtilsService.showToast(
@@ -381,18 +381,10 @@ export abstract class BasePeopleComponent<
return !searching && this.users && this.users.length > this.pageSize;
}
protected deleteWarningMessage(user: UserType): string {
return this.i18nService.t("removeUserConfirmation");
}
protected deactivateWarningMessage(): string {
protected revokeWarningMessage(): string {
return this.i18nService.t("revokeUserConfirmation");
}
protected activateWarningMessage(): string {
return this.i18nService.t("activateUserConfirmation");
}
protected getCheckedUsers() {
return this.users.filter((u) => (u as any).checked);
}

View File

@@ -1,6 +1,6 @@
<div *ngIf="loaded && activeOrganization != null" class="tw-flex">
<button
class="tw-flex tw-items-center tw-bg-background-alt tw-border-none"
class="tw-flex tw-items-center tw-border-none tw-bg-background-alt"
type="button"
id="pickerButton"
[appA11yTitle]="'organizationPicker' | i18n"
@@ -24,7 +24,7 @@
</button>
<div>
<div
class="tw-ml-3 tw-border tw-border-solid tw-rounded tw-border-danger-500 tw-text-danger"
class="tw-ml-3 tw-rounded tw-border tw-border-solid tw-border-danger-500 tw-text-danger"
*ngIf="!activeOrganization.enabled"
>
<div class="tw-py-2 tw-px-5">
@@ -33,7 +33,7 @@
</div>
</div>
<div
class="tw-ml-3 tw-border tw-border-solid tw-rounded tw-border-info-500 tw-text-info"
class="tw-ml-3 tw-rounded tw-border tw-border-solid tw-border-info-500 tw-text-info"
*ngIf="activeOrganization.isProviderUser"
>
<div class="tw-py-2 tw-px-5">
@@ -44,8 +44,8 @@
</div>
<bit-menu #orgPickerMenu>
<ul aria-labelledby="pickerButton" class="tw-p-0 tw-m-0">
<li *ngFor="let org of organizations" class="tw-list-none tw-flex tw-flex-col" role="none">
<ul aria-labelledby="pickerButton" class="tw-m-0 tw-p-0">
<li *ngFor="let org of organizations" class="tw-flex tw-list-none tw-flex-col" role="none">
<a bitMenuItem [routerLink]="['/organizations', org.id]">
<i
class="bwi bwi-check mr-2"

View File

@@ -1,14 +0,0 @@
<div class="progress">
<div
class="progress-bar {{ color }}"
role="progressbar"
[ngStyle]="{ width: scoreWidth + '%' }"
attr.aria-valuenow="{{ scoreWidth }}"
aria-valuemin="0"
aria-valuemax="100"
>
<ng-container *ngIf="showText && text">
{{ text }}
</ng-container>
</div>
</div>

View File

@@ -1,40 +0,0 @@
import { Component, Input, OnChanges } from "@angular/core";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
@Component({
selector: "app-password-strength",
templateUrl: "password-strength.component.html",
})
export class PasswordStrengthComponent implements OnChanges {
@Input() score?: number;
@Input() showText = false;
scoreWidth = 0;
color = "bg-danger";
text: string;
constructor(private i18nService: I18nService) {}
ngOnChanges(): void {
this.scoreWidth = this.score == null ? 0 : (this.score + 1) * 20;
switch (this.score) {
case 4:
this.color = "bg-success";
this.text = this.i18nService.t("strong");
break;
case 3:
this.color = "bg-primary";
this.text = this.i18nService.t("good");
break;
case 2:
this.color = "bg-warning";
this.text = this.i18nService.t("weak");
break;
default:
this.color = "bg-danger";
this.text = this.score != null ? this.i18nService.t("weak") : null;
break;
}
}
}

View File

@@ -1,5 +1,5 @@
import { APP_INITIALIZER, NgModule } from "@angular/core";
import { ToastrModule } from "ngx-toastr";
import { CommonModule } from "@angular/common";
import { APP_INITIALIZER, NgModule, Optional, SkipSelf } from "@angular/core";
import {
JslibServicesModule,
@@ -21,7 +21,6 @@ import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload
import { FolderService as FolderServiceAbstraction } from "@bitwarden/common/abstractions/folder/folder.service.abstraction";
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/abstractions/i18n.service";
import { ImportService as ImportServiceAbstraction } from "@bitwarden/common/abstractions/import.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { MessagingService as MessagingServiceAbstraction } from "@bitwarden/common/abstractions/messaging.service";
import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@bitwarden/common/abstractions/passwordReprompt.service";
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/abstractions/platformUtils.service";
@@ -33,33 +32,24 @@ import { ExportService } from "@bitwarden/common/services/export.service";
import { ImportService } from "@bitwarden/common/services/import.service";
import { MemoryStorageService } from "@bitwarden/common/services/memoryStorage.service";
import { StateService as StateServiceAbstraction } from "../../abstractions/state.service";
import { Account } from "../../models/account";
import { GlobalState } from "../../models/globalState";
import { BroadcasterMessagingService } from "../../services/broadcasterMessaging.service";
import { HtmlStorageService } from "../../services/htmlStorage.service";
import { I18nService } from "../../services/i18n.service";
import { PasswordRepromptService } from "../../services/passwordReprompt.service";
import { StateService } from "../../services/state.service";
import { StateMigrationService } from "../../services/stateMigration.service";
import { WebPlatformUtilsService } from "../../services/webPlatformUtils.service";
import { HomeGuard } from "../guards/home.guard";
import { PermissionsGuard as OrgPermissionsGuard } from "../organizations/guards/permissions.guard";
import { NavigationPermissionsService as OrgPermissionsService } from "../organizations/services/navigation-permissions.service";
import { BroadcasterMessagingService } from "./broadcaster-messaging.service";
import { EventService } from "./event.service";
import { HtmlStorageService } from "./html-storage.service";
import { I18nService } from "./i18n.service";
import { InitService } from "./init.service";
import { ModalService } from "./modal.service";
import { PasswordRepromptService } from "./password-reprompt.service";
import { PolicyListService } from "./policy-list.service";
import { RouterService } from "./router.service";
import { WebFileDownloadService } from "./webFileDownload.service";
import { Account, GlobalState, StateService } from "./state";
import { StateMigrationService } from "./state-migration.service";
import { WebFileDownloadService } from "./web-file-download.service";
import { WebPlatformUtilsService } from "./web-platform-utils.service";
@NgModule({
imports: [ToastrModule, JslibServicesModule],
declarations: [],
imports: [CommonModule, JslibServicesModule],
providers: [
OrgPermissionsService,
OrgPermissionsGuard,
InitService,
RouterService,
EventService,
@@ -129,22 +119,10 @@ import { WebFileDownloadService } from "./webFileDownload.service";
useClass: StateMigrationService,
deps: [AbstractStorageService, SECURE_STORAGE, STATE_FACTORY],
},
{
provide: StateServiceAbstraction,
useClass: StateService,
deps: [
AbstractStorageService,
SECURE_STORAGE,
MEMORY_STORAGE,
LogService,
StateMigrationServiceAbstraction,
STATE_FACTORY,
STATE_SERVICE_USE_CACHE,
],
},
StateService,
{
provide: BaseStateServiceAbstraction,
useExisting: StateServiceAbstraction,
useExisting: StateService,
},
{
provide: PasswordRepromptServiceAbstraction,
@@ -154,7 +132,12 @@ import { WebFileDownloadService } from "./webFileDownload.service";
provide: FileDownloadService,
useClass: WebFileDownloadService,
},
HomeGuard,
],
})
export class ServicesModule {}
export class CoreModule {
constructor(@Optional() @SkipSelf() parentModule?: CoreModule) {
if (parentModule) {
throw new Error("CoreModule is already loaded. Import it in the AppModule only");
}
}
}

View File

@@ -280,14 +280,14 @@ export class EventService {
this.getShortId(ev.organizationUserId)
);
break;
case EventType.OrganizationUser_Deactivated:
case EventType.OrganizationUser_Revoked:
msg = this.i18nService.t("revokedUserId", this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t(
"revokedUserId",
this.getShortId(ev.organizationUserId)
);
break;
case EventType.OrganizationUser_Activated:
case EventType.OrganizationUser_Restored:
msg = this.i18nService.t("restoredUserId", this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t(
"restoredUserId",
@@ -301,11 +301,9 @@ export class EventService {
case EventType.Organization_PurgedVault:
msg = humanReadableMsg = this.i18nService.t("purgedOrganizationVault");
break;
/*
case EventType.Organization_ClientExportedVault:
msg = this.i18nService.t('exportedOrganizationVault');
break;
*/
case EventType.Organization_ClientExportedVault:
msg = humanReadableMsg = this.i18nService.t("exportedOrganizationVault");
break;
case EventType.Organization_VaultAccessed:
msg = humanReadableMsg = this.i18nService.t("vaultAccessedByProvider");
break;

View File

@@ -0,0 +1,5 @@
export * from "./core.module";
export * from "./event.service";
export * from "./policy-list.service";
export * from "./router.service";
export * from "./state/state.service";

View File

@@ -17,7 +17,7 @@ import { ContainerService } from "@bitwarden/common/services/container.service";
import { EventService as EventLoggingService } from "@bitwarden/common/services/event.service";
import { VaultTimeoutService as VaultTimeoutService } from "@bitwarden/common/services/vaultTimeout.service";
import { I18nService as I18nService } from "../../services/i18n.service";
import { I18nService } from "./i18n.service";
@Injectable()
export class InitService {
@@ -52,7 +52,7 @@ export class InitService {
htmlEl.classList.add("locale_" + this.i18nService.translationLocale);
await this.themingService.monitorThemeChanges();
const containerService = new ContainerService(this.cryptoService);
containerService.attachToWindow(this.win);
containerService.attachToGlobal(this.win);
};
}
}

View File

@@ -2,7 +2,7 @@ import { Injectable } from "@angular/core";
import { PasswordRepromptService as BasePasswordRepromptService } from "@bitwarden/angular/services/passwordReprompt.service";
import { PasswordRepromptComponent } from "../app/components/password-reprompt.component";
import { PasswordRepromptComponent } from "../components/password-reprompt.component";
@Injectable()
export class PasswordRepromptService extends BasePasswordRepromptService {

View File

@@ -1,7 +1,7 @@
import { StateMigrationService as BaseStateMigrationService } from "@bitwarden/common/services/stateMigration.service";
import { Account } from "../models/account";
import { GlobalState } from "../models/globalState";
import { Account } from "./state/account";
import { GlobalState } from "./state/global-state";
export class StateMigrationService extends BaseStateMigrationService<GlobalState, Account> {
protected async migrationStateFrom1To2(): Promise<void> {

View File

@@ -0,0 +1,3 @@
export * from "./account";
export * from "./global-state";
export * from "./state.service";

View File

@@ -1,3 +1,15 @@
import { Inject, Injectable } from "@angular/core";
import {
MEMORY_STORAGE,
SECURE_STORAGE,
STATE_FACTORY,
STATE_SERVICE_USE_CACHE,
} from "@bitwarden/angular/services/jslib-services.module";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { StateMigrationService } from "@bitwarden/common/abstractions/stateMigration.service";
import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service";
import { StateFactory } from "@bitwarden/common/factories/stateFactory";
import { CipherData } from "@bitwarden/common/models/data/cipherData";
import { CollectionData } from "@bitwarden/common/models/data/collectionData";
import { FolderData } from "@bitwarden/common/models/data/folderData";
@@ -5,16 +17,33 @@ import { SendData } from "@bitwarden/common/models/data/sendData";
import { StorageOptions } from "@bitwarden/common/models/domain/storageOptions";
import { StateService as BaseStateService } from "@bitwarden/common/services/state.service";
import { StateService as StateServiceAbstraction } from "../abstractions/state.service";
import { Account } from "../models/account";
import { GlobalState } from "../models/globalState";
import { Account } from "./account";
import { GlobalState } from "./global-state";
@Injectable()
export class StateService extends BaseStateService<GlobalState, Account> {
constructor(
storageService: AbstractStorageService,
@Inject(SECURE_STORAGE) secureStorageService: AbstractStorageService,
@Inject(MEMORY_STORAGE) memoryStorageService: AbstractStorageService,
logService: LogService,
stateMigrationService: StateMigrationService,
@Inject(STATE_FACTORY) stateFactory: StateFactory<GlobalState, Account>,
@Inject(STATE_SERVICE_USE_CACHE) useAccountCache = true
) {
super(
storageService,
secureStorageService,
memoryStorageService,
logService,
stateMigrationService,
stateFactory,
useAccountCache
);
}
export class StateService
extends BaseStateService<GlobalState, Account>
implements StateServiceAbstraction
{
async addAccount(account: Account) {
// Apply web overides to default account values
// Apply web overrides to default account values
account = new Account(account);
await super.addAccount(account);
}

View File

@@ -4,7 +4,9 @@ import { ActivatedRouteSnapshot, CanActivate, Router } from "@angular/router";
import { AuthService } from "@bitwarden/common/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/enums/authenticationStatus";
@Injectable()
@Injectable({
providedIn: "root",
})
export class HomeGuard implements CanActivate {
constructor(private router: Router, private authService: AuthService) {}

View File

@@ -44,9 +44,9 @@
<i class="bwi bwi-caret-down bwi-sm" aria-hidden="true"></i>
</button>
<bit-menu class="dropdown-menu" #accountMenu>
<div class="tw-max-w-[300px] tw-min-w-[200px] tw-flex tw-flex-col">
<div class="tw-flex tw-min-w-[200px] tw-max-w-[300px] tw-flex-col">
<div
class="tw-flex tw-items-center tw-leading-tight tw-text-info tw-py-1 tw-px-4"
class="tw-flex tw-items-center tw-py-1 tw-px-4 tw-leading-tight tw-text-info"
*ngIf="name"
appStopProp
>
@@ -59,7 +59,7 @@
></app-avatar>
<div class="tw-ml-2 tw-block tw-overflow-hidden tw-whitespace-nowrap">
<span>{{ "loggedInAs" | i18n }}</span>
<small class="tw-text-muted tw-block tw-overflow-hidden tw-whitespace-nowrap">{{
<small class="tw-block tw-overflow-hidden tw-whitespace-nowrap tw-text-muted">{{
name
}}</small>
</div>

View File

@@ -31,8 +31,8 @@ import { NavbarComponent } from "../layouts/navbar.component";
import { UserLayoutComponent } from "../layouts/user-layout.component";
import { OrganizationLayoutComponent } from "../organizations/layouts/organization-layout.component";
import { BulkConfirmComponent as OrgBulkConfirmComponent } from "../organizations/manage/bulk/bulk-confirm.component";
import { BulkDeactivateComponent as OrgBulkDeactivateomponent } from "../organizations/manage/bulk/bulk-deactivate.component";
import { BulkRemoveComponent as OrgBulkRemoveComponent } from "../organizations/manage/bulk/bulk-remove.component";
import { BulkRestoreRevokeComponent as OrgBulkRestoreRevokeComponent } from "../organizations/manage/bulk/bulk-restore-revoke.component";
import { BulkStatusComponent as OrgBulkStatusComponent } from "../organizations/manage/bulk/bulk-status.component";
import { CollectionAddEditComponent as OrgCollectionAddEditComponent } from "../organizations/manage/collection-add-edit.component";
import { CollectionsComponent as OrgManageCollectionsComponent } from "../organizations/manage/collections.component";
@@ -239,7 +239,7 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
OrganizationSubscriptionComponent,
OrgAttachmentsComponent,
OrgBulkConfirmComponent,
OrgBulkDeactivateomponent,
OrgBulkRestoreRevokeComponent,
OrgBulkRemoveComponent,
OrgBulkStatusComponent,
OrgCiphersComponent,
@@ -394,7 +394,7 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
OrganizationSubscriptionComponent,
OrgAttachmentsComponent,
OrgBulkConfirmComponent,
OrgBulkDeactivateomponent,
OrgBulkRestoreRevokeComponent,
OrgBulkRemoveComponent,
OrgBulkStatusComponent,
OrgCiphersComponent,

View File

@@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { FormGroup } from "@angular/forms";
import { UntypedFormGroup } from "@angular/forms";
@Component({
selector: "app-org-info",
@@ -10,6 +10,6 @@ export class OrganizationInformationComponent {
@Input() createOrganization = true;
@Input() isProvider = false;
@Input() acceptingSponsorship = false;
@Input() formGroup: FormGroup;
@Input() formGroup: UntypedFormGroup;
@Output() changedBusinessOwned = new EventEmitter<void>();
}

View File

@@ -34,7 +34,6 @@
<input
id="register-form_input_master-password"
bitInput
(input)="updatePasswordStrength()"
type="{{ showPassword ? 'text' : 'password' }}"
formControlName="masterPassword"
/>
@@ -50,7 +49,13 @@
{{ "masterPassImportant" | i18n }}
</bit-hint>
</bit-form-field>
<app-password-strength [score]="masterPasswordScore" [showText]="true">
<app-password-strength
[password]="formGroup.get('masterPassword')?.value"
[email]="formGroup.get('email')?.value"
[name]="formGroup.get('name')?.value"
[showText]="true"
(passwordStrengthResult)="getStrengthResult($event)"
>
</app-password-strength>
</div>
@@ -85,11 +90,11 @@
<iframe id="hcaptcha_iframe" height="80"></iframe>
</div>
<div class="tw-flex tw-items-start tw-mb-3" *ngIf="showTerms">
<div class="tw-flex tw-items-center tw-h-6">
<div class="tw-mb-3 tw-flex tw-items-start" *ngIf="showTerms">
<div class="tw-flex tw-h-6 tw-items-center">
<input
id="register-form_input_accept-policies"
class="tw-w-4 tw-rounded tw-border tw-border-gray-300"
class="tw-border-gray-300 tw-w-4 tw-rounded tw-border"
bitInput
type="checkbox"
formControlName="acceptPolicies"
@@ -107,13 +112,13 @@
</bit-label>
</div>
<div class="tw-flex tw-mb-3">
<div class="tw-mb-3 tw-flex">
<bit-submit-button [loading]="form.loading">{{ "createAccount" | i18n }}</bit-submit-button>
<a
bitButton
buttonType="secondary"
routerLink="/login"
class="tw-inline-flex tw-items-center tw-ml-3 tw-px-3"
class="tw-ml-3 tw-inline-flex tw-items-center tw-px-3"
>
<i class="bwi bwi-sign-in tw-mr-2"></i>
{{ "logIn" | i18n }}

View File

@@ -1,5 +1,5 @@
import { Component, Input } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { UntypedFormBuilder } from "@angular/forms";
import { Router } from "@angular/router";
import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component";
@@ -28,7 +28,7 @@ export class RegisterFormComponent extends BaseRegisterComponent {
constructor(
formValidationErrorService: FormValidationErrorsService,
formBuilder: FormBuilder,
formBuilder: UntypedFormBuilder,
authService: AuthService,
router: Router,
i18nService: I18nService,
@@ -69,7 +69,7 @@ export class RegisterFormComponent extends BaseRegisterComponent {
if (
this.enforcedPolicyOptions != null &&
!this.policyService.evaluateMasterPassword(
this.masterPasswordScore,
this.passwordStrengthResult.score,
this.formGroup.get("masterPassword")?.value,
this.enforcedPolicyOptions
)

View File

@@ -66,7 +66,6 @@ import {
MenuModule,
} from "@bitwarden/components";
import { PasswordStrengthComponent } from "../components/password-strength.component";
import { PaymentComponent } from "../settings/payment.component";
import { TaxInfoComponent } from "../settings/tax-info.component";
@@ -122,7 +121,7 @@ registerLocaleData(localeZhCn, "zh-CN");
registerLocaleData(localeZhTw, "zh-TW");
@NgModule({
declarations: [PasswordStrengthComponent, PaymentComponent, TaxInfoComponent],
declarations: [PaymentComponent, TaxInfoComponent],
imports: [
CommonModule,
DragDropModule,
@@ -158,7 +157,6 @@ registerLocaleData(localeZhTw, "zh-TW");
MenuModule,
FormFieldModule,
SubmitButtonModule,
PasswordStrengthComponent,
PaymentComponent,
TaxInfoComponent,
],

View File

@@ -1,12 +1,12 @@
<form #form [formGroup]="formGroup" [appApiAction]="formPromise" (ngSubmit)="submit()">
<div class="tw-container tw-mb-3">
<div class="tw-mb-6">
<h2 class="tw-text-base tw-font-semibold tw-mb-3">{{ "billingPlanLabel" | i18n }}</h2>
<div class="tw-items-center tw-mb-1" *ngFor="let selectablePlan of selectablePlans">
<label class="tw-block tw- tw-text-main" for="interval{{ selectablePlan.type }}">
<h2 class="tw-mb-3 tw-text-base tw-font-semibold">{{ "billingPlanLabel" | i18n }}</h2>
<div class="tw-mb-1 tw-items-center" *ngFor="let selectablePlan of selectablePlans">
<label class="tw- tw-block tw-text-main" for="interval{{ selectablePlan.type }}">
<input
checked
class="tw-w-4 tw-h-4 tw-align-middle"
class="tw-h-4 tw-w-4 tw-align-middle"
id="interval{{ selectablePlan.type }}"
name="plan"
type="radio"
@@ -34,7 +34,7 @@
</div>
<div class="tw-mb-4">
<h2 class="tw-text-base tw-mb-3 tw-font-semibold">{{ "paymentType" | i18n }}</h2>
<h2 class="tw-mb-3 tw-text-base tw-font-semibold">{{ "paymentType" | i18n }}</h2>
<app-payment [hideCredit]="true" [trialFlow]="true"></app-payment>
<app-tax-info [trialFlow]="true" (onCountryChanged)="changedCountry()"></app-tax-info>
</div>

View File

@@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { FormBuilder, FormGroup } from "@angular/forms";
import { UntypedFormBuilder, FormGroup } from "@angular/forms";
import { Router } from "@angular/router";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
@@ -11,6 +11,7 @@ import { OrganizationService } from "@bitwarden/common/abstractions/organization
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { PolicyService } from "@bitwarden/common/abstractions/policy.service";
import { SyncService } from "@bitwarden/common/abstractions/sync.service";
import { ProductType } from "@bitwarden/common/enums/productType";
import { OrganizationPlansComponent } from "src/app/settings/organization-plans.component";
@@ -33,7 +34,7 @@ export class BillingComponent extends OrganizationPlansComponent {
organizationService: OrganizationService,
logService: LogService,
messagingService: MessagingService,
formBuilder: FormBuilder
formBuilder: UntypedFormBuilder
) {
super(
apiService,
@@ -51,10 +52,11 @@ export class BillingComponent extends OrganizationPlansComponent {
}
async ngOnInit() {
const additionalSeats = this.product == ProductType.Families ? 0 : 1;
this.formGroup.patchValue({
name: this.orgInfoForm.get("name")?.value,
billingEmail: this.orgInfoForm.get("email")?.value,
additionalSeats: 1,
additionalSeats: additionalSeats,
plan: this.plan,
product: this.product,
});

View File

@@ -3,7 +3,7 @@
<h2>What you can do with Bitwarden for Enterprise</h2>
</div>
<div class="tw-text-3xl tw-text-main tw-mt-12">
<div class="tw-mt-12 tw-text-3xl tw-text-main">
<p class="tw-mt-2.5 tw-mb-20">Collaborate and share securely</p>
<p class="tw-mt-2.5 tw-mb-20">Deploy and manage quickly and easily</p>
<p class="tw-mt-2.5 tw-mb-20">Access anywhere on any device</p>

View File

@@ -5,7 +5,7 @@
storage and sharing.
</h2>
</div>
<div class="tw-text-3xl tw-text-main tw-mt-12">
<div class="tw-mt-12 tw-text-3xl tw-text-main">
<p class="tw-mt-2.5 tw-mb-20">Collaborate and share securely</p>
<p class="tw-mt-2.5 tw-mb-20">Deploy and manage quickly and easily</p>
<p class="tw-mt-2.5 tw-mb-20">Access anywhere on any device</p>

View File

@@ -2,7 +2,7 @@
<div class="tw-pt-24">
<h2>What you can do with Btiwarden for Teams</h2>
</div>
<div class="tw-text-3xl tw-text-main tw-mt-12">
<div class="tw-mt-12 tw-text-3xl tw-text-main">
<p class="tw-mt-2.5 tw-mb-20">Collaborate and share securely</p>
<p class="tw-mt-2.5 tw-mb-20">Deploy and manage quickly and easily</p>
<p class="tw-mt-2.5 tw-mb-20">Access anywhere on any device</p>

View File

@@ -1,7 +1,7 @@
<div *ngIf="accountCreateOnly" class="">
<h1 class="tw-text-xl tw-text-center tw-mt-12" *ngIf="!layout">{{ "createAccount" | i18n }}</h1>
<h1 class="tw-mt-12 tw-text-center tw-text-xl" *ngIf="!layout">{{ "createAccount" | i18n }}</h1>
<div
class="tw-m-auto tw-rounded tw-border tw-border-solid tw-bg-background tw-border-secondary-300 tw-min-w-xl tw-max-w-xl tw-p-8"
class="tw-min-w-xl tw-m-auto tw-max-w-xl tw-rounded tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-8"
>
<app-register-form
[queryParamEmail]="email"
@@ -11,9 +11,9 @@
</div>
<div *ngIf="!accountCreateOnly">
<div
class="tw-bg-background-alt2 tw-h-96 tw--mt-48 tw-absolute tw--skew-y-3 tw-w-full tw--z-10"
class="tw-absolute tw--z-10 tw--mt-48 tw-h-96 tw-w-full tw--skew-y-3 tw-bg-background-alt2"
></div>
<div class="tw-flex tw-max-w-screen-xl tw-min-w-4xl tw-mx-auto tw-px-4">
<div class="tw-min-w-4xl tw-mx-auto tw-flex tw-max-w-screen-xl tw-px-4">
<div class="tw-w-1/2">
<img
alt="Bitwarden"
@@ -33,9 +33,9 @@
</div>
<div class="tw-w-1/2">
<div class="tw-pt-56">
<div class="tw-rounded tw-border tw-border-solid tw-bg-background tw-border-secondary-300">
<div class="tw-h-12 tw-flex tw-items-center tw-rounded-t tw-bg-secondary-100 tw-w-full">
<h2 class="tw-uppercase tw-pl-4 tw-text-base tw-mb-0 tw-font-bold">
<div class="tw-rounded tw-border tw-border-solid tw-border-secondary-300 tw-bg-background">
<div class="tw-flex tw-h-12 tw-w-full tw-items-center tw-rounded-t tw-bg-secondary-100">
<h2 class="tw-mb-0 tw-pl-4 tw-text-base tw-font-bold tw-uppercase">
Start your 7-Day free trial of Bitwarden for {{ org }}
</h2>
</div>
@@ -72,7 +72,7 @@
[email]="email"
[orgLabel]="orgLabel"
></app-trial-confirmation-details>
<div class="tw-flex tw-mb-3">
<div class="tw-mb-3 tw-flex">
<button bitButton buttonType="primary" (click)="navigateToOrgVault()">
Get Started
</button>
@@ -80,7 +80,7 @@
bitButton
buttonType="secondary"
(click)="navigateToOrgInvite()"
class="tw-inline-flex tw-items-center tw-ml-3 tw-px-3"
class="tw-ml-3 tw-inline-flex tw-items-center tw-px-3"
>
Invite Users
</button>

View File

@@ -1,7 +1,7 @@
import { StepperSelectionEvent } from "@angular/cdk/stepper";
import { TitleCasePipe } from "@angular/common";
import { Component, OnInit, ViewChild } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { UntypedFormBuilder, Validators } from "@angular/forms";
import { ActivatedRoute, Router } from "@angular/router";
import { first } from "rxjs";
@@ -34,6 +34,7 @@ export class TrialInitiationComponent implements OnInit {
accountCreateOnly = true;
policies: Policy[];
enforcedPolicyOptions: MasterPasswordPolicyOptions;
validOrgs: string[] = ["teams", "enterprise", "families"];
@ViewChild("stepper", { static: false }) verticalStepper: VerticalStepperComponent;
orgInfoFormGroup = this.formBuilder.group({
@@ -44,7 +45,7 @@ export class TrialInitiationComponent implements OnInit {
constructor(
private route: ActivatedRoute,
protected router: Router,
private formBuilder: FormBuilder,
private formBuilder: UntypedFormBuilder,
private titleCasePipe: TitleCasePipe,
private stateService: StateService,
private apiService: ApiService,
@@ -63,17 +64,22 @@ export class TrialInitiationComponent implements OnInit {
return;
}
this.org = qParams.org;
if (this.validOrgs.includes(qParams.org)) {
this.org = qParams.org;
} else {
this.org = "families";
}
this.orgLabel = this.titleCasePipe.transform(this.org);
this.accountCreateOnly = false;
if (qParams.org === "families") {
if (this.org === "families") {
this.plan = PlanType.FamiliesAnnually;
this.product = ProductType.Families;
} else if (qParams.org === "teams") {
} else if (this.org === "teams") {
this.plan = PlanType.TeamsAnnually;
this.product = ProductType.Teams;
} else if (qParams.org === "enterprise") {
} else if (this.org === "enterprise") {
this.plan = PlanType.EnterpriseAnnually;
this.product = ProductType.Enterprise;
}

View File

@@ -129,21 +129,21 @@
<button class="filter-button" (click)="applyOrganizationFilter(organization)">
<i class="bwi bwi-fw bwi-business" aria-hidden="true"></i>
{{ organization.name }}
</button>
<span class="ml-auto contents">
<i
*ngIf="!organization.enabled"
class="bwi bwi-fw bwi-exclamation-triangle text-danger"
class="org-options bwi bwi-fw bwi-exclamation-triangle text-danger"
aria-label="{{ 'organizationIsDisabled' | i18n }}"
appA11yTitle="{{ 'organizationIsDisabled' | i18n }}"
></i>
</button>
<ng-container>
<button [bitMenuTriggerFor]="orgMenu" class="org-options ml-auto">
></i
><button [bitMenuTriggerFor]="orgMenu" class="org-options">
<i class="bwi bwi-ellipsis-v" aria-hidden="true"></i>
</button>
<bit-menu class="filter-organization-options" #orgMenu>
<app-organization-options [organization]="organization"></app-organization-options>
</bit-menu>
</ng-container>
</span>
</span>
</li>
<li class="filter-option" *ngIf="!(displayMode === 'singleOrganizationPolicy')">

View File

@@ -8,12 +8,12 @@
</ng-container>
<div
*ngIf="loaded"
class="tw-max-w-[300px] tw-min-w-[200px] tw-flex tw-flex-col"
class="tw-flex tw-min-w-[200px] tw-max-w-[300px] tw-flex-col"
[appApiAction]="actionPromise"
>
<button
*ngIf="allowEnrollmentChanges(organization) && !organization.resetPasswordEnrolled"
class="dropdown-item"
class="tw-block tw-cursor-pointer tw-border-none tw-bg-background tw-px-4 tw-py-2 tw-text-left !tw-text-main hover:tw-bg-secondary-100 focus:tw-z-50 focus:tw-bg-secondary-100 focus:tw-outline-none focus:tw-ring focus:tw-ring-primary-700 focus:tw-ring-offset-2 active:!tw-ring-0 active:!tw-ring-offset-0"
(click)="toggleResetPasswordEnrollment(organization)"
>
<i class="bwi bwi-fw bwi-key" aria-hidden="true"></i>
@@ -21,7 +21,7 @@
</button>
<button
*ngIf="allowEnrollmentChanges(organization) && organization.resetPasswordEnrolled"
class="dropdown-item"
class="tw-block tw-cursor-pointer tw-border-none tw-bg-background tw-px-4 tw-py-2 tw-text-left !tw-text-main hover:tw-bg-secondary-100 focus:tw-z-50 focus:tw-bg-secondary-100 focus:tw-outline-none focus:tw-ring focus:tw-ring-primary-700 focus:tw-ring-offset-2 active:!tw-ring-0 active:!tw-ring-offset-0"
(click)="toggleResetPasswordEnrollment(organization)"
>
<i class="bwi bwi-fw bwi-undo" aria-hidden="true"></i>
@@ -30,7 +30,7 @@
<ng-container *ngIf="organization.useSso && organization.identifier">
<button
*ngIf="organization.ssoBound; else linkSso"
class="dropdown-item"
class="tw-block tw-cursor-pointer tw-border-none tw-bg-background tw-px-4 tw-py-2 tw-text-left !tw-text-main hover:tw-bg-secondary-100 focus:tw-z-50 focus:tw-bg-secondary-100 focus:tw-outline-none focus:tw-ring focus:tw-ring-primary-700 focus:tw-ring-offset-2 active:!tw-ring-0 active:!tw-ring-offset-0"
(click)="unlinkSso(organization)"
>
<i class="bwi bwi-fw bwi-chain-broken" aria-hidden="true"></i>
@@ -40,7 +40,10 @@
<app-link-sso [organization]="organization"> </app-link-sso>
</ng-template>
</ng-container>
<button class="dropdown-item text-danger" (click)="leave(organization)">
<button
class="text-danger tw-block tw-cursor-pointer tw-border-none tw-bg-background tw-px-4 tw-py-2 tw-text-left hover:tw-bg-secondary-100 focus:tw-z-50 focus:tw-bg-secondary-100 focus:tw-outline-none focus:tw-ring focus:tw-ring-primary-700 focus:tw-ring-offset-2 active:!tw-ring-0 active:!tw-ring-offset-0"
(click)="leave(organization)"
>
<i class="bwi bwi-fw bwi-sign-out" aria-hidden="true"></i>
{{ "leave" | i18n }}
</button>

View File

@@ -1,38 +1,38 @@
<div class="tw-m-2.5 tw-text-center tw-h-16">
<div class="tw-m-2.5 tw-h-16 tw-text-center">
<button
(click)="selectStep()"
[disabled]="disabled"
class="tw-w-full tw-flex tw-border-none tw-bg-transparent tw-items-center"
class="tw-flex tw-w-full tw-items-center tw-border-none tw-bg-transparent"
[ngClass]="{
'hover:tw-bg-secondary-100': !disabled && step.editable
}"
[attr.aria-expanded]="selected"
>
<span
class="tw-rounded-full tw-font-bold tw-leading-9 tw-mr-3.5 tw-w-9"
class="tw-mr-3.5 tw-w-9 tw-rounded-full tw-font-bold tw-leading-9"
*ngIf="!step.completed"
[ngClass]="{
'tw-text-contrast tw-bg-primary-500': selected,
'tw-text-main tw-bg-secondary-300': !selected && !disabled && step.editable,
'tw-text-muted tw-bg-transparent': disabled
'tw-bg-primary-500 tw-text-contrast': selected,
'tw-bg-secondary-300 tw-text-main': !selected && !disabled && step.editable,
'tw-bg-transparent tw-text-muted': disabled
}"
>
{{ stepNumber }}
</span>
<span
class="tw-text-contrast tw-bg-primary-500 tw-rounded-full tw-font-bold tw-leading-9 tw-mr-3.5 tw-w-9"
class="tw-mr-3.5 tw-w-9 tw-rounded-full tw-bg-primary-500 tw-font-bold tw-leading-9 tw-text-contrast"
*ngIf="step.completed"
>
<i class="bwi bwi-fw bwi-check tw-p-1" aria-hidden="true"></i>
</span>
<div
class="tw-text-left tw-txt-main tw-leading-snug tw-h-12 tw-mt-3.5"
class="tw-txt-main tw-mt-3.5 tw-h-12 tw-text-left tw-leading-snug"
[ngClass]="{
'tw-font-bold': selected
}"
>
<p
class="main-label text tw-text-main tw-mb-1"
class="main-label text tw-mb-1 tw-text-main"
[ngClass]="{
'tw-mt-1': !step.subLabel
}"

View File

@@ -1,6 +1,6 @@
<ng-template>
<div
class="tw-pl-7 tw-inline-block tw-w-11/12"
class="tw-inline-block tw-w-11/12 tw-pl-7"
[ngClass]="{ 'tw-border-0 tw-border-l tw-border-solid tw-border-secondary-300': applyBorder }"
>
<ng-content></ng-content>

View File

@@ -9,12 +9,12 @@
(onSelectStep)="selectStepByIndex(i)"
></app-vertical-step-content>
<div
class="tw-pl-7 tw-inline-block"
class="tw-inline-block tw-pl-7"
*ngIf="selectedIndex === i"
[ngTemplateOutlet]="selected ? selected.content : null"
></div>
<div
class="tw-h-6 tw-ml-8 tw-border-0 tw-border-l tw-border-solid tw-border-secondary-300"
class="tw-ml-8 tw-h-6 tw-border-0 tw-border-l tw-border-solid tw-border-secondary-300"
*ngIf="!isLast && !(selectedIndex === i)"
></div>
</li>

View File

@@ -7,7 +7,9 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti
import { SyncService } from "@bitwarden/common/abstractions/sync.service";
import { Permissions } from "@bitwarden/common/enums/permissions";
@Injectable()
@Injectable({
providedIn: "root",
})
export class PermissionsGuard implements CanActivate {
constructor(
private router: Router,

View File

@@ -22,7 +22,7 @@
{{ error }}
</app-callout>
<ng-container *ngIf="!done">
<app-callout type="warning" *ngIf="users.length > 0 && !error && isDeactivating">
<app-callout type="warning" *ngIf="users.length > 0 && !error && isRevoking">
{{ "revokeUsersWarning" | i18n }}
</app-callout>
<table class="table table-hover table-list">

View File

@@ -8,11 +8,11 @@ import { OrganizationUserBulkRequest } from "@bitwarden/common/models/request/or
import { BulkUserDetails } from "./bulk-status.component";
@Component({
selector: "app-bulk-deactivate",
templateUrl: "bulk-deactivate.component.html",
selector: "app-bulk-restore-revoke",
templateUrl: "bulk-restore-revoke.component.html",
})
export class BulkDeactivateComponent {
isDeactivating: boolean;
export class BulkRestoreRevokeComponent {
isRevoking: boolean;
organizationId: string;
users: BulkUserDetails[];
@@ -27,13 +27,13 @@ export class BulkDeactivateComponent {
protected i18nService: I18nService,
config: ModalConfig
) {
this.isDeactivating = config.data.isDeactivating;
this.isRevoking = config.data.isRevoking;
this.organizationId = config.data.organizationId;
this.users = config.data.users;
}
get bulkTitle() {
const titleKey = this.isDeactivating ? "revokeUsers" : "restoreUsers";
const titleKey = this.isRevoking ? "revokeUsers" : "restoreUsers";
return this.i18nService.t(titleKey);
}
@@ -42,7 +42,7 @@ export class BulkDeactivateComponent {
try {
const response = await this.performBulkUserAction();
const bulkMessage = this.isDeactivating ? "bulkRevokedMessage" : "bulkRestoredMessage";
const bulkMessage = this.isRevoking ? "bulkRevokedMessage" : "bulkRestoredMessage";
response.data.forEach((entry) => {
const error = entry.error !== "" ? entry.error : this.i18nService.t(bulkMessage);
this.statuses.set(entry.id, error);
@@ -57,10 +57,10 @@ export class BulkDeactivateComponent {
protected async performBulkUserAction() {
const request = new OrganizationUserBulkRequest(this.users.map((user) => user.id));
if (this.isDeactivating) {
return await this.apiService.deactivateManyOrganizationUsers(this.organizationId, request);
if (this.isRevoking) {
return await this.apiService.revokeManyOrganizationUsers(this.organizationId, request);
} else {
return await this.apiService.activateManyOrganizationUsers(this.organizationId, request);
return await this.apiService.restoreManyOrganizationUsers(this.organizationId, request);
}
}
}

View File

@@ -8,7 +8,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti
import { EventResponse } from "@bitwarden/common/models/response/eventResponse";
import { ListResponse } from "@bitwarden/common/models/response/listResponse";
import { EventService } from "../../services/event.service";
import { EventService } from "../../core";
@Component({
selector: "app-entity-events",

View File

@@ -14,7 +14,7 @@ import { Organization } from "@bitwarden/common/models/domain/organization";
import { EventResponse } from "@bitwarden/common/models/response/eventResponse";
import { BaseEventsComponent } from "../../common/base.events.component";
import { EventService } from "../../services/event.service";
import { EventService } from "../../core";
@Component({
selector: "app-org-events",

View File

@@ -32,11 +32,11 @@
<button
type="button"
class="btn btn-outline-secondary"
[ngClass]="{ active: status == userStatusType.Deactivated }"
(click)="filter(userStatusType.Deactivated)"
[ngClass]="{ active: status == userStatusType.Revoked }"
(click)="filter(userStatusType.Revoked)"
>
{{ "revoked" | i18n }}
<span bitBadge badgeType="info" *ngIf="deactivatedCount">{{ deactivatedCount }}</span>
<span bitBadge badgeType="info" *ngIf="revokedCount">{{ revokedCount }}</span>
</button>
</div>
<div class="ml-3">
@@ -75,11 +75,11 @@
<i class="bwi bwi-fw bwi-check" aria-hidden="true"></i>
{{ "confirmSelected" | i18n }}
</button>
<button class="dropdown-item" appStopClick (click)="bulkActivate()">
<button class="dropdown-item" appStopClick (click)="bulkRestore()">
<i class="bwi bwi-fw bwi-plus-circle" aria-hidden="true"></i>
{{ "restoreAccess" | i18n }}
</button>
<button class="dropdown-item" appStopClick (click)="bulkDeactivate()">
<button class="dropdown-item" appStopClick (click)="bulkRevoke()">
<i class="bwi bwi-fw bwi-minus-circle" aria-hidden="true"></i>
{{ "revokeAccess" | i18n }}
</button>
@@ -158,7 +158,7 @@
<span bitBadge badgeType="warning" *ngIf="u.status === userStatusType.Accepted">{{
"accepted" | i18n
}}</span>
<span bitBadge badgeType="secondary" *ngIf="u.status === userStatusType.Deactivated">{{
<span bitBadge badgeType="secondary" *ngIf="u.status === userStatusType.Revoked">{{
"revoked" | i18n
}}</span>
<small class="text-muted d-block" *ngIf="u.name">{{ u.name }}</small>
@@ -255,8 +255,8 @@
class="dropdown-item"
href="#"
appStopClick
(click)="activate(u)"
*ngIf="u.status === userStatusType.Deactivated"
(click)="restore(u)"
*ngIf="u.status === userStatusType.Revoked"
>
<i class="bwi bwi-fw bwi-plus-circle" aria-hidden="true"></i>
{{ "restoreAccess" | i18n }}
@@ -265,8 +265,8 @@
class="dropdown-item"
href="#"
appStopClick
(click)="deactivate(u)"
*ngIf="u.status !== userStatusType.Deactivated"
(click)="revoke(u)"
*ngIf="u.status !== userStatusType.Revoked"
>
<i class="bwi bwi-fw bwi-minus-circle" aria-hidden="true"></i>
{{ "revokeAccess" | i18n }}

View File

@@ -29,8 +29,8 @@ import { OrganizationUserUserDetailsResponse } from "@bitwarden/common/models/re
import { BasePeopleComponent } from "../../common/base.people.component";
import { BulkConfirmComponent } from "./bulk/bulk-confirm.component";
import { BulkDeactivateComponent } from "./bulk/bulk-deactivate.component";
import { BulkRemoveComponent } from "./bulk/bulk-remove.component";
import { BulkRestoreRevokeComponent } from "./bulk/bulk-restore-revoke.component";
import { BulkStatusComponent } from "./bulk/bulk-status.component";
import { EntityEventsComponent } from "./entity-events.component";
import { ResetPasswordComponent } from "./reset-password.component";
@@ -167,12 +167,12 @@ export class PeopleComponent
return this.apiService.deleteOrganizationUser(this.organizationId, id);
}
deactivateUser(id: string): Promise<any> {
return this.apiService.deactivateOrganizationUser(this.organizationId, id);
revokeUser(id: string): Promise<any> {
return this.apiService.revokeOrganizationUser(this.organizationId, id);
}
activateUser(id: string): Promise<any> {
return this.apiService.activateOrganizationUser(this.organizationId, id);
restoreUser(id: string): Promise<any> {
return this.apiService.restoreOrganizationUser(this.organizationId, id);
}
reinviteUser(id: string): Promise<any> {
@@ -245,11 +245,11 @@ export class PeopleComponent
modal.close();
this.removeUser(user);
});
comp.onDeactivatedUser.subscribe(() => {
comp.onRevokedUser.subscribe(() => {
modal.close();
this.load();
});
comp.onActivatedUser.subscribe(() => {
comp.onRestoredUser.subscribe(() => {
modal.close();
this.load();
});
@@ -290,25 +290,25 @@ export class PeopleComponent
await this.load();
}
async bulkDeactivate() {
await this.bulkActivateOrDeactivate(true);
async bulkRevoke() {
await this.bulkRevokeOrRestore(true);
}
async bulkActivate() {
await this.bulkActivateOrDeactivate(false);
async bulkRestore() {
await this.bulkRevokeOrRestore(false);
}
async bulkActivateOrDeactivate(isDeactivating: boolean) {
async bulkRevokeOrRestore(isRevoking: boolean) {
if (this.actionPromise != null) {
return;
}
const ref = this.modalService.open(BulkDeactivateComponent, {
const ref = this.modalService.open(BulkRestoreRevokeComponent, {
allowMultipleModals: true,
data: {
organizationId: this.organizationId,
users: this.getCheckedUsers(),
isDeactivating: isDeactivating,
isRevoking: isRevoking,
},
});

View File

@@ -9,7 +9,7 @@ import { PolicyType } from "@bitwarden/common/enums/policyType";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { PolicyResponse } from "@bitwarden/common/models/response/policyResponse";
import { PolicyListService } from "../../services/policy-list.service";
import { PolicyListService } from "../../core";
import { BasePolicy } from "../policies/base-policy.component";
import { PolicyEditComponent } from "./policy-edit.component";

View File

@@ -53,7 +53,6 @@
required
appInputVerbatim
autocomplete="new-password"
(input)="updatePasswordStrength()"
/>
<div class="input-group-append">
<button
@@ -78,7 +77,7 @@
</button>
</div>
</div>
<app-password-strength [score]="masterPasswordScore" [showText]="true">
<app-password-strength [password]="newPassword" [email]="email" [showText]="true">
</app-password-strength>
</div>
</div>

View File

@@ -1,5 +1,6 @@
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from "@angular/core";
import { PasswordStrengthComponent } from "@bitwarden/angular/shared/components/password-strength/password-strength.component";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
@@ -22,13 +23,13 @@ export class ResetPasswordComponent implements OnInit {
@Input() id: string;
@Input() organizationId: string;
@Output() onPasswordReset = new EventEmitter();
@ViewChild(PasswordStrengthComponent) passwordStrengthComponent: PasswordStrengthComponent;
enforcedPolicyOptions: MasterPasswordPolicyOptions;
newPassword: string = null;
showPassword = false;
masterPasswordScore: number;
formPromise: Promise<any>;
private newPasswordStrengthTimeout: any;
constructor(
private apiService: ApiService,
@@ -52,7 +53,7 @@ export class ResetPasswordComponent implements OnInit {
async generatePassword() {
const options = (await this.passwordGenerationService.getOptions())[0];
this.newPassword = await this.passwordGenerationService.generatePassword(options);
this.updatePasswordStrength();
this.passwordStrengthComponent.updatePasswordStrength(this.newPassword);
}
togglePassword() {
@@ -183,35 +184,4 @@ export class ResetPasswordComponent implements OnInit {
this.logService.error(e);
}
}
updatePasswordStrength() {
if (this.newPasswordStrengthTimeout != null) {
clearTimeout(this.newPasswordStrengthTimeout);
}
this.newPasswordStrengthTimeout = setTimeout(() => {
const strengthResult = this.passwordGenerationService.passwordStrength(
this.newPassword,
this.getPasswordStrengthUserInput()
);
this.masterPasswordScore = strengthResult == null ? null : strengthResult.score;
}, 300);
}
private getPasswordStrengthUserInput() {
let userInput: string[] = [];
const atPosition = this.email.indexOf("@");
if (atPosition > -1) {
userInput = userInput.concat(
this.email
.substr(0, atPosition)
.trim()
.toLowerCase()
.split(/[^A-Za-z0-9]/)
);
}
if (this.name != null && this.name !== "") {
userInput = userInput.concat(this.name.trim().toLowerCase().split(" "));
}
return userInput;
}
}

View File

@@ -11,7 +11,7 @@
<h2 class="modal-title" id="userAddEditTitle">
{{ title }}
<small class="text-muted" *ngIf="name">{{ name }}</small>
<span bitBadge badgeType="secondary" *ngIf="isDeactivated">{{ "revoked" | i18n }}</span>
<span bitBadge badgeType="secondary" *ngIf="isRevoked">{{ "revoked" | i18n }}</span>
</h2>
<button
type="button"
@@ -381,9 +381,9 @@
<div class="ml-auto">
<button
type="button"
(click)="activate()"
(click)="restore()"
class="btn btn-outline-secondary"
*ngIf="editMode && isDeactivated"
*ngIf="editMode && isRevoked"
[disabled]="form.loading"
>
<i
@@ -396,9 +396,9 @@
</button>
<button
type="button"
(click)="deactivate()"
(click)="revoke()"
class="btn btn-outline-secondary"
*ngIf="editMode && !isDeactivated"
*ngIf="editMode && !isRevoked"
[disabled]="form.loading"
>
<i

View File

@@ -27,12 +27,12 @@ export class UserAddEditComponent implements OnInit {
@Input() usesKeyConnector = false;
@Output() onSavedUser = new EventEmitter();
@Output() onDeletedUser = new EventEmitter();
@Output() onDeactivatedUser = new EventEmitter();
@Output() onActivatedUser = new EventEmitter();
@Output() onRevokedUser = new EventEmitter();
@Output() onRestoredUser = new EventEmitter();
loading = true;
editMode = false;
isDeactivated = false;
isRevoked = false;
title: string;
emails: string;
type: OrganizationUserType = OrganizationUserType.User;
@@ -101,7 +101,7 @@ export class UserAddEditComponent implements OnInit {
);
this.access = user.accessAll ? "all" : "selected";
this.type = user.type;
this.isDeactivated = user.status === OrganizationUserStatusType.Deactivated;
this.isRevoked = user.status === OrganizationUserStatusType.Revoked;
if (user.type === OrganizationUserType.Custom) {
this.permissions = user.permissions;
}
@@ -245,7 +245,7 @@ export class UserAddEditComponent implements OnInit {
}
}
async deactivate() {
async revoke() {
if (!this.editMode) {
return;
}
@@ -262,7 +262,7 @@ export class UserAddEditComponent implements OnInit {
}
try {
this.formPromise = this.apiService.deactivateOrganizationUser(
this.formPromise = this.apiService.revokeOrganizationUser(
this.organizationId,
this.organizationUserId
);
@@ -272,20 +272,20 @@ export class UserAddEditComponent implements OnInit {
null,
this.i18nService.t("revokedUserId", this.name)
);
this.isDeactivated = true;
this.onDeactivatedUser.emit();
this.isRevoked = true;
this.onRevokedUser.emit();
} catch (e) {
this.logService.error(e);
}
}
async activate() {
async restore() {
if (!this.editMode) {
return;
}
try {
this.formPromise = this.apiService.activateOrganizationUser(
this.formPromise = this.apiService.restoreOrganizationUser(
this.organizationId,
this.organizationUserId
);
@@ -295,8 +295,8 @@ export class UserAddEditComponent implements OnInit {
null,
this.i18nService.t("restoredUserId", this.name)
);
this.isDeactivated = false;
this.onActivatedUser.emit();
this.isRevoked = false;
this.onRestoredUser.emit();
} catch (e) {
this.logService.error(e);
}

View File

@@ -1,5 +1,5 @@
import { Directive, Input, OnInit } from "@angular/core";
import { FormControl, FormGroup } from "@angular/forms";
import { UntypedFormControl, UntypedFormGroup } from "@angular/forms";
import { PolicyType } from "@bitwarden/common/enums/policyType";
import { Organization } from "@bitwarden/common/models/domain/organization";
@@ -22,8 +22,8 @@ export abstract class BasePolicyComponent implements OnInit {
@Input() policyResponse: PolicyResponse;
@Input() policy: BasePolicy;
enabled = new FormControl(false);
data: FormGroup = null;
enabled = new UntypedFormControl(false);
data: UntypedFormGroup = null;
ngOnInit(): void {
this.enabled.setValue(this.policyResponse.enabled);

View File

@@ -1,5 +1,5 @@
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { UntypedFormBuilder } from "@angular/forms";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
@@ -32,7 +32,7 @@ export class MasterPasswordPolicyComponent extends BasePolicyComponent {
showKeyConnectorInfo = false;
constructor(
private formBuilder: FormBuilder,
private formBuilder: UntypedFormBuilder,
i18nService: I18nService,
private organizationService: OrganizationService
) {

View File

@@ -1,5 +1,5 @@
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { UntypedFormBuilder } from "@angular/forms";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { PolicyType } from "@bitwarden/common/enums/policyType";
@@ -34,7 +34,7 @@ export class PasswordGeneratorPolicyComponent extends BasePolicyComponent {
defaultTypes: { name: string; value: string }[];
constructor(private formBuilder: FormBuilder, i18nService: I18nService) {
constructor(private formBuilder: UntypedFormBuilder, i18nService: I18nService) {
super();
this.defaultTypes = [

View File

@@ -1,5 +1,5 @@
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { UntypedFormBuilder } from "@angular/forms";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { PolicyType } from "@bitwarden/common/enums/policyType";
@@ -30,7 +30,10 @@ export class ResetPasswordPolicyComponent extends BasePolicyComponent {
defaultTypes: { name: string; value: string }[];
showKeyConnectorInfo = false;
constructor(private formBuilder: FormBuilder, private organizationService: OrganizationService) {
constructor(
private formBuilder: UntypedFormBuilder,
private organizationService: OrganizationService
) {
super();
}

View File

@@ -1,5 +1,5 @@
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { UntypedFormBuilder } from "@angular/forms";
import { PolicyType } from "@bitwarden/common/enums/policyType";
@@ -21,7 +21,7 @@ export class SendOptionsPolicyComponent extends BasePolicyComponent {
disableHideEmail: false,
});
constructor(private formBuilder: FormBuilder) {
constructor(private formBuilder: UntypedFormBuilder) {
super();
}
}

View File

@@ -1,5 +1,5 @@
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { UntypedFormBuilder } from "@angular/forms";
import { ActivatedRoute } from "@angular/router";
import { ModalService } from "@bitwarden/angular/services/modal.service";
@@ -12,6 +12,7 @@ import { LogService } from "@bitwarden/common/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { PolicyService } from "@bitwarden/common/abstractions/policy.service";
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service";
import { EventType } from "@bitwarden/common/enums/eventType";
import { ExportComponent } from "../../../tools/import-export/export.component";
@@ -30,7 +31,7 @@ export class OrganizationExportComponent extends ExportComponent {
policyService: PolicyService,
logService: LogService,
userVerificationService: UserVerificationService,
formBuilder: FormBuilder,
formBuilder: UntypedFormBuilder,
fileDownloadService: FileDownloadService,
modalService: ModalService
) {
@@ -69,7 +70,11 @@ export class OrganizationExportComponent extends ExportComponent {
}
async collectEvent(): Promise<any> {
// TODO
// await this.eventService.collect(EventType.Organization_ClientExportedVault);
await this.eventService.collect(
EventType.Organization_ClientExportedVault,
null,
null,
this.organizationId
);
}
}

View File

@@ -63,10 +63,16 @@ const routes: Routes = [
{ path: "2fa", component: TwoFactorComponent, canActivate: [UnauthGuard] },
{
path: "register",
component: flagEnabled("showTrial") ? TrialInitiationComponent : RegisterComponent,
component: RegisterComponent,
canActivate: [UnauthGuard],
data: { titleId: "createAccount" },
},
buildFlaggedRoute("showTrial", {
path: "trial",
component: TrialInitiationComponent,
canActivate: [UnauthGuard],
data: { titleId: "startTrial" },
}),
{
path: "sso",
component: SsoComponent,

View File

@@ -1,17 +1,17 @@
<a
class="tw-border tw-border-solid tw-border-secondary-300 tw-rounded tw-overflow-hidden tw-h-full tw-w-72 tw-block !tw-text-main hover:tw-no-underline hover:tw-scale-105 tw-transition-all focus:tw-outline-none focus:tw-ring focus:tw-ring-offset-2 focus:tw-ring-primary-700"
class="tw-block tw-h-full tw-w-72 tw-overflow-hidden tw-rounded tw-border tw-border-solid tw-border-secondary-300 !tw-text-main tw-transition-all hover:tw-scale-105 hover:tw-no-underline focus:tw-outline-none focus:tw-ring focus:tw-ring-primary-700 focus:tw-ring-offset-2"
[routerLink]="route"
(click)="click()"
>
<div class="tw-relative">
<div
class="tw-text-center tw-h-28 tw-flex tw-bg-background-alt2 tw-text-primary-300"
class="tw-flex tw-h-28 tw-bg-background-alt2 tw-text-center tw-text-primary-300"
[ngClass]="{ 'tw-grayscale': premium }"
>
<div class="tw-m-auto" [innerHtml]="icon"></div>
</div>
<div class="tw-p-5" [ngClass]="{ 'tw-grayscale': report.requiresPremium }">
<h3 class="tw-text-xl tw-font-bold tw-mb-4">{{ report.title | i18n }}</h3>
<h3 class="tw-mb-4 tw-text-xl tw-font-bold">{{ report.title | i18n }}</h3>
<p class="tw-mb-0">{{ report.description | i18n }}</p>
</div>
<span

View File

@@ -10,6 +10,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti
import { SEND_KDF_ITERATIONS } from "@bitwarden/common/enums/kdfType";
import { SendType } from "@bitwarden/common/enums/sendType";
import { Utils } from "@bitwarden/common/misc/utils";
import { EncArrayBuffer } from "@bitwarden/common/models/domain/encArrayBuffer";
import { SendAccess } from "@bitwarden/common/models/domain/sendAccess";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetricCryptoKey";
import { SendAccessRequest } from "@bitwarden/common/models/request/sendAccessRequest";
@@ -109,8 +110,8 @@ export class AccessComponent implements OnInit {
}
try {
const buf = await response.arrayBuffer();
const decBuf = await this.cryptoService.decryptFromBytes(buf, this.decKey);
const encBuf = await EncArrayBuffer.fromResponse(response);
const decBuf = await this.cryptoService.decryptFromBytes(encBuf, this.decKey);
this.fileDownloadService.download({
fileName: this.send.file.fileName,
blobData: decBuf,

View File

@@ -37,15 +37,17 @@
name="NewMasterPasswordHash"
class="form-control mb-1"
[(ngModel)]="masterPassword"
(input)="updatePasswordStrength()"
required
appInputVerbatim
autocomplete="new-password"
/>
<app-password-strength
[score]="masterPasswordScore"
[password]="masterPassword"
[email]="email"
[showText]="true"
></app-password-strength>
(passwordStrengthResult)="getStrengthResult($event)"
>
</app-password-strength>
</div>
</div>
<div class="col-6">

View File

@@ -6,6 +6,7 @@
(ngSubmit)="submit()"
[appApiAction]="formPromise"
ngNativeValidate
[formGroup]="deleteForm"
>
<div class="modal-header">
<h2 class="modal-title" id="deleteAccountTitle">{{ "deleteAccount" | i18n }}</h2>
@@ -21,7 +22,7 @@
<div class="modal-body">
<p>{{ "deleteAccountDesc" | i18n }}</p>
<app-callout type="warning">{{ "deleteAccountWarning" | i18n }}</app-callout>
<app-user-verification [(ngModel)]="masterPassword" ngDefaultControl name="secret">
<app-user-verification ngDefaultControl formControlName="verification" name="verification">
</app-user-verification>
</div>
<div class="modal-footer">

View File

@@ -1,11 +1,10 @@
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountService } from "@bitwarden/common/abstractions/account/account.service.abstraction";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service";
import { Verification } from "@bitwarden/common/types/verification";
@Component({
@@ -13,30 +12,30 @@ import { Verification } from "@bitwarden/common/types/verification";
templateUrl: "delete-account.component.html",
})
export class DeleteAccountComponent {
masterPassword: Verification;
formPromise: Promise<any>;
formPromise: Promise<void>;
deleteForm = this.formBuilder.group({
verification: undefined as Verification | undefined,
});
constructor(
private apiService: ApiService,
private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService,
private userVerificationService: UserVerificationService,
private messagingService: MessagingService,
private formBuilder: FormBuilder,
private accountService: AccountService,
private logService: LogService
) {}
async submit() {
try {
this.formPromise = this.userVerificationService
.buildRequest(this.masterPassword)
.then((request) => this.apiService.deleteAccount(request));
const verification = this.deleteForm.get("verification").value;
this.formPromise = this.accountService.delete(verification);
await this.formPromise;
this.platformUtilsService.showToast(
"success",
this.i18nService.t("accountDeleted"),
this.i18nService.t("accountDeletedDesc")
);
this.messagingService.send("logout");
} catch (e) {
this.logService.error(e);
}

View File

@@ -39,12 +39,16 @@
name="NewMasterPasswordHash"
class="form-control mb-1"
[(ngModel)]="masterPassword"
(input)="updatePasswordStrength()"
required
appInputVerbatim
autocomplete="new-password"
/>
<app-password-strength [score]="masterPasswordScore" [showText]="true">
<app-password-strength
[password]="masterPassword"
[email]="email"
[showText]="true"
(passwordStrengthResult)="getStrengthResult($event)"
>
</app-password-strength>
</div>
</div>

View File

@@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { UntypedFormBuilder, Validators } from "@angular/forms";
import { Router } from "@angular/router";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
@@ -79,7 +79,7 @@ export class OrganizationPlansComponent implements OnInit {
private organizationService: OrganizationService,
private logService: LogService,
private messagingService: MessagingService,
private formBuilder: FormBuilder
private formBuilder: UntypedFormBuilder
) {
this.selfHosted = platformUtilsService.isSelfHost();
}
@@ -452,6 +452,8 @@ export class OrganizationPlansComponent implements OnInit {
const response = await this.apiService.postOrganizationLicense(fd);
const orgId = response.id;
await this.apiService.refreshIdentityToken();
// Org Keys live outside of the OrganizationLicense - add the keys to the org here
const request = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
await this.apiService.postOrganizationKeys(orgId, request);

View File

@@ -1,5 +1,5 @@
import { Component, OnInit } from "@angular/core";
import { FormControl } from "@angular/forms";
import { UntypedFormControl } from "@angular/forms";
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
@@ -25,7 +25,7 @@ export class PreferencesComponent implements OnInit {
localeOptions: any[];
themeOptions: any[];
vaultTimeout: FormControl = new FormControl(null);
vaultTimeout: UntypedFormControl = new UntypedFormControl(null);
private startingLocale: string;
private startingTheme: ThemeType;

View File

@@ -6,7 +6,7 @@ import { OrganizationService } from "@bitwarden/common/abstractions/organization
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { TokenService } from "@bitwarden/common/abstractions/token.service";
import { StateService } from "../../abstractions/state.service";
import { StateService } from "../core";
const BroadcasterSubscriptionId = "SettingsComponent";

View File

@@ -1,5 +1,5 @@
import { Component, OnInit } from "@angular/core";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
import { notAllowedValueAsync } from "@bitwarden/angular/validators/notAllowedValueAsync.validator";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
@@ -24,7 +24,7 @@ export class SponsoredFamiliesComponent implements OnInit {
// Conditional display properties
formPromise: Promise<any>;
sponsorshipForm: FormGroup;
sponsorshipForm: UntypedFormGroup;
constructor(
private apiService: ApiService,
@@ -32,7 +32,7 @@ export class SponsoredFamiliesComponent implements OnInit {
private platformUtilsService: PlatformUtilsService,
private syncService: SyncService,
private organizationService: OrganizationService,
private formBuilder: FormBuilder,
private formBuilder: UntypedFormBuilder,
private stateService: StateService
) {
this.sponsorshipForm = this.formBuilder.group({

View File

@@ -1,5 +1,5 @@
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { UntypedFormBuilder } from "@angular/forms";
import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/components/export.component";
import { ModalService } from "@bitwarden/angular/services/modal.service";
@@ -35,7 +35,7 @@ export class ExportComponent extends BaseExportComponent {
policyService: PolicyService,
logService: LogService,
userVerificationService: UserVerificationService,
formBuilder: FormBuilder,
formBuilder: UntypedFormBuilder,
fileDownloadService: FileDownloadService,
modalService: ModalService
) {

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Мир"
},
"numberOfUsers": {
"message": "Брой потребители"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Brugerantal"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Anzahl der Benutzer"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -1133,7 +1133,7 @@
"message": "Account Deleted"
},
"accountDeletedDesc": {
"message": "Your Bitwarden account and vault data were permanently deleted."
"message": "Your account has been closed and all associated data has been deleted."
},
"myAccount": {
"message": "My Account"
@@ -5351,5 +5351,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -573,7 +573,7 @@
"message": "Krei konton"
},
"startTrial": {
"message": "Start Trial"
"message": "Komencu Provperiodon"
},
"logIn": {
"message": "Saluti"
@@ -597,7 +597,7 @@
"message": "La ĉefa pasvorto estas la pasvorto, kiun vi uzas por aliri vian trezorejon. Tre gravas, ke vi ne forgesu vian ĉefan pasvorton. Ne eblas retrovi la pasvorton, se vi forgesos ĝin."
},
"masterPassImportant": {
"message": "Master passwords cannot be recovered if you forget it!"
"message": "Maleblas restarigado de ĉefpasvorto, se vi ĝin forgesos!"
},
"masterPassHintDesc": {
"message": "Majstra pasvorta sugesto povas helpi vin memori vian pasvorton se vi forgesas ĝin."
@@ -630,10 +630,10 @@
"message": "Nevalida retpoŝta adreso."
},
"masterPasswordRequired": {
"message": "Master password is required."
"message": "Ĉefpasvorto estas nepra."
},
"confirmMasterPasswordRequired": {
"message": "Master password retype is required."
"message": "Reentajpado de ĉefpasvorto estas nepra."
},
"masterPasswordMinLength": {
"message": "Master password must be at least 8 characters long."
@@ -793,7 +793,7 @@
"message": "Sekureca Ŝlosilo FIDO U2F"
},
"webAuthnTitle": {
"message": "FIDO2 WebAuthn"
"message": "WebAuthn FIDO2"
},
"webAuthnDesc": {
"message": "Use any WebAuthn enabled security key to access your account."
@@ -924,10 +924,10 @@
"description": "Include lowercase letters in the password generator."
},
"numbers": {
"message": "Numbers (0-9)"
"message": "Ciferoj (0-9)"
},
"specialCharacters": {
"message": "Special Characters (!@#$%^&*)"
"message": "Signoj Specialaj (!@#$%^&*)"
},
"numWords": {
"message": "Nombro de Vortoj"
@@ -1251,7 +1251,7 @@
"message": "Enŝaltita"
},
"restoreAccess": {
"message": "Restore Access"
"message": "Restarigu Aliron"
},
"premium": {
"message": "Premium",
@@ -1795,7 +1795,7 @@
"message": "jaro"
},
"yr": {
"message": "yr"
"message": "jaro"
},
"month": {
"message": "monato"
@@ -2212,7 +2212,7 @@
"message": "Ĉiujare"
},
"annual": {
"message": "Annual"
"message": "Ĉiujare"
},
"basePrice": {
"message": "Baza Prezo"
@@ -2740,7 +2740,7 @@
}
},
"createdOrganizationId": {
"message": "Created organization $ID$.",
"message": "Kreiĝis organizo $ID$.",
"placeholders": {
"id": {
"content": "$1",
@@ -2749,7 +2749,7 @@
}
},
"addedOrganizationId": {
"message": "Added organization $ID$.",
"message": "Aldoniĝis organizo $ID$.",
"placeholders": {
"id": {
"content": "$1",
@@ -2758,7 +2758,7 @@
}
},
"removedOrganizationId": {
"message": "Removed organization $ID$.",
"message": "Forviŝiĝis organizo $ID$.",
"placeholders": {
"id": {
"content": "$1",
@@ -3391,7 +3391,7 @@
"message": "Agordi minimumajn postulojn por majstra pasvorta forto."
},
"twoStepLoginPolicyTitle": {
"message": "Require two-step login"
"message": "Devigu dufazan ensaluton"
},
"twoStepLoginPolicyDesc": {
"message": "Postuli uzantojn agordi du-ŝtupan ensaluton en siaj personaj kontoj."
@@ -3546,7 +3546,7 @@
}
},
"restoredItemId": {
"message": "Restored item $ID$.",
"message": "Restariĝis ero $ID$.",
"placeholders": {
"id": {
"content": "$1",
@@ -4262,7 +4262,7 @@
}
},
"thisUser": {
"message": "this user"
"message": "ĉi tiu uzanto"
},
"resetPasswordMasterPasswordPolicyInEffect": {
"message": "One or more organization policies require the master password to meet the following requirements:"
@@ -4343,10 +4343,10 @@
"message": "Use System Theme"
},
"themeDark": {
"message": "Dark"
"message": "Malhela"
},
"themeLight": {
"message": "Light"
"message": "Hela"
},
"confirmSelected": {
"message": "Confirm Selected"
@@ -4385,7 +4385,7 @@
"message": "Restore Users"
},
"error": {
"message": "Error"
"message": "Eraro"
},
"resetPasswordManageUsers": {
"message": "Manage Users must also be enabled with the Manage Password Reset permission"
@@ -4400,7 +4400,7 @@
"message": "Please enter the details below to complete the provider setup. Contact Customer Support if you have any questions."
},
"providerName": {
"message": "Provider Name"
"message": "Nomo de Provizanto"
},
"providerSetup": {
"message": "The provider has been set up."
@@ -4409,7 +4409,7 @@
"message": "Clients"
},
"providerAdmin": {
"message": "Provider Admin"
"message": "Administranto de Provizanto"
},
"providerAdminDesc": {
"message": "The highest access user that can manage all aspects of your provider as well as access and manage client organizations."
@@ -4439,7 +4439,7 @@
"message": "You have users that have accepted their invitation, but still need to be confirmed. Users will not have access to the provider until they are confirmed."
},
"provider": {
"message": "Provider"
"message": "Provizanto"
},
"newClientOrganization": {
"message": "New Client Organization"
@@ -4506,13 +4506,13 @@
"message": "Are you sure you want to detach this organization? The organization will continue to exist but will no longer be managed by the provider."
},
"add": {
"message": "Add"
"message": "Aldonu"
},
"updatedMasterPassword": {
"message": "Updated Master Password"
"message": "Ĉefpasvorto Estas Aktualigita"
},
"updateMasterPassword": {
"message": "Update Master Password"
"message": "Aktualigu Ĉefpasvorton"
},
"updateMasterPasswordWarning": {
"message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update your Master Password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour."
@@ -4521,7 +4521,7 @@
"message": "Your Master Password does not meet the policy requirements of this organization. In order to join the organization, you must update your Master Password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour."
},
"maximumVaultTimeout": {
"message": "Vault timeout"
"message": "Tempolimo de trezorejo"
},
"maximumVaultTimeoutDesc": {
"message": "Set a maximum vault timeout for members."
@@ -4533,10 +4533,10 @@
"message": "Invalid Maximum Vault Timeout."
},
"hours": {
"message": "Hours"
"message": "Horoj"
},
"minutes": {
"message": "Minutes"
"message": "Minutoj"
},
"vaultTimeoutPolicyInEffect": {
"message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)",
@@ -4795,7 +4795,7 @@
"message": "Sponsorship Created"
},
"emailSent": {
"message": "Email Sent"
"message": "Retmesaĝo Sendiĝis"
},
"revokeSponsorshipConfirmation": {
"message": "After removing this account, the Families plan sponsorship will expire at the end of the billing period. You will not be able to redeem a new sponsorship offer until the existing one expires. Are you sure you want to continue?"
@@ -4813,19 +4813,19 @@
"message": "Send a verification code to your email"
},
"sendCode": {
"message": "Send Code"
"message": "Sendu Kodon"
},
"codeSent": {
"message": "Code Sent"
"message": "Kodo Sendiĝis"
},
"verificationCode": {
"message": "Verification Code"
"message": "Aŭtentiga Kodo"
},
"confirmIdentity": {
"message": "Confirm your identity to continue."
},
"verificationCodeRequired": {
"message": "Verification code is required."
"message": "Aŭtentiga kodo estas deviga."
},
"invalidVerificationCode": {
"message": "Invalid verification code"
@@ -4843,7 +4843,7 @@
"message": "Leave Organization"
},
"removeMasterPassword": {
"message": "Remove Master Password"
"message": "Forigu Ĉefpasvorton"
},
"removedMasterPassword": {
"message": "Master password removed."
@@ -4918,7 +4918,7 @@
"message": "Sponsoring Organization"
},
"keyConnectorTest": {
"message": "Test"
"message": "Testu"
},
"keyConnectorTestSuccess": {
"message": "Success! Key Connector reached."
@@ -4993,7 +4993,7 @@
"message": "Sent (Awaiting Sync)"
},
"sent": {
"message": "Sent"
"message": "Sendita"
},
"requestRemoved": {
"message": "Removed (Awaiting Sync)"
@@ -5023,7 +5023,7 @@
}
},
"required": {
"message": "required"
"message": "deviga"
},
"idpSingleSignOnServiceUrlRequired": {
"message": "Required if Entity ID is not a URL."
@@ -5068,13 +5068,13 @@
"message": "Access Denied. You do not have permission to view this page."
},
"masterPassword": {
"message": "Master Password"
"message": "Ĉefpasvorto"
},
"security": {
"message": "Security"
"message": "Sekureco"
},
"keys": {
"message": "Keys"
"message": "Ŝlosiloj"
},
"billingHistory": {
"message": "Billing History"
@@ -5124,11 +5124,11 @@
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random",
"message": "Hazarda",
"description": "Generates domain-based username using random letters"
},
"randomWord": {
"message": "Random Word"
"message": "Vorto Hazarda"
},
"service": {
"message": "Service"
@@ -5193,7 +5193,7 @@
"message": "Generate an email alias with an external forwarding service."
},
"hostname": {
"message": "Hostname",
"message": "Domajna nomo",
"description": "Part of a URL."
},
"apiAccessToken": {
@@ -5252,7 +5252,7 @@
"description": "the text, 'SCIM' and 'API', are acronymns and should not be translated."
},
"rotateKey": {
"message": "Rotate Key"
"message": "Rotaciigu Ŝlosilon"
},
"scimApiKey": {
"message": "SCIM API Key",
@@ -5275,10 +5275,10 @@
"description": "the text, 'SCIM', is an acronymn and should not be translated."
},
"inputRequired": {
"message": "Input is required."
"message": "Enigo estas deviga."
},
"inputEmail": {
"message": "Input is not an email-address."
"message": "Enigo ne estas retpoŝta adreso."
},
"inputMinLength": {
"message": "Input must be at least $COUNT$ characters long.",
@@ -5299,12 +5299,15 @@
}
},
"turnOn": {
"message": "Turn on"
"message": "Ŝaltu"
},
"on": {
"message": "On"
"message": "Ŝaltita"
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Number of users"
}
}

View File

@@ -5306,5 +5306,8 @@
},
"cardBrandMir": {
"message": "Mir"
},
"numberOfUsers": {
"message": "Kasutajate arv"
}
}

Some files were not shown because too many files have changed in this diff Show More