Skip to content

Commit d30abf1

Browse files
Merge pull request #6861 from DonOmalVindula/fix/26115
2 parents 4b7ce35 + 48f0d46 commit d30abf1

File tree

8 files changed

+60
-48
lines changed

8 files changed

+60
-48
lines changed

.changeset/dirty-grapes-impress.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@wso2is/admin.extensions.v1": patch
3+
"@wso2is/admin.groups.v1": patch
4+
"@wso2is/theme": patch
5+
---
6+
7+
Add config to disable add/delete actions for remote userstores

features/admin.extensions.v1/configs/groups.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import { GroupConfig } from "./models";
2020

2121
export const groupConfig: GroupConfig = {
22-
addGroupWizard: {
23-
showUserstoreDropdown: true
24-
}
22+
allowGroupAddForRemoteUserstores: true,
23+
allowGroupDeleteForRemoteUserstores: true
2524
};
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright (c) 2021, WSO2 LLC. (https://www.wso2.com).
2+
* Copyright (c) 2021-2024, WSO2 LLC. (https://www.wso2.com).
33
*
44
* WSO2 LLC. licenses this file to you under the Apache License,
55
* Version 2.0 (the "License"); you may not use this file except
@@ -16,26 +16,8 @@
1616
* under the License.
1717
*/
1818

19-
import { GroupsInterface } from "@wso2is/admin.groups.v1";
2019

2120
export interface GroupConfig {
22-
addGroupWizard: {
23-
requiredSteps?: string[];
24-
showUserstoreDropdown?: boolean;
25-
subHeading?: string;
26-
submitStep?: string;
27-
};
28-
editGroups?: {
29-
basicTab: {
30-
showGroupNameLabel: boolean;
31-
userstore: (groupObject: GroupsInterface) => string;
32-
};
33-
basicTabName: string;
34-
showRolesTab: boolean;
35-
};
36-
groupsList?: {
37-
description: string;
38-
filterGroups: (groupResources: GroupsInterface[]) => GroupsInterface[];
39-
showUserstoreDropdown: boolean;
40-
};
21+
allowGroupAddForRemoteUserstores: boolean;
22+
allowGroupDeleteForRemoteUserstores: boolean;
4123
}

features/admin.groups.v1/components/edit-group/edit-group-basic.tsx

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com).
2+
* Copyright (c) 2023-2024, WSO2 LLC. (https://www.wso2.com).
33
*
44
* WSO2 LLC. licenses this file to you under the Apache License,
55
* Version 2.0 (the "License"); you may not use this file except
@@ -23,7 +23,7 @@ import {
2323
UserStoreProperty,
2424
history
2525
} from "@wso2is/admin.core.v1";
26-
import { userstoresConfig } from "@wso2is/admin.extensions.v1";
26+
import { groupConfig, userstoresConfig } from "@wso2is/admin.extensions.v1";
2727
import {
2828
AlertInterface,
2929
AlertLevels,
@@ -97,7 +97,10 @@ export const BasicGroupDetails: FunctionComponent<BasicGroupProps> = (props: Bas
9797

9898
const userStore: string = groupObject?.displayName?.split("/")?.length > 1
9999
? groupObject.displayName.split("/")[0]
100-
: SharedUserStoreConstants.PRIMARY_USER_STORE;
100+
: userstoresConfig.primaryUserstoreName;
101+
102+
const isUserstoreDeleteDisabled: boolean = !groupConfig?.allowGroupDeleteForRemoteUserstores
103+
&& userStore !== userstoresConfig.primaryUserstoreName;
101104

102105
useEffect(() => {
103106
if (groupObject && groupObject.displayName.indexOf("/") !== -1) {
@@ -115,7 +118,7 @@ export const BasicGroupDetails: FunctionComponent<BasicGroupProps> = (props: Bas
115118
const validateGroupNamePattern = async (): Promise<string> => {
116119
let userStoreRegEx: string = "";
117120

118-
if (userStore !== SharedUserStoreConstants.PRIMARY_USER_STORE) {
121+
if (userStore !== userstoresConfig.primaryUserstoreName) {
119122
await SharedUserStoreUtils.getUserStoreRegEx(userStore,
120123
SharedUserStoreConstants.USERSTORE_REGEX_PROPERTIES.RolenameRegEx)
121124
.then((response: string) => {
@@ -352,7 +355,7 @@ export const BasicGroupDetails: FunctionComponent<BasicGroupProps> = (props: Bas
352355
</EmphasizedSegment>
353356
<Divider hidden />
354357
{
355-
!isReadOnly && (
358+
!isReadOnly && !isUserstoreDeleteDisabled && (
356359
<DangerZoneGroup sectionHeader="Danger Zone">
357360
<DangerZone
358361
actionTitle={

features/admin.groups.v1/components/group-list.tsx

+28-16
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@
1616
* under the License.
1717
*/
1818

19-
import { Show } from "@wso2is/access-control";
19+
import { Show, useRequiredScopes } from "@wso2is/access-control";
2020
import {
2121
AppConstants,
22-
AppState,
2322
FeatureConfigInterface,
2423
UIConstants,
2524
getEmptyPlaceholderIllustrations,
2625
history
2726
} from "@wso2is/admin.core.v1";
28-
import { hasRequiredScopes, isFeatureEnabled } from "@wso2is/core/helpers";
27+
import { userstoresConfig } from "@wso2is/admin.extensions.v1";
28+
import { isFeatureEnabled } from "@wso2is/core/helpers";
2929
import { LoadableComponentInterface, SBACInterface, TestableComponentInterface } from "@wso2is/core/models";
3030
import {
3131
AnimatedAvatar,
@@ -41,7 +41,6 @@ import {
4141
import moment, { Moment } from "moment";
4242
import React, { ReactElement, ReactNode, SyntheticEvent, useState } from "react";
4343
import { useTranslation } from "react-i18next";
44-
import { useSelector } from "react-redux";
4544
import { Header, Icon, Label, SemanticICONS } from "semantic-ui-react";
4645
import { GroupConstants } from "../constants";
4746
import { GroupsInterface } from "../models";
@@ -102,6 +101,14 @@ interface GroupListProps extends SBACInterface<FeatureConfigInterface>,
102101
* Indicates whether the currently selected user store is read-only or not.
103102
*/
104103
isReadOnlyUserStore?: boolean;
104+
/**
105+
* Flag to show/hide the delete action in the userstore list.
106+
*/
107+
isUserstoreDeleteDisabled?: boolean;
108+
/**
109+
* Flag to show/hide the add action in the userstore list.
110+
*/
111+
isUserstoreAddDisabled?: boolean;
105112
}
106113

107114
/**
@@ -128,16 +135,19 @@ export const GroupList: React.FunctionComponent<GroupListProps> = (props: GroupL
128135
showListItemActions,
129136
showMetaContent,
130137
isReadOnlyUserStore,
138+
isUserstoreAddDisabled,
139+
isUserstoreDeleteDisabled,
131140
[ "data-testid" ]: testId
132141
} = props;
133142

134143
const { t } = useTranslation();
135144

136-
const allowedScopes: string = useSelector((state: AppState) => state?.auth?.allowedScopes);
137-
138145
const [ showGroupDeleteConfirmation, setShowDeleteConfirmationModal ] = useState<boolean>(false);
139146
const [ currentDeletedGroup, setCurrentDeletedGroup ] = useState<GroupsInterface>();
140147

148+
const hasGroupsUpdatePermission: boolean = useRequiredScopes(featureConfig?.groups?.scopes?.update);
149+
const hasGroupsDeletePermission: boolean = useRequiredScopes(featureConfig?.groups?.scopes?.delete);
150+
141151
const handleGroupEdit = (groupId: string): void => {
142152
history.push(AppConstants.getPaths().get("GROUP_EDIT").replace(":id", groupId));
143153
};
@@ -214,7 +224,7 @@ export const GroupList: React.FunctionComponent<GroupListProps> = (props: GroupL
214224
return (
215225
<EmptyPlaceholder
216226
data-testid={ `${ testId }-empty-list-empty-placeholder` }
217-
action={ !isReadOnlyUserStore && (
227+
action={ !isReadOnlyUserStore && !isUserstoreAddDisabled && (
218228
<Show
219229
when={ featureConfig?.groups?.scopes?.create }
220230
>
@@ -231,14 +241,14 @@ export const GroupList: React.FunctionComponent<GroupListProps> = (props: GroupL
231241
image={ getEmptyPlaceholderIllustrations().newList }
232242
imageSize="tiny"
233243
title={
234-
isReadOnlyUserStore
244+
(isReadOnlyUserStore || isUserstoreAddDisabled)
235245
? t("roles:list.emptyPlaceholders.emptyRoleList.emptyRoles",
236246
{ type: "groups" })
237247
: t("roles:list.emptyPlaceholders.emptyRoleList.title",
238248
{ type: "group" })
239249
}
240250
subtitle={
241-
isReadOnlyUserStore
251+
(isReadOnlyUserStore || isUserstoreAddDisabled)
242252
? [
243253
t("roles:list.emptyPlaceholders.emptyRoleList.subtitles.0",
244254
{ type: "groups" })
@@ -341,11 +351,11 @@ export const GroupList: React.FunctionComponent<GroupListProps> = (props: GroupL
341351
icon: (group: GroupsInterface): SemanticICONS => {
342352
const userStore: string = group?.displayName?.split("/").length > 1
343353
? group?.displayName?.split("/")[0]
344-
: "PRIMARY";
354+
: userstoresConfig?.primaryUserstoreName;
345355

346356
return !isFeatureEnabled(featureConfig?.groups,
347357
GroupConstants.FEATURE_DICTIONARY.get("GROUP_UPDATE"))
348-
|| !hasRequiredScopes(featureConfig?.groups, featureConfig?.groups?.scopes?.update, allowedScopes)
358+
|| !hasGroupsUpdatePermission
349359
|| readOnlyUserStores?.includes(userStore.toString())
350360
? "eye"
351361
: "pencil alternate";
@@ -355,11 +365,11 @@ export const GroupList: React.FunctionComponent<GroupListProps> = (props: GroupL
355365
popupText: (group: GroupsInterface): string => {
356366
const userStore: string = group?.displayName?.split("/").length > 1
357367
? group?.displayName?.split("/")[0]
358-
: "PRIMARY";
368+
: userstoresConfig?.primaryUserstoreName;
359369

360370
return !isFeatureEnabled(featureConfig?.groups,
361371
GroupConstants.FEATURE_DICTIONARY.get("GROUP_UPDATE"))
362-
|| !hasRequiredScopes(featureConfig?.groups, featureConfig?.groups?.scopes?.update, allowedScopes)
372+
|| !hasGroupsUpdatePermission
363373
|| readOnlyUserStores?.includes(userStore.toString())
364374
? t("common:view")
365375
: t("common:edit");
@@ -372,10 +382,12 @@ export const GroupList: React.FunctionComponent<GroupListProps> = (props: GroupL
372382
hidden: (group: GroupsInterface): boolean => {
373383
const userStore: string = group?.displayName?.split("/").length > 1
374384
? group?.displayName?.split("/")[0]
375-
: "PRIMARY";
385+
: userstoresConfig?.primaryUserstoreName;
376386

377-
return !hasRequiredScopes(featureConfig?.groups, featureConfig?.groups?.scopes?.delete, allowedScopes)
378-
|| readOnlyUserStores?.includes(userStore.toString());
387+
return !hasGroupsDeletePermission
388+
|| readOnlyUserStores?.includes(userStore.toString())
389+
|| isReadOnlyUserStore
390+
|| isUserstoreDeleteDisabled;
379391
},
380392
icon: (): SemanticICONS => "trash alternate",
381393
onClick: (e: SyntheticEvent, group: GroupsInterface): void => {

features/admin.groups.v1/components/wizard/group-basics.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ export const GroupBasics: FunctionComponent<GroupBasicProps> = (props: GroupBasi
224224
>
225225
<Grid>
226226
{
227-
groupConfig?.addGroupWizard?.showUserstoreDropdown && (
227+
groupConfig?.allowGroupAddForRemoteUserstores && (
228228
<GridRow>
229229
<RootOnlyComponent>
230230
<GridColumn mobile={ 16 } tablet={ 16 } computer={ 10 }>

features/admin.groups.v1/pages/groups.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
getAUserStore,
2828
getEmptyPlaceholderIllustrations
2929
} from "@wso2is/admin.core.v1";
30-
import { commonConfig, userstoresConfig } from "@wso2is/admin.extensions.v1/configs";
30+
import { commonConfig, groupConfig, userstoresConfig } from "@wso2is/admin.extensions.v1/configs";
3131
import { RootOnlyComponent } from "@wso2is/admin.organizations.v1/components";
3232
import { useGetCurrentOrganizationType } from "@wso2is/admin.organizations.v1/hooks/use-get-organization-type";
3333
import { getUserStoreList } from "@wso2is/admin.userstores.v1/api";
@@ -109,6 +109,11 @@ const GroupsPage: FunctionComponent<any> = (): ReactElement => {
109109
mutate: mutateGroupsFetchRequest
110110
} = useGroupList(userStore, "members,roles", searchQuery, true);
111111

112+
const isUserstoreDeleteDisabled: boolean = !groupConfig?.allowGroupDeleteForRemoteUserstores
113+
&& userStore !== userstoresConfig.primaryUserstoreName;
114+
const isUserstoreAddDisabled: boolean = !groupConfig?.allowGroupAddForRemoteUserstores
115+
&& userStore !== userstoresConfig.primaryUserstoreName;
116+
112117
/**
113118
* Indicates whether the currently selected user store is read-only or not.
114119
*/
@@ -298,6 +303,8 @@ const GroupsPage: FunctionComponent<any> = (): ReactElement => {
298303
<PageLayout
299304
action={
300305
(!isGroupsListRequestLoading && paginatedGroups?.length > 0)
306+
&& !isUserstoreAddDisabled
307+
&& !isReadOnlyUserStore
301308
&& (
302309
<Show
303310
when={ featureConfig?.groups?.scopes?.create }
@@ -430,6 +437,8 @@ const GroupsPage: FunctionComponent<any> = (): ReactElement => {
430437
readOnlyUserStores={ readOnlyUserStoresList }
431438
featureConfig={ featureConfig }
432439
isReadOnlyUserStore={ isReadOnlyUserStore }
440+
isUserstoreAddDisabled={ isUserstoreAddDisabled }
441+
isUserstoreDeleteDisabled={ isUserstoreDeleteDisabled }
433442
/>)
434443
}
435444
</ListLayout>

modules/theme/src/themes/wso2is/apps/developer-portal.overrides

+1-1
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,6 @@ TODO : Move values to separate variables and cleanup styles.
15581558

15591559
.scroll-container {
15601560
height: calc(100vh - 450px);
1561-
min-width: 800px;
15621561
font-family: "Gilmer";
15631562
font-style: normal;
15641563
font-weight: 400;
@@ -1904,6 +1903,7 @@ TODO : Move values to separate variables and cleanup styles.
19041903
.email-template-resource-tab-pane {
19051904
border-bottom-left-radius: 0 !important;
19061905
border-bottom-right-radius: 0 !important;
1906+
pointer-events: none;
19071907
}
19081908

19091909
.email-template-preview {

0 commit comments

Comments
 (0)