1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-26 12:25:20 +01:00

[AC-2286] [Defect] - CLI: User creating a collection through the CLI does not have access to the collection (#9409)

* Send current Org user Id on collection creation through CLI

* Run npm prettier

* Add organization services to CreateCommand creation on ServeCommand

* Refactor organization data models to include organizationUserId property

* Refactor create command to utilize the OrganizationUserId on the Organization object

* Add users to collection request in edit command

* fix: organization.data test update to correct deserialization, refs AC-2286

---------

Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com>
This commit is contained in:
Rui Tomé 2024-06-07 20:14:21 +01:00 committed by GitHub
parent 7acc13cbb9
commit eef1e511b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 29 additions and 0 deletions

View File

@ -9,8 +9,10 @@ export class OrganizationCollectionRequest extends CollectionExport {
req.name = "Collection name"; req.name = "Collection name";
req.externalId = null; req.externalId = null;
req.groups = [SelectionReadOnly.template(), SelectionReadOnly.template()]; req.groups = [SelectionReadOnly.template(), SelectionReadOnly.template()];
req.users = [SelectionReadOnly.template(), SelectionReadOnly.template()];
return req; return req;
} }
groups: SelectionReadOnly[]; groups: SelectionReadOnly[];
users: SelectionReadOnly[];
} }

View File

