001package org.apache.turbine.util;
002
003
004/*
005 * Licensed to the Apache Software Foundation (ASF) under one
006 * or more contributor license agreements.  See the NOTICE file
007 * distributed with this work for additional information
008 * regarding copyright ownership.  The ASF licenses this file
009 * to you under the Apache License, Version 2.0 (the
010 * "License"); you may not use this file except in compliance
011 * with the License.  You may obtain a copy of the License at
012 *
013 *   http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing,
016 * software distributed under the License is distributed on an
017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
018 * KIND, either express or implied.  See the License for the
019 * specific language governing permissions and limitations
020 * under the License.
021 */
022
023
024import org.apache.fulcrum.security.SecurityService;
025import org.apache.fulcrum.security.entity.Permission;
026import org.apache.fulcrum.security.entity.Role;
027import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
028import org.apache.fulcrum.security.model.turbine.TurbineModelManager;
029import org.apache.fulcrum.security.util.RoleSet;
030import org.apache.fulcrum.security.util.UnknownEntityException;
031import org.apache.turbine.services.TurbineServices;
032
033/**
034 * Utility for doing security checks in Screens and Actions.
035 *
036 * Sample usage:<br>
037 *
038 * <pre>
039 * SecurityCheck mycheck =
040 *   new SecurityCheck(data, "Unauthorized to do this!", "WrongPermission");
041 * if (!mycheck.hasPermission("add_user");
042 *   return;
043 *</pre>
044 *
045 * @author <a href="mailto:mbryson@mindspring.com">Dave Bryson</a>
046 * @author <a href="jh@byteaction.de">J&#252;rgen Hoffmann</a>
047 * @version $Id$
048 */
049public class SecurityCheck
050{
051    private String message;
052
053    private String failScreen;
054
055    private RunData data = null;
056
057    private SecurityService securityService = null;
058
059    /**
060     * Holds information if a missing Permission or Role should be created and granted on-the-fly.
061     * This is good behavior, if these change a lot.
062     */
063    private boolean initialize;
064
065    /**
066     * Constructor.
067     *
068     * @param data A Turbine RunData object.
069     * @param message The message to display upon failure.
070     * @param failedScreen The screen to redirect to upon failure.
071     */
072    public SecurityCheck(RunData data,
073                         String message,
074                         String failedScreen)
075    {
076        this(data, message, failedScreen, false);
077    }
078
079    /**
080     * Constructor.
081     *
082     * @param data
083     *            A Turbine RunData object.
084     * @param message
085     *            The message to display upon failure.
086     * @param failedScreen
087     *            The screen to redirect to upon failure.
088     * @param initialize
089     *            if a non-existing Permission or Role should be created.
090     */
091    public SecurityCheck(RunData data, String message, String failedScreen, boolean initialize)
092    {
093        this.data = data;
094        this.message = message;
095        this.failScreen = failedScreen;
096        this.initialize = initialize;
097        this.securityService = (SecurityService)TurbineServices
098                .getInstance()
099                .getService(SecurityService.ROLE);
100    }
101
102    /**
103     * Does the user have this role?
104     *
105     * @param role A Role.
106     * @return True if the user has this role.
107     * @throws Exception a generic exception.
108     */
109    public boolean hasRole(Role role)
110            throws Exception
111    {
112        boolean value = false;
113        TurbineAccessControlList<?> acl = data.getACL();
114        if (acl == null ||
115            !acl.hasRole(role))
116        {
117            data.setScreen(failScreen);
118            data.setMessage(message);
119        }
120        else
121        {
122            value = true;
123        }
124        return value;
125    }
126
127    /**
128     * Does the user have this role?
129     *
130     * @param role
131     *            A String.
132     * @return True if the user has this role.
133     * @throws Exception
134     *                a generic exception.
135     */
136    public boolean hasRole(String role) throws Exception
137    {
138        Role roleObject = null;
139
140        try
141        {
142            roleObject = securityService.getRoleManager().getRoleByName(role);
143        }
144        catch (UnknownEntityException e)
145        {
146            if(initialize)
147            {
148                roleObject = securityService.getRoleManager().getRoleInstance(role);
149                securityService.getRoleManager().addRole(roleObject);
150                TurbineModelManager modelManager = (TurbineModelManager)securityService.getModelManager();
151                if (data.getUser() == null) {
152                  throw new UnknownEntityException("user is null");
153                }
154                modelManager.grant(data.getUser().getUserDelegate(), modelManager.getGlobalGroup(), roleObject);
155            }
156            else
157            {
158                throw(e);
159            }
160        }
161
162        return hasRole(roleObject);
163    }
164
165    /**
166     * Does the user have this permission?
167     *
168     * @param permission A Permission.
169     * @return True if the user has this permission.
170     * @throws Exception a generic exception.
171     */
172    public boolean hasPermission(Permission permission)
173            throws Exception
174    {
175        boolean value = false;
176        TurbineAccessControlList<?> acl = data.getACL();
177        if (acl == null ||
178            !acl.hasPermission(permission))
179        {
180            data.setScreen(failScreen);
181            data.setMessage(message);
182        }
183        else
184        {
185            value = true;
186        }
187        return value;
188    }
189
190    /**
191     * Does the user have this permission? If initialize is set to <code>true</code>
192     * The permission will be created and granted to the first available Role of
193     * the user, that the SecurityCheck is running against.
194     *
195     * If the User has no Roles, the first Role via SecurityService is granted the
196     * permission.
197     *
198     * @param permission
199     *            A String.
200     * @return True if the user has this permission.
201     * @throws Exception
202     *                a generic exception.
203     */
204    public boolean hasPermission(String permission)
205            throws Exception
206    {
207        Permission permissionObject = null;
208        try
209        {
210            permissionObject = securityService.getPermissionManager().getPermissionByName(permission);
211        }
212        catch (UnknownEntityException e)
213        {
214            if(initialize)
215            {
216                permissionObject = securityService.getPermissionManager().getPermissionInstance(permission);
217                securityService.getPermissionManager().addPermission(permissionObject);
218
219                Role role = null;
220                TurbineAccessControlList<?> acl = data.getACL();
221                RoleSet roles = acl.getRoles();
222                if(roles.size() > 0)
223                {
224                                        role = roles.toArray(new Role[0])[0];
225                                }
226
227                if(role == null)
228                {
229                    /*
230                     * The User within data has no roles yet, let us grant the permission
231                     * to the first role available through SecurityService.
232                     */
233                    roles = securityService.getRoleManager().getAllRoles();
234                    if(roles.size() > 0)
235                    {
236                                                role = roles.toArray(new Role[0])[0];
237                                        }
238                }
239
240                if(role != null)
241                {
242                    /*
243                     * If we have no role, there is nothing we can do about it. So only grant it,
244                     * if we have a role to grant it to.
245                     */
246                    TurbineModelManager modelManager = (TurbineModelManager)securityService.getModelManager();
247                    modelManager.grant(role, permissionObject);
248                }
249            }
250            else
251            {
252                throw(e);
253            }
254        }
255
256        return hasPermission(permissionObject);
257    }
258
259    /**
260     * Get the message that should be displayed.  This is initialized
261     * in the constructor.
262     *
263     * @return A String.
264     */
265    public String getMessage()
266    {
267        return message;
268    }
269
270    /**
271     * Get the screen that should be displayed.  This is initialized
272     * in the constructor.
273     *
274     * @return A String.
275     */
276    public String getFailScreen()
277    {
278        return failScreen;
279    }
280}