mirror of https://github.com/portainer/portainer
				
				
				
			fix(permissions): non admin access to view users [EE-5825] (#10352)
* fix non admin access to view users * review comments and fix testspull/10372/head
							parent
							
								
									13c48ab961
								
							
						
					
					
						commit
						3c4660bbf3
					
				| 
						 | 
				
			
			@ -31,7 +31,7 @@ func (handler *Handler) userList(w http.ResponseWriter, r *http.Request) *httper
 | 
			
		|||
		return httperror.InternalServerError("Unable to retrieve info from request context", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !securityContext.IsAdmin {
 | 
			
		||||
	if !securityContext.IsAdmin && !securityContext.IsTeamLeader {
 | 
			
		||||
		return httperror.Forbidden("Permission denied to access users list", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +42,9 @@ func (handler *Handler) userList(w http.ResponseWriter, r *http.Request) *httper
 | 
			
		|||
 | 
			
		||||
	endpointID, _ := request.RetrieveNumericQueryParameter(r, "environmentId", true)
 | 
			
		||||
	if endpointID == 0 {
 | 
			
		||||
		if securityContext.IsAdmin {
 | 
			
		||||
			sanitizeUsers(users)
 | 
			
		||||
		}
 | 
			
		||||
		return response.JSON(w, users)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +63,9 @@ func (handler *Handler) userList(w http.ResponseWriter, r *http.Request) *httper
 | 
			
		|||
	for _, user := range users {
 | 
			
		||||
		// the users who have the endpoint authorization
 | 
			
		||||
		if _, ok := user.EndpointAuthorizations[endpoint.ID]; ok {
 | 
			
		||||
			if securityContext.IsAdmin {
 | 
			
		||||
				sanitizeUser(&user)
 | 
			
		||||
			}
 | 
			
		||||
			canAccessEndpoint = append(canAccessEndpoint, user)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -71,9 +77,27 @@ func (handler *Handler) userList(w http.ResponseWriter, r *http.Request) *httper
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		if security.AuthorizedEndpointAccess(endpoint, endpointGroup, user.ID, teamMemberships) {
 | 
			
		||||
			if securityContext.IsAdmin {
 | 
			
		||||
				sanitizeUser(&user)
 | 
			
		||||
			}
 | 
			
		||||
			canAccessEndpoint = append(canAccessEndpoint, user)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return response.JSON(w, canAccessEndpoint)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sanitizeUser(user *portainer.User) {
 | 
			
		||||
	user.Password = ""
 | 
			
		||||
	user.EndpointAuthorizations = nil
 | 
			
		||||
	user.ThemeSettings = portainer.UserThemeSettings{}
 | 
			
		||||
	user.PortainerAuthorizations = nil
 | 
			
		||||
	user.UserTheme = ""
 | 
			
		||||
	user.TokenIssueAt = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sanitizeUsers(users []portainer.User) {
 | 
			
		||||
	for i := range users {
 | 
			
		||||
		sanitizeUser(&users[i])
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,6 @@ import { UserId } from '@/portainer/users/types';
 | 
			
		|||
import { TeamId } from '@/react/portainer/users/teams/types';
 | 
			
		||||
import { useTeams } from '@/react/portainer/users/teams/queries';
 | 
			
		||||
import { useUsers } from '@/portainer/users/queries';
 | 
			
		||||
import { useCurrentUser } from '@/react/hooks/useUser';
 | 
			
		||||
import { pluralize } from '@/portainer/helpers/strings';
 | 
			
		||||
 | 
			
		||||
import { Link } from '@@/Link';
 | 
			
		||||
| 
						 | 
				
			
			@ -31,8 +30,6 @@ export function AccessControlPanelDetails({
 | 
			
		|||
  resourceControl,
 | 
			
		||||
  resourceType,
 | 
			
		||||
}: Props) {
 | 
			
		||||
  const { isAdmin } = useCurrentUser();
 | 
			
		||||
 | 
			
		||||
  const inheritanceMessage = getInheritanceMessage(
 | 
			
		||||
    resourceType,
 | 
			
		||||
    resourceControl
 | 
			
		||||
| 
						 | 
				
			
			@ -44,10 +41,7 @@ export function AccessControlPanelDetails({
 | 
			
		|||
    TeamAccesses: restrictedToTeams = [],
 | 
			
		||||
  } = resourceControl || {};
 | 
			
		||||
 | 
			
		||||
  const users = useAuthorizedUsers(
 | 
			
		||||
    restrictedToUsers.map((ra) => ra.UserId),
 | 
			
		||||
    isAdmin
 | 
			
		||||
  );
 | 
			
		||||
  const users = useAuthorizedUsers(restrictedToUsers.map((ra) => ra.UserId));
 | 
			
		||||
  const teams = useAuthorizedTeams(restrictedToTeams.map((ra) => ra.TeamId));
 | 
			
		||||
 | 
			
		||||
  const teamsLength = teams.data ? teams.data.length : 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -62,8 +56,8 @@ export function AccessControlPanelDetails({
 | 
			
		|||
    )} you are not part of`;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const userMessage = isAdmin
 | 
			
		||||
    ? (users.data && users.data.join(', ')) || ''
 | 
			
		||||
  const userMessage = users.data
 | 
			
		||||
    ? users.data.join(', ')
 | 
			
		||||
    : `${restrictedToUsers.length} ${pluralize(
 | 
			
		||||
        restrictedToUsers.length,
 | 
			
		||||
        'user'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ export function ListView() {
 | 
			
		|||
    <>
 | 
			
		||||
      <PageHeader title="Teams" breadcrumbs={[{ label: 'Teams management' }]} />
 | 
			
		||||
 | 
			
		||||
      {usersQuery.data && teamsQuery.data && (
 | 
			
		||||
      {isAdmin && usersQuery.data && teamsQuery.data && (
 | 
			
		||||
        <CreateTeamForm users={usersQuery.data} teams={teamsQuery.data} />
 | 
			
		||||
      )}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue