Source Code Cross Referenced for RowSecuredDBObject.java in  » J2EE » Expresso » com » jcorporate » expresso » core » dbobj » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » Expresso » com.jcorporate.expresso.core.dbobj 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* ====================================================================
0002:         * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
0003:         *
0004:         * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
0005:         *
0006:         * Redistribution and use in source and binary forms, with or without
0007:         * modification, are permitted provided that the following conditions
0008:         * are met:
0009:         *
0010:         * 1. Redistributions of source code must retain the above copyright
0011:         *    notice, this list of conditions and the following disclaimer.
0012:         *
0013:         * 2. Redistributions in binary form must reproduce the above copyright
0014:         *    notice, this list of conditions and the following disclaimer in
0015:         *    the documentation and/or other materials provided with the
0016:         *    distribution.
0017:         *
0018:         * 3. The end-user documentation included with the redistribution,
0019:         *    if any, must include the following acknowledgment:
0020:         *       "This product includes software developed by Jcorporate Ltd.
0021:         *        (http://www.jcorporate.com/)."
0022:         *    Alternately, this acknowledgment may appear in the software itself,
0023:         *    if and wherever such third-party acknowledgments normally appear.
0024:         *
0025:         * 4. "Jcorporate" and product names such as "Expresso" must
0026:         *    not be used to endorse or promote products derived from this
0027:         *    software without prior written permission. For written permission,
0028:         *    please contact info@jcorporate.com.
0029:         *
0030:         * 5. Products derived from this software may not be called "Expresso",
0031:         *    or other Jcorporate product names; nor may "Expresso" or other
0032:         *    Jcorporate product names appear in their name, without prior
0033:         *    written permission of Jcorporate Ltd.
0034:         *
0035:         * 6. No product derived from this software may compete in the same
0036:         *    market space, i.e. framework, without prior written permission
0037:         *    of Jcorporate Ltd. For written permission, please contact
0038:         *    partners@jcorporate.com.
0039:         *
0040:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0041:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0042:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0043:         * DISCLAIMED.  IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
0044:         * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0045:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
0046:         * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0047:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0048:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0049:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0050:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0051:         * SUCH DAMAGE.
0052:         * ====================================================================
0053:         *
0054:         * This software consists of voluntary contributions made by many
0055:         * individuals on behalf of the Jcorporate Ltd. Contributions back
0056:         * to the project(s) are encouraged when you make modifications.
0057:         * Please send them to support@jcorporate.com. For more information
0058:         * on Jcorporate Ltd. and its products, please see
0059:         * <http://www.jcorporate.com/>.
0060:         *
0061:         * Portions of this software are based upon other open source
0062:         * products and are subject to their respective licenses.
0063:         */
0064:        package com.jcorporate.expresso.core.dbobj;
0065:
0066:        import com.jcorporate.expresso.core.db.DBConnection;
0067:        import com.jcorporate.expresso.core.db.DBException;
0068:        import com.jcorporate.expresso.core.registry.MutableRequestRegistry;
0069:        import com.jcorporate.expresso.core.registry.RequestRegistry;
0070:        import com.jcorporate.expresso.core.security.User;
0071:        import com.jcorporate.expresso.services.dbobj.RowGroupPerms;
0072:        import com.jcorporate.expresso.services.dbobj.RowPermissions;
0073:        import com.jcorporate.expresso.services.dbobj.UserGroup;
0074:
0075:        import java.util.ArrayList;
0076:        import java.util.Collection;
0077:        import java.util.Iterator;
0078:        import java.util.List;
0079:
0080:        /**
0081:         * subclass this for support of row-level Authorization. <br>
0082:         * <br>
0083:         * Typically, you construct RowSecuredDBObject passing in userId or the
0084:         * controller request to set the requesting identity.  Or, after construction, call
0085:         * setRequestingUid() so that user of this DBObject is known.  Otherwise,
0086:         * security checks will always return false (and access methods will throw
0087:         * SecurityException). <br>
0088:         * <br>
0089:         * LIMITATION: the primary key for a given row is persisted, along with the
0090:         * name of the table, to identify the permissions for that row. In other
0091:         * words, the primary key for permissions is the row's table name plus the
0092:         * row's primary key: permissionPK = targetTable + targetPrimKey.
0093:         * Each database vendor (MySQL,
0094:         * Oracle, etc.) has its own limit for the longest field that can be indexed
0095:         * as a primary key.  If a target row has a very long primary key, the database may
0096:         * not be able to accommodate the primary key for its permissions.  In that
0097:         * case, a runtime exception is thrown when trying to persist the permissions.
0098:         * If  (length(permissionPK) > MAXIMUM for database) { throw runtime exception}
0099:         * In most cases, the primary key is an integer or some other short field, so
0100:         * this limitation is not a problem.
0101:         * <p/>
0102:         * LIMITATION: all permissions are stored in a two tables: RowPermissions & RowGroupPerms.
0103:         * If your application
0104:         * has many tables (dbobjects) which all subclass RowSecuredDBObject,
0105:         * and also has many rows in these tables, you could run into scaling issues
0106:         * first with permissions.  Use RowSecuredDBObject subclasses for only the
0107:         * important objects. Roll your own security scheme if you expect a very large
0108:         * database... and tell us how you did it. :-)
0109:         *
0110:         * @author larry hamel, CodeGuild, Inc.
0111:         * @see com.jcorporate.expresso.services.dbobj.RowPermissions
0112:         * @see com.jcorporate.expresso.services.dbobj.RowGroupPerms
0113:         */
0114:        public class RowSecuredDBObject extends SecuredDBObject {
0115:
0116:            /**
0117:             * Flag for getPermission() if it must create new.
0118:             */
0119:            private static final String CREATED_NEW = "CREATED_NEW";
0120:
0121:            /**
0122:             * Constructor without parameters.  This constructor will attempt to use servlet filter
0123:             * to set data context and user ID from expresso v.5.6.  However, if you
0124:             * have not set up this filter in web.xml, be sure to set dbname and user id
0125:             * after constructing.
0126:             *
0127:             * @throws DBException upon database communication error
0128:             * @todo after expresso v.5.7, change impl to throw exception if servlet
0129:             * filter is not found. Introducing this in v5.6, so legacy
0130:             * does not want exceptions
0131:             */
0132:            public RowSecuredDBObject() throws DBException {
0133:                try {
0134:                    User user = RequestRegistry.getUser();
0135:                    try {
0136:                        user.getUid();
0137:                        this .setRequestingUid(user.getUid());
0138:                    } catch (Throwable e) { // npe if user is null
0139:                        getLogger()
0140:                                .warn(
0141:                                        "Cannot get user from request registry for class: '"
0142:                                                + getClass().getName()
0143:                                                + "'. No user has been associated with this thread yet. (see "
0144:                                                + MutableRequestRegistry.class
0145:                                                        .getName() + ")");
0146:
0147:                        // by default, the superclass sets requesting user ID
0148:                        // to 'system' == superuser,
0149:                        // so reset the requesting user here
0150:                        super .setRequestingUid(User.getIdFromLogin(
0151:                                User.UNKNOWN_USER, getDataContext()));
0152:                    }
0153:
0154:                } catch (Exception ex) {
0155:
0156:                    // by default, the superclass sets requesting user ID
0157:                    // to 'system' == superuser,
0158:                    // so reset the requesting user here
0159:                    super .setRequestingUid(User.getIdFromLogin(
0160:                            User.UNKNOWN_USER, getDataContext()));
0161:
0162:                    // no error for now if filter not found.
0163:                    // @todo after expresso v.5.7, change impl to throw exception
0164:                    // if servlet filter is not found. Introducing this in v5.6,
0165:                    // so legacy does not want exceptions
0166:                    getLogger().warn(
0167:                            "Problem automatically setting user ID: "
0168:                                    + getClass().getName() + ", err: "
0169:                                    + ex.getClass().getName() + ", msg: "
0170:                                    + ex.getMessage());
0171:                }
0172:
0173:                // warn if key of this row may be too long
0174:                checkKeyLength();
0175:            }
0176:
0177:            /**
0178:             * Constructor: Specify a DB connection AND user id.
0179:             *
0180:             * @param theConnection A DBConnection that this object should use to
0181:             *                      connect to the database
0182:             * @param theUser       User name attempting to use this object. If this is
0183:             *                      "SYSTEM", then full permissions are granted. Note that you
0184:             *                      cannot log in as "SYSTEM", it can only be used from within a
0185:             *                      method.
0186:             * @throws DBException If the object cannot be created
0187:             */
0188:            public RowSecuredDBObject(DBConnection theConnection, int theUser)
0189:                    throws DBException {
0190:                super (theConnection, theUser);
0191:
0192:                // check that key is not too long
0193:                checkKeyLength();
0194:            }
0195:
0196:            /**
0197:             * Creates a new RowSecuredDBObject object.
0198:             * This constructor will attempt to use servlet filter
0199:             * to set data context--from expresso v.5.6.  However, if you
0200:             * have not set up this filter in web.xml, be sure to set dbname and user id
0201:             * after constructing.
0202:             *
0203:             * @param theUser requesting user
0204:             * @throws DBException upon database communication error
0205:             * @todo after expresso v.5.7, change impl to throw exception if servlet filter is not found. Introducing this in v5.6, so legacy does not want exceptions     *
0206:             */
0207:            public RowSecuredDBObject(int theUser) throws DBException {
0208:                super (theUser);
0209:
0210:                try {
0211:                    setDataContext(RequestRegistry.getDataContext());
0212:                } catch (IllegalStateException e) {
0213:                    // no error for now if filter not found.
0214:                    // @todo after expresso v.5.7, change impl to throw exception if servlet filter is not found. Introducing this in v5.6, so legacy does not want exceptions
0215:                }
0216:
0217:                // check that key is not too long
0218:                checkKeyLength();
0219:            }
0220:
0221:            /**
0222:             * Creates a new RowSecuredDBObject object.
0223:             *
0224:             * @param request context for using this object
0225:             * @throws DBException upon database communication error
0226:             */
0227:            public RowSecuredDBObject(RequestContext request)
0228:                    throws DBException {
0229:                super (request);
0230:
0231:                // check that key is not too long
0232:                checkKeyLength();
0233:            }
0234:
0235:            /**
0236:             * @return list of a group names (strings) which have permission to change
0237:             *         permission
0238:             * @throws DBException upon database communication error
0239:             */
0240:            public List getAdministrateGroups() throws DBException {
0241:                List allGroups = this .getGroups();
0242:
0243:                if (allGroups.size() == 0) {
0244:                    return allGroups;
0245:                }
0246:
0247:                List permGroups = new ArrayList();
0248:
0249:                for (Iterator iterator = allGroups.iterator(); iterator
0250:                        .hasNext();) {
0251:                    RowGroupPerms perms = (RowGroupPerms) iterator.next();
0252:
0253:                    if (perms.canGroupAdministrate()) {
0254:                        permGroups.add(perms.group());
0255:                    }
0256:                }
0257:
0258:                return permGroups;
0259:            }
0260:
0261:            /**
0262:             * find any existing permission groups for this object. Typically,
0263:             * subclasses will call getReadGroups and getWriteGroups instead of this
0264:             * method
0265:             *
0266:             * @return list of RowGroupPerms
0267:             * @throws DBException upon database communication error
0268:             */
0269:            public List getGroups() throws DBException {
0270:                String primeKey = getKey();
0271:
0272:                RowGroupPerms rowGroupPerms = new RowGroupPerms(
0273:                        getJDBCMetaData().getTargetTable(), primeKey);
0274:                rowGroupPerms.setDataContext(getDataContext());
0275:
0276:                if (getLocalConnection() != null) {
0277:                    rowGroupPerms.setConnection(getLocalConnection());
0278:                }
0279:
0280:                return rowGroupPerms.searchAndRetrieveList();
0281:            }
0282:
0283:            /**
0284:             * set the group and permissions for this object; owner id is taken from
0285:             * getRequestingUid() before permissions can be set, caller's permission
0286:             * to change permissions is tested
0287:             *
0288:             * @param group name of group
0289:             * @param perm  value of permissions
0290:             * @throws DBException upon database communication error
0291:             */
0292:            public void setPermissions(String group, int perm)
0293:                    throws DBException {
0294:                if (!canRequesterAdministrate()) {
0295:                    throw new SecurityException(
0296:                            "cannot set permissions by user_id: "
0297:                                    + getRequestingUid()
0298:                                    + " for db object in table: "
0299:                                    + getJDBCMetaData().getTargetTable()
0300:                                    + " with primary key: " + getKey());
0301:                }
0302:
0303:                setPermissions(getRequestingUid(), group, perm);
0304:            }
0305:
0306:            /**
0307:             * set the permissions for this object; group bits are ignored; only owner
0308:             * & "other" permissions apply with this method owner id is taken from
0309:             * getRequestingUid()
0310:             *
0311:             * @param perm permissions to set
0312:             * @throws DBException upon database communication error
0313:             */
0314:            public void setPermissions(int perm) throws DBException {
0315:                setPermissions(getRequestingUid(), null, perm);
0316:            }
0317:
0318:            /**
0319:             * finds row permissions for the target row of this DBObject. if no row
0320:             * permissions are already persisted, the returned permissions object will
0321:             * be constructed and keyed to generating object, but all permissions will
0322:             * be false
0323:             *
0324:             * @return RowPermissions of the current perms
0325:             * @throws DBException if keys are not set on this object
0326:             */
0327:            public RowPermissions getPermissions() throws DBException {
0328:                if (!this .haveAllKeys()) {
0329:                    throw new DBException(
0330:                            "cannot get/set permissions on item before item's primary key(s) are available.");
0331:                }
0332:
0333:                String primeKey = getKey();
0334:                RowPermissions rowPermissions = new RowPermissions(
0335:                        getJDBCMetaData().getTargetTable(), primeKey);
0336:                rowPermissions.setDataContext(getDataContext());
0337:                if (getLocalConnection() != null) {
0338:                    rowPermissions.setConnection(getLocalConnection());
0339:                }
0340:
0341:                boolean found = rowPermissions.find();
0342:
0343:                // set owner if this is a new set of permissions
0344:                if (!found) {
0345:                    rowPermissions.setAttribute(CREATED_NEW, "1");
0346:                    rowPermissions.owner(getRequestingUid());
0347:                }
0348:
0349:                return rowPermissions;
0350:            }
0351:
0352:            /**
0353:             * @return list of group names (strings) which have read permission
0354:             * @throws DBException upon database communication error
0355:             */
0356:            public List getReadGroups() throws DBException {
0357:                List allGroups = this .getGroups();
0358:
0359:                if (allGroups.size() == 0) {
0360:                    return allGroups;
0361:                }
0362:
0363:                List readGroups = new ArrayList();
0364:
0365:                for (Iterator iterator = allGroups.iterator(); iterator
0366:                        .hasNext();) {
0367:                    RowGroupPerms perms = (RowGroupPerms) iterator.next();
0368:
0369:                    if (perms.canGroupRead()) {
0370:                        readGroups.add(perms.group());
0371:                    }
0372:                }
0373:
0374:                return readGroups;
0375:            }
0376:
0377:            /**
0378:             * determine if this function is allowed for this requesting user
0379:             *
0380:             * @param requestedFunction code for function -- Add, Update, Delete, Search (read)
0381:             * @return true if this function is allowed for this requesting user
0382:             * @throws SecurityException (unchecked) if not allowed
0383:             * @throws DBException       for other data-related errors.
0384:             */
0385:            public boolean isRowAllowed(String requestedFunction)
0386:                    throws DBException {
0387:                boolean result = false;
0388:
0389:                if (SEARCH.equals(requestedFunction)) {
0390:                    result = canRequesterRead();
0391:                } else if (UPDATE.equals(requestedFunction)
0392:                        || DELETE.equals(requestedFunction)) {
0393:                    result = canRequesterWrite();
0394:                } else if (ADD.equals(requestedFunction)) {
0395:                    // we do not test "add", since the row isn't written yet!
0396:                    // instead, superclass will test as part of update call
0397:                    result = true;
0398:                }
0399:
0400:                if (!result) {
0401:                    throw new SecurityException(
0402:                            "User '"
0403:                                    + User.getLoginFromId(getRequestingUid(),
0404:                                            getDataContext())
0405:                                    + "' does not have permission to perform function '"
0406:                                    + requestedFunction
0407:                                    + "' on database object in table '"
0408:                                    + getJDBCMetaData().getTargetTable()
0409:                                    + "', row: '"
0410:                                    + getKey()
0411:                                    + "' in db/context '"
0412:                                    + getDataContext()
0413:                                    + "'. Please contact your system administrator if you feel this is incorrect.");
0414:                }
0415:
0416:                return result;
0417:            }
0418:
0419:            /**
0420:             * iterate through collection, testing each row's privileges remove any row
0421:             * which does not have privileges; (do not throw security exception, just
0422:             * remove row)
0423:             *
0424:             * @param requestedFunction code for function -- Add, Update, Delete, Search (read)
0425:             * @param items             is a collection of RowSecuredDBObjects
0426:             * @return true if AT LEAST ONE item in collectino is allowed; also manipulates input list, removing unallowed items
0427:             * @throws DBException upon database communication error
0428:             */
0429:            public boolean isRowAllowed(String requestedFunction,
0430:                    Collection items) throws DBException {
0431:                if (items.size() == 0) {
0432:                    return false;
0433:                }
0434:
0435:                boolean result = false;
0436:                List goodItems = new ArrayList();
0437:
0438:                for (Iterator iterator = items.iterator(); iterator.hasNext();) {
0439:                    RowSecuredDBObject rowSecureDBObject = (RowSecuredDBObject) iterator
0440:                            .next();
0441:
0442:                    // key point: this is not set by superclass
0443:                    rowSecureDBObject.setRequestingUid(getRequestingUid());
0444:
0445:                    try {
0446:                        if (rowSecureDBObject.isRowAllowed(requestedFunction)) {
0447:                            result = true; // at least one row is allowed
0448:                            goodItems.add(rowSecureDBObject);
0449:                        }
0450:                    } catch (SecurityException e) {
0451:                        if (getLogger().isDebugEnabled()) {
0452:                            getLogger()
0453:                                    .debug(
0454:                                            "Security exception checking for isRowAllowed: denying a row with key: "
0455:                                                    + getKey()
0456:                                                    + " ,  removing it from list of approved.");
0457:                        }
0458:                        // do nothing; this Row will be removed
0459:                    }
0460:                }
0461:
0462:                if (result) {
0463:                    // keep only good items
0464:                    items.retainAll(goodItems);
0465:
0466:                    /**
0467:                     * @todo does this retain ordering?
0468:                     */
0469:                } else {
0470:                    items.clear();
0471:                }
0472:
0473:                return result;
0474:            }
0475:
0476:            /**
0477:             * @return list of group names (strings) which have write permission
0478:             * @throws DBException upon database communication error
0479:             */
0480:            public List getWriteGroups() throws DBException {
0481:                List allGroups = this .getGroups();
0482:
0483:                if (allGroups.size() == 0) {
0484:                    return allGroups;
0485:                }
0486:
0487:                List writeGroups = new ArrayList();
0488:
0489:                for (Iterator iterator = allGroups.iterator(); iterator
0490:                        .hasNext();) {
0491:                    RowGroupPerms perms = (RowGroupPerms) iterator.next();
0492:
0493:                    if (perms.canGroupWrite()) {
0494:                        writeGroups.add(perms.group());
0495:                    }
0496:                }
0497:
0498:                return writeGroups;
0499:            }
0500:
0501:            /**
0502:             * we override not to check permissions (which is done at the table level
0503:             * by superclass) but rather to add default permissions
0504:             *
0505:             * @throws DBException upon database communication error
0506:             * @see #add(String group, int permissions ) for a way to add() with more
0507:             *      specific permissions
0508:             */
0509:            public void add() throws DBException {
0510:                super .add();
0511:                setDefaultPermissions();
0512:            }
0513:
0514:            /* add() */
0515:
0516:            /*
0517:             * add row with given permissions, with group permissions applying
0518:            to provided group.
0519:             * @param group the name of the group that has group privileges
0520:             * @param permissions for owner, group & others
0521:             * @see com.jcorporate.expresso.services.dbobj.RowPermissions
0522:             * @throws DBException upon database communication error
0523:             */
0524:            public synchronized void add(String group, int permissions)
0525:                    throws DBException {
0526:                super .add();
0527:                setPermissions(getRequestingUid(), group, permissions);
0528:            }
0529:
0530:            /* add() */
0531:
0532:            /**
0533:             * add permissions for a group; will only ADD permissions, not replace will
0534:             * add row or update existing row (logical OR of bits) as necessary
0535:             *
0536:             * @param group to be added
0537:             * @param perm  to be added
0538:             * @throws DBException upon database communication error
0539:             */
0540:            public void addGroupPerm(String group, int perm) throws DBException {
0541:                if (group == null) {
0542:                    throw new DBException("null group name");
0543:                }
0544:
0545:                // test if group is kosher
0546:                UserGroup grp = new UserGroup();
0547:                grp.setDataContext(getDataContext());
0548:                grp.setField("GroupName", group);
0549:
0550:                if (!grp.find()) {
0551:                    throw new DBException("cannot find group: " + group);
0552:                }
0553:
0554:                RowGroupPerms rowGroupPerms = new RowGroupPerms(
0555:                        getJDBCMetaData().getTargetTable(), getKey());
0556:                rowGroupPerms.setDataContext(getDataContext());
0557:                if (getLocalConnection() != null) {
0558:                    rowGroupPerms.setConnection(getLocalConnection());
0559:                }
0560:                rowGroupPerms.group(group);
0561:
0562:                if (rowGroupPerms.find()) {
0563:                    // careful just to ADD permissions, which means bitwise OR
0564:                    int addperm = perm | rowGroupPerms.permissions();
0565:
0566:                    if (addperm != rowGroupPerms.permissions()) {
0567:                        rowGroupPerms.permissions(addperm);
0568:                        rowGroupPerms.update();
0569:                    }
0570:                } else {
0571:                    rowGroupPerms.permissions(perm);
0572:                    rowGroupPerms.add();
0573:                }
0574:            }
0575:
0576:            /**
0577:             * @return true if requesting id has permission to administrate (change
0578:             *         permissions)
0579:             * @throws DBException upon database communication error
0580:             */
0581:            public boolean canRequesterAdministrate() throws DBException {
0582:                boolean result = false;
0583:
0584:                int userId = this .getRequestingUid();
0585:
0586:                if (userId == SYSTEM_ACCOUNT) {
0587:                    return true;
0588:                }
0589:
0590:                User user = new User();
0591:                user.setUid(userId);
0592:                user.setDataContext(this .getDataContext());
0593:
0594:                if (user.isAdmin()) {
0595:                    return true;
0596:                }
0597:
0598:                if (!user.find()) {
0599:                    throw new DBException("cannot find requesting user.");
0600:                }
0601:
0602:                RowPermissions rowPermissions = this .getPermissions();
0603:
0604:                // do tests by cpu cheapness: easiest tests first;
0605:                // we're finished at first "true"
0606:                // public readability?
0607:                result = rowPermissions.canOthersAdministrate()
0608:                        || ((userId == rowPermissions.owner()) && rowPermissions
0609:                                .canOwnerAdministrate());
0610:
0611:                if (!result) {
0612:                    // check  groups
0613:                    result = doUsersGroupsIntersect(user,
0614:                            getAdministrateGroups());
0615:                }
0616:
0617:                return result;
0618:            }
0619:
0620:            /**
0621:             * determine if getRequestingUid has rights to read this row
0622:             *
0623:             * @return true  if getRequestingUid has rights to read this row
0624:             * @throws DBException upon database communication error
0625:             */
0626:            public boolean canRequesterRead() throws DBException {
0627:                boolean result = false;
0628:
0629:                int userId = this .getRequestingUid();
0630:
0631:                if (userId == SYSTEM_ACCOUNT) {
0632:                    return true;
0633:                }
0634:
0635:                User user = new User();
0636:                user.setUid(userId);
0637:                user.setDataContext(this .getDataContext());
0638:
0639:                if (user.isAdmin()) {
0640:                    return true;
0641:                }
0642:
0643:                if (!user.find()) {
0644:                    throw new DBException("cannot find requesting user.");
0645:                }
0646:
0647:                RowPermissions rowPermissions = this .getPermissions();
0648:
0649:                // do tests by cpu cheapness: easiest tests first;
0650:                // we're finished at first "true"
0651:                // public readability?
0652:                result = rowPermissions.canOthersRead()
0653:                        || ((userId == rowPermissions.owner()) && rowPermissions
0654:                                .canOwnerRead());
0655:
0656:                if (!result) {
0657:                    // check  groups
0658:                    /**
0659:                     * @todo rewrite as a multidbobject join
0660:                     */
0661:                    result = doUsersGroupsIntersect(user, getReadGroups());
0662:                }
0663:
0664:                return result;
0665:            }
0666:
0667:            private boolean doUsersGroupsIntersect(User user, List groups)
0668:                    throws DBException {
0669:                boolean result = false;
0670:                for (Iterator iterator = user.getGroups().iterator(); iterator
0671:                        .hasNext();) {
0672:                    String userGrpname = (String) iterator.next();
0673:                    for (Iterator iterator1 = groups.iterator(); iterator1
0674:                            .hasNext();) {
0675:                        String readGrpName = (String) iterator1.next();
0676:                        result = readGrpName.equals(userGrpname);
0677:                        if (result)
0678:                            return true;
0679:                    }
0680:                }
0681:                return false;
0682:            }
0683:
0684:            /**
0685:             * @return true if requesting id has permission to write
0686:             * @throws DBException upon database communication error
0687:             */
0688:            public boolean canRequesterWrite() throws DBException {
0689:                boolean result = false;
0690:
0691:                int userId = this .getRequestingUid();
0692:
0693:                if (userId == SYSTEM_ACCOUNT) {
0694:                    return true;
0695:                }
0696:
0697:                User user = new User();
0698:                user.setUid(userId);
0699:                user.setDataContext(this .getDataContext());
0700:
0701:                if (user.isAdmin()) {
0702:                    return true;
0703:                }
0704:
0705:                if (!user.find()) {
0706:                    throw new DBException("cannot find requesting user.");
0707:                }
0708:
0709:                RowPermissions rowPermissions = this .getPermissions();
0710:
0711:                // do tests by cpu cheapness: easiest tests first;
0712:                // we're finished at first "true"
0713:                // public readability?
0714:                result = rowPermissions.canOthersWrite()
0715:                        || ((userId == rowPermissions.owner()) && rowPermissions
0716:                                .canOwnerWrite());
0717:
0718:                if (!result) {
0719:                    // check  groups
0720:                    result = doUsersGroupsIntersect(user, getWriteGroups());
0721:                }
0722:
0723:                return result;
0724:            }
0725:
0726:            /**
0727:             * @return the default group for this requesting user; null if user has no
0728:             *         groups
0729:             * @throws DBException upon database communication error
0730:             */
0731:            public String defaultGroup() throws DBException {
0732:                User user = new User();
0733:                user.setUid(getRequestingUid());
0734:                user.setDataContext(getDataContext());
0735:
0736:                if (!user.find()) {
0737:                    return null;
0738:                } else {
0739:                    return user.getPrimaryGroup();
0740:                }
0741:            }
0742:
0743:            /**
0744:             * override this to change default
0745:             *
0746:             * @return the default permissions
0747:             * @todo move this into ConfigManager
0748:             */
0749:            public int defaultPermissions() {
0750:                return RowPermissions.DEFAULT_PERMISSIONS;
0751:            }
0752:
0753:            /**
0754:             * delete row. always delete permission records too
0755:             *
0756:             * @param deleteDetails set to true if related details should be deleted also
0757:             * @throws DBException upon database communication error
0758:             */
0759:            public synchronized void delete(boolean deleteDetails)
0760:                    throws DBException {
0761:                isRowAllowed(DELETE);
0762:                super .delete(deleteDetails);
0763:
0764:                // delete all permissions associated with this row
0765:                RowPermissions rowPermissions = getPermissions();
0766:
0767:                if (rowPermissions.find()) {
0768:                    rowPermissions.delete();
0769:                }
0770:
0771:                List groups = getGroups();
0772:
0773:                for (Iterator iterator = groups.iterator(); iterator.hasNext();) {
0774:                    RowGroupPerms rowGroupPerms = (RowGroupPerms) iterator
0775:                            .next();
0776:                    rowGroupPerms.delete();
0777:                }
0778:            }
0779:
0780:            /* delete() */
0781:
0782:            /**
0783:             * check that all objects can be deleted; must retrieve all objects to
0784:             * check individually
0785:             *
0786:             * @throws DBException upon database communication error
0787:             */
0788:            public synchronized void deleteAll() throws DBException {
0789:                List list = searchAndRetrieveList();
0790:
0791:                for (Iterator iter = list.iterator(); iter.hasNext();) {
0792:                    RowSecuredDBObject object = (RowSecuredDBObject) iter
0793:                            .next();
0794:                    object.isRowAllowed(DELETE);
0795:                }
0796:
0797:                super .deleteAll();
0798:            }
0799:
0800:            /* deleteAll() */
0801:
0802:            /**
0803:             * find object on criteria provided in fields
0804:             *
0805:             * @return true if found AND allowed
0806:             * @throws DBException if user does not have rights to read found item
0807:             */
0808:            public boolean find() throws DBException {
0809:                boolean result = super .find();
0810:
0811:                // must test AFTER search, since we do not necessarily have row keys yet
0812:                // to find permissions
0813:                if (result == true) {
0814:                    isRowAllowed(SEARCH);
0815:                }
0816:
0817:                return result;
0818:            }
0819:
0820:            /**
0821:             * @return uid of owner of this object
0822:             * @throws DBException upon database communication error
0823:             */
0824:            public int ownerID() throws DBException {
0825:                // here is the inserted part of override
0826:                RowPermissions perms = this .getPermissions();
0827:
0828:                return perms.getFieldInt(RowPermissions.OWNER_ID);
0829:            }
0830:
0831:            /**
0832:             * remove a permissions group
0833:             *
0834:             * @param group to be removed
0835:             * @throws DBException upon database communication error
0836:             */
0837:            public void removeGroup(String group) throws DBException {
0838:                if (group == null) {
0839:                    throw new DBException("null group name");
0840:                }
0841:
0842:                RowGroupPerms rowGroupPerms = new RowGroupPerms(
0843:                        getJDBCMetaData().getTargetTable(), getKey());
0844:                rowGroupPerms.setDataContext(getDataContext());
0845:                rowGroupPerms.group(group);
0846:
0847:                if (getLocalConnection() != null) {
0848:                    rowGroupPerms.setConnection(getLocalConnection());
0849:                }
0850:
0851:                if (rowGroupPerms.find()) {
0852:                    rowGroupPerms.delete();
0853:                }
0854:            }
0855:
0856:            /**
0857:             * retrieve object on criteria provided in fields
0858:             *
0859:             * @throws DBException upon database communication error
0860:             */
0861:            public void retrieve() throws DBException {
0862:                super .retrieve();
0863:                this .isRowAllowed(SEARCH); // test second in case we have a new object which will not have any permissions yet, and therefore always be disallowed
0864:            }
0865:
0866:            /**
0867:             * search on criteria provided in fields, and after search phase iterate
0868:             * through collection, testing each row's privileges remove any row which
0869:             * does not have privileges; (do not throw security exception, just remove
0870:             * row)
0871:             *
0872:             * @return list of RowSecuredDBObject's which are both found AND allowed for this requester
0873:             * @throws DBException upon database communication error
0874:             */
0875:            public synchronized ArrayList searchAndRetrieveList()
0876:                    throws DBException {
0877:                //return super.searchAndRetrieveList();
0878:                ArrayList result = super .searchAndRetrieveList();
0879:                this .isRowAllowed(SEARCH, result);
0880:
0881:                return result;
0882:            }
0883:
0884:            /**
0885:             * search on criteria provided in fields, and after search phase iterate
0886:             * through collection, testing each row's privileges remove any row which
0887:             * does not have privileges; (do not throw security exception, just remove
0888:             * row) sort results by sortKeys
0889:             *
0890:             * @param sortKeys sort field(s)
0891:             * @return list of RowSecuredDBObject's which are both found AND allowed for this requester
0892:             * @throws DBException upon database communication error
0893:             */
0894:            public synchronized ArrayList searchAndRetrieveList(String sortKeys)
0895:                    throws DBException {
0896:                ArrayList result = super .searchAndRetrieveList(sortKeys);
0897:                this .isRowAllowed(SEARCH, result);
0898:
0899:                return result;
0900:            }
0901:
0902:            /* searchAndRetrieve(String) */
0903:
0904:            /**
0905:             * before allowing update, check permission
0906:             *
0907:             * @throws DBException upon database communication error
0908:             */
0909:            public void update() throws DBException {
0910:                isRowAllowed(UPDATE);
0911:                super .update();
0912:            }
0913:
0914:            /*  update() */
0915:
0916:            /**
0917:             * check delete privilege for all detail records; different than superclass
0918:             * because we must set uid
0919:             *
0920:             * @param obj Object to be checked for deletion of detail records
0921:             * @throws DBException upon database communication error
0922:             */
0923:            protected void checkDeleteDetailPerm(DBObject obj)
0924:                    throws DBException {
0925:                // here is the inserted part of override
0926:                if (obj instanceof  RowSecuredDBObject) {
0927:                    RowSecuredDBObject row = (RowSecuredDBObject) obj;
0928:                    row.setRequestingUid(getRequestingUid());
0929:                }
0930:
0931:                super .checkDeleteDetailPerm(obj);
0932:            }
0933:
0934:            /**
0935:             * // warn if key of this row may be too long
0936:             *
0937:             * @throws DBException upon error
0938:             * @todo test this impl and uncomment
0939:             */
0940:            protected void checkKeyLength() throws DBException {
0941:                //		int totalLength = 0;
0942:                //		Iterator iter = getDef().getAllKeysIterator();
0943:                //		while (iter.hasNext()) {
0944:                //			DBField field = (DBField) iter.next();
0945:                //			totalLength += field.getLengthInt();
0946:                //		}
0947:                //
0948:                //		if ( totalLength > RowPermissions.getMaxKeyLen() ) {
0949:                //			getLogger().debug("objects in table: " + getTargetTable()
0950:                //					+ " have a potential key length of: " + totalLength
0951:                //					+ " which is greater than the maximum that can be stored for "
0952:                //					+ RowSecuredDBObject.class.getName()
0953:                //					+ " so consider subclassing just SecuredDBObject instead." );
0954:                //		}
0955:            }
0956:
0957:            /**
0958:             * called by add() does NOT check as to whether caller has permission-admin
0959:             * rights--assumes that caller is only calling add(), so therefore caller
0960:             * has rights on the new row.
0961:             *
0962:             * @throws DBException upon database communication error
0963:             */
0964:            private void setDefaultPermissions() throws DBException {
0965:                RowPermissions rowPermissions = getPermissions();
0966:                rowPermissions.owner(getRequestingUid());
0967:                rowPermissions.permissions(defaultPermissions());
0968:                rowPermissions.addOrUpdate();
0969:
0970:                // default group may be null
0971:                String group = defaultGroup();
0972:
0973:                if ((group != null) && (group.length() > 0)) {
0974:                    addGroupPerm(group, defaultPermissions());
0975:                }
0976:            }
0977:
0978:            /**
0979:             * set permissions as indicated and persist, either calling db actions add() or update()
0980:             *
0981:             * @param owner new owner
0982:             * @param group new group for group perms
0983:             * @param perm  permissions to set
0984:             * @throws DBException upon database communication error
0985:             */
0986:            private void setPermissions(int owner, String group, int perm)
0987:                    throws DBException {
0988:                RowPermissions rowPermissions = getPermissions();
0989:                rowPermissions.owner(owner);
0990:                rowPermissions.permissions(perm);
0991:                if (rowPermissions.getAttribute(CREATED_NEW) != null) {
0992:                    rowPermissions.add();
0993:                    rowPermissions.removeAttribute(CREATED_NEW);
0994:                } else {
0995:                    rowPermissions.update();
0996:                }
0997:
0998:                if (group != null) {
0999:                    addGroupPerm(group, perm);
1000:                }
1001:            }
1002:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.