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

Compare commits

..

9 Commits

Author SHA1 Message Date
Hinton
283f295481 Change fields to field(s) 2022-05-30 13:47:02 +02:00
Hinton
749ead5863 Move error summary below form 2022-05-23 17:15:21 +02:00
Hinton
8d369bcf84 Add error summary 2022-05-23 15:27:49 +02:00
Hinton
aa7fb1befb Add input i18n 2022-05-20 16:57:55 +02:00
Hinton
43ca31e0ae Validate before submit 2022-05-17 22:19:27 +02:00
Hinton
0dfc8c5a0b Merge branch 'master' of github.com:bitwarden/web into feature/cl-forms
# Conflicts:
#	jslib
2022-05-17 21:59:13 +02:00
Hinton
c1801dfc61 Merge branch 'master' of github.com:bitwarden/web into feature/cl-forms
# Conflicts:
#	jslib
2022-05-10 16:40:13 +02:00
Hinton
59a53740a4 Merge branch 'master' of github.com:bitwarden/web into feature/cl-forms
# Conflicts:
#	jslib
#	src/app/organizations/settings/account.component.html
#	src/app/organizations/settings/account.component.ts
#	src/app/oss.module.ts
2022-05-10 14:51:10 +02:00
Hinton
dd2c2b9720 Update Accounts form to use reactive forms and bit-form-field 2022-05-03 11:21:42 +02:00
62 changed files with 684 additions and 815 deletions

View File

@@ -19,8 +19,8 @@ jobs:
name: Setup
runs-on: ubuntu-20.04
outputs:
release_version: ${{ steps.version.outputs.version }}
tag_version: ${{ steps.version.outputs.version }}
release_version: ${{ steps.version.outputs.package }}
tag_version: ${{ steps.version.outputs.tag }}
branch_name: ${{ steps.branch.outputs.branch_name }}
steps:
- name: Branch check
@@ -38,11 +38,20 @@ jobs:
- name: Check Release Version
id: version
uses: bitwarden/gh-actions/release-version-check@ea9fab01d76940267b4147cc1c4542431246b9f6
with:
release-type: ${{ github.event.inputs.release_type }}
project-type: ts
file: package.json
run: |
version=$( jq -r ".version" package.json)
previous_release_tag_version=$(
curl -sL https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest | jq -r ".tag_name"
)
if [ "v$version" == "$previous_release_tag_version" ] && \
[ "${{ github.event.inputs.release_type }}" == "Initial Release" ]; then
echo "[!] Already released v$version. Please bump version to continue"
exit 1
fi
echo "::set-output name=package::$version"
echo "::set-output name=tag::v$version"
- name: Get branch name
id: branch

View File

@@ -22,16 +22,14 @@ const routes: Routes = [
component: ManageComponent,
canActivate: [PermissionsGuard],
data: {
permissions: NavigationPermissionsService.getPermissions("manage"),
permissions: NavigationPermissionsService.getPermissions("manage").concat(
Permissions.ManageSso
),
},
children: [
{
path: "sso",
component: SsoComponent,
canActivate: [PermissionsGuard],
data: {
permissions: [Permissions.ManageSso],
},
},
],
},

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,

2
jslib

Submodule jslib updated: 0d658ba26d...3bf25edd3e

4
package-lock.json generated
View File

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

View File

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

View File

@@ -101,7 +101,7 @@
<div [ngClass]="{ 'col-5': layout, 'col-12': !layout }">
<div class="row justify-content-md-center mt-5">
<div [ngClass]="{ 'col-5': !layout, 'col-12': layout }">
<h1 class="lead text-center mb-4" *ngIf="!layout">{{ "createAccount" | i18n }}</h1>
<p class="lead text-center mb-4" *ngIf="!layout">{{ "createAccount" | i18n }}</p>
<div class="card d-block">
<div class="card-body">
<app-callout

View File

