diff --git a/.changeset/new-teachers-decide.md b/.changeset/new-teachers-decide.md new file mode 100644 index 00000000000..cc382e446b7 --- /dev/null +++ b/.changeset/new-teachers-decide.md @@ -0,0 +1,66 @@ +--- +"@wso2is/admin.identity-verification-providers.v1": patch +"@wso2is/admin.remote-repository-configuration.v1": patch +"@wso2is/admin.alternative-login-identifier.v1": patch +"@wso2is/admin.authentication-flow-builder.v1": patch +"@wso2is/admin.organization-discovery.v1": patch +"@wso2is/admin.policy-administration.v1": patch +"@wso2is/admin.server-configurations.v1": patch +"@wso2is/admin.saml2-configuration.v1": patch +"@wso2is/admin.username-validation.v1": patch +"@wso2is/admin.wsfed-configuration.v1": patch +"@wso2is/admin.identity-providers.v1": patch +"@wso2is/admin.session-management.v1": patch +"@wso2is/admin.workflow-approvals.v1": patch +"@wso2is/admin.remote-userstores.v1": patch +"@wso2is/admin.console-settings.v1": patch +"@wso2is/admin.email-management.v1": patch +"@wso2is/admin.email-providers.v1": patch +"@wso2is/admin.email-templates.v1": patch +"@wso2is/admin.private-key-jwt.v1": patch +"@wso2is/admin.administrators.v1": patch +"@wso2is/admin.api-resources.v1": patch +"@wso2is/admin.api-resources.v2": patch +"@wso2is/admin.authorization.v1": patch +"@wso2is/admin.email-and-sms.v1": patch +"@wso2is/admin.impersonation.v1": patch +"@wso2is/admin.login-flow.ai.v1": patch +"@wso2is/admin.organizations.v1": patch +"@wso2is/admin.sms-providers.v1": patch +"@wso2is/admin.sms-templates.v1": patch +"@wso2is/admin.applications.v1": patch +"@wso2is/admin.certificates.v1": patch +"@wso2is/admin.feature-gate.v1": patch +"@wso2is/admin.org-insights.v1": patch +"@wso2is/admin.provisioning.v1": patch +"@wso2is/admin.subscription.v1": patch +"@wso2is/admin.branding.ai.v1": patch +"@wso2is/admin.connections.v1": patch +"@wso2is/admin.oidc-scopes.v1": patch +"@wso2is/admin.extensions.v1": patch +"@wso2is/admin.userstores.v1": patch +"@wso2is/admin.validation.v1": patch +"@wso2is/common.branding.v1": patch +"@wso2is/admin.branding.v1": patch +"@wso2is/admin.actions.v1": patch +"@wso2is/admin.secrets.v1": patch +"@wso2is/admin.tenants.v1": patch +"@wso2is/admin.claims.v1": patch +"@wso2is/admin.groups.v1": patch +"@wso2is/react-components": patch +"@wso2is/admin.roles.v1": patch +"@wso2is/admin.roles.v2": patch +"@wso2is/admin.users.v1": patch +"@wso2is/admin.core.v1": patch +"@wso2is/admin.home.v1": patch +"@wso2is/admin.logs.v1": patch +"@wso2is/common.ai.v1": patch +"@wso2is/dynamic-forms": patch +"@wso2is/identity-apps-core": patch +"@wso2is/myaccount": patch +"@wso2is/console": patch +"@wso2is/i18n": patch +"@wso2is/features": patch +--- + +Bump oxygen version diff --git a/.changeset/witty-ants-allow.md b/.changeset/witty-ants-allow.md new file mode 100644 index 00000000000..1bb10e3ef05 --- /dev/null +++ b/.changeset/witty-ants-allow.md @@ -0,0 +1,10 @@ +--- +"@wso2is/admin.policy-administration.v1": major +"@wso2is/react-components": patch +"@wso2is/admin.core.v1": patch +"@wso2is/console": patch +"@wso2is/i18n": patch +"@wso2is/features": patch +--- + +Introduce policyAdministration UI. diff --git a/apps/console/package.json b/apps/console/package.json index a6bf36ef3c1..c8f197d3e60 100644 --- a/apps/console/package.json +++ b/apps/console/package.json @@ -44,8 +44,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.actions.v1": "^1.7.40", "@wso2is/admin.administrators.v1": "^2.29.83", @@ -77,6 +77,7 @@ "@wso2is/admin.private-key-jwt.v1": "^2.25.83", "@wso2is/admin.remote-repository-configuration.v1": "^2.25.83", "@wso2is/admin.impersonation.v1": "^1.6.83", + "@wso2is/admin.policy-administration.v1": "^0.0.0", "@wso2is/admin.remote-userstores.v1": "^1.7.39", "@wso2is/admin.roles.v1": "^2.25.83", "@wso2is/admin.roles.v2": "^2.27.27", diff --git a/apps/console/src/configs/routes.tsx b/apps/console/src/configs/routes.tsx index 63bd3cc5ec0..0edf022e722 100644 --- a/apps/console/src/configs/routes.tsx +++ b/apps/console/src/configs/routes.tsx @@ -115,6 +115,31 @@ export const getAppViewRoutes = (): RouteInterface[] => { protected: true, showOnSidePanel: true }, + { + category: "console:common.sidePanel.policyAdministration", + children: [ + { + component: lazy(() => import("@wso2is/admin.policy-administration.v1/pages/edit-policy")), + exact: true, + id: "editPolicy", + name: "Edit Policy", + path: AppConstants.getPaths().get("EDIT_POLICY"), + protected: true, + showOnSidePanel: false + } + ], + component: lazy(() => import("@wso2is/admin.policy-administration.v1/pages/policy-administration")), + exact: true, + icon: { + icon: getSidePanelIcons().policyAdministration + }, + id: "policyAdministration", + name: "Policy Administration", + order: 30, + path: AppConstants.getPaths().get("POLICY_ADMINISTRATION"), + protected: true, + showOnSidePanel: true + }, { category: "console:develop.features.sidePanel.categories.application", children: [ diff --git a/apps/console/src/public/deployment.config.json b/apps/console/src/public/deployment.config.json index 63d4449d226..c4350243350 100644 --- a/apps/console/src/public/deployment.config.json +++ b/apps/console/src/public/deployment.config.json @@ -891,6 +891,7 @@ "scopes": { "create": [], "delete": [], + "feature": [], "read": [], "update": [] } diff --git a/apps/myaccount/package.json b/apps/myaccount/package.json index 7f74b7da0a8..713db71984d 100644 --- a/apps/myaccount/package.json +++ b/apps/myaccount/package.json @@ -39,8 +39,8 @@ "@babel/polyfill": "^7.0.0", "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.organizations.v1": "^2.26.83", "@wso2is/common.branding.v1": "^2.25.56", diff --git a/features/admin.actions.v1/package.json b/features/admin.actions.v1/package.json index 24a5612560e..72db91eb116 100644 --- a/features/admin.actions.v1/package.json +++ b/features/admin.actions.v1/package.json @@ -8,8 +8,8 @@ "dependencies": { "@asgardeo/auth-react": "^5.1.2", "@mui/material": "^5.13.0", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.extensions.v1": "^2.36.8", diff --git a/features/admin.administrators.v1/package.json b/features/admin.administrators.v1/package.json index fbef8c57665..fc9c2b723de 100644 --- a/features/admin.administrators.v1/package.json +++ b/features/admin.administrators.v1/package.json @@ -30,7 +30,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.authentication.v1": "workspace:^2.25.83", diff --git a/features/admin.alternative-login-identifier.v1/package.json b/features/admin.alternative-login-identifier.v1/package.json index 13dcd5392fa..ce43c4fcfbd 100644 --- a/features/admin.alternative-login-identifier.v1/package.json +++ b/features/admin.alternative-login-identifier.v1/package.json @@ -30,7 +30,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.claims.v1": "^2.26.42", "@wso2is/admin.core.v1": "^2.35.21", diff --git a/features/admin.api-resources.v1/package.json b/features/admin.api-resources.v1/package.json index 6271d9cd6fa..c9d3e9ba010 100644 --- a/features/admin.api-resources.v1/package.json +++ b/features/admin.api-resources.v1/package.json @@ -14,7 +14,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/core": "^2.5.5", "@wso2is/form": "^2.6.12", diff --git a/features/admin.api-resources.v2/package.json b/features/admin.api-resources.v2/package.json index e50f82a05ec..896e723e86a 100644 --- a/features/admin.api-resources.v2/package.json +++ b/features/admin.api-resources.v2/package.json @@ -14,8 +14,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/core": "^2.5.5", "@wso2is/form": "^2.6.12", diff --git a/features/admin.applications.v1/package.json b/features/admin.applications.v1/package.json index d57769e84ba..55f56996d6f 100644 --- a/features/admin.applications.v1/package.json +++ b/features/admin.applications.v1/package.json @@ -14,8 +14,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.api-resources.v2": "^2.25.83", "@wso2is/admin.authentication-flow-builder.v1": "^2.24.83", diff --git a/features/admin.authentication-flow-builder.v1/components/script-editor-panel/script-editor-panel.tsx b/features/admin.authentication-flow-builder.v1/components/script-editor-panel/script-editor-panel.tsx index 2168cd0aa4e..c6872f53818 100644 --- a/features/admin.authentication-flow-builder.v1/components/script-editor-panel/script-editor-panel.tsx +++ b/features/admin.authentication-flow-builder.v1/components/script-editor-panel/script-editor-panel.tsx @@ -287,7 +287,7 @@ const ScriptEditorPanel = (props: PropsWithChildren
{ secretMgtFeatureConfig?.enabled && -hasSecretReadPermissions && ( + hasSecretReadPermissions && ( setIsSecretSelectionDropdownOpen(false) } diff --git a/features/admin.authentication-flow-builder.v1/package.json b/features/admin.authentication-flow-builder.v1/package.json index 523500977b4..e8aa784ca04 100644 --- a/features/admin.authentication-flow-builder.v1/package.json +++ b/features/admin.authentication-flow-builder.v1/package.json @@ -14,8 +14,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/core": "^2.5.5", "@wso2is/react-components": "^2.8.19", "@wso2is/admin.applications.v1": "^2.30.83", diff --git a/features/admin.authorization.v1/package.json b/features/admin.authorization.v1/package.json index 3fe8415ad55..1a1fa95112c 100644 --- a/features/admin.authorization.v1/package.json +++ b/features/admin.authorization.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/core": "^2.5.5", "@wso2is/dynamic-forms": "^2.4.19", diff --git a/features/admin.branding.ai.v1/package.json b/features/admin.branding.ai.v1/package.json index 6ab2eb9304e..abe011b5934 100644 --- a/features/admin.branding.ai.v1/package.json +++ b/features/admin.branding.ai.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.branding.v1": "^2.27.56", "@wso2is/admin.core.v1": "^2.35.21", diff --git a/features/admin.branding.v1/package.json b/features/admin.branding.v1/package.json index fa141279300..1fa1695fbae 100644 --- a/features/admin.branding.v1/package.json +++ b/features/admin.branding.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.branding.ai.v1": "^2.26.83", "@wso2is/admin.core.v1": "^2.35.21", diff --git a/features/admin.certificates.v1/package.json b/features/admin.certificates.v1/package.json index ab0d742e4f8..113510d49d3 100644 --- a/features/admin.certificates.v1/package.json +++ b/features/admin.certificates.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/admin.claims.v1/package.json b/features/admin.claims.v1/package.json index 3a31d5714fb..08e267ac5ec 100644 --- a/features/admin.claims.v1/package.json +++ b/features/admin.claims.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.claims.v1": "^2.26.42", "@wso2is/admin.core.v1": "^2.35.21", diff --git a/features/admin.connections.v1/package.json b/features/admin.connections.v1/package.json index ceb9a09ab36..7d820af8be8 100644 --- a/features/admin.connections.v1/package.json +++ b/features/admin.connections.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.claims.v1": "^2.26.42", diff --git a/features/admin.console-settings.v1/package.json b/features/admin.console-settings.v1/package.json index dfb15c9331f..7a8f814073c 100644 --- a/features/admin.console-settings.v1/package.json +++ b/features/admin.console-settings.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.administrators.v1": "^2.29.83", "@wso2is/admin.applications.v1": "^2.30.83", diff --git a/features/admin.core.v1/configs/app.ts b/features/admin.core.v1/configs/app.ts index 13b0d61e43e..af501cab09b 100644 --- a/features/admin.core.v1/configs/app.ts +++ b/features/admin.core.v1/configs/app.ts @@ -34,6 +34,7 @@ import { getScopesResourceEndpoints } from "@wso2is/admin.oidc-scopes.v1"; import { getInsightsResourceEndpoints } from "@wso2is/admin.org-insights.v1/config/org-insights"; import { getOrganizationsResourceEndpoints } from "@wso2is/admin.organizations.v1/configs"; import { OrganizationUtils } from "@wso2is/admin.organizations.v1/utils"; +import { getPolicyAdministrationResourceEndpoints } from "@wso2is/admin.policy-administration.v1/configs"; import { getRemoteFetchConfigResourceEndpoints } from "@wso2is/admin.remote-repository-configuration.v1"; import { getRolesResourceEndpoints } from "@wso2is/admin.roles.v2/configs/endpoints"; import { getSecretsManagementEndpoints } from "@wso2is/admin.secrets.v1/configs/endpoints"; @@ -211,6 +212,7 @@ export class Config { I18nConstants.APPLICATION_TEMPLATES_NAMESPACE, I18nConstants.ACTIONS_NAMESPACE, I18nConstants.TENANTS_NAMESPACE, + I18nConstants.POLICY_ADMINISTRATION_NAMESPACE, I18nConstants.REMOTE_USER_STORES_NAMESPACE ], preload: [] @@ -270,6 +272,7 @@ export class Config { ...getApplicationTemplatesResourcesEndpoints(this.resolveServerHost()), ...getActionsResourceEndpoints(this.resolveServerHost()), ...getSmsTemplateResourceEndpoints(this.resolveServerHost()), + ...getPolicyAdministrationResourceEndpoints(this.resolveServerHost()), CORSOrigins: `${ this.getDeploymentConfig()?.serverHost }/api/server/v1/cors/origins`, // TODO: Remove this endpoint and use ID token to get the details me: `${ this.getDeploymentConfig()?.serverHost }/scim2/Me`, diff --git a/features/admin.core.v1/configs/ui.ts b/features/admin.core.v1/configs/ui.ts index 76e6c226c5a..e8f126ab0cd 100644 --- a/features/admin.core.v1/configs/ui.ts +++ b/features/admin.core.v1/configs/ui.ts @@ -250,6 +250,7 @@ export const getTechnologyLogos = (): GetTechnologyLogosInterface => { */ export type GetSidePanelIconsInterface = { adminAdvisoryBanner: FunctionComponent | ReactNode, + policyAdministration: FunctionComponent | ReactNode, administrators: FunctionComponent | ReactNode, apiResources: FunctionComponent | ReactNode, applicationRoles: FunctionComponent | ReactNode, @@ -294,6 +295,7 @@ export const getSidePanelIcons = (): GetSidePanelIconsInterface => { return { adminAdvisoryBanner: AdminAdvisoryBannerIcon, administrators: AdminOutlineIcon, + policyAdministration: AdminOutlineIcon, apiResources: CloudConnectionOutlineIcon, appLogs: IDPMetadataIcon, applicationRoles: ApplicationRolesIcon, diff --git a/features/admin.core.v1/constants/app-constants.ts b/features/admin.core.v1/constants/app-constants.ts index 0e5fd4277ab..82c1690be4d 100644 --- a/features/admin.core.v1/constants/app-constants.ts +++ b/features/admin.core.v1/constants/app-constants.ts @@ -411,7 +411,9 @@ export class AppConstants { `${ AppConstants.getAdminViewBasePath()}/actions/pre-issue-access-token` ], [ "TENANTS", `${AppConstants.getDefaultLayoutBasePath()}/organizations` ], [ "EDIT_TENANT", `${AppConstants.getDefaultLayoutBasePath()}/organizations/:id` ], - [ "SYSTEM_SETTINGS", `${AppConstants.getDefaultLayoutBasePath()}/organizations/system-settings` ] + [ "SYSTEM_SETTINGS", `${AppConstants.getDefaultLayoutBasePath()}/organizations/system-settings` ], + [ "POLICY_ADMINISTRATION", `${AppConstants.getAdminViewBasePath()}/policy-administration` ], + [ "EDIT_POLICY", `${AppConstants.getAdminViewBasePath()}/policy-administration/edit-policy/:id` ] ]); return paths; diff --git a/features/admin.core.v1/constants/i18n-constants.ts b/features/admin.core.v1/constants/i18n-constants.ts index 3d9f1c6229d..ddc00872825 100644 --- a/features/admin.core.v1/constants/i18n-constants.ts +++ b/features/admin.core.v1/constants/i18n-constants.ts @@ -276,6 +276,12 @@ export class I18nConstants { */ public static readonly REMOTE_USER_STORES_NAMESPACE: string = I18nModuleConstants.REMOTE_USER_STORES_NAMESPACE; + + /** + * Policy Administration namespace. + */ + public static readonly POLICY_ADMINISTRATION_NAMESPACE: string = I18nModuleConstants.POLICY_ADMINISTRATION_NAMESPACE; + /** * Locations of the I18n namespaces. */ @@ -327,6 +333,7 @@ export class I18nConstants { [ I18nConstants.IMPERSONATION_CONFIGURATION_NAMESPACE, "portals" ], [ I18nConstants.ACTIONS_NAMESPACE, "portals" ], [ I18nConstants.TENANTS_NAMESPACE, "portals" ], + [ I18nConstants.POLICY_ADMINISTRATION_NAMESPACE, "portals" ], [ I18nConstants.REMOTE_USER_STORES_NAMESPACE, "portals" ] ]); diff --git a/features/admin.core.v1/models/config.ts b/features/admin.core.v1/models/config.ts index 960a81c38cd..9d1cca732a6 100644 --- a/features/admin.core.v1/models/config.ts +++ b/features/admin.core.v1/models/config.ts @@ -30,6 +30,7 @@ import { ConnectionResourceEndpointsInterface } from "@wso2is/admin.connections. import { GroupsResourceEndpointsInterface } from "@wso2is/admin.groups.v1/models/endpoints"; import { ScopesResourceEndpointsInterface } from "@wso2is/admin.oidc-scopes.v1"; import { OrganizationResourceEndpointsInterface } from "@wso2is/admin.organizations.v1/models"; +import { PolicyAdministrationEndpointsInterface } from "@wso2is/admin.policy-administration.v1/models/endpoints"; import { RolesResourceEndpointsInterface } from "@wso2is/admin.roles.v2/models/endpoints"; import { SecretsManagementEndpoints } from "@wso2is/admin.secrets.v1/models/endpoints"; import { ServerConfigurationsResourceEndpointsInterface } from "@wso2is/admin.server-configurations.v1"; @@ -575,8 +576,8 @@ export interface ServiceResourceEndpointsInterface extends ClaimResourceEndpoint ExtensionTemplatesEndpointsInterface, ApplicationsTemplatesEndpointsInterface, SMSTemplateResourceEndpointsInterface, - ActionsResourceEndpointsInterface { - + ActionsResourceEndpointsInterface, + PolicyAdministrationEndpointsInterface { CORSOrigins: string; // TODO: Remove this endpoint and use ID token to get the details me: string; diff --git a/features/admin.core.v1/package.json b/features/admin.core.v1/package.json index 310f6dbe85b..21fb7e821e3 100644 --- a/features/admin.core.v1/package.json +++ b/features/admin.core.v1/package.json @@ -13,8 +13,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.actions.v1": "^1.7.40", "@wso2is/admin.administrators.v1": "^2.29.83", @@ -41,6 +41,7 @@ "@wso2is/admin.org-insights.v1": "^2.25.83", "@wso2is/admin.organization-discovery.v1": "^2.25.83", "@wso2is/admin.organizations.v1": "^2.26.83", + "@wso2is/admin.policy-administration.v1": "^0.0.0", "@wso2is/admin.private-key-jwt.v1": "^2.25.83", "@wso2is/admin.impersonation.v1": "^1.6.83", "@wso2is/admin.remote-repository-configuration.v1": "^2.25.83", diff --git a/features/admin.core.v1/store/reducers/config.ts b/features/admin.core.v1/store/reducers/config.ts index 6bad5289778..b3046ee9b6a 100644 --- a/features/admin.core.v1/store/reducers/config.ts +++ b/features/admin.core.v1/store/reducers/config.ts @@ -103,9 +103,12 @@ export const commonConfigReducerInitialState: CommonConfigReducerStateInterface< clientCertificates: "", createSecret: "", createSecretType: "", - dcrConfiguration:"", + dcrConfiguration: "", deleteSecret: "", deleteSecretType: "", + entitlementPoliciesApi: "", + entitlementPolicyCombiningAlgorithmApi: "", + entitlementPolicyPublishApi: "", extensionTemplates: "", extensions: "", externalClaims: "", diff --git a/features/admin.email-and-sms.v1/package.json b/features/admin.email-and-sms.v1/package.json index 80f9c54eec7..16e613dd84a 100644 --- a/features/admin.email-and-sms.v1/package.json +++ b/features/admin.email-and-sms.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.organizations.v1": "^2.26.83", diff --git a/features/admin.email-management.v1/package.json b/features/admin.email-management.v1/package.json index dea0012fcd1..0d4048c133f 100644 --- a/features/admin.email-management.v1/package.json +++ b/features/admin.email-management.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.branding.v1": "^2.27.56", "@wso2is/admin.core.v1": "^2.35.21", diff --git a/features/admin.email-providers.v1/package.json b/features/admin.email-providers.v1/package.json index aa267d094a8..94888c9bb71 100644 --- a/features/admin.email-providers.v1/package.json +++ b/features/admin.email-providers.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/admin.email-templates.v1/package.json b/features/admin.email-templates.v1/package.json index d4c19010ff0..3c31f2c6b1e 100644 --- a/features/admin.email-templates.v1/package.json +++ b/features/admin.email-templates.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.organizations.v1": "^2.26.83", diff --git a/features/admin.extensions.v1/package.json b/features/admin.extensions.v1/package.json index bfd6f91755b..002e51e487d 100644 --- a/features/admin.extensions.v1/package.json +++ b/features/admin.extensions.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.api-resources.v1": "^2.25.83", "@wso2is/admin.applications.v1": "^2.30.83", diff --git a/features/admin.feature-gate.v1/package.json b/features/admin.feature-gate.v1/package.json index 6af82b163af..741f7b96813 100644 --- a/features/admin.feature-gate.v1/package.json +++ b/features/admin.feature-gate.v1/package.json @@ -30,7 +30,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.organizations.v1": "^2.26.83", "@wso2is/access-control": "^3.3.9", diff --git a/features/admin.groups.v1/package.json b/features/admin.groups.v1/package.json index 7fe2c197132..ab975cbcdbe 100644 --- a/features/admin.groups.v1/package.json +++ b/features/admin.groups.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.authorization.v1": "^2.25.33", diff --git a/features/admin.home.v1/package.json b/features/admin.home.v1/package.json index edfcbd991c2..a95794fcc1a 100644 --- a/features/admin.home.v1/package.json +++ b/features/admin.home.v1/package.json @@ -30,7 +30,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.extensions.v1": "^2.36.8", diff --git a/features/admin.identity-providers.v1/package.json b/features/admin.identity-providers.v1/package.json index 74480e399df..66810f5515f 100644 --- a/features/admin.identity-providers.v1/package.json +++ b/features/admin.identity-providers.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.claims.v1": "^2.26.42", diff --git a/features/admin.identity-verification-providers.v1/package.json b/features/admin.identity-verification-providers.v1/package.json index 4e3ad770b02..7f4f792642d 100644 --- a/features/admin.identity-verification-providers.v1/package.json +++ b/features/admin.identity-verification-providers.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.claims.v1": "^2.26.42", "@wso2is/admin.connections.v1": "^2.30.19", diff --git a/features/admin.impersonation.v1/package.json b/features/admin.impersonation.v1/package.json index d10d397e1ed..4eea8ebd79e 100644 --- a/features/admin.impersonation.v1/package.json +++ b/features/admin.impersonation.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.server-configurations.v1": "^2.32.8", diff --git a/features/admin.login-flow.ai.v1/package.json b/features/admin.login-flow.ai.v1/package.json index a7ef14ab09a..d35ea45e608 100644 --- a/features/admin.login-flow.ai.v1/package.json +++ b/features/admin.login-flow.ai.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.claims.v1": "^2.26.42", diff --git a/features/admin.logs.v1/package.json b/features/admin.logs.v1/package.json index 551134d049c..fb2e678b6ba 100644 --- a/features/admin.logs.v1/package.json +++ b/features/admin.logs.v1/package.json @@ -30,7 +30,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", "@wso2is/form": "^2.6.12", diff --git a/features/admin.oidc-scopes.v1/package.json b/features/admin.oidc-scopes.v1/package.json index 94d4af02222..5f3e57a6f71 100644 --- a/features/admin.oidc-scopes.v1/package.json +++ b/features/admin.oidc-scopes.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.claims.v1": "^2.26.42", diff --git a/features/admin.org-insights.v1/package.json b/features/admin.org-insights.v1/package.json index 65ad004c78f..9f192b6c9cb 100644 --- a/features/admin.org-insights.v1/package.json +++ b/features/admin.org-insights.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/admin.organization-discovery.v1/package.json b/features/admin.organization-discovery.v1/package.json index 690a9bcca1e..baf48a0a176 100644 --- a/features/admin.organization-discovery.v1/package.json +++ b/features/admin.organization-discovery.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.organizations.v1": "^2.26.83", diff --git a/features/admin.organizations.v1/package.json b/features/admin.organizations.v1/package.json index b245238f40b..c0d11f6e203 100644 --- a/features/admin.organizations.v1/package.json +++ b/features/admin.organizations.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.authentication.v1": "^2.25.83", diff --git a/features/admin.policy-administration.v1/api/entitlement-policies.ts b/features/admin.policy-administration.v1/api/entitlement-policies.ts new file mode 100644 index 00000000000..d7eb9abffc1 --- /dev/null +++ b/features/admin.policy-administration.v1/api/entitlement-policies.ts @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + AsgardeoSPAClient, + HttpClientInstance, HttpError, HttpRequestConfig, HttpResponse +} from "@asgardeo/auth-react"; +import { RequestConfigInterface } from "@wso2is/admin.core.v1/hooks/use-request"; +import { store } from "@wso2is/admin.core.v1/store"; +import { HttpMethods } from "@wso2is/core/models"; +import { AxiosError, AxiosResponse } from "axios"; +import { PolicyInterface, PublishPolicyDataInterface } from "../models/policies"; + +/** + * Get an HTTP client instance. + */ +const httpClient: HttpClientInstance = AsgardeoSPAClient.getInstance().httpRequest.bind( + AsgardeoSPAClient.getInstance() +); + +/** + * Function to create a new policy. + * + * @param policyData - The policy data to be created. + * @returns A promise containing the response. + */ +export const createPolicy = ( + policyData: PolicyInterface +): Promise> => { + + const requestConfig: HttpRequestConfig = { + data: policyData, + headers: { + "Accept": "application/json", + "Content-Type": "application/json" + }, + method: HttpMethods.POST, + url: store.getState().config.endpoints.entitlementPoliciesApi + }; + + return httpClient(requestConfig) + .then((response: HttpResponse) => { + if (response.status !== 200) { + return Promise.reject(new Error("Failed to create the policy.")); + } + + return Promise.resolve(response?.data); + }) + .catch((error: HttpError) => { + return Promise.reject(error); + }); +}; + +/** + * Update an existing policy with new data. + * + * @param policyData - The policy data to be updated (payload). + * @returns A promise containing the updated policy data. + */ +export const updatePolicy = ( + policyData: Partial +): Promise => { + + const requestConfig: RequestConfigInterface = { + data: policyData, + headers: { + Accept: "application/json", + "Content-Type": "application/json" + }, + method: HttpMethods.PATCH, + url: store.getState().config.endpoints.entitlementPoliciesApi + }; + + return httpClient(requestConfig) + .then((response: AxiosResponse) => { + if (response.status !== 200) { + return Promise.reject( + new Error("Failed to update policy: " + policyData.policyId) + ); + } + + return Promise.resolve(response.data); + }) + .catch((error: AxiosError) => { + return Promise.reject(error); + }); +}; + +/** + * Deletes a policy when the relevant policy ID is passed in. + * + * @param policyId - ID of the policy to be deleted. + * @returns A promise containing the response. + */ +export const deletePolicy = (policyId: string): Promise => { + + const requestConfig: HttpRequestConfig = { + headers: { + "Accept": "application/json", + "Content-Type": "application/json" + }, + method: HttpMethods.DELETE, + url: `${store.getState().config.endpoints.entitlementPoliciesApi}/${policyId}` + }; + + return httpClient(requestConfig) + .then((response: HttpResponse) => { + if (response.status !== 200 && response.status !== 204) { + return Promise.reject(new Error("Failed to delete the policy.")); + } + + return Promise.resolve(response?.data); + }) + .catch((error: HttpError) => { + return Promise.reject(error); + }); +}; + +/** + * Function to publish (create) a policy using the given request data. + * + * @param requestData - The data needed to publish the policy. + * @returns A promise containing the response or an error. + */ +export const publishPolicy = ( + requestData: PublishPolicyDataInterface +): Promise> => { + + const requestConfig: HttpRequestConfig = { + data: requestData, + headers: { + "Accept": "application/json", + "Content-Type": "application/json" + }, + method: HttpMethods.POST, + url: store.getState().config.endpoints.entitlementPolicyPublishApi + }; + + return httpClient(requestConfig) + .then((response: HttpResponse) => { + if (response.status !== 200) { + return Promise.reject(new Error("Failed to publish the policy.")); + } + + return Promise.resolve(response.data); + }) + .catch((error: HttpError) => { + return Promise.reject(error); + }); +}; diff --git a/features/admin.policy-administration.v1/api/update-algorithm.ts b/features/admin.policy-administration.v1/api/update-algorithm.ts new file mode 100644 index 00000000000..b7ac7389a52 --- /dev/null +++ b/features/admin.policy-administration.v1/api/update-algorithm.ts @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { AsgardeoSPAClient, HttpClientInstance } from "@asgardeo/auth-react"; +import { RequestConfigInterface } from "@wso2is/admin.core.v1/hooks/use-request"; +import { store } from "@wso2is/admin.core.v1/store"; +import { HttpMethods } from "@wso2is/core/models"; +import { AxiosError, AxiosResponse } from "axios"; +import { PolicyAlgorithmRequestInterface } from "../models/policies"; + +/** + * Get an httpClient instance. + */ +const httpClient: HttpClientInstance = AsgardeoSPAClient.getInstance() + .httpRequest.bind(AsgardeoSPAClient.getInstance()) + +/** + * Function to update the policy combining algorithm. + * + * @param policyCombiningAlgorithm - The policy combining algorithm to be updated. + */ +export const updateAlgorithm = ( + policyCombiningAlgorithm: PolicyAlgorithmRequestInterface +) : Promise => { + const requestConfig: RequestConfigInterface = { + data: policyCombiningAlgorithm, + headers: { + Accept: "application/json", + "Content-Type": "application/json" + }, + method: HttpMethods.PATCH, + url: `${store.getState().config.endpoints.entitlementPolicyCombiningAlgorithmApi}` + }; + + return httpClient(requestConfig) + .then((response: AxiosResponse) => { + if (response.status !== 200) { + return Promise.reject(new Error("Failed to update the policy combining algorithm.")); + } + + return Promise.resolve(response); + }) + .catch((error: AxiosError) => { + return Promise.reject(error); + }); +}; diff --git a/features/admin.policy-administration.v1/api/use-get-algorithm.ts b/features/admin.policy-administration.v1/api/use-get-algorithm.ts new file mode 100644 index 00000000000..b8949f2a496 --- /dev/null +++ b/features/admin.policy-administration.v1/api/use-get-algorithm.ts @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import useRequest, { + RequestConfigInterface, + RequestErrorInterface, + RequestResultInterface +} from "@wso2is/admin.core.v1/hooks/use-request"; +import { store } from "@wso2is/admin.core.v1/store"; +import { HttpMethods } from "@wso2is/core/models"; +import { AlgorithmResponseInterface } from "../models/policies"; + +/** + * Fetches the policy combining algorithm. + * + * @param {boolean} shouldFetch - Flag to determine if the data should be fetched. + * @return {RequestResultInterface} Response as a promise. + */ +export const useGetAlgorithm = ( + shouldFetch: boolean = true +): RequestResultInterface => { + const requestConfig: RequestConfigInterface = { + headers: { + Accept: "application/json", + "Content-Type": "application/json" + }, + method: HttpMethods.GET, + url: `${store.getState().config.endpoints.entitlementPolicyCombiningAlgorithmApi}` + }; + + const { data, error, isValidating, mutate, isLoading } = useRequest(shouldFetch ? requestConfig : null, { + shouldRetryOnError: false + }); + + return { + data, + error, + isLoading, + isValidating, + mutate + }; +}; diff --git a/features/admin.policy-administration.v1/api/use-get-policies.ts b/features/admin.policy-administration.v1/api/use-get-policies.ts new file mode 100644 index 00000000000..c992429346d --- /dev/null +++ b/features/admin.policy-administration.v1/api/use-get-policies.ts @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import useRequest, { + RequestConfigInterface, + RequestErrorInterface, + RequestResultInterface +} from "@wso2is/admin.core.v1/hooks/use-request"; +import { store } from "@wso2is/admin.core.v1/store"; +import { HttpMethods } from "@wso2is/core/models"; +import { PolicyListInterface } from "../models/policies"; + +/** + * Hook to get the list of policies. + * + * @param shouldFetch - Should fetch the data. + * @param pageNumber - Pagination limit. + * @param isPDPPolicy - Is PDP policy. + * @param policySearchString - Search filter. + * @param policyType - Policy type. (Policy/PolicySet) + * @returns SWR response object containing the data, error, isValidating, mutate. + */ +export const useGetPolicies = < + Data = PolicyListInterface, + Error = RequestErrorInterface>( + shouldFetch: boolean, + pageNumber: number, + isPDPPolicy: boolean, + policySearchString: string, + policyType: string + ): RequestResultInterface => { + const requestConfig: RequestConfigInterface = { + headers: { + Accept: "application/json", + "Content-Type": "application/json" + }, + method: HttpMethods.GET, + params: { + isPDPPolicy, + pageNumber, + policySearchString, + policyType + }, + url: `${store.getState().config.endpoints.entitlementPoliciesApi}` + }; + + const { data, error, isValidating, mutate, isLoading } = useRequest(shouldFetch ? requestConfig : null, { + shouldRetryOnError: false + }); + + return { + data, + error, + isLoading, + isValidating, + mutate + }; +}; diff --git a/features/admin.policy-administration.v1/api/use-get-policy.ts b/features/admin.policy-administration.v1/api/use-get-policy.ts new file mode 100644 index 00000000000..98cf501095e --- /dev/null +++ b/features/admin.policy-administration.v1/api/use-get-policy.ts @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import useRequest, { + RequestConfigInterface, + RequestErrorInterface, + RequestResultInterface +} from "@wso2is/admin.core.v1/hooks/use-request"; +import { store } from "@wso2is/admin.core.v1/store"; +import { HttpMethods } from "@wso2is/core/models"; +import { PolicyInterface } from "../models/policies"; + +/** + * Hook to fetch a specific policy by its ID. + * + * @param policyId - The ID of the policy to fetch. + * @param shouldFetch - Should fetch the data. + * @returns SWR response object containing the data, error, isValidating, mutate. + */ +export const useGetPolicy = < + Data = PolicyInterface, + Error = RequestErrorInterface>( + policyId: string, + shouldFetch: boolean = true + ): RequestResultInterface => { + const requestConfig: RequestConfigInterface = { + headers: { + Accept: "application/json", + "Content-Type": "application/json" + }, + method: HttpMethods.GET, + url: `${store.getState().config.endpoints.entitlementPoliciesApi}/${policyId}` + }; + + const { data, error, isValidating, mutate, isLoading } = useRequest(shouldFetch ? requestConfig : null, { + shouldRetryOnError: false + }); + + return { + data, + error, + isLoading, + isValidating, + mutate + }; +}; diff --git a/features/admin.policy-administration.v1/components/edit-policy-algorithm/edit-policy-algorithm.scss b/features/admin.policy-administration.v1/components/edit-policy-algorithm/edit-policy-algorithm.scss new file mode 100644 index 00000000000..0b772db5991 --- /dev/null +++ b/features/admin.policy-administration.v1/components/edit-policy-algorithm/edit-policy-algorithm.scss @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.policy-algorithm-modal { + .algorithm-content { + height: 300px; + width: 468px; + .algorithm-dropdown{ + margin-top: 12px; + width: 100%; + } + .algorithm-description{ + margin-top: 14px; + } + } +} diff --git a/features/admin.policy-administration.v1/components/edit-policy-algorithm/edit-policy-algorithm.tsx b/features/admin.policy-administration.v1/components/edit-policy-algorithm/edit-policy-algorithm.tsx new file mode 100644 index 00000000000..4879efe8303 --- /dev/null +++ b/features/admin.policy-administration.v1/components/edit-policy-algorithm/edit-policy-algorithm.tsx @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FunctionComponent, MouseEvent, ReactElement } from "react"; +import Alert from "@oxygen-ui/react/Alert"; +import Box from "@oxygen-ui/react/Box"; +import Button from "@oxygen-ui/react/Button"; +import Dialog from "@oxygen-ui/react/Dialog"; +import DialogActions from "@oxygen-ui/react/DialogActions"; +import DialogContent from "@oxygen-ui/react/DialogContent"; +import DialogTitle from "@oxygen-ui/react/DialogTitle"; +import MenuItem from "@oxygen-ui/react/MenuItem"; +import Select from "@oxygen-ui/react/Select"; +import Stack from "@oxygen-ui/react/Stack"; +import Typography from "@oxygen-ui/react/Typography/Typography"; +import { AlertLevels, IdentifiableComponentInterface } from "@wso2is/core/models"; +import "./edit-policy-algorithm.scss"; +import { addAlert } from "@wso2is/core/store"; +import { useTranslation } from "react-i18next"; +import { useDispatch } from "react-redux"; +import { Dispatch } from "redux"; +import { updateAlgorithm } from "../../api/update-algorithm"; +import { AlgorithmOption, PolicyAlgorithmRequestInterface } from "../../models/policies"; + +interface EditPolicyAlgorithmProps extends IdentifiableComponentInterface{ + closeModal: () => void; + open: boolean; + selectedAlgorithm: AlgorithmOption; + setSelectedAlgorithm: (algorithm: AlgorithmOption) => void; + algorithmOptions : AlgorithmOption[]; + mutateAlgorithm: () => void; +} + +const EditPolicyAlgorithm: FunctionComponent = ( + props : EditPolicyAlgorithmProps): ReactElement => { + const { + closeModal, + open, + selectedAlgorithm, + setSelectedAlgorithm, + mutateAlgorithm, + algorithmOptions, + [ "data-componentid" ]: componentId + } = props; + const { t } = useTranslation(); + const dispatch: Dispatch = useDispatch(); + + const handleSelectChange = (event) => { + + const selectedAlgorithm: AlgorithmOption = algorithmOptions.find((option: AlgorithmOption) => option.value === event.target.value); + + setSelectedAlgorithm(selectedAlgorithm); + }; + + const selectedOption: AlgorithmOption = algorithmOptions.find(option => option.value === selectedAlgorithm.value); + + const handleUpdate = () => { + const data: PolicyAlgorithmRequestInterface = { + policyCombiningAlgorithm: selectedOption.label + }; + + updateAlgorithm(data).then(() => { + dispatch(addAlert({ + description: "The policy combining algorithm has been updated successfully", + level: AlertLevels.SUCCESS, + message: "Update successful" + })); + + mutateAlgorithm(); + closeModal(); + }).catch( () => { + dispatch(addAlert({ + description: t("idvp:create.notifications.create.genericError.description"), + level: AlertLevels.ERROR, + message: t("idvp:create.notifications.create.genericError.message") + })); + }); + }; + + return ( + + + { t("policyAdministration:policyAlgorithm.title") } + + + + { t("policyAdministration:policyAlgorithm.actionText") } + + + + { selectedOption?.description } + + + + + + + + + + + + ); +}; + +export default EditPolicyAlgorithm; diff --git a/features/admin.policy-administration.v1/components/edit-policy-algorithm/index.ts b/features/admin.policy-administration.v1/components/edit-policy-algorithm/index.ts new file mode 100644 index 00000000000..11608c5554d --- /dev/null +++ b/features/admin.policy-administration.v1/components/edit-policy-algorithm/index.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from "./edit-policy-algorithm"; diff --git a/features/admin.policy-administration.v1/components/policy-administration-page-layout.scss b/features/admin.policy-administration.v1/components/policy-administration-page-layout.scss new file mode 100644 index 00000000000..725835f3765 --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-administration-page-layout.scss @@ -0,0 +1,27 @@ +.policy-algorithm-btn { + padding: 1px 16px; + .algorithm-txt { + margin-left: 4px; + } +} + +.policy-list-card { + background-color: transparent; + padding: 0; +} + +#active-policy-list-container{ + height: 60vh; + overflow-x: hidden; + overflow-y: auto; +} + +#inactive-policy-list-container{ + height: 60vh; + overflow-x: hidden; + overflow-y: auto; +} + +.policy-list-header { + margin-bottom: 15px; +} diff --git a/features/admin.policy-administration.v1/components/policy-administration-page-layout.tsx b/features/admin.policy-administration.v1/components/policy-administration-page-layout.tsx new file mode 100644 index 00000000000..4076e2ef33b --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-administration-page-layout.tsx @@ -0,0 +1,367 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Button from "@oxygen-ui/react/Button"; +import Card from "@oxygen-ui/react/Card"; +import CardContent from "@oxygen-ui/react/CardContent"; +import CircularProgress from "@oxygen-ui/react/CircularProgress"; +import { DnDProvider } from "@oxygen-ui/react/dnd"; +import Grid from "@oxygen-ui/react/Grid"; +import Stack from "@oxygen-ui/react/Stack"; +import Typography from "@oxygen-ui/react/Typography"; +import { GearIcon } from "@oxygen-ui/react-icons"; +import { AdvancedSearchWithBasicFilters } from "@wso2is/admin.core.v1/components/advanced-search-with-basic-filters"; +import { IdentifiableComponentInterface } from "@wso2is/core/models"; +import { + DocumentationLink, + PageLayout, + PrimaryButton, + useDocumentation +} from "@wso2is/react-components"; +import React, { FunctionComponent, ReactElement, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import InfiniteScroll from "react-infinite-scroll-component"; +import { Icon } from "semantic-ui-react"; +import { PolicyList } from "./policy-list"; +import { NewPolicyWizard } from "./wizard/new-policy-wizard"; +import { useGetAlgorithm } from "../api/use-get-algorithm"; +import { useGetPolicies } from "../api/use-get-policies"; +import EditPolicyAlgorithmModal from "../components/edit-policy-algorithm/edit-policy-algorithm"; +import "./policy-administration-page-layout.scss"; +import { AlgorithmOption, PolicyInterface } from "../models/policies"; +import { algorithmOptions } from "../utils/policy-algorithms"; + +/** + * Props interface of {@link PolicyAdministrationPageLayout} + */ +type PolicyAdministrationPageLayoutProps = IdentifiableComponentInterface; + +/** + * Component to wrap the page layout of the tenant listing page that can access the tenant context. + * + * @param props - Props injected to the component. + * @returns Tenant page layout. + */ +const PolicyAdministrationPageLayout: FunctionComponent = ({ + ["data-componentid"]: componentId = "policy-administration-page-layout" +}: PolicyAdministrationPageLayoutProps): ReactElement => { + const { t } = useTranslation(); + const { getLink } = useDocumentation(); + + const [ showAlgorithmModal, setShowAlgorithmModal ] = useState(false); + const [ showWizard, setShowWizard ] = useState(false); + const [ isAlgorithmLoading, setIsAlgorithmLoading ] = useState(false); + const [ selectedAlgorithm, setSelectedAlgorithm ] = useState(); + const [ pageInactive, setPageInactive ] = useState(0); + const [ hasMoreInactivePolicies, setHasMoreInactivePolicies ] = useState(true); + const [ inactivePolicies, setInactivePolicies ] = useState([]); + const [ pageActive, setPageActive ] = useState(0); + const [ hasMoreActivePolicies, setHasMoreActivePolicies ] = useState(true); + const [ activePolicies, setActivePolicies ] = useState([]); + + const { + data: inactivePolicyArray, + isLoading: isLoadingInactivePolicies, + error: inactivePolicyError, + mutate: mutateInactivePolicy + } = useGetPolicies(true, pageInactive, false, "*", "ALL"); + + const { + data: activePolicyArray, + isLoading: isLoadingActivePolicies, + error: activePolicyError, + mutate: mutateActivePolicy + } = useGetPolicies(true, pageActive, true, "*", "ALL"); + + const { + data: algorithm, + isLoading: isLoadingAlgorithm, + error: getAlgorithmError, + mutate: mutateAlgorithm + } = useGetAlgorithm(); + + useEffect(() => { + if (algorithm) { + const selectedAlgorithm: AlgorithmOption = + algorithmOptions.find((option: AlgorithmOption) => option.label === algorithm); + + setSelectedAlgorithm(selectedAlgorithm); + setIsAlgorithmLoading(false); + } else { + setIsAlgorithmLoading(true); + } + }, [ algorithm ]); + + useEffect(() => { + if (!inactivePolicyArray) { + return; + } + + const activePolicyIds: string[] = activePolicies.map( + ((activePolicy: PolicyInterface) => activePolicy.policyId) + ); + + const filteredInactivePolicies: PolicyInterface[] = (inactivePolicyArray.policySet ?? []) + .filter((policy: PolicyInterface) => + policy !== null && !activePolicyIds.includes(policy.policyId) + ); + + if (pageInactive === 0) { + setInactivePolicies(filteredInactivePolicies); + } else { + setInactivePolicies( + (prev: PolicyInterface[]): PolicyInterface[] => [ ...prev, ...filteredInactivePolicies ] + ); + } + + if ((pageInactive + 1) >= (inactivePolicyArray.numberOfPages ?? 1)) { + setHasMoreInactivePolicies(false); + } + + }, [ inactivePolicyArray, activePolicyArray ]); + + useEffect(() => { + if (!activePolicyArray){ + return; + } + + const rawActivePolicies: PolicyInterface[] = activePolicyArray.policySet?.filter( + (policy: PolicyInterface) => policy !== null) || []; + + if (pageActive === 0) { + setActivePolicies(rawActivePolicies); + } else { + setActivePolicies((prev: PolicyInterface[]): PolicyInterface[] => [ ...prev, ...rawActivePolicies ]); + } + + if ((pageActive + 1) >= (activePolicyArray.numberOfPages ?? 1)) { + setHasMoreActivePolicies(false); + } + + }, [ activePolicyArray ]); + + + useEffect(() => { + setPageInactive(0); + setHasMoreInactivePolicies(true); + setInactivePolicies([]); + + setPageActive(0); + setHasMoreActivePolicies(true); + setActivePolicies([]); + }, []); + + const handleListFilter = (query: string): void => { + // TODO: Add search functionality here + }; + + if (isLoadingActivePolicies || isLoadingInactivePolicies) { + return ( + + + + ); + } + + if (activePolicyError || inactivePolicyError) { + return ( + + { t("common:errorLoadingData") } + + ); + } + + const fetchMoreActivePolicies = (): void => { + setPageActive((prevPage: number) => prevPage + 1); + }; + + const fetchMoreInactivePolicies = (): void => { + setPageInactive((prevPage: number) => prevPage + 1); + }; + + return ( + + { t("policyAdministration:subtitle") } + + { t("common:learnMore") } + + ) + } + action={ ( + !(inactivePolicies?.length <= 0)) && + ( + + + + + + setShowWizard(true) } + > + + { t("policyAdministration:buttons.newPolicy") } + + + + ) + } + data-componentid={ componentId } + className="policy-administration-page" + > + + + + + + + + + + Active Policies + + + +
) + } + dataLength={ activePolicies.length } + scrollableTarget={ "active-policy-list-container" } + style={ { overflow: "unset" } } + > + + + + + + + + + Inactive Policies + + + + ) + } + dataLength={ inactivePolicies?.length } + scrollableTarget={ "inactive-policy-list-container" } + style={ { overflow: "unset" } } + > + + + + + + + + + { + showWizard && ( + setShowWizard(false) } + mutateInactivityList={ mutateInactivePolicy } + /> + ) + } + + { + showAlgorithmModal && ( + setShowAlgorithmModal(false) } + selectedAlgorithm={ selectedAlgorithm } + setSelectedAlgorithm={ setSelectedAlgorithm } + algorithmOptions={ algorithmOptions } + mutateAlgorithm={ mutateAlgorithm } + /> + ) + } + + ); +}; + +export default PolicyAdministrationPageLayout; diff --git a/features/admin.policy-administration.v1/components/policy-editor/policy-editor.scss b/features/admin.policy-administration.v1/components/policy-editor/policy-editor.scss new file mode 100644 index 00000000000..88a95f74292 --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-editor/policy-editor.scss @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.script-editor-panel { + height: 100%; + width: calc(100% - 16px); + + .script-editor { + border: 1px solid var(--oxygen-palette-divider); + height: 500px; + } +} + +.script-editor-toolbar-container { + .oxygen-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + align-content: center; + flex-wrap: nowrap; + flex-direction: row; + padding-left: 0; + padding-right: 0; + + .actions { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-content: center; + align-items: center; + gap: 10px; + + .editor-theme-select { + .MuiSelect-select { + padding: 6px 15px; + min-width: 150px; + } + } + } + } +} + +.full-screen-script-editor-container { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 95%; + height: 90%; + padding: 32px; + + .script-editor-toolbar-container { + background-color: var(--oxygen-palette-common-white); + padding-left: 15px; + padding-right: 15px; + border-top-right-radius: var(--oxygen-shape-borderRadius); + border-top-left-radius: var(--oxygen-shape-borderRadius); + } +} diff --git a/features/admin.policy-administration.v1/components/policy-editor/policy-editor.tsx b/features/admin.policy-administration.v1/components/policy-editor/policy-editor.tsx new file mode 100644 index 00000000000..6b6fc6d73ae --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-editor/policy-editor.tsx @@ -0,0 +1,308 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { DiffOnMount, MonacoDiffEditor } from "@monaco-editor/react"; +import Modal from "@mui/material/Modal"; +import Box from "@oxygen-ui/react/Box"; +import CircularProgress from "@oxygen-ui/react/CircularProgress"; +import FormControl from "@oxygen-ui/react/FormControl"; +import IconButton from "@oxygen-ui/react/IconButton"; +import MenuItem from "@oxygen-ui/react/MenuItem"; +import Select from "@oxygen-ui/react/Select"; +import Toolbar from "@oxygen-ui/react/Toolbar"; +import Tooltip from "@oxygen-ui/react/Tooltip"; +import Typography from "@oxygen-ui/react/Typography"; +import { ApplicationManagementConstants } from "@wso2is/admin.applications.v1/constants/application-management"; +import { AppUtils } from "@wso2is/admin.core.v1/utils/app-utils"; +import { IdentifiableComponentInterface, StorageIdentityAppsSettingsInterface } from "@wso2is/core/models"; +import classNames from "classnames"; +import cloneDeep from "lodash-es/cloneDeep"; +import isEmpty from "lodash-es/isEmpty"; +import set from "lodash-es/set"; +import React, { + ChangeEvent, + HTMLAttributes, + LazyExoticComponent, + MutableRefObject, + PropsWithChildren, + ReactElement, + Suspense, + lazy, + useCallback, + useRef, + useState +} from "react"; +import { useTranslation } from "react-i18next"; +import { ScriptEditorPanelSizeModes, SupportedEditorThemes } from "../../models/policy-editor"; +import "./policy-editor.scss"; +import { formatXML } from "../../utils/utils"; + +/** + * Proptypes for the policy editor panel component. + */ +export interface PolicyEditorProps extends IdentifiableComponentInterface, HTMLAttributes { + policyScript: string; + onScriptChange: (updatedScript: string) => void; +} + +const MonacoEditor: LazyExoticComponent = lazy(() => + import("@monaco-editor/react" /* webpackChunkName: "MDMonacoEditor" */) +); + +// TODO: Move this to Oxygen UI once https://github.com/wso2/oxygen-ui/issues/158 is fixed. +const MaximizeIcon = ({ width = 16, height = 16 }: { width: number; height: number }): ReactElement => ( + + + + + + +); + +// TODO: Move this to Oxygen UI once https://github.com/wso2/oxygen-ui/issues/158 is fixed. +const MinimizeIcon = ({ width = 16, height = 16 }: { width: number; height: number }): ReactElement => ( + + + + + + + +); + +/** + * Policy editor panel component. + * + * @param props - Props injected to the component. + * @returns Policy editor panel component. + */ +const PolicyEditorPanel = (props: PropsWithChildren): ReactElement => { + const { className, "data-componentid": componentId, policyScript, onScriptChange } = props; + + const { t } = useTranslation(); + + const monacoEditorRef: MutableRefObject = useRef(null); + + const userPreferences: StorageIdentityAppsSettingsInterface = AppUtils.getUserPreferences(); + + const [ editorTheme, setEditorTheme ] = useState( + userPreferences?.identityAppsSettings?.userPreferences + ?.[ApplicationManagementConstants.CONDITIONAL_AUTH_EDITOR_THEME_STORAGE_KEY] + ?? SupportedEditorThemes.DARK + ); + const [ scriptEditorPanelSizeMode, setScriptEditorPanelSizeMode ] = useState( + ScriptEditorPanelSizeModes.Minimized + ); + + const persistConditionalAuthEditorTheme = (theme: any): void => { + + const userPreferences: StorageIdentityAppsSettingsInterface = AppUtils.getUserPreferences(); + + if (isEmpty(userPreferences)) { + return; + } + + const newPref: StorageIdentityAppsSettingsInterface = cloneDeep(userPreferences); + + set(newPref?.identityAppsSettings?.userPreferences, + ApplicationManagementConstants.CONDITIONAL_AUTH_EDITOR_THEME_STORAGE_KEY, theme); + + AppUtils.setUserPreferences(newPref); + }; + + /** + * Callback function to handle the editor theme change. + * + * @param editor - The Monaco editor instance. + */ + const handleEditorOnMount: DiffOnMount = useCallback( + (editor: MonacoDiffEditor): void => { + monacoEditorRef.current = editor; + }, + [ monacoEditorRef ] + ); + + + /** + * Function to replace a code block in the Monaco editor. + * + * @param toReplace - The new text to replace the selected code block with. + */ + // const replaceCodeBlock = (toReplace: string): void => { + // if (!monacoEditorRef.current) { + // return; + // } + // + // const selection: Monaco["Selection"] = monacoEditorRef.current.getSelection(); + // + // if (!selection) { + // return; + // } + // + // monacoEditorRef.current.executeEdits("replaceCodeBlock", [ + // { + // range: selection, + // text: toReplace + // } + // ]); + // + // setIsSecretSelectionDropdownOpen(false); + // }; + + /** + * Function to handle the script editor panel size change. + */ + const handleScriptEditorPanelSizeChange = (): void => { + if (scriptEditorPanelSizeMode === ScriptEditorPanelSizeModes.Minimized) { + setScriptEditorPanelSizeMode(ScriptEditorPanelSizeModes.Maximized); + + return; + } + + setScriptEditorPanelSizeMode(ScriptEditorPanelSizeModes.Minimized); + }; + + const ScriptEditor: ReactElement = ( + onScriptChange(newValue || "") } + onMount={ handleEditorOnMount } + data-componentid={ `${componentId}-code-editor` } + /> + ); + + const ScriptEditorToolbar: ReactElement = ( + + + + { t("authenticationFlow:scriptEditor.panelHeader") } + +
+ { scriptEditorPanelSizeMode === ScriptEditorPanelSizeModes.Minimized && ( + <> +
+ + + +
+ + ) } +
+ + + { + scriptEditorPanelSizeMode === ScriptEditorPanelSizeModes.Minimized + ? + : + } + + +
+
+
+
+ ); + + return ( + }> +
+ { ScriptEditorToolbar } + + + { ScriptEditorToolbar } + { ScriptEditor } + + + { ScriptEditor } +
+
+ ); +}; + +/** + * Default props for the script editor panel component. + */ +PolicyEditorPanel.defaultProps = { + "data-componentid": "policy-editor" +}; + +export default PolicyEditorPanel; diff --git a/features/admin.policy-administration.v1/components/policy-list-draggable-node.scss b/features/admin.policy-administration.v1/components/policy-list-draggable-node.scss new file mode 100644 index 00000000000..07c89ac73a1 --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-list-draggable-node.scss @@ -0,0 +1,10 @@ +.policy-list-node{ + padding: 0; + .policy-drag-icon { + margin-top: 2px; + } +} + +.policy-list-node:hover { + box-shadow: 0 2px 2px rgba(203, 206, 219, 0.4); +} diff --git a/features/admin.policy-administration.v1/components/policy-list-draggable-node.tsx b/features/admin.policy-administration.v1/components/policy-list-draggable-node.tsx new file mode 100644 index 00000000000..f9d49c844d2 --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-list-draggable-node.tsx @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Card from "@oxygen-ui/react/Card"; +import CardContent from "@oxygen-ui/react/CardContent"; +import Stack from "@oxygen-ui/react/Stack"; +import Typography from "@oxygen-ui/react/Typography"; +import { EllipsisVerticalIcon } from "@oxygen-ui/react-icons"; +import { AppConstants, history } from "@wso2is/admin.core.v1"; +import { AlertLevels, IdentifiableComponentInterface } from "@wso2is/core/models"; +import { addAlert } from "@wso2is/core/store"; +import kebabCase from "lodash-es/kebabCase"; +import React, { FunctionComponent, HTMLAttributes, ReactElement } from "react"; +import { useTranslation } from "react-i18next"; +import { useDispatch } from "react-redux"; +import { Dispatch } from "redux"; +import { Icon } from "semantic-ui-react"; +import "./policy-list-draggable-node.scss"; +import { Popup } from "../../../modules/react-components/src"; +import { deletePolicy, publishPolicy } from "../api/entitlement-policies"; +import { PolicyInterface } from "../models/policies"; + +/** + * Props interface of {@link PolicyListDraggableNode} + */ +export interface PolicyListDraggableNodePropsInterface + extends IdentifiableComponentInterface, + HTMLAttributes { + /** + * The node that is being dragged. + */ + policy: PolicyInterface; + mutateActivePolicyList?: () => void; + mutateInactivePolicyList?: () => void; + setInactivePolicies?: React.Dispatch>; + setPageInactive: React.Dispatch>; + setHasMoreInactivePolicies: React.Dispatch>; +} + +const PolicyListDraggableNode: FunctionComponent = ({ + "data-componentid": componentId = "policy-list-draggable-node", + id, + policy, + mutateActivePolicyList, + mutateInactivePolicyList, + setInactivePolicies, + setPageInactive, + setHasMoreInactivePolicies, + ...rest +}: PolicyListDraggableNodePropsInterface): ReactElement => { + const { t } = useTranslation(); + const dispatch: Dispatch = useDispatch(); + + const handleEdit = (policyId: string) => { + history.push(`${AppConstants.getPaths().get("EDIT_POLICY").replace(":id", kebabCase(policyId))}`); + }; + + const handleDelete = async (): Promise => { + try { + await publishPolicy({ + action: "DELETE", + enable: true, + order: 0, + policyIds: [ `${policy.policyId}` ], + subscriberIds: [ "PDP Subscriber" ] + }); + await deletePolicy(policy.policyId); + + dispatch(addAlert({ + description: "The policy has been deleted successfully", + level: AlertLevels.SUCCESS, + message: "Delete successful" + })); + + mutateActivePolicyList(); + mutateInactivePolicyList(); + + } catch (error) { + // Dispatch the error alert. + dispatch(addAlert({ + description: "An error occurred while deleting the policy", + level: AlertLevels.ERROR, + message: "Delete error" + })); + } + }; + + const handleDeactivate = async (): Promise => { + try { + await publishPolicy({ + action: "DELETE", + enable: true, + order: 0, + policyIds: [ `${policy.policyId}` ], + subscriberIds: [ "PDP Subscriber" ] + }); + + dispatch(addAlert({ + description: "The policy has been deactivated successfully", + level: AlertLevels.SUCCESS, + message: "Deactivation successful" + })); + + setPageInactive(0); + setHasMoreInactivePolicies(true); + setInactivePolicies([]); + + mutateActivePolicyList(); + mutateInactivePolicyList(); + + } catch (error) { + dispatch(addAlert({ + description: "An error occurred while deactivating the policy", + level: AlertLevels.ERROR, + message: "Deactivation error" + })); + + } + }; + + return ( + + + + + + + { policy.policyId } + + + handleEdit(policy.policyId) } + data-componentid={ `${componentId}-edit-button` } + className="list-icon" + size="small" + color="grey" + name="pencil alternate" + /> + ) } + position="top center" + content={ "Edit" } + inverted + /> + + ) } + position="top center" + content={ "Delete" } + inverted + /> + + ) } + position="top center" + content={ "Deactivate" } + inverted + /> + + + + + ); +}; + +export default PolicyListDraggableNode; diff --git a/features/admin.policy-administration.v1/components/policy-list-node.scss b/features/admin.policy-administration.v1/components/policy-list-node.scss new file mode 100644 index 00000000000..5eb4c7547ea --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-list-node.scss @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.policy-list-node{ + padding: 0; +} +.policy-list-node:hover { + box-shadow: 0 2px 2px rgba(203, 206, 219, 0.4); +} diff --git a/features/admin.policy-administration.v1/components/policy-list-node.tsx b/features/admin.policy-administration.v1/components/policy-list-node.tsx new file mode 100644 index 00000000000..561c9819757 --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-list-node.tsx @@ -0,0 +1,190 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import Card from "@oxygen-ui/react/Card"; +import CardContent from "@oxygen-ui/react/CardContent"; +import Stack from "@oxygen-ui/react/Stack"; +import Typography from "@oxygen-ui/react/Typography"; +import { AppConstants, history } from "@wso2is/admin.core.v1"; +import { AlertLevels, IdentifiableComponentInterface } from "@wso2is/core/models"; +import { addAlert } from "@wso2is/core/store"; +import kebabCase from "lodash-es/kebabCase"; +import React, { FunctionComponent, HTMLAttributes, ReactElement } from "react"; +import { useTranslation } from "react-i18next"; +import { useDispatch } from "react-redux"; +import { Dispatch } from "redux"; +import { Icon } from "semantic-ui-react"; +import { Popup } from "../../../modules/react-components/src"; +import { deletePolicy, publishPolicy } from "../api/entitlement-policies"; +import { PolicyInterface } from "../models/policies"; +import "./policy-list-node.scss"; + +/** + * Props interface of {@link PolicyListDraggableNode} + */ +export interface PolicyListDraggableNodePropsInterface + extends IdentifiableComponentInterface, + HTMLAttributes { + /** + * The node that is being dragged. + */ + policy: PolicyInterface; + mutateInactivePolicyList?: () => void; + setInactivePolicies?: React.Dispatch>; + setPageInactive: React.Dispatch>; + setHasMoreInactivePolicies: React.Dispatch>; + mutateActivePolicyList?: () => void; +} + +const PolicyListNode: FunctionComponent = ({ + "data-componentid": componentId = "policy-list--node", + id, + policy, + mutateInactivePolicyList, + setInactivePolicies, + setPageInactive, + setHasMoreInactivePolicies, + mutateActivePolicyList, + ...rest +}: PolicyListDraggableNodePropsInterface): ReactElement => { + const { t } = useTranslation(); + + const dispatch: Dispatch = useDispatch(); + + const handleEdit = (policyId: string) => { + history.push(`${AppConstants.getPaths().get("EDIT_POLICY").replace(":id", kebabCase(policyId))}`); + }; + + const handleDelete = async (): Promise => { + try { + await deletePolicy(policy.policyId); + + setPageInactive(0); + setHasMoreInactivePolicies(true); + setInactivePolicies([]); + + dispatch(addAlert({ + description: "The policy has been deleted successfully", + level: AlertLevels.SUCCESS, + message: "Delete successful" + })); + + mutateInactivePolicyList(); + + } catch (error) { + // Dispatch the error alert. + dispatch(addAlert({ + description: "An error occurred while deleting the policy", + level: AlertLevels.ERROR, + message: "Delete error" + })); + } + }; + + + + + + const handleActivate = async () : Promise => { + try{ + await publishPolicy({ + action: "CREATE", + enable: true, + order: 0, + policyIds: [ `${policy.policyId}` ], + subscriberIds: [ "PDP Subscriber" ] + }); + + setPageInactive(0); + setHasMoreInactivePolicies(true); + setInactivePolicies([]); + + mutateActivePolicyList(); + mutateInactivePolicyList(); + + } catch ( error ) { + dispatch(addAlert({ + description: "An error occurred while activating the policy", + level: AlertLevels.ERROR, + message: "Activation error" + })); + } + }; + + return ( + + + + + + ) } + position="top center" + content={ "Deactivate" } + inverted + /> + { policy.policyId } + + + handleEdit(policy.policyId) } + data-componentid={ `${componentId}-edit-button` } + className="list-icon" + size="small" + color="grey" + name="pencil alternate" + /> + ) } + position="top center" + content={ "Edit" } + inverted + /> + + ) } + position="top center" + content={ "Delete" } + inverted + /> + + + + + + ); +}; + +export default PolicyListNode; diff --git a/features/admin.policy-administration.v1/components/policy-list.scss b/features/admin.policy-administration.v1/components/policy-list.scss new file mode 100644 index 00000000000..36603941f5f --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-list.scss @@ -0,0 +1,5 @@ +.policy-inactive-list{ + display: flex; + flex-direction: column; + gap: 8px; +} diff --git a/features/admin.policy-administration.v1/components/policy-list.tsx b/features/admin.policy-administration.v1/components/policy-list.tsx new file mode 100644 index 00000000000..32709e3f81b --- /dev/null +++ b/features/admin.policy-administration.v1/components/policy-list.tsx @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { DroppableContainer, GetDragItemProps, useDnD } from "@oxygen-ui/react/dnd"; +import { + IdentifiableComponentInterface +} from "@wso2is/core/models"; +import React, { ReactElement } from "react"; +import PolicyListDraggableNode from "./policy-list-draggable-node"; +import PolicyListNode from "./policy-list-node"; +import { PolicyInterface } from "../models/policies"; +import "./policy-list.scss"; + +interface PolicyListProps extends IdentifiableComponentInterface { + onDrop?: (containerId: string) => void; + policies?: PolicyInterface[]; // Use PolicyInterface[] + containerId: string; + isDraggable?: boolean; // Add a prop to control drag functionality + mutateInactivePolicyList?: () => void; + mutateActivePolicyList?: () => void; + setInactivePolicies?: React.Dispatch>; + setPageInactive?: React.Dispatch>; + setHasMoreInactivePolicies?: React.Dispatch>; +} + + + +export const PolicyList: React.FunctionComponent = ({ + onDrop, + policies = [], + mutateInactivePolicyList, setInactivePolicies, + setPageInactive, + setHasMoreInactivePolicies, + mutateActivePolicyList, + containerId, + isDraggable = true // Default to draggable +}: PolicyListProps): ReactElement => { + const { generateComponentId } = useDnD(); + + const renderDraggableList = () => ( + // + // nodes={ policies } + // onDrop={ () => onDrop?.(containerId) } + // > + // { ({ + // nodes, + // getDragItemProps + // }: { + // nodes: PolicyInterface[]; + // getDragItemProps: GetDragItemProps; + // }) => + // nodes.map((policy: PolicyInterface, index: number) => { + // const { + // className: dragItemClassName, + // ...otherDragItemProps + // } = getDragItemProps(index); + + // return ( + //
+ // + //
+ // ); + // }) + // } + // +
+ ); + + const renderStaticList = () => ( +
+ { policies.map((policy: PolicyInterface) => ( + + )) } +
+ ); + + return isDraggable ? renderDraggableList() : renderStaticList(); +}; + diff --git a/features/admin.policy-administration.v1/components/wizard/new-policy-wizard.scss b/features/admin.policy-administration.v1/components/wizard/new-policy-wizard.scss new file mode 100644 index 00000000000..f68bb74633a --- /dev/null +++ b/features/admin.policy-administration.v1/components/wizard/new-policy-wizard.scss @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.policy-editor-container { + width: 688px; + height: 488px; + + .policy-editor { + border: 1px solid var(--oxygen-palette-divider); + + background: #f7f7f7; + border-radius: 8px; + margin-right: 10px; + margin-left: 10px; + } + .script-editor-toolbar-container{ + padding-left: 10px; + padding-right: 10px; + } +} diff --git a/features/admin.policy-administration.v1/components/wizard/new-policy-wizard.tsx b/features/admin.policy-administration.v1/components/wizard/new-policy-wizard.tsx new file mode 100644 index 00000000000..8c5325b30f2 --- /dev/null +++ b/features/admin.policy-administration.v1/components/wizard/new-policy-wizard.tsx @@ -0,0 +1,213 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import Box from "@oxygen-ui/react/Box"; +import Button from "@oxygen-ui/react/Button"; +import Dialog from "@oxygen-ui/react/Dialog"; +import DialogActions from "@oxygen-ui/react/DialogActions"; +import DialogContent from "@oxygen-ui/react/DialogContent"; +import DialogTitle from "@oxygen-ui/react/DialogTitle"; +import Stack from "@oxygen-ui/react/Stack"; +import Typography from "@oxygen-ui/react/Typography/Typography"; +import { getCertificateIllustrations } from "@wso2is/admin.core.v1"; +import { AlertLevels, IdentifiableComponentInterface } from "@wso2is/core/models"; +import { addAlert } from "@wso2is/core/store"; +import { FilePicker, PickerResult, XMLFileStrategy } from "@wso2is/react-components"; +import React, { FunctionComponent, MouseEvent, ReactElement, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useDispatch } from "react-redux"; +import { Dispatch } from "redux"; +import { Icon } from "semantic-ui-react"; +import "./new-policy-wizard.scss"; +import { createPolicy } from "../../api/entitlement-policies"; +import { PolicyInterface } from "../../models/policies"; +import { unformatXML } from "../../utils/utils"; +import PolicyEditor from "../policy-editor/policy-editor"; + + +interface NewPolicyWizardPropsInterface extends IdentifiableComponentInterface { + closeWizard: () => void; + open: boolean; + mutateInactivityList: () => void; +} + +/** + * New Policy Wizard + * + * @param props - Props injected to the component. + * @returns New Policy Wizard component. + */ + +export const NewPolicyWizard: FunctionComponent = +(props: NewPolicyWizardPropsInterface): ReactElement => { + const { closeWizard, [ "data-componentid" ]: componentId, open, mutateInactivityList } = props; + const { t } = useTranslation(); + const dispatch: Dispatch = useDispatch(); + + const [ selectedXMLFile, setSelectedXMLFile ] = useState(null); + const [ pastedContent, setPastedContent ] = useState(""); + const [ isSubmitting, setIsSubmitting ] = useState(false); + + + const handleSave = async (): Promise => { + if (!pastedContent || pastedContent.trim().length === 0) { + dispatch( + addAlert({ + description: t("policyAdministration:createPolicy.notifications.emptyContent.description"), + level: AlertLevels.ERROR, + message: t("policyAdministration:createPolicy.notifications.emptyContent.message") + }) + ); + + return; + } + + setIsSubmitting(true); + + const rawXml: string = selectedXMLFile + ? unformatXML(await selectedXMLFile.text()) + : unformatXML(pastedContent); + + const policy: PolicyInterface = { + active: true, + attributeDTOs: [], + lastModifiedTime: null, + lastModifiedUser: null, + policy: rawXml, + policyEditor: null, + policyEditorData: [], + policyId: "", + policyIdReferences: [], + policyOrder: 0, + policySetIdReferences: [], + policyType: null, + promote: false, + version: null + }; + + try { + await createPolicy(policy); + + dispatch( + addAlert({ + description: t("policyAdministration:createPolicy.notifications.success.description"), + level: AlertLevels.SUCCESS, + message: t("policyAdministration:createPolicy.notifications.success.message") + }) + ); + + closeWizard(); + mutateInactivityList(); + } catch (error) { + dispatch( + addAlert({ + description: t("policyAdministration:createPolicy.notifications.error.description"), + level: AlertLevels.ERROR, + message: t("policyAdministration:createPolicy.notifications.error.message") + }) + ); + } finally { + setIsSubmitting(false); + } + }; + + return ( + + + { t("policyAdministration:createPolicy.title") } + + { t("policyAdministration:createPolicy.description") } + + + + ) => { + + setSelectedXMLFile(result?.file || null); + + if (result?.file) { + const decodedXml = result.serialized ? atob(result.serialized) : ""; + + setPastedContent(decodedXml); + } else { + setPastedContent(result?.pastedContent || ""); + } + } } + + uploadButtonText="Upload XML File" + dropzoneText="Drag and drop a XML file here." + data-componentid={ `${componentId}-form-wizard-csv-file-picker` } + icon={ getCertificateIllustrations().uploadPlaceholder } + placeholderIcon={ } + pasteAreaPlaceholderText="Paste the XACML Policy here" + normalizeStateOnRemoveOperations={ true } + emptyFileError={ false } + scriptEditor={ + ( + { + setPastedContent(script); + } } + /> + ) + } + /> + + + + + + + + + + + + ); +}; + +const XML_FILE_PROCESSING_STRATEGY: XMLFileStrategy = new XMLFileStrategy([ + "text/xml", + "application/xml", + ".xml" +]); + diff --git a/features/admin.policy-administration.v1/configs/endpoints.ts b/features/admin.policy-administration.v1/configs/endpoints.ts new file mode 100644 index 00000000000..b34c0a451d5 --- /dev/null +++ b/features/admin.policy-administration.v1/configs/endpoints.ts @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PolicyAdministrationEndpointsInterface } from "../models/endpoints"; + +/** + * Get the policy administration resource endpoints. + * + * @param serverHost - Server host. + * + * @return {PolicyAdministrationEndpointsInterface} + */ + +export const getPolicyAdministrationResourceEndpoints = ( + serverHost: string +): PolicyAdministrationEndpointsInterface => { + return { + entitlementPoliciesApi: `${ serverHost }/api/identity/entitlement/v1/entitlements/policies`, + // eslint-disable-next-line max-len + entitlementPolicyCombiningAlgorithmApi: `${ serverHost }/api/identity/entitlement/v1/entitlements/combining-algorithm`, + entitlementPolicyPublishApi: `${ serverHost }/api/identity/entitlement/v1/entitlements/publish` + }; +}; diff --git a/features/admin.policy-administration.v1/configs/index.ts b/features/admin.policy-administration.v1/configs/index.ts new file mode 100644 index 00000000000..9e42ad8ada0 --- /dev/null +++ b/features/admin.policy-administration.v1/configs/index.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from "./endpoints"; diff --git a/features/admin.policy-administration.v1/models/endpoints.ts b/features/admin.policy-administration.v1/models/endpoints.ts new file mode 100644 index 00000000000..bda0057dc25 --- /dev/null +++ b/features/admin.policy-administration.v1/models/endpoints.ts @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface PolicyAdministrationEndpointsInterface { + entitlementPoliciesApi: string; + entitlementPolicyCombiningAlgorithmApi: string; + entitlementPolicyPublishApi: string; +} diff --git a/features/admin.policy-administration.v1/models/policies.ts b/features/admin.policy-administration.v1/models/policies.ts new file mode 100644 index 00000000000..27cd0d7ef6a --- /dev/null +++ b/features/admin.policy-administration.v1/models/policies.ts @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface AttributeDTO { + attributeValue: string; + attributeDataType: string; + attributeId: string; + attributeCategory: string; +} + +export interface PolicyInterface { + policy: string; + policyId: string; + active: boolean; + promote: boolean; + policyType: string; + policyEditor: string | null; + policyEditorData: any[]; + policyOrder: number; + version: string; + lastModifiedTime: string; + lastModifiedUser: string | null; + attributeDTOs: AttributeDTO[]; + policySetIdReferences: string[]; + policyIdReferences: string[]; +} + +export interface PolicyListInterface { + policySet: PolicyInterface[]; + "numberOfPages": number; +} + +export interface PolicyAlgorithmRequestInterface { + policyCombiningAlgorithm: string; +} + +export type AlgorithmResponseInterface = string; + +export interface AlgorithmOption { + value: number; + label: string; + description: string; +} + +export interface PublishPolicyDataInterface { + policyIds: string[]; + subscriberIds: string[]; + action: string; + enable: boolean; + order: number; +} diff --git a/features/admin.policy-administration.v1/models/policy-editor.ts b/features/admin.policy-administration.v1/models/policy-editor.ts new file mode 100644 index 00000000000..a97b2f52887 --- /dev/null +++ b/features/admin.policy-administration.v1/models/policy-editor.ts @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Enum for supported script editor themes. + */ +export enum SupportedEditorThemes { + /** + * Dark theme for the script editor. + */ + DARK = "vs-dark", + + /** + * High contrast theme for the script editor. + */ + HIGH_CONTRAST = "hc-black", + + /** + * Light theme for the script editor. + */ + LIGHT = "vc" +} + +/** + * Enum for script editor panel size modes. + */ +export enum ScriptEditorPanelSizeModes { + /** + * Maximized mode for the script editor panel. + */ + Maximized = "maximized", + + /** + * Minimized mode for the script editor panel. + */ + Minimized = "minimized", +} diff --git a/features/admin.policy-administration.v1/package.json b/features/admin.policy-administration.v1/package.json new file mode 100644 index 00000000000..d7f2910429b --- /dev/null +++ b/features/admin.policy-administration.v1/package.json @@ -0,0 +1,149 @@ +{ + "private": true, + "name": "@wso2is/admin.policy-administration.v1", + "version": "0.0.0", + "description": "WSO2 Identity Server Console - Policy Administration Connector UI", + "author": "WSO2", + "license": "Apache-2.0", + "dependencies": { + "@emotion/react": "^11.11.0", + "@emotion/styled": "^11.11.0", + "@microsoft/applicationinsights-core-js": "^3.0.0", + "@microsoft/applicationinsights-react-js": "^3.4.2", + "@microsoft/applicationinsights-web": "^3.0.0", + "@monaco-editor/react": "^4.5.1", + "@mui/icons-material": "^5.11.16", + "@mui/lab": "5.0.0-alpha.129", + "@mui/material": "^5.13.0", + "@mui/system": "^5.12.3", + "@mui/utils": "^5.12.3", + "@oxygen-ui/react": "^2.0.0", + "@oxygen-ui/react-icons": "^2.0.0", + "@wso2is/access-control": "^3.3.1", + "@wso2is/admin.applications.v1": "^2.30.21", + "@wso2is/admin.core.v1": "^2.34.27", + "@wso2is/admin.extensions.v1": "^2.34.27", + "@wso2is/admin.feature-gate.v1": "^1.4.27", + "@wso2is/admin.organizations.v1": "^2.26.27", + "@wso2is/admin.users.v1": "^2.27.27", + "@wso2is/admin.validation.v1": "^2.26.27", + "@wso2is/core": "^2.4.1", + "@wso2is/dynamic-forms": "^2.4.5", + "@wso2is/form": "^2.5.5", + "@wso2is/forms": "^2.3.1", + "@wso2is/i18n": "^2.12.0", + "@wso2is/react-components": "^2.8.5", + "@wso2is/theme": "^2.4.3", + "@wso2is/validation": "^2.4.0", + "axios": "^0.19.2", + "codemirror": "^5.52.0", + "country-language": "^0.1.7", + "deep-equal": "^2.2.2", + "file-saver": "^2.0.5", + "framer-motion": "^11.1.9", + "history": "^4.9.0", + "html-react-parser": "^2.0.0", + "i18next": "^21.9.1", + "i18next-browser-languagedetector": "^6.1.5", + "i18next-xhr-backend": "^3.2.2", + "js-beautify": "^1.13.0", + "lodash-es": "^4.17.21", + "moment": "^2.24.0", + "mustache": "^4.2.0", + "node-forge": "^0.10.0", + "rc-tree": "^4.0.0-beta.2", + "react-draggable": "^4.2.0", + "react-helmet": "^5.2.1", + "react-i18next": "^11.18.5", + "react-infinite-scroll-component": "^6.1.0", + "react-joyride": "^2.3.0", + "react-notification-system": "^0.4.0", + "react-redux": "^7.2.9", + "reactflow": "^11.7.2", + "recharts": "^2.6.2", + "reduce-reducers": "^1.0.4", + "redux": "^4.0.4", + "redux-form": "^8.3.7", + "redux-mock-store": "^1.5.4", + "redux-thunk": "^2.3.0", + "regenerator-runtime": "^0.13.9", + "semantic-ui-react": "^2.1.3", + "slashes": "^2.0.2", + "styled-components": "^4.4.1", + "swr": "^2.0.0", + "uuid": "^8.3.0" + }, + "devDependencies": { + "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3", + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-dynamic-import-vars": "^2.1.2", + "@rollup/plugin-image": "^3.0.3", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-typescript": "^11.1.6", + "@svgr/rollup": "^6.2.1", + "@svgr/webpack": "4.3.2", + "@testing-library/dom": "^7.24.3", + "@testing-library/jest-dom": "^5.11.9", + "@testing-library/user-event": "^12.7.3", + "@types/file-saver": "^2.0.1", + "@types/history": "^4.7.3", + "@types/jest": "^26.0.14", + "@types/lodash-es": "^4.17.4", + "@types/node": "^13.9.2", + "@types/node-forge": "^0.9.3", + "@types/react": "^18.0.18", + "@types/react-dom": "^18.0.6", + "@types/react-notification-system": "0.2.39", + "@types/react-redux": "^7.1.25", + "@types/react-router": "^5.1.18", + "@types/react-router-dom": "^5.1.3", + "@types/reactour": "^1.18.1", + "@types/redux-mock-store": "^1.0.2", + "@types/testing-library__jest-dom": "^5.14.3", + "@types/uuid": "^9.0.1", + "@types/webpack-env": "^1.16.0", + "@typescript-eslint/eslint-plugin": "^6.5.0", + "@typescript-eslint/parser": "^6.5.0", + "connect-history-api-fallback": "^2.0.0", + "copy-webpack-plugin": "^12.0.2", + "css-loader": "^1.0.0", + "eslint": "8.46.0", + "eslint-plugin-import": "^2.20.2", + "eslint-plugin-jest-dom": "^4.0.1", + "eslint-plugin-react": "7.30.0", + "eslint-plugin-react-hooks": "^4.0.0", + "eslint-plugin-testing-library": "^5.0.5", + "eslint-webpack-plugin": "^2.5.3", + "fork-ts-checker-webpack-plugin": "^6.1.0", + "jest": "^26.4.2", + "jest-environment-jsdom": "^26.3.0", + "jest-environment-jsdom-global": "^2.0.4", + "json-minimizer-webpack-plugin": "^4.0.0", + "msw": "^0.36.8", + "process": "^0.11.10", + "react-refresh": "^0.9.0", + "redux-devtools-extension": "^2.13.8", + "rimraf": "^3.0.2", + "rollup": "^4.17.2", + "rollup-plugin-dts": "^6.1.1", + "rollup-plugin-generate-package-json": "^3.2.0", + "rollup-plugin-polyfill-node": "^0.13.0", + "rollup-plugin-scss": "^4.0.0", + "rollup-plugin-styles": "^4.0.0", + "rollup-plugin-svg": "^2.0.0", + "style-loader": "^0.23.1", + "thread-loader": "^2.1.3", + "ts-jest": "^26.4.0", + "typescript": "^4.6.4" + }, + "peerDependencies": { + "@asgardeo/auth-react": "^5.1.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^4.3.1" + }, + "browserslist": [ + "> 0.2%" + ] +} diff --git a/features/admin.policy-administration.v1/pages/edit-policy.scss b/features/admin.policy-administration.v1/pages/edit-policy.scss new file mode 100644 index 00000000000..cb8edb5c3cd --- /dev/null +++ b/features/admin.policy-administration.v1/pages/edit-policy.scss @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.script-editor{ + border: 1px solid var(--oxygen-palette-divider); + padding-right: 0; + background: #f7f7f7; + border-radius: 8px; + margin-right: 10px; + margin-left: 10px; + margin-bottom: 10px; + + .script-editor-toolbar-container{ + padding-left: 10px; + padding-right: 10px; + } +} + +.edit-policy-btn { + margin-top: 10px; + margin-left: 20px; +} diff --git a/features/admin.policy-administration.v1/pages/edit-policy.tsx b/features/admin.policy-administration.v1/pages/edit-policy.tsx new file mode 100644 index 00000000000..756fed49a20 --- /dev/null +++ b/features/admin.policy-administration.v1/pages/edit-policy.tsx @@ -0,0 +1,176 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Alert from "@oxygen-ui/react/Alert"; +import Box from "@oxygen-ui/react/Box"; +import Button from "@oxygen-ui/react/Button"; +import CircularProgress from "@oxygen-ui/react/CircularProgress"; +import { AppConstants, history } from "@wso2is/admin.core.v1"; +import { AlertLevels, IdentifiableComponentInterface } from "@wso2is/core/models"; +import { addAlert } from "@wso2is/core/store"; +import { PageLayout } from "@wso2is/react-components"; +import isEmpty from "lodash-es/isEmpty"; +import lowerCase from "lodash-es/lowerCase"; +import React, { FunctionComponent, ReactElement, useState } from "react"; +import { useTranslation } from "react-i18next"; +import "./edit-policy.scss"; +import { useDispatch } from "react-redux"; +import { RouteComponentProps } from "react-router"; +import { Dispatch } from "redux"; +import { updatePolicy } from "../api/entitlement-policies"; +import { useGetPolicy } from "../api/use-get-policy"; +import startCase from "lodash-es/startCase"; +import PolicyEditor from "../components/policy-editor/policy-editor"; +import { PolicyInterface } from "../models/policies"; + + + +type EditPolicyPageProps = IdentifiableComponentInterface & RouteComponentProps; + +/** + * Component for editing a policy. + * + * @param props - Props injected to the component. + * @returns Policy edit page component. + */ +const EditPolicyPage: FunctionComponent = ({ + match, + ["data-componentid"]: componentId = "policy-edit-page" +}: EditPolicyPageProps & RouteComponentProps): ReactElement => { + const policyId: string = match.params["id"]; + const dispatch: Dispatch = useDispatch(); + + const shouldFetchPolicy: boolean = !isEmpty(policyId); + const [ updatedPolicyScript, setUpdatedPolicyScript ] = useState(); + + /** + * Converts kebab-case to snake_case. + * + * @param kebab - Kebab case string. + * @returns Snake case string. + */ + const kebabToSnakeCase = (kebab: string): string => { + return kebab.replace(/-/g, "_"); + }; + + // Fetch the policy using the useGetPolicy hook + const { data: policy, isLoading, error } = useGetPolicy( + kebabToSnakeCase(policyId || ""), + shouldFetchPolicy + ); + + const { t } = useTranslation(); + + /** + * Handles the back button click event. + */ + const handleBackButtonClick = (): void => { + history.push(AppConstants.getPaths().get("POLICY_ADMINISTRATION")); + }; + + + const handleUpdateButtonClick = (): void => { + if (!policy) { + return; + } + + const updatedPolicy: Partial = { + active: policy.active, + attributeDTOs: [], + policy: updatedPolicyScript, + policyEditorData: policy.policyEditorData, + policyId: policy.policyId, + policyIdReferences: policy.policyIdReferences, + policyOrder: policy.policyOrder, + policySetIdReferences: policy.policySetIdReferences, + promote: policy.promote + }; + + updatePolicy(updatedPolicy) + .then(() => { + dispatch( + addAlert({ + description: t("policyAdministration:editPolicy.notifications.updatePolicy." + + "success.description"), + level: AlertLevels.SUCCESS, + message: t("policyAdministration:editPolicy.notifications.updatePolicy.success.message") + }) + ); + + }) + .catch(() => { + dispatch( + addAlert({ + description: t("policyAdministration:editPolicy.notifications.updatePolicy.error.description"), + level: AlertLevels.ERROR, + message: t("policyAdministration:editPolicy.notifications.updatePolicy.error.message") + }) + ); + }); + }; + + return ( + + { /* Loading State */ } + { isLoading && ( + + + + ) } + + { /* Error State */ } + { error && ( + + { t("policyAdministration:editPolicy.errorDescription") } + + ) } + + { /* Render Policy Script Editor only if policy data is available */ } + { !isLoading && !error && policy && ( + + setUpdatedPolicyScript(updatedScript) } + /> + + ) } + + { /* Update Button: Show only if policy data is available */ } + { !isLoading && !error && policy && ( + + ) } + + ); +}; + +export default EditPolicyPage; diff --git a/features/admin.policy-administration.v1/pages/policy-administration.tsx b/features/admin.policy-administration.v1/pages/policy-administration.tsx new file mode 100644 index 00000000000..f02f498eaa9 --- /dev/null +++ b/features/admin.policy-administration.v1/pages/policy-administration.tsx @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IdentifiableComponentInterface } from "@wso2is/core/models"; +import React, { FunctionComponent, ReactElement } from "react"; +import PolicyAdministrationPageLayout from "../components/policy-administration-page-layout"; + +/** + * Props interface of {@link PolicyAdministrationPage} + */ +type PolicyAdministrationPageProps = IdentifiableComponentInterface; + +/** + * Landing page for the Policy Administration feature. + * + * @param props - Props injected to the component. + * @returns Policy Administration page component. + */ +const PolicyAdministrationPage: FunctionComponent = ({ + ["data-componentid"]: componentId = "policy-administration-page" +}: PolicyAdministrationPageProps): ReactElement => { + return ; +}; + +export default PolicyAdministrationPage; diff --git a/features/admin.policy-administration.v1/public-api.ts b/features/admin.policy-administration.v1/public-api.ts new file mode 100644 index 00000000000..d459835a6ee --- /dev/null +++ b/features/admin.policy-administration.v1/public-api.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { default as PolicyAdministrationPage } from "./pages/policy-administration"; diff --git a/features/admin.policy-administration.v1/rollup.config.cjs b/features/admin.policy-administration.v1/rollup.config.cjs new file mode 100644 index 00000000000..65fddd11671 --- /dev/null +++ b/features/admin.policy-administration.v1/rollup.config.cjs @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +const commonjs = require("@rollup/plugin-commonjs"); +const dynamicImportVars = require("@rollup/plugin-dynamic-import-vars"); +const image = require("@rollup/plugin-image"); +const json = require("@rollup/plugin-json"); +const { nodeResolve } = require("@rollup/plugin-node-resolve"); +const typescript = require("@rollup/plugin-typescript"); +const svgr = require("@svgr/rollup"); +const dts = require("rollup-plugin-dts"); +const nodePolyfills = require("rollup-plugin-polyfill-node"); +const scss = require("rollup-plugin-scss"); +const svg = require("rollup-plugin-svg"); + +const onwarn = (warning, warn) => { + if (warning.code === "MODULE_LEVEL_DIRECTIVE") { + return; + } + warn(warning); +}; + +module.exports = [ + { + cache: false, + external: [ "react", "react-dom", /^@wso2is\// ], + input: [ + "./public-api.ts" + ], + onwarn, + output: [ + { + dir: "dist/esm", + format: "esm", + preserveModules: true, + preserveModulesRoot: "." + } + ], + plugins: [ + nodeResolve(), + typescript({ + tsconfig: "./tsconfig.json" + }), + scss(), + svg(), + svgr(), + json(), + image(), + nodePolyfills(), + commonjs(), + dynamicImportVars() + ] + }, + { + cache: false, + input: "dist/esm/types/public-api.d.ts", + output: [ { file: "dist/esm/index.d.ts", format: "esm" } ], + plugins: [ dts.default() ] + } +]; diff --git a/features/admin.policy-administration.v1/tsconfig.json b/features/admin.policy-administration.v1/tsconfig.json new file mode 100644 index 00000000000..71337b4c236 --- /dev/null +++ b/features/admin.policy-administration.v1/tsconfig.json @@ -0,0 +1,42 @@ +{ + "compilerOptions": { + "jsx": "react", + "declaration": true, + "declarationDir": "dist/esm/types", + "lib": [ "ESNext", "DOM", "DOM.Iterable", "ScriptHost" ], + "resolveJsonModule": true, + "skipDefaultLibCheck": true, + "types": [ "node", "webpack-env", "jest", "@testing-library/jest-dom" ], + "emitDecoratorMetadata": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "importHelpers": true, + "module": "esnext", + "moduleResolution": "node", + "skipLibCheck": true, + "sourceMap": true, + "target": "es2015", + }, + "exclude": [ + "build", + "cache", + "coverage", + "dist", + "node_modules", + "scripts", + "**/test-configs/*", + "jest.config.ts", + "**/tests/*", + "**/__tests__/*", + "**/__mocks__/*", + "**/*.test.js", + "**/*.test.jsx", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.spec.jsx", + "**/*.spec.ts", + "**/*.spec.tsx" + ], + "compileOnSave": false, +} diff --git a/features/admin.policy-administration.v1/types/imports.d.ts b/features/admin.policy-administration.v1/types/imports.d.ts new file mode 100644 index 00000000000..54f3a6a5f3a --- /dev/null +++ b/features/admin.policy-administration.v1/types/imports.d.ts @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +declare module "*.json" { + const value: any; + + export default value; +} + +declare module "*.svg" { + import React = require("react"); + + export const ReactComponent: React.FunctionComponent>; + const src: string; + + export default src; +} + +declare module "*.png" { + const content: string; + + export default content; +} + +declare module "*.md"; diff --git a/features/admin.policy-administration.v1/utils/policy-algorithms.ts b/features/admin.policy-administration.v1/utils/policy-algorithms.ts new file mode 100644 index 00000000000..715750314ca --- /dev/null +++ b/features/admin.policy-administration.v1/utils/policy-algorithms.ts @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { AlgorithmOption } from "../models/policies"; + +export const algorithmOptions: AlgorithmOption[] = [ + { + description: "The deny overrides combining algorithm is intended for those cases where a deny decision" + + " should have priority over a permit decision.", + label: "deny-overrides", + value: 1 + }, + { + description: "The permit overrides combining algorithm is intended for those cases where a permit " + + "decision should have priority over a deny decision.", + label: "permit-overrides", + value: 2 + } +]; diff --git a/features/admin.policy-administration.v1/utils/utils.ts b/features/admin.policy-administration.v1/utils/utils.ts new file mode 100644 index 00000000000..819f97a6f3d --- /dev/null +++ b/features/admin.policy-administration.v1/utils/utils.ts @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use + * this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const formatXML = (xml: string): string => { + if (!xml || typeof xml !== "string") { + console.warn("Invalid XML input for formatting."); + return xml || ""; + } + + const PADDING: string = " ".repeat(4); // Indentation level + const regex: RegExp = /(>)(<)(\/*)/g; + + try { + // Add line breaks between tags + const formatted = xml.replace(regex, "$1\n$2$3"); + + // Detect if already formatted (basic check for line breaks and indentation) + const alreadyFormatted = formatted.split("\n").some((line) => line.startsWith(PADDING)); + + if (alreadyFormatted) { + return xml; // Return unmodified if already formatted + } + + let pad = 0; + + return formatted + .split("\n") + .map((line: string) => { + if (line.match(/<\/\w/)) pad -= 1; + + const indent = PADDING.repeat(Math.max(pad, 0)); + const formattedLine = `${indent}${line}`; + + if (line.match(/<\w[^>]*[^/]>.*$/)) pad += 1; + + return formattedLine; + }) + .join("\n"); + } catch (error) { + console.error("Error formatting XML:", error); + return xml; // Return raw XML in case of errors + } +}; + +export const unformatXML = (xml: string): string => { + if (!xml || typeof xml !== "string") { + console.warn("Invalid XML input for unformatting."); + return xml || ""; + } + + try { + // Remove all line breaks, tabs, and excessive spaces + return xml + .replace(/>\s+<") // Remove spaces between tags + .replace(/\s{2,}/g, " ") // Replace multiple spaces with a single space + .trim(); // Remove leading/trailing spaces + } catch (error) { + console.error("Error unformatting XML:", error); + return xml; // Return the original XML if unformatting fails + } +}; + diff --git a/features/admin.private-key-jwt.v1/package.json b/features/admin.private-key-jwt.v1/package.json index 284f95b0716..b5bf2d4fdb6 100644 --- a/features/admin.private-key-jwt.v1/package.json +++ b/features/admin.private-key-jwt.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.server-configurations.v1": "^2.32.8", diff --git a/features/admin.provisioning.v1/package.json b/features/admin.provisioning.v1/package.json index 4523a23b575..30f2d6387cd 100644 --- a/features/admin.provisioning.v1/package.json +++ b/features/admin.provisioning.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.connections.v1": "^2.30.19", diff --git a/features/admin.remote-repository-configuration.v1/package.json b/features/admin.remote-repository-configuration.v1/package.json index cd10cd071b2..660be2774ed 100644 --- a/features/admin.remote-repository-configuration.v1/package.json +++ b/features/admin.remote-repository-configuration.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/admin.remote-userstores.v1/package.json b/features/admin.remote-userstores.v1/package.json index 5924d0d34ed..aad8719006a 100644 --- a/features/admin.remote-userstores.v1/package.json +++ b/features/admin.remote-userstores.v1/package.json @@ -30,7 +30,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.claims.v1": "^2.26.42", diff --git a/features/admin.roles.v1/package.json b/features/admin.roles.v1/package.json index 12eb0b9aa42..bbcecaf39cc 100644 --- a/features/admin.roles.v1/package.json +++ b/features/admin.roles.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.groups.v1": "^2.26.42", diff --git a/features/admin.roles.v2/package.json b/features/admin.roles.v2/package.json index 7a8995b1bb4..7271586657e 100644 --- a/features/admin.roles.v2/package.json +++ b/features/admin.roles.v2/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.api-resources.v2": "^2.25.83", "@wso2is/admin.applications.v1": "^2.30.83", diff --git a/features/admin.saml2-configuration.v1/package.json b/features/admin.saml2-configuration.v1/package.json index cca09d44892..56b3239fafb 100644 --- a/features/admin.saml2-configuration.v1/package.json +++ b/features/admin.saml2-configuration.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/admin.secrets.v1/package.json b/features/admin.secrets.v1/package.json index b52b03e31eb..d53c2759c39 100644 --- a/features/admin.secrets.v1/package.json +++ b/features/admin.secrets.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/admin.server-configurations.v1/package.json b/features/admin.server-configurations.v1/package.json index 5d9edf190e2..2c648374728 100644 --- a/features/admin.server-configurations.v1/package.json +++ b/features/admin.server-configurations.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.extensions.v1": "^2.36.8", diff --git a/features/admin.session-management.v1/package.json b/features/admin.session-management.v1/package.json index 11e359d890d..3a882ae4b70 100644 --- a/features/admin.session-management.v1/package.json +++ b/features/admin.session-management.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/admin.sms-providers.v1/package.json b/features/admin.sms-providers.v1/package.json index 6a64d3a9151..887c01d5867 100644 --- a/features/admin.sms-providers.v1/package.json +++ b/features/admin.sms-providers.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.connections.v1": "^2.30.19", "@wso2is/admin.core.v1": "^2.35.21", diff --git a/features/admin.sms-templates.v1/package.json b/features/admin.sms-templates.v1/package.json index 429bdab43cb..4ca92121ba5 100644 --- a/features/admin.sms-templates.v1/package.json +++ b/features/admin.sms-templates.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.branding.v1": "^2.27.56", "@wso2is/admin.core.v1": "^2.35.21", diff --git a/features/admin.subscription.v1/package.json b/features/admin.subscription.v1/package.json index 25b676b927a..623b2467cc2 100644 --- a/features/admin.subscription.v1/package.json +++ b/features/admin.subscription.v1/package.json @@ -30,7 +30,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.organizations.v1": "^2.26.83", diff --git a/features/admin.tenants.v1/package.json b/features/admin.tenants.v1/package.json index 9ccdea044a7..51e9f60d58b 100644 --- a/features/admin.tenants.v1/package.json +++ b/features/admin.tenants.v1/package.json @@ -17,8 +17,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.extensions.v1": "^2.36.8", diff --git a/features/admin.username-validation.v1/package.json b/features/admin.username-validation.v1/package.json index b1b78828513..069b304ebdb 100644 --- a/features/admin.username-validation.v1/package.json +++ b/features/admin.username-validation.v1/package.json @@ -30,7 +30,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@wso2is/admin.applications.v1": "^2.30.83", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.validation.v1": "^2.27.21", diff --git a/features/admin.users.v1/package.json b/features/admin.users.v1/package.json index 342b146f726..f5ee2010b43 100644 --- a/features/admin.users.v1/package.json +++ b/features/admin.users.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.authentication.v1": "^2.25.83", "@wso2is/admin.authorization.v1": "^2.25.33", diff --git a/features/admin.userstores.v1/package.json b/features/admin.userstores.v1/package.json index f3f8deb89e6..7d535ad55f3 100644 --- a/features/admin.userstores.v1/package.json +++ b/features/admin.userstores.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.extensions.v1": "^2.36.8", diff --git a/features/admin.validation.v1/package.json b/features/admin.validation.v1/package.json index e515f0c7e77..fb3255a0c83 100644 --- a/features/admin.validation.v1/package.json +++ b/features/admin.validation.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.extensions.v1": "^2.36.8", diff --git a/features/admin.workflow-approvals.v1/package.json b/features/admin.workflow-approvals.v1/package.json index 7f9c710bf78..a705e40a396 100644 --- a/features/admin.workflow-approvals.v1/package.json +++ b/features/admin.workflow-approvals.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/admin.wsfed-configuration.v1/package.json b/features/admin.wsfed-configuration.v1/package.json index 9cafb039e2c..0512b9c63da 100644 --- a/features/admin.wsfed-configuration.v1/package.json +++ b/features/admin.wsfed-configuration.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/common.ai.v1/package.json b/features/common.ai.v1/package.json index 9c542cf5ac8..f02ed4804e1 100644 --- a/features/common.ai.v1/package.json +++ b/features/common.ai.v1/package.json @@ -18,8 +18,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/core": "^2.5.5", diff --git a/features/common.branding.v1/package.json b/features/common.branding.v1/package.json index 13fd8649983..b7805fcca8a 100644 --- a/features/common.branding.v1/package.json +++ b/features/common.branding.v1/package.json @@ -13,7 +13,7 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@wso2is/core": "^2.5.5", "@wso2is/admin.core.v1": "^2.35.21", "@wso2is/admin.organizations.v1": "^2.26.83", diff --git a/features/index.ts b/features/index.ts index 60c30bec33a..75976cbb5c4 100644 --- a/features/index.ts +++ b/features/index.ts @@ -43,6 +43,7 @@ export * from "./admin.oidc-scopes.v1/public-api"; export * from "./admin.org-insights.v1/public-api"; export * from "./admin.organization-discovery.v1/public-api"; export * from "./admin.organizations.v1/public-api"; +export * from "./admin.policy-administration.v1/public-api"; export * from "./admin.private-key-jwt.v1/public-api"; export * from "./admin.provisioning.v1/public-api"; export * from "./admin.remote-repository-configuration.v1/public-api"; diff --git a/features/package.json b/features/package.json index cd48285369f..73af543fea5 100644 --- a/features/package.json +++ b/features/package.json @@ -25,8 +25,8 @@ "@mui/material": "^5.13.0", "@mui/system": "^5.12.3", "@mui/utils": "^5.12.3", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@wso2is/access-control": "^3.3.9", "@wso2is/core": "^2.5.5", "@wso2is/dynamic-forms": "^2.4.19", diff --git a/modules/dynamic-forms/package.json b/modules/dynamic-forms/package.json index fc8dc72b83a..e97f59f8624 100644 --- a/modules/dynamic-forms/package.json +++ b/modules/dynamic-forms/package.json @@ -31,7 +31,7 @@ "typecheck": "pnpm compile" }, "dependencies": { - "@oxygen-ui/react": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", "@mui/material": "^5.13.0", "@wso2is/core": "^2.5.5", "@wso2is/validation": "^2.4.0", diff --git a/modules/i18n/src/constants.ts b/modules/i18n/src/constants.ts index 62cd53c1d71..f09d346de40 100644 --- a/modules/i18n/src/constants.ts +++ b/modules/i18n/src/constants.ts @@ -334,6 +334,11 @@ export class I18nModuleConstants { */ public static readonly TENANTS_NAMESPACE: string = "tenants"; + /** + * Policy Administration namespace. + */ + public static readonly POLICY_ADMINISTRATION_NAMESPACE: string = "policyAdministration"; + /** * Remote User Stores namespace. */ diff --git a/modules/i18n/src/models/namespaces/console-ns.ts b/modules/i18n/src/models/namespaces/console-ns.ts index db9041bc0c8..dbabbc08913 100644 --- a/modules/i18n/src/models/namespaces/console-ns.ts +++ b/modules/i18n/src/models/namespaces/console-ns.ts @@ -427,6 +427,7 @@ export interface ConsoleNS { userManagement: string; branding: string; tenants: string; + policyAdministration: string; }; validations: { inSecureURL: { diff --git a/modules/i18n/src/models/namespaces/index.ts b/modules/i18n/src/models/namespaces/index.ts index 1db9f9caeec..f5f8a72e347 100644 --- a/modules/i18n/src/models/namespaces/index.ts +++ b/modules/i18n/src/models/namespaces/index.ts @@ -63,4 +63,5 @@ export * from "./impersonation-ns"; export * from "./actions-ns"; export * from "./tenants-ns"; export * from "./sms-templates-ns"; +export * from "./policy-administration-ns"; export * from "./remote-user-stores-ns"; diff --git a/modules/i18n/src/models/namespaces/policy-administration-ns.ts b/modules/i18n/src/models/namespaces/policy-administration-ns.ts new file mode 100644 index 00000000000..12818da45c0 --- /dev/null +++ b/modules/i18n/src/models/namespaces/policy-administration-ns.ts @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface policyAdministrationNS { + subtitle: string; + title: string; + buttons: { + newPolicy: string; + policyAlgorithm: string; + }; + editPolicy: { + backBtn: string; + }; + createPolicy: { + title: string; + description: string; + }; + advancedSearch: { + placeholder: string; + } + policyAlgorithm: { + title: string; + actionText: string; + primaryBtn: string; + } +} diff --git a/modules/i18n/src/translations/en-US/meta.ts b/modules/i18n/src/translations/en-US/meta.ts index 911b94160e6..12763160707 100644 --- a/modules/i18n/src/translations/en-US/meta.ts +++ b/modules/i18n/src/translations/en-US/meta.ts @@ -70,6 +70,7 @@ export const meta: LocaleMeta = { I18nModuleConstants.ACTIONS_NAMESPACE, I18nModuleConstants.TENANTS_NAMESPACE, I18nModuleConstants.SMS_TEMPLATES_NAMESPACE, + I18nModuleConstants.POLICY_ADMINISTRATION_NAMESPACE, I18nModuleConstants.REMOTE_USER_STORES_NAMESPACE ] }; diff --git a/modules/i18n/src/translations/en-US/portals/console.ts b/modules/i18n/src/translations/en-US/portals/console.ts index 71a8d4f0909..59176d76af0 100644 --- a/modules/i18n/src/translations/en-US/portals/console.ts +++ b/modules/i18n/src/translations/en-US/portals/console.ts @@ -548,7 +548,8 @@ export const console: ConsoleNS = { userAttributesAndStores: "User Attributes & Stores", userManagement: "User Management", branding: "Branding", - tenants: "Root Organizations" + tenants: "Root Organizations", + policyAdministration: "Policy Administration" }, upgrade: "Upgrade", validations: { diff --git a/modules/i18n/src/translations/en-US/portals/index.ts b/modules/i18n/src/translations/en-US/portals/index.ts index 5876aeccd67..3b80dfa6d6f 100644 --- a/modules/i18n/src/translations/en-US/portals/index.ts +++ b/modules/i18n/src/translations/en-US/portals/index.ts @@ -63,4 +63,5 @@ export * from "./impersonation"; export * from "./actions"; export * from "./tenants"; export * from "./sms-templates"; +export * from "./policy-administration"; export * from "./remote-user-stores"; diff --git a/modules/i18n/src/translations/en-US/portals/policy-administration.ts b/modules/i18n/src/translations/en-US/portals/policy-administration.ts new file mode 100644 index 00000000000..4a9273f4cfc --- /dev/null +++ b/modules/i18n/src/translations/en-US/portals/policy-administration.ts @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { policyAdministrationNS } from "../../../models"; + +export const policyAdministration: policyAdministrationNS = { + advancedSearch: { + placeholder: "Search by policy name" + }, + buttons:{ + newPolicy: "New Policy", + policyAlgorithm: "Policy Algorithm" + }, + createPolicy: { + description: "Defines access control rules for secure and fine-grained resource authorization.", + title: "Create Policy" + }, + editPolicy: { + backBtn: "Go back to Policy Administration " + }, + policyAlgorithm: { + actionText: "Select a policy combining algorithm", + primaryBtn: "Update", + title: "Policy Algorithm" + }, + subtitle: "Create and manage your policies here.", + title: "Policy Administration" +}; diff --git a/modules/react-components/package.json b/modules/react-components/package.json index 4e784a8b1ce..e0079bc4bbd 100644 --- a/modules/react-components/package.json +++ b/modules/react-components/package.json @@ -38,8 +38,8 @@ "types": "dist/src/index.d.ts", "dependencies": { "@artsy/fresnel": "^6.1.0", - "@oxygen-ui/react": "^2.2.0", - "@oxygen-ui/react-icons": "^2.2.0", + "@oxygen-ui/react": "^2.3.0", + "@oxygen-ui/react-icons": "^2.3.0", "@storybook/addons": "^6.5.9", "@storybook/builder-webpack5": "^6.5.9", "@storybook/core-server": "^6.5.9", diff --git a/modules/react-components/src/components/file-picker/file-picker.tsx b/modules/react-components/src/components/file-picker/file-picker.tsx index f15674cb7db..efc8c9d7798 100644 --- a/modules/react-components/src/components/file-picker/file-picker.tsx +++ b/modules/react-components/src/components/file-picker/file-picker.tsx @@ -146,6 +146,10 @@ export interface FilePickerProps extends IdentifiableComponentInterface { * Empty file message. */ emptyFileErrorMsg?: string; + /** + * Provide a custom script editor for the paste tab. + */ + scriptEditor?: React.ReactNode; } // Internal workings interfaces, type defs, and aliases. @@ -178,6 +182,7 @@ export const FilePicker: FC = (props: FilePickerPropsAlias): Re file: initialFile, pastedContent: initialPastedContent, normalizeStateOnRemoveOperations, + scriptEditor, emptyFileError, emptyFileErrorMsg, hidePasteOption, @@ -492,44 +497,42 @@ export const FilePicker: FC = (props: FilePickerPropsAlias): Re const pasteOption: PaneItem = { menuItem: "Paste", - render: () => { - return ( -