diff --git a/apps/web/package.json b/apps/web/package.json index 82c447c9b4..4ae2970707 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -3,11 +3,8 @@ "version": "2024.6.2", "scripts": { "build:oss": "webpack", - "build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js", "build:oss:watch": "webpack serve", - "build:bit:watch": "webpack serve -c ../../bitwarden_license/bit-web/webpack.config.js", "build:bit:dev": "cross-env ENV=development npm run build:bit", - "build:bit:dev:analyze": "cross-env LOGGING=false webpack -c ../../bitwarden_license/bit-web/webpack.config.js --profile --json > stats.json && npx webpack-bundle-analyzer stats.json build/", "build:bit:dev:watch": "cross-env ENV=development NODE_OPTIONS=\"--max-old-space-size=8192\" npm run build:bit:watch", "build:bit:qa": "cross-env NODE_ENV=production ENV=qa npm run build:bit", "build:bit:euprd": "cross-env NODE_ENV=production ENV=euprd npm run build:bit", diff --git a/apps/web/src/app/admin-console/organizations/create/organization-information.component.html b/apps/web/src/app/admin-console/organizations/create/organization-information.component.html index e0a8006081..789efd9264 100644 --- a/apps/web/src/app/admin-console/organizations/create/organization-information.component.html +++ b/apps/web/src/app/admin-console/organizations/create/organization-information.component.html @@ -12,7 +12,7 @@ - {{ "billingEmail" | i18n }} + {{ "email" | i18n }} diff --git a/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts b/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts index 4383656bee..eb2f6a154e 100644 --- a/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts +++ b/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.ts @@ -147,6 +147,7 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy { } canShowBillingTab(organization: Organization): boolean { + return false; // disable billing tab in Vaultwarden return canAccessBillingTab(organization); } diff --git a/apps/web/src/app/admin-console/organizations/members/people.component.ts b/apps/web/src/app/admin-console/organizations/members/people.component.ts index a47e0acd0c..06f21a5361 100644 --- a/apps/web/src/app/admin-console/organizations/members/people.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/people.component.ts @@ -182,11 +182,7 @@ export class PeopleComponent extends NewBasePeopleComponent p.organizationId === this.organization.id); this.orgResetPasswordPolicyEnabled = resetPasswordPolicy?.enabled; - const billingMetadata = await this.billingApiService.getOrganizationBillingMetadata( - this.organization.id, - ); - - this.orgIsOnSecretsManagerStandalone = billingMetadata.isOnSecretsManagerStandalone; + this.orgIsOnSecretsManagerStandalone = false; // don't get billing metadata await this.load(); diff --git a/apps/web/src/app/admin-console/organizations/organization-routing.module.ts b/apps/web/src/app/admin-console/organizations/organization-routing.module.ts index 7abee6b0d0..2e3b789b23 100644 --- a/apps/web/src/app/admin-console/organizations/organization-routing.module.ts +++ b/apps/web/src/app/admin-console/organizations/organization-routing.module.ts @@ -68,13 +68,6 @@ const routes: Routes = [ (m) => m.OrganizationReportingModule, ), }, - { - path: "billing", - loadChildren: () => - import("../../billing/organizations/organization-billing.module").then( - (m) => m.OrganizationBillingModule, - ), - }, ], }, ]; diff --git a/apps/web/src/app/admin-console/organizations/settings/account.component.html b/apps/web/src/app/admin-console/organizations/settings/account.component.html index ae27df1ce9..8a644c63e3 100644 --- a/apps/web/src/app/admin-console/organizations/settings/account.component.html +++ b/apps/web/src/app/admin-console/organizations/settings/account.component.html @@ -17,7 +17,7 @@ - {{ "billingEmail" | i18n }} + {{ "email" | i18n }} diff --git a/apps/web/src/app/admin-console/organizations/settings/account.component.ts b/apps/web/src/app/admin-console/organizations/settings/account.component.ts index 41cf9b9e8f..4d7f6426fd 100644 --- a/apps/web/src/app/admin-console/organizations/settings/account.component.ts +++ b/apps/web/src/app/admin-console/organizations/settings/account.component.ts @@ -87,7 +87,7 @@ export class AccountComponent { ) {} async ngOnInit() { - this.selfHosted = this.platformUtilsService.isSelfHost(); + this.selfHosted = false; // set to false so we can rename organizations this.route.params .pipe( @@ -169,6 +169,7 @@ export class AccountComponent { }; submitCollectionManagement = async () => { + return; // flexible collections are not supported by Vaultwarden // Early exit if self-hosted if (this.selfHosted) { return; diff --git a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts index b228a4d135..e262fa51ff 100644 --- a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts +++ b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts @@ -2,6 +2,8 @@ import { UserVerificationDialogComponent } from "@bitwarden/auth/angular"; import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service"; import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/admin-console/abstractions/organization-user/requests"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; +import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; +import { VerificationWithSecret } from "@bitwarden/common/auth/types/verification"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -26,6 +28,7 @@ export class EnrollMasterPasswordReset { i18nService: I18nService, syncService: SyncService, logService: LogService, + userVerificationService: UserVerificationService, ) { const result = await UserVerificationDialogComponent.open(dialogService, { title: "enrollAccountRecovery", @@ -33,36 +36,42 @@ export class EnrollMasterPasswordReset { text: "resetPasswordEnrollmentWarning", type: "warning", }, + verificationType: { + type: "custom", + verificationFn: async (secret: VerificationWithSecret) => { + const request = + await userVerificationService.buildRequest( + secret, + ); + request.resetPasswordKey = await resetPasswordService.buildRecoveryKey( + data.organization.id, + ); + + // Process the enrollment request, which is an endpoint that is + // gated by a server-side check of the master password hash + await organizationUserService.putOrganizationUserResetPasswordEnrollment( + data.organization.id, + data.organization.userId, + request, + ); + return true; + }, + }, }); - // Handle the result of the dialog based on user action and verification success + // User canceled enrollment if (result.userAction === "cancel") { return; } - // User confirmed the dialog so check verification success + // Enrollment failed if (!result.verificationSuccess) { - // verification failed return; } - // Verification succeeded + // Enrollment succeeded try { - // This object is missing most of the properties in the - // `OrganizationUserResetPasswordEnrollmentRequest()`, but those - // properties don't carry over to the server model anyway and are - // never used by this flow. - const request = new OrganizationUserResetPasswordEnrollmentRequest(); - request.resetPasswordKey = await resetPasswordService.buildRecoveryKey(data.organization.id); - - await organizationUserService.putOrganizationUserResetPasswordEnrollment( - data.organization.id, - data.organization.userId, - request, - ); - platformUtilsService.showToast("success", null, i18nService.t("enrollPasswordResetSuccess")); - await syncService.fullSync(true); } catch (e) { logService.error(e); diff --git a/apps/web/src/app/app.component.ts b/apps/web/src/app/app.component.ts index 254f23eeb2..133eb4c059 100644 --- a/apps/web/src/app/app.component.ts +++ b/apps/web/src/app/app.component.ts @@ -219,6 +219,10 @@ export class AppComponent implements OnDestroy, OnInit { break; } case "showToast": + if (typeof message.text === "string" && typeof crypto.subtle === "undefined") { + message.title = "This browser requires HTTPS to use the web vault"; + message.text = "Check the Vaultwarden wiki for details on how to enable it"; + } this.toastService._showToast(message); break; case "convertAccountToKeyConnector": diff --git a/apps/web/src/app/auth/emergency-access/accept/accept-emergency.component.html b/apps/web/src/app/auth/emergency-access/accept/accept-emergency.component.html index 4690a4e63a..9d297671d2 100644 --- a/apps/web/src/app/auth/emergency-access/accept/accept-emergency.component.html +++ b/apps/web/src/app/auth/emergency-access/accept/accept-emergency.component.html @@ -1,6 +1,6 @@
- +

- +

{{ "loginOrCreateNewAccount" | i18n }}

@@ -51,7 +51,7 @@
-
+

{{ "or" | i18n }}

- - diff --git a/apps/web/src/app/auth/settings/two-factor-authenticator.component.ts b/apps/web/src/app/auth/settings/two-factor-authenticator.component.ts index 88b695eb72..f9aafc450a 100644 --- a/apps/web/src/app/auth/settings/two-factor-authenticator.component.ts +++ b/apps/web/src/app/auth/settings/two-factor-authenticator.component.ts @@ -112,11 +112,11 @@ export class TwoFactorAuthenticatorComponent new window.QRious({ element: document.getElementById("qr"), value: - "otpauth://totp/Bitwarden:" + + "otpauth://totp/Vaultwarden:" + Utils.encodeRFC3986URIComponent(email) + "?secret=" + encodeURIComponent(this.key) + - "&issuer=Bitwarden", + "&issuer=Vaultwarden", size: 160, }); }, 100); diff --git a/apps/web/src/app/billing/organizations/organization-billing-history-view.component.ts b/apps/web/src/app/billing/organizations/organization-billing-history-view.component.ts index 78872aa6a9..eed953b91a 100644 --- a/apps/web/src/app/billing/organizations/organization-billing-history-view.component.ts +++ b/apps/web/src/app/billing/organizations/organization-billing-history-view.component.ts @@ -44,7 +44,7 @@ export class OrgBillingHistoryViewComponent implements OnInit, OnDestroy { return; } this.loading = true; - this.billing = await this.organizationApiService.getBilling(this.organizationId); + this.billing = null; this.loading = false; } } diff --git a/apps/web/src/app/billing/organizations/organization-plans.component.html b/apps/web/src/app/billing/organizations/organization-plans.component.html index 1bd6b99dd1..ed391eb94c 100644 --- a/apps/web/src/app/billing/organizations/organization-plans.component.html +++ b/apps/web/src/app/billing/organizations/organization-plans.component.html @@ -6,7 +6,7 @@ >
{{ "loading" | i18n }} - +