@@ -122,20 +122,17 @@ export abstract class BaseEventsComponent {
const userId = r.actingUserId == null ? r.userId : r.actingUserId;
const eventInfo = await this.eventService.getEventInfo(r);
const user = this.getUserName(r, userId);
const userName = user != null ? user.name : this.i18nService.t("unknown");
return new EventView({
message: eventInfo.message,
humanReadableMessage: eventInfo.humanReadableMessage,
appIcon: eventInfo.appIcon,
appName: eventInfo.appName,
userId: userId,
userName: r.installationId != null ? `Installation: ${r.installationId}` : userName,
userName: user != null ? user.name : this.i18nService.t("unknown"),
userEmail: user != null ? user.email : "",
date: r.date,
ip: r.ipAddress,
type: r.type,
installationId: r.installationId,
});
})
);

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

@@ -1,6 +1,6 @@
<div class="container footer text-muted">
<div class="row">
<div class="col">&copy; {{ year }} Bitwarden Inc.</div>
<div class="col">&copy; {{ year }}, Bitwarden Inc.</div>
<div class="col text-center"></div>
<div class="col text-right">
{{ "versionNumber" | i18n: version }}

View File

@@ -1,5 +1,5 @@
<router-outlet></router-outlet>
<div class="container my-5 text-muted text-center">
&copy; {{ year }} Bitwarden Inc. <br />
&copy; {{ year }}, Bitwarden Inc. <br />
{{ "versionNumber" | i18n: version }}
</div>

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

@@ -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,10 @@ 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 { LinkSsoComponent } from "../settings/link-sso.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 +169,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 +183,10 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
AddEditCustomFieldsComponent,
AdjustPaymentComponent,
AdjustStorageComponent,
AdjustSubscription,
ApiKeyComponent,
AttachmentsComponent,
BillingSyncApiKeyComponent,
BillingSyncKeyComponent,
BreachReportComponent,
BulkActionsComponent,
@@ -135,12 +197,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 +216,65 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
EmergencyAddEditComponent,
ExportComponent,
ExposedPasswordsReportComponent,
FamiliesForEnterpriseSetupComponent,
FolderAddEditComponent,
FooterComponent,
FrontendLayoutComponent,
HintComponent,
ImportComponent,
InactiveTwoFactorReportComponent,
LinkSsoComponent,
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 +288,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 +345,7 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
AddEditCustomFieldsComponent,
AdjustPaymentComponent,
AdjustStorageComponent,
AdjustSubscription,
ApiKeyComponent,
AttachmentsComponent,
BreachReportComponent,
@@ -237,12 +357,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 +376,64 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
EmergencyAddEditComponent,
ExportComponent,
ExposedPasswordsReportComponent,
FamiliesForEnterpriseSetupComponent,
FolderAddEditComponent,
FooterComponent,
FrontendLayoutComponent,
HintComponent,
ImportComponent,
InactiveTwoFactorReportComponent,
LinkSsoComponent,
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 +447,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

@@ -1,59 +0,0 @@
<div
class="modal fade"
role="dialog"
aria-modal="true"
aria-labelledby="enrollMasterPasswordResetTitle"
>
<div class="modal-dialog modal-dialog-scrollable" role="document">
<form
class="modal-content"
#form
(ngSubmit)="submit()"
[appApiAction]="formPromise"
ngNativeValidate
>
<div class="modal-header">
<h2 class="modal-title" id="enrollMasterPasswordResetTitle">
{{ (isEnrolled ? "withdrawPasswordReset" : "enrollPasswordReset") | i18n }}
</h2>
<button
type="button"
class="close"
data-dismiss="modal"
appA11yTitle="{{ 'close' | i18n }}"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<app-callout type="warning" *ngIf="!isEnrolled">
{{ "resetPasswordEnrollmentWarning" | i18n }}
</app-callout>
<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">
<i
class="bwi bwi-spinner bwi-spin"
title="{{ 'loading' | i18n }}"
*ngIf="form.loading"
></i>
<span>
{{ "submit" | i18n }}
</span>
</button>
<button
bit-button
buttonType="secondary"
type="button"
data-dismiss="modal"
appA11yTitle="{{ 'close' | i18n }}"
>
<span>
{{ "cancel" | i18n }}
</span>
</button>
</div>
</form>
</div>
</div>

View File

