Added suborg management for users

This commit is contained in:
frikky
2021-11-22 23:30:54 +01:00
parent d0626b0290
commit 623a365030
5 changed files with 127 additions and 10 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ module main
go 1.15
//replace github.com/shuffle/shuffle-shared => ../../../../git/shuffle-shared
replace github.com/shuffle/shuffle-shared => ../../../../git/shuffle-shared
//replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi
//replace github.com/frikky/go-elasticsearch => ../../../../git/go-elasticsearch
+1 -1
View File
@@ -3056,7 +3056,7 @@ func buildSwaggerApp(resp http.ResponseWriter, body []byte, user shuffle.User) {
if test.Editing && len(user.Id) > 0 {
// Quick verification test
ctx := context.Background()
app, err := shuffle.GetApp(ctx, test.Id, user)
app, err := shuffle.GetApp(ctx, test.Id, user, false)
if err != nil {
log.Printf("[WARNING] Error getting app when editing: %s", app.Name)
resp.WriteHeader(401)
+122 -7
View File
@@ -8,6 +8,8 @@ import {
FormControl,
InputLabel,
Paper,
OutlinedInput,
Checkbox,
Card,
Tooltip,
FormControlLabel,
@@ -70,6 +72,19 @@ const useStyles = makeStyles({
},
});
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 500,
},
},
getContentAnchorEl: () => null,
}
const Admin = (props) => {
const { globalUrl, userdata } = props;
@@ -88,6 +103,7 @@ const Admin = (props) => {
const [loading, setLoading] = React.useState(false);
const [selectedOrganization, setSelectedOrganization] = React.useState({});
//console.log("Selected: ", selectedOrganization)
const [organizationFeatures, setOrganizationFeatures] = React.useState({});
const [loginInfo, setLoginInfo] = React.useState("");
const [curTab, setCurTab] = React.useState(0);
@@ -95,6 +111,7 @@ const Admin = (props) => {
const [organizations, setOrganizations] = React.useState([]);
const [orgSyncResponse, setOrgSyncResponse] = React.useState("");
const [userSettings, setUserSettings] = React.useState({});
const [matchingOrganizations, setMatchingOrganizations] = React.useState([]);
const [environments, setEnvironments] = React.useState([]);
const [authentication, setAuthentication] = React.useState([]);
@@ -1411,7 +1428,10 @@ const Admin = (props) => {
alert.error("Failed setting user: " + responseJson.reason);
} else {
alert.success("Set the user field " + field + " to " + value);
setSelectedUserModalOpen(false);
if (field !== "suborgs") {
setSelectedUserModalOpen(false);
}
}
})
.catch((error) => {
@@ -1557,11 +1577,58 @@ const Admin = (props) => {
</Dialog>
) : null;
const handleOrgEditChange = (event) => {
if (userdata.id === selectedUser.id) {
alert.info("Can't remove orgs from yourself")
return
}
setMatchingOrganizations(event.target.value)
// Workaround for empty orgs
if (event.target.value.length === 0) {
event.target.value.push("REMOVE")
}
setUser(selectedUser.id, "suborgs", event.target.value)
}
const userOrgEdit = selectedUser.id !== undefined && selectedUser.orgs !== undefined && selectedUser.orgs !== null && selectedOrganization.child_orgs !== undefined && selectedOrganization.child_orgs !== null && selectedOrganization.child_orgs.length > 0 ?
<FormControl fullWidth sx={{ m: 1,}}>
<InputLabel id="demo-multiple-checkbox-label" style={{padding: 5}}>Accessible Sub-Organizations ({selectedUser.orgs? selectedUser.orgs.length-1 : 0})</InputLabel>
<Select
fullWidth
style={{width: "100%", }}
disabled={selectedUser.id === userdata.id}
labelId="demo-multiple-checkbox-label"
id="demo-multiple-checkbox"
multiple
value={matchingOrganizations}
onChange={handleOrgEditChange}
input={
<OutlinedInput label="Tag" />
}
renderValue={(selected) => {
return selected.join(', ')
}}
MenuProps={MenuProps}
>
{selectedOrganization.child_orgs.map((org, index) => (
<MenuItem key={index} value={org.id}>
<Checkbox checked={matchingOrganizations.indexOf(org.id) > -1} />
<ListItemText primary={org.name} />
</MenuItem>
))}
</Select>
</FormControl>
: null
const editUserModal = (
<Dialog
open={selectedUserModalOpen}
onClose={() => {
setSelectedUserModalOpen(false);
setImage2FA("");
setSecret2FA("");
}}
PaperProps={{
style: {
@@ -1620,6 +1687,7 @@ const Admin = (props) => {
</Button>
</div>
)}
{isCloud ? null : (
<div style={{ display: "flex" }}>
<TextField
@@ -1657,6 +1725,8 @@ const Admin = (props) => {
</Button>
</div>
)}
{userOrgEdit}
<Divider
style={{
marginTop: 20,
@@ -1664,7 +1734,7 @@ const Admin = (props) => {
backgroundColor: theme.palette.inputColor,
}}
/>
<div style={{ margin: "auto", maxWidth: 400 }}>
<div style={{ margin: "auto", maxWidth: 450 }}>
<Button
style={{}}
variant="outlined"
@@ -1705,7 +1775,7 @@ const Admin = (props) => {
: "Enable 2FA"}
</Button>
</div>
{show2faSetup && isCloud ? (
{show2faSetup ? (
<div
style={{
margin: "auto",
@@ -2578,6 +2648,9 @@ const Admin = (props) => {
</Dialog>
);
const usersView =
curTab === 1 ? (
<div>
@@ -2651,6 +2724,12 @@ const Admin = (props) => {
primary="MFA"
style={{ minWidth: 100, maxWidth: 100 }}
/>
{selectedOrganization.child_orgs !== undefined && selectedOrganization.child_orgs !== null && selectedOrganization.child_orgs.length > 0 ?
<ListItemText
primary="Suborgs"
style={{ minWidth: 100, maxWidth: 100 }}
/>
: null}
<ListItemText
primary="Actions"
style={{ minWidth: 180, maxWidth: 180 }}
@@ -2794,11 +2873,40 @@ const Admin = (props) => {
}
style={{ minWidth: 100, maxWidth: 100 }}
/>
<ListItemText style={{ display: "flex" }}>
{selectedOrganization.child_orgs !== undefined && selectedOrganization.child_orgs !== null && selectedOrganization.child_orgs.length > 0 ?
<ListItemText
style={{ display: "flex" }}
primary={data.orgs === undefined || data.orgs === null ? 0 : data.orgs.length-1}
/>
: null}
<ListItemText style={{ display: "flex" }}>
<IconButton
onClick={() => {
setSelectedUserModalOpen(true);
setSelectedUser(data);
// Find matching orgs between current org and current user's access to those orgs
if (userdata.orgs !== undefined && userdata.orgs !== null && userdata.orgs.length > 0 && selectedOrganization.child_orgs !== undefined && selectedOrganization.child_orgs !== null && selectedOrganization.child_orgs.length > 0) {
console.log("In here?")
var active = []
for (var key in userdata.orgs) {
console.log("ORG: ", userdata.orgs[key])
const found = selectedOrganization.child_orgs.find(item => item.id === userdata.orgs[key].id)
if (found !== null && found !== undefined) {
if (data.orgs === undefined || data.orgs === null) {
continue
}
const subfound = data.orgs.find(item => item === found.id)
if (subfound !== null && subfound !== undefined) {
active.push(subfound)
}
}
}
setMatchingOrganizations(active)
}
}}
>
<EditIcon color="primary" />
@@ -2822,14 +2930,17 @@ const Admin = (props) => {
) : null;
const run2FASetup = (data) => {
console.log("2fa: ", data);
console.log("2fa: ", data, show2faSetup);
if (!show2faSetup) {
get2faCode(data.id);
} else {
// Should remove?
setImage2FA("");
setSecret2FA("");
}
setShow2faSetup(!show2faSetup);
//setShow2faSetup(true);
};
const uploadFiles = (files) => {
@@ -3788,6 +3899,7 @@ const Admin = (props) => {
style={{}}
variant="contained"
color="primary"
disabled={userdata.admin !== "true"}
onClick={() => {
setModalOpen(true);
}}
@@ -3959,7 +4071,7 @@ const Admin = (props) => {
// primary={environment.Registered ? "true" : "false"}
const iconStyle = { marginRight: 10 };
const data = (
const data = (
<div
style={{
width: 1300,
@@ -3982,6 +4094,7 @@ const Admin = (props) => {
</span>
/>
<Tab
disabled={userdata.admin !== "true"}
label=<span>
<AccessibilityNewIcon style={iconStyle} />
Users
@@ -3994,12 +4107,14 @@ const Admin = (props) => {
</span>
/>
<Tab
disabled={userdata.admin !== "true"}
label=<span>
<DescriptionIcon style={iconStyle} />
Files
</span>
/>
<Tab
disabled={userdata.admin !== "true"}
label=<span>
<ScheduleIcon style={iconStyle} />
Schedules
@@ -4007,7 +4122,7 @@ const Admin = (props) => {
/>
<Tab
index={5}
disabled={isCloud}
disabled={isCloud || userdata.admin !== "true"}
label=<span>
<EcoIcon style={iconStyle} />
Environments
+2
View File
@@ -426,6 +426,7 @@ const Settings = (props) => {
}}
/>
);
const landingpageData = (
<div style={{ display: "flex", marginTop: 120 }}>
<Paper style={boxStyle}>
@@ -789,6 +790,7 @@ const Settings = (props) => {
<div style={{ flex: 1, marginTop: 20 }}>
{userdata !== undefined &&
userdata.eth_info !== undefined &&
userdata.eth_info.account !== undefined &&
userdata.eth_info.account.length > 0 ? (
<div style={{ width: "100%", textAlign: "left" }}>
<Typography variant="body2">Network: TBD</Typography>
+1 -1
View File
@@ -2578,7 +2578,7 @@ const Workflows = (props) => {
}
return (
<span style={{ zIndex: 10 }}>
<span key={index} style={{ zIndex: 10 }}>
<IconButton
style={{
backgroundColor: "transparent",