{{ "uploadLicenseFileOrg" | i18n }}

@@ -33,12 +33,7 @@
-
+ !!plan.PasswordManager); @@ -192,6 +193,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { this.plan = providerDefaultPlan.type; this.product = providerDefaultPlan.product; } + end of asking /api/plans in Vaultwarden */ if (!this.createOrganization) { this.upgradeFlowPrefillForm(); @@ -263,6 +265,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { } get selectableProducts() { + return null; // there are no products to select in Vaultwarden if (this.acceptingSponsorship) { const familyPlan = this.passwordManagerPlans.find( (plan) => plan.type === PlanType.FamiliesAnnually, @@ -294,6 +297,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { } get selectablePlans() { + return null; // no plans to select in Vaultwarden const selectedProductType = this.formGroup.controls.product.value; const result = this.passwordManagerPlans?.filter( @@ -435,6 +439,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { } get planOffersSecretsManager() { + return false; // no support for secrets manager in Vaultwarden return this.selectedSecretsManagerPlan != null; } @@ -443,6 +448,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { } changedProduct() { + return; // no choice of products in Vaultwarden const selectedPlan = this.selectablePlans[0]; this.setPlanType(selectedPlan.type); @@ -562,11 +568,8 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { const collectionCt = collection.encryptedString; const orgKeys = await this.cryptoService.makeKeyPair(orgKey[1]); - if (this.selfHosted) { - orgId = await this.createSelfHosted(key, collectionCt, orgKeys); - } else { - orgId = await this.createCloudHosted(key, collectionCt, orgKeys, orgKey[1]); - } + // always use createCloudHosted() to disable license file upload + orgId = await this.createCloudHosted(key, collectionCt, orgKeys, orgKey[1]); this.platformUtilsService.showToast( "success", @@ -659,7 +662,9 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { request.billingEmail = this.formGroup.controls.billingEmail.value; request.initiationPath = "New organization creation in-product"; request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString); + request.planType = PlanType.Free; // always select the free plan in Vaultwarden + /* there is no plan to select in Vaultwarden if (this.selectedPlan.type === PlanType.Free) { request.planType = PlanType.Free; } else { @@ -686,6 +691,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { // Secrets Manager this.buildSecretsManagerRequest(request); + end plan selection and no support for secret manager in Vaultwarden */ if (this.hasProvider) { const providerRequest = new ProviderOrganizationCreateRequest( @@ -765,6 +771,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { } private upgradeFlowPrefillForm() { + return; // Vaultwarden only supports free plan if (this.acceptingSponsorship) { this.formGroup.controls.product.setValue(ProductType.Families); this.changedProduct(); diff --git a/apps/web/src/app/core/router.service.ts b/apps/web/src/app/core/router.service.ts index c0c1ec2640..fe4422a3b0 100644 --- a/apps/web/src/app/core/router.service.ts +++ b/apps/web/src/app/core/router.service.ts @@ -45,7 +45,7 @@ export class RouterService { .subscribe((event: NavigationEnd) => { this.currentUrl = event.url; - let title = i18nService.t("bitWebVault"); + let title = "Vaultwarden Web"; if (this.currentUrl.includes("/sm/")) { title = i18nService.t("bitSecretsManager"); diff --git a/apps/web/src/app/core/web-platform-utils.service.ts b/apps/web/src/app/core/web-platform-utils.service.ts index 02c7c29e34..9fd100024a 100644 --- a/apps/web/src/app/core/web-platform-utils.service.ts +++ b/apps/web/src/app/core/web-platform-utils.service.ts @@ -133,14 +133,17 @@ export class WebPlatformUtilsService implements PlatformUtilsService { } isDev(): boolean { + return false; // treat Vaultwarden as production ready return process.env.NODE_ENV === "development"; } isSelfHost(): boolean { + return true; // treat Vaultwarden as self hosted return WebPlatformUtilsService.isSelfHost(); } static isSelfHost(): boolean { + return true; // treat Vaultwarden as self hosted return process.env.ENV.toString() === "selfhosted"; } diff --git a/apps/web/src/app/layouts/frontend-layout.component.html b/apps/web/src/app/layouts/frontend-layout.component.html index 72f0f1f1da..cea0867131 100644 --- a/apps/web/src/app/layouts/frontend-layout.component.html +++ b/apps/web/src/app/layouts/frontend-layout.component.html @@ -1,6 +1,11 @@
- - © {{ year }} Bitwarden Inc.
+ Vaultwarden Web
{{ "versionNumber" | i18n: version }} +

+
+ A modified version of the Bitwarden® Web Vault for Vaultwarden (an unofficial rewrite of the + Bitwarden® server).
+ Vaultwarden is not associated with the Bitwarden® project nor Bitwarden Inc. +
diff --git a/apps/web/src/app/layouts/header/web-header.component.html b/apps/web/src/app/layouts/header/web-header.component.html index e2b3e7910a..fda32e9257 100644 --- a/apps/web/src/app/layouts/header/web-header.component.html +++ b/apps/web/src/app/layouts/header/web-header.component.html @@ -89,7 +89,12 @@ {{ "accountSettings" | i18n }}
- + {{ "getHelp" | i18n }} diff --git a/apps/web/src/app/layouts/product-switcher/navigation-switcher/navigation-switcher.component.html b/apps/web/src/app/layouts/product-switcher/navigation-switcher/navigation-switcher.component.html index 17698367bf..e1ea9cbab4 100644 --- a/apps/web/src/app/layouts/product-switcher/navigation-switcher/navigation-switcher.component.html +++ b/apps/web/src/app/layouts/product-switcher/navigation-switcher/navigation-switcher.component.html @@ -11,7 +11,7 @@
{{ "moreFromBitwarden" | i18n }} diff --git a/apps/web/src/app/layouts/product-switcher/product-switcher-content.component.html b/apps/web/src/app/layouts/product-switcher/product-switcher-content.component.html index 62d8b6a075..ec8a14c115 100644 --- a/apps/web/src/app/layouts/product-switcher/product-switcher-content.component.html +++ b/apps/web/src/app/layouts/product-switcher/product-switcher-content.component.html @@ -30,7 +30,7 @@
{{ "moreFromBitwarden" | i18n }} diff --git a/apps/web/src/app/layouts/user-layout.component.ts b/apps/web/src/app/layouts/user-layout.component.ts index 1ce8d4d227..ca8268adcc 100644 --- a/apps/web/src/app/layouts/user-layout.component.ts +++ b/apps/web/src/app/layouts/user-layout.component.ts @@ -1,7 +1,7 @@ import { CommonModule } from "@angular/common"; import { Component, OnInit } from "@angular/core"; import { RouterModule } from "@angular/router"; -import { Observable, combineLatest, concatMap } from "rxjs"; +import { Observable, of } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; @@ -58,26 +58,7 @@ export class UserLayoutComponent implements OnInit { await this.syncService.fullSync(false); - this.hasFamilySponsorshipAvailable$ = this.organizationService.canManageSponsorships$; - - // We want to hide the subscription menu for organizations that provide premium. - // Except if the user has premium personally or has a billing history. - this.showSubscription$ = combineLatest([ - this.billingAccountProfileStateService.hasPremiumPersonally$, - this.billingAccountProfileStateService.hasPremiumFromAnyOrganization$, - ]).pipe( - concatMap(async ([hasPremiumPersonally, hasPremiumFromOrg]) => { - const isCloud = !this.platformUtilsService.isSelfHost(); - - let billing = null; - if (isCloud) { - // TODO: We should remove the need to call this! - billing = await this.apiService.getUserBillingHistory(); - } - - const cloudAndBillingHistory = isCloud && !billing?.hasNoHistory; - return hasPremiumPersonally || !hasPremiumFromOrg || cloudAndBillingHistory; - }), - ); + this.hasFamilySponsorshipAvailable$ = of(false); // disable family Sponsorships in Vaultwarden + this.showSubscription$ = of(false); // always hide subscriptions in Vaultwarden } } diff --git a/apps/web/src/app/oss-routing.module.ts b/apps/web/src/app/oss-routing.module.ts index e543a6f083..343933b043 100644 --- a/apps/web/src/app/oss-routing.module.ts +++ b/apps/web/src/app/oss-routing.module.ts @@ -236,13 +236,6 @@ const routes: Routes = [ component: DomainRulesComponent, data: { titleId: "domainRules" }, }, - { - path: "subscription", - loadChildren: () => - import("./billing/individual/individual-billing.module").then( - (m) => m.IndividualBillingModule, - ), - }, { path: "emergency-access", children: [ diff --git a/apps/web/src/app/platform/web-environment.service.ts b/apps/web/src/app/platform/web-environment.service.ts index c2eb37eea5..2b5ac93392 100644 --- a/apps/web/src/app/platform/web-environment.service.ts +++ b/apps/web/src/app/platform/web-environment.service.ts @@ -27,8 +27,17 @@ export class WebEnvironmentService extends DefaultEnvironmentService { super(stateProvider, accountService); // The web vault always uses the current location as the base url - const urls = process.env.URLS as Urls; - urls.base ??= this.win.location.origin; + // If the base URL is `https://vaultwarden.example.com/base/path/`, + // `window.location.href` should have one of the following forms: + // + // - `https://vaultwarden.example.com/base/path/` + // - `https://vaultwarden.example.com/base/path/#/some/route[?queryParam=...]` + // + // We want to get to just `https://vaultwarden.example.com/base/path`. + let baseUrl = this.win.location.href; + baseUrl = baseUrl.replace(/#.*/, ""); // Strip off `#` and everything after. + baseUrl = baseUrl.replace(/\/+$/, ""); // Trim any trailing `/` chars. + const urls = { base: baseUrl }; // Find the region const domain = Utils.getDomain(this.win.location.href); diff --git a/apps/web/src/app/tools/send/access.component.html b/apps/web/src/app/tools/send/access.component.html index 6fef7d361d..1deb1164ff 100644 --- a/apps/web/src/app/tools/send/access.component.html +++ b/apps/web/src/app/tools/send/access.component.html @@ -2,7 +2,7 @@
- +

View Send

@@ -66,19 +66,6 @@

{{ "sendAccessTaglineProductDesc" | i18n }} - {{ "sendAccessTaglineLearnMore" | i18n }} - Bitwarden Send - {{ "sendAccessTaglineOr" | i18n }} - {{ - "sendAccessTaglineSignUp" | i18n - }} - {{ "sendAccessTaglineTryToday" | i18n }}

diff --git a/apps/web/src/app/tools/send/add-edit.component.html b/apps/web/src/app/tools/send/add-edit.component.html index 3225b61350..2a192514bf 100644 --- a/apps/web/src/app/tools/send/add-edit.component.html +++ b/apps/web/src/app/tools/send/add-edit.component.html @@ -227,7 +227,12 @@ {{ "password" | i18n }} {{ "newPassword" | i18n }} - + {{ "sendPasswordDesc" | i18n }} diff --git a/apps/web/src/app/vault/individual-vault/vault-filter/components/organization-options.component.ts b/apps/web/src/app/vault/individual-vault/vault-filter/components/organization-options.component.ts index 8dd63e62dd..1a1e45cc35 100644 --- a/apps/web/src/app/vault/individual-vault/vault-filter/components/organization-options.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-filter/components/organization-options.component.ts @@ -10,6 +10,7 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli import { PolicyType } from "@bitwarden/common/admin-console/enums"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Policy } from "@bitwarden/common/admin-console/models/domain/policy"; +import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -48,6 +49,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy { private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, private dialogService: DialogService, private resetPasswordService: OrganizationUserResetPasswordService, + private userVerificationService: UserVerificationService, ) {} async ngOnInit() { @@ -155,6 +157,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy { this.i18nService, this.syncService, this.logService, + this.userVerificationService, ); } else { // Remove reset password diff --git a/apps/web/src/index.html b/apps/web/src/index.html index c3a2c03ed9..1a326771a6 100644 --- a/apps/web/src/index.html +++ b/apps/web/src/index.html @@ -5,7 +5,7 @@ - Bitwarden Web Vault + Vaultwarden Web @@ -17,7 +17,7 @@
- +

form:nth-child(1) > div:nth-child(3) { + @extend %vw-hide; +} + +/* Hide the `This account is owned by a business` checkbox and label */ +#ownedBusiness, +label[for^="ownedBusiness"] { + @extend %vw-hide; +} + +/* Hide the radio button and label for the `Custom` org user type */ +#userTypeCustom, +label[for^="userTypeCustom"] { + @extend %vw-hide; +} + +/* Hide Business Name */ +app-org-account form div bit-form-field.tw-block:nth-child(3) { + @extend %vw-hide; +} + +/* Hide organization plans */ +app-organization-plans > form > h2.mt-5 { + @extend %vw-hide; +} + +/* Hide Device Verification form at the Two Step Login screen */ +app-security > app-two-factor-setup > form { + @extend %vw-hide; +} + +/* Replace the Bitwarden Shield at the top left with a Vaultwarden icon */ +.bwi-shield:before { + content: "" !important; + width: 32px !important; + height: 40px !important; + display: block !important; + background-image: url(../images/icon-white.png) !important; + background-repeat: no-repeat; + background-position-y: bottom; +} +/**** END Vaultwarden CHANGES ****/ diff --git a/apps/web/tailwind.config.js b/apps/web/tailwind.config.js index 08673c3f9a..db1dd55694 100644 --- a/apps/web/tailwind.config.js +++ b/apps/web/tailwind.config.js @@ -6,7 +6,6 @@ config.content = [ "../../libs/components/src/**/*.{html,ts}", "../../libs/auth/src/**/*.{html,ts}", "../../libs/angular/src/**/*.{html,ts}", - "../../bitwarden_license/bit-web/src/**/*.{html,ts}", ]; module.exports = config; diff --git a/apps/web/webpack.config.js b/apps/web/webpack.config.js index f22d98f081..a9904a2ecf 100644 --- a/apps/web/webpack.config.js +++ b/apps/web/webpack.config.js @@ -138,8 +138,6 @@ const plugins = [ { from: "./src/favicon.ico" }, { from: "./src/browserconfig.xml" }, { from: "./src/app-id.json" }, - { from: "./src/404.html" }, - { from: "./src/404", to: "404" }, { from: "./src/images", to: "images" }, { from: "./src/locales", to: "locales" }, { from: "../../node_modules/qrious/dist/qrious.min.js", to: "scripts" }, diff --git a/clients.code-workspace b/clients.code-workspace index a424f91eeb..72f7c59185 100644 --- a/clients.code-workspace +++ b/clients.code-workspace @@ -8,18 +8,10 @@ "name": "web vault", "path": "apps/web", }, - { - "name": "web vault (bit)", - "path": "bitwarden_license/bit-web", - }, { "name": "cli", "path": "apps/cli", }, - { - "name": "cli (bit)", - "path": "bitwarden_license/bit-cli", - }, { "name": "desktop", "path": "apps/desktop", @@ -32,10 +24,6 @@ "name": "libs", "path": "libs", }, - { - "name": "common (bit)", - "path": "bitwarden_license/bit-common", - }, ], "settings": { "eslint.options": { diff --git a/jest.config.js b/jest.config.js index f4e97262a3..12e11b35a3 100644 --- a/jest.config.js +++ b/jest.config.js @@ -20,9 +20,6 @@ module.exports = { "/apps/cli/jest.config.js", "/apps/desktop/jest.config.js", "/apps/web/jest.config.js", - "/bitwarden_license/bit-web/jest.config.js", - "/bitwarden_license/bit-cli/jest.config.js", - "/bitwarden_license/bit-common/jest.config.js", "/libs/admin-console/jest.config.js", "/libs/angular/jest.config.js", diff --git a/libs/angular/src/auth/components/register.component.ts b/libs/angular/src/auth/components/register.component.ts index e3197355dc..e3004ebdf7 100644 --- a/libs/angular/src/auth/components/register.component.ts +++ b/libs/angular/src/auth/components/register.component.ts @@ -110,6 +110,14 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn } async submit(showToast = true) { + if (typeof crypto.subtle === "undefined") { + this.platformUtilsService.showToast( + "error", + "This browser requires HTTPS to use the web vault", + "Check the Vaultwarden wiki for details on how to enable it", + ); + return; + } let email = this.formGroup.value.email; email = email.trim().toLowerCase(); let name = this.formGroup.value.name; diff --git a/libs/auth/src/angular/user-verification/user-verification-dialog.component.html b/libs/auth/src/angular/user-verification/user-verification-dialog.component.html index aa4d26ae61..fb3b7cf4cb 100644 --- a/libs/auth/src/angular/user-verification/user-verification-dialog.component.html +++ b/libs/auth/src/angular/user-verification/user-verification-dialog.component.html @@ -9,8 +9,8 @@ @@ -29,7 +29,7 @@ @@ -41,7 +41,7 @@ @@ -50,8 +50,8 @@ @@ -85,10 +85,12 @@ - + diff --git a/libs/auth/src/angular/user-verification/user-verification-dialog.component.ts b/libs/auth/src/angular/user-verification/user-verification-dialog.component.ts index 7b2c869e3a..f8746b5b24 100644 --- a/libs/auth/src/angular/user-verification/user-verification-dialog.component.ts +++ b/libs/auth/src/angular/user-verification/user-verification-dialog.component.ts @@ -142,6 +142,31 @@ export class UserVerificationDialogComponent { * return; * } * + * ---------------------------------------------------------- + * + * @example + * // Example 4: Custom user verification validation + * + * const result = await UserVerificationDialogComponent.open(dialogService, { + * verificationType: { + * type: "custom", + * // Pass in a function that will be used to validate the input of the + * // verification dialog, returning true when finished. + * verificationFn: async (secret: VerificationWithSecret) => { + * const request = await userVerificationService.buildRequest(secret); + * + * // ... Do something with the custom request type + * + * await someServicer.sendMyRequestThatVerfiesUserIdentity( + * // ... Some other data + * request, + * ); + * return true; + * }, + * }, + * }); + * + * // ... Evaluate the result as usual */ static async open( dialogService: DialogService, @@ -202,6 +227,18 @@ export class UserVerificationDialogComponent { } try { + if ( + typeof this.dialogOptions.verificationType === "object" && + this.dialogOptions.verificationType.type === "custom" + ) { + const success = await this.dialogOptions.verificationType.verificationFn(this.secret.value); + this.close({ + userAction: "confirm", + verificationSuccess: success, + }); + return; + } + // TODO: once we migrate all user verification scenarios to use this new implementation, // we should consider refactoring the user verification service handling of the // OTP and MP flows to not throw errors on verification failure. diff --git a/libs/auth/src/angular/user-verification/user-verification-dialog.types.ts b/libs/auth/src/angular/user-verification/user-verification-dialog.types.ts index f4637c770a..cb03f4e18f 100644 --- a/libs/auth/src/angular/user-verification/user-verification-dialog.types.ts +++ b/libs/auth/src/angular/user-verification/user-verification-dialog.types.ts @@ -1,3 +1,4 @@ +import { VerificationWithSecret } from "@bitwarden/common/auth/types/verification"; import { ButtonType } from "@bitwarden/components"; /** @@ -60,12 +61,27 @@ export type UserVerificationDialogOptions = { */ confirmButtonOptions?: UserVerificationConfirmButtonOptions; - /** - * Indicates whether the verification is only performed client-side. Includes local MP verification, PIN, and Biometrics. - * Optional. - * **Important:** Only for use on desktop and browser platforms as when there are no client verification methods, the user is instructed to set a pin (which is not supported on web) + /** The validation method used to verify the secret. + * + * Possible values: + * + * - "default": Perform the default validation operation for the determined + * secret type. This would, for example, validate master passwords + * locally but OTPs on the server. + * - "client": Only do a client-side verification with no possible server + * request. Includes local MP verification, PIN, and Biometrics. + * **Important:** This option is only for use on desktop and browser + * platforms. When there are no client verification methods the user is + * instructed to set a pin, and this is not supported on web. + * - "custom": Custom validation is done to verify the secret. This is + * passed in from callers when opening the dialog. The custom type is + * meant to provide a mechanism where users can call a secured endpoint + * that performs user verification server side. */ - clientSideOnlyVerification?: boolean; + verificationType?: + | "default" + | "client" + | { type: "custom"; verificationFn: (secret: VerificationWithSecret) => Promise }; }; /** diff --git a/libs/components/src/tw-theme.css b/libs/components/src/tw-theme.css index 00ab2ff717..0950b9d787 100644 --- a/libs/components/src/tw-theme.css +++ b/libs/components/src/tw-theme.css @@ -14,16 +14,16 @@ --color-background: 255 255 255; --color-background-alt: 251 251 251; --color-background-alt2: 23 92 219; - --color-background-alt3: 18 82 163; - --color-background-alt4: 13 60 119; + --color-background-alt3: 33 37 41; /* bg of menu panel */ + --color-background-alt4: 16 18 21; /* bg of active menu item */ /* Can only be used behind the extension refresh flag */ --color-primary-100: 200 217 249; - --color-primary-300: 103 149 232; + --color-primary-300: 108 117 125; /* hover of menu items */ /* Can only be used behind the extension refresh flag */ --color-primary-500: 23 93 220; - --color-primary-600: 23 93 220; - --color-primary-700: 18 82 163; + --color-primary-600: 18 82 163; /* color of links and buttons */ + --color-primary-700: 13 60 119; /* hover of links and buttons */ --color-secondary-100: 240 240 240; --color-secondary-300: 206 212 220; diff --git a/libs/components/tailwind.config.js b/libs/components/tailwind.config.js index 7a53c82ec5..9d0a337bd2 100644 --- a/libs/components/tailwind.config.js +++ b/libs/components/tailwind.config.js @@ -6,7 +6,6 @@ config.content = [ "libs/auth/src/**/*.{html,ts,mdx}", "apps/web/src/**/*.{html,ts,mdx}", "apps/browser/src/**/*.{html,ts,mdx}", - "bitwarden_license/bit-web/src/**/*.{html,ts,mdx}", ".storybook/preview.tsx", ]; config.safelist = [ diff --git a/tailwind.config.js b/tailwind.config.js index 50d82bf7d8..9b543ed950 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -9,7 +9,6 @@ config.content = [ "./libs/platform/src/**/*.{html,ts,mdx}", "./libs/vault/src/**/*.{html,ts,mdx}", "./apps/web/src/**/*.{html,ts,mdx}", - "./bitwarden_license/bit-web/src/**/*.{html,ts,mdx}", "./.storybook/preview.js", ]; config.safelist = [ diff --git a/tsconfig.json b/tsconfig.json index 8085b9f832..81a954ec84 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,8 +33,7 @@ "@bitwarden/send-ui": ["./libs/tools/send/send-ui/src"], "@bitwarden/node/*": ["./libs/node/src/*"], "@bitwarden/web-vault/*": ["./apps/web/src/*"], - "@bitwarden/vault": ["./libs/vault/src"], - "@bitwarden/bit-common/*": ["./bitwarden_license/bit-common/src/*"] + "@bitwarden/vault": ["./libs/vault/src"] }, "plugins": [ { @@ -43,13 +42,7 @@ ], "useDefineForClassFields": false }, - "include": [ - "apps/web/src/**/*", - "apps/browser/src/**/*", - "libs/*/src/**/*", - "bitwarden_license/bit-web/src/**/*", - "bitwarden_license/bit-common/src/**/*" - ], + "include": ["apps/web/src/**/*", "apps/browser/src/**/*", "libs/*/src/**/*"], "exclude": [ "apps/web/src/**/*.spec.ts", "apps/browser/src/**/*.spec.ts",