@@ -1,97 +0,0 @@
import { Component } from "@angular/core";
import { ModalRef } from "jslib-angular/components/modal/modal.ref";
import { ModalConfig } from "jslib-angular/services/modal.service";
import { ApiService } from "jslib-common/abstractions/api.service";
import { CryptoService } from "jslib-common/abstractions/crypto.service";
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { LogService } from "jslib-common/abstractions/log.service";
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
import { SyncService } from "jslib-common/abstractions/sync.service";
import { UserVerificationService } from "jslib-common/abstractions/userVerification.service";
import { Utils } from "jslib-common/misc/utils";
import { Organization } from "jslib-common/models/domain/organization";
import { OrganizationUserResetPasswordEnrollmentRequest } from "jslib-common/models/request/organizationUserResetPasswordEnrollmentRequest";
import { Verification } from "jslib-common/types/verification";
@Component({
selector: "app-enroll-master-password-reset",
templateUrl: "enroll-master-password-reset.component.html",
})
export class EnrollMasterPasswordReset {
organization: Organization;
verification: Verification;
formPromise: Promise<any>;
constructor(
private userVerificationService: UserVerificationService,
private apiService: ApiService,
private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService,
private cryptoService: CryptoService,
private syncService: SyncService,
private logService: LogService,
private modalRef: ModalRef,
config: ModalConfig
) {
this.organization = config.data.organization;
}
async submit() {
let toastStringRef = "withdrawPasswordResetSuccess";
this.formPromise = this.userVerificationService
.buildRequest(this.verification, OrganizationUserResetPasswordEnrollmentRequest)
.then(async (request) => {
// Set variables
let keyString: string = null;
// Enrolling
if (!this.organization.resetPasswordEnrolled) {
// Retrieve Public Key
const orgKeys = await this.apiService.getOrganizationKeys(this.organization.id);
if (orgKeys == null) {
throw new Error(this.i18nService.t("resetPasswordOrgKeysError"));
}
const publicKey = Utils.fromB64ToArray(orgKeys.publicKey);
// RSA Encrypt user's encKey.key with organization public key
const encKey = await this.cryptoService.getEncKey();
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer);
keyString = encryptedKey.encryptedString;
toastStringRef = "enrollPasswordResetSuccess";
// Create request and execute enrollment
request.resetPasswordKey = keyString;
await this.apiService.putOrganizationUserResetPasswordEnrollment(
this.organization.id,
this.organization.userId,
request
);
} else {
// Withdrawal
request.resetPasswordKey = keyString;
await this.apiService.putOrganizationUserResetPasswordEnrollment(
this.organization.id,
this.organization.userId,
request
);
}
await this.syncService.fullSync(true);
});
try {
await this.formPromise;
this.platformUtilsService.showToast("success", null, this.i18nService.t(toastStringRef));
this.modalRef.close();
} catch (e) {
this.logService.error(e);
}
}
get isEnrolled(): boolean {
return this.organization.resetPasswordEnrolled;
}
}

View File

@@ -1,14 +0,0 @@
import { ScrollingModule } from "@angular/cdk/scrolling";
import { NgModule } from "@angular/core";
import { LooseComponentsModule } from "../../loose-components.module";
import { SharedModule } from "../../shared.module";
import { EnrollMasterPasswordReset } from "./enroll-master-password-reset.component";
@NgModule({
imports: [SharedModule, ScrollingModule, LooseComponentsModule],
declarations: [EnrollMasterPasswordReset],
exports: [EnrollMasterPasswordReset],
})
export class OrganizationUserModule {}

View File

@@ -53,16 +53,18 @@ import localeZhTw from "@angular/common/locales/zh-Hant";
import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { RouterModule } from "@angular/router";
import { BadgeModule, ButtonModule, CalloutModule, MenuModule } from "@bitwarden/components";
import {
BadgeModule,
ButtonModule,
CalloutModule,
FormFieldModule,
MenuModule,
} from "@bitwarden/components";
import { InfiniteScrollModule } from "ngx-infinite-scroll";
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");
@@ -130,8 +132,8 @@ registerLocaleData(localeZhTw, "zh-TW");
BadgeModule,
ButtonModule,
MenuModule,
FormFieldModule,
],
declarations: [PasswordStrengthComponent, OrganizationPlansComponent, PaymentComponent],
exports: [
CommonModule,
DragDropModule,
@@ -141,15 +143,13 @@ registerLocaleData(localeZhTw, "zh-TW");
ReactiveFormsModule,
RouterModule,
BadgeModule,
FormFieldModule,
ButtonModule,
CalloutModule,
ToastrModule,
BadgeModule,
ButtonModule,
MenuModule,
PasswordStrengthComponent,
OrganizationPlansComponent,
PaymentComponent,
],
providers: [DatePipe],
bootstrap: [],

