001/* 002 * (C) Copyright 2015 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 * Nicolas Chapurlat <nchapurlat@nuxeo.com> 018 */ 019 020package org.nuxeo.ecm.platform.usermanager.io; 021 022import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; 023import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 024import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 025 026import java.io.IOException; 027import java.io.OutputStream; 028import java.util.Collection; 029 030import javax.inject.Inject; 031 032import org.codehaus.jackson.JsonGenerator; 033import org.nuxeo.ecm.core.api.DocumentModel; 034import org.nuxeo.ecm.core.api.NuxeoGroup; 035import org.nuxeo.ecm.core.api.NuxeoPrincipal; 036import org.nuxeo.ecm.core.api.model.Property; 037import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter; 038import org.nuxeo.ecm.core.io.marshallers.json.OutputStreamWithJsonWriter; 039import org.nuxeo.ecm.core.io.marshallers.json.document.DocumentPropertyJsonWriter; 040import org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher; 041import org.nuxeo.ecm.core.io.registry.Writer; 042import org.nuxeo.ecm.core.io.registry.reflect.Setup; 043import org.nuxeo.ecm.directory.api.DirectoryService; 044import org.nuxeo.ecm.platform.usermanager.UserManager; 045 046import com.thoughtworks.xstream.io.json.JsonWriter; 047 048/** 049 * Convert {@link NuxeoPrincipal} to Json. 050 * <p> 051 * This marshaller is enrichable: register class implementing {@link AbstractJsonEnricher} and managing 052 * {@link NuxeoPrincipal}. 053 * </p> 054 * <p> 055 * This marshaller is also extensible: extend it and simply override 056 * {@link ExtensibleEntityJsonWriter#extend(NuxeoPrincipal, JsonWriter)}. 057 * </p> 058 * <p> 059 * Format is: 060 * 061 * <pre> 062 * {@code 063 * { 064 * "entity-type":"user", 065 * "id":"USERNAME", 066 * "properties":{ <- depending on the user schema / format is managed by {@link DocumentPropertyJsonWriter} 067 * "firstName":"FIRSTNAME", 068 * "lastName":"LASTNAME", 069 * "username":"USERNAME", 070 * "email":"user@mail.com", 071 * "company":"COMPANY", 072 * "password":"", <- ALWAYS EMPTY 073 * "groups":[ 074 * "GROUP1 NAME OF THE USER", 075 * "GROUP2 NAME OF THE USER", 076 * ... 077 * ] 078 * }, 079 * "extendedGroups":[ 080 * { 081 * "name":"GROUP1NAME", 082 * "label":"GROUP1 DISPLAY NAME", 083 * "url":"GROUP1 URL" 084 * }, 085 * ... 086 * ], 087 * "isAdministrator":true|false, 088 * "isAnonymous":false|false 089 * <-- contextParameters if there are enrichers activated 090 * <-- additional property provided by extend() method 091 * } 092 * </pre> 093 * 094 * </p> 095 * 096 * @since 7.2 097 */ 098@Setup(mode = SINGLETON, priority = REFERENCE) 099public class NuxeoPrincipalJsonWriter extends ExtensibleEntityJsonWriter<NuxeoPrincipal> { 100 101 public static final String ENTITY_TYPE = "user"; 102 103 @Inject 104 private UserManager userManager; 105 106 @Inject 107 private DirectoryService directoryService; 108 109 public NuxeoPrincipalJsonWriter() { 110 super(ENTITY_TYPE, NuxeoPrincipal.class); 111 } 112 113 @Override 114 protected void writeEntityBody(NuxeoPrincipal principal, JsonGenerator jg) throws IOException { 115 jg.writeStringField("id", principal.getName()); 116 writeProperties(jg, principal); 117 writeExtendedGroups(jg, principal); 118 jg.writeBooleanField("isAdministrator", principal.isAdministrator()); 119 jg.writeBooleanField("isAnonymous", principal.isAnonymous()); 120 } 121 122 private void writeProperties(JsonGenerator jg, NuxeoPrincipal principal) throws IOException { 123 DocumentModel doc = principal.getModel(); 124 if (doc == null) { 125 return; 126 } 127 String userSchema = userManager.getUserSchemaName(); 128 Collection<Property> properties = doc.getPropertyObjects(userSchema); 129 if (properties.isEmpty()) { 130 return; 131 } 132 Writer<Property> propertyWriter = registry.getWriter(ctx, Property.class, APPLICATION_JSON_TYPE); 133 jg.writeObjectFieldStart("properties"); 134 for (Property property : properties) { 135 String localName = property.getField().getName().getLocalName(); 136 jg.writeFieldName(localName); 137 if (localName.equals(getPasswordField())) { 138 jg.writeString(""); 139 } else { 140 OutputStream out = new OutputStreamWithJsonWriter(jg); 141 propertyWriter.write(property, Property.class, Property.class, APPLICATION_JSON_TYPE, out); 142 } 143 } 144 jg.writeEndObject(); 145 } 146 147 private void writeExtendedGroups(JsonGenerator jg, NuxeoPrincipal principal) throws IOException { 148 jg.writeArrayFieldStart("extendedGroups"); 149 for (String strGroup : principal.getAllGroups()) { 150 NuxeoGroup group = userManager.getGroup(strGroup); 151 String label = group == null ? strGroup : group.getLabel(); 152 jg.writeStartObject(); 153 jg.writeStringField("name", strGroup); 154 jg.writeStringField("label", label); 155 jg.writeStringField("url", "group/" + strGroup); 156 jg.writeEndObject(); 157 } 158 jg.writeEndArray(); 159 } 160 161 private String getPasswordField() { 162 String userDirectoryName = userManager.getUserDirectoryName(); 163 return directoryService.getDirectory(userDirectoryName).getPasswordField(); 164 } 165 166}