1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-13 14:53:33 +00:00

[PM-12479] Updating retrieval of groups (#11800)

* Renamed group service to group api service
* Updating models in various components.
* Updating internal service name. clean up.
---------
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Matt Bishop <mbishop@bitwarden.com>
This commit is contained in:
Jared McCannon
2024-11-12 13:52:11 -06:00
committed by GitHub
parent ea2f95e226
commit e32bfce094
13 changed files with 99 additions and 52 deletions

View File

@@ -6,8 +6,10 @@ import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CoreOrganizationModule } from "../../core-organization.module"; import { CoreOrganizationModule } from "../../core-organization.module";
import { GroupDetailsView } from "../../views/group-details.view";
import { GroupView } from "../../views/group.view"; import { GroupView } from "../../views/group.view";
import { AddEditGroupDetail } from "./../../views/add-edit-group-detail";
import { GroupRequest } from "./requests/group.request"; import { GroupRequest } from "./requests/group.request";
import { OrganizationGroupBulkRequest } from "./requests/organization-group-bulk.request"; import { OrganizationGroupBulkRequest } from "./requests/organization-group-bulk.request";
import { GroupDetailsResponse, GroupResponse } from "./responses/group.response"; import { GroupDetailsResponse, GroupResponse } from "./responses/group.response";
@@ -15,13 +17,13 @@ import { GroupDetailsResponse, GroupResponse } from "./responses/group.response"
@Injectable({ @Injectable({
providedIn: "root", providedIn: "root",
}) })
export class GroupService { export class GroupApiService {
constructor( constructor(
protected apiService: ApiService, protected apiService: ApiService,
protected configService: ConfigService, protected configService: ConfigService,
) {} ) {}
async get(orgId: string, groupId: string): Promise<GroupView> { async get(orgId: string, groupId: string): Promise<GroupDetailsView> {
const r = await this.apiService.send( const r = await this.apiService.send(
"GET", "GET",
"/organizations/" + orgId + "/groups/" + groupId + "/details", "/organizations/" + orgId + "/groups/" + groupId + "/details",
@@ -30,7 +32,7 @@ export class GroupService {
true, true,
); );
return GroupView.fromResponse(new GroupDetailsResponse(r)); return GroupDetailsView.fromResponse(new GroupDetailsResponse(r));
} }
async getAll(orgId: string): Promise<GroupView[]> { async getAll(orgId: string): Promise<GroupView[]> {
@@ -44,12 +46,26 @@ export class GroupService {
const listResponse = new ListResponse(r, GroupDetailsResponse); const listResponse = new ListResponse(r, GroupDetailsResponse);
return Promise.all(listResponse.data?.map((gr) => GroupView.fromResponse(gr))) ?? []; return listResponse.data.map((gr) => GroupView.fromResponse(gr));
}
async getAllDetails(orgId: string): Promise<GroupDetailsView[]> {
const r = await this.apiService.send(
"GET",
"/organizations/" + orgId + "/groups/details",
null,
true,
true,
);
const listResponse = new ListResponse(r, GroupDetailsResponse);
return listResponse.data.map((gr) => GroupDetailsView.fromResponse(gr));
} }
} }
@Injectable({ providedIn: CoreOrganizationModule }) @Injectable({ providedIn: CoreOrganizationModule })
export class InternalGroupService extends GroupService { export class InternalGroupApiService extends GroupApiService {
constructor( constructor(
protected apiService: ApiService, protected apiService: ApiService,
protected configService: ConfigService, protected configService: ConfigService,
@@ -77,7 +93,7 @@ export class InternalGroupService extends GroupService {
); );
} }
async save(group: GroupView): Promise<GroupView> { async save(group: AddEditGroupDetail): Promise<GroupView> {
const request = new GroupRequest(); const request = new GroupRequest();
request.name = group.name; request.name = group.name;
request.users = group.members; request.users = group.members;

View File

@@ -1,2 +1,2 @@
export * from "./group/group.service"; export * from "./group/group-api.service";
export * from "./user-admin.service"; export * from "./user-admin.service";

View File

@@ -0,0 +1,10 @@
import { CollectionAccessSelectionView } from "@bitwarden/admin-console/common";
export interface AddEditGroupDetail {
id: string;
organizationId: string;
name: string;
externalId: string;
collections: CollectionAccessSelectionView[];
members: string[];
}

View File

@@ -0,0 +1,20 @@
import { CollectionAccessSelectionView } from "@bitwarden/admin-console/common";
import { View } from "@bitwarden/common/models/view/view";
import { GroupDetailsResponse } from "../services/group/responses/group.response";
export class GroupDetailsView implements View {
id: string;
organizationId: string;
name: string;
externalId: string;
collections: CollectionAccessSelectionView[] = [];
static fromResponse(response: GroupDetailsResponse): GroupDetailsView {
const view: GroupDetailsView = Object.assign(new GroupDetailsView(), response);
view.collections = response.collections.map((c) => new CollectionAccessSelectionView(c));
return view;
}
}

View File

@@ -1,23 +1,14 @@
import { CollectionAccessSelectionView } from "@bitwarden/admin-console/common";
import { View } from "@bitwarden/common/models/view/view"; import { View } from "@bitwarden/common/models/view/view";
import { GroupDetailsResponse, GroupResponse } from "../services/group/responses/group.response"; import { GroupResponse } from "../services/group/responses/group.response";
export class GroupView implements View { export class GroupView implements View {
id: string; id: string;
organizationId: string; organizationId: string;
name: string; name: string;
externalId: string; externalId: string;
collections: CollectionAccessSelectionView[] = [];
members: string[] = [];
static fromResponse(response: GroupResponse): GroupView { static fromResponse(response: GroupResponse): GroupView {
const view: GroupView = Object.assign(new GroupView(), response) as GroupView; return Object.assign(new GroupView(), response);
if (response instanceof GroupDetailsResponse && response.collections != undefined) {
view.collections = response.collections.map((c) => new CollectionAccessSelectionView(c));
}
return view;
} }
} }

View File

@@ -1,3 +1,4 @@
export * from "./group.view"; export * from "./group.view";
export * from "./group-details.view";
export * from "./organization-user.view"; export * from "./organization-user.view";
export * from "./organization-user-admin-view"; export * from "./organization-user-admin-view";

View File

@@ -30,7 +30,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
import { UserId } from "@bitwarden/common/types/guid"; import { UserId } from "@bitwarden/common/types/guid";
import { DialogService, ToastService } from "@bitwarden/components"; import { DialogService, ToastService } from "@bitwarden/components";
import { InternalGroupService as GroupService, GroupView } from "../core"; import { InternalGroupApiService as GroupService } from "../core";
import { import {
AccessItemType, AccessItemType,
AccessItemValue, AccessItemValue,
@@ -40,6 +40,8 @@ import {
PermissionMode, PermissionMode,
} from "../shared/components/access-selector"; } from "../shared/components/access-selector";
import { AddEditGroupDetail } from "./../core/views/add-edit-group-detail";
/** /**
* Indices for the available tabs in the dialog * Indices for the available tabs in the dialog
*/ */
@@ -105,7 +107,7 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
title: string; title: string;
collections: AccessItemView[] = []; collections: AccessItemView[] = [];
members: Array<AccessItemView & { userId: UserId }> = []; members: Array<AccessItemView & { userId: UserId }> = [];
group: GroupView; group: AddEditGroupDetail;
groupForm = this.formBuilder.group({ groupForm = this.formBuilder.group({
name: ["", [Validators.required, Validators.maxLength(100)]], name: ["", [Validators.required, Validators.maxLength(100)]],
@@ -149,7 +151,7 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
); );
} }
private groupDetails$: Observable<GroupView | undefined> = of(this.editMode).pipe( private groupDetails$: Observable<AddEditGroupDetail | undefined> = of(this.editMode).pipe(
concatMap((editMode) => { concatMap((editMode) => {
if (!editMode) { if (!editMode) {
return of(undefined); return of(undefined);
@@ -159,9 +161,11 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
this.groupService.get(this.organizationId, this.groupId), this.groupService.get(this.organizationId, this.groupId),
this.apiService.getGroupUsers(this.organizationId, this.groupId), this.apiService.getGroupUsers(this.organizationId, this.groupId),
]).pipe( ]).pipe(
map(([groupView, users]) => { map(([groupView, users]): AddEditGroupDetail => {
groupView.members = users; return {
return groupView; ...groupView,
members: users,
};
}), }),
catchError((e: unknown) => { catchError((e: unknown) => {
if (e instanceof ErrorResponse) { if (e instanceof ErrorResponse) {
@@ -295,14 +299,16 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
return; return;
} }
const groupView = new GroupView();
groupView.id = this.groupId;
groupView.organizationId = this.organizationId;
const formValue = this.groupForm.value; const formValue = this.groupForm.value;
groupView.name = formValue.name;
groupView.members = formValue.members?.map((m) => m.id) ?? []; const groupView: AddEditGroupDetail = {
groupView.collections = formValue.collections.map((c) => convertToSelectionView(c)); id: this.groupId,
organizationId: this.organizationId,
name: formValue.name,
members: formValue.members?.map((m) => m.id) ?? [],
collections: formValue.collections.map((c) => convertToSelectionView(c)),
externalId: formValue.externalId,
};
await this.groupService.save(groupView); await this.groupService.save(groupView);
@@ -346,7 +352,10 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
/** /**
* Maps the group's current collection access to AccessItemValues to populate the access-selector's FormControl * Maps the group's current collection access to AccessItemValues to populate the access-selector's FormControl
*/ */
function mapToAccessSelections(group: GroupView, items: AccessItemView[]): AccessItemValue[] { function mapToAccessSelections(
group: AddEditGroupDetail,
items: AccessItemView[],
): AccessItemValue[] {
return ( return (
group.collections group.collections
// The FormControl value only represents editable collection access - exclude readonly access selections // The FormControl value only represents editable collection access - exclude readonly access selections
@@ -365,7 +374,7 @@ function mapToAccessSelections(group: GroupView, items: AccessItemView[]): Acces
function mapToAccessItemViews( function mapToAccessItemViews(
collections: CollectionAdminView[], collections: CollectionAdminView[],
organization: Organization, organization: Organization,
group?: GroupView, group?: AddEditGroupDetail,
): AccessItemView[] { ): AccessItemView[] {
return ( return (
collections collections

View File

@@ -28,7 +28,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { DialogService, TableDataSource, ToastService } from "@bitwarden/components"; import { DialogService, TableDataSource, ToastService } from "@bitwarden/components";
import { InternalGroupService as GroupService, GroupView } from "../core"; import { GroupDetailsView, InternalGroupApiService as GroupService } from "../core";
import { import {
GroupAddEditDialogResultType, GroupAddEditDialogResultType,
@@ -40,7 +40,7 @@ type GroupDetailsRow = {
/** /**
* Details used for displaying group information * Details used for displaying group information
*/ */
details: GroupView; details: GroupDetailsView;
/** /**
* True if the group is selected in the table * True if the group is selected in the table
@@ -108,7 +108,7 @@ export class GroupsComponent {
), ),
// groups // groups
this.refreshGroups$.pipe( this.refreshGroups$.pipe(
switchMap(() => this.groupService.getAll(this.organizationId)), switchMap(() => this.groupService.getAllDetails(this.organizationId)),
), ),
]), ]),
), ),

View File

@@ -35,8 +35,8 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { DialogService, ToastService } from "@bitwarden/components"; import { DialogService, ToastService } from "@bitwarden/components";
import { import {
GroupService, GroupApiService,
GroupView, GroupDetailsView,
OrganizationUserAdminView, OrganizationUserAdminView,
UserAdminService, UserAdminService,
} from "../../../core"; } from "../../../core";
@@ -144,7 +144,7 @@ export class MemberDialogComponent implements OnDestroy {
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
// TODO: We should really look into consolidating naming conventions for these services // TODO: We should really look into consolidating naming conventions for these services
private collectionAdminService: CollectionAdminService, private collectionAdminService: CollectionAdminService,
private groupService: GroupService, private groupService: GroupApiService,
private userService: UserAdminService, private userService: UserAdminService,
private organizationUserApiService: OrganizationUserApiService, private organizationUserApiService: OrganizationUserApiService,
private dialogService: DialogService, private dialogService: DialogService,
@@ -171,8 +171,8 @@ export class MemberDialogComponent implements OnDestroy {
const groups$ = this.organization$.pipe( const groups$ = this.organization$.pipe(
switchMap((organization) => switchMap((organization) =>
organization.useGroups organization.useGroups
? this.groupService.getAll(this.params.organizationId) ? this.groupService.getAllDetails(this.params.organizationId)
: of([] as GroupView[]), : of([] as GroupDetailsView[]),
), ),
); );
@@ -278,7 +278,7 @@ export class MemberDialogComponent implements OnDestroy {
private loadOrganizationUser( private loadOrganizationUser(
userDetails: OrganizationUserAdminView, userDetails: OrganizationUserAdminView,
groups: GroupView[], groups: GroupDetailsView[],
collections: CollectionAdminView[], collections: CollectionAdminView[],
organization: Organization, organization: Organization,
) { ) {
@@ -635,7 +635,7 @@ function mapCollectionToAccessItemView(
collection: CollectionAdminView, collection: CollectionAdminView,
organization: Organization, organization: Organization,
accessSelection?: CollectionAccessSelectionView, accessSelection?: CollectionAccessSelectionView,
group?: GroupView, group?: GroupDetailsView,
): AccessItemView { ): AccessItemView {
return { return {
type: AccessItemType.Collection, type: AccessItemType.Collection,
@@ -648,7 +648,7 @@ function mapCollectionToAccessItemView(
}; };
} }
function mapGroupToAccessItemView(group: GroupView): AccessItemView { function mapGroupToAccessItemView(group: GroupDetailsView): AccessItemView {
return { return {
type: AccessItemType.Group, type: AccessItemType.Group,
id: group.id, id: group.id,

View File

@@ -56,7 +56,7 @@ import {
} from "../../../billing/organizations/change-plan-dialog.component"; } from "../../../billing/organizations/change-plan-dialog.component";
import { BaseMembersComponent } from "../../common/base-members.component"; import { BaseMembersComponent } from "../../common/base-members.component";
import { PeopleTableDataSource } from "../../common/people-table-data-source"; import { PeopleTableDataSource } from "../../common/people-table-data-source";
import { GroupService } from "../core"; import { GroupApiService } from "../core";
import { OrganizationUserView } from "../core/views/organization-user.view"; import { OrganizationUserView } from "../core/views/organization-user.view";
import { openEntityEventsDialog } from "../manage/entity-events.component"; import { openEntityEventsDialog } from "../manage/entity-events.component";
@@ -129,7 +129,7 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
private organizationApiService: OrganizationApiServiceAbstraction, private organizationApiService: OrganizationApiServiceAbstraction,
private organizationUserApiService: OrganizationUserApiService, private organizationUserApiService: OrganizationUserApiService,
private router: Router, private router: Router,
private groupService: GroupService, private groupService: GroupApiService,
private collectionService: CollectionService, private collectionService: CollectionService,
private billingApiService: BillingApiServiceAbstraction, private billingApiService: BillingApiServiceAbstraction,
private modalService: ModalService, private modalService: ModalService,

View File

@@ -29,7 +29,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { BitValidators, DialogService } from "@bitwarden/components"; import { BitValidators, DialogService } from "@bitwarden/components";
import { GroupService, GroupView } from "../../../admin-console/organizations/core"; import { GroupApiService, GroupView } from "../../../admin-console/organizations/core";
import { PermissionMode } from "../../../admin-console/organizations/shared/components/access-selector/access-selector.component"; import { PermissionMode } from "../../../admin-console/organizations/shared/components/access-selector/access-selector.component";
import { import {
AccessItemType, AccessItemType,
@@ -101,7 +101,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private dialogRef: DialogRef<CollectionDialogResult>, private dialogRef: DialogRef<CollectionDialogResult>,
private organizationService: OrganizationService, private organizationService: OrganizationService,
private groupService: GroupService, private groupService: GroupApiService,
private collectionAdminService: CollectionAdminService, private collectionAdminService: CollectionAdminService,
private i18nService: I18nService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,

View File

@@ -14,7 +14,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { DialogService } from "@bitwarden/components"; import { DialogService } from "@bitwarden/components";
import { GroupService, GroupView } from "../../../admin-console/organizations/core"; import { GroupApiService, GroupView } from "../../../admin-console/organizations/core";
import { import {
AccessItemType, AccessItemType,
AccessItemValue, AccessItemValue,
@@ -61,7 +61,7 @@ export class BulkCollectionsDialogComponent implements OnDestroy {
private dialogRef: DialogRef<BulkCollectionsDialogResult>, private dialogRef: DialogRef<BulkCollectionsDialogResult>,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private organizationService: OrganizationService, private organizationService: OrganizationService,
private groupService: GroupService, private groupService: GroupApiService,
private organizationUserApiService: OrganizationUserApiService, private organizationUserApiService: OrganizationUserApiService,
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService, private i18nService: I18nService,

View File

@@ -81,7 +81,7 @@ import {
PasswordRepromptService, PasswordRepromptService,
} from "@bitwarden/vault"; } from "@bitwarden/vault";
import { GroupService, GroupView } from "../../admin-console/organizations/core"; import { GroupApiService, GroupView } from "../../admin-console/organizations/core";
import { openEntityEventsDialog } from "../../admin-console/organizations/manage/entity-events.component"; import { openEntityEventsDialog } from "../../admin-console/organizations/manage/entity-events.component";
import { TrialFlowService } from "../../billing/services/trial-flow.service"; import { TrialFlowService } from "../../billing/services/trial-flow.service";
import { FreeTrial } from "../../core/types/free-trial"; import { FreeTrial } from "../../core/types/free-trial";
@@ -234,7 +234,7 @@ export class VaultComponent implements OnInit, OnDestroy {
private collectionAdminService: CollectionAdminService, private collectionAdminService: CollectionAdminService,
private searchService: SearchService, private searchService: SearchService,
private searchPipe: SearchPipe, private searchPipe: SearchPipe,
private groupService: GroupService, private groupService: GroupApiService,
private logService: LogService, private logService: LogService,
private eventCollectionService: EventCollectionService, private eventCollectionService: EventCollectionService,
private totpService: TotpService, private totpService: TotpService,