diff --git a/apps/cli/src/admin-console/models/request/organization-collection.request.ts b/apps/cli/src/admin-console/models/request/organization-collection.request.ts index 7546d11609..1bb7a24ce7 100644 --- a/apps/cli/src/admin-console/models/request/organization-collection.request.ts +++ b/apps/cli/src/admin-console/models/request/organization-collection.request.ts @@ -9,8 +9,10 @@ export class OrganizationCollectionRequest extends CollectionExport { req.name = "Collection name"; req.externalId = null; req.groups = [SelectionReadOnly.template(), SelectionReadOnly.template()]; + req.users = [SelectionReadOnly.template(), SelectionReadOnly.template()]; return req; } groups: SelectionReadOnly[]; + users: SelectionReadOnly[]; } diff --git a/apps/cli/src/commands/edit.command.ts b/apps/cli/src/commands/edit.command.ts index e64ff8b551..75cd241207 100644 --- a/apps/cli/src/commands/edit.command.ts +++ b/apps/cli/src/commands/edit.command.ts @@ -170,10 +170,17 @@ export class EditCommand { : req.groups.map( (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(); request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString; request.externalId = req.externalId; request.groups = groups; + request.users = users; const response = await this.apiService.putCollection(req.organizationId, id, request); const view = CollectionExport.toView(req); view.id = response.id; diff --git a/apps/cli/src/commands/serve.command.ts b/apps/cli/src/commands/serve.command.ts index 2b1e21f8ab..8949e5b71e 100644 --- a/apps/cli/src/commands/serve.command.ts +++ b/apps/cli/src/commands/serve.command.ts @@ -87,6 +87,7 @@ export class ServeCommand { this.serviceContainer.apiService, this.serviceContainer.folderApiService, this.serviceContainer.billingAccountProfileStateService, + this.serviceContainer.organizationService, ); this.editCommand = new EditCommand( this.serviceContainer.cipherService, diff --git a/apps/cli/src/vault.program.ts b/apps/cli/src/vault.program.ts index c8e0701845..04ca47ac1e 100644 --- a/apps/cli/src/vault.program.ts +++ b/apps/cli/src/vault.program.ts @@ -226,6 +226,7 @@ export class VaultProgram extends BaseProgram { this.serviceContainer.apiService, this.serviceContainer.folderApiService, this.serviceContainer.billingAccountProfileStateService, + this.serviceContainer.organizationService, ); const response = await command.run(object, encodedJson, cmd); this.processResponse(response); diff --git a/apps/cli/src/vault/create.command.ts b/apps/cli/src/vault/create.command.ts index 78ee04e73c..716c2b42bb 100644 --- a/apps/cli/src/vault/create.command.ts +++ b/apps/cli/src/vault/create.command.ts @@ -4,6 +4,7 @@ import * as path from "path"; import { firstValueFrom } from "rxjs"; 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 { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { CipherExport } from "@bitwarden/common/models/export/cipher.export"; @@ -32,6 +33,7 @@ export class CreateCommand { private apiService: ApiService, private folderApiService: FolderApiServiceAbstraction, private accountProfileService: BillingAccountProfileStateService, + private organizationService: OrganizationService, ) {} async run( @@ -183,6 +185,8 @@ export class CreateCommand { if (orgKey == null) { throw new Error("No encryption key for this organization."); } + const organization = await this.organizationService.get(req.organizationId); + const currentOrgUserId = organization.organizationUserId; const groups = req.groups == null @@ -190,10 +194,17 @@ export class CreateCommand { : req.groups.map( (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(); request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString; request.externalId = req.externalId; request.groups = groups; + request.users = users; const response = await this.apiService.postCollection(req.organizationId, request); const view = CollectionExport.toView(req); view.id = response.id; diff --git a/libs/common/src/admin-console/models/data/organization.data.spec.ts b/libs/common/src/admin-console/models/data/organization.data.spec.ts index eb65303bce..1868048390 100644 --- a/libs/common/src/admin-console/models/data/organization.data.spec.ts +++ b/libs/common/src/admin-console/models/data/organization.data.spec.ts @@ -39,6 +39,7 @@ describe("ORGANIZATIONS state", () => { permissions: undefined, resetPasswordEnrolled: false, userId: "userId", + organizationUserId: "organizationUserId", hasPublicAndPrivateKeys: false, providerId: "providerId", providerName: "providerName", diff --git a/libs/common/src/admin-console/models/data/organization.data.ts b/libs/common/src/admin-console/models/data/organization.data.ts index 02fe0d6bf2..afc6b40b93 100644 --- a/libs/common/src/admin-console/models/data/organization.data.ts +++ b/libs/common/src/admin-console/models/data/organization.data.ts @@ -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; diff --git a/libs/common/src/admin-console/models/domain/organization.ts b/libs/common/src/admin-console/models/domain/organization.ts index a4cadcd392..b68de7ac08 100644 --- a/libs/common/src/admin-console/models/domain/organization.ts +++ b/libs/common/src/admin-console/models/domain/organization.ts @@ -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; diff --git a/libs/common/src/admin-console/models/response/profile-organization.response.ts b/libs/common/src/admin-console/models/response/profile-organization.response.ts index 9092d48c77..1649bf47ba 100644 --- a/libs/common/src/admin-console/models/response/profile-organization.response.ts +++ b/libs/common/src/admin-console/models/response/profile-organization.response.ts @@ -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");