View File

@@ -16,7 +16,7 @@
aria-hidden="true"
></i>
</button>
<h3 class="filter-title">&nbsp;{{ collectionsGrouping.name | i18n }}</h3>
<h3 class="filter-title">{{ collectionsGrouping.name | i18n }}</h3>
</div>
<ul id="collection-filters" *ngIf="!isCollapsed(collectionsGrouping)" class="filter-options">
<ng-template #recursiveCollections let-collections>
@@ -31,7 +31,7 @@
<button
class="toggle-button"
*ngIf="c.children.length"
(click)="toggleCollapse(c.node)"
(click)="collapse(c.node)"
title="{{ 'toggleCollapse' | i18n }}"
[attr.aria-expanded]="!isCollapsed(c.node)"
[attr.aria-controls]="c.node.name + '_children'"
@@ -51,7 +51,7 @@
class="bwi bwi-collection bwi-fw"
aria-hidden="true"
></i
>&nbsp;{{ c.node.name }}
>{{ c.node.name }}
</button>
</span>
<ul

View File

@@ -16,7 +16,9 @@
}"
></i>
</button>
<h3 class="filter-title">&nbsp;{{ "folders" | i18n }}</h3>
<h3 class="filter-title">
{{ "folders" | i18n }}
</h3>
<button
class="text-muted ml-auto add-button"
(click)="addFolder()"
@@ -54,7 +56,7 @@
</button>
<button class="filter-button" (click)="applyFilter(f.node)">
<i *ngIf="f.children.length === 0" class="bwi bwi-fw bwi-folder" aria-hidden="true"></i
>&nbsp;{{ f.node.name }}
>{{ f.node.name }}
</button>
<button
class="edit-button"

View File

@@ -14,7 +14,7 @@
<span class="filter-buttons">
<a href="#" routerLink="/create-organization" class="filter-button">
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
&nbsp;{{ "newOrganization" | i18n }}
{{ "newOrganization" | i18n }}
</a>
</span>
</li>
@@ -45,6 +45,14 @@
>
&nbsp;{{ organizationGrouping.name | i18n }}
</button>
<a
href="#"
routerLink="/create-organization"
class="text-muted ml-auto create-organization-link"
appA11yTitle="{{ 'newOrganization' | i18n }}"
>
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
</a>
</div>
<ul id="organization-filters" *ngIf="!isCollapsed" class="filter-options">
<li
@@ -67,14 +75,6 @@
</ng-container>
</span>
</li>
<li class="filter-option">
<span class="filter-buttons">
<a href="#" routerLink="/create-organization" class="filter-button">
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
&nbsp;{{ "newOrganization" | i18n }}
</a>
</span>
</li>
</ul>
</ng-container>
<ng-container *ngSwitchCase="'singleOrganizationAndPersonalOwnershipPolicies'">
@@ -110,6 +110,15 @@
>
&nbsp;{{ organizationGrouping.name | i18n }}
</button>
<a
href="#"
routerLink="/create-organization"
class="text-muted ml-auto create-organization-link"
appA11yTitle="{{ 'newOrganization' | i18n }}"
*ngIf="!(displayMode === 'singleOrganizationPolicy')"
>
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
</a>
</div>
<ul id="organization-filters" *ngIf="!isCollapsed" class="filter-options">
<li class="filter-option" [ngClass]="{ active: activeFilter.myVaultOnly }">
@@ -140,14 +149,6 @@
</ng-container>
</span>
</li>
<li class="filter-option" *ngIf="!(displayMode === 'singleOrganizationPolicy')">
<span class="filter-buttons">
<a href="#" routerLink="/create-organization" class="filter-button">
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
&nbsp;{{ "newOrganization" | i18n }}
</a>
</span>
</li>
</ul>
</ng-container>
</ng-container>

View File

