1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-09 21:20:27 +00:00

Merge branch 'main' into ps/PM-8297-improve-updater

This commit is contained in:
Daniel García
2025-05-13 19:41:30 +02:00
committed by GitHub
197 changed files with 772 additions and 60 deletions

View File

@@ -5258,6 +5258,9 @@
"secureDevicesBody": {
"message": "Save unlimited passwords across unlimited devices with Bitwarden mobile, browser, and desktop apps."
},
"nudgeBadgeAria": {
"message": "1 notification"
},
"emptyVaultNudgeTitle": {
"message": "Import existing passwords"
},
@@ -5321,5 +5324,8 @@
"message": "Learn more about SSH agent",
"description": "Two part message",
"example": "Store your keys and connect with the SSH agent for fast, encrypted authentication. Learn more about SSH agent"
},
"noPermissionsViewPage": {
"message": "You do not have permissions to view this page. Try logging in with a different account."
}
}

View File

@@ -21,6 +21,8 @@ export const RedirectFocusDirection = {
Next: "next",
} as const;
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum InlineMenuFillType {
AccountCreationUsername = 5,
PasswordGeneration = 6,

View File

@@ -5,6 +5,8 @@ import {
AssertCredentialResult,
} from "@bitwarden/common/platform/abstractions/fido2/fido2-client.service.abstraction";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum MessageType {
CredentialCreationRequest,
CredentialCreationResponse,

View File

@@ -26,6 +26,8 @@ import { PopOutComponent } from "../../../platform/popup/components/pop-out.comp
import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component";
import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum SendState {
Empty,
NoResults,

View File

@@ -23,6 +23,7 @@
*ngIf="!isBrowserAutofillSettingOverridden && (showAutofillBadge$ | async)"
bitBadge
variant="notification"
[attr.aria-label]="'nudgeBadgeAria' | i18n"
>1</span
>
</div>
@@ -53,6 +54,7 @@
*ngIf="!(showVaultBadge$ | async)?.hasBadgeDismissed"
bitBadge
variant="notification"
[attr.aria-label]="'nudgeBadgeAria' | i18n"
>1</span
>
</div>
@@ -83,6 +85,7 @@
*ngIf="(downloadBitwardenNudgeStatus$ | async)?.hasBadgeDismissed === false"
bitBadge
variant="notification"
[attr.aria-label]="'nudgeBadgeAria' | i18n"
>1
</span>
</div>

View File

@@ -1,6 +1,6 @@
import { inject } from "@angular/core";
import { CanActivateFn } from "@angular/router";
import { switchMap, tap } from "rxjs";
import { CanActivateFn, Router } from "@angular/router";
import { map, switchMap } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -13,18 +13,22 @@ export const canAccessAtRiskPasswords: CanActivateFn = () => {
const taskService = inject(TaskService);
const toastService = inject(ToastService);
const i18nService = inject(I18nService);
const router = inject(Router);
return accountService.activeAccount$.pipe(
filterOutNullish(),
switchMap((user) => taskService.tasksEnabled$(user.id)),
tap((tasksEnabled) => {
map((tasksEnabled) => {
if (!tasksEnabled) {
toastService.showToast({
variant: "error",
title: "",
message: i18nService.t("accessDenied"),
message: i18nService.t("noPermissionsViewPage"),
});
return router.createUrlTree(["/tabs/vault"]);
}
return true;
}),
);
};

View File

@@ -10,6 +10,8 @@ import {
import { I18nPipe } from "@bitwarden/ui-common";
import { DarkImageSourceDirective, VaultCarouselModule } from "@bitwarden/vault";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum AtRiskCarouselDialogResult {
Dismissed = "dismissed",
}

View File

@@ -30,6 +30,8 @@ export interface GeneratorDialogResult {
generatedValue?: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum GeneratorDialogAction {
Selected = "selected",
Canceled = "canceled",

View File

@@ -55,6 +55,8 @@ import { VaultPageService } from "./vault-page.service";
import { AutofillVaultListItemsComponent, VaultListItemsContainerComponent } from ".";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
enum VaultState {
Empty,
NoResults,

View File

@@ -71,6 +71,7 @@
"browser-hrtime": "1.1.8",
"chalk": "4.1.2",
"commander": "11.1.0",
"core-js": "3.40.0",
"form-data": "4.0.1",
"https-proxy-agent": "7.0.6",
"inquirer": "8.2.6",

View File

@@ -106,6 +106,8 @@ export class LoginCommand {
return Response.badRequest("client_secret is required.");
}
} else if (options.sso != null && this.canInteract) {
// If the optional Org SSO Identifier isn't provided, the option value is `true`.
const orgSsoIdentifier = options.sso === true ? null : options.sso;
const passwordOptions: any = {
type: "password",
length: 64,
@@ -119,7 +121,7 @@ export class LoginCommand {
const codeVerifierHash = await this.cryptoFunctionService.hash(ssoCodeVerifier, "sha256");
const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash);
try {
const ssoParams = await this.openSsoPrompt(codeChallenge, state);
const ssoParams = await this.openSsoPrompt(codeChallenge, state, orgSsoIdentifier);
ssoCode = ssoParams.ssoCode;
orgIdentifier = ssoParams.orgIdentifier;
} catch {
@@ -664,6 +666,7 @@ export class LoginCommand {
private async openSsoPrompt(
codeChallenge: string,
state: string,
orgSsoIdentifier: string,
): Promise<{ ssoCode: string; orgIdentifier: string }> {
const env = await firstValueFrom(this.environmentService.environment$);
@@ -712,6 +715,8 @@ export class LoginCommand {
this.ssoRedirectUri,
state,
codeChallenge,
null,
orgSsoIdentifier,
);
this.platformUtilsService.launchUri(webAppSsoUrl);
});

View File

@@ -118,7 +118,10 @@ export class Program extends BaseProgram {
.description("Log into a user account.")
.option("--method <method>", "Two-step login method.")
.option("--code <code>", "Two-step login code.")
.option("--sso", "Log in with Single-Sign On.")
.option(
"--sso [identifier]",
"Log in with Single-Sign On with optional organization identifier.",
)
.option("--apikey", "Log in with an Api Key.")
.option("--passwordenv <passwordenv>", "Environment variable storing your password")
.option(

View File

@@ -15,6 +15,8 @@ const DEFAULT_MESSAGE_TIMEOUT = 10 * 1000; // 10 seconds
export type MessageHandler = (MessageCommon) => void;
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum IPCConnectionState {
Disconnected = "disconnected",
Connecting = "connecting",

View File

@@ -25,6 +25,8 @@ import { SearchBarService } from "../../layout/search/search-bar.service";
import { AddEditComponent } from "./add-edit.component";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
enum Action {
None = "",
Add = "add",

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum SshAgentPromptType {
Always = "always",
Never = "never",

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum BiometricAction {
Authenticate = "authenticate",
GetStatus = "status",

View File

@@ -31,6 +31,8 @@ export interface CredentialGeneratorDialogResult {
generatedValue?: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum CredentialGeneratorDialogAction {
Selected = "selected",
Canceled = "canceled",

View File

@@ -43,6 +43,8 @@ export interface BulkCollectionsDialogParams {
collections: CollectionView[];
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum BulkCollectionsDialogResult {
Saved = "saved",
Canceled = "canceled",

View File

@@ -132,6 +132,8 @@ import { VaultHeaderComponent } from "./vault-header/vault-header.component";
const BroadcasterSubscriptionId = "OrgVaultComponent";
const SearchTextDebounceInterval = 200;
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
enum AddAccessStatusType {
All = 0,
AddAccess = 1,

View File

@@ -58,6 +58,8 @@ import { AddEditGroupDetail } from "./../core/views/add-edit-group-detail";
/**
* Indices for the available tabs in the dialog
*/
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum GroupAddEditTabType {
Info = 0,
Members = 1,
@@ -82,6 +84,8 @@ export interface GroupAddEditDialogParams {
initialTab?: GroupAddEditTabType;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum GroupAddEditDialogResultType {
Saved = "saved",
Canceled = "canceled",

View File

@@ -64,6 +64,8 @@ import { commaSeparatedEmails } from "./validators/comma-separated-emails.valida
import { inputEmailLimitValidator } from "./validators/input-email-limit.validator";
import { orgSeatLimitReachedValidator } from "./validators/org-seat-limit-reached.validator";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum MemberDialogTab {
Role = 0,
Groups = 1,
@@ -92,6 +94,8 @@ export interface EditMemberDialogParams extends CommonMemberDialogParams {
export type MemberDialogParams = EditMemberDialogParams | AddMemberDialogParams;
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum MemberDialogResult {
Saved = "saved",
Canceled = "canceled",

View File

@@ -50,6 +50,8 @@ export type ResetPasswordDialogData = {
organizationId: string;
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ResetPasswordDialogResult {
Ok = "ok",
}

View File

@@ -112,7 +112,7 @@ export class OrganizationUserResetPasswordService
if (orgSymKey == null) {
throw new Error("No org key found");
}
const decPrivateKey = await this.encryptService.decryptToBytes(
const decPrivateKey = await this.encryptService.unwrapDecapsulationKey(
new EncString(response.encryptedPrivateKey),
orgSymKey,
);

View File

@@ -41,6 +41,8 @@ export type PolicyEditDialogData = {
organizationId: string;
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum PolicyEditDialogResult {
Saved = "saved",
UpgradePlan = "upgrade-plan",

View File

@@ -71,6 +71,8 @@ export interface DeleteOrganizationDialogParams {
requestType: "InvalidFamiliesForEnterprise" | "RegularDelete";
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum DeleteOrganizationDialogResult {
Deleted = "deleted",
Canceled = "canceled",

View File

@@ -26,6 +26,8 @@ import {
Permission,
} from "./access-selector.models";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum PermissionMode {
/**
* No permission controls or column present. No permission values are emitted.

View File

@@ -15,6 +15,8 @@ import { GroupView } from "../../../core";
/**
* Permission options that replace/correspond with manage, readOnly, and hidePassword server fields.
*/
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum CollectionPermission {
View = "view",
ViewExceptPass = "viewExceptPass",
@@ -23,6 +25,8 @@ export enum CollectionPermission {
Manage = "manage",
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum AccessItemType {
Collection,
Group,

View File

@@ -65,6 +65,8 @@ import {
} from "../access-selector/access-selector.models";
import { AccessSelectorModule } from "../access-selector/access-selector.module";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum CollectionDialogTabType {
Info = 0,
Access = 1,
@@ -76,6 +78,8 @@ export enum CollectionDialogTabType {
* @readonly
* @enum {string}
*/
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
enum ButtonType {
/** Displayed when the user has reached the maximum number of collections allowed for the organization. */
Upgrade = "upgrade",
@@ -103,6 +107,8 @@ export interface CollectionDialogResult {
collection: CollectionResponse | CollectionView;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum CollectionDialogAction {
Saved = "saved",
Canceled = "canceled",

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum WebauthnLoginCredentialPrfStatus {
Enabled = 0,
Supported = 1,

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum EmergencyAccessStatusType {
Invited = 0,
Accepted = 1,

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum EmergencyAccessType {
View = 0,
Takeover = 1,

View File

@@ -8,6 +8,8 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
import { DialogConfig, DialogRef, DIALOG_DATA, DialogService } from "@bitwarden/components";
import { KeyService } from "@bitwarden/key-management";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum EmergencyAccessConfirmDialogResult {
Confirmed = "confirmed",
}

View File

@@ -26,6 +26,8 @@ export type EmergencyAccessAddEditDialogData = {
readOnly: boolean;
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum EmergencyAccessAddEditDialogResult {
Saved = "saved",
Canceled = "canceled",

View File

@@ -24,6 +24,8 @@ import { KdfType, KdfConfigService, KeyService } from "@bitwarden/key-management
import { EmergencyAccessService } from "../../../emergency-access";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum EmergencyAccessTakeoverResultType {
Done = "done",
}

View File

@@ -19,6 +19,8 @@ import { PendingWebauthnLoginCredentialView } from "../../../core/views/pending-
import { CreatePasskeyFailedIcon } from "./create-passkey-failed.icon";
import { CreatePasskeyIcon } from "./create-passkey.icon";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum CreateCredentialDialogResult {
Success,
}

View File

@@ -51,8 +51,38 @@
<h2 class="tw-mb-3 tw-text-base tw-font-semibold">{{ "paymentType" | i18n }}</h2>
<app-payment [showAccountCredit]="false"></app-payment>
<app-manage-tax-information
(taxInformationChanged)="changedCountry()"
(taxInformationChanged)="onTaxInformationChanged()"
></app-manage-tax-information>
@if (trialLength === 0) {
@let priceLabel =
subscriptionProduct === SubscriptionProduct.PasswordManager
? "passwordManagerPlanPrice"
: "secretsManagerPlanPrice";
<div id="price" class="tw-my-4">
<div class="tw-text-muted tw-text-base">
{{ priceLabel | i18n }}: {{ getPriceFor(formGroup.value.cadence) | currency: "USD $" }}
<div>
{{ "estimatedTax" | i18n }}:
@if (fetchingTaxAmount) {
<ng-container *ngTemplateOutlet="loadingSpinner" />
} @else {
{{ taxAmount | currency: "USD $" }}
}
</div>
</div>
<hr class="tw-my-1 tw-grid tw-grid-cols-3 tw-ml-0" />
<p class="tw-text-lg">
<strong>{{ "total" | i18n }}: </strong>
@if (fetchingTaxAmount) {
<ng-container *ngTemplateOutlet="loadingSpinner" />
} @else {
{{ total | currency: "USD $" }}/{{ interval | i18n }}
}
</p>
</div>
}
</div>
<div class="tw-flex tw-space-x-2">
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
@@ -62,3 +92,12 @@
</div>
</div>
</form>
<ng-template #loadingSpinner>
<i
class="bwi bwi-spinner bwi-spin tw-text-muted"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
</ng-template>

View File

@@ -1,7 +1,16 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from "@angular/core";
import {
Component,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
ViewChild,
} from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { from, Subject, switchMap, takeUntil } from "rxjs";
import { ManageTaxInformationComponent } from "@bitwarden/angular/billing/components";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
@@ -12,7 +21,14 @@ import {
PaymentInformation,
PlanInformation,
} from "@bitwarden/common/billing/abstractions/organization-billing.service";
import { PaymentMethodType, PlanType, ProductTierType } from "@bitwarden/common/billing/enums";
import { TaxServiceAbstraction } from "@bitwarden/common/billing/abstractions/tax.service.abstraction";
import {
PaymentMethodType,
PlanType,
ProductTierType,
ProductType,
} from "@bitwarden/common/billing/enums";
import { PreviewTaxAmountForOrganizationTrialRequest } from "@bitwarden/common/billing/models/request/tax";
import { PlanResponse } from "@bitwarden/common/billing/models/response/plan.response";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@@ -34,11 +50,15 @@ export interface OrganizationCreatedEvent {
planDescription: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
enum SubscriptionCadence {
Annual,
Monthly,
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum SubscriptionProduct {
PasswordManager,
SecretsManager,
@@ -50,7 +70,7 @@ export enum SubscriptionProduct {
imports: [BillingSharedModule],
standalone: true,
})
export class TrialBillingStepComponent implements OnInit {
export class TrialBillingStepComponent implements OnInit, OnDestroy {
@ViewChild(PaymentComponent) paymentComponent: PaymentComponent;
@ViewChild(ManageTaxInformationComponent) taxInfoComponent: ManageTaxInformationComponent;
@Input() organizationInfo: OrganizationInfo;
@@ -60,6 +80,7 @@ export class TrialBillingStepComponent implements OnInit {
@Output() organizationCreated = new EventEmitter<OrganizationCreatedEvent>();
loading = true;
fetchingTaxAmount = false;
annualCadence = SubscriptionCadence.Annual;
monthlyCadence = SubscriptionCadence.Monthly;
@@ -73,6 +94,12 @@ export class TrialBillingStepComponent implements OnInit {
annualPlan?: PlanResponse;
monthlyPlan?: PlanResponse;
taxAmount = 0;
private destroy$ = new Subject<void>();
protected readonly SubscriptionProduct = SubscriptionProduct;
constructor(
private apiService: ApiService,
private i18nService: I18nService,
@@ -80,6 +107,7 @@ export class TrialBillingStepComponent implements OnInit {
private messagingService: MessagingService,
private organizationBillingService: OrganizationBillingService,
private toastService: ToastService,
private taxService: TaxServiceAbstraction,
) {}
async ngOnInit(): Promise<void> {
@@ -87,9 +115,26 @@ export class TrialBillingStepComponent implements OnInit {
this.applicablePlans = plans.data.filter(this.isApplicable);
this.annualPlan = this.findPlanFor(SubscriptionCadence.Annual);
this.monthlyPlan = this.findPlanFor(SubscriptionCadence.Monthly);
if (this.trialLength === 0) {
this.formGroup.controls.cadence.valueChanges
.pipe(
switchMap((cadence) => from(this.previewTaxAmount(cadence))),
takeUntil(this.destroy$),
)
.subscribe((taxAmount) => {
this.taxAmount = taxAmount;
});
}
this.loading = false;
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
async submit(): Promise<void> {
if (!this.taxInfoComponent.validate()) {
return;
@@ -115,7 +160,11 @@ export class TrialBillingStepComponent implements OnInit {
this.messagingService.send("organizationCreated", { organizationId });
}
protected changedCountry() {
async onTaxInformationChanged() {
if (this.trialLength === 0) {
this.taxAmount = await this.previewTaxAmount(this.formGroup.value.cadence);
}
this.paymentComponent.showBankAccount =
this.taxInfoComponent.getTaxInformation().country === "US";
if (
@@ -170,6 +219,7 @@ export class TrialBillingStepComponent implements OnInit {
const payment: PaymentInformation = {
paymentMethod,
billing: this.getBillingInformationFromTaxInfoComponent(),
skipTrial: this.trialLength === 0,
};
const response = await this.organizationBillingService.purchaseSubscription({
@@ -250,4 +300,45 @@ export class TrialBillingStepComponent implements OnInit {
const notDisabledOrLegacy = !plan.disabled && !plan.legacyYear;
return hasCorrectProductType && notDisabledOrLegacy;
}
private previewTaxAmount = async (cadence: SubscriptionCadence): Promise<number> => {
this.fetchingTaxAmount = true;
if (!this.taxInfoComponent.validate()) {
return 0;
}
const plan = this.findPlanFor(cadence);
const productType =
this.subscriptionProduct === SubscriptionProduct.PasswordManager
? ProductType.PasswordManager
: ProductType.SecretsManager;
const taxInformation = this.taxInfoComponent.getTaxInformation();
const request: PreviewTaxAmountForOrganizationTrialRequest = {
planType: plan.type,
productType,
taxInformation: {
...taxInformation,
},
};
const response = await this.taxService.previewTaxAmountForOrganizationTrial(request);
this.fetchingTaxAmount = false;
return response.taxAmount;
};
get price() {
return this.getPriceFor(this.formGroup.value.cadence);
}
get total() {
return this.price + this.taxAmount;
}
get interval() {
return this.formGroup.value.cadence === SubscriptionCadence.Annual ? "year" : "month";
}
}

View File

@@ -179,7 +179,7 @@ export class FreeBitwardenFamiliesComponent implements OnInit {
return;
}
await this.apiService.deleteRevokeSponsorship(this.organizationId);
await this.organizationSponsorshipApiService.deleteRevokeSponsorship(this.organizationId, true);
this.toastService.showToast({
variant: "success",

View File

@@ -74,11 +74,15 @@ type ChangePlanDialogParams = {
productTierType: ProductTierType;
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ChangePlanDialogResultType {
Closed = "closed",
Submitted = "submitted",
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum PlanCardState {
Selected = "selected",
NotSelected = "not_selected",

View File

@@ -7,6 +7,8 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { DialogConfig, DIALOG_DATA, DialogRef, DialogService } from "@bitwarden/components";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum DownloadLicenseDialogResult {
Cancelled = "cancelled",
Downloaded = "downloaded",

View File

@@ -27,6 +27,8 @@ import { DialogService, ToastService } from "@bitwarden/components";
import { BillingSyncKeyComponent } from "./billing-sync-key.component";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
enum LicenseOptions {
SYNC = 0,
UPLOAD = 1,

View File

@@ -109,7 +109,7 @@ export class SponsoringOrgRowComponent implements OnInit {
return;
}
await this.apiService.deleteRevokeSponsorship(this.sponsoringOrg.id);
await this.organizationSponsorshipApiService.deleteRevokeSponsorship(this.sponsoringOrg.id);
this.toastService.showToast({
variant: "success",
title: null,

View File

@@ -21,6 +21,8 @@ export interface AddCreditDialogData {
organizationId: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum AddCreditDialogResult {
Added = "added",
Cancelled = "cancelled",

View File

@@ -30,6 +30,8 @@ export interface AdjustPaymentDialogParams {
providerId?: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum AdjustPaymentDialogResultType {
Closed = "closed",
Submitted = "submitted",

View File

@@ -22,6 +22,8 @@ export interface AdjustStorageDialogParams {
organizationId?: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum AdjustStorageDialogResultType {
Submitted = "submitted",
Closed = "closed",

View File

@@ -25,6 +25,8 @@ type OrganizationOffboardingParams = {
export type OffboardingSurveyDialogParams = UserOffboardingParams | OrganizationOffboardingParams;
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum OffboardingSurveyDialogResultType {
Closed = "closed",
Submitted = "submitted",

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum UpdateLicenseDialogResult {
Updated = "updated",
Cancelled = "cancelled",

View File

@@ -7,6 +7,8 @@ import { ReportUnsecuredWebsites } from "./icons/report-unsecured-websites.icon"
import { ReportWeakPasswords } from "./icons/report-weak-passwords.icon";
import { ReportEntry } from "./shared";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ReportType {
ExposedPasswords = "exposedPasswords",
ReusedPasswords = "reusedPasswords",

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ReportVariant {
Enabled = "Enabled",
RequiresPremium = "RequiresPremium",

View File

@@ -95,6 +95,8 @@ export interface VaultItemDialogParams {
restore?: (c: CipherView) => Promise<boolean>;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum VaultItemDialogResult {
/**
* A cipher was saved (created or updated).

View File

@@ -26,6 +26,8 @@ export interface WebVaultGeneratorDialogResult {
generatedValue?: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum WebVaultGeneratorDialogAction {
Selected = "selected",
Canceled = "canceled",

View File

@@ -35,6 +35,8 @@ import { WebCipherFormGenerationService } from "../services/web-cipher-form-gene
/**
* The result of the AddEditCipherDialogV2 component.
*/
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum AddEditCipherDialogResult {
Edited = "edited",
Added = "added",

View File

@@ -29,6 +29,8 @@ export interface BulkDeleteDialogParams {
unassignedCiphers?: string[];
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum BulkDeleteDialogResult {
Deleted = "deleted",
Canceled = "canceled",

View File

@@ -23,6 +23,8 @@ export interface BulkMoveDialogParams {
cipherIds?: string[];
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum BulkMoveDialogResult {
Moved = "moved",
Canceled = "canceled",

View File

@@ -113,6 +113,8 @@ export interface FolderAddEditDialogParams {
folderId: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum FolderAddEditDialogResult {
Deleted = "deleted",
Canceled = "canceled",

View File

@@ -17,6 +17,8 @@ import { UserId } from "@bitwarden/common/types/guid";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { PBKDF2KdfConfig, KdfConfigService, KdfType } from "@bitwarden/key-management";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum VisibleVaultBanner {
KDFSettings = "kdf-settings",
OutdatedBrowser = "outdated-browser",

View File

@@ -15,6 +15,8 @@ export type VaultFilterType =
| FolderFilter
| CollectionFilter;
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum VaultFilterLabel {
OrganizationFilter = "organizationFilter",
TypeFilter = "typeFilter",

View File

@@ -54,6 +54,8 @@ export interface ViewCipherDialogParams {
disableEdit?: boolean;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ViewCipherDialogResult {
Edited = "edited",
Deleted = "deleted",

View File

@@ -7,6 +7,8 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { VaultMessages } from "@bitwarden/common/vault/enums/vault-messages.enum";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum BrowserPromptState {
Loading = "loading",
Error = "error",

View File

@@ -1,3 +1,5 @@
import "core-js/proposals/explicit-resource-management";
import { program } from "commander";
import { registerOssPrograms } from "@bitwarden/cli/register-oss-programs";

View File

@@ -149,6 +149,8 @@ export interface PasswordHealthReportApplicationsRequest {
url: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum DrawerType {
None = 0,
AppAtRiskMembers = 1,

View File

@@ -50,7 +50,7 @@ describe("RiskInsightsReportService", () => {
let testCase = testCaseResults[0];
expect(testCase).toBeTruthy();
expect(testCase.cipherMembers).toHaveLength(2);
expect(testCase.trimmedUris).toHaveLength(3);
expect(testCase.trimmedUris).toHaveLength(2);
expect(testCase.weakPasswordDetail).toBeTruthy();
expect(testCase.exposedPasswordDetail).toBeTruthy();
expect(testCase.reusedPasswordCount).toEqual(2);
@@ -69,7 +69,7 @@ describe("RiskInsightsReportService", () => {
it("should generate the raw data + uri report correctly", async () => {
const result = await firstValueFrom(service.generateRawDataUriReport$("orgId"));
expect(result).toHaveLength(9);
expect(result).toHaveLength(8);
// Two ciphers that have google.com as their uri. There should be 2 results
const googleResults = result.filter((x) => x.trimmedUri === "google.com");
@@ -88,7 +88,7 @@ describe("RiskInsightsReportService", () => {
it("should generate applications health report data correctly", async () => {
const result = await firstValueFrom(service.generateApplicationsReport$("orgId"));
expect(result).toHaveLength(6);
expect(result).toHaveLength(5);
// Two ciphers have google.com associated with them. The first cipher
// has 2 members and the second has 4. However, the 2 members in the first
@@ -132,7 +132,7 @@ describe("RiskInsightsReportService", () => {
expect(reportSummary.totalMemberCount).toEqual(7);
expect(reportSummary.totalAtRiskMemberCount).toEqual(6);
expect(reportSummary.totalApplicationCount).toEqual(6);
expect(reportSummary.totalAtRiskApplicationCount).toEqual(5);
expect(reportSummary.totalApplicationCount).toEqual(5);
expect(reportSummary.totalAtRiskApplicationCount).toEqual(4);
});
});

View File

@@ -428,7 +428,7 @@ export class RiskInsightsReportService {
const cipherUris: string[] = [];
const uris = cipher.login?.uris ?? [];
uris.map((u: { uri: string }) => {
const uri = Utils.getHostname(u.uri).replace("www.", "");
const uri = Utils.getDomain(u.uri);
if (!cipherUris.includes(uri)) {
cipherUris.push(uri);
}

View File

@@ -25,6 +25,8 @@ export type AddEditMemberDialogParams = {
};
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum AddEditMemberDialogResultType {
Closed = "closed",
Deleted = "deleted",

View File

@@ -74,7 +74,7 @@ export class WebProviderService {
const [publicKey, encryptedPrivateKey] = await this.keyService.makeKeyPair(organizationKey);
const encryptedCollectionName = await this.encryptService.encrypt(
const encryptedCollectionName = await this.encryptService.encryptString(
this.i18nService.t("defaultCollection"),
organizationKey,
);

View File

@@ -18,6 +18,8 @@ export type AddExistingOrganizationDialogParams = {
provider: Provider;
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum AddExistingOrganizationDialogResultType {
Closed = "closed",
Submitted = "submitted",

View File

@@ -22,6 +22,8 @@ type CreateClientDialogParams = {
plans: PlanResponse[];
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum CreateClientDialogResultType {
Closed = "closed",
Submitted = "submitted",

View File

@@ -23,6 +23,8 @@ type ManageClientNameDialogParams = {
};
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ManageClientNameDialogResultType {
Closed = "closed",
Submitted = "submitted",

View File

@@ -18,6 +18,8 @@ type ManageClientSubscriptionDialogParams = {
provider: Provider;
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ManageClientSubscriptionDialogResultType {
Closed = "closed",
Submitted = "submitted",

View File

@@ -37,6 +37,8 @@ import { PasswordHealthMembersURIComponent } from "./password-health-members-uri
import { PasswordHealthMembersComponent } from "./password-health-members.component";
import { PasswordHealthComponent } from "./password-health.component";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum RiskInsightsTabType {
AllApps = 0,
CriticalApps = 1,

View File

@@ -11,6 +11,8 @@ import { DialogRef, DIALOG_DATA, BitValidators, ToastService } from "@bitwarden/
import { ProjectView } from "../../models/view/project.view";
import { ProjectService } from "../../projects/project.service";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum OperationType {
Add,
Edit,

View File

@@ -44,11 +44,15 @@ import { SecretService } from "../secret.service";
import { SecretDeleteDialogComponent, SecretDeleteOperation } from "./secret-delete.component";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum OperationType {
Add,
Edit,
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum SecretDialogTabType {
NameValuePair = 0,
People = 1,

View File

@@ -10,6 +10,8 @@ import { DialogRef, DIALOG_DATA, BitValidators, ToastService } from "@bitwarden/
import { ServiceAccountView } from "../../models/view/service-account.view";
import { ServiceAccountService } from "../service-account.service";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum OperationType {
Add,
Edit,

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ApItemEnum {
User,
Group,

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ApPermissionEnum {
CanRead = "canRead",
CanReadWrite = "canReadWrite",

View File

@@ -15,6 +15,8 @@ export interface BulkConfirmationStatus {
description: string;
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum BulkConfirmationResult {
Continue,
Cancel,

View File

@@ -73,6 +73,7 @@ export default tseslint.config(
"@angular-eslint/use-lifecycle-interface": "error",
"@angular-eslint/use-pipe-transform-interface": 0,
"@bitwarden/platform/required-using": "error",
"@bitwarden/platform/no-enums": "error",
"@typescript-eslint/explicit-member-accessibility": ["error", { accessibility: "no-public" }],
"@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled
"@typescript-eslint/no-floating-promises": "error",

View File

@@ -116,7 +116,7 @@ export class DefaultCollectionAdminService implements CollectionAdminService {
const promises = collections.map(async (c) => {
const view = new CollectionAdminView();
view.id = c.id;
view.name = await this.encryptService.decryptToUtf8(new EncString(c.name), orgKey);
view.name = await this.encryptService.decryptString(new EncString(c.name), orgKey);
view.externalId = c.externalId;
view.organizationId = c.organizationId;
@@ -146,7 +146,7 @@ export class DefaultCollectionAdminService implements CollectionAdminService {
}
const collection = new CollectionRequest();
collection.externalId = model.externalId;
collection.name = (await this.encryptService.encrypt(model.name, key)).encryptedString;
collection.name = (await this.encryptService.encryptString(model.name, key)).encryptedString;
collection.groups = model.groups.map(
(group) =>
new SelectionReadOnlyRequest(group.id, group.readOnly, group.hidePasswords, group.manage),

View File

@@ -120,9 +120,12 @@ const mockStateProvider = () => {
const mockCryptoService = () => {
const keyService = mock<KeyService>();
const encryptService = mock<EncryptService>();
encryptService.decryptToUtf8
encryptService.decryptString
.calledWith(expect.any(EncString), expect.anything())
.mockResolvedValue("DECRYPTED_STRING");
encryptService.decryptToUtf8
.calledWith(expect.any(EncString), expect.anything(), expect.anything())
.mockResolvedValue("DECRYPTED_STRING");
(window as any).bitwardenContainerService = new ContainerService(keyService, encryptService);

View File

@@ -113,7 +113,7 @@ export class DefaultCollectionService implements CollectionService {
collection.organizationId = model.organizationId;
collection.readOnly = model.readOnly;
collection.externalId = model.externalId;
collection.name = await this.encryptService.encrypt(model.name, key);
collection.name = await this.encryptService.encryptString(model.name, key);
return collection;
}

View File

@@ -46,6 +46,11 @@ describe("DefaultvNextCollectionService", () => {
keyService.orgKeys$.mockReturnValue(cryptoKeys);
// Set up mock decryption
encryptService.decryptString
.calledWith(expect.any(EncString), expect.any(SymmetricCryptoKey))
.mockImplementation((encString, key) =>
Promise.resolve(encString.data.replace("ENC_", "DEC_")),
);
encryptService.decryptToUtf8
.calledWith(expect.any(EncString), expect.any(SymmetricCryptoKey), expect.any(String))
.mockImplementation((encString, key) =>
@@ -103,6 +108,7 @@ describe("DefaultvNextCollectionService", () => {
]);
// Assert that the correct org keys were used for each encrypted string
// This should be replaced with decryptString when the platform PR (https://github.com/bitwarden/clients/pull/14544) is merged
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(
expect.objectContaining(new EncString(collection1.name)),
orgKey1,

View File

@@ -113,7 +113,7 @@ export class DefaultvNextCollectionService implements vNextCollectionService {
collection.organizationId = model.organizationId;
collection.readOnly = model.readOnly;
collection.externalId = model.externalId;
collection.name = await this.encryptService.encrypt(model.name, key);
collection.name = await this.encryptService.encryptString(model.name, key);
return collection;
}

View File

@@ -22,6 +22,8 @@ export type AddAccountCreditDialogParams = {
providerId?: string;
};
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum AddAccountCreditDialogResultType {
Closed = "closed",
Submitted = "submitted",

View File

@@ -1079,7 +1079,7 @@ const safeProviders: SafeProvider[] = [
safeProvider({
provide: OrganizationSponsorshipApiServiceAbstraction,
useClass: OrganizationSponsorshipApiService,
deps: [ApiServiceAbstraction],
deps: [ApiServiceAbstraction, PlatformUtilsServiceAbstraction],
}),
safeProvider({
provide: OrganizationBillingApiServiceAbstraction,

View File

@@ -36,6 +36,8 @@ import { SendService } from "@bitwarden/common/tools/send/services/send.service.
import { DialogService, ToastService } from "@bitwarden/components";
// Value = hours
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
enum DatePreset {
OneHour = 1,
OneDay = 24,

View File

@@ -36,6 +36,8 @@ import { PasswordInputResult } from "./password-input-result";
/**
* Determines which form input elements will be displayed in the UI.
*/
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum InputPasswordFlow {
/**
* - Input: New password

View File

@@ -41,6 +41,8 @@ import { AnonLayoutWrapperDataService } from "../anon-layout/anon-layout-wrapper
import { LoginDecryptionOptionsService } from "./login-decryption-options.service";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
enum State {
NewUser,
ExistingUserUntrustedDevice,

View File

@@ -40,6 +40,8 @@ import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legac
import { AuthRequestApiService } from "../../common/abstractions/auth-request-api.service";
import { LoginViaAuthRequestCacheService } from "../../common/services/auth-request/default-login-via-auth-request-cache.service";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
enum Flow {
StandardAuthRequest, // when user clicks "Login with device" from /login or "Approve from your other device" from /login-initiated
AdminAuthRequest, // when user clicks "Request admin approval" from /login-initiated

View File

@@ -46,6 +46,8 @@ import { LoginComponentService, PasswordPolicies } from "./login-component.servi
const BroadcasterSubscriptionId = "LoginComponent";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum LoginUiState {
EMAIL_ENTRY = "EmailEntry",
MASTER_PASSWORD_ENTRY = "MasterPasswordEntry",

View File

@@ -26,6 +26,8 @@ import { RegistrationUserAddIcon } from "../../icons";
import { RegistrationCheckEmailIcon } from "../../icons/registration-check-email.icon";
import { RegistrationEnvSelectorComponent } from "../registration-env-selector/registration-env-selector.component";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum RegistrationStartState {
USER_DATA_ENTRY = "UserDataEntry",
CHECK_EMAIL = "CheckEmail",

View File

@@ -155,7 +155,14 @@ export class SsoComponent implements OnInit {
return;
}
// Detect if we have landed here but only have an SSO identifier in the URL.
// Detect if we are on the first portion of the SSO flow
// and have been sent here from another client with the info in query params.
// If so, we want to initialize the SSO flow with those values.
if (this.hasParametersFromOtherClientRedirect(qParams)) {
this.initializeFromRedirectFromOtherClient(qParams);
}
// Detect if we have landed here with an SSO identifier in the URL.
// This is used by integrations that want to "short-circuit" the login to send users
// directly to their IdP to simulate IdP-initiated SSO, so we submit automatically.
if (qParams.identifier != null) {
@@ -165,13 +172,6 @@ export class SsoComponent implements OnInit {
return;
}
// Detect if we are on the first portion of the SSO flow
// and have been sent here from another client with the info in query params.
// If so, we want to initialize the SSO flow with those values.
if (this.hasParametersFromOtherClientRedirect(qParams)) {
this.initializeFromRedirectFromOtherClient(qParams);
}
// Try to determine the identifier using claimed domain or local state
// persisted from the user's last login attempt.
await this.initializeIdentifierFromEmailOrStorage();

View File

@@ -1,10 +1,14 @@
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum LegacyKeyMigrationAction {
PREVENT_LOGIN_AND_SHOW_REQUIRE_MIGRATION_WARNING,
NAVIGATE_TO_MIGRATION_COMPONENT,
}
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum DuoLaunchAction {
DIRECT_LAUNCH,
SINGLE_ACTION_POPOUT,

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ActiveClientVerificationOption {
MasterPassword = "masterPassword",
Pin = "pin",

View File

@@ -1,5 +1,7 @@
import { AbstractControl, FormGroup, ValidationErrors, ValidatorFn } from "@angular/forms";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum ValidationGoal {
InputsShouldMatch,
InputsShouldNotMatch,

View File

@@ -92,4 +92,27 @@ describe("SsoUrlService", () => {
);
expect(result).toBe(expectedUrl);
});
it("should build CLI SSO URL with Org SSO Identifier correctly", () => {
const baseUrl = "https://web-vault.bitwarden.com";
const clientType = ClientType.Cli;
const redirectUri = "https://localhost:1000";
const state = "abc123";
const codeChallenge = "xyz789";
const email = "test@bitwarden.com";
const orgSsoIdentifier = "test-org";
const expectedUrl = `${baseUrl}/#/sso?clientId=cli&redirectUri=${encodeURIComponent(redirectUri)}&state=${state}&codeChallenge=${codeChallenge}&email=${encodeURIComponent(email)}&identifier=${encodeURIComponent(orgSsoIdentifier)}`;
const result = service.buildSsoUrl(
baseUrl,
clientType,
redirectUri,
state,
codeChallenge,
email,
orgSsoIdentifier,
);
expect(result).toBe(expectedUrl);
});
});

View File

@@ -11,6 +11,7 @@ export class SsoUrlService {
* @param state A state value that will be peristed through the SSO flow
* @param codeChallenge A challenge value that will be used to verify the SSO code after authentication
* @param email The optional email adddress of the user initiating SSO, which will be used to look up the org SSO identifier
* @param orgSsoIdentifier The optional SSO identifier of the org that is initiating SSO
* @returns The URL for redirecting users to the web app SSO component
*/
buildSsoUrl(
@@ -20,6 +21,7 @@ export class SsoUrlService {
state: string,
codeChallenge: string,
email?: string,
orgSsoIdentifier?: string,
): string {
let url =
webAppUrl +
@@ -36,6 +38,10 @@ export class SsoUrlService {
url += "&email=" + encodeURIComponent(email);
}
if (orgSsoIdentifier) {
url += "&identifier=" + encodeURIComponent(orgSsoIdentifier);
}
return url;
}
}

View File

@@ -475,7 +475,6 @@ export abstract class ApiService {
getSponsorshipSyncStatus: (
sponsoredOrgId: string,
) => Promise<OrganizationSponsorshipSyncStatusResponse>;
deleteRevokeSponsorship: (sponsoringOrganizationId: string) => Promise<void>;
deleteRemoveSponsorship: (sponsoringOrgId: string) => Promise<void>;
postPreValidateSponsorshipToken: (
sponsorshipToken: string,

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum OrganizationApiKeyType {
Default = 0,
BillingSync = 1,

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum OrganizationConnectionType {
CloudBillingSync = 1,
Scim = 2,

View File

@@ -1,3 +1,5 @@
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum OrganizationUserStatusType {
Invited = 0,
Accepted = 1,

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