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