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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.UpdateOrganization(id, &organization))
|
isGlobalAdmin, _ := c.isGlobalAdmin()
|
||||||
|
|
||||||
|
c.Data["json"] = wrapActionResponse(object.UpdateOrganization(id, &organization, isGlobalAdmin))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ type Organization struct {
|
|||||||
UseEmailAsUsername bool `json:"useEmailAsUsername"`
|
UseEmailAsUsername bool `json:"useEmailAsUsername"`
|
||||||
EnableTour bool `json:"enableTour"`
|
EnableTour bool `json:"enableTour"`
|
||||||
IpRestriction string `json:"ipRestriction"`
|
IpRestriction string `json:"ipRestriction"`
|
||||||
|
NavItems []string `xorm:"varchar(500)" json:"navItems"`
|
||||||
|
|
||||||
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
|
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
|
||||||
AccountItems []*AccountItem `xorm:"varchar(5000)" json:"accountItems"`
|
AccountItems []*AccountItem `xorm:"varchar(5000)" json:"accountItems"`
|
||||||
@ -195,9 +196,10 @@ func GetMaskedOrganizations(organizations []*Organization, errs ...error) ([]*Or
|
|||||||
return organizations, nil
|
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)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
if org, err := getOrganization(owner, name); err != nil {
|
org, err := getOrganization(owner, name)
|
||||||
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
} else if org == nil {
|
} else if org == nil {
|
||||||
return false, 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()
|
session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
|
||||||
|
|
||||||
if organization.MasterPassword == "***" {
|
if organization.MasterPassword == "***" {
|
||||||
|
@ -241,7 +241,7 @@ function ManagementPage(props) {
|
|||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img className="logo" src={logo ?? props.logo} alt="logo" />
|
<img className="logo" src={logo ?? props.logo} alt="logo" />
|
||||||
</Link>,
|
</Link>,
|
||||||
disabled: true,
|
disabled: true, key: "logo",
|
||||||
style: {
|
style: {
|
||||||
padding: 0,
|
padding: 0,
|
||||||
height: "auto",
|
height: "auto",
|
||||||
@ -323,7 +323,35 @@ function ManagementPage(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
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) {
|
function renderLoginIfNotLoggedIn(component) {
|
||||||
|
@ -26,6 +26,7 @@ import LdapTable from "./table/LdapTable";
|
|||||||
import AccountTable from "./table/AccountTable";
|
import AccountTable from "./table/AccountTable";
|
||||||
import ThemeEditor from "./common/theme/ThemeEditor";
|
import ThemeEditor from "./common/theme/ThemeEditor";
|
||||||
import MfaTable from "./table/MfaTable";
|
import MfaTable from "./table/MfaTable";
|
||||||
|
import {NavItemTree} from "./common/NavItemTree";
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@ -522,6 +523,21 @@ class OrganizationEditPage extends React.Component {
|
|||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</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"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("organization:Account items"), i18next.t("organization:Account items - Tooltip"))} :
|
{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