1
0
mirror of https://github.com/bitwarden/web synced 2025-12-06 00:03:28 +00:00

Compare commits

..

6 Commits

Author SHA1 Message Date
github-actions[bot]
ee4afdd0f2 Bumped version to 2022.5.2 (#1730)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-06-07 13:04:54 -07:00
github-actions[bot]
6da0925374 Bumped version to 2022.5.1 (#1727)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-06-07 11:47:12 -07:00
Addison Beck
c233afcdf5 [fix] Pull org admin vault collections directly from the API (#1700)
* [fix] Pull org admin vault collections directly from the API

* [refactor] Establish pattern for interfaces in module scoped services

* [fix] Remove access modifiers from constructor params for an extended service

* [fix] Rename skipFilterCollectionRefresh to firstLoaded

* [fix] Simplify hiding unwanted filters in the org vault

* Revert "[refactor] Establish pattern for interfaces in module scoped services"

This reverts commit f1edae5a3e.

* Update src/app/modules/vault-filter/vault-filter.component.ts

Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>

* Update src/app/modules/vault-filter/organization-vault-filter.component.ts

Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>

* [fix] Ran prettier

Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
2022-06-06 13:28:10 -04:00
Oscar Hinton
e1ffca07ba Add archive notice (#1724) 2022-06-02 09:09:08 -04:00
Oscar Hinton
fb35805202 [CL-38] Follow Angular styleguide naming convention (#1655) 2022-06-02 11:34:27 +02:00
dwbit
b6b7298980 Adding missing code for Serbian Latin (#1713) 2022-06-02 11:23:48 +02:00
62 changed files with 604 additions and 645 deletions

View File

@@ -1,8 +1,6 @@
> **Repository Reorganization in Progress**
> **Archived**
>
> We are currently migrating some projects over to a mono repository. For existing PR's we will be providing documentation on how to move/migrate them. To minimize the overhead we are actively reviewing open PRs. If possible please ensure any pending comments are resolved as soon as possible.
>
> New pull requests created during this transition period may not get addressed —if needed, please create a new PR after the reorganization is complete.
> This repository is archived, please go to https://github.com/bitwarden/clients for future development.
<p align="center">
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/web-vault-macbook.png" alt="" width="600" height="358" />

View File

@@ -1,9 +1,11 @@
import { CommonModule } from "@angular/common";
import { ComponentFactoryResolver, NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { JslibModule } from "jslib-angular/jslib.module";
import { ModalService } from "jslib-angular/services/modal.service";
import { LayoutsModule } from "src/app/layouts/layouts.module";
import { SharedModule } from "src/app/modules/shared.module";
import { OssModule } from "src/app/oss.module";
import { AddOrganizationComponent } from "./clients/add-organization.component";
import { ClientsComponent } from "./clients/clients.component";
@@ -26,7 +28,7 @@ import { SetupProviderComponent } from "./setup/setup-provider.component";
import { SetupComponent } from "./setup/setup.component";
@NgModule({
imports: [SharedModule, LayoutsModule, ProvidersRoutingModule],
imports: [CommonModule, FormsModule, OssModule, JslibModule, ProvidersRoutingModule],
declarations: [
AcceptProviderComponent,
AccountComponent,

View File

@@ -15,3 +15,4 @@ files:
en-GB: en_GB
en-IN: en_IN
sr-CY: sr_CY
sr-CS: sr_CS

2
jslib

Submodule jslib updated: 0d658ba26d...f4066b4f58

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@bitwarden/web-vault",
"version": "2022.05.0",
"version": "2022.5.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@bitwarden/web-vault",
"version": "2022.05.0",
"version": "2022.5.2",
"hasInstallScript": true,
"license": "GPL-3.0",
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "@bitwarden/web-vault",
"version": "2022.05.0",
"version": "2022.5.2",
"license": "GPL-3.0",
"repository": "https://github.com/bitwarden/web",
"scripts": {

View File

@@ -46,7 +46,7 @@
<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">
<a bit-menu-item [routerLink]="['/organizations', org.id]">
<a bitMenuItem [routerLink]="['/organizations', org.id]">
<i
class="bwi bwi-check mr-2"
[ngClass]="org.id === activeOrganization.id ? 'visible' : 'invisible'"
@@ -58,7 +58,7 @@
</li>
<bit-menu-divider></bit-menu-divider>
<li class="tw-list-none" role="none">
<a bit-menu-item routerLink="/create-organization">
<a bitMenuItem routerLink="/create-organization">
<i class="bwi bwi-plus mr-2"></i>
{{ "newOrganization" | i18n }}</a
>

View File

@@ -5,7 +5,7 @@ import { OrganizationService } from "jslib-common/abstractions/organization.serv
import { Utils } from "jslib-common/misc/utils";
import { Organization } from "jslib-common/models/domain/organization";
import { NavigationPermissionsService } from "../services/navigation-permissions.service";
import { NavigationPermissionsService } from "../organizations/services/navigation-permissions.service";
@Component({
selector: "app-organization-switcher",

View File

@@ -5,7 +5,7 @@ import { MessagingService } from "jslib-common/abstractions/messaging.service";
@Component({
selector: "app-premium-badge",
template: `
<button *appNotPremium bit-badge badgeType="success" (click)="premiumRequired()">
<button *appNotPremium bitBadge badgeType="success" (click)="premiumRequired()">
{{ "premium" | i18n }}
</button>
`,

View File

@@ -1,13 +0,0 @@
import { NgModule } from "@angular/core";
import { FooterComponent } from "../layouts/footer.component";
import { FrontendLayoutComponent } from "../layouts/frontend-layout.component";
import { NavbarComponent } from "../layouts/navbar.component";
import { SharedModule } from "../modules/shared.module";
@NgModule({
imports: [SharedModule],
declarations: [NavbarComponent, FooterComponent, FrontendLayoutComponent],
exports: [NavbarComponent, FooterComponent],
})
export class LayoutsModule {}

View File

@@ -65,24 +65,24 @@
</div>
</div>
<bit-menu-divider></bit-menu-divider>
<a bit-menu-item routerLink="/settings/account">
<a bitMenuItem routerLink="/settings/account">
<i class="bwi bwi-fw bwi-user" aria-hidden="true"></i>
{{ "accountSettings" | i18n }}
</a>
<a bit-menu-item href="https://bitwarden.com/help/" target="_blank" rel="noopener">
<a bitMenuItem href="https://bitwarden.com/help/" target="_blank" rel="noopener">
<i class="bwi bwi-fw bwi-question-circle" aria-hidden="true"></i>
{{ "getHelp" | i18n }}
</a>
<a bit-menu-item href="https://bitwarden.com/download/" target="_blank" rel="noopener">
<a bitMenuItem href="https://bitwarden.com/download/" target="_blank" rel="noopener">
<i class="bwi bwi-fw bwi-download" aria-hidden="true"></i>
{{ "getApps" | i18n }}
</a>
<bit-menu-divider></bit-menu-divider>
<button bit-menu-item type="button" (click)="lock()">
<button bitMenuItem type="button" (click)="lock()">
<i class="bwi bwi-fw bwi-lock" aria-hidden="true"></i>
{{ "lockNow" | i18n }}
</button>
<button bit-menu-item type="button" (click)="logOut()">
<button bitMenuItem type="button" (click)="logOut()">
<i class="bwi bwi-fw bwi-sign-out" aria-hidden="true"></i>
{{ "logOut" | i18n }}
</button>

View File

@@ -20,10 +20,66 @@ import { UpdateTempPasswordComponent } from "../accounts/update-temp-password.co
import { VerifyEmailTokenComponent } from "../accounts/verify-email-token.component";
import { VerifyRecoverDeleteComponent } from "../accounts/verify-recover-delete.component";
import { NestedCheckboxComponent } from "../components/nested-checkbox.component";
import { OrganizationSwitcherComponent } from "../components/organization-switcher.component";
import { PasswordRepromptComponent } from "../components/password-reprompt.component";
import { PasswordStrengthComponent } from "../components/password-strength.component";
import { PremiumBadgeComponent } from "../components/premium-badge.component";
import { LayoutsModule } from "../layouts/layouts.module";
import { FooterComponent } from "../layouts/footer.component";
import { FrontendLayoutComponent } from "../layouts/frontend-layout.component";
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 { BulkRemoveComponent as OrgBulkRemoveComponent } from "../organizations/manage/bulk/bulk-remove.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";
import { EntityEventsComponent as OrgEntityEventsComponent } from "../organizations/manage/entity-events.component";
import { EventsComponent as OrgEventsComponent } from "../organizations/manage/events.component";
import { GroupAddEditComponent as OrgGroupAddEditComponent } from "../organizations/manage/group-add-edit.component";
import { GroupsComponent as OrgGroupsComponent } from "../organizations/manage/groups.component";
import { ManageComponent as OrgManageComponent } from "../organizations/manage/manage.component";
import { PeopleComponent as OrgPeopleComponent } from "../organizations/manage/people.component";
import { PoliciesComponent as OrgPoliciesComponent } from "../organizations/manage/policies.component";
import { PolicyEditComponent as OrgPolicyEditComponent } from "../organizations/manage/policy-edit.component";
import { ResetPasswordComponent as OrgResetPasswordComponent } from "../organizations/manage/reset-password.component";
import { UserAddEditComponent as OrgUserAddEditComponent } from "../organizations/manage/user-add-edit.component";
import { UserConfirmComponent as OrgUserConfirmComponent } from "../organizations/manage/user-confirm.component";
import { UserGroupsComponent as OrgUserGroupsComponent } from "../organizations/manage/user-groups.component";
import { DisableSendPolicyComponent } from "../organizations/policies/disable-send.component";
import { MasterPasswordPolicyComponent } from "../organizations/policies/master-password.component";
import { PasswordGeneratorPolicyComponent } from "../organizations/policies/password-generator.component";
import { PersonalOwnershipPolicyComponent } from "../organizations/policies/personal-ownership.component";
import { RequireSsoPolicyComponent } from "../organizations/policies/require-sso.component";
import { ResetPasswordPolicyComponent } from "../organizations/policies/reset-password.component";
import { SendOptionsPolicyComponent } from "../organizations/policies/send-options.component";
import { SingleOrgPolicyComponent } from "../organizations/policies/single-org.component";
import { TwoFactorAuthenticationPolicyComponent } from "../organizations/policies/two-factor-authentication.component";
import { AccountComponent as OrgAccountComponent } from "../organizations/settings/account.component";
import { AdjustSubscription } from "../organizations/settings/adjust-subscription.component";
import { BillingSyncApiKeyComponent } from "../organizations/settings/billing-sync-api-key.component";
import { ChangePlanComponent } from "../organizations/settings/change-plan.component";
import { DeleteOrganizationComponent } from "../organizations/settings/delete-organization.component";
import { DownloadLicenseComponent } from "../organizations/settings/download-license.component";
import { ImageSubscriptionHiddenComponent as OrgSubscriptionHiddenComponent } from "../organizations/settings/image-subscription-hidden.component";
import { OrganizationBillingComponent } from "../organizations/settings/organization-billing.component";
import { OrganizationSubscriptionComponent } from "../organizations/settings/organization-subscription.component";
import { SettingsComponent as OrgSettingComponent } from "../organizations/settings/settings.component";
import { TwoFactorSetupComponent as OrgTwoFactorSetupComponent } from "../organizations/settings/two-factor-setup.component";
import { AcceptFamilySponsorshipComponent } from "../organizations/sponsorships/accept-family-sponsorship.component";
import { FamiliesForEnterpriseSetupComponent } from "../organizations/sponsorships/families-for-enterprise-setup.component";
import { ExportComponent as OrgExportComponent } from "../organizations/tools/export.component";
import { ExposedPasswordsReportComponent as OrgExposedPasswordsReportComponent } from "../organizations/tools/exposed-passwords-report.component";
import { ImportComponent as OrgImportComponent } from "../organizations/tools/import.component";
import { InactiveTwoFactorReportComponent as OrgInactiveTwoFactorReportComponent } from "../organizations/tools/inactive-two-factor-report.component";
import { ReusedPasswordsReportComponent as OrgReusedPasswordsReportComponent } from "../organizations/tools/reused-passwords-report.component";
import { ToolsComponent as OrgToolsComponent } from "../organizations/tools/tools.component";
import { UnsecuredWebsitesReportComponent as OrgUnsecuredWebsitesReportComponent } from "../organizations/tools/unsecured-websites-report.component";
import { WeakPasswordsReportComponent as OrgWeakPasswordsReportComponent } from "../organizations/tools/weak-passwords-report.component";
import { AddEditComponent as OrgAddEditComponent } from "../organizations/vault/add-edit.component";
import { AttachmentsComponent as OrgAttachmentsComponent } from "../organizations/vault/attachments.component";
import { CiphersComponent as OrgCiphersComponent } from "../organizations/vault/ciphers.component";
import { CollectionsComponent as OrgCollectionsComponent } from "../organizations/vault/collections.component";
import { ProvidersComponent } from "../providers/providers.component";
import { BreachReportComponent } from "../reports/breach-report.component";
import { ExposedPasswordsReportComponent } from "../reports/exposed-passwords-report.component";
@@ -58,7 +114,9 @@ import { EmergencyAccessTakeoverComponent } from "../settings/emergency-access-t
import { EmergencyAccessViewComponent } from "../settings/emergency-access-view.component";
import { EmergencyAccessComponent } from "../settings/emergency-access.component";
import { EmergencyAddEditComponent } from "../settings/emergency-add-edit.component";
import { OrganizationPlansComponent } from "../settings/organization-plans.component";
import { PaymentMethodComponent } from "../settings/payment-method.component";
import { PaymentComponent } from "../settings/payment.component";
import { PreferencesComponent } from "../settings/preferences.component";
import { PremiumComponent } from "../settings/premium.component";
import { ProfileComponent } from "../settings/profile.component";
@@ -110,10 +168,11 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
// Please do not add to this list of declarations - we should refactor these into modules when doing so makes sense until there are none left.
// If you are building new functionality, please create or extend a feature module instead.
@NgModule({
imports: [SharedModule, VaultFilterModule, OrganizationBadgeModule, PipesModule, LayoutsModule],
imports: [SharedModule, VaultFilterModule, OrganizationBadgeModule, PipesModule],
declarations: [
PremiumBadgeComponent,
AcceptEmergencyComponent,
AcceptFamilySponsorshipComponent,
AcceptOrganizationComponent,
AccessComponent,
AccountComponent,
@@ -123,8 +182,10 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
AddEditCustomFieldsComponent,
AdjustPaymentComponent,
AdjustStorageComponent,
AdjustSubscription,
ApiKeyComponent,
AttachmentsComponent,
BillingSyncApiKeyComponent,
BillingSyncKeyComponent,
BreachReportComponent,
BulkActionsComponent,
@@ -135,12 +196,16 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
ChangeEmailComponent,
ChangeKdfComponent,
ChangePasswordComponent,
ChangePlanComponent,
CiphersComponent,
CollectionsComponent,
CreateOrganizationComponent,
DeauthorizeSessionsComponent,
DeleteAccountComponent,
DeleteOrganizationComponent,
DisableSendPolicyComponent,
DomainRulesComponent,
DownloadLicenseComponent,
EmergencyAccessAddEditComponent,
EmergencyAccessAttachmentsComponent,
EmergencyAccessComponent,
@@ -150,17 +215,64 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
EmergencyAddEditComponent,
ExportComponent,
ExposedPasswordsReportComponent,
FamiliesForEnterpriseSetupComponent,
FolderAddEditComponent,
FooterComponent,
FrontendLayoutComponent,
HintComponent,
ImportComponent,
InactiveTwoFactorReportComponent,
LockComponent,
LoginComponent,
MasterPasswordPolicyComponent,
NavbarComponent,
NestedCheckboxComponent,
OrganizationSwitcherComponent,
OrgAccountComponent,
OrgAddEditComponent,
OrganizationBillingComponent,
OrganizationLayoutComponent,
OrganizationPlansComponent,
OrganizationSubscriptionComponent,
OrgAttachmentsComponent,
OrgBulkConfirmComponent,
OrgBulkRemoveComponent,
OrgBulkStatusComponent,
OrgCiphersComponent,
OrgCollectionAddEditComponent,
OrgCollectionsComponent,
OrgEntityEventsComponent,
OrgEventsComponent,
OrgExportComponent,
OrgExposedPasswordsReportComponent,
OrgGroupAddEditComponent,
OrgGroupsComponent,
OrgImportComponent,
OrgInactiveTwoFactorReportComponent,
OrgManageCollectionsComponent,
OrgManageComponent,
OrgPeopleComponent,
OrgPoliciesComponent,
OrgPolicyEditComponent,
OrgResetPasswordComponent,
OrgReusedPasswordsReportComponent,
OrgSettingComponent,
OrgToolsComponent,
OrgTwoFactorSetupComponent,
OrgSubscriptionHiddenComponent,
OrgUnsecuredWebsitesReportComponent,
OrgUserAddEditComponent,
OrgUserConfirmComponent,
OrgUserGroupsComponent,
OrgWeakPasswordsReportComponent,
GeneratorComponent,
PasswordGeneratorHistoryComponent,
PasswordGeneratorPolicyComponent,
PasswordRepromptComponent,
PasswordStrengthComponent,
PaymentComponent,
PaymentMethodComponent,
PersonalOwnershipPolicyComponent,
PreferencesComponent,
PremiumBadgeComponent,
PremiumComponent,
@@ -174,21 +286,26 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
ReportCardComponent,
ReportListComponent,
ReportsComponent,
RequireSsoPolicyComponent,
ResetPasswordPolicyComponent,
ReusedPasswordsReportComponent,
SecurityComponent,
SecurityKeysComponent,
SendAddEditComponent,
SendComponent,
SendEffluxDatesComponent,
SendOptionsPolicyComponent,
SetPasswordComponent,
SettingsComponent,
ShareComponent,
SingleOrgPolicyComponent,
SponsoredFamiliesComponent,
SponsoringOrgRowComponent,
SsoComponent,
SubscriptionComponent,
TaxInfoComponent,
ToolsComponent,
TwoFactorAuthenticationPolicyComponent,
TwoFactorAuthenticatorComponent,
TwoFactorComponent,
TwoFactorDuoComponent,
@@ -226,6 +343,7 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
AddEditCustomFieldsComponent,
AdjustPaymentComponent,
AdjustStorageComponent,
AdjustSubscription,
ApiKeyComponent,
AttachmentsComponent,
BreachReportComponent,
@@ -237,12 +355,16 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
ChangeEmailComponent,
ChangeKdfComponent,
ChangePasswordComponent,
ChangePlanComponent,
CiphersComponent,
CollectionsComponent,
CreateOrganizationComponent,
DeauthorizeSessionsComponent,
DeleteAccountComponent,
DeleteOrganizationComponent,
DisableSendPolicyComponent,
DomainRulesComponent,
DownloadLicenseComponent,
EmergencyAccessAddEditComponent,
EmergencyAccessAttachmentsComponent,
EmergencyAccessComponent,
@@ -252,17 +374,63 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
EmergencyAddEditComponent,
ExportComponent,
ExposedPasswordsReportComponent,
FamiliesForEnterpriseSetupComponent,
FolderAddEditComponent,
FooterComponent,
FrontendLayoutComponent,
HintComponent,
ImportComponent,
InactiveTwoFactorReportComponent,
LockComponent,
LoginComponent,
MasterPasswordPolicyComponent,
NavbarComponent,
NestedCheckboxComponent,
OrganizationSwitcherComponent,
OrgAccountComponent,
OrgAddEditComponent,
OrganizationBillingComponent,
OrganizationLayoutComponent,
OrganizationPlansComponent,
OrganizationSubscriptionComponent,
OrgAttachmentsComponent,
OrgBulkConfirmComponent,
OrgBulkRemoveComponent,
OrgBulkStatusComponent,
OrgCiphersComponent,
OrgCollectionAddEditComponent,
OrgCollectionsComponent,
OrgEntityEventsComponent,
OrgEventsComponent,
OrgExportComponent,
OrgExposedPasswordsReportComponent,
OrgGroupAddEditComponent,
OrgGroupsComponent,
OrgImportComponent,
OrgInactiveTwoFactorReportComponent,
OrgManageCollectionsComponent,
OrgManageComponent,
OrgPeopleComponent,
OrgPoliciesComponent,
OrgPolicyEditComponent,
OrgResetPasswordComponent,
OrgReusedPasswordsReportComponent,
OrgSettingComponent,
OrgToolsComponent,
OrgTwoFactorSetupComponent,
OrgUnsecuredWebsitesReportComponent,
OrgUserAddEditComponent,
OrgUserConfirmComponent,
OrgUserGroupsComponent,
OrgWeakPasswordsReportComponent,
GeneratorComponent,
PasswordGeneratorHistoryComponent,
PasswordGeneratorPolicyComponent,
PasswordRepromptComponent,
PasswordStrengthComponent,
PaymentComponent,
PaymentMethodComponent,
PersonalOwnershipPolicyComponent,
PreferencesComponent,
PremiumBadgeComponent,
PremiumComponent,
@@ -276,21 +444,26 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
ReportCardComponent,
ReportListComponent,
ReportsComponent,
RequireSsoPolicyComponent,
ResetPasswordPolicyComponent,
ReusedPasswordsReportComponent,
SecurityComponent,
SecurityKeysComponent,
SendAddEditComponent,
SendComponent,
SendEffluxDatesComponent,
SendOptionsPolicyComponent,
SetPasswordComponent,
SettingsComponent,
ShareComponent,
SingleOrgPolicyComponent,
SponsoredFamiliesComponent,
SponsoringOrgRowComponent,
SsoComponent,
SubscriptionComponent,
TaxInfoComponent,
ToolsComponent,
TwoFactorAuthenticationPolicyComponent,
TwoFactorAuthenticatorComponent,
TwoFactorComponent,
TwoFactorDuoComponent,

View File

@@ -32,7 +32,7 @@
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification>
</div>
<div class="modal-footer">
<button bit-button buttonType="primary" type="submit" [disabled]="form.loading">
<button bitButton buttonType="primary" type="submit" [disabled]="form.loading">
<i
class="bwi bwi-spinner bwi-spin"
title="{{ 'loading' | i18n }}"
@@ -43,7 +43,7 @@
</span>
</button>
<button
bit-button
bitButton
buttonType="secondary"
type="button"
data-dismiss="modal"

View File

@@ -59,10 +59,6 @@ import { ToastrModule } from "ngx-toastr";
import { JslibModule } from "jslib-angular/jslib.module";
import { PasswordStrengthComponent } from "../components/password-strength.component";
import { OrganizationPlansComponent } from "../settings/organization-plans.component";
import { PaymentComponent } from "../settings/payment.component";
registerLocaleData(localeAf, "af");
registerLocaleData(localeAz, "az");
registerLocaleData(localeBe, "be");
@@ -131,7 +127,6 @@ registerLocaleData(localeZhTw, "zh-TW");
ButtonModule,
MenuModule,
],
declarations: [PasswordStrengthComponent, OrganizationPlansComponent, PaymentComponent],
exports: [
CommonModule,
DragDropModule,
@@ -147,9 +142,6 @@ registerLocaleData(localeZhTw, "zh-TW");
BadgeModule,
ButtonModule,
MenuModule,
PasswordStrengthComponent,
OrganizationPlansComponent,
PaymentComponent,
],
providers: [DatePipe],
bootstrap: [],

View File

@@ -0,0 +1,28 @@
import { Component, Input } from "@angular/core";
import { Organization } from "jslib-common/models/domain/organization";
import { VaultFilterComponent } from "./vault-filter.component";
@Component({
selector: "app-organization-vault-filter",
templateUrl: "vault-filter.component.html",
})
export class OrganizationVaultFilterComponent extends VaultFilterComponent {
hideOrganizations = true;
hideFavorites = true;
hideFolders = true;
organization: Organization;
async initCollections() {
if (this.organization.canEditAnyCollection) {
return await this.vaultFilterService.buildAdminCollections(this.organization.id);
}
return await this.vaultFilterService.buildCollections(this.organization.id);
}
async reloadCollectionsAndFolders() {
this.collections = await this.initCollections();
}
}

View File

@@ -27,7 +27,6 @@
appAutofocus
/>
<app-organization-filter
*ngIf="showOrgFilter"
[hide]="hideOrganizations"
[activeFilter]="activeFilter"
[collapsedFilterNodes]="collapsedFilterNodes"
@@ -39,7 +38,7 @@
></app-organization-filter>
<div class="filter">
<app-status-filter
[hideFavorites]="!showFavorites"
[hideFavorites]="hideFavorites"
[hideTrash]="hideTrash"
[activeFilter]="activeFilter"
(onFilterChange)="applyFilter($event)"
@@ -55,7 +54,7 @@
</div>
<div class="filter">
<app-folder-filter
[hide]="!showFolders"
[hide]="hideFolders"
[activeFilter]="activeFilter"
[collapsedFilterNodes]="collapsedFilterNodes"
[folderNodes]="folders"

View File

@@ -1,34 +1,26 @@
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { Component, EventEmitter, Output } from "@angular/core";
import { VaultFilterComponent as BaseVaultFilterComponent } from "jslib-angular/modules/vault-filter/vault-filter.component";
import { VaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service";
import { Organization } from "jslib-common/models/domain/organization";
import { VaultFilterService } from "./vault-filter.service";
@Component({
selector: "app-vault-filter",
templateUrl: "vault-filter.component.html",
})
export class VaultFilterComponent extends BaseVaultFilterComponent {
@Input() showOrgFilter = true;
@Input() showFolders = true;
@Input() showFavorites = true;
@Output() onSearchTextChanged = new EventEmitter<string>();
searchPlaceholder: string;
searchText = "";
organization: Organization;
constructor(vaultFilterService: VaultFilterService) {
constructor(protected vaultFilterService: VaultFilterService) {
// This empty constructor is required to provide the web vaultFilterService subclass to super()
// TODO: refactor this to use proper dependency injection
super(vaultFilterService);
}
searchTextChanged() {
this.onSearchTextChanged.emit(this.searchText);
}
async initCollections() {
return await this.vaultFilterService.buildCollections(this.organization?.id);
}
}

View File

@@ -1,13 +1,5 @@
import { NgModule } from "@angular/core";
import { VaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service";
import { CipherService } from "jslib-common/abstractions/cipher.service";
import { CollectionService } from "jslib-common/abstractions/collection.service";
import { FolderService } from "jslib-common/abstractions/folder.service";
import { OrganizationService } from "jslib-common/abstractions/organization.service";
import { PolicyService } from "jslib-common/abstractions/policy.service";
import { StateService } from "jslib-common/abstractions/state.service";
import { SharedModule } from "../shared.module";
import { CollectionFilterComponent } from "./components/collection-filter.component";
@@ -17,7 +9,9 @@ import { OrganizationFilterComponent } from "./components/organization-filter.co
import { OrganizationOptionsComponent } from "./components/organization-options.component";
import { StatusFilterComponent } from "./components/status-filter.component";
import { TypeFilterComponent } from "./components/type-filter.component";
import { OrganizationVaultFilterComponent } from "./organization-vault-filter.component";
import { VaultFilterComponent } from "./vault-filter.component";
import { VaultFilterService } from "./vault-filter.service";
@NgModule({
imports: [SharedModule],
@@ -29,22 +23,10 @@ import { VaultFilterComponent } from "./vault-filter.component";
OrganizationOptionsComponent,
StatusFilterComponent,
TypeFilterComponent,
OrganizationVaultFilterComponent,
LinkSsoComponent,
],
exports: [VaultFilterComponent],
providers: [
{
provide: VaultFilterService,
useClass: VaultFilterService,
deps: [
StateService,
OrganizationService,
FolderService,
CipherService,
CollectionService,
PolicyService,
],
},
],
exports: [VaultFilterComponent, OrganizationVaultFilterComponent],
providers: [VaultFilterService],
})
export class VaultFilterModule {}

View File

@@ -1,3 +1,54 @@
import { VaultFilterService as BaseVaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service";
import { Injectable } from "@angular/core";
export class VaultFilterService extends BaseVaultFilterService {}
import { DynamicTreeNode } from "jslib-angular/modules/vault-filter/models/dynamic-tree-node.model";
import { VaultFilterService as BaseVaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service";
import { ApiService } from "jslib-common/abstractions/api.service";
import { CipherService } from "jslib-common/abstractions/cipher.service";
import { CollectionService } from "jslib-common/abstractions/collection.service";
import { FolderService } from "jslib-common/abstractions/folder.service";
import { OrganizationService } from "jslib-common/abstractions/organization.service";
import { PolicyService } from "jslib-common/abstractions/policy.service";
import { StateService } from "jslib-common/abstractions/state.service";
import { CollectionData } from "jslib-common/models/data/collectionData";
import { Collection } from "jslib-common/models/domain/collection";
import { CollectionDetailsResponse } from "jslib-common/models/response/collectionResponse";
import { CollectionView } from "jslib-common/models/view/collectionView";
@Injectable()
export class VaultFilterService extends BaseVaultFilterService {
constructor(
stateService: StateService,
organizationService: OrganizationService,
folderService: FolderService,
cipherService: CipherService,
collectionService: CollectionService,
policyService: PolicyService,
protected apiService: ApiService
) {
super(
stateService,
organizationService,
folderService,
cipherService,
collectionService,
policyService
);
}
async buildAdminCollections(organizationId: string) {
let result: CollectionView[] = [];
const collectionResponse = await this.apiService.getCollections(organizationId);
if (collectionResponse?.data != null && collectionResponse.data.length) {
const collectionDomains = collectionResponse.data.map(
(r: CollectionDetailsResponse) => new Collection(new CollectionData(r))
);
result = await this.collectionService.decryptMany(collectionDomains);
}
const nestedCollections = await this.collectionService.getAllNested(result);
return new DynamicTreeNode<CollectionView>({
fullList: result,
nestedList: nestedCollections,
});
}
}

View File

@@ -1,5 +1,5 @@
<button
bit-badge
bitBadge
[style.color]="textColor"
[style.background-color]="color"
appA11yTitle="{{ organizationName }}"

View File

@@ -4,15 +4,12 @@
<div class="groupings">
<div class="content">
<div class="inner-content">
<app-vault-filter
<app-organization-vault-filter
#vaultFilter
[showFolders]="false"
[showFavorites]="false"
[activeFilter]="activeFilter"
[showOrgFilter]="false"
(onFilterChange)="applyVaultFilter($event)"
(onSearchTextChanged)="filterSearchText($event)"
></app-vault-filter>
></app-organization-vault-filter>
</div>
</div>
</div>

View File

@@ -25,14 +25,13 @@ import { Organization } from "jslib-common/models/domain/organization";
import { CipherView } from "jslib-common/models/view/cipherView";
import { EntityEventsComponent } from "../../../../organizations/manage/entity-events.component";
import { VaultFilterComponent } from "../../../vault-filter/vault-filter.component";
import { AddEditComponent } from "../../../../organizations/vault/add-edit.component";
import { AttachmentsComponent } from "../../../../organizations/vault/attachments.component";
import { CiphersComponent } from "../../../../organizations/vault/ciphers.component";
import { CollectionsComponent } from "../../../../organizations/vault/collections.component";
import { OrganizationVaultFilterComponent } from "../../../vault-filter/organization-vault-filter.component";
import { VaultService } from "../../vault.service";
import { AddEditComponent } from "./add-edit.component";
import { AttachmentsComponent } from "./attachments.component";
import { CiphersComponent } from "./ciphers.component";
import { CollectionsComponent } from "./collections.component";
const BroadcasterSubscriptionId = "OrgVaultComponent";
@Component({
@@ -40,7 +39,8 @@ const BroadcasterSubscriptionId = "OrgVaultComponent";
templateUrl: "organization-vault.component.html",
})
export class OrganizationVaultComponent implements OnInit, OnDestroy {
@ViewChild("vaultFilter", { static: true }) vaultFilterComponent: VaultFilterComponent;
@ViewChild("vaultFilter", { static: true })
vaultFilterComponent: OrganizationVaultFilterComponent;
@ViewChild(CiphersComponent, { static: true }) ciphersComponent: CiphersComponent;
@ViewChild("attachments", { read: ViewContainerRef, static: true })
attachmentsModalRef: ViewContainerRef;
@@ -58,6 +58,11 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy {
trashCleanupWarning: string = null;
activeFilter: VaultFilter = new VaultFilter();
// This is a hack to avoid redundant api calls that fetch OrganizationVaultFilterComponent collections
// When it makes sense to do so we should leverage some other communication method for change events that isn't directly tied to the query param for organizationId
// i.e. exposing the VaultFiltersService to the OrganizationSwitcherComponent to make relevant updates from a change event instead of just depending on the router
firstLoaded = true;
constructor(
private route: ActivatedRoute,
private organizationService: OrganizationService,
@@ -96,11 +101,7 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy {
case "syncCompleted":
if (message.successfully) {
await Promise.all([
this.vaultFilterComponent.reloadCollectionsAndFolders(
new VaultFilter({
selectedOrganizationId: this.organization.id,
} as Partial<VaultFilter>)
),
this.vaultFilterComponent.reloadCollectionsAndFolders(),
this.ciphersComponent.refresh(),
]);
this.changeDetectorRef.detectChanges();
@@ -110,9 +111,12 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy {
});
});
}
await this.vaultFilterComponent.reloadCollectionsAndFolders(
new VaultFilter({ selectedOrganizationId: this.organization.id } as Partial<VaultFilter>)
);
if (!this.firstLoaded) {
await this.vaultFilterComponent.reloadCollectionsAndFolders();
}
this.firstLoaded = false;
await this.ciphersComponent.reload();
if (qParams.viewEvents != null) {

View File

@@ -2,22 +2,12 @@ import { NgModule } from "@angular/core";
import { VaultModule } from "../../vault.module";
import { AddEditComponent } from "./add-edit.component";
import { AttachmentsComponent } from "./attachments.component";
import { CiphersComponent } from "./ciphers.component";
import { CollectionsComponent } from "./collections.component";
import { OrganizationVaultRoutingModule } from "./organization-vault-routing.module";
import { OrganizationVaultComponent } from "./organization-vault.component";
@NgModule({
imports: [VaultModule, OrganizationVaultRoutingModule],
declarations: [
OrganizationVaultComponent,
AddEditComponent,
AttachmentsComponent,
CiphersComponent,
CollectionsComponent,
],
declarations: [OrganizationVaultComponent],
exports: [OrganizationVaultComponent],
})
export class OrganizationVaultModule {}

View File

@@ -1,89 +0,0 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { Permissions } from "jslib-common/enums/permissions";
import { PermissionsGuard } from "../guards/permissions.guard";
import { PoliciesComponent } from "../policies/policies.component";
import { NavigationPermissionsService } from "../services/navigation-permissions.service";
import { CollectionsComponent } from "./collections.component";
import { EventsComponent } from "./events.component";
import { GroupsComponent } from "./groups.component";
import { ManageComponent } from "./manage.component";
import { PeopleComponent } from "./people.component";
const routes: Routes = [
{
path: "",
component: ManageComponent,
canActivate: [PermissionsGuard],
data: {
permissions: NavigationPermissionsService.getPermissions("manage"),
},
children: [
{
path: "",
pathMatch: "full",
redirectTo: "people",
},
{
path: "collections",
component: CollectionsComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "collections",
permissions: [
Permissions.CreateNewCollections,
Permissions.EditAnyCollection,
Permissions.DeleteAnyCollection,
Permissions.EditAssignedCollections,
Permissions.DeleteAssignedCollections,
],
},
},
{
path: "events",
component: EventsComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "eventLogs",
permissions: [Permissions.AccessEventLogs],
},
},
{
path: "groups",
component: GroupsComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "groups",
permissions: [Permissions.ManageGroups],
},
},
{
path: "people",
component: PeopleComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "people",
permissions: [Permissions.ManageUsers, Permissions.ManageUsersPassword],
},
},
{
path: "policies",
component: PoliciesComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "policies",
permissions: [Permissions.ManagePolicies],
},
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ManageRoutingModule {}

View File

@@ -1,46 +0,0 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { SharedModule } from "../../modules/shared.module";
import { PoliciesModule } from "../policies/policies.module";
import { BulkConfirmComponent } from "./bulk/bulk-confirm.component";
import { BulkRemoveComponent } from "./bulk/bulk-remove.component";
import { BulkStatusComponent } from "./bulk/bulk-status.component";
import { CollectionAddEditComponent } from "./collection-add-edit.component";
import { CollectionsComponent as ManageCollectionsComponent } from "./collections.component";
import { EntityEventsComponent } from "./entity-events.component";
import { EventsComponent } from "./events.component";
import { GroupAddEditComponent } from "./group-add-edit.component";
import { GroupsComponent } from "./groups.component";
import { ManageRoutingModule } from "./manage-routing.module";
import { ManageComponent } from "./manage.component";
import { PeopleComponent } from "./people.component";
import { PolicyEditComponent } from "./policy-edit.component";
import { ResetPasswordComponent } from "./reset-password.component";
import { UserAddEditComponent } from "./user-add-edit.component";
import { UserConfirmComponent } from "./user-confirm.component";
import { UserGroupsComponent } from "./user-groups.component";
@NgModule({
imports: [CommonModule, SharedModule, PoliciesModule, ManageRoutingModule],
declarations: [
BulkConfirmComponent,
BulkRemoveComponent,
BulkStatusComponent,
CollectionAddEditComponent,
EntityEventsComponent,
EventsComponent,
GroupAddEditComponent,
GroupsComponent,
ManageCollectionsComponent,
ManageComponent,
PeopleComponent,
PolicyEditComponent,
ResetPasswordComponent,
UserAddEditComponent,
UserConfirmComponent,
UserGroupsComponent,
],
})
export class ManageModule {}

View File

@@ -10,9 +10,9 @@ import { Organization } from "jslib-common/models/domain/organization";
import { PolicyResponse } from "jslib-common/models/response/policyResponse";
import { PolicyListService } from "../../services/policy-list.service";
import { PolicyEditComponent } from "../manage/policy-edit.component";
import { BasePolicy } from "../policies/base-policy.component";
import { BasePolicy } from "./base-policy.component";
import { PolicyEditComponent } from "./policy-edit.component";
@Component({
selector: "app-org-policies",

View File

@@ -0,0 +1,222 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { AuthGuard } from "jslib-angular/guards/auth.guard";
import { Permissions } from "jslib-common/enums/permissions";
import { PermissionsGuard } from "./guards/permissions.guard";
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
import { CollectionsComponent } from "./manage/collections.component";
import { EventsComponent } from "./manage/events.component";
import { GroupsComponent } from "./manage/groups.component";
import { ManageComponent } from "./manage/manage.component";
import { PeopleComponent } from "./manage/people.component";
import { PoliciesComponent } from "./manage/policies.component";
import { NavigationPermissionsService } from "./services/navigation-permissions.service";
import { AccountComponent } from "./settings/account.component";
import { OrganizationBillingComponent } from "./settings/organization-billing.component";
import { OrganizationSubscriptionComponent } from "./settings/organization-subscription.component";
import { SettingsComponent } from "./settings/settings.component";
import { TwoFactorSetupComponent } from "./settings/two-factor-setup.component";
import { ExportComponent } from "./tools/export.component";
import { ExposedPasswordsReportComponent } from "./tools/exposed-passwords-report.component";
import { ImportComponent } from "./tools/import.component";
import { InactiveTwoFactorReportComponent } from "./tools/inactive-two-factor-report.component";
import { ReusedPasswordsReportComponent } from "./tools/reused-passwords-report.component";
import { ToolsComponent } from "./tools/tools.component";
import { UnsecuredWebsitesReportComponent } from "./tools/unsecured-websites-report.component";
import { WeakPasswordsReportComponent } from "./tools/weak-passwords-report.component";
const routes: Routes = [
{
path: ":organizationId",
component: OrganizationLayoutComponent,
canActivate: [AuthGuard, PermissionsGuard],
data: {
permissions: NavigationPermissionsService.getPermissions("admin"),
},
children: [
{ path: "", pathMatch: "full", redirectTo: "vault" },
{
path: "vault",
loadChildren: async () =>
(await import("../modules/vault/modules/organization-vault/organization-vault.module"))
.OrganizationVaultModule,
},
{
path: "tools",
component: ToolsComponent,
canActivate: [PermissionsGuard],
data: { permissions: NavigationPermissionsService.getPermissions("tools") },
children: [
{
path: "",
pathMatch: "full",
redirectTo: "import",
},
{
path: "import",
component: ImportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "importData",
permissions: [Permissions.AccessImportExport],
},
},
{
path: "export",
component: ExportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "exportVault",
permissions: [Permissions.AccessImportExport],
},
},
{
path: "exposed-passwords-report",
component: ExposedPasswordsReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "exposedPasswordsReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "inactive-two-factor-report",
component: InactiveTwoFactorReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "inactive2faReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "reused-passwords-report",
component: ReusedPasswordsReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "reusedPasswordsReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "unsecured-websites-report",
component: UnsecuredWebsitesReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "unsecuredWebsitesReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "weak-passwords-report",
component: WeakPasswordsReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "weakPasswordsReport",
permissions: [Permissions.AccessReports],
},
},
],
},
{
path: "manage",
component: ManageComponent,
canActivate: [PermissionsGuard],
data: {
permissions: NavigationPermissionsService.getPermissions("manage"),
},
children: [
{
path: "",
pathMatch: "full",
redirectTo: "people",
},
{
path: "collections",
component: CollectionsComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "collections",
permissions: [
Permissions.CreateNewCollections,
Permissions.EditAnyCollection,
Permissions.DeleteAnyCollection,
Permissions.EditAssignedCollections,
Permissions.DeleteAssignedCollections,
],
},
},
{
path: "events",
component: EventsComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "eventLogs",
permissions: [Permissions.AccessEventLogs],
},
},
{
path: "groups",
component: GroupsComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "groups",
permissions: [Permissions.ManageGroups],
},
},
{
path: "people",
component: PeopleComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "people",
permissions: [Permissions.ManageUsers, Permissions.ManageUsersPassword],
},
},
{
path: "policies",
component: PoliciesComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "policies",
permissions: [Permissions.ManagePolicies],
},
},
],
},
{
path: "settings",
component: SettingsComponent,
canActivate: [PermissionsGuard],
data: { permissions: NavigationPermissionsService.getPermissions("settings") },
children: [
{ path: "", pathMatch: "full", redirectTo: "account" },
{ path: "account", component: AccountComponent, data: { titleId: "myOrganization" } },
{
path: "two-factor",
component: TwoFactorSetupComponent,
data: { titleId: "twoStepLogin" },
},
{
path: "billing",
component: OrganizationBillingComponent,
canActivate: [PermissionsGuard],
data: { titleId: "billing", permissions: [Permissions.ManageBilling] },
},
{
path: "subscription",
component: OrganizationSubscriptionComponent,
data: { titleId: "subscription" },
},
],
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class OrganizationsRoutingModule {}

View File

@@ -1,46 +0,0 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { AuthGuard } from "jslib-angular/guards/auth.guard";
import { PermissionsGuard } from "./guards/permissions.guard";
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
import { NavigationPermissionsService } from "./services/navigation-permissions.service";
const routes: Routes = [
{
path: ":organizationId",
component: OrganizationLayoutComponent,
canActivate: [AuthGuard, PermissionsGuard],
data: {
permissions: NavigationPermissionsService.getPermissions("admin"),
},
children: [
{ path: "", pathMatch: "full", redirectTo: "vault" },
{
path: "vault",
loadChildren: async () =>
(await import("../modules/vault/modules/organization-vault/organization-vault.module"))
.OrganizationVaultModule,
},
{
path: "tools",
loadChildren: async () => (await import("./tools/tools.module")).ToolsModule,
},
{
path: "manage",
loadChildren: async () => (await import("./manage/manage.module")).ManageModule,
},
{
path: "settings",
loadChildren: async () => (await import("./settings/settings.module")).SettingsModule,
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class OrganizationsRoutingModule {}

View File

@@ -1,22 +0,0 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { LayoutsModule } from "../layouts/layouts.module";
import { SharedModule } from "../modules/shared.module";
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
import { OrganizationSwitcherComponent } from "./layouts/organization-switcher.component";
import { OrganizationsRoutingModule } from "./organizations-routing.module";
import { AcceptFamilySponsorshipComponent } from "./sponsorships/accept-family-sponsorship.component";
import { FamiliesForEnterpriseSetupComponent } from "./sponsorships/families-for-enterprise-setup.component";
@NgModule({
imports: [CommonModule, OrganizationsRoutingModule, SharedModule, LayoutsModule],
declarations: [
AcceptFamilySponsorshipComponent,
FamiliesForEnterpriseSetupComponent,
OrganizationLayoutComponent,
OrganizationSwitcherComponent,
],
})
export class OrganizationsModule {}

View File

@@ -1,32 +0,0 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { SharedModule } from "../../modules/shared.module";
import { DisableSendPolicyComponent } from "./disable-send.component";
import { MasterPasswordPolicyComponent } from "./master-password.component";
import { PasswordGeneratorPolicyComponent } from "./password-generator.component";
import { PersonalOwnershipPolicyComponent } from "./personal-ownership.component";
import { PoliciesComponent } from "./policies.component";
import { RequireSsoPolicyComponent } from "./require-sso.component";
import { ResetPasswordPolicyComponent } from "./reset-password.component";
import { SendOptionsPolicyComponent } from "./send-options.component";
import { SingleOrgPolicyComponent } from "./single-org.component";
import { TwoFactorAuthenticationPolicyComponent } from "./two-factor-authentication.component";
@NgModule({
imports: [CommonModule, SharedModule],
declarations: [
DisableSendPolicyComponent,
MasterPasswordPolicyComponent,
PasswordGeneratorPolicyComponent,
PersonalOwnershipPolicyComponent,
RequireSsoPolicyComponent,
ResetPasswordPolicyComponent,
SendOptionsPolicyComponent,
SingleOrgPolicyComponent,
TwoFactorAuthenticationPolicyComponent,
PoliciesComponent,
],
})
export class PoliciesModule {}

View File

@@ -12,9 +12,9 @@ import { BillingResponse } from "jslib-common/models/response/billingResponse";
@Component({
selector: "app-org-billing",
templateUrl: "./billing.component.html",
templateUrl: "./organization-billing.component.html",
})
export class BillingComponent implements OnInit {
export class OrganizationBillingComponent implements OnInit {
loading = false;
firstLoaded = false;
showAdjustPayment = false;

View File

@@ -23,9 +23,9 @@ import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component";
@Component({
selector: "app-org-subscription",
templateUrl: "subscription.component.html",
templateUrl: "organization-subscription.component.html",
})
export class SubscriptionComponent implements OnInit {
export class OrganizationSubscriptionComponent implements OnInit {
@ViewChild("setupBillingSyncTemplate", { read: ViewContainerRef, static: true })
setupBillingSyncModalRef: ViewContainerRef;

View File

@@ -1,48 +0,0 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { Permissions } from "jslib-common/enums/permissions";
import { PermissionsGuard } from "../guards/permissions.guard";
import { NavigationPermissionsService } from "../services/navigation-permissions.service";
import { AccountComponent } from "./account.component";
import { BillingComponent } from "./billing.component";
import { SettingsComponent } from "./settings.component";
import { SubscriptionComponent } from "./subscription.component";
import { TwoFactorSetupComponent } from "./two-factor-setup.component";
const routes: Routes = [
{
path: "",
component: SettingsComponent,
canActivate: [PermissionsGuard],
data: { permissions: NavigationPermissionsService.getPermissions("settings") },
children: [
{ path: "", pathMatch: "full", redirectTo: "account" },
{ path: "account", component: AccountComponent, data: { titleId: "myOrganization" } },
{
path: "two-factor",
component: TwoFactorSetupComponent,
data: { titleId: "twoStepLogin" },
},
{
path: "billing",
component: BillingComponent,
canActivate: [PermissionsGuard],
data: { titleId: "billing", permissions: [Permissions.ManageBilling] },
},
{
path: "subscription",
component: SubscriptionComponent,
data: { titleId: "subscription" },
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class SettingsRoutingModule {}

View File

@@ -1,35 +0,0 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { SharedModule } from "../../modules/shared.module";
import { AccountComponent } from "./account.component";
import { AdjustSubscription } from "./adjust-subscription.component";
import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component";
import { BillingComponent } from "./billing.component";
import { ChangePlanComponent } from "./change-plan.component";
import { DeleteOrganizationComponent } from "./delete-organization.component";
import { DownloadLicenseComponent } from "./download-license.component";
import { ImageSubscriptionHiddenComponent } from "./image-subscription-hidden.component";
import { SettingsRoutingModule } from "./settings-routing.module";
import { SettingsComponent } from "./settings.component";
import { SubscriptionComponent } from "./subscription.component";
import { TwoFactorSetupComponent } from "./two-factor-setup.component";
@NgModule({
imports: [CommonModule, SharedModule, SettingsRoutingModule],
declarations: [
AccountComponent,
AdjustSubscription,
BillingComponent,
BillingSyncApiKeyComponent,
ChangePlanComponent,
DeleteOrganizationComponent,
DownloadLicenseComponent,
ImageSubscriptionHiddenComponent,
SettingsComponent,
SubscriptionComponent,
TwoFactorSetupComponent,
],
})
export class SettingsModule {}

View File

@@ -1,101 +0,0 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { Permissions } from "jslib-common/enums/permissions";
import { PermissionsGuard } from "../guards/permissions.guard";
import { NavigationPermissionsService } from "../services/navigation-permissions.service";
import { ExportComponent } from "./export.component";
import { ExposedPasswordsReportComponent } from "./exposed-passwords-report.component";
import { ImportComponent } from "./import.component";
import { InactiveTwoFactorReportComponent } from "./inactive-two-factor-report.component";
import { ReusedPasswordsReportComponent } from "./reused-passwords-report.component";
import { ToolsComponent } from "./tools.component";
import { UnsecuredWebsitesReportComponent } from "./unsecured-websites-report.component";
import { WeakPasswordsReportComponent } from "./weak-passwords-report.component";
const routes: Routes = [
{
path: "",
component: ToolsComponent,
canActivate: [PermissionsGuard],
data: { permissions: NavigationPermissionsService.getPermissions("tools") },
children: [
{
path: "",
pathMatch: "full",
redirectTo: "import",
},
{
path: "import",
component: ImportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "importData",
permissions: [Permissions.AccessImportExport],
},
},
{
path: "export",
component: ExportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "exportVault",
permissions: [Permissions.AccessImportExport],
},
},
{
path: "exposed-passwords-report",
component: ExposedPasswordsReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "exposedPasswordsReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "inactive-two-factor-report",
component: InactiveTwoFactorReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "inactive2faReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "reused-passwords-report",
component: ReusedPasswordsReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "reusedPasswordsReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "unsecured-websites-report",
component: UnsecuredWebsitesReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "unsecuredWebsitesReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "weak-passwords-report",
component: WeakPasswordsReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "weakPasswordsReport",
permissions: [Permissions.AccessReports],
},
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ToolsRoutingModule {}

View File

@@ -1,29 +0,0 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { SharedModule } from "../../modules/shared.module";
import { ExportComponent } from "./export.component";
import { ExposedPasswordsReportComponent } from "./exposed-passwords-report.component";
import { ImportComponent } from "./import.component";
import { InactiveTwoFactorReportComponent } from "./inactive-two-factor-report.component";
import { ReusedPasswordsReportComponent } from "./reused-passwords-report.component";
import { ToolsRoutingModule } from "./tools-routing.module";
import { ToolsComponent } from "./tools.component";
import { UnsecuredWebsitesReportComponent } from "./unsecured-websites-report.component";
import { WeakPasswordsReportComponent } from "./weak-passwords-report.component";
@NgModule({
imports: [CommonModule, SharedModule, ToolsRoutingModule],
declarations: [
ExportComponent,
ExposedPasswordsReportComponent,
ImportComponent,
InactiveTwoFactorReportComponent,
ReusedPasswordsReportComponent,
ToolsComponent,
UnsecuredWebsitesReportComponent,
WeakPasswordsReportComponent,
],
})
export class ToolsModule {}

View File

@@ -22,11 +22,11 @@ import { Organization } from "jslib-common/models/domain/organization";
import { CipherCreateRequest } from "jslib-common/models/request/cipherCreateRequest";
import { CipherRequest } from "jslib-common/models/request/cipherRequest";
import { AddEditComponent as BaseAddEditComponent } from "../../../../vault/add-edit.component";
import { AddEditComponent as BaseAddEditComponent } from "../../vault/add-edit.component";
@Component({
selector: "app-org-vault-add-edit",
templateUrl: "../../../../vault/add-edit.component.html",
templateUrl: "../../vault/add-edit.component.html",
})
export class AddEditComponent extends BaseAddEditComponent {
organization: Organization;

View File

@@ -12,11 +12,11 @@ import { Cipher } from "jslib-common/models/domain/cipher";
import { Organization } from "jslib-common/models/domain/organization";
import { AttachmentView } from "jslib-common/models/view/attachmentView";
import { AttachmentsComponent as BaseAttachmentsComponent } from "../../../../vault/attachments.component";
import { AttachmentsComponent as BaseAttachmentsComponent } from "../../vault/attachments.component";
@Component({
selector: "app-org-vault-attachments",
templateUrl: "../../../../vault/attachments.component.html",
templateUrl: "../../vault/attachments.component.html",
})
export class AttachmentsComponent extends BaseAttachmentsComponent {
viewOnly = false;

View File

@@ -15,11 +15,11 @@ import { TotpService } from "jslib-common/abstractions/totp.service";
import { Organization } from "jslib-common/models/domain/organization";
import { CipherView } from "jslib-common/models/view/cipherView";
import { CiphersComponent as BaseCiphersComponent } from "../../../../vault/ciphers.component";
import { CiphersComponent as BaseCiphersComponent } from "../../vault/ciphers.component";
@Component({
selector: "app-org-vault-ciphers",
templateUrl: "../../../../vault/ciphers.component.html",
templateUrl: "../../vault/ciphers.component.html",
})
export class CiphersComponent extends BaseCiphersComponent {
@Output() onEventsClicked = new EventEmitter<CipherView>();

View File

@@ -11,11 +11,11 @@ import { Cipher } from "jslib-common/models/domain/cipher";
import { Organization } from "jslib-common/models/domain/organization";
import { CipherCollectionsRequest } from "jslib-common/models/request/cipherCollectionsRequest";
import { CollectionsComponent as BaseCollectionsComponent } from "../../../../vault/collections.component";
import { CollectionsComponent as BaseCollectionsComponent } from "../../vault/collections.component";
@Component({
selector: "app-org-vault-collections",
templateUrl: "../../../../vault/collections.component.html",
templateUrl: "../../vault/collections.component.html",
})
export class CollectionsComponent extends BaseCollectionsComponent {
organization: Organization;

View File

@@ -233,8 +233,10 @@ const routes: Routes = [
},
{
path: "organizations",
loadChildren: async () =>
(await import("./organizations/organizations.module")).OrganizationsModule,
loadChildren: () =>
import("./organizations/organization-routing.module").then(
(m) => m.OrganizationsRoutingModule
),
},
];

View File

@@ -4,11 +4,13 @@ import { LooseComponentsModule } from "./modules/loose-components.module";
import { OrganizationManageModule } from "./modules/organizations/manage/organization-manage.module";
import { OrganizationUserModule } from "./modules/organizations/users/organization-user.module";
import { PipesModule } from "./modules/pipes/pipes.module";
import { SharedModule } from "./modules/shared.module";
import { VaultFilterModule } from "./modules/vault-filter/vault-filter.module";
import { OrganizationBadgeModule } from "./modules/vault/modules/organization-badge/organization-badge.module";
@NgModule({
imports: [
SharedModule,
LooseComponentsModule,
VaultFilterModule,
OrganizationBadgeModule,

View File

@@ -17,13 +17,7 @@
<small class="form-text text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small>
</div>
</div>
<button
bit-button
buttonType="primary"
class="btn-submit"
type="submit"
[disabled]="form.loading"
>
<button bitButton buttonType="primary" class="btn-submit" type="submit" [disabled]="form.loading">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "checkBreaches" | i18n }}</span>
</button>

View File

@@ -8,7 +8,7 @@ import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType";
import { Organization } from "jslib-common/models/domain/organization";
import { CipherView } from "jslib-common/models/view/cipherView";
import { AddEditComponent as OrgAddEditComponent } from "../modules/vault/modules/organization-vault/add-edit.component";
import { AddEditComponent as OrgAddEditComponent } from "../organizations/vault/add-edit.component";
import { AddEditComponent } from "../vault/add-edit.component";
@Directive()

View File

@@ -3,7 +3,7 @@
</div>
<p>{{ "exposedPasswordsReportDesc" | i18n }}</p>
<button
bit-button
bitButton
buttonType="primary"
type="button"
class="btn-submit"

View File

@@ -15,7 +15,7 @@
<p class="tw-mb-0">{{ report.description | i18n }}</p>
</div>
<span
bit-badge
bitBadge
badgeType="success"
class="tw-absolute tw-left-2 tw-top-2 tw-leading-none"
*ngIf="premium"

View File

@@ -3,7 +3,7 @@
<div class="row mt-4">
<div class="col">
<a bit-button routerLink="./" *ngIf="!homepage">
<a bitButton routerLink="./" *ngIf="!homepage">
<i class="bwi bwi-angle-left" aria-hidden="true"></i>
{{ "backToReports" | i18n }}
</a>

View File

@@ -23,7 +23,7 @@
<ul class="filter-options">
<li class="filter-option" [ngClass]="{ active: selectedAll }">
<span class="filter-buttons">
<button bit-button class="filter-button" appStopClick (click)="selectAll()">
<button bitButton class="filter-button" appStopClick (click)="selectAll()">
<i class="bwi bwi-fw bwi-filter"></i>{{ "allSends" | i18n }}
</button>
</span>
@@ -38,7 +38,7 @@
<li class="filter-option" [ngClass]="{ active: selectedType === sendType.Text }">
<span class="filter-buttons">
<button
bit-button
bitButton
class="filter-button"
appStopClick
(click)="selectType(sendType.Text)"
@@ -50,7 +50,7 @@
<li class="filter-option" [ngClass]="{ active: selectedType === sendType.File }">
<span class="filter-buttons">
<button
bit-button
bitButton
class="filter-button"
appStopClick
(click)="selectType(sendType.File)"
@@ -160,19 +160,15 @@
<i class="bwi bwi-ellipsis-v bwi-lg" aria-hidden="true"></i>
</button>
<bit-menu #sendOptions>
<button bit-menu-item (click)="copy(s)">
<button bitMenuItem (click)="copy(s)">
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
{{ "copySendLink" | i18n }}
</button>
<button
bit-menu-item
(click)="removePassword(s)"
*ngIf="s.password && !disableSend"
>
<button bitMenuItem (click)="removePassword(s)" *ngIf="s.password && !disableSend">
<i class="bwi bwi-fw bwi-close" aria-hidden="true"></i>
{{ "removePassword" | i18n }}
</button>
<button bit-menu-item (click)="delete(s)">
<button bitMenuItem (click)="delete(s)">
<span class="tw-text-danger">
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
{{ "delete" | i18n }}

View File

@@ -14,13 +14,13 @@
<div class="card border-danger">
<div class="card-body">
<p>{{ "dangerZoneDesc" | i18n }}</p>
<button bit-button buttonType="danger" (click)="deauthorizeSessions()">
<button bitButton buttonType="danger" (click)="deauthorizeSessions()">
{{ "deauthorizeSessions" | i18n }}
</button>
<button bit-button buttonType="danger" (click)="purgeVault()">
<button bitButton buttonType="danger" (click)="purgeVault()">
{{ "purgeVault" | i18n }}
</button>
<button bit-button buttonType="danger" (click)="deleteAccount()">
<button bitButton buttonType="danger" (click)="deleteAccount()">
{{ "deleteAccount" | i18n }}
</button>
</div>

View File

@@ -3,6 +3,7 @@ import { Component } from "@angular/core";
import { ApiService } from "jslib-common/abstractions/api.service";
import { LogService } from "jslib-common/abstractions/log.service";
import { OrganizationConnectionType } from "jslib-common/enums/organizationConnectionType";
import { Utils } from "jslib-common/misc/utils";
import { BillingSyncConfigApi } from "jslib-common/models/api/billingSyncConfigApi";
import { BillingSyncConfigRequest } from "jslib-common/models/request/billingSyncConfigRequest";
import { OrganizationConnectionRequest } from "jslib-common/models/request/organizationConnectionRequest";

View File

@@ -71,7 +71,7 @@
</div>
</div>
</div>
<button bit-button buttonType="primary" class="btn-submit" [disabled]="form.loading">
<button bitButton buttonType="primary" class="btn-submit" [disabled]="form.loading">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "changeKdf" | i18n }}</span>
</button>

View File

@@ -87,7 +87,7 @@
</a>
</div>
</div>
<button bit-button buttonType="primary" class="btn-submit" [disabled]="form.loading">
<button bitButton buttonType="primary" class="btn-submit" [disabled]="form.loading">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "changeMasterPassword" | i18n }}</span>
</button>

View File

@@ -3,7 +3,7 @@
{{ "paymentMethod" | i18n }}
</h1>
<button
bit-button
bitButton
buttonType="secondary"
(click)="load()"
class="tw-ml-auto"
@@ -28,7 +28,7 @@
<strong>{{ creditOrBalance | currency: "$" }}</strong>
</p>
<p>{{ "creditAppliedDesc" | i18n }}</p>
<button bit-button buttonType="secondary" (click)="addCredit()" *ngIf="!showAddCredit">
<button bitButton buttonType="secondary" (click)="addCredit()" *ngIf="!showAddCredit">
{{ "addCredit" | i18n }}
</button>
<app-add-credit
@@ -56,7 +56,7 @@
{{ paymentSource.description }}
</p>
</ng-container>
<button bit-button buttonType="secondary" (click)="changePayment()" *ngIf="!showAdjustPayment">
<button bitButton buttonType="secondary" (click)="changePayment()" *ngIf="!showAdjustPayment">
{{ (paymentSource ? "changePaymentMethod" : "addPaymentMethod") | i18n }}
</button>
<app-adjust-payment

View File

@@ -48,7 +48,7 @@
{{ "premiumPrice" | i18n: (premiumPrice | currency: "$") }}
</p>
<a
bit-button
bitButton
href="https://vault.bitwarden.com/#/settings/premium"
target="_blank"
rel="noopener"
@@ -69,7 +69,7 @@
}}</small>
</div>
<button
bit-button
bitButton
buttonType="primary"
type="submit"
class="btn-submit"
@@ -125,13 +125,7 @@
</p>
</div>
<small class="text-muted font-italic">{{ "paymentChargedAnnually" | i18n }}</small>
<button
bit-button
buttonType="primary"
type="submit"
class="btn-submit"
[disabled]="form.loading"
>
<button bitButton buttonType="primary" type="submit" class="btn-submit" [disabled]="form.loading">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "submit" | i18n }}</span>
</button>

View File

@@ -8,10 +8,10 @@
<p>
{{ "userApiKeyDesc" | i18n }}
</p>
<button bit-button buttonType="secondary" (click)="viewUserApiKey()">
<button bitButton buttonType="secondary" (click)="viewUserApiKey()">
{{ "viewApiKey" | i18n }}
</button>
<button bit-button buttonType="secondary" (click)="rotateUserApiKey()">
<button bitButton buttonType="secondary" (click)="rotateUserApiKey()">
{{ "rotateApiKey" | i18n }}
</button>
<ng-template #viewUserApiKeyTemplate></ng-template>

View File

@@ -5,7 +5,7 @@
<p *ngIf="organizationId">{{ "twoStepLoginOrganizationDesc" | i18n }}</p>
<bit-callout type="warning" *ngIf="!organizationId">
<p>{{ "twoStepLoginRecoveryWarning" | i18n }}</p>
<button bit-button buttonType="secondary" (click)="recoveryCode()">
<button bitButton buttonType="secondary" (click)="recoveryCode()">
{{ "viewRecoveryCode" | i18n }}
</button>
</bit-callout>
@@ -45,7 +45,7 @@
</div>
<div class="ml-auto">
<button
bit-button
bitButton
buttonType="secondary"
[disabled]="!canAccessPremium && p.premium"
(click)="manage(p.type)"

View File

@@ -3,7 +3,7 @@
{{ "billingHistory" | i18n }}
</h1>
<button
bit-button
bitButton
buttonType="secondary"
(click)="load()"
class="tw-ml-auto"

View File

@@ -39,7 +39,7 @@
>
<p>{{ "subscriptionPendingCanceled" | i18n }}</p>
<button
bit-button
bitButton
type="button"
buttonType="secondary"
#reinstateBtn
@@ -63,7 +63,7 @@
<dt>{{ "status" | i18n }}</dt>
<dd>
<span class="text-capitalize">{{ (subscription && subscription.status) || "-" }}</span>
<span bit-badge badgeType="warning" *ngIf="subscriptionMarkedForCancel">{{
<span bitBadge badgeType="warning" *ngIf="subscriptionMarkedForCancel">{{
"pendingCancellation" | i18n
}}</span>
</dd>
@@ -96,11 +96,11 @@
</div>
<ng-container *ngIf="selfHosted">
<div>
<button type="button" bit-button buttonType="secondary" (click)="updateLicense()">
<button type="button" bitButton buttonType="secondary" (click)="updateLicense()">
{{ "updateLicense" | i18n }}
</button>
<a
bit-button
bitButton
buttonType="secondary"
href="https://vault.bitwarden.com/#/settings/subscription"
target="_blank"
@@ -131,7 +131,7 @@
<ng-container *ngIf="!selfHosted">
<div class="d-flex">
<button
bit-button
bitButton
type="button"
buttonType="secondary"
(click)="downloadLicense()"
@@ -140,7 +140,7 @@
{{ "downloadLicense" | i18n }}
</button>
<button
bit-button
bitButton
#cancelBtn
type="button"
buttonType="danger"
@@ -171,11 +171,11 @@
<ng-container *ngIf="subscription && !subscription.cancelled && !subscriptionMarkedForCancel">
<div class="mt-3">
<div class="d-flex" *ngIf="!showAdjustStorage">
<button bit-button type="button" buttonType="secondary" (click)="adjustStorage(true)">
<button bitButton type="button" buttonType="secondary" (click)="adjustStorage(true)">
{{ "addStorage" | i18n }}
</button>
<button
bit-button
bitButton
type="button"
buttonType="secondary"
class="tw-ml-1"

View File

@@ -64,12 +64,12 @@
</button>
<bit-menu #cipherOptions>
<ng-container *ngIf="c.type === cipherType.Login && !c.isDeleted">
<button bit-menu-item (click)="copy(c, c.login.username, 'username', 'Username')">
<button bitMenuItem (click)="copy(c, c.login.username, 'username', 'Username')">
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
{{ "copyUsername" | i18n }}
</button>
<button
bit-menu-item
bitMenuItem
(click)="copy(c, c.login.password, 'password', 'Password')"
*ngIf="c.viewPassword"
>
@@ -77,24 +77,24 @@
{{ "copyPassword" | i18n }}
</button>
<button
bit-menu-item
bitMenuItem
(click)="copy(c, c.login.totp, 'verificationCodeTotp', 'TOTP')"
*ngIf="displayTotpCopyButton(c)"
>
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
{{ "copyVerificationCode" | i18n }}
</button>
<button bit-menu-item *ngIf="c.login.canLaunch" (click)="launch(c.login.launchUri)">
<button bitMenuItem *ngIf="c.login.canLaunch" (click)="launch(c.login.launchUri)">
<i class="bwi bwi-fw bwi-share-square" aria-hidden="true"></i>
{{ "launch" | i18n }}
</button>
</ng-container>
<button bit-menu-item (click)="attachments(c)">
<button bitMenuItem (click)="attachments(c)">
<i class="bwi bwi-fw bwi-paperclip" aria-hidden="true"></i>
{{ "attachments" | i18n }}
</button>
<button
bit-menu-item
bitMenuItem
*ngIf="((!organization && !c.organizationId) || organization) && !c.isDeleted"
(click)="clone(c)"
>
@@ -102,26 +102,26 @@
{{ "clone" | i18n }}
</button>
<button
bit-menu-item
bitMenuItem
*ngIf="!organization && !c.organizationId && !c.isDeleted"
(click)="share(c)"
>
<i class="bwi bwi-fw bwi-arrow-circle-right" aria-hidden="true"></i>
{{ "moveToOrganization" | i18n }}
</button>
<button bit-menu-item *ngIf="c.organizationId && !c.isDeleted" (click)="collections(c)">
<button bitMenuItem *ngIf="c.organizationId && !c.isDeleted" (click)="collections(c)">
<i class="bwi bwi-fw bwi-collection" aria-hidden="true"></i>
{{ "collections" | i18n }}
</button>
<button bit-menu-item *ngIf="c.organizationId && accessEvents" (click)="events(c)">
<button bitMenuItem *ngIf="c.organizationId && accessEvents" (click)="events(c)">
<i class="bwi bwi-fw bwi-file-text" aria-hidden="true"></i>
{{ "eventLogs" | i18n }}
</button>
<button bit-menu-item (click)="restore(c)" *ngIf="c.isDeleted">
<button bitMenuItem (click)="restore(c)" *ngIf="c.isDeleted">
<i class="bwi bwi-fw bwi-undo" aria-hidden="true"></i>
{{ "restore" | i18n }}
</button>
<button bit-menu-item (click)="delete(c)">
<button bitMenuItem (click)="delete(c)">
<span class="tw-text-danger">
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
{{ (c.isDeleted ? "permanentlyDelete" : "delete") | i18n }}