001: package org.tigris.scarab.actions;
002:
003: /* ================================================================
004: * Copyright (c) 2000-2002 CollabNet. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are
008: * met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowlegement: "This product includes
019: * software developed by Collab.Net <http://www.Collab.Net/>."
020: * Alternately, this acknowlegement may appear in the software itself, if
021: * and wherever such third-party acknowlegements normally appear.
022: *
023: * 4. The hosted project names must not be used to endorse or promote
024: * products derived from this software without prior written
025: * permission. For written permission, please contact info@collab.net.
026: *
027: * 5. Products derived from this software may not use the "Tigris" or
028: * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
029: * prior written permission of Collab.Net.
030: *
031: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
032: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
033: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
034: * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
035: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
036: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
037: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
038: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
039: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
040: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
041: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
042: *
043: * ====================================================================
044: *
045: * This software consists of voluntary contributions made by many
046: * individuals on behalf of Collab.Net.
047: */
048:
049: import java.io.Serializable;
050: import java.util.List;
051: import java.util.ArrayList;
052: import java.util.Arrays;
053: import java.util.Iterator;
054:
055: // Turbine Stuff
056: import org.apache.torque.TorqueException;
057: import org.apache.torque.util.Criteria;
058: import org.apache.turbine.TemplateContext;
059: import org.apache.turbine.RunData;
060:
061: import org.apache.fulcrum.security.TurbineSecurity;
062: import org.apache.fulcrum.security.entity.Role;
063: import org.apache.fulcrum.security.util.AccessControlList;
064:
065: // Scarab Stuff
066: import org.tigris.scarab.om.PendingGroupUserRolePeer;
067: import org.tigris.scarab.om.ScarabUser;
068: import org.tigris.scarab.om.ScarabModule;
069: import org.tigris.scarab.om.PendingGroupUserRole;
070: import org.tigris.scarab.om.ScarabUserManager;
071: import org.tigris.scarab.tools.SecurityAdminTool;
072: import org.tigris.scarab.tools.ScarabRequestTool;
073: import org.tigris.scarab.tools.localization.L10NMessage;
074: import org.tigris.scarab.tools.localization.L10NKeySet;
075: import org.tigris.scarab.tools.localization.Localizable;
076: import org.tigris.scarab.util.ScarabConstants;
077: import org.tigris.scarab.actions.base.RequireLoginFirstAction;
078: import org.tigris.scarab.util.EmailContext;
079: import org.tigris.scarab.util.Email;
080: import org.tigris.scarab.util.SimpleSkipFiltering;
081: import org.tigris.scarab.services.security.ScarabSecurity;
082:
083: /**
084: * This class is responsible for moderated self-serve role assignments
085: * within a particular module.
086: *
087: * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
088: */
089: public class HandleRoleRequests extends RequireLoginFirstAction {
090: public void doRequestroles(RunData data, TemplateContext context)
091: throws Exception {
092: String template = getCurrentTemplate(data, null);
093: String nextTemplate = getNextTemplate(data, template);
094: ScarabUser user = (ScarabUser) data.getUser();
095: SecurityAdminTool scarabA = getSecurityAdminTool(context);
096: ScarabRequestTool scarabR = getScarabRequestTool(context);
097:
098: // List roles = scarabA.getNonRootRoles();
099: List groups = Arrays.asList(scarabA.getGroups());
100:
101: Iterator gi = groups.iterator();
102:
103: String autoApproveRoleSet = null;
104: String waitApproveRoleSet = null;
105:
106: while (gi.hasNext()) {
107: ScarabModule module = ((ScarabModule) gi.next());
108: String[] autoRoles = module.getAutoApprovedRoles();
109: String roleName = data.getParameters().getString(
110: module.getModuleId().toString());
111: AccessControlList acl = user.getACL();
112: Role requiredRoleForRequests = module.getRequiredRole();
113: boolean bRoleRequestable = requiredRoleForRequests == null
114: || acl.hasRole(requiredRoleForRequests, module);
115: if (roleName != null && roleName.length() > 0
116: && bRoleRequestable) {
117: boolean autoApprove = Arrays.asList(autoRoles)
118: .contains(roleName);
119: if (autoApprove) {
120: TurbineSecurity.grant(user, module, TurbineSecurity
121: .getRole(roleName));
122:
123: // TODO: Needs to be refactored into the Users system?
124: ScarabUserManager.getMethodResult().remove(
125: user.getUserName(),
126: ScarabUserManager.GET_ACL);
127: ScarabUserManager.getMethodResult().remove(
128: user.getUserName(),
129: ScarabUserManager.HAS_ROLE_IN_MODULE,
130: roleName, module.getModuleId());
131:
132: autoApproveRoleSet = addToRoleSet(
133: autoApproveRoleSet, module, roleName);
134: } else {
135: deleteRoleRequests(user, module);
136: // '0' role really means 'remove request' from module
137: if (!roleName.equals("0")) {
138: try {
139: sendNotification(module, user, roleName);
140: } catch (Exception e) {
141: L10NMessage l10nMessage = new L10NMessage(
142: L10NKeySet.CouldNotSendNotification,
143: e);
144: scarabR.setAlertMessage(l10nMessage);
145: }
146: PendingGroupUserRole pend = new PendingGroupUserRole();
147: pend.setGroupId(module.getModuleId());
148: pend.setUserId(user.getUserId());
149: pend.setRoleName(roleName);
150: pend.save();
151: waitApproveRoleSet = addToRoleSet(
152: waitApproveRoleSet, module, roleName);
153: }
154: }
155: }
156: }
157:
158: if (autoApproveRoleSet != null) {
159: SimpleSkipFiltering htmlSet = new SimpleSkipFiltering(
160: autoApproveRoleSet + "<br>");
161: Localizable msg = new L10NMessage(
162: L10NKeySet.RoleRequestGranted, htmlSet);
163: scarabR.setConfirmMessage(msg);
164: }
165:
166: if (waitApproveRoleSet != null) {
167: SimpleSkipFiltering htmlSet = new SimpleSkipFiltering(
168: waitApproveRoleSet + "<br>");
169: Localizable msg = new L10NMessage(
170: L10NKeySet.RoleRequestAwaiting, htmlSet);
171: scarabR.setInfoMessage(msg);
172: }
173:
174: setTarget(data, nextTemplate);
175: }
176:
177: private void deleteRoleRequests(ScarabUser user, ScarabModule module) {
178: Criteria crit = new Criteria();
179: crit.add(PendingGroupUserRolePeer.GROUP_ID, module
180: .getModuleId());
181: crit.add(PendingGroupUserRolePeer.USER_ID, user.getUserId());
182: try {
183: PendingGroupUserRolePeer.doDelete(crit);
184: } catch (TorqueException e) {
185: log().error("deleteRoleRequests: " + e);
186: }
187: }
188:
189: /**
190: * Add a role to the String representation of the list of
191: * roles (used later for display purposes).
192: * @param autoApproveRoleSet
193: * @param role
194: * @return
195: */
196: private String addToRoleSet(String roleSet, ScarabModule module,
197: String role) {
198: String result;
199: if (roleSet == null) {
200: result = "<br> ";
201: } else {
202: result = roleSet + "<br> ";
203: }
204: result += module.getName() + ":" + role;
205: return result;
206: }
207:
208: /**
209: * Helper method to retrieve the ScarabRequestTool from the Context
210: */
211: private SecurityAdminTool getSecurityAdminTool(
212: TemplateContext context) {
213: return (SecurityAdminTool) context
214: .get(ScarabConstants.SECURITY_ADMIN_TOOL);
215: }
216:
217: /**
218: * Send email notification about role request to all users which have the rights
219: * to approve the request. If those users include both users which have
220: * a role in the module, and those who don't (like global admin), only
221: * users with roles in the module are notified.
222: * Returns true if everything is OK, and false in case of error.
223: */
224: private void sendNotification(ScarabModule module, ScarabUser user,
225: String role) throws Exception {
226: EmailContext econtext = new EmailContext();
227:
228: econtext.setModule(module);
229: econtext.setUser(user);
230: econtext.put("role", role);
231:
232: // Who can approve this request?
233: List approvers = Arrays.asList(module
234: .getUsers(ScarabSecurity.USER__APPROVE_ROLES));
235:
236: // Which potential approvers has any role in this module?
237: List approversWithRole = new ArrayList();
238: for (Iterator i = approvers.iterator(); i.hasNext();) {
239: ScarabUser u = (ScarabUser) i.next();
240: if (u.hasAnyRoleIn(module)) {
241: approversWithRole.add(u);
242: }
243: }
244:
245: // If some approvers have role in this module, sent email only to them.
246: if (!approversWithRole.isEmpty()) {
247: approvers = approversWithRole;
248: }
249:
250: Email.sendEmail(econtext, module, "scarab.email.default",
251: module.getSystemEmail(), approvers, null,
252: "RoleRequest.vm");
253: }
254: }
|