Added suborg management for users
This commit is contained in:
@@ -2,7 +2,7 @@ module main
|
|||||||
|
|
||||||
go 1.15
|
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/kin-openapi => ../../../../git/kin-openapi
|
||||||
//replace github.com/frikky/go-elasticsearch => ../../../../git/go-elasticsearch
|
//replace github.com/frikky/go-elasticsearch => ../../../../git/go-elasticsearch
|
||||||
|
|||||||
@@ -3056,7 +3056,7 @@ func buildSwaggerApp(resp http.ResponseWriter, body []byte, user shuffle.User) {
|
|||||||
if test.Editing && len(user.Id) > 0 {
|
if test.Editing && len(user.Id) > 0 {
|
||||||
// Quick verification test
|
// Quick verification test
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
app, err := shuffle.GetApp(ctx, test.Id, user)
|
app, err := shuffle.GetApp(ctx, test.Id, user, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARNING] Error getting app when editing: %s", app.Name)
|
log.Printf("[WARNING] Error getting app when editing: %s", app.Name)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import {
|
|||||||
FormControl,
|
FormControl,
|
||||||
InputLabel,
|
InputLabel,
|
||||||
Paper,
|
Paper,
|
||||||
|
OutlinedInput,
|
||||||
|
Checkbox,
|
||||||
Card,
|
Card,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
FormControlLabel,
|
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 Admin = (props) => {
|
||||||
const { globalUrl, userdata } = props;
|
const { globalUrl, userdata } = props;
|
||||||
|
|
||||||
@@ -88,6 +103,7 @@ const Admin = (props) => {
|
|||||||
const [loading, setLoading] = React.useState(false);
|
const [loading, setLoading] = React.useState(false);
|
||||||
|
|
||||||
const [selectedOrganization, setSelectedOrganization] = React.useState({});
|
const [selectedOrganization, setSelectedOrganization] = React.useState({});
|
||||||
|
//console.log("Selected: ", selectedOrganization)
|
||||||
const [organizationFeatures, setOrganizationFeatures] = React.useState({});
|
const [organizationFeatures, setOrganizationFeatures] = React.useState({});
|
||||||
const [loginInfo, setLoginInfo] = React.useState("");
|
const [loginInfo, setLoginInfo] = React.useState("");
|
||||||
const [curTab, setCurTab] = React.useState(0);
|
const [curTab, setCurTab] = React.useState(0);
|
||||||
@@ -95,6 +111,7 @@ const Admin = (props) => {
|
|||||||
const [organizations, setOrganizations] = React.useState([]);
|
const [organizations, setOrganizations] = React.useState([]);
|
||||||
const [orgSyncResponse, setOrgSyncResponse] = React.useState("");
|
const [orgSyncResponse, setOrgSyncResponse] = React.useState("");
|
||||||
const [userSettings, setUserSettings] = React.useState({});
|
const [userSettings, setUserSettings] = React.useState({});
|
||||||
|
const [matchingOrganizations, setMatchingOrganizations] = React.useState([]);
|
||||||
|
|
||||||
const [environments, setEnvironments] = React.useState([]);
|
const [environments, setEnvironments] = React.useState([]);
|
||||||
const [authentication, setAuthentication] = React.useState([]);
|
const [authentication, setAuthentication] = React.useState([]);
|
||||||
@@ -1411,8 +1428,11 @@ const Admin = (props) => {
|
|||||||
alert.error("Failed setting user: " + responseJson.reason);
|
alert.error("Failed setting user: " + responseJson.reason);
|
||||||
} else {
|
} else {
|
||||||
alert.success("Set the user field " + field + " to " + value);
|
alert.success("Set the user field " + field + " to " + value);
|
||||||
|
|
||||||
|
if (field !== "suborgs") {
|
||||||
setSelectedUserModalOpen(false);
|
setSelectedUserModalOpen(false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
@@ -1557,11 +1577,58 @@ const Admin = (props) => {
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
) : null;
|
) : 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 = (
|
const editUserModal = (
|
||||||
<Dialog
|
<Dialog
|
||||||
open={selectedUserModalOpen}
|
open={selectedUserModalOpen}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setSelectedUserModalOpen(false);
|
setSelectedUserModalOpen(false);
|
||||||
|
setImage2FA("");
|
||||||
|
setSecret2FA("");
|
||||||
}}
|
}}
|
||||||
PaperProps={{
|
PaperProps={{
|
||||||
style: {
|
style: {
|
||||||
@@ -1620,6 +1687,7 @@ const Admin = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isCloud ? null : (
|
{isCloud ? null : (
|
||||||
<div style={{ display: "flex" }}>
|
<div style={{ display: "flex" }}>
|
||||||
<TextField
|
<TextField
|
||||||
@@ -1657,6 +1725,8 @@ const Admin = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{userOrgEdit}
|
||||||
<Divider
|
<Divider
|
||||||
style={{
|
style={{
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
@@ -1664,7 +1734,7 @@ const Admin = (props) => {
|
|||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: theme.palette.inputColor,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div style={{ margin: "auto", maxWidth: 400 }}>
|
<div style={{ margin: "auto", maxWidth: 450 }}>
|
||||||
<Button
|
<Button
|
||||||
style={{}}
|
style={{}}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@@ -1705,7 +1775,7 @@ const Admin = (props) => {
|
|||||||
: "Enable 2FA"}
|
: "Enable 2FA"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{show2faSetup && isCloud ? (
|
{show2faSetup ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
margin: "auto",
|
margin: "auto",
|
||||||
@@ -2578,6 +2648,9 @@ const Admin = (props) => {
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const usersView =
|
const usersView =
|
||||||
curTab === 1 ? (
|
curTab === 1 ? (
|
||||||
<div>
|
<div>
|
||||||
@@ -2651,6 +2724,12 @@ const Admin = (props) => {
|
|||||||
primary="MFA"
|
primary="MFA"
|
||||||
style={{ minWidth: 100, maxWidth: 100 }}
|
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
|
<ListItemText
|
||||||
primary="Actions"
|
primary="Actions"
|
||||||
style={{ minWidth: 180, maxWidth: 180 }}
|
style={{ minWidth: 180, maxWidth: 180 }}
|
||||||
@@ -2794,11 +2873,40 @@ const Admin = (props) => {
|
|||||||
}
|
}
|
||||||
style={{ minWidth: 100, maxWidth: 100 }}
|
style={{ minWidth: 100, maxWidth: 100 }}
|
||||||
/>
|
/>
|
||||||
|
{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" }}>
|
<ListItemText style={{ display: "flex" }}>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedUserModalOpen(true);
|
setSelectedUserModalOpen(true);
|
||||||
setSelectedUser(data);
|
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" />
|
<EditIcon color="primary" />
|
||||||
@@ -2822,14 +2930,17 @@ const Admin = (props) => {
|
|||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
const run2FASetup = (data) => {
|
const run2FASetup = (data) => {
|
||||||
console.log("2fa: ", data);
|
console.log("2fa: ", data, show2faSetup);
|
||||||
if (!show2faSetup) {
|
if (!show2faSetup) {
|
||||||
get2faCode(data.id);
|
get2faCode(data.id);
|
||||||
} else {
|
} else {
|
||||||
// Should remove?
|
// Should remove?
|
||||||
|
setImage2FA("");
|
||||||
|
setSecret2FA("");
|
||||||
}
|
}
|
||||||
|
|
||||||
setShow2faSetup(!show2faSetup);
|
setShow2faSetup(!show2faSetup);
|
||||||
|
//setShow2faSetup(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const uploadFiles = (files) => {
|
const uploadFiles = (files) => {
|
||||||
@@ -3788,6 +3899,7 @@ const Admin = (props) => {
|
|||||||
style={{}}
|
style={{}}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
disabled={userdata.admin !== "true"}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setModalOpen(true);
|
setModalOpen(true);
|
||||||
}}
|
}}
|
||||||
@@ -3982,6 +4094,7 @@ const Admin = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
|
disabled={userdata.admin !== "true"}
|
||||||
label=<span>
|
label=<span>
|
||||||
<AccessibilityNewIcon style={iconStyle} />
|
<AccessibilityNewIcon style={iconStyle} />
|
||||||
Users
|
Users
|
||||||
@@ -3994,12 +4107,14 @@ const Admin = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
|
disabled={userdata.admin !== "true"}
|
||||||
label=<span>
|
label=<span>
|
||||||
<DescriptionIcon style={iconStyle} />
|
<DescriptionIcon style={iconStyle} />
|
||||||
Files
|
Files
|
||||||
</span>
|
</span>
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
|
disabled={userdata.admin !== "true"}
|
||||||
label=<span>
|
label=<span>
|
||||||
<ScheduleIcon style={iconStyle} />
|
<ScheduleIcon style={iconStyle} />
|
||||||
Schedules
|
Schedules
|
||||||
@@ -4007,7 +4122,7 @@ const Admin = (props) => {
|
|||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
index={5}
|
index={5}
|
||||||
disabled={isCloud}
|
disabled={isCloud || userdata.admin !== "true"}
|
||||||
label=<span>
|
label=<span>
|
||||||
<EcoIcon style={iconStyle} />
|
<EcoIcon style={iconStyle} />
|
||||||
Environments
|
Environments
|
||||||
|
|||||||
@@ -426,6 +426,7 @@ const Settings = (props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const landingpageData = (
|
const landingpageData = (
|
||||||
<div style={{ display: "flex", marginTop: 120 }}>
|
<div style={{ display: "flex", marginTop: 120 }}>
|
||||||
<Paper style={boxStyle}>
|
<Paper style={boxStyle}>
|
||||||
@@ -789,6 +790,7 @@ const Settings = (props) => {
|
|||||||
<div style={{ flex: 1, marginTop: 20 }}>
|
<div style={{ flex: 1, marginTop: 20 }}>
|
||||||
{userdata !== undefined &&
|
{userdata !== undefined &&
|
||||||
userdata.eth_info !== undefined &&
|
userdata.eth_info !== undefined &&
|
||||||
|
userdata.eth_info.account !== undefined &&
|
||||||
userdata.eth_info.account.length > 0 ? (
|
userdata.eth_info.account.length > 0 ? (
|
||||||
<div style={{ width: "100%", textAlign: "left" }}>
|
<div style={{ width: "100%", textAlign: "left" }}>
|
||||||
<Typography variant="body2">Network: TBD</Typography>
|
<Typography variant="body2">Network: TBD</Typography>
|
||||||
|
|||||||
@@ -2578,7 +2578,7 @@ const Workflows = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span style={{ zIndex: 10 }}>
|
<span key={index} style={{ zIndex: 10 }}>
|
||||||
<IconButton
|
<IconButton
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
|
|||||||
Reference in New Issue
Block a user