mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 02:35:49 +08:00
feat: can define what Casdoor pages an org admin can see via Organization.NavItems (#3539)
* feat: support define what Casdoor pages an org admin can see * feat: remove useless code * fix: fix NavItemNodes i18next invalid * fix: only global admin can edit navItems * fix: move navItem tree to extra file
This commit is contained in:
parent
e3001671a2
commit
df295717f0
@ -124,7 +124,9 @@ func (c *ApiController) UpdateOrganization() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateOrganization(id, &organization))
|
||||
isGlobalAdmin, _ := c.isGlobalAdmin()
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateOrganization(id, &organization, isGlobalAdmin))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,7 @@ type Organization struct {
|
||||
UseEmailAsUsername bool `json:"useEmailAsUsername"`
|
||||
EnableTour bool `json:"enableTour"`
|
||||
IpRestriction string `json:"ipRestriction"`
|
||||
NavItems []string `xorm:"varchar(500)" json:"navItems"`
|
||||
|
||||
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
|
||||
AccountItems []*AccountItem `xorm:"varchar(5000)" json:"accountItems"`
|
||||
@ -195,9 +196,10 @@ func GetMaskedOrganizations(organizations []*Organization, errs ...error) ([]*Or
|
||||
return organizations, nil
|
||||
}
|
||||
|
||||
func UpdateOrganization(id string, organization *Organization) (bool, error) {
|
||||
func UpdateOrganization(id string, organization *Organization, isGlobalAdmin bool) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
if org, err := getOrganization(owner, name); err != nil {
|
||||
org, err := getOrganization(owner, name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
} else if org == nil {
|
||||
return false, nil
|
||||
@ -222,6 +224,10 @@ func UpdateOrganization(id string, organization *Organization) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if !isGlobalAdmin {
|
||||
organization.NavItems = org.NavItems
|
||||
}
|
||||
|
||||
session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
|
||||
if organization.MasterPassword == "***" {
|
||||
|
@ -241,7 +241,7 @@ function ManagementPage(props) {
|
||||
<Link to="/">
|
||||
<img className="logo" src={logo ?? props.logo} alt="logo" />
|
||||
</Link>,
|
||||
disabled: true,
|
||||
disabled: true, key: "logo",
|
||||
style: {
|
||||
padding: 0,
|
||||
height: "auto",
|
||||
@ -323,9 +323,37 @@ function ManagementPage(props) {
|
||||
}
|
||||
}
|
||||
|
||||
const navItems = props.account.organization.navItems;
|
||||
|
||||
if (!Array.isArray(navItems)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (navItems.includes("all")) {
|
||||
return res;
|
||||
}
|
||||
|
||||
const resFiltered = res.map(item => {
|
||||
if (!Array.isArray(item.children)) {
|
||||
return item;
|
||||
}
|
||||
const filteredChildren = [];
|
||||
item.children.forEach(itemChild => {
|
||||
if (navItems.includes(itemChild.key)) {
|
||||
filteredChildren.push(itemChild);
|
||||
}
|
||||
});
|
||||
|
||||
item.children = filteredChildren;
|
||||
return item;
|
||||
});
|
||||
|
||||
return resFiltered.filter(item => {
|
||||
if (item.key === "#" || item.key === "logo") {return true;}
|
||||
return Array.isArray(item.children) && item.children.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
function renderLoginIfNotLoggedIn(component) {
|
||||
if (props.account === null) {
|
||||
sessionStorage.setItem("from", window.location.pathname);
|
||||
|
@ -26,6 +26,7 @@ import LdapTable from "./table/LdapTable";
|
||||
import AccountTable from "./table/AccountTable";
|
||||
import ThemeEditor from "./common/theme/ThemeEditor";
|
||||
import MfaTable from "./table/MfaTable";
|
||||
import {NavItemTree} from "./common/NavItemTree";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
@ -522,6 +523,21 @@ class OrganizationEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Navbar items"), i18next.t("general:Navbar items - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<NavItemTree
|
||||
disabled={!Setting.isAdminUser(this.props.account)}
|
||||
checkedKeys={this.state.organization.navItems ?? ["all"]}
|
||||
defaultExpandedKeys={["all"]}
|
||||
onCheck={(checked, _) => {
|
||||
this.updateOrganizationField("navItems", checked);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("organization:Account items"), i18next.t("organization:Account items - Tooltip"))} :
|
||||
|
97
web/src/common/NavItemTree.js
Normal file
97
web/src/common/NavItemTree.js
Normal file
@ -0,0 +1,97 @@
|
||||
import i18next from "i18next";
|
||||
import {Tree} from "antd";
|
||||
import React from "react";
|
||||
|
||||
export const NavItemTree = ({disable, checkedKeys, defaultExpandedKeys, onCheck}) => {
|
||||
const NavItemNodes = [
|
||||
{
|
||||
title: i18next.t("organization:All"),
|
||||
key: "all",
|
||||
children: [
|
||||
{
|
||||
title: i18next.t("general:Home"),
|
||||
key: "/home-top",
|
||||
children: [
|
||||
{title: i18next.t("general:Dashboard"), key: "/"},
|
||||
{title: i18next.t("general:Shortcuts"), key: "/shortcuts"},
|
||||
{title: i18next.t("general:Apps"), key: "/apps"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:User Management"),
|
||||
key: "/orgs-top",
|
||||
children: [
|
||||
{title: i18next.t("general:Organizations"), key: "/organizations"},
|
||||
{title: i18next.t("general:Groups"), key: "/groups"},
|
||||
{title: i18next.t("general:Users"), key: "/users"},
|
||||
{title: i18next.t("general:Invitations"), key: "/invitations"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Identity"),
|
||||
key: "/applications-top",
|
||||
children: [
|
||||
{title: i18next.t("general:Applications"), key: "/applications"},
|
||||
{title: i18next.t("general:Providers"), key: "/providers"},
|
||||
{title: i18next.t("general:Resources"), key: "/resources"},
|
||||
{title: i18next.t("general:Certs"), key: "/certs"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Authorization"),
|
||||
key: "/roles-top",
|
||||
children: [
|
||||
{title: i18next.t("general:Applications"), key: "/roles"},
|
||||
{title: i18next.t("general:Permissions"), key: "/permissions"},
|
||||
{title: i18next.t("general:Models"), key: "/models"},
|
||||
{title: i18next.t("general:Adapters"), key: "/adapters"},
|
||||
{title: i18next.t("general:Enforcers"), key: "/enforcers"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Logging & Auditing"),
|
||||
key: "/sessions-top",
|
||||
children: [
|
||||
{title: i18next.t("general:Sessions"), key: "/sessions"},
|
||||
{title: i18next.t("general:Records"), key: "/records"},
|
||||
{title: i18next.t("general:Tokens"), key: "/tokens"},
|
||||
{title: i18next.t("general:Verifications"), key: "/verifications"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Business & Payments"),
|
||||
key: "/business-top",
|
||||
children: [
|
||||
{title: i18next.t("general:Products"), key: "/products"},
|
||||
{title: i18next.t("general:Payments"), key: "/payments"},
|
||||
{title: i18next.t("general:Plans"), key: "/plans"},
|
||||
{title: i18next.t("general:Pricings"), key: "/pricings"},
|
||||
{title: i18next.t("general:Subscriptions"), key: "/subscriptions"},
|
||||
{title: i18next.t("general:Transactions"), key: "/transactions"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Admin"),
|
||||
key: "/admin-top",
|
||||
children: [
|
||||
{title: i18next.t("general:System Info"), key: "/sysinfo"},
|
||||
{title: i18next.t("general:Syncers"), key: "/syncers"},
|
||||
{title: i18next.t("general:Webhooks"), key: "/webhooks"},
|
||||
{title: i18next.t("general:Swagger"), key: "/swagger"},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Tree
|
||||
disabled={disable}
|
||||
checkable
|
||||
checkedKeys={checkedKeys}
|
||||
defaultExpandedKeys={defaultExpandedKeys}
|
||||
onCheck={onCheck}
|
||||
treeData={NavItemNodes}
|
||||
/>
|
||||
);
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user