001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Nuxeo - initial API and implementation
011 *
012 * $Id$
013 */
014
015package org.nuxeo.ecm.core.api.security.impl;
016
017import java.util.ArrayList;
018import java.util.Arrays;
019import java.util.Iterator;
020import java.util.List;
021
022import org.nuxeo.ecm.core.api.security.ACE;
023import org.nuxeo.ecm.core.api.security.ACL;
024import org.nuxeo.ecm.core.api.security.AdministratorGroupsProvider;
025import org.nuxeo.ecm.core.api.security.SecurityConstants;
026import org.nuxeo.runtime.api.Framework;
027
028import com.google.common.collect.Lists;
029
030/**
031 * An ACL implementation.
032 *
033 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
034 */
035public class ACLImpl extends ArrayList<ACE>implements ACL {
036
037    private static final long serialVersionUID = 5332101749929771434L;
038
039    private final String name;
040
041    private final boolean isReadOnly;
042
043    public ACLImpl(String name, boolean isReadOnly) {
044        this.name = name;
045        this.isReadOnly = isReadOnly;
046    }
047
048    public ACLImpl() {
049        this(LOCAL_ACL, false);
050    }
051
052    public ACLImpl(String name) {
053        this(name, false);
054    }
055
056    @Override
057    public String getName() {
058        return name;
059    }
060
061    @Override
062    public ACE[] getACEs() {
063        return toArray(new ACE[size()]);
064    }
065
066    @Override
067    public void setACEs(ACE[] aces) {
068        clear();
069        addAll(Arrays.asList(aces));
070    }
071
072    public boolean isReadOnly() {
073        return isReadOnly;
074    }
075
076    @Override
077    public boolean blockInheritance(String username) {
078        boolean aclChanged = false;
079        List<ACE> aces = Lists.newArrayList(getACEs());
080        if (!aces.contains(ACE.BLOCK)) {
081            aces.add(ACE.builder(username, SecurityConstants.EVERYTHING).creator(username).build());
082            aces.addAll(getAdminEverythingACES());
083            aces.add(ACE.BLOCK);
084            aclChanged = true;
085            setACEs(aces.toArray(new ACE[aces.size()]));
086        }
087        return aclChanged;
088    }
089
090    @Override
091    public boolean unblockInheritance() {
092        boolean aclChanged = false;
093        List<ACE> aces = Lists.newArrayList(getACEs());
094        if (aces.contains(ACE.BLOCK)) {
095            aces.remove(ACE.BLOCK);
096            aclChanged = true;
097            setACEs(aces.toArray(new ACE[aces.size()]));
098        }
099        return aclChanged;
100    }
101
102    @Override
103    public boolean add(ACE ace) {
104        boolean aclChanged = false;
105        List<ACE> aces = Lists.newArrayList(getACEs());
106        if (!aces.contains(ace)) {
107            int pos = aces.indexOf(ACE.BLOCK);
108            if (pos >= 0) {
109                aces.add(pos, ace);
110            } else {
111                aces.add(ace);
112            }
113            aclChanged = true;
114            setACEs(aces.toArray(new ACE[aces.size()]));
115        }
116
117        return aclChanged;
118    }
119
120    protected List<ACE> getAdminEverythingACES() {
121        List<ACE> aces = new ArrayList<>();
122        AdministratorGroupsProvider provider = Framework.getLocalService(AdministratorGroupsProvider.class);
123        List<String> administratorsGroups = provider.getAdministratorsGroups();
124        for (String adminGroup : administratorsGroups) {
125            aces.add(new ACE(adminGroup, SecurityConstants.EVERYTHING, true));
126        }
127        return aces;
128    }
129
130    @Override
131    public boolean replace(ACE oldACE, ACE newACE) {
132        boolean aclChanged = false;
133        int index = indexOf(oldACE);
134        if (index != -1) {
135            remove(oldACE);
136            add(index, newACE);
137            aclChanged = true;
138        }
139
140        return aclChanged;
141    }
142
143    @Override
144    public boolean removeByUsername(String username) {
145        boolean aclChanged = false;
146
147        List<ACE> aces = Lists.newArrayList(getACEs());
148        for (Iterator<ACE> it = aces.iterator(); it.hasNext();) {
149            ACE ace = it.next();
150            if (ace.getUsername().equals(username)) {
151                it.remove();
152                aclChanged = true;
153            }
154        }
155        setACEs(aces.toArray(new ACE[aces.size()]));
156
157        return aclChanged;
158    }
159
160    @Override
161    public Object clone() {
162        ACLImpl copy = new ACLImpl(name, isReadOnly);
163        ACE[] aces = new ACE[size()];
164        for (int i = 0; i < size(); i++) {
165            aces[i] = (ACE) get(i).clone();
166        }
167        copy.setACEs(aces);
168        return copy;
169    }
170
171}