View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.user2;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.LinkedList;
26  import java.util.List;
27  import java.util.SortedSet;
28  import java.util.TreeSet;
29  
30  import org.apache.logging.log4j.LogManager;
31  import org.apache.logging.log4j.Logger;
32  import org.mycore.datamodel.classifications2.MCRCategLinkReference;
33  import org.mycore.datamodel.classifications2.MCRCategLinkService;
34  import org.mycore.datamodel.classifications2.MCRCategLinkServiceFactory;
35  import org.mycore.datamodel.classifications2.MCRCategory;
36  import org.mycore.datamodel.classifications2.MCRCategoryDAO;
37  import org.mycore.datamodel.classifications2.MCRCategoryDAOFactory;
38  import org.mycore.datamodel.classifications2.MCRCategoryID;
39  import org.mycore.datamodel.classifications2.MCRLabel;
40  import org.mycore.datamodel.classifications2.impl.MCRCategoryImpl;
41  
42  /**
43   * Manages roles and role assignments using a database table.
44   * 
45   * @author Frank L\u00fctzenkirchen
46   * @author Thomas Scheffler (yagee)
47   */
48  public class MCRRoleManager {
49  
50      private static Logger LOGGER = LogManager.getLogger(MCRRoleManager.class);
51  
52      /** Map of defined roles, key is the unique role name */
53      private static HashMap<String, MCRRole> rolesByName = new HashMap<>();
54  
55      /** List of all defined roles */
56      private static List<MCRRole> rolesList = new ArrayList<>();
57  
58      private static final MCRCategoryDAO DAO = MCRCategoryDAOFactory.getInstance();
59  
60      private static long lastLoaded;
61  
62      private static final MCRCategLinkService CATEG_LINK_SERVICE = MCRCategLinkServiceFactory.getInstance();
63  
64      static {
65          loadSystemRoles();
66      }
67  
68      private static void loadSystemRoles() {
69          if (lastLoaded == DAO.getLastModified() || !DAO.exist(MCRUser2Constants.ROLE_CLASSID)) {
70              return;
71          }
72          lastLoaded = DAO.getLastModified();
73          int onlyNonHierarchicalRoles = 1;
74          MCRCategory roleCategory = DAO.getCategory(MCRUser2Constants.ROLE_CLASSID, onlyNonHierarchicalRoles);
75          rolesByName.clear();
76          rolesList.clear();
77          if (roleCategory != null) {
78              for (MCRCategory child : roleCategory.getChildren()) {
79                  String name = child.getId().getID();
80                  MCRRole role = new MCRRole(name, child.getLabels());
81                  rolesByName.put(name, role);
82                  rolesList.add(role);
83              }
84          }
85      }
86  
87      /**
88       * Returns the role with the given role name, or null.
89       * 
90       * @param name the unique role name
91       * @return the role with the given role name, or null.
92       */
93      public static MCRRole getRole(String name) {
94          loadSystemRoles();
95          MCRRole mcrRole = rolesByName.get(name);
96          if (mcrRole == null) {
97              return getExternalRole(name);
98          }
99          return mcrRole;
100     }
101 
102     /**
103      * Factory for external roles
104      * @param name a valid {@link MCRCategoryID}
105      * @return MCRRole instance or null if category does not exist
106      */
107     public static MCRRole getExternalRole(String name) {
108         MCRCategoryID categoryID = MCRCategoryID.fromString(name);
109         if (categoryID.isRootID()) {
110             LOGGER.debug("External role may not be a rootCategory: {}", categoryID);
111             return null;
112         }
113         MCRCategory category = DAO.getCategory(categoryID, 0);
114         if (category == null) {
115             LOGGER.debug("Category does not exist: {}", categoryID);
116             return null;
117         }
118         return new MCRRole(name, category.getLabels());
119     }
120 
121     /**
122      * Returns a role array for the given role names. 
123      * @param names unique role names
124      * @return array each element either MCRRole instance, or null
125      */
126     public static MCRRole[] getRoles(String... names) {
127         loadSystemRoles();
128         MCRRole[] roles = new MCRRole[names.length];
129         for (int i = 0; i < names.length; i++) {
130             roles[i] = rolesByName.get(names[i]);
131             if (roles[i] == null) {
132                 roles[i] = getExternalRole(names[i]);
133             }
134         }
135         return roles;
136     }
137 
138     /**
139      * Returns a role collection for the given role names.
140      * If a role is not known the returning collection contains fewer items.
141      * @param names unique role names
142      * @return collection each element is MCRRole instance.
143      */
144     public static Collection<MCRRole> getRoles(Collection<String> names) {
145         loadSystemRoles();
146         String[] namesArr = names.toArray(new String[names.size()]);
147         MCRRole[] roles = getRoles(namesArr);
148         return Arrays.asList(roles);
149     }
150 
151     /**
152      * Returns a list of all defined roles
153      * 
154      * @return a list of all defined roles
155      */
156     public static List<MCRRole> listSystemRoles() {
157         return rolesList;
158     }
159 
160     /**
161      * Removes user from all roles
162      * 
163      * @param user the user to remove from all roles
164      */
165     static void unassignRoles(MCRUser user) {
166         CATEG_LINK_SERVICE.deleteLink(getLinkID(user));
167     }
168 
169     /**
170      * Stores role membership information of the user
171      * 
172      * @param user the user 
173      */
174     static void storeRoleAssignments(MCRUser user) {
175         MCRCategLinkReference ref = getLinkID(user);
176         LinkedList<MCRCategoryID> categories = new LinkedList<>();
177         for (String roleID : user.getSystemRoleIDs()) {
178             MCRCategoryID categID = new MCRCategoryID(MCRUser2Constants.ROLE_CLASSID.getRootID(), roleID);
179             categories.add(categID);
180         }
181         for (String roleID : user.getExternalRoleIDs()) {
182             MCRCategoryID categID = MCRCategoryID.fromString(roleID);
183             categories.add(categID);
184         }
185         LOGGER.info("Assigning {} to these roles: {}", user.getUserID(), categories);
186         CATEG_LINK_SERVICE.setLinks(ref, categories);
187     }
188 
189     static Collection<MCRCategoryID> getRoleIDs(MCRUser user) {
190         return CATEG_LINK_SERVICE.getLinksFromReference(getLinkID(user));
191     }
192 
193     static boolean isAssignedToRole(MCRUser user, String roleID) {
194         MCRCategoryID categoryID = MCRCategoryID.fromString(roleID);
195         MCRCategLinkReference linkReference = getLinkID(user);
196         return CATEG_LINK_SERVICE.isInCategory(linkReference, categoryID);
197     }
198 
199     private static MCRCategLinkReference getLinkID(MCRUser user) {
200         return new MCRCategLinkReference(user.getUserName() + "@" + user.getRealmID(),
201             MCRUser2Constants.CATEG_LINK_TYPE);
202     }
203 
204     /**
205      * Adds <code>role</code> to the classification system.
206      * If the representing {@link MCRCategory} already exists this method does nothing.
207      * It will create any category if necessary. 
208      */
209     public static void addRole(MCRRole role) {
210         MCRCategoryID categoryID = null;
211         if (role.isSystemRole()) {
212             categoryID = new MCRCategoryID(MCRUser2Constants.ROLE_CLASSID.getRootID(), role.getName());
213         } else {
214             categoryID = MCRCategoryID.fromString(role.getName());
215         }
216         if (DAO.exist(categoryID)) {
217             return;
218         }
219         MCRCategoryID rootID = MCRCategoryID.rootID(categoryID.getRootID());
220         if (!DAO.exist(rootID)) {
221             MCRCategoryImpl category = new MCRCategoryImpl();
222             category.setId(rootID);
223             SortedSet<MCRLabel> labels = new TreeSet<>();
224             labels.add(new MCRLabel("de", "Systemrollen", null));
225             labels.add(new MCRLabel("en", "system roles", null));
226             category.setLabels(labels);
227             DAO.addCategory(null, category);
228         }
229         MCRCategoryImpl category = new MCRCategoryImpl();
230         category.setId(categoryID);
231         category.getLabels().addAll(role.getLabels());
232         DAO.addCategory(rootID, category);
233     }
234 
235     /**
236      * Deletes a role from the system.
237      * If the role is currently not stored in the classification system this method does nothing.
238      * This method will fail if any objects (e.g. users) are linked to it.
239      */
240     public static void deleteRole(String roleID) {
241         MCRRole role = MCRRoleManager.getRole(roleID);
242         if (role == null) {
243             //unknown role
244             return;
245         }
246         MCRCategoryID categoryID = null;
247         if (role.isSystemRole()) {
248             categoryID = new MCRCategoryID(MCRUser2Constants.ROLE_CLASSID.getRootID(), role.getName());
249         } else {
250             categoryID = MCRCategoryID.fromString(role.getName());
251         }
252         DAO.deleteCategory(categoryID);
253     }
254 
255     /**
256      * Returns a collection of userIDs linked to the given <code>role</code>.
257      * @param role role to list user IDs.
258      */
259     public static Collection<String> listUserIDs(MCRRole role) {
260         MCRCategoryID categoryID = getCategoryID(role);
261         return CATEG_LINK_SERVICE.getLinksFromCategoryForType(categoryID, MCRUser2Constants.CATEG_LINK_TYPE);
262     }
263 
264     private static MCRCategoryID getCategoryID(MCRRole role) {
265         if (role.isSystemRole()) {
266             return new MCRCategoryID(MCRUser2Constants.ROLE_CLASSID.getRootID(), role.getName());
267         }
268         return MCRCategoryID.fromString(role.getName());
269     }
270 }