@ -170,10 +170,17 @@ export class EditCommand {
: req.groups.map( : req.groups.map(
(g) => new SelectionReadOnlyRequest(g.id, g.readOnly, g.hidePasswords, g.manage), (g) => new SelectionReadOnlyRequest(g.id, g.readOnly, g.hidePasswords, g.manage),
); );
const users =
req.users == null
? null
: req.users.map(
(u) => new SelectionReadOnlyRequest(u.id, u.readOnly, u.hidePasswords, u.manage),
);
const request = new CollectionRequest(); const request = new CollectionRequest();
request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString; request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString;
request.externalId = req.externalId; request.externalId = req.externalId;
request.groups = groups; request.groups = groups;
request.users = users;
const response = await this.apiService.putCollection(req.organizationId, id, request); const response = await this.apiService.putCollection(req.organizationId, id, request);
const view = CollectionExport.toView(req); const view = CollectionExport.toView(req);
view.id = response.id; view.id = response.id;

View File

@ -87,6 +87,7 @@ export class ServeCommand {
this.serviceContainer.apiService, this.serviceContainer.apiService,
this.serviceContainer.folderApiService, this.serviceContainer.folderApiService,
this.serviceContainer.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
this.serviceContainer.organizationService,
); );
this.editCommand = new EditCommand( this.editCommand = new EditCommand(
this.serviceContainer.cipherService, this.serviceContainer.cipherService,

View File

@ -226,6 +226,7 @@ export class VaultProgram extends BaseProgram {
this.serviceContainer.apiService, this.serviceContainer.apiService,
this.serviceContainer.folderApiService, this.serviceContainer.folderApiService,
this.serviceContainer.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
this.serviceContainer.organizationService,
); );
const response = await command.run(object, encodedJson, cmd); const response = await command.run(object, encodedJson, cmd);
this.processResponse(response); this.processResponse(response);

View File

@ -4,6 +4,7 @@ import * as path from "path";
import { firstValueFrom } from "rxjs"; import { firstValueFrom } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request"; import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { CipherExport } from "@bitwarden/common/models/export/cipher.export"; import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
@ -32,6 +33,7 @@ export class CreateCommand {
private apiService: ApiService, private apiService: ApiService,
private folderApiService: FolderApiServiceAbstraction, private folderApiService: FolderApiServiceAbstraction,
private accountProfileService: BillingAccountProfileStateService, private accountProfileService: BillingAccountProfileStateService,
private organizationService: OrganizationService,
) {} ) {}
async run( async run(
@ -183,6 +185,8 @@ export class CreateCommand {
if (orgKey == null) { if (orgKey == null) {
throw new Error("No encryption key for this organization."); throw new Error("No encryption key for this organization.");
} }
const organization = await this.organizationService.get(req.organizationId);
const currentOrgUserId = organization.organizationUserId;
const groups = const groups =
req.groups == null req.groups == null
@ -190,10 +194,17 @@ export class CreateCommand {
: req.groups.map( : req.groups.map(
(g) => new SelectionReadOnlyRequest(g.id, g.readOnly, g.hidePasswords, g.manage), (g) => new SelectionReadOnlyRequest(g.id, g.readOnly, g.hidePasswords, g.manage),
); );
const users =
req.users == null
? [new SelectionReadOnlyRequest(currentOrgUserId, false, false, true)]
: req.users.map(
(u) => new SelectionReadOnlyRequest(u.id, u.readOnly, u.hidePasswords, u.manage),
);
const request = new CollectionRequest(); const request = new CollectionRequest();
request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString; request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString;
request.externalId = req.externalId; request.externalId = req.externalId;
request.groups = groups; request.groups = groups;
request.users = users;
const response = await this.apiService.postCollection(req.organizationId, request); const response = await this.apiService.postCollection(req.organizationId, request);
const view = CollectionExport.toView(req); const view = CollectionExport.toView(req);
view.id = response.id; view.id = response.id;

View File

@ -39,6 +39,7 @@ describe("ORGANIZATIONS state", () => {
permissions: undefined, permissions: undefined,
resetPasswordEnrolled: false, resetPasswordEnrolled: false,
userId: "userId", userId: "userId",
organizationUserId: "organizationUserId",
hasPublicAndPrivateKeys: false, hasPublicAndPrivateKeys: false,
providerId: "providerId", providerId: "providerId",
providerName: "providerName", providerName: "providerName",

View File

@ -36,6 +36,7 @@ export class OrganizationData {
permissions: PermissionsApi; permissions: PermissionsApi;
resetPasswordEnrolled: boolean; resetPasswordEnrolled: boolean;
userId: string; userId: string;
organizationUserId: string;
hasPublicAndPrivateKeys: boolean; hasPublicAndPrivateKeys: boolean;
providerId: string; providerId: string;
providerName: string; providerName: string;
@ -96,6 +97,7 @@ export class OrganizationData {
this.permissions = response.permissions; this.permissions = response.permissions;
this.resetPasswordEnrolled = response.resetPasswordEnrolled; this.resetPasswordEnrolled = response.resetPasswordEnrolled;
this.userId = response.userId; this.userId = response.userId;
this.organizationUserId = response.organizationUserId;
this.hasPublicAndPrivateKeys = response.hasPublicAndPrivateKeys; this.hasPublicAndPrivateKeys = response.hasPublicAndPrivateKeys;
this.providerId = response.providerId; this.providerId = response.providerId;
this.providerName = response.providerName; this.providerName = response.providerName;

View File

@ -43,6 +43,7 @@ export class Organization {
permissions: PermissionsApi; permissions: PermissionsApi;
resetPasswordEnrolled: boolean; resetPasswordEnrolled: boolean;
userId: string; userId: string;
organizationUserId: string;
hasPublicAndPrivateKeys: boolean; hasPublicAndPrivateKeys: boolean;
providerId: string; providerId: string;
providerName: string; providerName: string;
@ -113,6 +114,7 @@ export class Organization {
this.permissions = obj.permissions; this.permissions = obj.permissions;
this.resetPasswordEnrolled = obj.resetPasswordEnrolled; this.resetPasswordEnrolled = obj.resetPasswordEnrolled;
this.userId = obj.userId; this.userId = obj.userId;
this.organizationUserId = obj.organizationUserId;
this.hasPublicAndPrivateKeys = obj.hasPublicAndPrivateKeys; this.hasPublicAndPrivateKeys = obj.hasPublicAndPrivateKeys;
this.providerId = obj.providerId; this.providerId = obj.providerId;
this.providerName = obj.providerName; this.providerName = obj.providerName;

View File

@ -36,6 +36,7 @@ export class ProfileOrganizationResponse extends BaseResponse {
permissions: PermissionsApi; permissions: PermissionsApi;
resetPasswordEnrolled: boolean; resetPasswordEnrolled: boolean;
userId: string; userId: string;
organizationUserId: string;
providerId: string; providerId: string;
providerName: string; providerName: string;
providerType?: ProviderType; providerType?: ProviderType;
@ -86,6 +87,7 @@ export class ProfileOrganizationResponse extends BaseResponse {
this.permissions = new PermissionsApi(this.getResponseProperty("permissions")); this.permissions = new PermissionsApi(this.getResponseProperty("permissions"));
this.resetPasswordEnrolled = this.getResponseProperty("ResetPasswordEnrolled"); this.resetPasswordEnrolled = this.getResponseProperty("ResetPasswordEnrolled");
this.userId = this.getResponseProperty("UserId"); this.userId = this.getResponseProperty("UserId");
this.organizationUserId = this.getResponseProperty("OrganizationUserId");
this.providerId = this.getResponseProperty("ProviderId"); this.providerId = this.getResponseProperty("ProviderId");
this.providerName = this.getResponseProperty("ProviderName"); this.providerName = this.getResponseProperty("ProviderName");
this.providerType = this.getResponseProperty("ProviderType"); this.providerType = this.getResponseProperty("ProviderType");