1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[PM-5951] Migrate org invite state (#9014)

* use deep linked url for org invite instead of separate state

* remove organization invite state & fix tests

* clear login redirect for SSO JIT users since they are accepted when setting MP

* create accept org invite service and consolidate components in module

* finish switch to accept org invite service

* move logic to accept org service

* the rest of the owl

* clear org invite along with deep linked route

* pr feedback

* fix test and add error to catch null invite

* pr feedback

* clear stored invite if it doesn't match provided one
This commit is contained in:
Jake Fink
2024-05-30 12:03:17 -04:00
committed by GitHub
parent f79d1dac92
commit e29025df28
32 changed files with 797 additions and 467 deletions

View File

@@ -1,6 +1,7 @@
import { ListResponse } from "../../../models/response/list.response";
import { PolicyType } from "../../enums";
import { MasterPasswordPolicyOptions } from "../../models/domain/master-password-policy-options";
import { Policy } from "../../models/domain/policy";
import { PolicyRequest } from "../../models/request/policy.request";
import { PolicyResponse } from "../../models/response/policy.response";
@@ -13,7 +14,7 @@ export class PolicyApiServiceAbstraction {
token: string,
email: string,
organizationUserId: string,
) => Promise<ListResponse<PolicyResponse>>;
) => Promise<Policy[] | undefined>;
getMasterPasswordPolicyOptsForOrgUser: (orgId: string) => Promise<MasterPasswordPolicyOptions>;
putPolicy: (organizationId: string, type: PolicyType, request: PolicyRequest) => Promise<any>;

View File

@@ -1,5 +1,6 @@
import { PolicyId } from "../../../types/guid";
import { PolicyType } from "../../enums";
import { Policy } from "../domain/policy";
import { PolicyResponse } from "../response/policy.response";
export class PolicyData {
@@ -20,4 +21,8 @@ export class PolicyData {
this.data = response.data;
this.enabled = response.enabled;
}
static fromPolicy(policy: Policy): PolicyData {
return Object.assign(new PolicyData(), policy);
}
}

View File

@@ -47,7 +47,7 @@ export class PolicyApiService implements PolicyApiServiceAbstraction {
token: string,
email: string,
organizationUserId: string,
): Promise<ListResponse<PolicyResponse>> {
): Promise<Policy[] | undefined> {
const r = await this.apiService.send(
"GET",
"/organizations/" +
@@ -63,7 +63,7 @@ export class PolicyApiService implements PolicyApiServiceAbstraction {
false,
true,
);
return new ListResponse(r, PolicyResponse);
return Policy.fromListResponse(new ListResponse(r, PolicyResponse));
}
private async getMasterPasswordPolicyResponseForOrgUser(

View File

@@ -3,11 +3,15 @@ import { UserKey } from "../../types/key";
export abstract class PasswordResetEnrollmentServiceAbstraction {
/*
* Checks the user's enrollment status and enrolls them if required
* NOTE: Will also enroll the user in the organization if in the
* invited status
*/
abstract enrollIfRequired(organizationSsoIdentifier: string): Promise<void>;
/**
* Enroll current user in password reset
* NOTE: Will also enroll the user in the organization if in the
* invited status
* @param organizationId - Organization in which to enroll the user
* @returns Promise that resolves when the user is enrolled
* @throws Error if the action fails
@@ -16,6 +20,8 @@ export abstract class PasswordResetEnrollmentServiceAbstraction {
/**
* Enroll user in password reset
* NOTE: Will also enroll the user in the organization if in the
* invited status
* @param organizationId - Organization in which to enroll the user
* @param userId - User to enroll
* @param userKey - User's symmetric key

View File

@@ -101,8 +101,6 @@ export abstract class StateService<T extends Account = Account> {
setLastSync: (value: string, options?: StorageOptions) => Promise<void>;
getMinimizeOnCopyToClipboard: (options?: StorageOptions) => Promise<boolean>;
setMinimizeOnCopyToClipboard: (value: boolean, options?: StorageOptions) => Promise<void>;
getOrganizationInvitation: (options?: StorageOptions) => Promise<any>;
setOrganizationInvitation: (value: any, options?: StorageOptions) => Promise<void>;
getPasswordGenerationOptions: (options?: StorageOptions) => Promise<PasswordGeneratorOptions>;
setPasswordGenerationOptions: (
value: PasswordGeneratorOptions,

View File

@@ -1,5 +1,4 @@
export class GlobalState {
organizationInvitation?: any;
enableBrowserIntegration?: boolean;
enableBrowserIntegrationFingerprint?: boolean;
enableDuckDuckGoBrowserIntegration?: boolean;

View File

@@ -474,23 +474,6 @@ export class StateService<
);
}
async getOrganizationInvitation(options?: StorageOptions): Promise<any> {
return (
await this.getGlobals(this.reconcileOptions(options, await this.defaultInMemoryOptions()))
)?.organizationInvitation;
}
async setOrganizationInvitation(value: any, options?: StorageOptions): Promise<void> {
const globals = await this.getGlobals(
this.reconcileOptions(options, await this.defaultInMemoryOptions()),
);
globals.organizationInvitation = value;
await this.saveGlobals(
globals,
this.reconcileOptions(options, await this.defaultInMemoryOptions()),
);
}
async getPasswordGenerationOptions(options?: StorageOptions): Promise<PasswordGeneratorOptions> {
return (
await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()))

View File

@@ -63,6 +63,7 @@ export const TOKEN_DISK_LOCAL = new StateDefinition("tokenDiskLocal", "disk", {
export const TOKEN_MEMORY = new StateDefinition("token", "memory");
export const TWO_FACTOR_MEMORY = new StateDefinition("twoFactor", "memory");
export const USER_DECRYPTION_OPTIONS_DISK = new StateDefinition("userDecryptionOptions", "disk");
export const ORGANIZATION_INVITE_DISK = new StateDefinition("organizationInvite", "disk");
export const VAULT_TIMEOUT_SETTINGS_DISK_LOCAL = new StateDefinition(
"vaultTimeoutSettings",
"disk",