mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 01:03:35 +00:00
Merge branch 'main' into auth/pm-8111/browser-refresh-login-component
This commit is contained in:
@@ -3,6 +3,7 @@ import { Observable, Subject } from "rxjs";
|
||||
|
||||
import { LogoutReason } from "@bitwarden/auth/common";
|
||||
import { ClientType } from "@bitwarden/common/enums";
|
||||
import { RegionConfig } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import {
|
||||
AbstractStorageService,
|
||||
ObservableStorageService,
|
||||
@@ -58,3 +59,12 @@ export const CLIENT_TYPE = new SafeInjectionToken<ClientType>("CLIENT_TYPE");
|
||||
export const REFRESH_ACCESS_TOKEN_ERROR_CALLBACK = new SafeInjectionToken<() => void>(
|
||||
"REFRESH_ACCESS_TOKEN_ERROR_CALLBACK",
|
||||
);
|
||||
|
||||
/**
|
||||
* Injection token for injecting the NodeJS process.env additional regions into services.
|
||||
* Using an injection token allows services to be tested without needing to
|
||||
* mock the process.env.
|
||||
*/
|
||||
export const ENV_ADDITIONAL_REGIONS = new SafeInjectionToken<RegionConfig[]>(
|
||||
"ENV_ADDITIONAL_REGIONS",
|
||||
);
|
||||
|
||||
@@ -143,7 +143,10 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co
|
||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import {
|
||||
EnvironmentService,
|
||||
RegionConfig,
|
||||
} from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { FileUploadService as FileUploadServiceAbstraction } from "@bitwarden/common/platform/abstractions/file-upload/file-upload.service";
|
||||
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwarden/common/platform/abstractions/key-generation.service";
|
||||
@@ -300,6 +303,7 @@ import {
|
||||
INTRAPROCESS_MESSAGING_SUBJECT,
|
||||
CLIENT_TYPE,
|
||||
REFRESH_ACCESS_TOKEN_ERROR_CALLBACK,
|
||||
ENV_ADDITIONAL_REGIONS,
|
||||
} from "./injection-tokens";
|
||||
import { ModalService } from "./modal.service";
|
||||
|
||||
@@ -532,10 +536,14 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: CollectionService,
|
||||
deps: [CryptoServiceAbstraction, EncryptService, I18nServiceAbstraction, StateProvider],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: ENV_ADDITIONAL_REGIONS,
|
||||
useValue: process.env.ADDITIONAL_REGIONS as unknown as RegionConfig[],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: EnvironmentService,
|
||||
useClass: DefaultEnvironmentService,
|
||||
deps: [StateProvider, AccountServiceAbstraction],
|
||||
deps: [StateProvider, AccountServiceAbstraction, ENV_ADDITIONAL_REGIONS],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: InternalUserDecryptionOptionsServiceAbstraction,
|
||||
|
||||
@@ -136,6 +136,7 @@ export class DefaultEnvironmentService implements EnvironmentService {
|
||||
constructor(
|
||||
private stateProvider: StateProvider,
|
||||
private accountService: AccountService,
|
||||
private additionalRegionConfigs: RegionConfig[] = [],
|
||||
) {
|
||||
this.globalState = this.stateProvider.getGlobal(GLOBAL_ENVIRONMENT_KEY);
|
||||
this.globalCloudRegionState = this.stateProvider.getGlobal(GLOBAL_CLOUD_REGION_KEY);
|
||||
@@ -177,8 +178,7 @@ export class DefaultEnvironmentService implements EnvironmentService {
|
||||
}
|
||||
|
||||
availableRegions(): RegionConfig[] {
|
||||
const additionalRegions = (process.env.ADDITIONAL_REGIONS as unknown as RegionConfig[]) ?? [];
|
||||
return PRODUCTION_REGIONS.concat(additionalRegions);
|
||||
return PRODUCTION_REGIONS.concat(this.additionalRegionConfigs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -113,6 +113,13 @@ export abstract class CipherService implements UserKeyRotationDataProvider<Ciphe
|
||||
* @returns A promise that resolves when the collections have been saved
|
||||
*/
|
||||
saveCollectionsWithServer: (cipher: Cipher) => Promise<Cipher>;
|
||||
|
||||
/**
|
||||
* Save the collections for a cipher with the server as an admin.
|
||||
* Used for Unassigned ciphers or when the user only has admin access to the cipher (not assigned normally).
|
||||
* @param cipher
|
||||
*/
|
||||
saveCollectionsWithServerAdmin: (cipher: Cipher) => Promise<void>;
|
||||
/**
|
||||
* Bulk update collections for many ciphers with the server
|
||||
* @param orgId
|
||||
|
||||
@@ -858,6 +858,11 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
return new Cipher(updated[cipher.id as CipherId], cipher.localData);
|
||||
}
|
||||
|
||||
async saveCollectionsWithServerAdmin(cipher: Cipher): Promise<void> {
|
||||
const request = new CipherCollectionsRequest(cipher.collectionIds);
|
||||
await this.apiService.putCipherCollectionsAdmin(cipher.id, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk update collections for many ciphers with the server
|
||||
* @param orgId
|
||||
|
||||
@@ -96,6 +96,17 @@ describe("UriOptionComponent", () => {
|
||||
expect(component["uriForm"].enabled).toBe(false);
|
||||
});
|
||||
|
||||
it("should update form when `writeValue` is invoked", () => {
|
||||
expect(component["uriForm"].value).toEqual({ uri: null, matchDetection: null });
|
||||
|
||||
component.writeValue({ uri: "example.com", matchDetection: UriMatchStrategy.Exact });
|
||||
|
||||
expect(component["uriForm"].value).toEqual({
|
||||
uri: "example.com",
|
||||
matchDetection: UriMatchStrategy.Exact,
|
||||
});
|
||||
});
|
||||
|
||||
describe("match detection", () => {
|
||||
it("should hide the match detection select by default", () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -149,12 +149,12 @@ export class UriOptionComponent implements ControlValueAccessor {
|
||||
}
|
||||
|
||||
// NG_VALUE_ACCESSOR implementation
|
||||
writeValue(value: any): void {
|
||||
writeValue(value: { uri: string; matchDetection: UriMatchStrategySetting | null }): void {
|
||||
if (value) {
|
||||
this.uriForm.setValue(
|
||||
{
|
||||
uri: value.uri ?? "",
|
||||
matchDetection: value.match ?? null,
|
||||
matchDetection: value.matchDetection ?? null,
|
||||
},
|
||||
{ emitEvent: false },
|
||||
);
|
||||
|
||||
@@ -64,6 +64,15 @@ export interface CollectionAssignmentParams {
|
||||
* removed from the ciphers upon submission.
|
||||
*/
|
||||
activeCollection?: CollectionView;
|
||||
|
||||
/**
|
||||
* Flag indicating if the user is performing the action as an admin on a SINGLE cipher. When true,
|
||||
* the `/admin` endpoint will be used to update the cipher's collections. Required when updating
|
||||
* ciphers an Admin does not normally have access to or for Unassigned ciphers.
|
||||
*
|
||||
* The bulk method already handles admin actions internally.
|
||||
*/
|
||||
isSingleCipherAdmin?: boolean;
|
||||
}
|
||||
|
||||
export enum CollectionAssignmentResult {
|
||||
@@ -463,6 +472,10 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
|
||||
const { collections } = this.formGroup.getRawValue();
|
||||
cipherView.collectionIds = collections.map((i) => i.id as CollectionId);
|
||||
const cipher = await this.cipherService.encrypt(cipherView, this.activeUserId);
|
||||
await this.cipherService.saveCollectionsWithServer(cipher);
|
||||
if (this.params.isSingleCipherAdmin) {
|
||||
await this.cipherService.saveCollectionsWithServerAdmin(cipher);
|
||||
} else {
|
||||
await this.cipherService.saveCollectionsWithServer(cipher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user