@Override public void versioning(Document doc) { if (!doc.isLatestVersion() && !doc.isPrivateWorkingCopy()) { String msg = "The operation is not allowed on a non-current version of a document"; throw new CmisVersioningException(buildMsgWithId(msg, doc.getId()), HTTP_STATUS_CODE_409); } }
@Override public void setContentStream( CallContext callContext, String repositoryId, Holder<String> objectId, boolean overwriteFlag, ContentStream contentStream, Holder<String> changeToken) { exceptionService.invalidArgumentRequiredHolderString("objectId", objectId); Lock lock = threadLockService.getWriteLock(repositoryId, objectId.getValue()); try { lock.lock(); // ////////////////// // General Exception // ////////////////// exceptionService.invalidArgumentRequired("contentStream", contentStream); Document doc = (Document) contentService.getContent(repositoryId, objectId.getValue()); exceptionService.objectNotFound(DomainType.OBJECT, doc, objectId.getValue()); exceptionService.permissionDenied( callContext, repositoryId, PermissionMapping.CAN_SET_CONTENT_DOCUMENT, doc); DocumentTypeDefinition td = (DocumentTypeDefinition) typeManager.getTypeDefinition(repositoryId, doc.getObjectType()); exceptionService.constraintImmutable(repositoryId, doc, td); // ////////////////// // Specific Exception // ////////////////// exceptionService.contentAlreadyExists(doc, overwriteFlag); exceptionService.streamNotSupported(td, contentStream); exceptionService.updateConflict(doc, changeToken); exceptionService.versioning(doc); Folder parent = contentService.getParent(repositoryId, objectId.getValue()); exceptionService.objectNotFoundParentFolder(repositoryId, objectId.getValue(), parent); // ////////////////// // Body of the method // ////////////////// String oldId = objectId.getValue(); // TODO Externalize versioningState if (doc.isPrivateWorkingCopy()) { Document result = contentService.replacePwc(callContext, repositoryId, doc, contentStream); objectId.setValue(result.getId()); } else { Document result = contentService.createDocumentWithNewStream( callContext, repositoryId, doc, contentStream); objectId.setValue(result.getId()); } nemakiCachePool.get(repositoryId).removeCmisCache(oldId); } finally { lock.unlock(); } }
@Override public void constraintAlreadyCheckedOut(String repositoryId, Document document) { VersionSeries vs = contentService.getVersionSeries(repositoryId, document); if (vs.isVersionSeriesCheckedOut()) { if (!(document.isPrivateWorkingCopy())) { constraint(document.getId(), "The version series is already checked out"); } } }
@Override public void constraintUpdateWhenCheckedOut( String repositoryId, String currentUserId, Document document) { VersionSeries vs = contentService.getVersionSeries(repositoryId, document); if (vs.isVersionSeriesCheckedOut()) { if (document.isPrivateWorkingCopy()) { // Can update by only the use who has checked it out String whoCheckedOut = vs.getVersionSeriesCheckedOutBy(); if (!currentUserId.equals(whoCheckedOut)) { constraint( document.getId(), "This private working copy can be modified only by the user who has checked it out. "); } } else { // All versions except for PWC are locked. constraint(document.getId(), "All versions except for PWC are locked when checked out."); } } }
// TODO Merge arguments(acl, content) // FIXME Refactor duplicate isAllowableBaseType @Override public Boolean checkPermission( CallContext callContext, String repositoryId, String key, Acl acl, String baseType, Content content) { // All permission checks must go through baseType check if (!isAllowableBaseType(key, baseType, content, repositoryId)) return false; // Admin always pass a permission check CallContextImpl cci = (CallContextImpl) callContext; Boolean _isAdmin = (Boolean) cci.get(CallContextKey.IS_ADMIN); boolean isAdmin = (_isAdmin == null) ? false : _isAdmin; if (isAdmin) return true; // PWC doesn't accept any actions from a non-owner user // TODO admin can manipulate PWC even when it is checked out ? if (content.isDocument()) { Document document = (Document) content; if (document.isPrivateWorkingCopy()) { VersionSeries vs = contentService.getVersionSeries(repositoryId, document); if (!callContext.getUsername().equals(vs.getVersionSeriesCheckedOutBy())) { return false; } } } // Relation has no ACL stored in DB. // Though some actions are defined in the specs, // Some other direct actions is needed to be set here. if (content.isRelationship()) { Relationship relationship = (Relationship) content; return checkRelationshipPermission(callContext, repositoryId, key, relationship); } // Void Acl fails(but Admin can do an action) if (acl == null) return false; // Even if a user has multiple ACEs, the permissions is pushed into // Set<String> and remain unique. // Get ACL for the current user String userName = callContext.getUsername(); List<Ace> aces = acl.getAllAces(); Set<String> userPermissions = new HashSet<String>(); Set<String> groups = principalService.getGroupIdsContainingUser(repositoryId, userName); for (Ace ace : aces) { // Filter ace which has not permissions if (ace.getPermissions() == null) continue; // Add user permissions if (ace.getPrincipalId().equals(userName)) { userPermissions.addAll(ace.getPermissions()); } // Add inherited permissions which user inherits if (CollectionUtils.isNotEmpty(groups) && groups.contains(ace.getPrincipalId())) { userPermissions.addAll(ace.getPermissions()); } } // Check mapping between the user and the content return checkCalculatedPermissions(repositoryId, key, userPermissions); }