1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-14 10:26:19 +01: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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
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 { CoreOrganizationModule } from "../../core-organization.module";
import { GroupDetailsView } from "../../views/group-details.view";
import { GroupView } from "../../views/group.view";
import { AddEditGroupDetail } from "./../../views/add-edit-group-detail";
import { GroupRequest } from "./requests/group.request";
import { OrganizationGroupBulkRequest } from "./requests/organization-group-bulk.request";
import { GroupDetailsResponse, GroupResponse } from "./responses/group.response";
@ -15,13 +17,13 @@ import { GroupDetailsResponse, GroupResponse } from "./responses/group.response"
@Injectable({
providedIn: "root",
})
export class GroupService {
export class GroupApiService {
constructor(
protected apiService: ApiService,
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(
"GET",
"/organizations/" + orgId + "/groups/" + groupId + "/details",
@ -30,7 +32,7 @@ export class GroupService {
true,
);
return GroupView.fromResponse(new GroupDetailsResponse(r));
return GroupDetailsView.fromResponse(new GroupDetailsResponse(r));
}
async getAll(orgId: string): Promise<GroupView[]> {
@ -44,12 +46,26 @@ export class GroupService {
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 })
export class InternalGroupService extends GroupService {
export class InternalGroupApiService extends GroupApiService {
constructor(
protected apiService: ApiService,
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();
request.name = group.name;
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";

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 { GroupDetailsResponse, GroupResponse } from "../services/group/responses/group.response";
import { GroupResponse } from "../services/group/responses/group.response";
export class GroupView implements View {
id: string;
organizationId: string;
name: string;
externalId: string;
collections: CollectionAccessSelectionView[] = [];
members: string[] = [];
static fromResponse(response: GroupResponse): GroupView {
const view: GroupView = Object.assign(new GroupView(), response) as GroupView;
if (response instanceof GroupDetailsResponse && response.collections != undefined) {
view.collections = response.collections.map((c) => new CollectionAccessSelectionView(c));
}
return view;
return Object.assign(new GroupView(), response);
}
}

View File

@ -1,3 +1,4 @@
export * from "./group.view";
export * from "./group-details.view";
export * from "./organization-user.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 { DialogService, ToastService } from "@bitwarden/components";
import { InternalGroupService as GroupService, GroupView } from "../core";
import { InternalGroupApiService as GroupService } from "../core";
import {
AccessItemType,
AccessItemValue,
@ -40,6 +40,8 @@ import {
PermissionMode,
} from "../shared/components/access-selector";
import { AddEditGroupDetail } from "./../core/views/add-edit-group-detail";
/**
* Indices for the available tabs in the dialog
*/
@ -105,7 +107,7 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
title: string;
collections: AccessItemView[] = [];
members: Array<AccessItemView & { userId: UserId }> = [];
group: GroupView;
group: AddEditGroupDetail;
groupForm = this.formBuilder.group({
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) => {
if (!editMode) {
return of(undefined);
@ -159,9 +161,11 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
this.groupService.get(this.organizationId, this.groupId),
this.apiService.getGroupUsers(this.organizationId, this.groupId),
]).pipe(
map(([groupView, users]) => {
groupView.members = users;
return groupView;
map(([groupView, users]): AddEditGroupDetail => {
return {
...groupView,
members: users,
};
}),
catchError((e: unknown) => {
if (e instanceof ErrorResponse) {
@ -295,14 +299,16 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
return;
}
const groupView = new GroupView();
groupView.id = this.groupId;
groupView.organizationId = this.organizationId;
const formValue = this.groupForm.value;
groupView.name = formValue.name;
groupView.members = formValue.members?.map((m) => m.id) ?? [];
groupView.collections = formValue.collections.map((c) => convertToSelectionView(c));
const groupView: AddEditGroupDetail = {
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);
@ -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
*/
function mapToAccessSelections(group: GroupView, items: AccessItemView[]): AccessItemValue[] {
function mapToAccessSelections(
group: AddEditGroupDetail,
items: AccessItemView[],
): AccessItemValue[] {
return (
group.collections
// 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(
collections: CollectionAdminView[],
organization: Organization,
group?: GroupView,
group?: AddEditGroupDetail,
): AccessItemView[] {
return (
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 { DialogService, TableDataSource, ToastService } from "@bitwarden/components";
import { InternalGroupService as GroupService, GroupView } from "../core";
import { GroupDetailsView, InternalGroupApiService as GroupService } from "../core";
import {
GroupAddEditDialogResultType,
@ -40,7 +40,7 @@ type GroupDetailsRow = {
/**
* Details used for displaying group information
*/
details: GroupView;
details: GroupDetailsView;
/**
* True if the group is selected in the table
@ -108,7 +108,7 @@ export class GroupsComponent {
),
// groups
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 {
GroupService,
GroupView,
GroupApiService,
GroupDetailsView,
OrganizationUserAdminView,
UserAdminService,
} from "../../../core";
@ -144,7 +144,7 @@ export class MemberDialogComponent implements OnDestroy {
private formBuilder: FormBuilder,
// TODO: We should really look into consolidating naming conventions for these services
private collectionAdminService: CollectionAdminService,
private groupService: GroupService,
private groupService: GroupApiService,
private userService: UserAdminService,
private organizationUserApiService: OrganizationUserApiService,
private dialogService: DialogService,
@ -171,8 +171,8 @@ export class MemberDialogComponent implements OnDestroy {
const groups$ = this.organization$.pipe(
switchMap((organization) =>
organization.useGroups
? this.groupService.getAll(this.params.organizationId)
: of([] as GroupView[]),
? this.groupService.getAllDetails(this.params.organizationId)
: of([] as GroupDetailsView[]),
),
);
@ -278,7 +278,7 @@ export class MemberDialogComponent implements OnDestroy {
private loadOrganizationUser(
userDetails: OrganizationUserAdminView,
groups: GroupView[],
groups: GroupDetailsView[],
collections: CollectionAdminView[],
organization: Organization,
) {
@ -635,7 +635,7 @@ function mapCollectionToAccessItemView(
collection: CollectionAdminView,
organization: Organization,
accessSelection?: CollectionAccessSelectionView,
group?: GroupView,
group?: GroupDetailsView,
): AccessItemView {
return {
type: AccessItemType.Collection,
@ -648,7 +648,7 @@ function mapCollectionToAccessItemView(
};
}
function mapGroupToAccessItemView(group: GroupView): AccessItemView {
function mapGroupToAccessItemView(group: GroupDetailsView): AccessItemView {
return {
type: AccessItemType.Group,
id: group.id,

View File

@ -56,7 +56,7 @@ import {
} from "../../../billing/organizations/change-plan-dialog.component";
import { BaseMembersComponent } from "../../common/base-members.component";
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 { openEntityEventsDialog } from "../manage/entity-events.component";
@ -129,7 +129,7 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
private organizationApiService: OrganizationApiServiceAbstraction,
private organizationUserApiService: OrganizationUserApiService,
private router: Router,
private groupService: GroupService,
private groupService: GroupApiService,
private collectionService: CollectionService,
private billingApiService: BillingApiServiceAbstraction,
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 { 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 {
AccessItemType,
@ -101,7 +101,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
private formBuilder: FormBuilder,
private dialogRef: DialogRef<CollectionDialogResult>,
private organizationService: OrganizationService,
private groupService: GroupService,
private groupService: GroupApiService,
private collectionAdminService: CollectionAdminService,
private i18nService: I18nService,
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 { DialogService } from "@bitwarden/components";
import { GroupService, GroupView } from "../../../admin-console/organizations/core";
import { GroupApiService, GroupView } from "../../../admin-console/organizations/core";
import {
AccessItemType,
AccessItemValue,
@ -61,7 +61,7 @@ export class BulkCollectionsDialogComponent implements OnDestroy {
private dialogRef: DialogRef<BulkCollectionsDialogResult>,
private formBuilder: FormBuilder,
private organizationService: OrganizationService,
private groupService: GroupService,
private groupService: GroupApiService,
private organizationUserApiService: OrganizationUserApiService,
private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService,

View File

@ -81,7 +81,7 @@ import {
PasswordRepromptService,
} 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 { TrialFlowService } from "../../billing/services/trial-flow.service";
import { FreeTrial } from "../../core/types/free-trial";
@ -234,7 +234,7 @@ export class VaultComponent implements OnInit, OnDestroy {
private collectionAdminService: CollectionAdminService,
private searchService: SearchService,
private searchPipe: SearchPipe,
private groupService: GroupService,
private groupService: GroupApiService,
private logService: LogService,
private eventCollectionService: EventCollectionService,
private totpService: TotpService,