001/* 002 * Copyright 2021 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.plugins.extraction.execution; 017 018import java.io.IOException; 019import java.util.Collection; 020import java.util.HashMap; 021import java.util.Map; 022import java.util.Set; 023 024import org.apache.avalon.framework.activity.Initializable; 025import org.apache.avalon.framework.component.Component; 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.avalon.framework.service.Serviceable; 029import org.apache.commons.io.FileUtils; 030import org.apache.commons.lang3.StringUtils; 031import org.apache.excalibur.source.Source; 032import org.apache.excalibur.source.SourceException; 033import org.apache.excalibur.source.SourceResolver; 034import org.apache.excalibur.source.TraversableSource; 035import org.apache.excalibur.source.impl.FileSource; 036 037import org.ametys.core.cache.AbstractCacheManager; 038import org.ametys.core.cache.Cache; 039import org.ametys.core.group.GroupIdentity; 040import org.ametys.core.right.ProfileAssignmentStorage.AnonymousOrAnyConnectedKeys; 041import org.ametys.core.right.ProfileAssignmentStorage.UserOrGroup; 042import org.ametys.core.right.ProfileAssignmentStorageExtensionPoint; 043import org.ametys.core.right.RightManager; 044import org.ametys.core.right.RightManager.RightResult; 045import org.ametys.core.ui.Callable; 046import org.ametys.core.user.CurrentUserProvider; 047import org.ametys.core.user.UserIdentity; 048import org.ametys.plugins.core.user.UserHelper; 049import org.ametys.plugins.extraction.ExtractionConstants; 050import org.ametys.plugins.extraction.ExtractionRightAssignmentContext; 051import org.ametys.runtime.i18n.I18nizableText; 052import org.ametys.runtime.plugin.component.AbstractLogEnabled; 053 054/** 055 * Object representing the extraction definition file content 056 */ 057public class ExtractionDAO extends AbstractLogEnabled implements Serviceable, Component, Initializable 058{ 059 /** The Avalon role */ 060 public static final String ROLE = ExtractionDAO.class.getName(); 061 062 /** Extraction author cache id */ 063 private static final String EXTRACTION_AUTHOR_CACHE = ExtractionDAO.class.getName() + "$extractionAuthor"; 064 065 private CurrentUserProvider _userProvider; 066 private RightManager _rightManager; 067 private SourceResolver _sourceResolver; 068 private ExtractionDefinitionReader _definitionReader; 069 private ProfileAssignmentStorageExtensionPoint _profileAssignmentStorageEP; 070 private CurrentUserProvider _currentUserProvider; 071 private AbstractCacheManager _cacheManager; 072 private UserHelper _userHelper; 073 private TraversableSource _root; 074 075 public void service(ServiceManager manager) throws ServiceException 076 { 077 _userProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 078 _rightManager = (RightManager) manager.lookup(RightManager.ROLE); 079 _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); 080 _definitionReader = (ExtractionDefinitionReader) manager.lookup(ExtractionDefinitionReader.ROLE); 081 _profileAssignmentStorageEP = (ProfileAssignmentStorageExtensionPoint) manager.lookup(ProfileAssignmentStorageExtensionPoint.ROLE); 082 _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 083 _cacheManager = (AbstractCacheManager) manager.lookup(AbstractCacheManager.ROLE); 084 _userHelper = (UserHelper) manager.lookup(UserHelper.ROLE); 085 } 086 087 public void initialize() throws Exception 088 { 089 _root = (TraversableSource) _sourceResolver.resolveURI(ExtractionConstants.DEFINITIONS_DIR); 090 _cacheManager.createRequestCache(EXTRACTION_AUTHOR_CACHE, 091 new I18nizableText("plugin.extraction", "PLUGINS_EXTRACTION_CACHE_DEFINITION_AUTHOR_LABEL"), 092 new I18nizableText("plugin.extraction", "PLUGINS_EXTRACTION_CACHE_DEFINITION_AUTHOR_DESCRIPTION"), 093 true); 094 } 095 096 /** 097 * Get the root container properties 098 * @return The root container properties 099 * @throws IOException If an error occurred while reading folder 100 */ 101 @Callable 102 public Map<String, Object> getRootProperties() throws IOException 103 { 104 String rootURI = ExtractionConstants.DEFINITIONS_DIR; 105 TraversableSource rootDir = (TraversableSource) _sourceResolver.resolveURI(rootURI); 106 Map<String, Object> infos = getExtractionContainerProperties(rootDir); 107 return infos; 108 } 109 110 /** 111 * Get extraction container properties 112 * @param folder the source of the extraction container 113 * @return The extraction container properties 114 */ 115 public Map<String, Object> getExtractionContainerProperties(TraversableSource folder) 116 { 117 Map<String, Object> infos = new HashMap<>(); 118 119 UserIdentity currentUser = _userProvider.getUser(); 120 121 infos.put("canRead", canRead(currentUser, folder)); 122 infos.put("canRename", canRename(currentUser, folder)); 123 infos.put("canWrite", canWrite(currentUser, folder)); 124 infos.put("canDelete", canDelete(currentUser, folder)); 125 infos.put("canAssignRights", canAssignRights(currentUser, folder)); 126 127 return infos; 128 } 129 130 /** 131 * Get extraction properties 132 * @param extraction the extraction 133 * @param file the source of the extraction 134 * @return The extraction properties 135 */ 136 public Map<String, Object> getExtractionProperties(Extraction extraction, TraversableSource file) 137 { 138 Map<String, Object> infos = new HashMap<>(); 139 140 UserIdentity currentUser = _userProvider.getUser(); 141 infos.put("descriptionId", extraction.getDescriptionId()); 142 143 UserIdentity author = extraction.getAuthor(); 144 infos.put("author", _userHelper.user2json(author)); 145 146 infos.put("canRead", canRead(currentUser, file, author)); 147 infos.put("canWrite", canWrite(currentUser, file, author)); 148 infos.put("canDelete", canDelete(currentUser, file, author)); 149 infos.put("canAssignRights", canAssignRights(currentUser, file, author)); 150 151 return infos; 152 } 153 154 /** 155 * Check if a folder has a descendant in read access for a given user 156 * @param userIdentity the user 157 * @param folder the source of the extraction container 158 * @return <code>true</code> if the folder has a descendant in read access, <code>false</code> otherwise 159 */ 160 public Boolean hasAnyReadableDescendant(UserIdentity userIdentity, TraversableSource folder) 161 { 162 try 163 { 164 if (folder.exists()) 165 { 166 for (TraversableSource child : (Collection<TraversableSource>) folder.getChildren()) 167 { 168 if (child.isCollection()) 169 { 170 if (canRead(userIdentity, child) || hasAnyReadableDescendant(userIdentity, child)) 171 { 172 return true; 173 } 174 } 175 else if (child.getName().endsWith(".xml") && canRead(userIdentity, child, getUserIdentityByExtractionPath((FileSource) child))) 176 { 177 return true; 178 } 179 } 180 } 181 182 return false; 183 } 184 catch (SourceException e) 185 { 186 throw new RuntimeException("Cannot list child elements of " + folder.getURI(), e); 187 } 188 } 189 190 /** 191 * Check if a folder have descendant in write access for a given user 192 * @param userIdentity the user identity 193 * @param folder the source of the extraction container 194 * @return true if the user have write right for at least one child of this container 195 */ 196 public Boolean hasAnyWritableDescendant(UserIdentity userIdentity, TraversableSource folder) 197 { 198 return hasAnyWritableDescendant(userIdentity, folder, false); 199 } 200 201 /** 202 * Check if a folder have descendant in write access for a given user 203 * @param userIdentity the user identity 204 * @param folder the source of the extraction container 205 * @param ignoreExtraction true to ignore extraction file from search (rights will check only on containers) 206 * @return true if the user have write right for at least one child of this container 207 */ 208 public Boolean hasAnyWritableDescendant(UserIdentity userIdentity, TraversableSource folder, boolean ignoreExtraction) 209 { 210 try 211 { 212 if (folder.exists()) 213 { 214 for (TraversableSource child : (Collection<TraversableSource>) folder.getChildren()) 215 { 216 if (child.isCollection()) 217 { 218 if (canWrite(userIdentity, child) || hasAnyWritableDescendant(userIdentity, child)) 219 { 220 return true; 221 } 222 } 223 else if (!ignoreExtraction && child.getName().endsWith(".xml") && canWrite(userIdentity, child, getUserIdentityByExtractionPath((FileSource) child))) 224 { 225 return true; 226 } 227 } 228 } 229 230 return false; 231 } 232 catch (SourceException e) 233 { 234 throw new RuntimeException("Cannot list child elements of " + folder.getURI(), e); 235 } 236 } 237 238 /** 239 * Checks if a folder has descendants in the right assignment access for a given user 240 * @param userIdentity the user 241 * @param folder the source of the extraction container 242 * @return <code>true</code> if the folder has descendant, <code>false</code> otherwise 243 */ 244 public boolean hasAnyAssignableDescendant(UserIdentity userIdentity, TraversableSource folder) 245 { 246 try 247 { 248 if (folder.exists()) 249 { 250 for (TraversableSource child : (Collection<TraversableSource>) folder.getChildren()) 251 { 252 if (child.isCollection()) 253 { 254 if (canAssignRights(userIdentity, child) || hasAnyAssignableDescendant(userIdentity, child)) 255 { 256 return true; 257 } 258 } 259 else if (child.getName().endsWith(".xml")) 260 { 261 if (canAssignRights(userIdentity, child, getUserIdentityByExtractionPath((FileSource) child))) 262 { 263 return true; 264 } 265 } 266 } 267 } 268 269 return false; 270 } 271 catch (SourceException e) 272 { 273 throw new RuntimeException("Cannot list child elements of " + folder.getURI(), e); 274 } 275 } 276 277 /** 278 * Check if a user has read rights on an extraction container 279 * @param userIdentity the user 280 * @param folder the source of the extraction container 281 * @return <code>true</code> if the user has read rights on an extraction container, <code>false</code> otherwise 282 */ 283 public boolean canRead(UserIdentity userIdentity, TraversableSource folder) 284 { 285 return _rightManager.hasReadAccess(userIdentity, getExtractionRightPath(folder)) || canWrite(userIdentity, folder); 286 } 287 288 /** 289 * Check if a user has write rights on an extraction container 290 * @param userIdentity the user 291 * @param folder the source of the extraction container 292 * @return <code>true</code> if the user has write rights on an extraction container, <code>false</code> otherwise 293 */ 294 public boolean canWrite(UserIdentity userIdentity, TraversableSource folder) 295 { 296 return canWrite(userIdentity, folder, false); 297 } 298 299 /** 300 * Determines if the user can rename an extraction container 301 * @param userIdentity the user 302 * @param folder the extraction container 303 * @return true if the user can delete the extraction container 304 */ 305 public boolean canRename(UserIdentity userIdentity, TraversableSource folder) 306 { 307 try 308 { 309 return !_isRoot(folder) // is not root 310 && canWrite(userIdentity, folder) // has write access 311 && canWrite(userIdentity, (TraversableSource) folder.getParent()); // has write access on parent 312 } 313 catch (SourceException e) 314 { 315 throw new RuntimeException("Unable to determine user rights on the extraction container " + folder.getURI(), e); 316 } 317 } 318 319 /** 320 * Determines if the user can delete an extraction container 321 * @param userIdentity the user 322 * @param folder the extraction container 323 * @return true if the user can delete the extraction container 324 */ 325 public boolean canDelete(UserIdentity userIdentity, TraversableSource folder) 326 { 327 try 328 { 329 return !_isRoot(folder) // is not root 330 && canWrite(userIdentity, (TraversableSource) folder.getParent()) // has write access on parent 331 && canWrite(userIdentity, folder, true); // has write access on itselft and each descendant 332 } 333 catch (SourceException e) 334 { 335 throw new RuntimeException("Unable to determine user rights on extraction container " + folder.getURI(), e); 336 } 337 } 338 339 /** 340 * Check if a user has write access on an extraction container 341 * @param userIdentity the user user identity 342 * @param folder the extraction container 343 * @param recursively true to check write access on all descendants recursively 344 * @return true if the user has write access on the extraction container 345 */ 346 public boolean canWrite(UserIdentity userIdentity, TraversableSource folder, boolean recursively) 347 { 348 boolean hasRight = _rightManager.hasRight(userIdentity, ExtractionConstants.MODIFY_EXTRACTION_RIGHT_ID, getExtractionRightPath(folder)) == RightResult.RIGHT_ALLOW; 349 if (!hasRight) 350 { 351 return false; 352 } 353 354 try 355 { 356 if (recursively) 357 { 358 for (TraversableSource child : (Collection<TraversableSource>) folder.getChildren()) 359 { 360 if (child.isCollection()) 361 { 362 hasRight = hasRight && canWrite(userIdentity, child, true); 363 } 364 else if (child.getName().endsWith(".xml")) 365 { 366 hasRight = hasRight && canWrite(userIdentity, child, getUserIdentityByExtractionPath((FileSource) child)); 367 } 368 369 if (!hasRight) 370 { 371 return false; 372 } 373 } 374 } 375 376 return hasRight; 377 } 378 catch (SourceException e) 379 { 380 throw new RuntimeException("Unable to determine user rights on extraction container " + folder.getURI(), e); 381 } 382 } 383 384 /** 385 * Check if a user can edit rights on an extraction container 386 * @param userIdentity the user 387 * @param folder the source of the extraction container 388 * @return true if the user can edit rights on an extraction container 389 */ 390 public boolean canAssignRights(UserIdentity userIdentity, TraversableSource folder) 391 { 392 try 393 { 394 return _rightManager.hasRight(userIdentity, "Runtime_Rights_Rights_Handle", "/cms") == RightResult.RIGHT_ALLOW 395 || !_isRoot(folder) // is not root 396 && canWrite(userIdentity, (TraversableSource) folder.getParent()) // has write access on parent 397 && canWrite(userIdentity, folder, true); // has write access on itselft and each descendant 398 } 399 catch (SourceException e) 400 { 401 throw new RuntimeException("Unable to determine the user rights on the extraction container " + folder.getURI(), e); 402 } 403 } 404 405 /** 406 * Determines if the extraction container is the root node 407 * @param folder the extraction container 408 * @return true if is root 409 */ 410 protected boolean _isRoot(TraversableSource folder) 411 { 412 return _root.getURI().equals(folder.getURI()); 413 } 414 415 /** 416 * Checks if a user has read rights on an extraction 417 * @param userIdentity the user 418 * @param extractionSrc the source for the extraction 419 * @param author the author of extraction 420 * @return <code>true</code> if the user has read rights on an extraction, <code>false</code> otherwise 421 */ 422 public boolean canRead(UserIdentity userIdentity, TraversableSource extractionSrc, UserIdentity author) 423 { 424 return userIdentity.equals(author) || _rightManager.hasReadAccess(userIdentity, getExtractionRightPath(extractionSrc)) || canWrite(userIdentity, extractionSrc, author); 425 } 426 427 /** 428 * Check if a user has write rights on an extraction 429 * @param userIdentity the user 430 * @param extractionSrc the source for the extraction 431 * @param author the author of extraction 432 * @return <code>true</code> if the user has write rights on an extraction, <code>false</code> otherwise 433 */ 434 public boolean canWrite(UserIdentity userIdentity, TraversableSource extractionSrc, UserIdentity author) 435 { 436 return userIdentity.equals(author) || _rightManager.hasRight(userIdentity, ExtractionConstants.MODIFY_EXTRACTION_RIGHT_ID, getExtractionRightPath(extractionSrc)) == RightResult.RIGHT_ALLOW; 437 } 438 439 /** 440 * Checks if a user has write rights on an extraction 441 * @param userIdentity the user 442 * @param extractionSrc the source for the extraction 443 * @param author the author of extraction 444 * @return <code>true</code> if the user has write rights on an extraction, <code>false</code> otherwise 445 */ 446 public boolean canDelete(UserIdentity userIdentity, TraversableSource extractionSrc, UserIdentity author) 447 { 448 try 449 { 450 return canWrite(userIdentity, extractionSrc, author) && canWrite(userIdentity, (TraversableSource) extractionSrc.getParent()); 451 } 452 catch (SourceException e) 453 { 454 throw new RuntimeException("Unable to determines user rights on extraction " + extractionSrc.getURI(), e); 455 } 456 } 457 458 /** 459 * Check if a user has right affectation rights on an extraction container 460 * @param userIdentity the user 461 * @param extractionSrc the source for the extraction 462 * @param author the extraction author 463 * @return <code>true</code> if the user has right affectation rights on an extraction, <code>false</code> otherwise 464 */ 465 public boolean canAssignRights(UserIdentity userIdentity, TraversableSource extractionSrc, UserIdentity author) 466 { 467 return canWrite(userIdentity, extractionSrc, author) || _rightManager.hasRight(userIdentity, "Runtime_Rights_Rights_Handle", "/cms") == RightResult.RIGHT_ALLOW; 468 } 469 470 /** 471 * Get the relative path of an extraction or an extraction container 472 * @param source The source of the extraction or extraction container 473 * @return the relative path 474 */ 475 public String getExtractionRightPath(Source source) 476 { 477 String relPath = source.getURI().substring(_root.getURI().length()); 478 479 if (relPath.endsWith("/")) 480 { 481 relPath = relPath.substring(0, relPath.length() - 1); 482 } 483 484 return StringUtils.isEmpty(relPath) ? ExtractionRightAssignmentContext.ROOT_CONTEXT_PREFIX : ExtractionRightAssignmentContext.ROOT_CONTEXT_PREFIX + "/" + relPath; 485 } 486 487 /** 488 * Get the absolute path of an extraction or an extraction from the context 489 * @param context The context 490 * @return the relative path 491 * @throws IOException if I/O error occurred. 492 */ 493 public String getExtractionAbsolutePathFromContext(String context) throws IOException 494 { 495 String relPath = StringUtils.substringAfter(context, ExtractionRightAssignmentContext.ROOT_CONTEXT_PREFIX); 496 497 return ExtractionConstants.DEFINITIONS_DIR + relPath; 498 } 499 500 /** 501 * Copy rights from one context to another one 502 * @param sourceContext the source context 503 * @param targetContext the target context 504 */ 505 public void copyRights(String sourceContext, String targetContext) 506 { 507 // Get the mapping between users and profiles 508 Map<UserIdentity, Map<UserOrGroup, Set<String>>> profilesForUsers = _profileAssignmentStorageEP.getProfilesForUsers(sourceContext, null); 509 // Copy allowed user assignment profiles to new context 510 profilesForUsers.entrySet() 511 .forEach(entry -> _copyAllowedUsers(entry.getKey(), entry.getValue().get(UserOrGroup.ALLOWED), targetContext)); 512 // Copy denied user assignment profiles to new context 513 profilesForUsers.entrySet() 514 .forEach(entry -> _copyDeniedUsers(entry.getKey(), entry.getValue().get(UserOrGroup.DENIED), targetContext)); 515 516 // Get the mapping between groups and profiles 517 Map<GroupIdentity, Map<UserOrGroup, Set<String>>> profilesForGroups = _profileAssignmentStorageEP.getProfilesForGroups(sourceContext, null); 518 // Copy allowed group assignment profiles to new context 519 profilesForGroups.entrySet() 520 .forEach(entry -> _copyAllowedGroups(entry.getKey(), entry.getValue().get(UserOrGroup.ALLOWED), targetContext)); 521 // Copy denied group assignment profiles to new context 522 profilesForGroups.entrySet() 523 .forEach(entry -> _copyDeniedGroups(entry.getKey(), entry.getValue().get(UserOrGroup.DENIED), targetContext)); 524 525 // Get the mapping between anonymous or any connected user and profiles 526 Map<AnonymousOrAnyConnectedKeys, Set<String>> profilesForAnonymousOrAnyConnectedUser = _profileAssignmentStorageEP.getProfilesForAnonymousAndAnyConnectedUser(sourceContext); 527 // Copy allowed anonymous user assignment profiles to new context 528 profilesForAnonymousOrAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANONYMOUS_ALLOWED) 529 .forEach(profileId -> _profileAssignmentStorageEP.allowProfileToAnonymous(profileId, targetContext)); 530 // Copy denied anonymous user assignment profiles to new context 531 profilesForAnonymousOrAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANONYMOUS_DENIED) 532 .forEach(profileId -> _profileAssignmentStorageEP.denyProfileToAnonymous(profileId, targetContext)); 533 // Copy allowed any connected user assignment profiles to new context 534 profilesForAnonymousOrAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANYCONNECTEDUSER_ALLOWED) 535 .forEach(profileId -> _profileAssignmentStorageEP.allowProfileToAnyConnectedUser(profileId, targetContext)); 536 // Copy denied any connected user assignment profiles to new context 537 profilesForAnonymousOrAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANYCONNECTEDUSER_DENIED) 538 .forEach(profileId -> _profileAssignmentStorageEP.denyProfileToAnyConnectedUser(profileId, targetContext)); 539 } 540 541 private void _copyAllowedUsers(UserIdentity userIdentity, Set<String> profiles, String context) 542 { 543 profiles.forEach(profile -> _profileAssignmentStorageEP.allowProfileToUser(userIdentity, profile, context)); 544 } 545 546 private void _copyDeniedUsers(UserIdentity userIdentity, Set<String> profiles, String context) 547 { 548 profiles.forEach(profile -> _profileAssignmentStorageEP.denyProfileToUser(userIdentity, profile, context)); 549 } 550 551 private void _copyAllowedGroups(GroupIdentity groupIdentity, Set<String> profiles, String context) 552 { 553 profiles.forEach(profile -> _profileAssignmentStorageEP.allowProfileToGroup(groupIdentity, profile, context)); 554 } 555 556 private void _copyDeniedGroups(GroupIdentity groupIdentity, Set<String> profiles, String context) 557 { 558 profiles.forEach(profile -> _profileAssignmentStorageEP.denyProfileToGroup(groupIdentity, profile, context)); 559 } 560 561 /** 562 * Delete rights from a context 563 * @param context the context 564 */ 565 public void deleteRights(String context) 566 { 567 // Get the mapping between users and profiles 568 Map<UserIdentity, Map<UserOrGroup, Set<String>>> profilesForUsers = _profileAssignmentStorageEP.getProfilesForUsers(context, null); 569 // Copy allowed user assignment profiles to new context 570 profilesForUsers.entrySet() 571 .forEach(entry -> _removeAllowedUsers(entry.getKey(), entry.getValue().get(UserOrGroup.ALLOWED), context)); 572 // Copy denied user assignment profiles to new context 573 profilesForUsers.entrySet() 574 .forEach(entry -> _removeDeniedUsers(entry.getKey(), entry.getValue().get(UserOrGroup.DENIED), context)); 575 576 // Get the mapping between groups and profiles 577 Map<GroupIdentity, Map<UserOrGroup, Set<String>>> profilesForGroups = _profileAssignmentStorageEP.getProfilesForGroups(context, null); 578 // Copy allowed group assignment profiles to new context 579 profilesForGroups.entrySet() 580 .forEach(entry -> _removeAllowedGroups(entry.getKey(), entry.getValue().get(UserOrGroup.ALLOWED), context)); 581 // Copy denied group assignment profiles to new context 582 profilesForGroups.entrySet() 583 .forEach(entry -> _removeDeniedGroups(entry.getKey(), entry.getValue().get(UserOrGroup.DENIED), context)); 584 585 // Get the mapping between anonymous or any connected user and profiles 586 Map<AnonymousOrAnyConnectedKeys, Set<String>> profilesForAnonymousOrAnyConnectedUser = _profileAssignmentStorageEP.getProfilesForAnonymousAndAnyConnectedUser(context); 587 // Copy allowed anonymous user assignment profiles to new context 588 profilesForAnonymousOrAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANONYMOUS_ALLOWED) 589 .forEach(profileId -> _profileAssignmentStorageEP.removeAllowedProfileFromAnonymous(profileId, context)); 590 // Copy denied anonymous user assignment profiles to new context 591 profilesForAnonymousOrAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANONYMOUS_DENIED) 592 .forEach(profileId -> _profileAssignmentStorageEP.removeDeniedProfileFromAnonymous(profileId, context)); 593 // Copy allowed any connected user assignment profiles to new context 594 profilesForAnonymousOrAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANYCONNECTEDUSER_ALLOWED) 595 .forEach(profileId -> _profileAssignmentStorageEP.removeAllowedProfileFromAnyConnectedUser(profileId, context)); 596 // Copy denied any connected user assignment profiles to new context 597 profilesForAnonymousOrAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANYCONNECTEDUSER_DENIED) 598 .forEach(profileId -> _profileAssignmentStorageEP.removeDeniedProfileFromAnyConnectedUser(profileId, context)); 599 } 600 601 private void _removeAllowedUsers(UserIdentity userIdentity, Set<String> profiles, String context) 602 { 603 profiles.forEach(profile -> _profileAssignmentStorageEP.removeAllowedProfileFromUser(userIdentity, profile, context)); 604 } 605 606 private void _removeDeniedUsers(UserIdentity userIdentity, Set<String> profiles, String context) 607 { 608 profiles.forEach(profile -> _profileAssignmentStorageEP.removeDeniedProfileFromUser(userIdentity, profile, context)); 609 } 610 611 private void _removeAllowedGroups(GroupIdentity groupIdentity, Set<String> profiles, String context) 612 { 613 profiles.forEach(profile -> _profileAssignmentStorageEP.removeAllowedProfileFromGroup(groupIdentity, profile, context)); 614 } 615 616 private void _removeDeniedGroups(GroupIdentity groupIdentity, Set<String> profiles, String context) 617 { 618 profiles.forEach(profile -> _profileAssignmentStorageEP.removeDeniedProfileFromGroup(groupIdentity, profile, context)); 619 } 620 621 /** 622 * Move an extraction file or folder inside a given directory 623 * 624 * @param srcRelPath The relative URI of file/folder to move 625 * @param parentRelPath The URI relative of parent target file 626 * @return a result map with the name and uri of moved file in case of 627 * success. 628 * @throws IOException If an error occurred manipulating the source 629 */ 630 @Callable (right = ExtractionConstants.MODIFY_EXTRACTION_RIGHT_ID) 631 public Map<String, Object> moveExtractionDefinitionFile(String srcRelPath, String parentRelPath) throws IOException 632 { 633 Map<String, Object> result = new HashMap<>(); 634 635 FileSource rootParametersFileSource = null; 636 FileSource srcFileSource = null; 637 FileSource parentFileSource = null; 638 try 639 { 640 String rootParametersFolder = "context://WEB-INF/param/extraction/definitions/"; 641 642 rootParametersFileSource = (FileSource) _sourceResolver.resolveURI(rootParametersFolder); 643 srcFileSource = (FileSource) _sourceResolver.resolveURI(rootParametersFolder + srcRelPath); 644 parentFileSource = (FileSource) _sourceResolver.resolveURI(rootParametersFolder + parentRelPath); 645 if (!StringUtils.startsWith(srcFileSource.getURI(), rootParametersFileSource.getURI()) || !StringUtils.startsWith(parentFileSource.getURI(), rootParametersFileSource.getURI())) 646 { 647 result.put("success", false); 648 result.put("error", "no-exists"); 649 650 getLogger().error("User '" + _currentUserProvider.getUser() + " tried to move parameter file outside of the \"WEB-INF/param\" root directory."); 651 652 return result; 653 } 654 655 String sourceContext = ExtractionRightAssignmentContext.ROOT_CONTEXT_PREFIX + "/" + srcRelPath; 656 String targetContext = ExtractionRightAssignmentContext.ROOT_CONTEXT_PREFIX + "/" + parentRelPath + (StringUtils.isEmpty(parentRelPath) ? "" : "/") + srcFileSource.getName(); 657 658 result = moveSource(rootParametersFolder + srcRelPath, rootParametersFolder + parentRelPath, sourceContext, targetContext); 659 660 if (result.containsKey("uri")) 661 { 662 String newURI = (String) result.get("uri"); 663 String path = newURI.substring(rootParametersFolder.length()); 664 result.put("path", path); 665 } 666 } 667 finally 668 { 669 _sourceResolver.release(rootParametersFileSource); 670 _sourceResolver.release(srcFileSource); 671 _sourceResolver.release(parentFileSource); 672 } 673 674 return result; 675 } 676 677 /** 678 * Move a file or folder 679 * 680 * @param srcUri The URI of file/folder to move 681 * @param parentTargetUri The URI of parent target file 682 * @param sourceContext the source context 683 * @param targetContext the target context 684 * @return a result map with the name and uri of moved file in case of 685 * success. 686 * @throws IOException If an error occurred manipulating the source 687 */ 688 public Map<String, Object> moveSource(String srcUri, String parentTargetUri, String sourceContext, String targetContext) throws IOException 689 { 690 Map<String, Object> result = new HashMap<>(); 691 692 FileSource srcFile = (FileSource) _sourceResolver.resolveURI(srcUri); 693 694 if (!srcFile.exists()) 695 { 696 result.put("success", false); 697 result.put("error", "no-exists"); 698 return result; 699 } 700 701 FileSource parentDargetDir = (FileSource) _sourceResolver.resolveURI(parentTargetUri); 702 String fileName = srcFile.getName(); 703 FileSource targetFile = (FileSource) _sourceResolver.resolveURI(parentTargetUri + (fileName.length() > 0 ? "/" + fileName : "")); 704 705 if (targetFile.exists()) 706 { 707 result.put("msg", "already-exists"); 708 return result; 709 } 710 711 copyRightsRecursively(sourceContext, targetContext, srcFile); 712 FileUtils.moveToDirectory(srcFile.getFile(), parentDargetDir.getFile(), false); 713 deleteRightsRecursively(sourceContext, targetFile); 714 715 result.put("success", true); 716 result.put("name", targetFile.getName()); 717 result.put("uri", targetFile.getURI()); 718 719 return result; 720 } 721 722 /** 723 * Copy rights from one context to another one 724 * @param sourceContext the source context 725 * @param targetContext the target context 726 * @param file the source of the file to copy 727 */ 728 public void copyRightsRecursively(String sourceContext, String targetContext, TraversableSource file) 729 { 730 copyRights(sourceContext, targetContext); 731 if (file.isCollection()) 732 { 733 try 734 { 735 for (TraversableSource child : (Collection<TraversableSource>) file.getChildren()) 736 { 737 copyRightsRecursively(sourceContext + "/" + child.getName(), targetContext + "/" + child.getName(), child); 738 } 739 } 740 catch (SourceException e) 741 { 742 throw new RuntimeException("Cannot list child elements of " + file.getURI(), e); 743 } 744 } 745 } 746 747 /** 748 * Copy rights from one context to another one 749 * @param context the context 750 * @param file the source of the file to copy 751 */ 752 public void deleteRightsRecursively(String context, TraversableSource file) 753 { 754 deleteRights(context); 755 if (file.isCollection()) 756 { 757 try 758 { 759 for (TraversableSource child : (Collection<TraversableSource>) file.getChildren()) 760 { 761 deleteRightsRecursively(context + "/" + child.getName(), child); 762 } 763 } 764 catch (SourceException e) 765 { 766 throw new RuntimeException("Cannot list child elements of " + file.getURI(), e); 767 } 768 } 769 } 770 771 /** 772 * get the author of extraction 773 * @param extractionPath the path of the extraction 774 * @return the author 775 */ 776 public UserIdentity getUserIdentityByExtractionPath(FileSource extractionPath) 777 { 778 return _getExtractionAuthorCache().get(extractionPath, path -> _getUserIdentityByExtractionFile(path)); 779 780 } 781 782 private UserIdentity _getUserIdentityByExtractionFile(FileSource extractionPath) 783 { 784 try 785 { 786 Extraction extraction = _definitionReader.readExtractionDefinitionFile(extractionPath.getFile()); 787 return extraction.getAuthor(); 788 } 789 catch (Exception e) 790 { 791 throw new RuntimeException("Cannot read extraction " + extractionPath, e); 792 } 793 } 794 private Cache<FileSource, UserIdentity> _getExtractionAuthorCache() 795 { 796 return this._cacheManager.get(EXTRACTION_AUTHOR_CACHE); 797 } 798}