@@ -1,17 +1,17 @@
import { Component, Input } from "@angular/core";
import { ModalService } from "jslib-angular/services/modal.service";
import { ApiService } from "jslib-common/abstractions/api.service";
import { CryptoService } from "jslib-common/abstractions/crypto.service";
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { LogService } from "jslib-common/abstractions/log.service";
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
import { PolicyService } from "jslib-common/abstractions/policy.service";
import { SyncService } from "jslib-common/abstractions/sync.service";
import { PolicyType } from "jslib-common/enums/policyType";
import { Utils } from "jslib-common/misc/utils";
import { Organization } from "jslib-common/models/domain/organization";
import { Policy } from "jslib-common/models/domain/policy";
import { EnrollMasterPasswordReset } from "../../organizations/users/enroll-master-password-reset.component";
import { OrganizationUserResetPasswordEnrollmentRequest } from "jslib-common/models/request/organizationUserResetPasswordEnrollmentRequest";
@Component({
selector: "app-organization-options",
@@ -29,8 +29,8 @@ export class OrganizationOptionsComponent {
private i18nService: I18nService,
private apiService: ApiService,
private syncService: SyncService,
private cryptoService: CryptoService,
private policyService: PolicyService,
private modalService: ModalService,
private logService: LogService
) {}
@@ -113,11 +113,70 @@ export class OrganizationOptionsComponent {
}
async toggleResetPasswordEnrollment(org: Organization) {
this.modalService.open(EnrollMasterPasswordReset, {
allowMultipleModals: true,
data: {
organization: org,
},
});
// Set variables
let keyString: string = null;
let toastStringRef = "withdrawPasswordResetSuccess";
// Enrolling
if (!org.resetPasswordEnrolled) {
// Alert user about enrollment
const confirmed = await this.platformUtilsService.showDialog(
this.i18nService.t("resetPasswordEnrollmentWarning"),
null,
this.i18nService.t("yes"),
this.i18nService.t("no"),
"warning"
);
if (!confirmed) {
return;
}
// Retrieve Public Key
this.actionPromise = this.apiService
.getOrganizationKeys(org.id)
.then(async (response) => {
if (response == null) {
throw new Error(this.i18nService.t("resetPasswordOrgKeysError"));
}
const publicKey = Utils.fromB64ToArray(response.publicKey);
// RSA Encrypt user's encKey.key with organization public key
const encKey = await this.cryptoService.getEncKey();
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer);
keyString = encryptedKey.encryptedString;
toastStringRef = "enrollPasswordResetSuccess";
// Create request and execute enrollment
const request = new OrganizationUserResetPasswordEnrollmentRequest();
request.resetPasswordKey = keyString;
return this.apiService.putOrganizationUserResetPasswordEnrollment(
org.id,
org.userId,
request
);
})
.then(() => {
return this.syncService.fullSync(true);
});
} else {
// Withdrawal
const request = new OrganizationUserResetPasswordEnrollmentRequest();
request.resetPasswordKey = keyString;
this.actionPromise = this.apiService
.putOrganizationUserResetPasswordEnrollment(org.id, org.userId, request)
.then(() => {
return this.syncService.fullSync(true);
});
}
try {
await this.actionPromise;
this.platformUtilsService.showToast("success", null, this.i18nService.t(toastStringRef));
await this.load();
} catch (e) {
this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), e.message);
this.logService.error(e);
}
}
}

View File

