diff --git a/models/user.go b/models/user.go index 53e3270be..15cd39c12 100644 --- a/models/user.go +++ b/models/user.go @@ -37,6 +37,9 @@ type User struct { // access key AccessKey string `json:"accessKey,omitempty"` + // has policy + HasPolicy bool `json:"hasPolicy,omitempty"` + // member of MemberOf []string `json:"memberOf"` diff --git a/portal-ui/src/screens/Console/Users/UserDetails.tsx b/portal-ui/src/screens/Console/Users/UserDetails.tsx index f92515aeb..3c094a96c 100644 --- a/portal-ui/src/screens/Console/Users/UserDetails.tsx +++ b/portal-ui/src/screens/Console/Users/UserDetails.tsx @@ -151,6 +151,7 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => { const [changeUserPasswordModalOpen, setChangeUserPasswordModalOpen] = useState(false); const [deleteOpen, setDeleteOpen] = useState(false); + const [hasPolicy, setHasPolicy] = useState(false); const userName = match.params["userName"]; @@ -188,6 +189,7 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => { } setCurrentPolicies(currentPolicies); setEnabled(res.status === "enabled"); + setHasPolicy(res.hasPolicy) setLoading(false); }) .catch((err: ErrorResponseHandler) => { @@ -382,7 +384,7 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => { /> - +
diff --git a/portal-ui/src/screens/Console/Users/UserServiceAccountsPanel.tsx b/portal-ui/src/screens/Console/Users/UserServiceAccountsPanel.tsx index 168b0e7bb..d4b578d20 100644 --- a/portal-ui/src/screens/Console/Users/UserServiceAccountsPanel.tsx +++ b/portal-ui/src/screens/Console/Users/UserServiceAccountsPanel.tsx @@ -38,6 +38,7 @@ interface IUserServiceAccountsProps { classes: any; user: string; setErrorSnackMessage: typeof setErrorSnackMessage; + hasPolicy: boolean; } const styles = (theme: Theme) => @@ -53,6 +54,7 @@ const UserServiceAccountsPanel = ({ classes, user, setErrorSnackMessage, + hasPolicy, }: IUserServiceAccountsProps) => { const [records, setRecords] = useState([]); const [loading, setLoading] = useState(false); @@ -75,7 +77,6 @@ const UserServiceAccountsPanel = ({ .invoke("GET", `/api/v1/user/${user}/service-accounts`) .then((res: string[]) => { const serviceAccounts = res.sort(stringSort); - setLoading(false); setRecords(serviceAccounts); }) @@ -169,6 +170,7 @@ const UserServiceAccountsPanel = ({ setAddScreenOpen(true); setSelectedServiceAccount(null); }} + disabled={!hasPolicy} > Create service account diff --git a/restapi/admin_users.go b/restapi/admin_users.go index 080894edf..bc0b36d3a 100644 --- a/restapi/admin_users.go +++ b/restapi/admin_users.go @@ -281,11 +281,35 @@ func getUserInfoResponse(session *models.Principal, params admin_api.GetUserInfo return nil, prepareError(err) } + var policies []string + if user.PolicyName == "" { + policies = []string{} + } else { + policies = strings.Split(user.PolicyName, ",") + } + + hasPolicy := true + + if len(policies) == 0 { + hasPolicy = false + for i := 0; i < len(user.MemberOf); i++ { + group, err := adminClient.getGroupDescription(ctx, user.MemberOf[i]) + if err != nil { + continue + } + if group.Policy != "" { + hasPolicy = true + break + } + } + } + userInformation := &models.User{ AccessKey: params.Name, MemberOf: user.MemberOf, - Policy: strings.Split(user.PolicyName, ","), + Policy: policies, Status: string(user.Status), + HasPolicy: hasPolicy, } return userInformation, nil diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 900229493..c0f1146bc 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -5454,6 +5454,9 @@ func init() { "accessKey": { "type": "string" }, + "hasPolicy": { + "type": "boolean" + }, "memberOf": { "type": "array", "items": { @@ -11049,6 +11052,9 @@ func init() { "accessKey": { "type": "string" }, + "hasPolicy": { + "type": "boolean" + }, "memberOf": { "type": "array", "items": { diff --git a/swagger-console.yml b/swagger-console.yml index 91ab05635..c597774cf 100644 --- a/swagger-console.yml +++ b/swagger-console.yml @@ -2485,6 +2485,9 @@ definitions: type: string status: type: string + hasPolicy: + type: boolean + listUsersResponse: type: object properties: