Skip to content

Commit

Permalink
Prepare endpoint, hook, and data
Browse files Browse the repository at this point in the history
Previous preparation of some
elements is needed:
- The `User` data type needs the following
parameters that will be managed in the
'Is a member of' section:
  - `memberof_group`
  - `memberof_netgroup`
  - `memberof_role`
  - `memberof_hbacrule`
  - `memberof_sudorule`
  - `memberof_subid`
- The `useGettingGroupsQuery` endpoint
wrapper to make the API call
- The original `UserGroup` data type has been
replaced by the `UserGroupOld` one. All the
files that use that type have been adapted
- The new `UserGroup` type will contain
the new data structure.
- The `useUserMemberOfData` hook to
retrieve and parse the data
- The `normalizeString` helper function
to normalize string LDAP values

Signed-off-by: Carla Martinez <[email protected]>
  • Loading branch information
carma12 committed Feb 19, 2024
1 parent 838b4c6 commit a7e209f
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 39 deletions.
12 changes: 6 additions & 6 deletions src/components/MemberOf/MemberOfAddModalOld.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Button, DualListSelector } from "@patternfly/react-core";
import ModalWithFormLayout from "src/components/layouts/ModalWithFormLayout";
// Data types
import {
UserGroup,
UserGroupOld,
Netgroup,
Roles,
HBACRules,
Expand All @@ -26,7 +26,7 @@ interface TabData {
export interface PropsToAdd {
modalData: ModalData;
availableData:
| UserGroup[]
| UserGroupOld[]
| Netgroup[]
| Roles[]
| HBACRules[]
Expand All @@ -35,7 +35,7 @@ export interface PropsToAdd {
groupRepository: unknown[];
updateGroupRepository: (
args:
| UserGroup[]
| UserGroupOld[]
| Netgroup[]
| Roles[]
| HBACRules[]
Expand All @@ -50,7 +50,7 @@ export interface PropsToAdd {
// its variables. Just the mandatory ones ('name' and 'description') are accessible at this point.
// To display all the possible data types for all the tabs (and not only the mandatory ones)
// an extra interface 'MemberOfElement' will be defined. This will be called when assigning
// a new group instead of refering to each type (UserGroup | Netgroup | Roles | HBACRules |
// a new group instead of refering to each type (UserGroupOld | Netgroup | Roles | HBACRules |
// SudoRules | HostGroup).
interface MemberOfElement {
hostGroup?: string;
Expand Down Expand Up @@ -136,9 +136,9 @@ const MemberOfAddModal = (props: PropsToAdd) => {
optionData.description !== undefined && optionData.description,
gid: optionData.gid !== undefined && optionData.gid,
status: optionData.status !== undefined && optionData.status,
} as UserGroup);
} as UserGroupOld);
// Send updated data to table
props.updateGroupRepository(props.groupRepository as UserGroup[]);
props.updateGroupRepository(props.groupRepository as UserGroupOld[]);
}
// Netgroups
if (props.tabData.tabName === "Netgroups") {
Expand Down
12 changes: 6 additions & 6 deletions src/components/MemberOf/MemberOfAddModalUserGroups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import {
Modal,
} from "@patternfly/react-core";
// Data types
import { UserGroup } from "src/utils/datatypes/globalDataTypes";
import { UserGroupOld } from "src/utils/datatypes/globalDataTypes";

export interface PropsToAdd {
showModal: boolean;
onCloseModal: () => void;
availableData: UserGroup[];
availableData: UserGroupOld[];
groupRepository: unknown[];
updateGroupRepository: (newList: UserGroup[]) => void;
updateGroupRepository: (newList: UserGroupOld[]) => void;
}

const MemberOfAddModal = (props: PropsToAdd) => {
Expand Down Expand Up @@ -84,16 +84,16 @@ const MemberOfAddModal = (props: PropsToAdd) => {
// Add group option
const onClickAddGroupHandler = () => {
chosenOptions.map((opt) => {
const optionData: UserGroup | undefined = getInfoFromGroupData(opt);
const optionData: UserGroupOld | undefined = getInfoFromGroupData(opt);
if (optionData !== undefined) {
props.groupRepository.push({
name: optionData.name !== undefined && optionData.name,
description:
optionData.description !== undefined && optionData.description,
gid: optionData.gid !== undefined && optionData.gid,
} as UserGroup);
} as UserGroupOld);
// Send updated data to table
props.updateGroupRepository(props.groupRepository as UserGroup[]);
props.updateGroupRepository(props.groupRepository as UserGroupOld[]);
}
});
// Clean chosen options and close modal
Expand Down
2 changes: 1 addition & 1 deletion src/components/MemberOf/MemberOfDeleteModalOld.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import MemberOfDeletedGroupsTable from "src/components/MemberOf/MemberOfDeletedG
// its variables. Just the mandatory ones ('name' and 'description') are accessible at this point.
// To display all the possible data types for all the tabs (and not only the mandatory ones)
// an extra interface 'MemberOfElement' will be defined. This will be called in the 'PropsToTable'
// interface instead of each type (UserGroup | Netgroup | Roles | HBACRules | SudoRules).
// interface instead of each type (UserGroupOld | Netgroup | Roles | HBACRules | SudoRules).
interface MemberOfElement {
name: string;
gid?: string;
Expand Down
10 changes: 5 additions & 5 deletions src/components/MemberOf/MemberOfDeleteModalUserGroups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import {
// Tables
import MemberOfDeletedGroupsTable from "src/components/MemberOf/MemberOfDeletedGroupsTable";
// Data types
import { UserGroup } from "src/utils/datatypes/globalDataTypes";
import { UserGroupOld } from "src/utils/datatypes/globalDataTypes";

interface PropsToDelete {
showModal: boolean;
onCloseModal: () => void;
tabName: string;
groupNamesToDelete: string[];
groupRepository: UserGroup[];
updateGroupRepository: (args: UserGroup[]) => void;
groupRepository: UserGroupOld[];
updateGroupRepository: (args: UserGroupOld[]) => void;
updateGroupNamesToDelete: (args: string[]) => void;
}

Expand All @@ -35,15 +35,15 @@ const MemberOfDeleteModal = (props: PropsToDelete) => {

// Obtain full info of groups to delete
const getListOfGroupsToDelete = () => {
const groupsToDelete: UserGroup[] = [];
const groupsToDelete: UserGroupOld[] = [];
props.groupNamesToDelete.map((groupName) =>
groupsToDelete.push(getGroupInfoByName(groupName))
);
return groupsToDelete;
};

// Groups to delete list
const groupsToDelete: UserGroup[] = getListOfGroupsToDelete();
const groupsToDelete: UserGroupOld[] = getListOfGroupsToDelete();

// Delete groups
const deleteGroups = () => {
Expand Down
6 changes: 3 additions & 3 deletions src/components/MemberOf/MemberOfTableUserGroups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import React from "react";
// PatternFly
import { Table, Tr, Th, Td, Thead, Tbody } from "@patternfly/react-table";
// Data types
import { UserGroup } from "src/utils/datatypes/globalDataTypes";
import { UserGroupOld } from "src/utils/datatypes/globalDataTypes";
// Components
import SkeletonOnTableLayout from "../layouts/Skeleton/SkeletonOnTableLayout";
import EmptyBodyTable from "../tables/EmptyBodyTable";

export interface MemberOfUserGroupsTableProps {
userGroups: UserGroup[];
userGroups: UserGroupOld[];
checkedItems: string[];
onCheckItemsChange: (checkedItems: string[]) => void;
showTableRows: boolean;
}

// Body
const UserGroupsTableBody = (props: {
userGroups: UserGroup[];
userGroups: UserGroupOld[];
checkedItems: string[];
onCheckboxChange: (checked: boolean, groupName: string) => void;
}) => {
Expand Down
8 changes: 4 additions & 4 deletions src/components/MemberOf/MemberOfToolbarOld.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import ToolbarLayout, {
} from "src/components/layouts/ToolbarLayout";
// Data types
import {
UserGroup,
UserGroupOld,
Netgroup,
Roles,
HBACRules,
Expand Down Expand Up @@ -57,7 +57,7 @@ interface ButtonData {
interface SettersData {
changeMemberGroupsList: (
arg:
| UserGroup[]
| UserGroupOld[]
| Netgroup[]
| Roles[]
| HBACRules[]
Expand All @@ -74,14 +74,14 @@ interface SearchValueData {

export interface PropsToToolbar {
pageRepo:
| UserGroup[]
| UserGroupOld[]
| Netgroup[]
| Roles[]
| HBACRules[]
| SudoRules[]
| HostGroup[];
shownItems:
| UserGroup[]
| UserGroupOld[]
| Netgroup[]
| Roles[]
| HBACRules[]
Expand Down
10 changes: 5 additions & 5 deletions src/components/MemberOf/MemberOfUserGroups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
// PatternFly
import { Pagination, PaginationVariant } from "@patternfly/react-core";
// Data types
import { UserGroup } from "src/utils/datatypes/globalDataTypes";
import { UserGroupOld } from "src/utils/datatypes/globalDataTypes";
// Redux
import { useAppSelector } from "src/store/hooks";
// Components
Expand Down Expand Up @@ -39,8 +39,8 @@ function filterUserGroupsData<Type extends TypeWithName>(
}

interface MemberOfUserGroupsProps {
usersGroupsFromUser: UserGroup[];
updateUsersGroupsFromUser: (newList: UserGroup[]) => void;
usersGroupsFromUser: UserGroupOld[];
updateUsersGroupsFromUser: (newList: UserGroupOld[]) => void;
}

const MemberOfUserGroups = (props: MemberOfUserGroupsProps) => {
Expand Down Expand Up @@ -69,7 +69,7 @@ const MemberOfUserGroups = (props: MemberOfUserGroupsProps) => {
const showTableRows = props.usersGroupsFromUser.length > 0;

// Available data to be added as member of
const userGroupsFilteredData: UserGroup[] = filterUserGroupsData(
const userGroupsFilteredData: UserGroupOld[] = filterUserGroupsData(
userGroupsFullList,
props.usersGroupsFromUser
);
Expand Down Expand Up @@ -116,7 +116,7 @@ const MemberOfUserGroups = (props: MemberOfUserGroupsProps) => {
onCloseModal={() => setShowAddModal(false)}
availableData={userGroupsFilteredData}
groupRepository={props.usersGroupsFromUser}
updateGroupRepository={(newList: UserGroup[]) =>
updateGroupRepository={(newList: UserGroupOld[]) =>
props.updateUsersGroupsFromUser(newList)
}
/>
Expand Down
67 changes: 67 additions & 0 deletions src/hooks/useUserMemberOfData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// RPC
import React from "react";
import { BatchRPCResponse, useGettingGroupsQuery } from "src/services/rpc";
// Data types
import { UserGroup } from "src/utils/datatypes/globalDataTypes";
// Utils
import { API_VERSION_BACKUP, normalizeString } from "src/utils/utils";

type MemberOfData = {
isLoading: boolean;
isFetching: boolean;
refetch: () => void;
userGroupsFullList: UserGroup[];
};

const useUserMemberOfData = ({ firstUserIdx, lastUserIdx }): MemberOfData => {
// [API call] User groups
// TODO: Normalize data to prevent array of arrays
const userGroupsQuery = useGettingGroupsQuery({
searchValue: "",
sizeLimit: 0,
apiVersion: API_VERSION_BACKUP,
startIdx: firstUserIdx,
stopIdx: lastUserIdx,
});

const [userGroupsFullList, setUserGroupsFullList] = React.useState<
UserGroup[]
>([]);
const userGroupsData = userGroupsQuery.data || {};
const isUserGroupsLoading = userGroupsQuery.isLoading;

React.useEffect(() => {
if (userGroupsData !== undefined && !userGroupsQuery.isFetching) {
const dataParsed = userGroupsData as BatchRPCResponse;
const count = dataParsed.result.count;
const results = dataParsed.result.results;

const userGroupsTempList: UserGroup[] = [];

for (let i = 0; i < count; i++) {
userGroupsTempList.push({
cn: normalizeString(results[i].result.cn),
gidnumber: normalizeString(results[i].result.gidnumber),
description: normalizeString(results[i].result.description),
dn: results[i].result.dn,
});
}
setUserGroupsFullList(userGroupsTempList);
}
}, [userGroupsData, userGroupsQuery.isFetching]);

// [API call] Refresh
const refetch = () => {
userGroupsQuery.refetch();
};

// Return data
return {
isFetching: userGroupsQuery.isFetching,
isLoading: isUserGroupsLoading,
refetch,
userGroupsFullList,
} as MemberOfData;
};

export { useUserMemberOfData };
4 changes: 2 additions & 2 deletions src/pages/ActiveUsers/UserMemberOf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import MemberOfToolbar from "src/components/MemberOf/MemberOfToolbarOld";
import MemberOfTable from "src/components/MemberOf/MemberOfTable";
// Data types
import {
UserGroup,
UserGroupOld,
Netgroup,
Roles,
HBACRules,
Expand Down Expand Up @@ -226,7 +226,7 @@ const UserMemberOf = (props: PropsToUserMemberOf) => {

// Update pagination
const changeMemberGroupsList = (
value: UserGroup[] | Netgroup[] | Roles[] | HBACRules[] | SudoRules[]
value: UserGroupOld[] | Netgroup[] | Roles[] | HBACRules[] | SudoRules[]
) => {
switch (activeTabKey) {
case 1:
Expand Down
22 changes: 21 additions & 1 deletion src/services/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
UIDType,
User,
Service,
cnType,
} from "../utils/datatypes/globalDataTypes";
import { apiToHost } from "../utils/hostUtils";
import { apiToUser } from "../utils/userUtils";
Expand Down Expand Up @@ -141,7 +142,7 @@ export interface GenericPayload {
stopIdx: number;
objName?: string;
objAttr?: string;
entryType?: "user" | "stage" | "preserved" | "host" | "service";
entryType?: "user" | "stage" | "preserved" | "host" | "service" | "group";
}

export interface HostAddPayload {
Expand Down Expand Up @@ -695,6 +696,8 @@ export const api = createApi({
id = idResponseData.result.result[i] as servicesType;
} else if (objName === "user" || objName === "stageuser") {
id = idResponseData.result.result[i] as UIDType;
} else if (objName === "group") {
id = idResponseData.result.result[i] as cnType;
} else {
// Unknown, should never happen
return {
Expand Down Expand Up @@ -1073,6 +1076,16 @@ export const api = createApi({
});
},
}),
getUserByUid: build.query<User, string>({
query: (uid) => {
return getCommand({
method: "user_show",
params: [[uid], { version: API_VERSION_BACKUP }],
});
},
transformResponse: (response: FindRPCResponse): User =>
response.result.result as unknown as User,
}),
}),
});

Expand Down Expand Up @@ -1116,6 +1129,12 @@ export const useGettingServicesQuery = (payloadData) => {
payloadData["objAttr"] = "krbprincipalname";
return useGettingGenericQuery(payloadData);
};
// Groups
export const useGettingGroupsQuery = (payloadData) => {
payloadData["objName"] = "group";
payloadData["objAttr"] = "cn";
return useGettingGenericQuery(payloadData);
};

// Full search wrappers
export const useGetUsersFullQuery = (userId: string) => {
Expand Down Expand Up @@ -1182,4 +1201,5 @@ export const {
useGetGenericListQuery,
useRemoveServicesMutation,
useSearchEntriesMutation,
useGetUserByUidQuery,
} = api;
4 changes: 2 additions & 2 deletions src/store/Identity/userGroups-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { createSlice } from "@reduxjs/toolkit";
import type { RootState } from "../store";
import userGroupsJson from "./userGroups.json";
// Data type
import { UserGroup } from "src/utils/datatypes/globalDataTypes";
import { UserGroupOld } from "src/utils/datatypes/globalDataTypes";

interface UserGroupState {
userGroupList: UserGroup[];
userGroupList: UserGroupOld[];
}

const initialState: UserGroupState = {
Expand Down
Loading

0 comments on commit a7e209f

Please sign in to comment.