@@ -15,7 +15,9 @@
}"
></i>
</button>
<h3>&nbsp;{{ "types" | i18n }}</h3>
<h3>
{{ "types" | i18n }}
</h3>
</div>
<ul id="type-filters" *ngIf="!isCollapsed" class="filter-options">
<li
@@ -24,14 +26,14 @@
>
<span class="filter-buttons">
<button class="filter-button" (click)="applyFilter(cipherTypeEnum.Login)">
<i class="bwi bwi-fw bwi-globe" aria-hidden="true"></i>&nbsp;{{ "typeLogin" | i18n }}
<i class="bwi bwi-fw bwi-globe" aria-hidden="true"></i>{{ "typeLogin" | i18n }}
</button>
</span>
</li>
<li class="filter-option" [ngClass]="{ active: activeFilter.cipherType === cipherTypeEnum.Card }">
<span class="filter-buttons">
<button class="filter-button" (click)="applyFilter(cipherTypeEnum.Card)">
<i class="bwi bwi-fw bwi-credit-card" aria-hidden="true"></i>&nbsp;{{ "typeCard" | i18n }}
<i class="bwi bwi-fw bwi-credit-card" aria-hidden="true"></i>{{ "typeCard" | i18n }}
</button>
</span>
</li>
@@ -41,7 +43,7 @@
>
<span class="filter-buttons">
<button class="filter-button" (click)="applyFilter(cipherTypeEnum.Identity)">
<i class="bwi bwi-fw bwi-id-card" aria-hidden="true"></i>&nbsp;{{ "typeIdentity" | i18n }}
<i class="bwi bwi-fw bwi-id-card" aria-hidden="true"></i>{{ "typeIdentity" | i18n }}
</button>
</span>
</li>
@@ -51,9 +53,7 @@
>
<span class="filter-buttons">
<button class="filter-button" (click)="applyFilter(cipherTypeEnum.SecureNote)">
<i class="bwi bwi-fw bwi-sticky-note" aria-hidden="true"></i>&nbsp;{{
"typeSecureNote" | i18n
}}
<i class="bwi bwi-fw bwi-sticky-note" aria-hidden="true"></i>{{ "typeSecureNote" | i18n }}
</button>
</span>
</li>

View File

@@ -28,6 +28,16 @@ export class VaultFilterComponent extends BaseVaultFilterComponent {
this.onSearchTextChanged.emit(this.searchText);
}
// This method exists because the vault component gets its data mixed up during the initial sync on first login. It looks for data before the sync is complete.
// It should be removed as soon as doing so makes sense.
async reloadOrganizations() {
this.organizations = await this.vaultFilterService.buildOrganizations();
this.activePersonalOwnershipPolicy =
await this.vaultFilterService.checkForPersonalOwnershipPolicy();
this.activeSingleOrganizationPolicy =
await this.vaultFilterService.checkForSingleOrganizationPolicy();
}
async initCollections() {
return await this.vaultFilterService.buildCollections(this.organization?.id);
}

View File

