mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 10:13:31 +00:00
Merge branch 'main' into autofill/pm-8027-inline-menu-appears-within-input-fields-that-do-not-relate-to-user-login
This commit is contained in:
@@ -20,8 +20,6 @@ export class UserTypePipe implements PipeTransform {
|
||||
return this.i18nService.t("admin");
|
||||
case OrganizationUserType.User:
|
||||
return this.i18nService.t("user");
|
||||
case OrganizationUserType.Manager:
|
||||
return this.i18nService.t("manager");
|
||||
case OrganizationUserType.Custom:
|
||||
return this.i18nService.t("custom");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Observable, Subject, Subscription, firstValueFrom, throwError, timeout } from "rxjs";
|
||||
import { firstValueFrom, Observable, Subject, Subscription, throwError, timeout } from "rxjs";
|
||||
|
||||
/** Test class to enable async awaiting of observable emissions */
|
||||
export class ObservableTracker<T> {
|
||||
@@ -43,6 +43,9 @@ export class ObservableTracker<T> {
|
||||
|
||||
private trackEmissions(observable: Observable<T>): T[] {
|
||||
const emissions: T[] = [];
|
||||
this.emissionReceived.subscribe((value) => {
|
||||
emissions.push(value);
|
||||
});
|
||||
this.subscription = observable.subscribe((value) => {
|
||||
if (value == null) {
|
||||
this.emissionReceived.next(null);
|
||||
@@ -64,9 +67,7 @@ export class ObservableTracker<T> {
|
||||
}
|
||||
}
|
||||
});
|
||||
this.emissionReceived.subscribe((value) => {
|
||||
emissions.push(value);
|
||||
});
|
||||
|
||||
return emissions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { SelectionReadOnlyRequest } from "../../../models/request/selection-read
|
||||
export class OrganizationUserInviteRequest {
|
||||
emails: string[] = [];
|
||||
type: OrganizationUserType;
|
||||
accessAll: boolean;
|
||||
accessSecretsManager: boolean;
|
||||
collections: SelectionReadOnlyRequest[] = [];
|
||||
groups: string[];
|
||||
|
||||
@@ -4,7 +4,6 @@ import { SelectionReadOnlyRequest } from "../../../models/request/selection-read
|
||||
|
||||
export class OrganizationUserUpdateRequest {
|
||||
type: OrganizationUserType;
|
||||
accessAll: boolean;
|
||||
accessSecretsManager: boolean;
|
||||
collections: SelectionReadOnlyRequest[] = [];
|
||||
groups: string[] = [];
|
||||
|
||||
@@ -10,11 +10,6 @@ export class OrganizationUserResponse extends BaseResponse {
|
||||
type: OrganizationUserType;
|
||||
status: OrganizationUserStatusType;
|
||||
externalId: string;
|
||||
/**
|
||||
* @deprecated
|
||||
* To be removed after Flexible Collections.
|
||||
**/
|
||||
accessAll: boolean;
|
||||
accessSecretsManager: boolean;
|
||||
permissions: PermissionsApi;
|
||||
resetPasswordEnrolled: boolean;
|
||||
@@ -30,7 +25,6 @@ export class OrganizationUserResponse extends BaseResponse {
|
||||
this.status = this.getResponseProperty("Status");
|
||||
this.permissions = new PermissionsApi(this.getResponseProperty("Permissions"));
|
||||
this.externalId = this.getResponseProperty("ExternalId");
|
||||
this.accessAll = this.getResponseProperty("AccessAll");
|
||||
this.accessSecretsManager = this.getResponseProperty("AccessSecretsManager");
|
||||
this.resetPasswordEnrolled = this.getResponseProperty("ResetPasswordEnrolled");
|
||||
this.hasMasterPassword = this.getResponseProperty("HasMasterPassword");
|
||||
|
||||
@@ -7,7 +7,7 @@ import { OrganizationData } from "../../models/data/organization.data";
|
||||
import { Organization } from "../../models/domain/organization";
|
||||
|
||||
export function canAccessVaultTab(org: Organization): boolean {
|
||||
return org.canViewAssignedCollections || org.canViewAllCollections;
|
||||
return org.canViewAllCollections;
|
||||
}
|
||||
|
||||
export function canAccessSettingsTab(org: Organization): boolean {
|
||||
@@ -77,10 +77,7 @@ export function canAccessImportExport(i18nService: I18nService) {
|
||||
export function canAccessImport(i18nService: I18nService) {
|
||||
return map<Organization[], Organization[]>((orgs) =>
|
||||
orgs
|
||||
.filter(
|
||||
(org) =>
|
||||
org.canAccessImportExport || (org.canCreateNewCollections && org.flexibleCollections),
|
||||
)
|
||||
.filter((org) => org.canAccessImportExport || org.canCreateNewCollections)
|
||||
.sort(Utils.getSortFunction(i18nService, "name")),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ describe("ORGANIZATIONS state", () => {
|
||||
permissions: undefined,
|
||||
resetPasswordEnrolled: false,
|
||||
userId: "userId",
|
||||
organizationUserId: "organizationUserId",
|
||||
hasPublicAndPrivateKeys: false,
|
||||
providerId: "providerId",
|
||||
providerName: "providerName",
|
||||
|
||||
@@ -36,6 +36,7 @@ export class OrganizationData {
|
||||
permissions: PermissionsApi;
|
||||
resetPasswordEnrolled: boolean;
|
||||
userId: string;
|
||||
organizationUserId: string;
|
||||
hasPublicAndPrivateKeys: boolean;
|
||||
providerId: string;
|
||||
providerName: string;
|
||||
@@ -96,6 +97,7 @@ export class OrganizationData {
|
||||
this.permissions = response.permissions;
|
||||
this.resetPasswordEnrolled = response.resetPasswordEnrolled;
|
||||
this.userId = response.userId;
|
||||
this.organizationUserId = response.organizationUserId;
|
||||
this.hasPublicAndPrivateKeys = response.hasPublicAndPrivateKeys;
|
||||
this.providerId = response.providerId;
|
||||
this.providerName = response.providerName;
|
||||
|
||||
@@ -43,6 +43,7 @@ export class Organization {
|
||||
permissions: PermissionsApi;
|
||||
resetPasswordEnrolled: boolean;
|
||||
userId: string;
|
||||
organizationUserId: string;
|
||||
hasPublicAndPrivateKeys: boolean;
|
||||
providerId: string;
|
||||
providerName: string;
|
||||
@@ -113,6 +114,7 @@ export class Organization {
|
||||
this.permissions = obj.permissions;
|
||||
this.resetPasswordEnrolled = obj.resetPasswordEnrolled;
|
||||
this.userId = obj.userId;
|
||||
this.organizationUserId = obj.organizationUserId;
|
||||
this.hasPublicAndPrivateKeys = obj.hasPublicAndPrivateKeys;
|
||||
this.providerId = obj.providerId;
|
||||
this.providerName = obj.providerName;
|
||||
@@ -140,16 +142,6 @@ export class Organization {
|
||||
return this.enabled && this.status === OrganizationUserStatusType.Confirmed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a user has Manager permissions or greater
|
||||
*
|
||||
* @deprecated
|
||||
* This is deprecated with the introduction of Flexible Collections.
|
||||
*/
|
||||
get isManager() {
|
||||
return this.type === OrganizationUserType.Manager || this.isAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a user has Admin permissions or greater
|
||||
*/
|
||||
@@ -177,19 +169,13 @@ export class Organization {
|
||||
}
|
||||
|
||||
get canCreateNewCollections() {
|
||||
if (this.flexibleCollections) {
|
||||
return (
|
||||
!this.limitCollectionCreationDeletion ||
|
||||
this.isAdmin ||
|
||||
this.permissions.createNewCollections
|
||||
);
|
||||
}
|
||||
|
||||
return this.isManager || this.permissions.createNewCollections;
|
||||
return (
|
||||
!this.limitCollectionCreationDeletion || this.isAdmin || this.permissions.createNewCollections
|
||||
);
|
||||
}
|
||||
|
||||
canEditAnyCollection(flexibleCollectionsV1Enabled: boolean) {
|
||||
if (!this.flexibleCollections || !flexibleCollectionsV1Enabled) {
|
||||
if (!flexibleCollectionsV1Enabled) {
|
||||
// Pre-Flexible Collections v1 logic
|
||||
return this.isAdmin || this.permissions.editAnyCollection;
|
||||
}
|
||||
@@ -219,8 +205,8 @@ export class Organization {
|
||||
flexibleCollectionsV1Enabled: boolean,
|
||||
restrictProviderAccessFlagEnabled: boolean,
|
||||
) {
|
||||
// Before Flexible Collections, any admin or anyone with editAnyCollection permission could edit all ciphers
|
||||
if (!this.flexibleCollections || !flexibleCollectionsV1Enabled || !this.flexibleCollections) {
|
||||
// Before Flexible Collections V1, any admin or anyone with editAnyCollection permission could edit all ciphers
|
||||
if (!flexibleCollectionsV1Enabled) {
|
||||
return this.isAdmin || this.permissions.editAnyCollection;
|
||||
}
|
||||
|
||||
@@ -267,33 +253,6 @@ export class Organization {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* This is deprecated with the introduction of Flexible Collections.
|
||||
* This will always return false if FlexibleCollections flag is on.
|
||||
*/
|
||||
get canEditAssignedCollections() {
|
||||
return this.isManager || this.permissions.editAssignedCollections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* This is deprecated with the introduction of Flexible Collections.
|
||||
* This will always return false if FlexibleCollections flag is on.
|
||||
*/
|
||||
get canDeleteAssignedCollections() {
|
||||
return this.isManager || this.permissions.deleteAssignedCollections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* This is deprecated with the introduction of Flexible Collections.
|
||||
* This will always return false if FlexibleCollections flag is on.
|
||||
*/
|
||||
get canViewAssignedCollections() {
|
||||
return this.canDeleteAssignedCollections || this.canEditAssignedCollections;
|
||||
}
|
||||
|
||||
get canManageGroups() {
|
||||
return (this.isAdmin || this.permissions.manageGroups) && this.useGroups;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ export class ProfileOrganizationResponse extends BaseResponse {
|
||||
permissions: PermissionsApi;
|
||||
resetPasswordEnrolled: boolean;
|
||||
userId: string;
|
||||
organizationUserId: string;
|
||||
providerId: string;
|
||||
providerName: string;
|
||||
providerType?: ProviderType;
|
||||
@@ -86,6 +87,7 @@ export class ProfileOrganizationResponse extends BaseResponse {
|
||||
this.permissions = new PermissionsApi(this.getResponseProperty("permissions"));
|
||||
this.resetPasswordEnrolled = this.getResponseProperty("ResetPasswordEnrolled");
|
||||
this.userId = this.getResponseProperty("UserId");
|
||||
this.organizationUserId = this.getResponseProperty("OrganizationUserId");
|
||||
this.providerId = this.getResponseProperty("ProviderId");
|
||||
this.providerName = this.getResponseProperty("ProviderName");
|
||||
this.providerType = this.getResponseProperty("ProviderType");
|
||||
|
||||
@@ -49,15 +49,11 @@ export class CollectionView implements View, ITreeNodeObject {
|
||||
);
|
||||
}
|
||||
|
||||
if (org?.flexibleCollections) {
|
||||
return (
|
||||
org?.canEditAllCiphers(v1FlexibleCollections, restrictProviderAccess) ||
|
||||
this.manage ||
|
||||
(this.assigned && !this.readOnly)
|
||||
);
|
||||
}
|
||||
|
||||
return org?.canEditAnyCollection(false) || (org?.canEditAssignedCollections && this.assigned);
|
||||
return (
|
||||
org?.canEditAllCiphers(v1FlexibleCollections, restrictProviderAccess) ||
|
||||
this.manage ||
|
||||
(this.assigned && !this.readOnly)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -256,17 +256,14 @@ export class ImportComponent implements OnInit, OnDestroy {
|
||||
if (!this._importBlockedByPolicy) {
|
||||
this.formGroup.controls.targetSelector.enable();
|
||||
}
|
||||
const flexCollectionEnabled =
|
||||
organizations.find((x) => x.id == this.organizationId)?.flexibleCollections ?? false;
|
||||
|
||||
if (value) {
|
||||
this.collections$ = Utils.asyncToObservable(() =>
|
||||
this.collectionService
|
||||
.getAllDecrypted()
|
||||
.then((decryptedCollections) =>
|
||||
decryptedCollections
|
||||
.filter(
|
||||
(c2) => c2.organizationId === value && (!flexCollectionEnabled || c2.manage),
|
||||
)
|
||||
.filter((c2) => c2.organizationId === value && c2.manage)
|
||||
.sort(Utils.getSortFunction(this.i18nService, "name")),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -167,11 +167,7 @@ export class ExportComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
this.organizations$ = this.organizationService.memberOrganizations$.pipe(
|
||||
map((orgs) =>
|
||||
orgs
|
||||
.filter((org) => org.flexibleCollections)
|
||||
.sort(Utils.getSortFunction(this.i18nService, "name")),
|
||||
),
|
||||
map((orgs) => orgs.sort(Utils.getSortFunction(this.i18nService, "name"))),
|
||||
);
|
||||
|
||||
this.exportForm.controls.vaultSelector.valueChanges
|
||||
|
||||
Reference in New Issue
Block a user