001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.lenya.cms.ac.usecases;
019:
020: import java.util.ArrayList;
021: import java.util.Arrays;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Set;
025: import java.util.TreeSet;
026:
027: import org.apache.cocoon.ProcessingException;
028: import org.apache.lenya.cms.publication.Document;
029: import org.apache.lenya.cms.publication.DocumentFactory;
030: import org.apache.lenya.cms.publication.Publication;
031: import org.apache.lenya.cms.publication.URLInformation;
032:
033: import org.apache.lenya.ac.AccessControlException;
034: import org.apache.lenya.ac.Accreditable;
035: import org.apache.lenya.ac.AccreditableManager;
036: import org.apache.lenya.ac.Group;
037: import org.apache.lenya.ac.IPRange;
038: import org.apache.lenya.ac.Item;
039: import org.apache.lenya.ac.Policy;
040: import org.apache.lenya.ac.Role;
041: import org.apache.lenya.ac.User;
042: import org.apache.lenya.ac.Credential;
043: import org.apache.lenya.ac.ModifiablePolicy;
044: import org.apache.lenya.ac.InheritingPolicyManager;
045: import org.apache.lenya.ac.World;
046:
047: /**
048: * Usecase to display the AccessControl tab in the site area for a document.
049: * This is a mix-in class that ideally would inherit both from
050: * AccessControlUsecase and DocumentUsecase. FIXME i just took the appropriate
051: * code from DocumentUsecase, maybe its possible to have a saner inheritance?
052: *
053: * @version $Id: AccessControl.java 408702 2006-05-22 16:03:49Z andreas $
054: */
055:
056: public class AccessControl extends AccessControlUsecase {
057:
058: protected static final String AC_AREA = "acArea";
059: protected static final String ADD = "add";
060: protected static final String DELETE = "delete";
061: protected static final String UP = "up";
062: protected static final String DOWN = "down";
063: protected static final String USER = "user";
064: protected static final String GROUP = "group";
065: protected static final String IPRANGE = "ipRange";
066: protected static final String WORLD = "world";
067: protected static final String ROLE = "role";
068: protected static final String SUB_USER = "subuser";
069: protected static final String SUB_GROUP = "subgroup";
070: protected static final String SUB_IPRANGE = "subipRange";
071:
072: private static String[] types = { USER, GROUP, IPRANGE, SUB_USER,
073: SUB_GROUP, SUB_IPRANGE, WORLD };
074: private static String[] operations = { ADD, DELETE, DOWN, UP };
075:
076: protected static final String SSL = "ssl";
077: protected static final String ANCESTOR_SSL = "ancestorSsl";
078: protected static final String DOCUMENT = "document";
079: protected static final String SUB_CREDENTIALS = "subCredentials";
080: protected static final String PARENT_CREDENTIALS = "parentCredentials";
081: private static final String METHOD = "method";
082: private String COMPLETE_AREA = "private.completeArea";
083:
084: /**
085: * @see org.apache.lenya.cms.usecase.AbstractUsecase#initParameters()
086: */
087: protected void initParameters() {
088: super .initParameters();
089:
090: try {
091: URLInformation info = new URLInformation(getSourceURL());
092: setParameter(COMPLETE_AREA, info.getCompleteArea());
093:
094: DocumentFactory map = getDocumentFactory();
095: if (map.isDocument(getSourceURL())) {
096: Document sourceDocument = map
097: .getFromURL(getSourceURL());
098: setParameter(DOCUMENT, sourceDocument);
099: }
100:
101: setParameter(SSL, Boolean.toString(isSSLProtected()));
102: setParameter(ANCESTOR_SSL, Boolean
103: .toString(isAncestorSSLProtected()));
104:
105: User[] users = getUserManager().getUsers();
106: String[] userIds = new String[users.length];
107: for (int i = 0; i < users.length; i++) {
108: userIds[i] = users[i].getId();
109: }
110: Arrays.sort(userIds);
111: setParameter("users", userIds);
112:
113: Group[] groups = getGroupManager().getGroups();
114: String[] groupIds = new String[groups.length];
115: for (int i = 0; i < groups.length; i++) {
116: groupIds[i] = groups[i].getId();
117: }
118: Arrays.sort(groupIds);
119: setParameter("groups", groupIds);
120:
121: IPRange[] ipRanges = getIpRangeManager().getIPRanges();
122: String[] ipRangeIds = new String[ipRanges.length];
123: for (int i = 0; i < ipRanges.length; i++) {
124: ipRangeIds[i] = ipRanges[i].getId();
125: }
126: Arrays.sort(ipRangeIds);
127: setParameter("ipRanges", ipRangeIds);
128:
129: Role[] roles = getRoleManager().getRoles();
130: String visitorRole = "";
131: Set roleIds = new TreeSet();
132: for (int i = 0; i < roles.length; i++) {
133: if (roles[i].isAssignable()) {
134: roleIds.add(roles[i].getId());
135: if (roles[i].getId().equals("visit")) {
136: visitorRole = roles[i].getId();
137: }
138: }
139: }
140: setParameter("roles", roleIds.toArray(new String[roleIds
141: .size()]));
142: setParameter("visitorRole", visitorRole);
143:
144: setParameter(SUB_CREDENTIALS, getSubtreeCredentials());
145: setParameter(PARENT_CREDENTIALS, getParentCredentials());
146:
147: } catch (final Exception e) {
148: addErrorMessage("Could not read a value.");
149: getLogger().error(
150: "Could not read value for AccessControl usecase. ",
151: e);
152: }
153:
154: }
155:
156: /**
157: * @see org.apache.lenya.cms.usecase.AbstractUsecase#doCheckPreconditions()
158: */
159: protected void doCheckPreconditions() throws Exception {
160: super .doCheckPreconditions();
161: URLInformation info = new URLInformation(getSourceURL());
162: String acArea = getParameterAsString(AC_AREA);
163: if (!acArea.equals(Publication.LIVE_AREA)
164: && !info.getArea().equals(acArea)) {
165: addErrorMessage("This usecase can only be invoked in the configured area.");
166: }
167: }
168:
169: protected void doCheckExecutionConditions() throws Exception {
170: super .doCheckExecutionConditions();
171: for (int i = 0; i < types.length; i++) {
172: for (int j = 0; j < operations.length; j++) {
173: String type = types[i];
174: String paramName = operations[j] + "Credential_" + type;
175: if (getParameterAsString(paramName) != null) {
176: String roleId = getParameterAsString(ROLE);
177: String id = getParameterAsString(type);
178: Accreditable item = getAccreditable(type, id);
179: if (item == null) {
180: addErrorMessage("no_such_accreditable",
181: new String[] { type, id });
182: } else {
183: Role role = getRoleManager().getRole(roleId);
184: if (role == null) {
185: addErrorMessage("role_no_such_role",
186: new String[] { roleId });
187: }
188: if (!role.isAssignable()) {
189: addErrorMessage("cannot-assign-role",
190: new String[] { roleId });
191: }
192: if (operations[j].equals(ADD)) {
193: ModifiablePolicy policy = getPolicy();
194: if (containsCredential(policy, item, role)) {
195: addErrorMessage(
196: "credential-already-contained",
197: new String[] {
198: ((Item) item).getId(),
199: role.getId() });
200: }
201: }
202: }
203: if (hasErrors()) {
204: deleteParameter(paramName);
205: }
206: }
207: }
208: }
209: }
210:
211: /**
212: * @see org.apache.lenya.cms.usecase.AbstractUsecase#doExecute()
213: */
214: public void doExecute() throws Exception {
215: super .doExecute();
216: if (getParameterAsString("change_ssl") != null) {
217: String ssl = getBooleanCheckboxParameter("ssl");
218: setSSLProtected(Boolean.valueOf(ssl).booleanValue());
219: }
220:
221: for (int i = 0; i < types.length; i++) {
222: for (int j = 0; j < operations.length; j++) {
223: String type = types[i];
224: String paramName = operations[j] + "Credential_" + type;
225: if (getParameterAsString(paramName) != null) {
226: String roleId = getParameterAsString(ROLE);
227: String method = getParameterAsString(METHOD);
228: String id = getParameterAsString(type);
229: Accreditable item = getAccreditable(type, id);
230: Role role = getRoleManager().getRole(roleId);
231: manipulateCredential(item, role, operations[j],
232: method);
233: setParameter(SUB_CREDENTIALS,
234: getSubtreeCredentials());
235: deleteParameter(paramName);
236: }
237: }
238: }
239: }
240:
241: protected Accreditable getAccreditable(String type, String id) {
242: Accreditable item = null;
243: if (type.equals(USER)) {
244: item = getUserManager().getUser(id);
245: } else if (type.equals(GROUP)) {
246: item = getGroupManager().getGroup(id);
247: } else if (type.equals(IPRANGE)) {
248: item = getIpRangeManager().getIPRange(id);
249: } else if (type.equals(WORLD)) {
250: item = World.getInstance();
251: }
252: return item;
253: }
254:
255: /**
256: * Returns if one of the ancestors of this URL is SSL protected.
257: *
258: * @return A boolean value.
259: * @throws ProcessingException when something went wrong.
260: */
261: protected boolean isAncestorSSLProtected()
262: throws ProcessingException {
263: boolean ssl;
264: try {
265: String ancestorUrl = "";
266: int lastSlashIndex = getPolicyURL().lastIndexOf("/");
267: if (lastSlashIndex != -1) {
268: ancestorUrl = getPolicyURL().substring(0,
269: lastSlashIndex);
270: }
271:
272: Policy policy = getPolicyManager().getPolicy(
273: getAccreditableManager(), ancestorUrl);
274: ssl = policy.isSSLProtected();
275: } catch (AccessControlException e) {
276: throw new ProcessingException("Resolving policy failed: ",
277: e);
278: }
279: return ssl;
280: }
281:
282: /**
283: * Returns if one of the ancestors of this URL is SSL protected.
284: *
285: * @return A boolean value.
286: * @throws ProcessingException when something went wrong.
287: */
288: protected boolean isSSLProtected() throws ProcessingException {
289: boolean ssl;
290: try {
291: Policy policy = getPolicyManager().getPolicy(
292: getAccreditableManager(), getPolicyURL());
293: ssl = policy.isSSLProtected();
294: } catch (AccessControlException e) {
295: throw new ProcessingException("Resolving policy failed: ",
296: e);
297: }
298: return ssl;
299: }
300:
301: /**
302: * Sets if this URL is SSL protected.
303: *
304: * @param ssl A boolean value.
305: * @throws ProcessingException when something went wrong.
306: */
307: protected void setSSLProtected(boolean ssl)
308: throws ProcessingException {
309: try {
310: ModifiablePolicy policy = getPolicy();
311: policy.setSSL(ssl);
312: getPolicyManager()
313: .saveSubtreePolicy(getPolicyURL(), policy);
314: } catch (AccessControlException e) {
315: throw new ProcessingException("Resolving policy failed: ",
316: e);
317: }
318: }
319:
320: protected InheritingPolicyManager getPolicyManager() {
321: return (InheritingPolicyManager) getAccessController()
322: .getPolicyManager();
323: }
324:
325: protected AccreditableManager getAccreditableManager() {
326: return getAccessController().getAccreditableManager();
327: }
328:
329: /**
330: * Changes a credential by adding or deleting an item for a role.
331: *
332: * @param accreditable The accreditable to add or delete.
333: * @param role The role.
334: * @param operation The operation, either {@link #ADD}or {@link #DELETE}.
335: * @param method
336: * @throws ProcessingException when something went wrong.
337: */
338: protected void manipulateCredential(Accreditable accreditable,
339: Role role, String operation, String method)
340: throws ProcessingException {
341: try {
342: ModifiablePolicy policy = getPolicy();
343:
344: if (operation.equals(ADD)) {
345: policy.addRole(accreditable, role, method);
346: } else if (operation.equals(DELETE)) {
347: policy.removeRole(accreditable, role);
348: } else if (operation.equals(UP)) {
349: policy.moveRoleUp(accreditable, role);
350: } else if (operation.equals(DOWN)) {
351: policy.moveRoleDown(accreditable, role);
352: }
353: getPolicyManager()
354: .saveSubtreePolicy(getPolicyURL(), policy);
355:
356: } catch (Exception e) {
357: throw new ProcessingException(
358: "Manipulating credential failed: ", e);
359: }
360: }
361:
362: protected ModifiablePolicy getPolicy()
363: throws AccessControlException {
364: return (ModifiablePolicy) getPolicyManager()
365: .buildSubtreePolicy(getAccreditableManager(),
366: getPolicyURL());
367: }
368:
369: protected boolean containsCredential(ModifiablePolicy policy,
370: Accreditable accreditable, Role role)
371: throws AccessControlException {
372: Credential[] credentials = policy.getCredentials();
373: boolean contains = false;
374: int i = 0;
375: while (!contains && i < credentials.length) {
376: Accreditable credAccr = credentials[i].getAccreditable();
377: Role credRole = credentials[i].getRole();
378: contains = credAccr.equals(accreditable)
379: && credRole.equals(role);
380: i++;
381: }
382: return contains;
383: }
384:
385: /**
386: * Returns the credential wrappers for the request of this object model.
387: *
388: * @return An array of CredentialWrappers.
389: * @throws ProcessingException when something went wrong.
390: */
391: public CredentialWrapper[] getSubtreeCredentials()
392: throws ProcessingException {
393: return getCredentials(true);
394: }
395:
396: /**
397: * Returns the credential wrappers for the parent URI of the URL belonging
398: * to the request of this object model.
399: *
400: * @return An array of CredentialWrappers.
401: * @throws ProcessingException when something went wrong.
402: */
403: public CredentialWrapper[] getParentCredentials()
404: throws ProcessingException {
405: return getCredentials(false);
406: }
407:
408: /**
409: * Returns the credentials of the policy of the selected URL.
410: *
411: * @return An array of CredentialWrappers.
412: * @throws ProcessingException when something went wrong.
413: */
414: public CredentialWrapper[] getCredentials(boolean inherit)
415: throws ProcessingException {
416:
417: List credentials = new ArrayList();
418:
419: ModifiablePolicy policies[] = getPolicies(inherit);
420: List policyCredentials = new ArrayList();
421: for (int i = 0; i < policies.length; i++) {
422: Credential[] creds;
423: try {
424: creds = policies[i].getCredentials();
425: for (int j = 0; j < creds.length; j++) {
426: policyCredentials.add(creds[j]);
427: }
428: } catch (AccessControlException e) {
429: throw new ProcessingException(
430: "AccessControlException - receiving credential failed: ",
431: e);
432: }
433: }
434: for (Iterator i = policyCredentials.iterator(); i.hasNext();) {
435: Credential credential = (Credential) i.next();
436: Accreditable accreditable = credential.getAccreditable();
437: Role role = credential.getRole();
438: String method = credential.getMethod();
439: credentials.add(new CredentialWrapper(accreditable, role,
440: method));
441: }
442: return (CredentialWrapper[]) credentials
443: .toArray(new CredentialWrapper[credentials.size()]);
444: }
445:
446: /**
447: * Returns the policies for a certain URL.
448: *
449: * @param inherit If true, all ancestor policies are returned. Otherwise,
450: * only the URL policies are returned.
451: * @return An array of DefaultPolicy objects.
452: * @throws ProcessingException when something went wrong.
453: */
454: protected ModifiablePolicy[] getPolicies(boolean inherit)
455: throws ProcessingException {
456:
457: ModifiablePolicy[] policies;
458:
459: try {
460: if (inherit) {
461: policies = new ModifiablePolicy[1];
462: AccreditableManager policyManager = getAccreditableManager();
463: policies[0] = (ModifiablePolicy) getPolicyManager()
464: .buildSubtreePolicy(policyManager,
465: getPolicyURL());
466: } else {
467: String ancestorUrl = "";
468:
469: String currentUrl = getPolicyURL();
470: if (currentUrl.endsWith("/")) {
471: currentUrl = currentUrl.substring(0, currentUrl
472: .length() - 1);
473: }
474:
475: int lastSlashIndex = currentUrl.lastIndexOf("/");
476: if (lastSlashIndex != -1) {
477: ancestorUrl = currentUrl.substring(0,
478: lastSlashIndex);
479: }
480: Policy[] pArray = getPolicyManager().getPolicies(
481: getAccreditableManager(), ancestorUrl);
482: policies = new ModifiablePolicy[pArray.length];
483: for (int i = 0; i < pArray.length; i++) {
484: policies[policies.length - 1 - i] = (ModifiablePolicy) pArray[i];
485: }
486: }
487: } catch (AccessControlException e) {
488: throw new ProcessingException(e);
489: }
490:
491: return policies;
492: }
493:
494: protected String getPolicyURL() {
495: String infoUrl = getSourceURL();
496: URLInformation info = new URLInformation(infoUrl);
497:
498: String area = getParameterAsString(AC_AREA);
499: String url = "/" + info.getPublicationId() + "/" + area
500: + info.getDocumentUrl();
501: return url;
502: }
503:
504: }
|