001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.ejb.beans;
034:
035: import com.flexive.core.Database;
036: import com.flexive.core.LifeCycleInfoImpl;
037: import static com.flexive.core.DatabaseConst.*;
038: import com.flexive.core.security.UserTicketStore;
039: import com.flexive.core.structure.StructureLoader;
040: import com.flexive.shared.*;
041: import com.flexive.shared.content.FxPermissionUtils;
042: import com.flexive.shared.exceptions.*;
043: import com.flexive.shared.interfaces.*;
044: import com.flexive.shared.security.*;
045: import com.flexive.shared.structure.FxEnvironment;
046: import com.flexive.shared.value.FxString;
047: import org.apache.commons.lang.StringUtils;
048: import org.apache.commons.logging.Log;
049: import org.apache.commons.logging.LogFactory;
050:
051: import javax.annotation.Resource;
052: import javax.ejb.*;
053: import java.sql.*;
054: import java.util.ArrayList;
055: import java.util.Hashtable;
056: import java.util.List;
057:
058: /**
059: * Bean handling ACLs.
060: *
061: * @author Gregor Schober (gregor.schober@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
062: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
063: */
064: @Stateless(name="ACLEngine")
065: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
066: @TransactionManagement(TransactionManagementType.CONTAINER)
067: public class ACLEngineBean implements ACLEngine, ACLEngineLocal {
068:
069: private static transient Log LOG = LogFactory
070: .getLog(ACLEngineBean.class);
071: @Resource
072: javax.ejb.SessionContext ctx;
073: @EJB
074: AccountEngineLocal account;
075: @EJB
076: UserGroupEngineLocal group;
077: @EJB
078: MandatorEngineLocal mandator;
079: @EJB
080: SequencerEngineLocal seq;
081:
082: public ACLEngineBean() {
083: }
084:
085: /**
086: * Helper function.
087: *
088: * @param description the description to check
089: * @return the description
090: * @throws FxInvalidParameterException if the description id invalid
091: */
092: private String checkDescription(String description)
093: throws FxInvalidParameterException {
094: if (description == null)
095: description = "";
096: if (description.length() > 255)
097: throw new FxInvalidParameterException("DESCRIPTION",
098: "ex.acl.propertyDescriptionTooLong");
099: return description;
100: }
101:
102: /**
103: * Helper function.
104: *
105: * @param name the name to check
106: * @return the name
107: * @throws FxInvalidParameterException if the name id invalid
108: */
109: private String checkName(String name)
110: throws FxInvalidParameterException {
111: if (StringUtils.isEmpty(name))
112: throw new FxInvalidParameterException("NAME",
113: "ex.acl.propertyNameMissing");
114: if (name.length() > 250)
115: throw new FxInvalidParameterException("NAME",
116: "ex.acl.propertyNameTooLong");
117: return name;
118: }
119:
120: /**
121: * Helper function.
122: *
123: * @param label the label to check
124: * @return the label
125: * @throws FxInvalidParameterException if the label id invalid
126: */
127: private FxString checkLabel(FxString label)
128: throws FxInvalidParameterException {
129: if (label == null || label.isEmpty())
130: throw new FxInvalidParameterException("LABEL",
131: "ex.acl.propertyLabelMissing");
132: return label;
133: }
134:
135: /**
136: * {@inheritDoc}
137: */
138: @TransactionAttribute(TransactionAttributeType.REQUIRED)
139: public long create(String name, FxString label, long mandatorId,
140: String color, String description, ACL.Category category)
141: throws FxApplicationException {
142:
143: final UserTicket ticket = FxContext.get().getTicket();
144: final FxEnvironment environment = CacheAdmin.getEnvironment();
145: // Security
146: if (!ticket.isInRole(Role.MandatorSupervisor))
147: FxPermissionUtils.checkRole(ticket, Role.ACLManagement);
148: if (!ticket.isGlobalSupervisor()) {
149: if (ticket.getMandatorId() != mandatorId) {
150: String mandatorName = environment.getMandator(
151: mandatorId).getName();
152: FxNoAccessException na = new FxNoAccessException(
153: "ex.acl.mayNotCreateForForeignMandator",
154: mandatorName);
155: if (LOG.isInfoEnabled())
156: LOG.info(na, na);
157: throw na;
158: }
159: }
160:
161: // Parameter checks
162: color = FxFormatUtils.processColorString("COLOR", color);
163: description = checkDescription(description);
164: name = checkName(name);
165: label = checkLabel(label);
166: if (category == null)
167: throw new FxInvalidParameterException("CATEGORY",
168: "ex.acl.categoryMissing");
169:
170: Connection con = null;
171: PreparedStatement ps = null;
172: String sql;
173:
174: try {
175:
176: // Obtain a database connection
177: con = Database.getDbConnection();
178:
179: // Obtain a new id
180: int newId = (int) seq.getId(SequencerEngine.System.ACL);
181: sql = "INSERT INTO "
182: + TBL_ACLS
183: + "("
184: +
185: // 1 2 3 4 5 6 7 8 9
186: "ID,CAT_TYPE,COLOR,DESCRIPTION,MANDATOR,NAME,CREATED_BY,CREATED_AT,MODIFIED_BY,MODIFIED_AT)"
187: + "VALUES (?,?,?,?,?,?,?,?,?,?)";
188: final long NOW = System.currentTimeMillis();
189: ps = con.prepareStatement(sql);
190: ps.setInt(1, newId);
191: ps.setInt(2, category.getId());
192: ps.setString(3, color);
193: ps.setString(4, description);
194: ps.setLong(5, mandatorId);
195: ps.setString(6, name);
196: ps.setLong(7, ticket.getUserId());
197: ps.setLong(8, NOW);
198: ps.setLong(9, ticket.getUserId());
199: ps.setLong(10, NOW);
200: ps.executeUpdate();
201:
202: Database.storeFxString(label, con, TBL_ACLS, "LABEL", "ID",
203: newId);
204: try {
205: StructureLoader.updateACL(FxContext.get()
206: .getDivisionId(), this .load(newId));
207: } catch (FxLoadException e) {
208: LOG.error(e, e);
209: } catch (FxNotFoundException e) {
210: LOG.error(e, e);
211: }
212: return newId;
213: } catch (SQLException exc) {
214: final boolean uniqueConstraintViolation = Database
215: .isUniqueConstraintViolation(exc);
216: ctx.setRollbackOnly();
217: if (uniqueConstraintViolation) {
218: throw new FxEntryExistsException(LOG,
219: "ex.acl.aclAlreadyExists", name);
220: } else {
221: throw new FxCreateException(LOG, exc,
222: "ex.acl.createFailed", exc.getMessage());
223: }
224: } finally {
225: Database.closeObjects(ACLEngineBean.class, con, ps);
226: }
227: }
228:
229: /**
230: * {@inheritDoc}
231: */
232: @TransactionAttribute(TransactionAttributeType.REQUIRED)
233: public void remove(long id) throws FxApplicationException {
234: UserTicket ticket = FxContext.get().getTicket();
235: ACL theACL = load(id);
236:
237: // Protected interal ACLs
238: if (theACL.getId() <= ACL.MAX_INTERNAL_ID)
239: throw new FxNoAccessException(LOG,
240: "ex.acl.deleteFailed.internalACL", theACL.getName());
241:
242: // Security
243: if (!ticket.isGlobalSupervisor()) {
244: // Security
245: if (!ticket.isInRole(Role.MandatorSupervisor)
246: && !ticket.isInRole(Role.ACLManagement))
247: throw new FxNoAccessException(LOG,
248: "ex.acl.deleteFailed.noPermission", theACL
249: .getName());
250: if (ticket.getMandatorId() != theACL.getMandatorId())
251: throw new FxNoAccessException(LOG,
252: "ex.acl.deleteFailed.foreignMandator", theACL
253: .getName());
254: }
255:
256: Connection con = null;
257: PreparedStatement stmt = null;
258: String curSql;
259:
260: try {
261: // Obtain a database connection
262: con = Database.getDbConnection();
263:
264: // Delete all ACLAssignments
265: curSql = "DELETE FROM " + TBL_ASSIGN_ACLS + " WHERE ACL="
266: + id;
267: stmt = con.prepareStatement(curSql);
268: stmt.executeUpdate();
269: stmt.close();
270:
271: // Delete the label
272: curSql = "DELETE FROM " + TBL_ACLS + ML + " WHERE ID=" + id;
273: stmt = con.prepareStatement(curSql);
274: stmt.executeUpdate();
275: stmt.close();
276:
277: // Delete the ACL itself
278: curSql = "DELETE FROM " + TBL_ACLS + " WHERE ID=" + id;
279: stmt = con.prepareStatement(curSql);
280: stmt.executeUpdate();
281:
282: // Refresh all UserTicket that are affected
283: UserTicketStore.flagDirtyHavingACL(id);
284: StructureLoader.removeACL(FxContext.get().getDivisionId(),
285: id);
286: } catch (SQLException exc) {
287: final boolean uniqueConstraintViolation = Database
288: .isUniqueConstraintViolation(exc);
289: final boolean keyViolation = Database
290: .isForeignKeyViolation(exc);
291: ctx.setRollbackOnly();
292: if (uniqueConstraintViolation)
293: throw new FxRemoveException(LOG,
294: "ex.acl.aclAlreadyExists", theACL.getName());
295: else if (keyViolation)
296: throw new FxRemoveException(LOG,
297: "ex.acl.deleteFailed.aclIsInUse", theACL
298: .getName());
299: else
300: throw new FxRemoveException(LOG, "ex.acl.deleteFailed",
301: theACL.getName(), exc.getMessage());
302: } finally {
303: Database.closeObjects(ACLEngineBean.class, con, stmt);
304: }
305: }
306:
307: /**
308: * {@inheritDoc}
309: */
310: @TransactionAttribute(TransactionAttributeType.REQUIRED)
311: public void update(long id, String name, FxString label,
312: String color, String description,
313: List<ACLAssignment> assignments)
314: throws FxApplicationException {
315: UserTicket ticket = FxContext.get().getTicket();
316: // Load the current version of the ACL
317: ACL theACL = load(id);
318:
319: // Check the assignments array: Every group may only be contained once
320: if (assignments == null) {
321: assignments = new ArrayList<ACLAssignment>(0);
322: } else if (assignments.size() > 0) {
323: Hashtable<Long, Boolean> uniqueCheck = new Hashtable<Long, Boolean>(
324: assignments.size());
325: for (ACLAssignment ass : assignments) {
326: // Group defined more than once in the list?
327: if (uniqueCheck.put(ass.getGroupId(), Boolean.TRUE) != null) {
328: String groupName = "unknown";
329: try {
330: groupName = group.load(ass.getGroupId())
331: .getName();
332: } catch (Throwable t) {
333: //ignore
334: }
335: throw new FxUpdateException(
336: "ex.aclAssignment.update.groupDefinedMoreThanOnce",
337: theACL.getName(), groupName);
338: }
339: }
340: }
341:
342: // Security
343: if (!ticket.isGlobalSupervisor()) {
344: // Security
345: if (!ticket.isInRole(Role.MandatorSupervisor)
346: && !ticket.isInRole(Role.ACLManagement))
347: throw new FxNoAccessException(LOG,
348: "ex.acl.updateFailed.noPermission", theACL
349: .getName());
350: if (ticket.getMandatorId() != theACL.getMandatorId())
351: throw new FxNoAccessException(LOG,
352: "ex.acl.updateFailed.foreignMandator", theACL
353: .getName());
354: }
355:
356: // Parameter checks
357: if (color != null)
358: color = FxFormatUtils.processColorString("COLOR", color);
359: if (name != null)
360: name = checkName(name);
361: if (label != null)
362: label = checkLabel(label);
363: if (description != null)
364: description = checkDescription(description);
365:
366: // Set values
367: if (color != null)
368: theACL.setColor(color);
369: if (name != null)
370: theACL.setName(name);
371: if (label != null)
372: theACL.setLabel(label);
373: if (description != null)
374: theACL.setDescription(description);
375:
376: Connection con = null;
377: PreparedStatement stmt = null;
378: String curSql;
379:
380: try {
381: // Obtain a database connection
382: con = Database.getDbConnection();
383:
384: curSql = "UPDATE " + TBL_ACLS + " SET "
385: +
386: // 1 2 3 4 5 6
387: "cat_type=?,color=?,description=?,name=?,modified_by=?,modified_at=? WHERE id="
388: + id;
389: final long NOW = System.currentTimeMillis();
390: stmt = con.prepareStatement(curSql);
391: stmt.setInt(1, theACL.getCategory().getId());
392: stmt.setString(2, theACL.getColor());
393: stmt.setString(3, theACL.getDescription());
394: stmt.setString(4, theACL.getName());
395: stmt.setLong(5, ticket.getUserId());
396: stmt.setLong(6, NOW);
397: final int uCount = stmt.executeUpdate();
398: stmt.close();
399: if (uCount != 1) {
400: throw new SQLException(uCount
401: + " rows affected instead of 1");
402: }
403: Database.storeFxString(theACL.getLabel(), con, TBL_ACLS,
404: "LABEL", "ID", theACL.getId());
405: //remove assignments
406: curSql = "DELETE FROM " + TBL_ASSIGN_ACLS + " WHERE ACL=?";
407: stmt = con.prepareStatement(curSql);
408: stmt.setLong(1, theACL.getId());
409: stmt.executeUpdate();
410: if (assignments.size() > 0) {
411: stmt.close();
412: // 1 2 3 4 5 6 7 8
413: curSql = "INSERT INTO "
414: + TBL_ASSIGN_ACLS
415: + " (USERGROUP, ACL, PEDIT, PREMOVE, PEXPORT, PREL, PREAD, PCREATE, "
416: +
417: //9 10 11 12
418: "CREATED_BY, CREATED_AT, MODIFIED_BY, MODIFIED_AT) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";
419: stmt = con.prepareStatement(curSql);
420: stmt.setLong(2, theACL.getId());
421: stmt.setLong(9, ticket.getUserId());
422: stmt.setLong(10, NOW);
423: stmt.setLong(11, ticket.getUserId());
424: stmt.setLong(12, NOW);
425: for (ACLAssignment assignment : assignments) {
426: stmt.setLong(1, assignment.getGroupId());
427: stmt.setBoolean(3, assignment.getMayEdit());
428: stmt.setBoolean(4, assignment.getMayDelete());
429: stmt.setBoolean(5, assignment.getMayExport());
430: stmt.setBoolean(6, assignment.getMayRelate());
431: stmt.setBoolean(7, assignment.getMayRead());
432: stmt.setBoolean(8, assignment.getMayCreate());
433: if (assignment.getMayCreate()
434: || assignment.getMayDelete()
435: || assignment.getMayEdit()
436: || assignment.getMayExport()
437: || assignment.getMayRelate()
438: || assignment.getMayRead())
439: stmt.executeUpdate();
440: }
441: }
442: try {
443: StructureLoader.updateACL(FxContext.get()
444: .getDivisionId(), this .load(id));
445: } catch (FxLoadException e) {
446: LOG.error(e, e);
447: } catch (FxNotFoundException e) {
448: LOG.error(e, e);
449: }
450: } catch (SQLException exc) {
451: final boolean uniqueConstraintViolation = Database
452: .isUniqueConstraintViolation(exc);
453: ctx.setRollbackOnly();
454: if (uniqueConstraintViolation)
455: throw new FxEntryExistsException(LOG,
456: "ex.acl.updateFailed.nameTaken", theACL
457: .getName(), name);
458: else
459: throw new FxUpdateException(LOG, "ex.acl.updateFailed",
460: theACL.getName(), exc.getMessage());
461: } finally {
462: Database.closeObjects(ACLEngineBean.class, con, stmt);
463: }
464:
465: }
466:
467: /**
468: * {@inheritDoc}
469: */
470: public ACL load(long id) throws FxApplicationException {
471: return load(id, false);
472: }
473:
474: /**
475: * {@inheritDoc}
476: */
477: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
478: public ACL load(long id, boolean ignoreSecurity)
479: throws FxApplicationException {
480: Connection con = null;
481: Statement stmt = null;
482: String curSql;
483: try {
484: final FxEnvironment environment = CacheAdmin
485: .getEnvironment();
486:
487: // Obtain a database connection
488: con = Database.getDbConnection();
489: // 1 2 3 4 5 6 7 8 9
490: curSql = "SELECT MANDATOR,NAME,CAT_TYPE,DESCRIPTION,COLOR,CREATED_BY,CREATED_AT,MODIFIED_BY,MODIFIED_AT FROM "
491: + TBL_ACLS + " WHERE ID=" + id;
492: stmt = con.createStatement();
493: ResultSet rs = stmt.executeQuery(curSql);
494:
495: if (rs == null || !rs.next())
496: throw new FxNotFoundException("ex.acl.load.notFound",
497: id);
498:
499: // Read the ACL
500: long mandatorId = rs.getLong(1);
501: String name = rs.getString(2);
502: int cat = rs.getInt(3);
503: String desc = rs.getString(4);
504: String color = rs.getString(5);
505: FxString label = Database.loadFxString(con, TBL_ACLS,
506: "LABEL", "ID=" + id);
507: String sMandator = environment.getMandator(mandatorId)
508: .getName();
509: ACL theACL = new ACL(id, name, label, mandatorId,
510: sMandator, desc, color, ACL.Category.getById(cat),
511: LifeCycleInfoImpl.load(rs, 6, 7, 8, 9));
512: if (ignoreSecurity
513: && mandatorId != FxContext.get().getTicket()
514: .getMandatorId())
515: throw new FxNoAccessException(LOG,
516: "ex.acl.loadFailed.foreignMandator", theACL
517: .getName());
518: // Return the ACL
519: return theACL;
520: } catch (SQLException exc) {
521: throw new FxLoadException(LOG, "ex.acl.load.sqlError", id,
522: exc.getMessage());
523: } finally {
524: Database.closeObjects(ACLEngineBean.class, con, stmt);
525: }
526: }
527:
528: /**
529: * {@inheritDoc}
530: */
531: @TransactionAttribute(TransactionAttributeType.REQUIRED)
532: public void assign(long aclId, long groupId, boolean mayRead,
533: boolean mayEdit, boolean mayRelate, boolean mayDelete,
534: boolean mayExport, boolean mayCreate)
535: throws FxApplicationException {
536: UserTicket ticket = FxContext.get().getTicket();
537: // Delete rather than create?
538: if (!mayRead && !mayRelate && !mayExport && !mayEdit
539: && !mayDelete) {
540: try {
541: unassign(aclId, groupId);
542: return;
543: } catch (FxNotFoundException e) {
544: //can happen if an ACL only has create set! -> ignore it then
545: } catch (FxRemoveException exc) {
546: throw new FxCreateException(exc.getMessage(), exc);
547: }
548: }
549:
550: // Permission & exists check
551: checkPermissions(ticket, groupId, aclId, true);
552:
553: Connection con = null;
554: PreparedStatement stmt = null;
555: String curSql;
556: try {
557: // Obtain a database connection
558: con = Database.getDbConnection();
559:
560: // Delete any old assignments
561: curSql = "DELETE FROM " + TBL_ASSIGN_ACLS
562: + " WHERE USERGROUP=" + groupId + " AND ACL="
563: + aclId;
564: stmt = con.prepareStatement(curSql);
565: int ucount = stmt.executeUpdate();
566: stmt.close();
567: if (LOG.isDebugEnabled())
568: LOG.debug("Deleted assignments group[" + groupId
569: + "]-acl[" + aclId + "]:" + ucount);
570:
571: curSql = "INSERT INTO "
572: + TBL_ASSIGN_ACLS
573: +
574: //1 2 3 4 5 6 7 8 9 10 11 12
575: "(USERGROUP,ACL,PREAD,PEDIT,PREMOVE,PCREATE,PEXPORT,PREL,CREATED_AT,CREATED_BY,MODIFIED_AT,MODIFIED_BY)"
576: + " VALUES " + "(?,?,?,?,?,?,?,?,?,?,?,?)";
577:
578: final long NOW = System.currentTimeMillis();
579: stmt = con.prepareStatement(curSql);
580: stmt.setLong(1, groupId);
581: stmt.setLong(2, aclId);
582: stmt.setBoolean(3, mayRead);
583: stmt.setBoolean(4, mayEdit);
584: stmt.setBoolean(5, mayDelete);
585: stmt.setBoolean(6, mayCreate);
586: stmt.setBoolean(7, mayExport);
587: stmt.setBoolean(8, mayRelate);
588: stmt.setLong(9, NOW);
589: stmt.setLong(10, ticket.getUserId());
590: stmt.setLong(11, NOW);
591: stmt.setLong(12, ticket.getUserId());
592:
593: stmt.executeUpdate();
594:
595: // Update active UserTickets
596: UserTicketStore.flagDirtyHavingGroupId(groupId);
597: } catch (Exception exc) {
598: ctx.setRollbackOnly();
599: FxCreateException dbe = new FxCreateException(exc,
600: "ex.aclAssignment.createFailed");
601: LOG.error(dbe, exc);
602: throw dbe;
603: } finally {
604: Database.closeObjects(ACLEngineBean.class, con, stmt);
605: }
606:
607: }
608:
609: /**
610: * {@inheritDoc}
611: */
612: @TransactionAttribute(TransactionAttributeType.REQUIRED)
613: public void assign(long aclId, long groupId,
614: ACL.Permission... permissions)
615: throws FxApplicationException {
616: boolean mayRead = false;
617: boolean mayEdit = false;
618: boolean mayRelate = false;
619: boolean mayDelete = false;
620: boolean mayExport = false;
621: boolean mayCreate = false;
622: for (ACL.Permission perm : permissions) {
623: switch (perm) {
624: case CREATE:
625: mayCreate = true;
626: break;
627: case DELETE:
628: mayDelete = true;
629: break;
630: case EDIT:
631: mayEdit = true;
632: break;
633: case EXPORT:
634: mayExport = true;
635: break;
636: case RELATE:
637: mayRelate = true;
638: break;
639: case READ:
640: mayRead = true;
641: break;
642: }
643: }
644: assign(aclId, groupId, mayRead, mayEdit, mayRelate, mayDelete,
645: mayExport, mayCreate);
646: }
647:
648: /**
649: * {@inheritDoc}
650: */
651: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
652: public List<ACLAssignment> loadGroupAssignments(long groupId)
653: throws FxApplicationException {
654: return loadAssignments(null, groupId);
655: }
656:
657: /**
658: * {@inheritDoc}
659: */
660: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
661: public List<ACLAssignment> loadAssignments(long aclId)
662: throws FxApplicationException {
663: return loadAssignments(aclId, null);
664: }
665:
666: /**
667: * {@inheritDoc}
668: */
669: @TransactionAttribute(TransactionAttributeType.REQUIRED)
670: public void unassign(long aclId, long groupId)
671: throws FxApplicationException {
672: Connection con = null;
673: Statement stmt = null;
674: String curSql;
675: UserTicket ticket = FxContext.get().getTicket();
676: checkPermissions(ticket, groupId, aclId, true);
677:
678: try {
679: // Obtain a database connection
680: con = Database.getDbConnection();
681:
682: // Delete any old assignments
683: curSql = "DELETE FROM " + TBL_ASSIGN_ACLS
684: + " WHERE USERGROUP=" + groupId + " AND ACL="
685: + aclId;
686: stmt = con.createStatement();
687: if (stmt.executeUpdate(curSql) == 0) {
688: FxNotFoundException nfe = new FxNotFoundException(
689: "ex.aclAssignment.notFound", aclId, groupId);
690: if (LOG.isInfoEnabled())
691: LOG.info(nfe, nfe);
692: throw nfe;
693: }
694:
695: // Update active UserTickets
696: UserTicketStore.flagDirtyHavingGroupId(groupId);
697: } catch (FxNotFoundException e) {
698: throw e;
699: } catch (Exception exc) {
700: ctx.setRollbackOnly();
701: FxRemoveException dbe = new FxRemoveException(exc,
702: "ex.aclAssignment.unassigneFailed", aclId, groupId);
703: LOG.error(dbe, exc);
704: throw dbe;
705: } finally {
706: Database.closeObjects(ACLEngineBean.class, con, stmt);
707: }
708:
709: }
710:
711: /**
712: * Permission check helper function.
713: *
714: * @param ticket the ticket to use
715: * @param groupId the group id
716: * @param aclId the acl id
717: * @param checkRole the role check option
718: * @throws FxApplicationException if a error occured
719: */
720: private void checkPermissions(UserTicket ticket, Long groupId,
721: Long aclId, boolean checkRole)
722: throws FxApplicationException {
723:
724: // Security check (1)
725: if (checkRole && !ticket.isInRole(Role.MandatorSupervisor))
726: FxPermissionUtils.checkRole(ticket, Role.ACLManagement);
727:
728: if (groupId != null) {
729: UserGroup grp = group.load(groupId);
730: if (!grp.mayAccessGroup(ticket))
731: throw new FxNoAccessException(LOG,
732: "ex.acl.noAccess.foreignMandator");
733: }
734:
735: if (aclId != null) {
736: ACL acl = load(aclId);
737: if (!ticket.isGlobalSupervisor()
738: && acl.getMandatorId() != ticket.getMandatorId()) {
739: // ACL belongs a foreign mandator
740: throw new FxNoAccessException(LOG,
741: "ex.acl.noAccess.read", aclId);
742: }
743: }
744: }
745:
746: /**
747: * {@inheritDoc}
748: */
749: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
750: public List<ACLAssignment> loadAssignments(Long aclId, Long groupId)
751: throws FxApplicationException {
752: Connection con = null;
753: Statement stmt = null;
754: String curSql;
755: UserTicket ticket = FxContext.get().getTicket();
756:
757: // Permission & Exists check
758: checkPermissions(ticket, groupId, aclId, false);
759: try {
760: // Obtain a database connection
761: con = Database.getDbConnection();
762:
763: // load assignments
764: // 1 2 3 4 5 6 7
765: curSql = "SELECT ass.USERGROUP,ass.ACL,ass.PREAD,ass.PEDIT,ass.PREMOVE,ass.PEXPORT,ass.PREL,"
766: +
767: // 8 , 9 10 11 12 13
768: "ass.PCREATE,acl.CAT_TYPE,ass.CREATED_BY,ass.CREATED_AT,ass.MODIFIED_BY,ass.MODIFIED_AT "
769: + "FROM "
770: + TBL_ASSIGN_ACLS
771: + " ass, "
772: + TBL_ACLS
773: + " acl WHERE "
774: + "ass.ACL=acl.ID AND "
775: + ((groupId != null) ? "USERGROUP=" + groupId : "")
776: + ((groupId != null && aclId != null) ? " AND "
777: : "")
778: + ((aclId != null) ? "ACL=" + aclId : "");
779:
780: stmt = con.createStatement();
781: ResultSet rs = stmt.executeQuery(curSql);
782:
783: // Read the data
784: ArrayList<ACLAssignment> result = new ArrayList<ACLAssignment>(
785: 20);
786: while (rs != null && rs.next())
787: result.add(new ACLAssignment(rs.getLong(2), rs
788: .getLong(1), rs.getBoolean(3),
789: rs.getBoolean(4), rs.getBoolean(7), rs
790: .getBoolean(5), rs.getBoolean(6), rs
791: .getBoolean(8), ACL.Category.getById(rs
792: .getByte(9)), LifeCycleInfoImpl.load(
793: rs, 10, 11, 12, 13)));
794:
795: // Return the found entries
796: result.trimToSize();
797: return result;
798: } catch (SQLException exc) {
799: throw new FxLoadException(LOG, exc,
800: "ex.aclAssignment.loadFailed");
801: } finally {
802: Database.closeObjects(ACLEngineBean.class, con, stmt);
803: }
804: }
805:
806: }
|