Skip to content

Commit

Permalink
Merge pull request #6973 from pavinduLakshan/console_settings_bug_fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
pavinduLakshan authored Oct 14, 2024
2 parents 9c71a72 + 7589832 commit 8bf814f
Show file tree
Hide file tree
Showing 19 changed files with 375 additions and 225 deletions.
6 changes: 6 additions & 0 deletions .changeset/ninety-ads-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@wso2is/admin.console-settings.v1": patch
"@wso2is/admin.roles.v2": patch
---

Bug fixes related to conosle settings in primary organizations for managed deployments
4 changes: 4 additions & 0 deletions features/admin.administrators.v1/constants/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ export class AdministratorConstants {
// Timeout for the debounce function.
public static readonly DEBOUNCE_TIMEOUT: number = 1000;

public static readonly INVITE_INTERNAL_USER_FORM_ID: string = "inviteInternalUserForm";

public static readonly INVITE_EXTERNAL_USER_FORM_ID: string = "inviteExternalUserForm";

/**
* Get the consumer users paths as a map.
*
Expand Down
390 changes: 227 additions & 163 deletions features/admin.administrators.v1/wizard/steps/admin-user-basic.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import React, {
useEffect,
useState
} from "react";
import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import AdministratorsList from "./administrators-list/administrators-list";
import InvitedAdministratorsList from "./invited-administrators/invited-administrators-list";
Expand All @@ -57,6 +58,7 @@ const ConsoleAdministrators: FunctionComponent<ConsoleAdministratorsInterface> =
const { [ "data-componentid" ]: componentId } = props;

const { isFirstLevelOrganization, isSubOrganization } = useGetCurrentOrganizationType();
const { t } = useTranslation();

const consoleSettingsFeatureConfig: FeatureAccessConfigInterface =
useSelector((state: AppState) => state?.config?.ui?.features?.consoleSettings);
Expand All @@ -71,6 +73,7 @@ const ConsoleAdministrators: FunctionComponent<ConsoleAdministratorsInterface> =
const [ isEnterpriseLoginEnabled, setIsEnterpriseLoginEnabled ] = useState<boolean>(false);

const organizationName: string = store.getState().auth.tenantDomain;
const productName: string = useSelector((state: AppState) => state.config.ui.productName);

const useOrgConfig: UseOrganizationConfigType = useOrganizationConfigV2;

Expand Down Expand Up @@ -186,8 +189,12 @@ const ConsoleAdministrators: FunctionComponent<ConsoleAdministratorsInterface> =
value={ activeAdministratorGroup }
onChange={ (_: ChangeEvent<HTMLInputElement>, value: string) => setActiveAdministratorGroup(value) }
>
<FormControlLabel value="administrators" control={ <Radio /> } label="Administrators" />
<FormControlLabel value="privilegedUsers" control={ <Radio /> } label="Privileged Users" />
<FormControlLabel value="administrators" control={ <Radio /> } label={ productName } />
<FormControlLabel
value="privilegedUsers"
control={ <Radio /> }
label={ t("common:organizationName", { orgName: organizationName }) }
/>
</RadioGroup>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@
.submit-button {
margin-top: 2rem;
}

.multi-option-radio-group {
gap: 40px;
margin: 20px 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
* under the License.
*/

import FormControlLabel from "@oxygen-ui/react/FormControlLabel";
import Radio from "@oxygen-ui/react/Radio";
import RadioGroup from "@oxygen-ui/react/RadioGroup";
import { FeatureStatus, useCheckFeatureStatus, useRequiredScopes } from "@wso2is/access-control";
import { useOrganizationConfigV2 } from "@wso2is/admin.administrators.v1/api/useOrganizationConfigV2";
import { UseOrganizationConfigType } from "@wso2is/admin.administrators.v1/models";
Expand All @@ -30,7 +33,7 @@ import { RoleAudienceTypes } from "@wso2is/admin.roles.v2/constants/role-constan
import { RoleConstants } from "@wso2is/core/constants";
import { FeatureAccessConfigInterface, IdentifiableComponentInterface, RolesInterface } from "@wso2is/core/models";
import { ResourceTab, ResourceTabPaneInterface } from "@wso2is/react-components";
import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
import React, { ChangeEvent, FunctionComponent, ReactElement, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import ConsoleRolePermissions from "./console-role-permissions";
Expand Down Expand Up @@ -64,40 +67,42 @@ interface ConsoleRolesEditPropsInterface extends IdentifiableComponentInterface
* @param props - contains role details to be edited.
*/
const ConsoleRolesEdit: FunctionComponent<ConsoleRolesEditPropsInterface> = (
props: ConsoleRolesEditPropsInterface): ReactElement => {

const {
isLoading,
roleObject,
onRoleUpdate,
defaultActiveIndex
} = props;
props: ConsoleRolesEditPropsInterface
): ReactElement => {
const { isLoading, roleObject, onRoleUpdate, defaultActiveIndex } = props;

const { t } = useTranslation();
const { isFirstLevelOrganization, isSubOrganization, organizationType } = useGetCurrentOrganizationType();

const userRolesFeatureConfig: FeatureAccessConfigInterface = useSelector(
(state: AppState) => state?.config?.ui?.features?.userRoles);
(state: AppState) => state?.config?.ui?.features?.userRoles
);
const hasRolesUpdatePermissions: boolean = useRequiredScopes(userRolesFeatureConfig?.scopes?.update);

const administratorRoleDisplayName: string = useSelector(
(state: AppState) => state?.config?.ui?.administratorRoleDisplayName);
(state: AppState) => state?.config?.ui?.administratorRoleDisplayName
);

const consoleSettingsFeatureConfig: FeatureAccessConfigInterface =
useSelector((state: AppState) => state?.config?.ui?.features?.consoleSettings);
const consoleSettingsFeatureConfig: FeatureAccessConfigInterface = useSelector(
(state: AppState) => state?.config?.ui?.features?.consoleSettings
);
const isConsoleRolesEditable: boolean = !consoleSettingsFeatureConfig?.disabledFeatures?.includes(
"consoleSettings.editableConsoleRoles"
);
const isPrivilegedUsersInConsoleSettingsEnabled: boolean =
!consoleSettingsFeatureConfig?.disabledFeatures?.includes(
"consoleSettings.privilegedUsers"
);

const [ isAdminRole, setIsAdminRole ] = useState<boolean>(false);
const [ isEnterpriseLoginEnabled, setIsEnterpriseLoginEnabled ] = useState<boolean>(false);
const [ activeUserStore, setActiveUserStore ] = useState<string>("PRIMARY");

const organizationName: string = store.getState().auth.tenantDomain;

const useOrgConfig: UseOrganizationConfigType = useOrganizationConfigV2;

const saasFeatureStatus : FeatureStatus = useCheckFeatureStatus(
FeatureGateConstants.SAAS_FEATURES_IDENTIFIER);
const saasFeatureStatus: FeatureStatus = useCheckFeatureStatus(FeatureGateConstants.SAAS_FEATURES_IDENTIFIER);

const {
data: OrganizationConfig,
Expand All @@ -121,10 +126,12 @@ const ConsoleRolesEdit: FunctionComponent<ConsoleRolesEditPropsInterface> = (
* Set the if the role is `Internal/admin`.
*/
useEffect(() => {
if(roleObject) {
setIsAdminRole(roleObject.displayName === RoleConstants.ADMIN_ROLE ||
roleObject?.displayName === RoleConstants.ADMIN_GROUP ||
roleObject?.displayName === administratorRoleDisplayName);
if (roleObject) {
setIsAdminRole(
roleObject.displayName === RoleConstants.ADMIN_ROLE ||
roleObject?.displayName === RoleConstants.ADMIN_GROUP ||
roleObject?.displayName === administratorRoleDisplayName
);
}
}, [ roleObject ]);

Expand All @@ -135,8 +142,9 @@ const ConsoleRolesEdit: FunctionComponent<ConsoleRolesEditPropsInterface> = (
render: () => (
<ResourceTab.Pane controlledSegmentation attached={ false }>
<BasicRoleDetails
isReadOnly={ isSubOrg || isAdminRole || !isConsoleRolesEditable
|| !hasRolesUpdatePermissions }
isReadOnly={
isSubOrg || isAdminRole || !isConsoleRolesEditable || !hasRolesUpdatePermissions
}
role={ roleObject }
onRoleUpdate={ onRoleUpdate }
tabIndex={ 0 }
Expand All @@ -151,10 +159,7 @@ const ConsoleRolesEdit: FunctionComponent<ConsoleRolesEditPropsInterface> = (
<ResourceTab.Pane controlledSegmentation attached={ false }>
<ConsoleRolePermissions
isReadOnly={
isSubOrg
|| isAdminRole
|| !isConsoleRolesEditable
|| !hasRolesUpdatePermissions
isSubOrg || isAdminRole || !isConsoleRolesEditable || !hasRolesUpdatePermissions
}
role={ roleObject }
onRoleUpdate={ onRoleUpdate }
Expand All @@ -164,7 +169,7 @@ const ConsoleRolesEdit: FunctionComponent<ConsoleRolesEditPropsInterface> = (
</ResourceTab.Pane>
)
},
( (isFirstLevelOrganization() && isEnterpriseLoginEnabled) || isSubOrganization() ) && {
((isFirstLevelOrganization() && isEnterpriseLoginEnabled) || isSubOrganization()) && {
menuItem: t("roles:edit.menuItems.groups"),
render: () => (
<ResourceTab.Pane controlledSegmentation attached={ false }>
Expand All @@ -181,10 +186,34 @@ const ConsoleRolesEdit: FunctionComponent<ConsoleRolesEditPropsInterface> = (
menuItem: t("roles:edit.menuItems.users"),
render: () => (
<ResourceTab.Pane controlledSegmentation attached={ false }>
{ isFirstLevelOrganization() &&
isEnterpriseLoginEnabled &&
isPrivilegedUsersInConsoleSettingsEnabled && (
<RadioGroup
row
aria-labelledby="console-administrators-radio-group"
className="multi-option-radio-group"
defaultValue="PRIMARY"
name="console-administrators-radio-group-2"
value={ activeUserStore }
onChange={ (_: ChangeEvent<HTMLInputElement>, value: string) => {
setActiveUserStore(value);
} }
>
<FormControlLabel value="PRIMARY" control={ <Radio /> } label="Asgardeo" />
<FormControlLabel
value="DEFAULT"
control={ <Radio /> }
label={ organizationName + " organization" }
/>
</RadioGroup>
) }

<RoleUsersList
isReadOnly={ !hasRolesUpdatePermissions }
role={ roleObject }
onRoleUpdate={ onRoleUpdate }
activeUserStore={ activeUserStore }
tabIndex={ 3 }
/>
</ResourceTab.Pane>
Expand All @@ -211,12 +240,10 @@ const ConsoleRolesEdit: FunctionComponent<ConsoleRolesEditPropsInterface> = (
return panes;
};

return (
<ResourceTab
isLoading={ isLoading }
defaultActiveIndex={ defaultActiveIndex }
panes={ resolveResourcePanes() }
/>
return (<ResourceTab
isLoading={ isLoading }
defaultActiveIndex={ defaultActiveIndex }
panes={ resolveResourcePanes() } />
);
};

Expand Down
75 changes: 47 additions & 28 deletions features/admin.roles.v2/components/edit-role/edit-role-users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export const RoleUsersList: FunctionComponent<RoleUsersPropsInterface> = (
onRoleUpdate,
isReadOnly,
tabIndex,
activeUserStore,
[ "data-componentid" ]: componentId
} = props;

Expand All @@ -97,7 +98,8 @@ export const RoleUsersList: FunctionComponent<RoleUsersPropsInterface> = (
const [ activeOption, setActiveOption ] = useState<GroupsInterface|UserBasicInterface>(undefined);
const [ availableUserStores, setAvailableUserStores ] = useState<UserstoreDisplayItem[]>([]);
const [ selectedUserStoreDomainName, setSelectedUserStoreDomainName ] = useState<string>(
disabledUserstores.includes(RemoteUserStoreConstants.PRIMARY_USER_STORE_NAME) ? "DEFAULT" : "Primary"
activeUserStore ??
disabledUserstores.includes(RemoteUserStoreConstants.PRIMARY_USER_STORE_NAME) ? "DEFAULT" : "PRIMARY"
);
const [ isPlaceholderVisible, setIsPlaceholderVisible ] = useState<boolean>(true);
const [ selectedUsersFromUserStore, setSelectedUsersFromUserStore ] = useState<UserBasicInterface[]>([]);
Expand Down Expand Up @@ -125,10 +127,14 @@ export const RoleUsersList: FunctionComponent<RoleUsersPropsInterface> = (
const isUserBelongToSelectedUserStore = (user: UserBasicInterface, userStoreName: string) => {
const userNameChunks: string[] = user.userName.split("/");

return (userNameChunks.length === 1 && userStoreName === "Primary")
return (userNameChunks.length === 1 && userStoreName === "PRIMARY")
|| (userNameChunks.length === 2 && userNameChunks[0] === userStoreName.toUpperCase());
};

useEffect(() => {
setSelectedUserStoreDomainName(activeUserStore);
}, [ activeUserStore ]);

useEffect(() => {
if (!role?.users?.length) {
return;
Expand Down Expand Up @@ -303,8 +309,15 @@ export const RoleUsersList: FunctionComponent<RoleUsersPropsInterface> = (
const removedUsers: RolesMemberInterface[] = role?.users?.filter((user: RolesMemberInterface) => {
return selectedUsers?.find(
(selectedUser: UserBasicInterface) => selectedUser.id === user.value) === undefined;
}).filter((user: RolesMemberInterface) => {
const userNameChunks: string[] = user.display.split("/");

return (userNameChunks.length === 1 && selectedUserStoreDomainName === "PRIMARY")
|| (userNameChunks.length === 2 && userNameChunks[0] === selectedUserStoreDomainName.toUpperCase());
}) ?? [];



const removeOperations: PatchUserRemoveOpInterface[] = removedUsers?.map((user: RolesMemberInterface) => {
return ({
"op": "remove",
Expand Down Expand Up @@ -390,33 +403,39 @@ export const RoleUsersList: FunctionComponent<RoleUsersPropsInterface> = (
{
users && availableUserStores && !isReadOnly && (
<Grid container spacing={ 1 }>
<Grid xs={ 12 } sm={ 4 } md={ 2 } alignItems="center">
<FormControl fullWidth size="medium">
<Select
value={ selectedUserStoreDomainName }
onChange={
(e: SelectChangeEvent<unknown>) => {
updateSelectedAllUsers();
setSelectedUsersFromUserStore([]);
setSelectedUserStoreDomainName(e.target.value as string);
{ !activeUserStore && (
<Grid xs={ 12 } sm={ 4 } md={ 2 } alignItems="center">
<FormControl fullWidth size="medium">
<Select
value={ selectedUserStoreDomainName }
onChange={
(e: SelectChangeEvent<unknown>) => {
updateSelectedAllUsers();
setSelectedUsersFromUserStore([]);
setSelectedUserStoreDomainName(
e.target.value as string
);
}
}
}
data-componentid={ `${ componentId }-user-store-domain-dropdown` }
>
{ isUserStoresLoading
? <p>{ t("common:loading") }</p>
: availableUserStores?.map((userstore: UserStoreListItem) =>
(<MenuItem
key={ userstore.name }
value={ userstore.name }
>
{ userstore.name }
</MenuItem>)
)
}
</Select>
</FormControl>
</Grid>
data-componentid={
`${ componentId }-user-store-domain-dropdown`
}
>
{ isUserStoresLoading
? <p>{ t("common:loading") }</p>
: availableUserStores?.map((userstore: UserStoreListItem) =>
(<MenuItem
key={ userstore.name }
value={ userstore.name }
>
{ userstore.name }
</MenuItem>)
)
}
</Select>
</FormControl>
</Grid>
) }
<Grid xs={ 12 } sm={ 4 } md={ 8 }>
<Autocomplete
multiple
Expand Down
7 changes: 7 additions & 0 deletions features/admin.roles.v2/models/roles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ export interface RoleEditSectionsInterface {
* Tab index
*/
tabIndex: number;
/**
* active user store
*
* Note: used to conditionally determine whether the userstore is handled
* outside the component.
*/
activeUserStore?: string
}

/**
Expand Down
1 change: 1 addition & 0 deletions modules/i18n/src/models/namespaces/common-ns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export interface CommonNS {
name: string;
new: string;
next: string;
organizationName: string;
operatingSystem: string;
operations: string;
overview: string;
Expand Down
Loading

0 comments on commit 8bf814f

Please sign in to comment.