001package org.apache.fulcrum.security.torque.basic;
002/*
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 */
020import java.sql.Connection;
021import java.util.ArrayList;
022import java.util.List;
023
024import org.apache.fulcrum.security.entity.Group;
025import org.apache.fulcrum.security.entity.User;
026import org.apache.fulcrum.security.model.basic.BasicModelManager;
027import org.apache.fulcrum.security.model.basic.entity.BasicGroup;
028import org.apache.fulcrum.security.model.basic.entity.BasicUser;
029import org.apache.fulcrum.security.spi.AbstractManager;
030import org.apache.fulcrum.security.torque.security.TorqueAbstractSecurityEntity;
031import org.apache.fulcrum.security.util.DataBackendException;
032import org.apache.fulcrum.security.util.UnknownEntityException;
033import org.apache.torque.TorqueException;
034import org.apache.torque.util.Transaction;
035/**
036 * This implementation persists to a database via Torque.
037 *
038 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
039 * @version $Id:$
040 */
041public class TorqueBasicModelManagerImpl extends AbstractManager implements BasicModelManager
042{
043    /**
044     * Puts a user in a group.
045     *
046     * This method is used when adding a user to a group
047     *
048     * @param user the User.
049     * @throws DataBackendException if there was an error accessing the data backend.
050     * @throws UnknownEntityException if the account is not present.
051     */
052    @Override
053        public synchronized void grant(User user, Group group) throws DataBackendException, UnknownEntityException
054    {
055        boolean groupExists = getGroupManager().checkExists(group);
056        boolean userExists = getUserManager().checkExists(user);
057
058        if (groupExists && userExists)
059        {
060            ((BasicUser) user).addGroup(group);
061            ((BasicGroup) group).addUser(user);
062
063            Connection con = null;
064
065            try
066            {
067                con = Transaction.begin();
068
069                ((TorqueAbstractSecurityEntity)user).update(con);
070                ((TorqueAbstractSecurityEntity)group).update(con);
071
072                Transaction.commit(con);
073                con = null;
074            }
075            catch (TorqueException e)
076            {
077                throw new DataBackendException("grant('" + user.getName() + user.getId() + "', '" + group.getName() + group.getId() + "') failed", e);
078            }
079            finally
080            {
081                if (con != null)
082                {
083                    Transaction.safeRollback(con);
084                }
085            }
086
087            return;
088        }
089
090        if (!groupExists)
091        {
092            throw new UnknownEntityException("Unknown group '" + group.getName() + "'");
093        }
094
095        if (!userExists)
096        {
097            throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
098        }
099    }
100
101    /**
102     * Removes a user in a group.
103     *
104     * This method is used when removing a user to a group
105     *
106     * @param user the User.
107     * @throws DataBackendException if there was an error accessing the data backend.
108     * @throws UnknownEntityException if the user or group is not present.
109     */
110    @Override
111        public synchronized void revoke(User user, Group group) throws DataBackendException, UnknownEntityException
112    {
113        boolean groupExists = getGroupManager().checkExists(group);
114        boolean userExists = getUserManager().checkExists(user);
115
116        if (groupExists && userExists)
117        {
118            ((BasicUser) user).removeGroup(group);
119            ((BasicGroup) group).removeUser(user);
120
121            Connection con = null;
122
123            try
124            {
125                con = Transaction.begin();
126
127                ((TorqueAbstractSecurityEntity)user).update(con);
128                ((TorqueAbstractSecurityEntity)group).update(con);
129
130                Transaction.commit(con);
131                con = null;
132            }
133            catch (TorqueException e)
134            {
135                throw new DataBackendException("grant('" + user.getName() + user.getId() + "', '" + group.getName() + group.getId() + "') failed", e);
136            }
137            finally
138            {
139                if (con != null)
140                {
141                    Transaction.safeRollback(con);
142                }
143            }
144
145            return;
146        }
147
148        if (!groupExists)
149        {
150            throw new UnknownEntityException("Unknown group '" + group.getName() + "'");
151        }
152
153        if (!userExists)
154        {
155            throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
156        }
157    }
158
159    /**
160     * Revokes all groups from a user
161     *
162     * This method is used when deleting an account.
163     *
164     * @param user the User.
165     * @throws DataBackendException if there was an error accessing the data backend.
166     * @throws UnknownEntityException if the account is not present.
167     */
168    @Override
169        public synchronized void revokeAll(User user)
170        throws DataBackendException, UnknownEntityException
171    {
172        boolean userExists = getUserManager().checkExists(user);
173
174        if (userExists)
175        {
176            BasicUser u = (BasicUser) user;
177
178            // copy to avoid ConcurrentModificationException
179            List<Group> groups = new ArrayList<Group>(u.getGroups());
180
181            for (Group group : groups)
182            {
183                u.removeGroup(group);
184            }
185
186            Connection con = null;
187
188            try
189            {
190                con = Transaction.begin();
191
192                ((TorqueAbstractSecurityEntity)user).update(con);
193
194                Transaction.commit(con);
195                con = null;
196            }
197            catch (TorqueException e)
198            {
199                throw new DataBackendException("revokeAll('" + user.getName() + user.getId() + "') failed", e);
200            }
201            finally
202            {
203                if (con != null)
204                {
205                    Transaction.safeRollback(con);
206                }
207            }
208
209            return;
210        }
211        else
212        {
213            throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
214        }
215    }
216}