001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.right; 017 018import java.util.Collections; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.commons.lang3.StringUtils; 028import org.apache.ibatis.session.SqlSession; 029 030import org.ametys.core.ObservationConstants; 031import org.ametys.core.datasource.AbstractMyBatisDAO; 032import org.ametys.core.observation.Event; 033import org.ametys.core.observation.ObservationManager; 034import org.ametys.core.user.CurrentUserProvider; 035 036/** 037 * Manages registration of profiles 038 */ 039public class RightProfilesDAO extends AbstractMyBatisDAO 040{ 041 /** The component role. */ 042 public static final String ROLE = RightProfilesDAO.class.getName(); 043 044 private final String _cache = this.getClass().getName() + "$Cache"; 045 046 private ServiceManager _smanager; 047 048 private ObservationManager _observationManager; 049 050 private CurrentUserProvider _currentUserProvider; 051 052 private RightManager _rightManager; 053 054 @Override 055 public void service(ServiceManager smanager) throws ServiceException 056 { 057 _smanager = smanager; 058 super.service(smanager); 059 } 060 061 private RightManager _getRightManager() 062 { 063 if (_rightManager == null) 064 { 065 try 066 { 067 _rightManager = (RightManager) _smanager.lookup(RightManager.ROLE); 068 } 069 catch (ServiceException e) 070 { 071 throw new IllegalStateException("Cannot get RightManager for RightProfilesDAO", e); 072 } 073 } 074 return _rightManager; 075 } 076 077 /** 078 * Get all existing profiles 079 * @return The list for profiles 080 */ 081 public List<Profile> getProfiles() 082 { 083 try (SqlSession session = getSession()) 084 { 085 return session.selectList("Profiles.getProfiles"); 086 } 087 } 088 089 /** 090 * Get the profiles on a given context 091 * @param context The context. Can be null. If null, the profiles with no context are returned. 092 * @return The list for profiles for this context 093 */ 094 public List<Profile> getProfiles(String context) 095 { 096 try (SqlSession session = getSession()) 097 { 098 if (context == null) 099 { 100 return session.selectList("Profiles.getProfilesWithNullContext"); 101 } 102 else 103 { 104 return session.selectList("Profiles.getProfilesByContext"); 105 } 106 } 107 } 108 109 /** 110 * Get the profile with given identifier 111 * @param id The id of profile to retrieve 112 * @return The profile 113 */ 114 public Profile getProfile(String id) 115 { 116 try (SqlSession session = getSession()) 117 { 118 return session.selectOne("Profiles.getProfile", id); 119 } 120 } 121 122 /** 123 * Get all profiles containing the right wth given id 124 * @param rightId The id of right 125 * @return The id of profiles with this right 126 */ 127 public Set<String> getProfilesWithRight (String rightId) 128 { 129 Map<String, Set<String>> cache = _getRightManager().getCache(_cache, false); 130 if (cache == null) 131 { 132 // Build the cache with only one SQL query 133 cache = _getRightManager().getCache(_cache, true); 134 if (cache == null) 135 { 136 // When not in a request, cache cannot exists 137 cache = new HashMap<>(); 138 } 139 140 try (SqlSession session = getSession()) 141 { 142 List<Map<String, String>> profileRights = session.selectList("Profiles.getProfileRights"); 143 144 for (Map<String, String> profileRight : profileRights) 145 { 146 String currentProfileId = profileRight.get("profileId"); 147 String currentRightId = profileRight.get("rightId"); 148 149 if (cache.containsKey(currentRightId)) 150 { 151 cache.get(currentRightId).add(currentProfileId); 152 } 153 else 154 { 155 Set<String> profiles = new HashSet<>(); 156 profiles.add(currentProfileId); 157 cache.put(currentRightId, profiles); 158 } 159 } 160 } 161 } 162 163 if (cache.containsKey(rightId)) 164 { 165 return cache.get(rightId); 166 } 167 else 168 { 169 return Collections.EMPTY_SET; 170 } 171 } 172 173 /** 174 * Creates a new profile with null context. The identifier of the profile will be automatically generated from label. 175 * @param label The label of profile 176 * @return The create profile 177 */ 178 public Profile addProfile (String label) 179 { 180 return addProfile(label, null); 181 } 182 183 /** 184 * Creates a new profile. The identifier of the profile will be automatically generated from label. 185 * @param label The label of profile 186 * @param context The context. Can be null 187 * @return The create profile 188 */ 189 public Profile addProfile (String label, String context) 190 { 191 String id = _generateUniqueId(label); 192 Profile profile = new Profile(id, label, context); 193 addProfile(profile); 194 return profile; 195 } 196 197 private String _generateUniqueId(String label) 198 { 199 // Id generated from name lowercased, trimmed, and spaces and underscores replaced by dashes 200 String value = label.toLowerCase().trim().replaceAll("[\\W_]", "-").replaceAll("-+", "-").replaceAll("^-", ""); 201 int i = 2; 202 String suffixedValue = value; 203 while (getProfile(suffixedValue) != null) 204 { 205 suffixedValue = value + i; 206 i++; 207 } 208 209 return suffixedValue; 210 } 211 212 /** 213 * Creates a new profile 214 * @param id The unique identifier of profile 215 * @param label The label of profile 216 * @param context The context. Can be null 217 * @return The create profile 218 */ 219 public Profile addProfile (String id, String label, String context) 220 { 221 Profile profile = new Profile(id, label, context); 222 addProfile(profile); 223 return profile; 224 } 225 226 /** 227 * Add a new profile 228 * @param profile The profile to add 229 * @param silent Set to true to not notify observer of this update 230 */ 231 public void addProfile (Profile profile, boolean silent) 232 { 233 try (SqlSession session = getSession(true)) 234 { 235 session.insert("Profiles.addProfile", profile); 236 237 if (!silent) 238 { 239 _notifyEvent(profile, ObservationConstants.EVENT_PROFILE_ADDED); 240 } 241 } 242 } 243 244 /** 245 * Add a new profile 246 * @param profile The profile to add 247 */ 248 public void addProfile (Profile profile) 249 { 250 addProfile(profile, false); 251 } 252 253 /** 254 * Rename a profile 255 * @param profile The profile to rename 256 * @param newLabel The updated label 257 */ 258 public void renameProfile (Profile profile, String newLabel) 259 { 260 renameProfile(profile, newLabel, false); 261 } 262 263 /** 264 * Rename a profile 265 * @param profile The profile to rename 266 * @param newLabel The updated label 267 * @param silent Set to true to not notify observer of this update 268 */ 269 public void renameProfile (Profile profile, String newLabel, boolean silent) 270 { 271 try (SqlSession session = getSession(true)) 272 { 273 Map<String, Object> params = new HashMap<>(); 274 params.put("id", profile.getId()); 275 params.put("label", newLabel); 276 session.update("Profiles.renameProfile", params); 277 278 if (!silent) 279 { 280 _notifyEvent(profile, ObservationConstants.EVENT_PROFILE_UPDATED); 281 } 282 } 283 } 284 285 286 /** 287 * Get the rights of a profile 288 * @param profileId The profile id 289 * @return The rights 290 */ 291 public List<String> getRights (String profileId) 292 { 293 if (StringUtils.isEmpty(profileId)) 294 { 295 return Collections.EMPTY_LIST; 296 } 297 else 298 { 299 try (SqlSession session = getSession()) 300 { 301 return session.selectList("Profiles.getRights", profileId); 302 } 303 } 304 } 305 306 /** 307 * Get the rights of a profile 308 * @param profile The profile 309 * @return The rights 310 */ 311 public List<String> getRights (Profile profile) 312 { 313 if (profile == null) 314 { 315 return Collections.EMPTY_LIST; 316 } 317 else 318 { 319 return getRights(profile.getId()); 320 } 321 } 322 323 /** 324 * Add a right to a profile 325 * @param profile The profile 326 * @param rightId The id of right to add 327 */ 328 public void addRight (Profile profile, String rightId) 329 { 330 try (SqlSession session = getSession(true)) 331 { 332 _addRight (session, profile, rightId); 333 } 334 } 335 336 /** 337 * Add a right to a profile 338 * @param profile The profile 339 * @param rightIds The id of rights to add 340 */ 341 public void addRights (Profile profile, List<String> rightIds) 342 { 343 try (SqlSession session = getSession()) 344 { 345 for (String rightId : rightIds) 346 { 347 _addRight (session, profile, rightId); 348 } 349 350 session.commit(); 351 } 352 } 353 354 /** 355 * Update the rights of a profile 356 * @param profile The profile 357 * @param rights The rights of the profile 358 */ 359 public void updateRights (Profile profile, List<String> rights) 360 { 361 updateRights(profile, rights, false); 362 } 363 364 /** 365 * Update the rights of a profile 366 * @param profile The profile 367 * @param rights The rights of the profile 368 * @param silent Set to true to not notify observer of this update 369 */ 370 public void updateRights (Profile profile, List<String> rights, boolean silent) 371 { 372 try (SqlSession session = getSession()) 373 { 374 session.delete("Profiles.deleteProfileRights", profile.getId()); 375 376 if (rights != null) 377 { 378 for (String rightId : rights) 379 { 380 _addRight (session, profile, rightId); 381 } 382 } 383 384 session.commit(); 385 386 if (!silent) 387 { 388 _notifyEvent(profile, ObservationConstants.EVENT_PROFILE_UPDATED); 389 } 390 } 391 } 392 393 private void _addRight (SqlSession session, Profile profile, String rightId) 394 { 395 Map<String, Object> params = new HashMap<>(); 396 params.put("profileId", profile.getId()); 397 params.put("rightId", rightId); 398 399 session.insert("Profiles.addRight", params); 400 } 401 402 /** 403 * Add a right to a profile 404 * @param profile The profile 405 */ 406 public void removeRights (Profile profile) 407 { 408 removeRights(profile, false); 409 } 410 411 /** 412 * Add a right to a profile 413 * @param profile The profile 414 * @param silent Set to true to not notify observer of this update 415 */ 416 public void removeRights (Profile profile, boolean silent) 417 { 418 try (SqlSession session = getSession(true)) 419 { 420 session.delete("Profiles.deleteProfileRights", profile.getId()); 421 422 if (!silent) 423 { 424 _notifyEvent(profile, ObservationConstants.EVENT_PROFILE_UPDATED); 425 } 426 } 427 } 428 429 /** 430 * Delete a profile 431 * @param profile The profile to delete 432 */ 433 public void deleteProfile (Profile profile) 434 { 435 deleteProfile(profile, false); 436 } 437 438 /** 439 * Delete a profile 440 * @param profile The profile to delete 441 * @param silent Set to true to not notify observer of this update 442 */ 443 public void deleteProfile (Profile profile, boolean silent) 444 { 445 try (SqlSession session = getSession()) 446 { 447 session.delete("Profiles.deleteProfile", profile.getId()); 448 session.delete("Profiles.deleteProfileRights", profile.getId()); 449 450 session.commit(); 451 452 if (!silent) 453 { 454 _notifyEvent(profile, ObservationConstants.EVENT_PROFILE_DELETED); 455 } 456 } 457 } 458 459 private void _notifyEvent (Profile profile, String eventId) 460 { 461 try 462 { 463 if (_observationManager == null) 464 { 465 _observationManager = (ObservationManager) _smanager.lookup(ObservationManager.ROLE); 466 } 467 if (_currentUserProvider == null) 468 { 469 _currentUserProvider = (CurrentUserProvider) _smanager.lookup(CurrentUserProvider.ROLE); 470 } 471 472 Map<String, Object> eventParams = new HashMap<>(); 473 eventParams.put(ObservationConstants.ARGS_PROFILE, profile); 474 _observationManager.notify(new Event(eventId, _currentUserProvider.getUser(), eventParams)); 475 } 476 catch (ServiceException e) 477 { 478 getLogger().error("Fail to notify observers for event '" + eventId + "'", e); 479 } 480 } 481}