001/*
002 * (C) Copyright 2013 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 *     dmetzler
018 */
019package org.nuxeo.ecm.restapi.server.jaxrs.usermanager;
020
021import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
022import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
023
024import java.util.HashSet;
025import java.util.LinkedList;
026import java.util.List;
027import java.util.Queue;
028import java.util.Set;
029
030import org.nuxeo.ecm.core.api.NuxeoException;
031import org.nuxeo.ecm.core.api.NuxeoGroup;
032import org.nuxeo.ecm.platform.query.api.PageProviderDefinition;
033import org.nuxeo.ecm.platform.query.api.PageProviderService;
034import org.nuxeo.ecm.platform.usermanager.UserManager;
035import org.nuxeo.ecm.webengine.model.WebObject;
036import org.nuxeo.runtime.api.Framework;
037
038/**
039 * @since 5.7.3
040 */
041@WebObject(type = "groups")
042public class GroupRootObject extends AbstractUMRootObject<NuxeoGroup> {
043
044    public static final String PAGE_PROVIDER_NAME = "nuxeo_groups_listing";
045
046    @Override
047    protected NuxeoGroup getArtifact(String id) {
048        return um.getGroup(id);
049    }
050
051    @Override
052    protected String getArtifactType() {
053        return "group";
054    }
055
056    @Override
057    protected void checkPrecondition(NuxeoGroup group) {
058        checkCurrentUserCanCreateArtifact(group);
059        checkGroupHasAName(group);
060        checkGroupDoesNotAlreadyExists(group, um);
061    }
062
063    @Override
064    protected NuxeoGroup createArtifact(NuxeoGroup group) {
065        um.createGroup(group.getModel());
066        return um.getGroup(group.getName());
067    }
068
069    private void checkGroupDoesNotAlreadyExists(NuxeoGroup group, UserManager um) {
070        if (um.getGroup(group.getName()) != null) {
071            throw new NuxeoException("Group already exists", SC_CONFLICT);
072        }
073    }
074
075    private void checkGroupHasAName(NuxeoGroup group) {
076        if (group.getName() == null) {
077            throw new NuxeoException("Group MUST have a name", SC_BAD_REQUEST);
078        }
079    }
080
081    @Override
082    boolean isAPowerUserEditableArtifact(NuxeoGroup artifact) {
083        return isAPowerUserEditableGroup(artifact);
084
085    }
086
087    static boolean isAPowerUserEditableGroup(NuxeoGroup group) {
088        UserManager um = Framework.getService(UserManager.class);
089        Set<String> allGroups = computeAllGroups(um, group);
090        List<String> administratorsGroups = um.getAdministratorsGroups();
091        return allGroups.stream().noneMatch(administratorsGroups::contains);
092    }
093
094    protected static Set<String> computeAllGroups(UserManager um, NuxeoGroup group) {
095        Set<String> allGroups = new HashSet<>();
096        Queue<NuxeoGroup> queue = new LinkedList<>();
097        queue.add(group);
098
099        while (!queue.isEmpty()) {
100            NuxeoGroup nuxeoGroup = queue.poll();
101            allGroups.add(nuxeoGroup.getName());
102            nuxeoGroup.getParentGroups()
103                      .stream()
104                      .filter(pg -> !allGroups.contains(pg))
105                      .map(um::getGroup)
106                      .forEach(queue::add);
107        }
108
109        return allGroups;
110    }
111
112    @Override
113    protected PageProviderDefinition getPageProviderDefinition() {
114        PageProviderService ppService = Framework.getService(PageProviderService.class);
115        return ppService.getPageProviderDefinition(PAGE_PROVIDER_NAME);
116    }
117
118}