    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><code>
    039 * SecurityCheck mycheck =
    040 *   new SecurityCheck(data, "Unauthorized to do this!", "WrongPermission");
    041 * if (!mycheck.hasPermission("add_user");
    042 *   return;
    043 *</code></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: SecurityCheck.java 1706239 2015-10-01 13:18:35Z tv $
    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     * @exception 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     * @exception 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                modelManager.grant(data.getUser(), modelManager.getGlobalGroup(), roleObject);
    152            }
    153            else
    154            {
    155                throw(e);
    156            }
    157        }
    158
    159        return hasRole(roleObject);
    160    }
    161
    162    /**
    163     * Does the user have this permission?
    164     *
    165     * @param permission A Permission.
    166     * @return True if the user has this permission.
    167     * @exception Exception, a generic exception.
    168     */
    169    public boolean hasPermission(Permission permission)
    170            throws Exception
    171    {
    172        boolean value = false;
    173        TurbineAccessControlList acl = data.getACL();
    174        if (acl == null ||
    175            !acl.hasPermission(permission))
    176        {
    177            data.setScreen(failScreen);
    178            data.setMessage(message);
    179        }
    180        else
    181        {
    182            value = true;
    183        }
    184        return value;
    185    }
    186
    187    /**
    188     * Does the user have this permission? If initialize is set to <code>true</code>
    189     * The permission will be created and granted to the first available Role of
    190     * the user, that the SecurityCheck is running against.
    191     *
    192     * If the User has no Roles, the first Role via TurbineSecurity is granted the
    193     * permission.
    194     *
    195     * @param permission
    196     *            A String.
    197     * @return True if the user has this permission.
    198     * @exception Exception,
    199     *                a generic exception.
    200     */
    201    public boolean hasPermission(String permission)
    202            throws Exception
    203    {
    204        Permission permissionObject = null;
    205        try
    206        {
    207            permissionObject = securityService.getPermissionManager().getPermissionByName(permission);
    208        }
    209        catch (UnknownEntityException e)
    210        {
    211            if(initialize)
    212            {
    213                permissionObject = securityService.getPermissionManager().getPermissionInstance(permission);
    214                securityService.getPermissionManager().addPermission(permissionObject);
    215
    216                Role role = null;
    217                TurbineAccessControlList acl = data.getACL();
    218                RoleSet roles = acl.getRoles();
    219                if(roles.size() > 0)
    220                {
    221                                        role = roles.toArray(new Role[0])[0];
    222                                }
    223
    224                if(role == null)
    225                {
    226                    /*
    227                     * The User within data has no roles yet, let us grant the permission
    228                     * to the first role available through TurbineSecurity.
    229                     */
    230                    roles = securityService.getRoleManager().getAllRoles();
    231                    if(roles.size() > 0)
    232                    {
    233                                                role = roles.toArray(new Role[0])[0];
    234                                        }
    235                }
    236
    237                if(role != null)
    238                {
    239                    /*
    240                     * If we have no role, there is nothing we can do about it. So only grant it,
    241                     * if we have a role to grant it to.
    242                     */
    243                    TurbineModelManager modelManager = (TurbineModelManager)securityService.getModelManager();
    244                    modelManager.grant(role, permissionObject);
    245                }
    246            }
    247            else
    248            {
    249                throw(e);
    250            }
    251        }
    252
    253        return hasPermission(permissionObject);
    254    }
    255
    256    /**
    257     * Get the message that should be displayed.  This is initialized
    258     * in the constructor.
    259     *
    260     * @return A String.
    261     */
    262    public String getMessage()
    263    {
    264        return message;
    265    }
    266
    267    /**
    268     * Get the screen that should be displayed.  This is initialized
    269     * in the constructor.
    270     *
    271     * @return A String.
    272     */
    273    public String getFailScreen()
    274    {
    275        return failScreen;
    276    }
    277}