@@ -12,7 +12,6 @@ import { SharedModule } from "../shared.module";
import { CollectionFilterComponent } from "./components/collection-filter.component";
import { FolderFilterComponent } from "./components/folder-filter.component";
import { LinkSsoComponent } from "./components/link-sso.component";
import { OrganizationFilterComponent } from "./components/organization-filter.component";
import { OrganizationOptionsComponent } from "./components/organization-options.component";
import { StatusFilterComponent } from "./components/status-filter.component";
@@ -29,7 +28,6 @@ import { VaultFilterComponent } from "./vault-filter.component";
OrganizationOptionsComponent,
StatusFilterComponent,
TypeFilterComponent,
LinkSsoComponent,
],
exports: [VaultFilterComponent],
providers: [

View File

@@ -58,6 +58,7 @@ export class IndividualVaultComponent implements OnInit, OnDestroy {
updateKeyModalRef: ViewContainerRef;
favorites = false;
type: CipherType = null;
folderId: string = null;
collectionId: string = null;
organizationId: string = null;
@@ -326,7 +327,7 @@ export class IndividualVaultComponent implements OnInit, OnDestroy {
async addCipher() {
const component = await this.editCipher(null);
component.type = this.activeFilter.cipherType;
component.type = this.type;
component.folderId = this.folderId === "none" ? null : this.folderId;
if (this.activeFilter.selectedCollectionId != null) {
const collection = this.filterComponent.collections.fullList.filter(
@@ -398,7 +399,7 @@ export class IndividualVaultComponent implements OnInit, OnDestroy {
if (queryParams == null) {
queryParams = {
favorites: this.favorites ? true : null,
type: this.activeFilter.cipherType,
type: this.type,
folderId: this.folderId,
collectionId: this.collectionId,
deleted: this.deleted ? true : null,

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 { 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 { VaultFilterComponent } from "../../../vault-filter/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({

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

@@ -52,7 +52,7 @@
target="_blank"
rel="noopener"
appA11yTitle="{{ 'learnMore' | i18n }}"
href="https://bitwarden.com/help/user-types-access-control/"
href="https://bitwarden.com/help/provider-users/"
>
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
</a>

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

@@ -14,62 +14,50 @@
#form
(ngSubmit)="submit()"
[appApiAction]="formPromise"
ngNativeValidate
[formGroup]="formData"
>
<div class="row">
<div class="col-6">
<div class="form-group">
<label for="name">{{ "organizationName" | i18n }}</label>
<input
id="name"
class="form-control"
type="text"
name="Name"
[(ngModel)]="org.name"
[disabled]="selfHosted"
/>
</div>
<div class="form-group">
<label for="billingEmail">{{ "billingEmail" | i18n }}</label>
<input
id="billingEmail"
class="form-control"
type="text"
name="BillingEmail"
[(ngModel)]="org.billingEmail"
[disabled]="selfHosted || !canManageBilling"
/>
</div>
<div class="form-group">
<label for="businessName">{{ "businessName" | i18n }}</label>
<input
id="businessName"
class="form-control"
type="text"
name="BusinessName"
[(ngModel)]="org.businessName"
[disabled]="selfHosted || !canManageBilling"
/>
</div>
<div class="form-group">
<label for="identifier">{{ "identifier" | i18n }}</label>
<input
id="identifier"
class="form-control"
type="text"
name="Identifier"
[(ngModel)]="org.identifier"
/>
</div>
<bit-form-field>
<bit-label>{{ "organizationName" | i18n }}</bit-label>
<input bitInput type="text" formControlName="name" />
</bit-form-field>
<bit-form-field>
<bit-label>{{ "billingEmail" | i18n }}</bit-label>
<input bitInput type="email" formControlName="billingEmail" />
</bit-form-field>
<bit-form-field>
<bit-label>{{ "businessName" | i18n }}</bit-label>
<input bitInput type="text" formControlName="businessName" />
</bit-form-field>
<bit-form-field>
<bit-label>{{ "identifier" | i18n }}</bit-label>
<input bitInput type="text" formControlName="identifier" />
</bit-form-field>
</div>
<div class="col-6">
<app-avatar data="{{ org.name }}" dynamic="true" size="75" fontSize="35"></app-avatar>
<app-avatar
[data]="formData.get('name').value"
dynamic="true"
size="75"
fontSize="35"
></app-avatar>
</div>
</div>
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
<button
type="submit"
bit-button
buttonType="primary"
class="btn-submit"
[disabled]="form.loading"
>
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "save" | i18n }}</span>
</button>
<bit-error-summary *ngIf="showErrorSummary" [formGroup]="formData"></bit-error-summary>
</form>
<ng-container *ngIf="canUseApi">
<div class="secondary-header border-0 mb-0">

View File

@@ -1,4 +1,5 @@
import { Component, ViewChild, ViewContainerRef } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { ActivatedRoute, Router } from "@angular/router";
import { ModalService } from "jslib-angular/services/modal.service";
@@ -41,10 +42,19 @@ export class AccountComponent {
org: OrganizationResponse;
formPromise: Promise<any>;
taxFormPromise: Promise<any>;
showErrorSummary = false;
private organizationId: string;
formData = this.formBuilder.group({
name: ["", [Validators.required]],
billingEmail: ["", [Validators.required, Validators.email]],
businessName: [],
identifier: [],
});
constructor(
private formBuilder: FormBuilder,
private modalService: ModalService,
private apiService: ApiService,
private i18nService: I18nService,
@@ -60,6 +70,12 @@ export class AccountComponent {
async ngOnInit() {
this.selfHosted = this.platformUtilsService.isSelfHost();
if (this.selfHosted) {
this.formData.disable();
} else {
this.formData.enable();
}
this.route.parent.parent.params.subscribe(async (params) => {
this.organizationId = params.organizationId;
this.canManageBilling = (
@@ -68,6 +84,13 @@ export class AccountComponent {
try {
this.org = await this.apiService.getOrganization(this.organizationId);
this.canUseApi = this.org.useApi;
this.formData.setValue({
name: this.org.name,
billingEmail: this.org.billingEmail,
businessName: this.org.businessName,
identifier: this.org.identifier,
});
} catch (e) {
this.logService.error(e);
}
@@ -76,12 +99,19 @@ export class AccountComponent {
}
async submit() {
this.formData.markAllAsTouched();
this.showErrorSummary = true;
if (!this.formData.valid) {
return;
}
try {
const request = new OrganizationUpdateRequest();
request.name = this.org.name;
request.businessName = this.org.businessName;
request.billingEmail = this.org.billingEmail;
request.identifier = this.org.identifier;
request.name = this.formData.get("name").value;
request.businessName = this.formData.get("businessName").value;
request.billingEmail = this.formData.get("billingEmail").value;
request.identifier = this.formData.get("identifier").value;
// Backfill pub/priv key if necessary
if (!this.org.hasPublicAndPrivateKeys) {

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

@@ -2,19 +2,19 @@ import { NgModule } from "@angular/core";
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,
PipesModule,
OrganizationManageModule,
OrganizationUserModule,
],
exports: [LooseComponentsModule, VaultFilterModule, OrganizationBadgeModule, PipesModule],
bootstrap: [],

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

@@ -1,7 +1,7 @@
<form #form (ngSubmit)="load()" [appApiAction]="formPromise" class="container" ngNativeValidate>
<div class="row justify-content-center mt-5">
<div class="col-12">
<h1 class="lead text-center mb-4">Bitwarden Send</h1>
<p class="lead text-center mb-4">Bitwarden Send</p>
</div>
<div class="col-12 text-center" *ngIf="creatorIdentifier != null">
<p>{{ "sendCreatorIdentifier" | i18n: creatorIdentifier }}</p>

View File

@@ -307,9 +307,6 @@ export class EventService {
case EventType.Organization_DisabledKeyConnector:
msg = humanReadableMsg = this.i18nService.t("disabledKeyConnector");
break;
case EventType.Organization_SponsorshipsSynced:
msg = humanReadableMsg = this.i18nService.t("sponsorshipsSynced");
break;
// Policies
case EventType.Policy_Updated: {
msg = this.i18nService.t("modifiedPolicyId", this.formatPolicyId(ev));

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

@@ -40,13 +40,11 @@ export class GeneratorComponent extends BaseGeneratorComponent {
route,
window
);
if (platformUtilsService.isSelfHost()) {
// Cannot use Firefox Relay on self hosted web vaults due to CORS issues with Firefox Relay API
this.forwardOptions.splice(
this.forwardOptions.findIndex((o) => o.value === "firefoxrelay"),
1
);
}
// Cannot use Firefox Relay on the web vault yet due to CORS issues with Firefox Relay API
this.forwardOptions.splice(
this.forwardOptions.findIndex((o) => o.value === "firefoxrelay"),
1
);
}
async history() {

View File

@@ -4163,7 +4163,7 @@
"message": "Password reset success!"
},
"resetPasswordEnrollmentWarning": {
"message": "Enrollment will allow organization administrators to change your master password"
"message": "Enrollment will allow organization administrators to change your master password. Are you sure you want to enroll?"
},
"resetPasswordPolicy": {
"message": "Master Password Reset"
@@ -4674,8 +4674,8 @@
"removeSponsorshipSuccess": {
"message": "Sponsorship Removed"
},
"ssoKeyConnectorError": {
"message": "Key Connector error: make sure Key Connector is available and working correctly."
"ssoKeyConnectorUnavailable": {
"message": "Unable to reach the Key Connector, try again later."
},
"keyConnectorUrl": {
"message": "Key Connector URL"
@@ -5041,9 +5041,6 @@
"message": "Last Sync",
"Description": "Used as a prefix to indicate the last time a sync occured. Example \"Last sync 1968-11-16 00:00:00\""
},
"sponsorshipsSynced": {
"message": "Self-hosted sponsorships synced."
},
"billingManagedByProvider": {
"message": "Managed by $PROVIDER$",
"placeholders": {
@@ -5069,5 +5066,20 @@
},
"apiAccessToken": {
"message": "API Access Token"
},
"inputRequired": {
"message": "Input is required."
},
"inputEmail": {
"message": "Input is not an email-address."
},
"fieldsNeedAttention": {
"message": "$COUNT$ field(s) above need your attention.",
"placeholders": {
"count": {
"content": "$1",
"example": "4"
}
}
}
}

View File

@@ -14,6 +14,14 @@
font-size: $font-size-base;
}
a.create-organization-link {
&:hover {
@include themify($themes) {
color: themed("iconHover") !important;
}
}
}
button {
@extend .no-btn;
}