001/* 002 * (C) Copyright 2016 Nuxeo SA (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 * Thomas Roger 018 * Yannis JULIENNE 019 */ 020package org.nuxeo.functionaltests; 021 022import static org.nuxeo.functionaltests.AbstractTest.NUXEO_URL; 023import static org.nuxeo.functionaltests.Constants.ADMINISTRATOR; 024 025import java.io.IOException; 026import java.util.ArrayList; 027import java.util.Arrays; 028import java.util.Calendar; 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032 033import org.apache.commons.lang.StringUtils; 034import org.apache.commons.logging.Log; 035import org.apache.commons.logging.LogFactory; 036import org.codehaus.jackson.JsonNode; 037import org.codehaus.jackson.map.ObjectMapper; 038import org.nuxeo.client.api.NuxeoClient; 039import org.nuxeo.client.api.objects.Document; 040import org.nuxeo.client.api.objects.Documents; 041import org.nuxeo.client.api.objects.acl.ACE; 042import org.nuxeo.client.api.objects.user.Group; 043import org.nuxeo.client.internals.spi.NuxeoClientException; 044import org.nuxeo.common.utils.URIUtils; 045 046import okhttp3.Response; 047import okhttp3.ResponseBody; 048 049/** 050 * @since 8.3 051 */ 052public class RestHelper { 053 054 private static final NuxeoClient CLIENT = new NuxeoClient(NUXEO_URL, ADMINISTRATOR, ADMINISTRATOR); 055 056 private static final String USER_WORKSPACE_PATH_FORMAT = "/default-domain/UserWorkspaces/%s"; 057 058 private static final String DEFAULT_USER_EMAIL = "devnull@nuxeo.com"; 059 060 private static final String DOCUMENT_QUERY_BY_PATH_BASE = "SELECT * FROM Document WHERE ecm:path = '%s'"; 061 062 private static final List<String> documentIdsToDelete = new ArrayList<>(); 063 064 private static final List<String> documentPathsToDelete = new ArrayList<>(); 065 066 private static final List<String> usersToDelete = new ArrayList<>(); 067 068 private static final List<String> groupsToDelete = new ArrayList<>(); 069 070 private static final int NOT_FOUND_ERROR_STATUS = 404; 071 072 protected static final Log log = LogFactory.getLog(RestHelper.class); 073 074 // @yannis : temporary fix for setting user password before JAVACLIENT-91 075 private static final ObjectMapper MAPPER = new ObjectMapper(); 076 077 private RestHelper() { 078 // helper class 079 } 080 081 public static void cleanup() { 082 cleanupDocuments(); 083 cleanupUsers(); 084 cleanupGroups(); 085 } 086 087 public static void cleanupDocuments() { 088 documentIdsToDelete.forEach(RestHelper::deleteDocument); 089 documentIdsToDelete.clear(); 090 documentPathsToDelete.clear(); 091 } 092 093 public static void cleanupUsers() { 094 for (String user : usersToDelete) { 095 RestHelper.deleteDocument(String.format(USER_WORKSPACE_PATH_FORMAT, user)); 096 } 097 usersToDelete.forEach(RestHelper::deleteUser); 098 usersToDelete.clear(); 099 } 100 101 public static void cleanupGroups() { 102 groupsToDelete.forEach(RestHelper::deleteGroup); 103 groupsToDelete.clear(); 104 } 105 106 public static String createUser(String username, String password) { 107 return createUser(username, password, null, null, null, null, null); 108 } 109 110 public static String createUser(String username, String password, String firstName, String lastName, String company, 111 String email, String group) { 112 113 String finalEmail = StringUtils.isBlank(email) ? DEFAULT_USER_EMAIL : email; 114 115 // @yannis : temporary fix for setting user password before JAVACLIENT-91 116 String json = buildUserJSON(username, password, firstName, lastName, company, finalEmail, group); 117 118 Response response = CLIENT.post(AbstractTest.NUXEO_URL + "/api/v1/user", json); 119 if (!response.isSuccessful()) { 120 throw new RuntimeException(String.format("Unable to create user '%s'", username)); 121 } 122 123 try (ResponseBody responseBody = response.body()) { 124 JsonNode jsonNode = MAPPER.readTree(responseBody.charStream()); 125 String id = jsonNode.get("id").getTextValue(); 126 usersToDelete.add(id); 127 return id; 128 } catch (IOException e) { 129 throw new RuntimeException(e); 130 } 131 } 132 133 public static void addUserToDelete(String userName) { 134 usersToDelete.add(userName); 135 } 136 137 public static void removeUserToDelete(String userName) { 138 usersToDelete.remove(userName); 139 } 140 141 private static String buildUserJSON(String username, String password, String firstName, String lastName, 142 String company, String email, String group) { 143 StringBuilder sb = new StringBuilder(); 144 sb.append("{"); 145 sb.append("\"entity-type\": \"user\"").append(",\n"); 146 sb.append("\"id\": \"").append(username).append("\",\n"); 147 sb.append("\"properties\": {").append("\n"); 148 if (firstName != null) { 149 sb.append("\"firstName\": \"").append(firstName).append("\",\n"); 150 } 151 if (lastName != null) { 152 sb.append("\"lastName\": \"").append(lastName).append("\",\n"); 153 } 154 if (email != null) { 155 sb.append("\"email\": \"").append(email).append("\",\n"); 156 } 157 if (company != null) { 158 sb.append("\"company\": \"").append(company).append("\",\n"); 159 } 160 if (group != null) { 161 sb.append("\"groups\": [\"").append(group).append("\"]").append(",\n"); 162 } 163 sb.append("\"username\": \"").append(username).append("\",\n"); 164 sb.append("\"password\": \"").append(password).append("\"\n"); 165 sb.append("}").append("\n"); 166 sb.append("}"); 167 return sb.toString(); 168 } 169 170 public static void deleteUser(String username) { 171 try { 172 CLIENT.getUserManager().deleteUser(username); 173 } catch (NuxeoClientException e) { 174 if (NOT_FOUND_ERROR_STATUS == e.getStatus()) { 175 log.warn(String.format("User %s not deleted because not found", username)); 176 } else { 177 throw e; 178 } 179 } 180 } 181 182 public static void createGroup(String name, String label) { 183 createGroup(name, label, null, null); 184 } 185 186 public static void createGroup(String name, String label, String[] members, String[] subGroups) { 187 Group group = new Group(); 188 group.setGroupName(name); 189 group.setGroupLabel(label); 190 if (members != null) { 191 group.setMemberUsers(Arrays.asList(members)); 192 } 193 if (subGroups != null) { 194 group.setMemberGroups(Arrays.asList(subGroups)); 195 } 196 197 CLIENT.getUserManager().createGroup(group); 198 groupsToDelete.add(name); 199 } 200 201 public static void deleteGroup(String name) { 202 try { 203 CLIENT.getUserManager().deleteGroup(name); 204 } catch (NuxeoClientException e) { 205 if (NOT_FOUND_ERROR_STATUS == e.getStatus()) { 206 log.warn(String.format("Group %s not deleted because not found", name)); 207 } else { 208 throw e; 209 } 210 } 211 } 212 213 public static String createDocument(String idOrPath, String type, String title, String description) { 214 Document document = new Document(title, type); 215 Map<String, Object> properties = new HashMap<>(); 216 properties.put("dc:title", title); 217 if (description != null) { 218 properties.put("dc:description", description); 219 } 220 document.setProperties(properties); 221 222 if (idOrPath.startsWith("/")) { 223 document = CLIENT.repository().createDocumentByPath(idOrPath, document); 224 } else { 225 document = CLIENT.repository().createDocumentById(idOrPath, document); 226 } 227 228 String docId = document.getId(); 229 String docPath = document.getPath(); 230 // do we already have to delete one parent? 231 if (documentPathsToDelete.stream().noneMatch(docPath::startsWith)) { 232 documentIdsToDelete.add(docId); 233 documentPathsToDelete.add(docPath); 234 } 235 return docId; 236 } 237 238 public static void deleteDocument(String idOrPath) { 239 // TODO change that by proper deleteDocument(String) 240 if (idOrPath.startsWith("/")) { 241 // @yannis : temporary way to avoid DocumentNotFoundException in server log before NXP-19658 242 Documents documents = CLIENT.repository().query(String.format(DOCUMENT_QUERY_BY_PATH_BASE, idOrPath)); 243 if (documents.size() > 0) { 244 CLIENT.repository().deleteDocument(documents.getDocument(0)); 245 } 246 } else { 247 CLIENT.repository().deleteDocument(CLIENT.repository().fetchDocumentById(idOrPath)); 248 } 249 } 250 251 public static void addPermission(String idOrPath, String username, String permission) { 252 Document document; 253 if (idOrPath.startsWith("/")) { 254 document = CLIENT.repository().fetchDocumentByPath(idOrPath); 255 } else { 256 document = CLIENT.repository().fetchDocumentById(idOrPath); 257 } 258 259 ACE ace = new ACE(); 260 ace.setUsername(username); 261 ace.setPermission(permission); 262 263 // @yannis : temporary fix for setting permission before JAVACLIENT-90 is done 264 Calendar beginDate = Calendar.getInstance(); 265 ace.setBegin(beginDate); 266 Calendar endDate = Calendar.getInstance(); 267 endDate.add(Calendar.YEAR, 1); 268 ace.setEnd(endDate); 269 270 document.addPermission(ace); 271 } 272 273 public static void removePermissions(String idOrPath, String username) { 274 Document document; 275 if (idOrPath.startsWith("/")) { 276 document = CLIENT.repository().fetchDocumentByPath(idOrPath); 277 } else { 278 document = CLIENT.repository().fetchDocumentById(idOrPath); 279 } 280 281 document.removePermission(username); 282 } 283 284 public static void logOnServer(String level, String message) { 285 CLIENT.get(String.format("%s/restAPI/systemLog?token=dolog&level=%s&message=%s", AbstractTest.NUXEO_URL, level, 286 URIUtils.quoteURIPathComponent(message, true))); 287 } 288 289}