View Javadoc
1   package de.dlr.shepard.auth.users.services;
2   
3   import de.dlr.shepard.auth.permission.io.PermissionsIO;
4   import de.dlr.shepard.auth.permission.model.Permissions;
5   import de.dlr.shepard.auth.permission.model.Roles;
6   import de.dlr.shepard.auth.permission.services.PermissionsService;
7   import de.dlr.shepard.auth.security.AuthenticationContext;
8   import de.dlr.shepard.auth.users.daos.UserGroupDAO;
9   import de.dlr.shepard.auth.users.entities.User;
10  import de.dlr.shepard.auth.users.entities.UserGroup;
11  import de.dlr.shepard.auth.users.io.UserGroupIO;
12  import de.dlr.shepard.common.exceptions.InvalidAuthException;
13  import de.dlr.shepard.common.exceptions.InvalidPathException;
14  import de.dlr.shepard.common.util.AccessType;
15  import de.dlr.shepard.common.util.DateHelper;
16  import de.dlr.shepard.common.util.PermissionType;
17  import de.dlr.shepard.common.util.QueryParamHelper;
18  import io.quarkus.logging.Log;
19  import jakarta.enterprise.context.RequestScoped;
20  import jakarta.inject.Inject;
21  import jakarta.ws.rs.NotFoundException;
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.Optional;
25  
26  @RequestScoped
27  public class UserGroupService {
28  
29    @Inject
30    AuthenticationContext authenticationContext;
31  
32    @Inject
33    UserGroupDAO userGroupDAO;
34  
35    @Inject
36    UserService userService;
37  
38    @Inject
39    PermissionsService permissionsService;
40  
41    @Inject
42    DateHelper dateHelper;
43  
44    /**
45     * Gets userGroup by userGroupId
46     *
47     * @param userGroupId
48     * @return UserGroup
49     * @throws InvalidPathException if user group could not be found by id
50     * @throws InvalidAuthException if user has no read permissions on usergroup
51     */
52    public UserGroup getUserGroup(Long userGroupId) {
53      UserGroup group = getUserGroupOptional(userGroupId).orElseThrow(() ->
54        new InvalidPathException(String.format("ID ERROR - User Group with id %s is null or deleted", userGroupId))
55      );
56      assertIsAllowedToReadUserGroup(userGroupId);
57      return group;
58    }
59  
60    /**
61     * Gets userGroup by userGroupId.
62     *
63     * No additional checks like a read permission check are performed.
64     * @param userGroupId
65     * @return Optional<UserGroup>
66     */
67    public Optional<UserGroup> getUserGroupOptional(Long userGroupId) {
68      UserGroup group = userGroupDAO.findByNeo4jId(userGroupId);
69      if (group == null || group.isDeleted()) {
70        return Optional.empty();
71      }
72      return Optional.of(group);
73    }
74  
75    public List<UserGroup> getAllUserGroups(QueryParamHelper params) {
76      return userGroupDAO.findAllUserGroups(params, authenticationContext.getCurrentUserName());
77    }
78  
79    public UserGroup createUserGroup(UserGroupIO userGroup) {
80      var user = userService.getCurrentUser();
81      var toCreate = new UserGroup();
82      toCreate.setName(userGroup.getName());
83      toCreate.setCreatedBy(user);
84      toCreate.setCreatedAt(dateHelper.getDate());
85      toCreate.setUsers(fetchUsers(userGroup.getUsernames()));
86      var created = userGroupDAO.createOrUpdate(toCreate);
87      permissionsService.createPermissions(created, user, PermissionType.Private);
88      return created;
89    }
90  
91    /**
92     * Updates usergroup by id
93     *
94     * @param id
95     * @param userGroup
96     * @return UserGroup
97     * @throws InvalidPathException if user group could not be found by id
98     * @throws InvalidAuthException if user has no read or edit permissions on usergroup
99     */
100   public UserGroup updateUserGroup(Long id, UserGroupIO userGroup) {
101     getUserGroup(id);
102     assertIsAllowedToEditUserGroup(id);
103 
104     var user = userService.getCurrentUser();
105     var old = userGroupDAO.findByNeo4jId(id);
106     old.setUpdatedBy(user);
107     old.setUpdatedAt(dateHelper.getDate());
108     old.setName(userGroup.getName());
109     old.setUsers(fetchUsers(userGroup.getUsernames()));
110     var updated = userGroupDAO.createOrUpdate(old);
111     return updated;
112   }
113 
114   /**
115    * Deletes a user group and removes the permissions
116    * @param id
117    * @throws InvalidPathException if user group could not be found by id
118    * @throws InvalidAuthException if user has no read or edit permissions on usergroup
119    * @throws NotFoundException if the usergroup's permissions could not be retrieved or deleted, or if permissions could not be found on entity with id
120    */
121   public void deleteUserGroup(Long id) {
122     getUserGroup(id);
123     assertIsAllowedToEditUserGroup(id);
124 
125     Optional<Permissions> permissions = permissionsService.getPermissionsOfEntityOptional(id);
126     if (permissions.isPresent() && !permissionsService.deletePermissions(permissions.get())) {
127       String errorMsg = String.format("Could not delete permissions %s", permissions.toString());
128       Log.error(errorMsg);
129       throw new NotFoundException(errorMsg);
130     }
131     if (!userGroupDAO.deleteByNeo4jId(id)) {
132       String errorMsg = String.format("Could not delete userGroup with id %s", id);
133       Log.error(errorMsg);
134       throw new NotFoundException(errorMsg);
135     }
136   }
137 
138   public Roles getUserGroupRoles(long groupId) {
139     getUserGroup(groupId);
140 
141     return permissionsService.getUserRolesOnEntity(groupId, authenticationContext.getCurrentUserName());
142   }
143 
144   public Permissions getUserGroupPermissions(long groupId) {
145     getUserGroup(groupId);
146     assertIsAllowedToManageUserGroup(groupId);
147 
148     return permissionsService.getPermissionsOfEntity(groupId);
149   }
150 
151   public Permissions updateUserGroupPermissions(PermissionsIO newPermissions, long groupId) {
152     getUserGroup(groupId);
153     assertIsAllowedToManageUserGroup(groupId);
154 
155     return permissionsService.updatePermissionsByNeo4jId(newPermissions, groupId);
156   }
157 
158   /**
159    * Checks if the user requested the UserGroup is allowed to read it
160    *
161    * @throws InvalidAuthException when user is not allowed to read the UserGroup
162    */
163   public void assertIsAllowedToReadUserGroup(long groupId) {
164     if (
165       !permissionsService.isAccessTypeAllowedForUser(
166         groupId,
167         AccessType.Read,
168         authenticationContext.getCurrentUserName()
169       )
170     ) {
171       throw new InvalidAuthException("The requested action is forbidden by the permission policies");
172     }
173   }
174 
175   /**
176    * Checks if the user requested the UserGroup is allowed to edit it
177    *
178    * @throws InvalidAuthException when user is not allowed to edit the UserGroup
179    */
180   public void assertIsAllowedToEditUserGroup(long groupId) {
181     if (
182       !permissionsService.isAccessTypeAllowedForUser(
183         groupId,
184         AccessType.Write,
185         authenticationContext.getCurrentUserName()
186       )
187     ) {
188       throw new InvalidAuthException("The requested action is forbidden by the permission policies");
189     }
190   }
191 
192   /**
193    * Checks if the user requested the UserGroup is allowed to manage it
194    *
195    * @throws InvalidAuthException when user is not allowed to manage the UserGroup
196    */
197   public void assertIsAllowedToManageUserGroup(long groupId) {
198     if (
199       !permissionsService.isAccessTypeAllowedForUser(
200         groupId,
201         AccessType.Manage,
202         authenticationContext.getCurrentUserName()
203       )
204     ) {
205       throw new InvalidAuthException("The requested action is forbidden by the permission policies");
206     }
207   }
208 
209   private ArrayList<User> fetchUsers(String[] usernames) {
210     var result = new ArrayList<User>(usernames.length);
211     for (var username : usernames) {
212       if (username == null) {
213         continue;
214       }
215       userService.getUserOptional(username).ifPresent(u -> result.add(u));
216     }
217     return result;
218   }
219 }