001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/authz/tags/sakai_2-4-1/authz-tool/tool/src/java/org/sakaiproject/authz/tool/PermissionsAction.java $
003: * $Id: PermissionsAction.java 10974 2006-06-21 18:48:03Z ggolden@umich.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.authz.tool;
021:
022: import java.util.Collection;
023: import java.util.Collections;
024: import java.util.Hashtable;
025: import java.util.Iterator;
026: import java.util.List;
027: import java.util.Map;
028: import java.util.Set;
029: import java.util.Vector;
030:
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.sakaiproject.authz.api.AuthzGroup;
034: import org.sakaiproject.authz.api.AuthzPermissionException;
035: import org.sakaiproject.authz.api.GroupAlreadyDefinedException;
036: import org.sakaiproject.authz.api.GroupIdInvalidException;
037: import org.sakaiproject.authz.api.GroupNotDefinedException;
038: import org.sakaiproject.authz.api.Role;
039: import org.sakaiproject.authz.api.RoleAlreadyDefinedException;
040: import org.sakaiproject.authz.cover.AuthzGroupService;
041: import org.sakaiproject.authz.cover.FunctionManager;
042: import org.sakaiproject.cheftool.Context;
043: import org.sakaiproject.cheftool.JetspeedRunData;
044: import org.sakaiproject.cheftool.RunData;
045: import org.sakaiproject.cheftool.VelocityPortlet;
046: import org.sakaiproject.cheftool.VelocityPortletPaneledAction;
047: import org.sakaiproject.entity.api.Reference;
048: import org.sakaiproject.entity.cover.EntityManager;
049: import org.sakaiproject.event.api.SessionState;
050: import org.sakaiproject.util.ResourceLoader;
051:
052: /**
053: * <p>
054: * PermissionsAction is a helper Action that other tools can use to edit their permissions.
055: * </p>
056: */
057: public class PermissionsAction {
058: /** Our logger. */
059: private static Log M_log = LogFactory
060: .getLog(PermissionsAction.class);
061:
062: /** Resource bundle using current language locale */
063: private static ResourceLoader rb = new ResourceLoader("authz-tool");
064:
065: /** State attributes for Permissions mode - when it is MODE_DONE the tool can process the results. */
066: public static final String STATE_MODE = "pemissions.mode";
067:
068: /** State attribute for the realm id - users should set before starting. */
069: public static final String STATE_REALM_ID = "permission.realmId";
070:
071: /** State attribute for the realm id - users should set before starting. */
072: public static final String STATE_REALM_ROLES_ID = "permission.realmRolesId";
073:
074: /** State attribute for the description of what's being edited - users should set before starting. */
075: public static final String STATE_DESCRIPTION = "permission.description";
076:
077: /** State attribute for the lock/ability string prefix to be presented / edited - users should set before starting. */
078: public static final String STATE_PREFIX = "permission.prefix";
079:
080: /** State attributes for storing the realm being edited. */
081: private static final String STATE_REALM_EDIT = "permission.realm";
082:
083: /** State attributes for storing the abilities, filtered by the prefix. */
084: private static final String STATE_ABILITIES = "permission.abilities";
085:
086: /** State attribute for storing the roles to display. */
087: private static final String STATE_ROLES = "permission.roles";
088:
089: /** State attribute for storing the abilities of each role for this resource. */
090: private static final String STATE_ROLE_ABILITIES = "permission.rolesAbilities";
091:
092: /** Modes. */
093: public static final String MODE_MAIN = "main";
094:
095: /** vm files for each mode. TODO: path too hard coded */
096: private static final String TEMPLATE_MAIN = "helper/chef_permissions";
097:
098: /**
099: * build the context.
100: *
101: * @return The name of the template to use.
102: */
103: static public String buildHelperContext(VelocityPortlet portlet,
104: Context context, RunData rundata, SessionState state) {
105: // in state is the realm id
106: context.put("thelp", rb);
107: String realmId = (String) state.getAttribute(STATE_REALM_ID);
108:
109: // in state is the realm to use for roles - if not, use realmId
110: String realmRolesId = (String) state
111: .getAttribute(STATE_REALM_ROLES_ID);
112:
113: // get the realm locked for editing
114: AuthzGroup edit = (AuthzGroup) state
115: .getAttribute(STATE_REALM_EDIT);
116: if (edit == null) {
117: if (AuthzGroupService.allowUpdate(realmId)) {
118: try {
119: edit = AuthzGroupService.getAuthzGroup(realmId);
120: state.setAttribute(STATE_REALM_EDIT, edit);
121: } catch (GroupNotDefinedException e) {
122: try {
123: // we can create the realm
124: edit = AuthzGroupService.addAuthzGroup(realmId);
125: state.setAttribute(STATE_REALM_EDIT, edit);
126: } catch (GroupIdInvalidException ee) {
127: M_log
128: .warn("PermissionsAction.buildHelperContext: addRealm: "
129: + ee);
130: cleanupState(state);
131: return null;
132: } catch (GroupAlreadyDefinedException ee) {
133: M_log
134: .warn("PermissionsAction.buildHelperContext: addRealm: "
135: + ee);
136: cleanupState(state);
137: return null;
138: } catch (AuthzPermissionException ee) {
139: M_log
140: .warn("PermissionsAction.buildHelperContext: addRealm: "
141: + ee);
142: cleanupState(state);
143: return null;
144: }
145: }
146: }
147:
148: // no permission
149: else {
150: M_log
151: .warn("PermissionsAction.buildHelperContext: no permission: "
152: + realmId);
153: cleanupState(state);
154: return null;
155: }
156: }
157:
158: // in state is the prefix for abilities to present
159: String prefix = (String) state.getAttribute(STATE_PREFIX);
160:
161: // in state is the list of abilities we will present
162: List functions = (List) state.getAttribute(STATE_ABILITIES);
163: if (functions == null) {
164: // get all functions prefixed with our prefix
165: functions = FunctionManager.getRegisteredFunctions(prefix);
166:
167: state.setAttribute(STATE_ABILITIES, functions);
168: }
169:
170: // in state is the description of the edit
171: String description = (String) state
172: .getAttribute(STATE_DESCRIPTION);
173:
174: // the list of roles
175: List roles = (List) state.getAttribute(STATE_ROLES);
176: if (roles == null) {
177: // get the roles from the edit, unless another is specified
178: AuthzGroup roleRealm = edit;
179: if (realmRolesId != null) {
180: try {
181: roleRealm = AuthzGroupService
182: .getAuthzGroup(realmRolesId);
183: } catch (Exception e) {
184: M_log
185: .warn("PermissionsAction.buildHelperContext: getRolesRealm: "
186: + realmRolesId + " : " + e);
187: }
188: }
189: roles = new Vector();
190: roles.addAll(roleRealm.getRoles());
191: Collections.sort(roles);
192: state.setAttribute(STATE_ROLES, roles);
193: }
194:
195: // the abilities not including this realm for each role
196: Map rolesAbilities = (Map) state
197: .getAttribute(STATE_ROLE_ABILITIES);
198: if (rolesAbilities == null) {
199: rolesAbilities = new Hashtable();
200: state.setAttribute(STATE_ROLE_ABILITIES, rolesAbilities);
201:
202: // get this resource's role Realms,those that refine the role definitions, but not it's own
203: Reference ref = EntityManager.newReference(edit.getId());
204: Collection realms = ref.getAuthzGroups();
205: realms.remove(ref.getReference());
206:
207: for (Iterator iRoles = roles.iterator(); iRoles.hasNext();) {
208: Role role = (Role) iRoles.next();
209: Set locks = AuthzGroupService.getAllowedFunctions(role
210: .getId(), realms);
211: rolesAbilities.put(role.getId(), locks);
212: }
213: }
214:
215: context.put("realm", edit);
216: context.put("prefix", prefix);
217: context.put("abilities", functions);
218: context.put("description", description);
219: if (roles.size() > 0) {
220: context.put("roles", roles);
221: }
222: context.put("rolesAbilities", rolesAbilities);
223:
224: // set me as the helper class
225: state.setAttribute(VelocityPortletPaneledAction.STATE_HELPER,
226: PermissionsAction.class.getName());
227:
228: // make sure observers are disabled
229: VelocityPortletPaneledAction.disableObservers(state);
230:
231: return TEMPLATE_MAIN;
232: }
233:
234: /**
235: * Remove the state variables used internally, on the way out.
236: */
237: private static void cleanupState(SessionState state) {
238: state.removeAttribute(STATE_REALM_ID);
239: state.removeAttribute(STATE_REALM_EDIT);
240: state.removeAttribute(STATE_PREFIX);
241: state.removeAttribute(STATE_ABILITIES);
242: state.removeAttribute(STATE_DESCRIPTION);
243: state.removeAttribute(STATE_ROLES);
244: state.removeAttribute(STATE_ROLE_ABILITIES);
245: state.removeAttribute(STATE_MODE);
246: state
247: .removeAttribute(VelocityPortletPaneledAction.STATE_HELPER);
248:
249: // re-enable observers
250: VelocityPortletPaneledAction.enableObservers(state);
251: }
252:
253: /**
254: * Handle the eventSubmit_doSave command to save the edited permissions.
255: */
256: static public void doSave(RunData data) {
257: SessionState state = ((JetspeedRunData) data)
258: .getPortletSessionState(((JetspeedRunData) data)
259: .getJs_peid());
260:
261: AuthzGroup edit = (AuthzGroup) state
262: .getAttribute(STATE_REALM_EDIT);
263:
264: // read the form, updating the edit
265: readForm(data, edit, state);
266:
267: // commit the change
268: try {
269: AuthzGroupService.save(edit);
270: } catch (GroupNotDefinedException e) {
271: // TODO: GroupNotDefinedException
272: } catch (AuthzPermissionException e) {
273: // TODO: AuthzPermissionException
274: }
275:
276: // clean up state
277: cleanupState(state);
278: }
279:
280: /**
281: * Handle the eventSubmit_doCancel command to abort the edits.
282: */
283: static public void doCancel(RunData data) {
284: SessionState state = ((JetspeedRunData) data)
285: .getPortletSessionState(((JetspeedRunData) data)
286: .getJs_peid());
287:
288: // clean up state
289: cleanupState(state);
290: }
291:
292: /**
293: * Read the permissions form.
294: */
295: static private void readForm(RunData data, AuthzGroup edit,
296: SessionState state) {
297: List abilities = (List) state.getAttribute(STATE_ABILITIES);
298: List roles = (List) state.getAttribute(STATE_ROLES);
299:
300: // look for each role's ability field
301: for (Iterator iRoles = roles.iterator(); iRoles.hasNext();) {
302: Role role = (Role) iRoles.next();
303:
304: for (Iterator iLocks = abilities.iterator(); iLocks
305: .hasNext();) {
306: String lock = (String) iLocks.next();
307:
308: String checked = data.getParameters().getString(
309: role.getId() + lock);
310: if (checked != null) {
311: // we have an ability! Make sure there's a role
312: Role myRole = edit.getRole(role.getId());
313: if (myRole == null) {
314: try {
315: myRole = edit.addRole(role.getId());
316: } catch (RoleAlreadyDefinedException e) {
317: M_log
318: .warn("PermissionsAction.readForm: addRole after getRole null: "
319: + role.getId() + " : " + e);
320: }
321: }
322: myRole.allowFunction(lock);
323: } else {
324: // if we do have this role, make sure there's not this lock
325: Role myRole = edit.getRole(role.getId());
326: if (myRole != null) {
327: myRole.disallowFunction(lock);
328: }
329: }
330: }
331: }
332: }
333: }
|