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