001/* 002 * (C) Copyright 2015-2017 Nuxeo (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * dmetzler 018 * Vladimir Pasquier <vpasquier@nuxeo.com> 019 * Mincong Huang <mhuang@nuxeo.com> 020 */ 021package org.nuxeo.ecm.automation.core.operations.document; 022 023import java.io.Serializable; 024import java.util.Calendar; 025import java.util.HashMap; 026import java.util.Map; 027 028import org.nuxeo.ecm.automation.core.Constants; 029import org.nuxeo.ecm.automation.core.annotations.Context; 030import org.nuxeo.ecm.automation.core.annotations.Operation; 031import org.nuxeo.ecm.automation.core.annotations.OperationMethod; 032import org.nuxeo.ecm.automation.core.annotations.Param; 033import org.nuxeo.ecm.automation.core.collectors.DocumentModelCollector; 034import org.nuxeo.ecm.core.api.CoreSession; 035import org.nuxeo.ecm.core.api.DocumentModel; 036import org.nuxeo.ecm.core.api.DocumentRef; 037import org.nuxeo.ecm.core.api.NuxeoException; 038import org.nuxeo.ecm.core.api.NuxeoPrincipal; 039import org.nuxeo.ecm.core.api.security.ACE; 040import org.nuxeo.ecm.core.api.security.ACL; 041import org.nuxeo.ecm.core.api.security.ACP; 042import org.nuxeo.ecm.core.api.security.impl.ACPImpl; 043import org.nuxeo.ecm.platform.usermanager.UserManager; 044import org.nuxeo.ecm.webengine.model.exceptions.IllegalParameterException; 045import org.nuxeo.runtime.api.Framework; 046import org.nuxeo.runtime.services.config.ConfigurationService; 047 048/** 049 * Operation that adds a permission to a given ACL for a given user. 050 * 051 * @since 5.7.3 052 */ 053@Operation(id = AddPermission.ID, category = Constants.CAT_DOCUMENT, label = "Add Permission", description = "Add Permission on the input document(s). Returns the document(s).", aliases = { "Document.AddACL" }) 054public class AddPermission { 055 056 public static final String ID = "Document.AddPermission"; 057 058 public static final String NOTIFY_KEY = "notify"; 059 060 public static final String COMMENT_KEY = "comment"; 061 062 /** 063 * Configuration property name, which defines whether virtual user (non-existent user) is allowed in Nuxeo 064 * automation. If allowed, Nuxeo server will not check the user existence during automation execution. Set this 065 * property to true if you use Nuxeo computed user or computed group. 066 * 067 * @since 9.1 068 */ 069 public static final String ALLOW_VIRTUAL_USER = "nuxeo.automation.allowVirtualUser"; 070 071 @Context 072 protected CoreSession session; 073 074 @Param(name = "username", required = false, alias = "user", description = "ACE target user/group.") 075 protected String user; 076 077 /** 078 * @since 8.1 079 */ 080 @Param(name = "email", required = false, description = "ACE target user/group.") 081 protected String email; 082 083 @Param(name = "permission", description = "ACE permission.") 084 String permission; 085 086 @Param(name = "acl", required = false, values = { ACL.LOCAL_ACL }, description = "ACL name.") 087 String aclName = ACL.LOCAL_ACL; 088 089 @Param(name = "begin", required = false, description = "ACE begin date.") 090 Calendar begin; 091 092 @Param(name = "end", required = false, description = "ACE end date.") 093 Calendar end; 094 095 @Param(name = "blockInheritance", required = false, description = "Block inheritance or not.") 096 boolean blockInheritance = false; 097 098 @Param(name = "notify", required = false, description = "Notify the user or not") 099 boolean notify = false; 100 101 @Param(name = "comment", required = false, description = "Comment") 102 String comment; 103 104 @OperationMethod(collector = DocumentModelCollector.class) 105 public DocumentModel run(DocumentModel doc) { 106 addPermission(doc); 107 return session.getDocument(doc.getRef()); 108 } 109 110 @OperationMethod(collector = DocumentModelCollector.class) 111 public DocumentModel run(DocumentRef docRef) { 112 DocumentModel doc = session.getDocument(docRef); 113 addPermission(doc); 114 return doc; 115 } 116 117 protected void addPermission(DocumentModel doc) { 118 if (user == null && email == null) { 119 throw new IllegalParameterException("'username' or 'email' parameter must be set"); 120 } 121 122 if (user == null && end == null) { 123 throw new IllegalParameterException("'end' parameter must be set when adding a permission for an 'email'"); 124 } 125 126 String username; 127 if (user == null) { 128 // share a document with someone not registered in Nuxeo, by using only an email 129 username = NuxeoPrincipal.computeTransientUsername(email); 130 } else { 131 username = user; 132 ConfigurationService configService = Framework.getService(ConfigurationService.class); 133 if (configService.isBooleanPropertyFalse(ALLOW_VIRTUAL_USER)) { 134 checkUserExistence(username); 135 } 136 } 137 138 ACP acp = doc.getACP() != null ? doc.getACP() : new ACPImpl(); 139 Map<String, Serializable> contextData = new HashMap<>(); 140 contextData.put(NOTIFY_KEY, notify); 141 contextData.put(COMMENT_KEY, comment); 142 143 String creator = session.getPrincipal().getName(); 144 ACE ace = ACE.builder(username, permission) 145 .creator(creator) 146 .begin(begin) 147 .end(end) 148 .contextData(contextData) 149 .build(); 150 boolean permissionChanged = false; 151 if (blockInheritance) { 152 permissionChanged = acp.blockInheritance(aclName, creator); 153 } 154 permissionChanged = acp.addACE(aclName, ace) || permissionChanged; 155 if (permissionChanged) { 156 doc.setACP(acp, true); 157 } 158 } 159 160 protected void checkUserExistence(String username) { 161 UserManager userManager = Framework.getService(UserManager.class); 162 if (userManager.getUserModel(username) == null && userManager.getGroupModel(username) == null) { 163 String errorMsg = "User or group name '" + username + "' does not exist. Please provide a valid name."; 164 throw new NuxeoException(errorMsg); 165 } 166 } 167 168}