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; 025 026import java.io.IOException; 027import java.io.OutputStream; 028import java.util.Arrays; 029import java.util.Collection; 030import java.util.List; 031 032import javax.inject.Inject; 033 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.NuxeoGroup; 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.platform.usermanager.UserManager; 044 045import com.fasterxml.jackson.core.JsonGenerator; 046 047/** 048 * Convert {@link NuxeoGroup} to Json. 049 * <p> 050 * This marshaller is enrichable: register class implementing {@link AbstractJsonEnricher} and managing 051 * {@link NuxeoGroup}. 052 * </p> 053 * <p> 054 * This marshaller is also extensible: extend it and simply override 055 * {@link ExtensibleEntityJsonWriter#extend(Object, JsonGenerator)}. 056 * </p> 057 * <p> 058 * Format is: 059 * 060 * <pre> 061 * {@code 062 * { 063 * "entity-type":"group", 064 * "groupname": "GROUP_NAME", <- deprecated, for backward compatibility 065 * "grouplabel": "GROUP_DISPLAY_NAME", <- deprecated, for backward compatibility 066 * "id": "GROUP_NAME", 067 * "properties":{ <- depending on the group schema / format is managed by {@link DocumentPropertyJsonWriter } 068 * "groupname":"GROUP_NAME", 069 * "grouplabel":"GROUP_DISPLAY_NAME", 070 * "description": "GROUP_DESCRIPTION" 071 * }, 072 * "memberUsers": [ 073 * "USERNAME1", 074 * "USERNAME2", 075 * ... 076 * ], 077 * "memberGroups": [ 078 * "GROUPNAME1", 079 * "GROUPNAME2", 080 * ... 081 * ], 082 * "parentGroups": [ 083 * "GROUPNAME1", 084 * "GROUPNAME2", 085 * ... 086 * ] 087 * <-- contextParameters if there are enrichers activated 088 * <-- additional property provided by extend() method 089 * } 090 * } 091 * </pre> 092 * 093 * @since 7.2 094 */ 095@Setup(mode = SINGLETON, priority = REFERENCE) 096public class NuxeoGroupJsonWriter extends ExtensibleEntityJsonWriter<NuxeoGroup> { 097 098 public static final String ENTITY_TYPE = "group"; 099 100 /** 101 * @since 9.3 102 */ 103 public static final String MEMBER_USERS_FETCH_PROPERTY = "memberUsers"; 104 105 /** 106 * @since 9.3 107 */ 108 public static final String MEMBER_GROUPS_FETCH_PROPERTY = "memberGroups"; 109 110 /** 111 * @since 9.3 112 */ 113 public static final String PARENT_GROUPS_FETCH_PROPERTY = "parentGroups"; 114 115 /** 116 * @since 9.3 117 */ 118 public static final String GROUP_NAME_COMPATIBILITY_FIELD = "groupname"; 119 120 /** 121 * @since 9.3 122 */ 123 public static final String GROUP_LABEL_COMPATIBILITY_FIELD = "grouplabel"; 124 125 @Inject 126 private UserManager userManager; 127 128 public NuxeoGroupJsonWriter() { 129 super(ENTITY_TYPE, NuxeoGroup.class); 130 } 131 132 @Override 133 protected void writeEntityBody(NuxeoGroup group, JsonGenerator jg) throws IOException { 134 // for backward compatibility, those are now in the 'properties' field 135 jg.writeStringField(GROUP_NAME_COMPATIBILITY_FIELD, group.getName()); 136 jg.writeStringField(GROUP_LABEL_COMPATIBILITY_FIELD, group.getLabel()); 137 138 jg.writeStringField("id", group.getName()); 139 writeProperties(group, jg); 140 writeMemberUsers(group, jg); 141 writeMemberGroups(group, jg); 142 writeParentGroups(group, jg); 143 } 144 145 protected void writeProperties(NuxeoGroup group, JsonGenerator jg) throws IOException { 146 DocumentModel doc = group.getModel(); 147 if (doc == null) { 148 return; 149 } 150 String groupSchema = userManager.getGroupSchemaName(); 151 Collection<Property> properties = doc.getPropertyObjects(groupSchema); 152 if (properties.isEmpty()) { 153 return; 154 } 155 156 List<String> excludedProperties = Arrays.asList(userManager.getGroupMembersField(), 157 userManager.getGroupSubGroupsField(), userManager.getGroupParentGroupsField()); 158 Writer<Property> propertyWriter = registry.getWriter(ctx, Property.class, APPLICATION_JSON_TYPE); 159 jg.writeObjectFieldStart("properties"); 160 for (Property property : properties) { 161 String localName = property.getField().getName().getLocalName(); 162 if (!excludedProperties.contains(localName)) { 163 jg.writeFieldName(localName); 164 OutputStream out = new OutputStreamWithJsonWriter(jg); 165 propertyWriter.write(property, Property.class, Property.class, APPLICATION_JSON_TYPE, out); 166 } 167 } 168 jg.writeEndObject(); 169 } 170 171 protected void writeMemberUsers(NuxeoGroup group, JsonGenerator jg) throws IOException { 172 if (ctx.getFetched(ENTITY_TYPE).contains(MEMBER_USERS_FETCH_PROPERTY)) { 173 jg.writeArrayFieldStart(MEMBER_USERS_FETCH_PROPERTY); 174 for (String user : group.getMemberUsers()) { 175 jg.writeString(user); 176 } 177 jg.writeEndArray(); 178 } 179 } 180 181 protected void writeMemberGroups(NuxeoGroup group, JsonGenerator jg) throws IOException { 182 if (ctx.getFetched(ENTITY_TYPE).contains(MEMBER_GROUPS_FETCH_PROPERTY)) { 183 jg.writeArrayFieldStart(MEMBER_GROUPS_FETCH_PROPERTY); 184 for (String user : group.getMemberGroups()) { 185 jg.writeString(user); 186 } 187 jg.writeEndArray(); 188 } 189 } 190 191 protected void writeParentGroups(NuxeoGroup group, JsonGenerator jg) throws IOException { 192 if (ctx.getFetched(ENTITY_TYPE).contains(PARENT_GROUPS_FETCH_PROPERTY)) { 193 jg.writeArrayFieldStart(PARENT_GROUPS_FETCH_PROPERTY); 194 for (String user : group.getParentGroups()) { 195 jg.writeString(user); 196 } 197 jg.writeEndArray(); 198 } 199 } 200 201}