001/* 002 * (C) Copyright 2015-2019 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 * 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; 025import static org.nuxeo.ecm.platform.usermanager.UserManagerImpl.USER_HAS_PARTIAL_CONTENT; 026 027import java.io.IOException; 028import java.io.OutputStream; 029import java.util.Collection; 030 031import javax.inject.Inject; 032 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.fasterxml.jackson.core.JsonGenerator; 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(Object, JsonGenerator)}. 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 * } 093 * </pre> 094 * 095 * @since 7.2 096 */ 097@Setup(mode = SINGLETON, priority = REFERENCE) 098public class NuxeoPrincipalJsonWriter extends ExtensibleEntityJsonWriter<NuxeoPrincipal> { 099 100 public static final String ENTITY_TYPE = "user"; 101 102 @Inject 103 private UserManager userManager; 104 105 @Inject 106 private DirectoryService directoryService; 107 108 public NuxeoPrincipalJsonWriter() { 109 super(ENTITY_TYPE, NuxeoPrincipal.class); 110 } 111 112 @Override 113 protected void writeEntityBody(NuxeoPrincipal principal, JsonGenerator jg) throws IOException { 114 jg.writeStringField("id", principal.getName()); 115 writeProperties(jg, principal); 116 writeExtendedGroups(jg, principal); 117 DocumentModel model = principal.getModel(); 118 if (model != null && Boolean.TRUE.equals(model.getContextData(USER_HAS_PARTIAL_CONTENT))) { 119 jg.writeBooleanField("isPartial", true); 120 } 121 jg.writeBooleanField("isAdministrator", principal.isAdministrator()); 122 jg.writeBooleanField("isAnonymous", principal.isAnonymous()); 123 } 124 125 private void writeProperties(JsonGenerator jg, NuxeoPrincipal principal) throws IOException { 126 DocumentModel doc = principal.getModel(); 127 if (doc == null) { 128 return; 129 } 130 String userSchema = userManager.getUserSchemaName(); 131 Collection<Property> properties = doc.getPropertyObjects(userSchema); 132 if (properties.isEmpty()) { 133 return; 134 } 135 Writer<Property> propertyWriter = registry.getWriter(ctx, Property.class, APPLICATION_JSON_TYPE); 136 jg.writeObjectFieldStart("properties"); 137 for (Property property : properties) { 138 String localName = property.getField().getName().getLocalName(); 139 if (!localName.equals(getPasswordField())) { 140 jg.writeFieldName(localName); 141 OutputStream out = new OutputStreamWithJsonWriter(jg); 142 propertyWriter.write(property, Property.class, Property.class, APPLICATION_JSON_TYPE, out); 143 } 144 } 145 jg.writeEndObject(); 146 } 147 148 private void writeExtendedGroups(JsonGenerator jg, NuxeoPrincipal principal) throws IOException { 149 jg.writeArrayFieldStart("extendedGroups"); 150 for (String strGroup : principal.getAllGroups()) { 151 NuxeoGroup group = userManager.getGroup(strGroup); 152 String label = group == null ? strGroup : group.getLabel(); 153 jg.writeStartObject(); 154 jg.writeStringField("name", strGroup); 155 jg.writeStringField("label", label); 156 jg.writeStringField("url", "group/" + strGroup); 157 jg.writeEndObject(); 158 } 159 jg.writeEndArray(); 160 } 161 162 private String getPasswordField() { 163 String userDirectoryName = userManager.getUserDirectoryName(); 164 return directoryService.getDirectory(userDirectoryName).getPasswordField(); 165 } 166 167}