001/* 002 * (C) Copyright 2016-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 * Michael Vachette 018 * Florent Guillaume 019 */ 020package org.nuxeo.ecm.automation.core.operations.users; 021 022import java.util.Arrays; 023import java.util.AbstractMap.SimpleEntry; 024import java.util.Map.Entry; 025 026import org.apache.commons.lang.StringUtils; 027import org.nuxeo.ecm.automation.OperationException; 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.util.Properties; 034import org.nuxeo.ecm.automation.core.util.StringList; 035import org.nuxeo.ecm.core.api.DocumentModel; 036import org.nuxeo.ecm.directory.BaseSession; 037import org.nuxeo.ecm.platform.usermanager.UserManager; 038 039/** 040 * Operation to create or update a group. 041 * 042 * @since 9.1 043 */ 044@Operation(id = CreateOrUpdateGroup.ID, // 045 category = Constants.CAT_USERS_GROUPS, // 046 label = "Create or Update Group", // 047 description = "Create or Update Group") 048public class CreateOrUpdateGroup { 049 050 public static final String ID = "Group.CreateOrUpdate"; 051 052 public static final String CREATE_OR_UPDATE = "createOrUpdate"; 053 054 public static final String CREATE = "create"; 055 056 public static final String UPDATE = "update"; 057 058 public static final String GROUP_SCHEMA = "group"; 059 060 protected static final String GROUP_COLON = GROUP_SCHEMA + ':'; 061 062 public static final String GROUP_NAME = "groupname"; 063 064 public static final String GROUP_LABEL = "grouplabel"; 065 066 public static final String GROUP_DESCRIPTION = "description"; 067 068 public static final String MEMBERS = "members"; 069 070 public static final String SUB_GROUPS = "subGroups"; 071 072 public static final String PARENT_GROUPS = "parentGroups"; 073 074 public static final String GROUP_TENANTID = "tenantId"; 075 076 @Context 077 protected UserManager userManager; 078 079 @Param(name = "groupname") 080 protected String groupName; 081 082 @Param(name = "tenantId", required = false) 083 protected String tenantId; 084 085 @Param(name = "grouplabel", required = false) 086 protected String groupLabel; 087 088 @Param(name = "description", required = false) 089 protected String groupDescription; 090 091 @Param(name = "members", required = false) 092 protected StringList members; 093 094 @Param(name = "subGroups", required = false) 095 protected StringList subGroups; 096 097 @Param(name = "parentGroups", required = false) 098 protected StringList parentGroups; 099 100 @Param(name = "properties", required = false) 101 protected Properties properties = new Properties(); 102 103 @Param(name = "mode", required = false, values = { CREATE_OR_UPDATE, CREATE, UPDATE }) 104 protected String mode; 105 106 @OperationMethod 107 public void run() throws OperationException { 108 String tenantGroupName = getTenantGroupName(groupName, tenantId); 109 boolean create; 110 DocumentModel groupDoc = userManager.getGroupModel(tenantGroupName); 111 if (groupDoc == null) { 112 if (UPDATE.equals(mode)) { 113 throw new OperationException("Cannot update non-existent group: " + groupName); 114 } 115 create = true; 116 groupDoc = userManager.getBareGroupModel(); 117 groupDoc.setProperty(GROUP_SCHEMA, GROUP_NAME, groupName); 118 } else { 119 if (CREATE.equals(mode)) { 120 throw new OperationException("Cannot create already-existing group: " + groupName); 121 } 122 create = false; 123 } 124 if (members != null) { 125 groupDoc.setProperty(GROUP_SCHEMA, MEMBERS, members); 126 } 127 if (subGroups != null) { 128 groupDoc.setProperty(GROUP_SCHEMA, SUB_GROUPS, subGroups); 129 } 130 if (parentGroups != null) { 131 groupDoc.setProperty(GROUP_SCHEMA, PARENT_GROUPS, parentGroups); 132 } 133 for (Entry<String, String> entry : Arrays.asList( // 134 new SimpleEntry<>(GROUP_TENANTID, tenantId), // 135 new SimpleEntry<>(GROUP_LABEL, groupLabel), // 136 new SimpleEntry<>(GROUP_DESCRIPTION, groupDescription))) { 137 String key = entry.getKey(); 138 String value = entry.getValue(); 139 if (StringUtils.isNotBlank(value)) { 140 properties.put(key, value); 141 } 142 } 143 for (Entry<String, String> entry : properties.entrySet()) { 144 String key = entry.getKey(); 145 String value = entry.getValue(); 146 if (key.startsWith(GROUP_COLON)) { 147 key = key.substring(GROUP_COLON.length()); 148 } 149 groupDoc.setProperty(GROUP_SCHEMA, key, value); 150 } 151 if (create) { 152 groupDoc = userManager.createGroup(groupDoc); 153 } else { 154 userManager.updateGroup(groupDoc); 155 groupDoc = userManager.getGroupModel(tenantGroupName); 156 } 157 } 158 159 /** 160 * Use tenant_mytenant_mygroup instead of mygroup for groups having a tenant id. 161 * <p> 162 * This is done explicitly instead of the implicit computation done in SQLSession.createEntry which is based on a 163 * tenant id deduced from the logged-in user. 164 */ 165 public static String getTenantGroupName(String groupName, String tenantId) { 166 if (StringUtils.isBlank(tenantId)) { 167 return groupName; 168 } 169 return BaseSession.computeMultiTenantDirectoryId(tenantId, groupName); 170 } 171 172}