Source Code Cross Referenced for ContextAuthorization.java in  » Database-ORM » MMBase » org » mmbase » security » implementation » context » 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 » Database ORM » MMBase » org.mmbase.security.implementation.context 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:
003:        This software is OSI Certified Open Source Software.
004:        OSI Certified is a certification mark of the Open Source Initiative.
005:
006:        The license (Mozilla version 1.0) can be read at the MMBase site.
007:        See http://www.MMBase.org/license
008:
009:         */
010:        package org.mmbase.security.implementation.context;
011:
012:        import org.mmbase.bridge.Query;
013:        import org.mmbase.cache.Cache;
014:        import org.mmbase.storage.search.*;
015:        import java.util.*;
016:
017:        import org.w3c.dom.*;
018:        import org.xml.sax.InputSource;
019:
020:        import javax.xml.xpath.*;
021:
022:        import org.mmbase.module.core.MMBase;
023:        import org.mmbase.module.core.MMObjectNode;
024:        import org.mmbase.security.*;
025:        import org.mmbase.security.SecurityException; // must be imported explicity, because it is also in
026:        // java.lang
027:        import org.mmbase.util.logging.Logger;
028:        import org.mmbase.util.logging.Logging;
029:
030:        /**
031:         * Authorization based on a XML-configuration file. The XML file contains users, groups and
032:         * contexts. Contextes provide rights to users and/or groups and are identified by a string (which
033:         * is stored in the owner field).
034:         *
035:         * @author Eduard Witteveen
036:         * @author Pierre van Rooden
037:         * @author Michiel Meeuwissen
038:         * @version $Id: ContextAuthorization.java,v 1.46 2007/06/06 11:35:47 nklasens Exp $
039:         * @see    ContextAuthentication
040:         */
041:        public class ContextAuthorization extends Authorization {
042:            private static final Logger log = Logging
043:                    .getLoggerInstance(ContextAuthorization.class);
044:            private Document document;
045:            private ContextCache cache = new ContextCache();
046:
047:            protected Cache<String, AllowingContexts> allowingContextsCache = new Cache<String, AllowingContexts>(
048:                    200) { // 200 users.
049:                public String getName() {
050:                    return "CS:AllowingContextsCache";
051:                }
052:
053:                public String getDescription() {
054:                    return "Links user id to a set of contexts";
055:                }
056:            };
057:
058:            private int maxContextsInQuery = 50; // must be configurable
059:
060:            /** contains elements of type = Operation */
061:            private Set<Operation> globalAllowedOperations = new HashSet<Operation>();
062:            private Map<String, String> replaceNotFound = new HashMap<String, String>();
063:            private Map<UserContext, String> userDefaultContexts = new HashMap<UserContext, String>();
064:            private SortedSet<String> allContexts;
065:
066:            protected void load() {
067:                log.debug("using: '" + configResource
068:                        + "' as config file for authentication");
069:                try {
070:                    InputSource in = MMBaseCopConfig.securityLoader
071:                            .getInputSource(configResource);
072:                    // clear the cache of unfound contexts
073:                    replaceNotFound.clear();
074:                    allowingContextsCache.clear();
075:                    // clear the cache of user default contexts
076:                    userDefaultContexts.clear();
077:                    // reload the security xml document
078:                    document = org.mmbase.util.XMLBasicReader
079:                            .getDocumentBuilder(this .getClass()).parse(in);
080:                    getGlobalAllowedOperations();
081:                    setAllContexts();
082:                } catch (org.xml.sax.SAXException se) {
083:                    String message = "error loading configfile :'"
084:                            + configResource + "'(" + se + "->"
085:                            + se.getMessage() + "(" + se.getMessage() + "))";
086:                    throw new SecurityException(message, se);
087:                } catch (java.io.IOException ioe) {
088:                    throw new SecurityException("error loading configfile :'"
089:                            + configResource + "'(" + ioe + ")", ioe);
090:                }
091:                log.debug("loaded: '" + configResource
092:                        + "' as config file for authorization");
093:            }
094:
095:            public String getDefaultContext(UserContext user)
096:                    throws SecurityException {
097:                String defaultContext = userDefaultContexts.get(user);
098:                if (defaultContext == null) {
099:                    String xpath = "/contextconfig/accounts/user[@name='"
100:                            + user.getIdentifier() + "']";
101:                    Node found;
102:                    try {
103:                        log.debug("going to execute the query:" + xpath
104:                                + " on file : " + configResource);
105:                        XPath xp = XPathFactory.newInstance().newXPath();
106:                        found = (Node) xp.evaluate(xpath, document,
107:                                XPathConstants.NODE);
108:                    } catch (XPathExpressionException xe) {
109:                        throw new SecurityException(
110:                                "error executing query: '" + xpath
111:                                        + "' on file: '" + configResource + "'",
112:                                xe);
113:                    }
114:                    if (found == null) {
115:                        throw new SecurityException("Could not find user "
116:                                + user.getIdentifier()
117:                                + " in context security config file ("
118:                                + configResource + ")");
119:                    }
120:
121:                    NamedNodeMap nnm = found.getAttributes();
122:                    Node contextNode = nnm.getNamedItem("context");
123:                    defaultContext = contextNode.getNodeValue();
124:                    userDefaultContexts.put(user, defaultContext);
125:                }
126:                if (log.isDebugEnabled()) {
127:                    log.debug("user with name: " + user
128:                            + " has the default context: " + defaultContext);
129:                }
130:                return defaultContext;
131:            }
132:
133:            public void create(UserContext user, int nodeNumber)
134:                    throws SecurityException {
135:                if (log.isDebugEnabled()) {
136:                    log.debug("create on node #" + nodeNumber + " by user: "
137:                            + user);
138:                }
139:                String defaultContext = getDefaultContext(user);
140:                setContext(user, nodeNumber, defaultContext);
141:            }
142:
143:            public void update(UserContext user, int nodeNumber)
144:                    throws SecurityException {
145:                if (log.isDebugEnabled()) {
146:                    log.debug("update on node #" + nodeNumber + " by user: "
147:                            + user);
148:                }
149:            }
150:
151:            public void remove(UserContext user, int nodeNumber)
152:                    throws SecurityException {
153:                if (log.isDebugEnabled()) {
154:                    log.debug("remove on node #" + nodeNumber + " by user: "
155:                            + user);
156:                }
157:            }
158:
159:            public void setContext(UserContext user, int nodeNumber,
160:                    String context) throws SecurityException {
161:                // notify the log
162:                if (log.isDebugEnabled()) {
163:                    log.debug("set context on node #" + nodeNumber
164:                            + " by user: " + user + " to " + context);
165:                }
166:                // don't even bother if the context was already set.
167:                MMObjectNode node = getMMNode(nodeNumber);
168:                if (node.getStringValue("owner").equals(context))
169:                    return;
170:
171:                // check if is a valid context for us..
172:                Set<String> possible = getPossibleContexts(user, nodeNumber);
173:                if (!possible.contains(context)) {
174:                    throw new SecurityException("could not set the context to "
175:                            + context + " for node #" + nodeNumber
176:                            + " by user: " + user);
177:                }
178:
179:                // check if this operation is allowed? (should also be done somewhere else, but we can never be sure enough)
180:                verify(user, nodeNumber, Operation.CHANGE_CONTEXT);
181:
182:                // well now really set it...
183:                node.setValue("owner", context);
184:                node.commit();
185:                if (log.isDebugEnabled()) {
186:                    log.debug("changed context settings of node #" + nodeNumber
187:                            + " to context: " + context + " by user: " + user);
188:                }
189:            }
190:
191:            public String getContext(UserContext user, int nodeNumber)
192:                    throws SecurityException {
193:                // notify the log
194:                if (log.isDebugEnabled()) {
195:                    log.debug("get context on node #" + nodeNumber
196:                            + " by user: " + user);
197:                }
198:
199:                // check if this operation is allowed? (should also be done somewhere else, but we can never be sure enough)
200:                verify(user, nodeNumber, Operation.READ);
201:
202:                // and get the value...
203:                return getContext(nodeNumber);
204:            }
205:
206:            private void setAllContexts() throws SecurityException {
207:                allContexts = new TreeSet<String>();
208:                String xpath = "/contextconfig/contexts/context";
209:                log.trace("going to execute the query:" + xpath);
210:                NodeList found;
211:                try {
212:                    XPath xp = XPathFactory.newInstance().newXPath();
213:                    found = (NodeList) xp.evaluate(xpath, document,
214:                            XPathConstants.NODESET);
215:                } catch (XPathExpressionException xe) {
216:                    throw new SecurityException("error executing query: '"
217:                            + xpath + "' ", xe);
218:                }
219:                for (int i = 0; i < found.getLength(); i++) {
220:                    Node context = found.item(i);
221:                    NamedNodeMap nnm = context.getAttributes();
222:                    Node contextNameNode = nnm.getNamedItem("name");
223:                    allContexts.add(contextNameNode.getNodeValue());
224:                }
225:            }
226:
227:            public Set<String> getPossibleContexts(UserContext user,
228:                    int nodeNumber) throws SecurityException {
229:                if (log.isDebugEnabled()) {
230:                    log.debug("get possible context on node #" + nodeNumber
231:                            + " by user: " + user);
232:                }
233:
234:                // check if this operation is allowed? (should also be done somewhere else, but we can never be sure enough)
235:                // TODO: research if we maybe better could use WRITE or CHANGE_CONTEXT as rights for this operation...
236:                verify(user, nodeNumber, Operation.READ);
237:
238:                // retrieve the current context..
239:                String currentContext = getContext(user, nodeNumber);
240:                synchronized (replaceNotFound) {
241:                    if (replaceNotFound.containsKey(currentContext)) {
242:                        currentContext = replaceNotFound.get(currentContext);
243:                    }
244:                }
245:
246:                Set<String> list;
247:                synchronized (cache) {
248:                    list = cache.contextGet(currentContext);
249:                    if (list != null) {
250:                        log.debug("cache hit");
251:                        return list;
252:                    }
253:                    list = new HashSet<String>();
254:                }
255:
256:                // possible contextes are dependeding of the context they're in...
257:                String xpath = "/contextconfig/contexts/context[@name='"
258:                        + currentContext + "']/possible";
259:                log.debug("going to execute the query:" + xpath);
260:                NodeList found;
261:                try {
262:                    XPath xp = XPathFactory.newInstance().newXPath();
263:                    found = (NodeList) xp.evaluate(xpath, document,
264:                            XPathConstants.NODESET);
265:                } catch (XPathExpressionException xe) {
266:                    throw new SecurityException("error executing query: '"
267:                            + xpath + "' ", xe);
268:                }
269:
270:                for (int i = 0; i < found.getLength(); i++) {
271:                    Node context = found.item(i);
272:                    NamedNodeMap nnm = context.getAttributes();
273:                    Node contextNameNode = nnm.getNamedItem("context");
274:                    list.add(contextNameNode.getNodeValue());
275:                    if (log.isDebugEnabled()) {
276:                        log.debug("the context: "
277:                                + contextNameNode.getNodeValue()
278:                                + " is possible context for node #"
279:                                + nodeNumber + " by user: " + user);
280:                    }
281:                }
282:                synchronized (cache) {
283:                    cache.contextAdd(currentContext, list);
284:                }
285:                return list;
286:            }
287:
288:            /**
289:             * @since MMBase-1.9
290:             */
291:            protected String getContext(int nodeNumber) {
292:                MMObjectNode node = getMMNode(nodeNumber);
293:                return node.getStringValue("owner");
294:            }
295:
296:            public boolean check(UserContext user, int nodeNumber,
297:                    Operation operation) throws SecurityException {
298:                if (log.isDebugEnabled()) {
299:                    log.debug("check on node #" + nodeNumber + " by user: "
300:                            + user + " for operation " + operation);
301:                }
302:
303:                // is our usercontext still valid?
304:                if (!manager.getAuthentication().isValid(user)) {
305:                    String msg = "the usercontext was expired";
306:                    throw new java.lang.SecurityException(msg);
307:                }
308:                // operations can be granted for the whole system...
309:                if (globalAllowedOperations.contains(operation)) {
310:                    log.debug("not retrieving the node, since operation:"
311:                            + operation + " is granted to everyone");
312:                    return true;
313:                }
314:
315:                //  look which groups belong to this,...
316:                String context = getContext(nodeNumber);
317:                return check(user, context, operation.toString());
318:            }
319:
320:            private boolean check(UserContext user, int nodeNumber,
321:                    String operation) throws SecurityException {
322:                return check(user, getContext(user, nodeNumber), operation);
323:            }
324:
325:            private boolean check(UserContext user, String context,
326:                    Operation operation) throws SecurityException {
327:                return check(user, context, operation.toString());
328:            }
329:
330:            private boolean check(UserContext user, String context,
331:                    String operation) throws SecurityException {
332:                // look if we have this one already inside the positive cache...
333:                synchronized (cache) {
334:                    Boolean result = cache.rightGet(operation, context, user
335:                            .getIdentifier());
336:                    if (result != null) {
337:                        log.trace("cache hit");
338:                        return result.booleanValue();
339:                    }
340:                }
341:
342:                String xpath;
343:                xpath = "/contextconfig/contexts/context[@name='" + context
344:                        + "']";
345:                Node found;
346:                try {
347:                    if (log.isDebugEnabled()) {
348:                        log.trace("going to execute the query:" + xpath);
349:                    }
350:                    XPathFactory xf = XPathFactory.newInstance();
351:                    found = (Node) xf.newXPath().evaluate(xpath, document,
352:                            XPathConstants.NODE);
353:
354:                    if (found == null) { // fall back to default
355:                        log.warn("context with name :'" + context
356:                                + "' was not found in the configuration "
357:                                + configResource);
358:
359:                        // retrieve the default context...
360:                        xpath = "/contextconfig/contexts/context[@name = ancestor::contexts/@default]";
361:
362:                        if (log.isDebugEnabled()) {
363:                            log.trace("going to execute the query:" + xpath
364:                                    + " on file : " + configResource);
365:                        }
366:
367:                        found = (Node) xf.newXPath().evaluate(xpath, document,
368:                                XPathConstants.NODE);
369:
370:                        if (found == null) {
371:                            throw new SecurityException(
372:                                    "Configuration error: Context "
373:                                            + context
374:                                            + " not found and no default context found either (change "
375:                                            + configResource + ")");
376:                        }
377:
378:                        // put it in the cache
379:                        NamedNodeMap nnm = found.getAttributes();
380:                        Node defaultContextNode = nnm.getNamedItem("name");
381:                        String defaultContext = defaultContextNode
382:                                .getNodeValue();
383:
384:                        synchronized (replaceNotFound) {
385:                            replaceNotFound.put(context, defaultContext);
386:                        }
387:                    }
388:
389:                    // found is not null now.
390:                    // now get the requested operation
391:
392:                    // now do the same query with the default context...
393:                    xpath = "operation[@type='" + operation + "']/grant";
394:                    if (log.isDebugEnabled()) {
395:                        log.debug("going to execute the query:" + xpath
396:                                + " On " + found.toString());
397:                    }
398:                    NodeList grants = (NodeList) xf.newXPath().evaluate(xpath,
399:                            found, XPathConstants.NODESET);
400:
401:                    if (log.isDebugEnabled()) {
402:                        log.debug("Found " + grants.getLength() + " grants on "
403:                                + operation + " for context " + context);
404:                    }
405:
406:                    Set<String> allowedGroups = new HashSet<String>();
407:                    for (int currentNode = 0; currentNode < grants.getLength(); currentNode++) {
408:                        Node contains = grants.item(currentNode);
409:                        NamedNodeMap nnm = contains.getAttributes();
410:                        Node groupNameNode = nnm.getNamedItem("group");
411:                        if (groupNameNode == null) {
412:                            throw new SecurityException(
413:                                    "Configuration error: 'grant' element must contain attribute 'group'");
414:                        }
415:                        allowedGroups.add(groupNameNode.getNodeValue());
416:                        if (log.isDebugEnabled()) {
417:                            log.debug("the group "
418:                                    + groupNameNode.getNodeValue()
419:                                    + " is granted for context " + context);
420:                        }
421:                    }
422:
423:                    boolean allowed = userInGroups(user.getIdentifier(),
424:                            allowedGroups, new HashSet<String>());
425:                    if (log.isDebugEnabled()) {
426:                        if (allowed) {
427:                            log
428:                                    .debug("operation "
429:                                            + operation
430:                                            + " was permitted for user with id "
431:                                            + user);
432:                        } else {
433:                            log.debug("operation " + operation
434:                                    + " was NOT permitted for user with id "
435:                                    + user);
436:                        }
437:                    }
438:
439:                    // put it in the cache
440:                    synchronized (cache) {
441:                        cache.rightAdd(operation, context,
442:                                user.getIdentifier(), allowed);
443:                    }
444:
445:                    return allowed;
446:
447:                } catch (XPathExpressionException xe) {
448:                    throw new java.lang.SecurityException(
449:                            "error executing query: '" + xpath + "' ", xe);
450:                }
451:
452:            }
453:
454:            private boolean userInGroups(String user, Set<String> groups,
455:                    Set<String> done) {
456:                // look if we have something to do...
457:                if (groups.size() == 0) {
458:                    log
459:                            .debug("entering userInGroups(recursive) with username: '"
460:                                    + user
461:                                    + "' without any groups, so user was not found..");
462:                    return false;
463:                }
464:
465:                if (log.isDebugEnabled()) {
466:                    log
467:                            .debug("entering userInGroups(recursive) with username: '"
468:                                    + user
469:                                    + "' and look if the user is in the following groups:");
470:
471:                    Iterator<String> di = groups.iterator();
472:                    while (di.hasNext()) {
473:                        log.debug("\t -> group : " + di.next());
474:                    }
475:                }
476:
477:                Set<String> fetchedGroups = new HashSet<String>();
478:                for (String groupname : groups) {
479:                    // get the group we are researching....
480:                    // well, since we are already exploring ourselve, no need to do it again....
481:                    done.add(groupname);
482:                    // do the xpath query...
483:                    String xpath = "/contextconfig/groups/group[@name='"
484:                            + groupname + "']/contains";
485:
486:                    if (log.isDebugEnabled()) {
487:                        log.debug("\tresearching group with name : "
488:                                + groupname);
489:                        log.debug("\tgoing to execute the query:" + xpath);
490:                    }
491:
492:                    NodeList found;
493:                    XPathFactory xf = XPathFactory.newInstance();
494:                    try {
495:                        found = (NodeList) xf.newXPath().evaluate(xpath,
496:                                document, XPathConstants.NODESET);
497:                    } catch (XPathExpressionException xe) {
498:                        throw new java.lang.SecurityException(
499:                                "error executing query: '" + xpath + "' ", xe);
500:                    }
501:                    // research the result...
502:                    for (int i = 0; i < found.getLength(); i++) {
503:                        Node contains = found.item(i);
504:                        NamedNodeMap nnm = contains.getAttributes();
505:                        String type = nnm.getNamedItem("type").getNodeValue();
506:                        String named = nnm.getNamedItem("named").getNodeValue();
507:                        if (log.isDebugEnabled()) {
508:                            log.debug("\t<contains type=\"" + type
509:                                    + "\" named=\"" + named + "\" />");
510:                        }
511:                        if (type.equals("group")) {
512:                            // this is a group...
513:                            // when not already known, add it to our to fetch-list
514:                            if (!done.contains(named)) {
515:                                log
516:                                        .debug("\tfound a new group with name "
517:                                                + named
518:                                                + ", which could contain our user, adding it to the to fetch list");
519:                                fetchedGroups.add(named);
520:                            }
521:                        } else if (type.equals("user")) {
522:                            // oh, maybe its me !!
523:                            if (named.equals(user)) {
524:                                log.debug("found the user with name " + named
525:                                        + " thus allowed.");
526:                                return true;
527:                            }
528:                            log.debug("\tdid found the user with name " + named
529:                                    + " but is not we are looking for.");
530:                        } else {
531:                            String msg = "dont know the type:" + type;
532:                            throw new SecurityException(msg);
533:                        }
534:                    }
535:                }
536:                return userInGroups(user, fetchedGroups, done);
537:            }
538:
539:            public void verify(UserContext user, int nodeNumber,
540:                    Operation operation) throws SecurityException {
541:                if (log.isDebugEnabled()) {
542:                    if (operation.getInt() > Operation.READ_INT) {
543:                        log.debug("assert on node #" + nodeNumber
544:                                + " by user: " + user + " for operation "
545:                                + operation);
546:                    } else {
547:                        log.trace("assert on node #" + nodeNumber
548:                                + " by user: " + user + " for operation "
549:                                + operation);
550:                    }
551:                }
552:                if (!check(user, nodeNumber, operation)) {
553:                    throw new SecurityException("Operation '" + operation
554:                            + "' on " + nodeNumber + " ("
555:                            + getContext(nodeNumber)
556:                            + ") was NOT permitted to " + user.getIdentifier());
557:                }
558:            }
559:
560:            public boolean check(UserContext user, int nodeNumber,
561:                    int srcNodeNumber, int dstNodeNumber, Operation operation)
562:                    throws SecurityException {
563:                if (operation == Operation.CREATE) {
564:                    // may link on both nodes
565:                    return check(user, srcNodeNumber, "link")
566:                            && check(user, dstNodeNumber, "link");
567:                } else if (operation == Operation.CHANGE_RELATION) {
568:                    return check(user, nodeNumber, Operation.WRITE.toString())
569:                            && check(user, srcNodeNumber, "link")
570:                            && check(user, dstNodeNumber, "link");
571:                } else {
572:                    throw new RuntimeException(
573:                            "Called check with wrong operation " + operation);
574:                }
575:            }
576:
577:            public void verify(UserContext user, int nodeNumber,
578:                    int srcNodeNumber, int dstNodeNumber, Operation operation)
579:                    throws SecurityException {
580:                if (operation == Operation.CREATE) {
581:                    // may link on both nodes
582:                    if (!check(user, srcNodeNumber, "link")) {
583:                        String msg = "Operation 'link' on " + srcNodeNumber
584:                                + " was NOT permitted to "
585:                                + user.getIdentifier();
586:                        throw new SecurityException(msg);
587:                    }
588:                    if (!check(user, dstNodeNumber, "link")) {
589:                        String msg = "Operation 'link' on " + dstNodeNumber
590:                                + " was NOT permitted to "
591:                                + user.getIdentifier();
592:                        throw new SecurityException(msg);
593:                    }
594:                } else if (operation == Operation.CHANGE_RELATION) {
595:                    if (!check(user, srcNodeNumber, "link")) {
596:                        String msg = "Operation 'link' on " + srcNodeNumber
597:                                + " was NOT permitted to "
598:                                + user.getIdentifier();
599:                        throw new SecurityException(msg);
600:                    }
601:                    if (!check(user, dstNodeNumber, "link")) {
602:                        String msg = "Operation 'link' on " + dstNodeNumber
603:                                + " was NOT permitted to "
604:                                + user.getIdentifier();
605:                        throw new SecurityException(msg);
606:                    }
607:                    verify(user, nodeNumber, Operation.WRITE);
608:                } else {
609:                    throw new RuntimeException(
610:                            "Called check with wrong operation " + operation);
611:                }
612:            }
613:
614:            private void getGlobalAllowedOperations() {
615:                // get all the Operations and add them to the globalAllowedOperations set..
616:                String xpath = "/contextconfig/global/allowed";
617:                log.debug("going to execute the query:" + xpath);
618:                NodeList found;
619:                XPathFactory xf = XPathFactory.newInstance();
620:                try {
621:                    found = (NodeList) xf.newXPath().evaluate(xpath, document,
622:                            XPathConstants.NODESET);
623:                } catch (XPathExpressionException xe) {
624:                    throw new SecurityException("error executing query: '"
625:                            + xpath + "' ", xe);
626:                }
627:
628:                for (int i = 0; i < found.getLength(); i++) {
629:                    Node allowed = found.item(i);
630:                    NamedNodeMap nnm = allowed.getAttributes();
631:                    Node contextNameNode = nnm.getNamedItem("operation");
632:                    Operation operation = Operation
633:                            .getOperation(contextNameNode.getNodeValue());
634:                    log.info("Everyone may do operation:" + operation);
635:                    if (globalAllowedOperations.contains(operation))
636:                        throw new SecurityException("operation:" + operation
637:                                + " already in allowed list");
638:                    globalAllowedOperations.add(operation);
639:                }
640:            }
641:
642:            private static org.mmbase.module.core.MMObjectBuilder builder = null;
643:
644:            private MMObjectNode getMMNode(int n) {
645:                if (builder == null) {
646:                    MMBase mmb = MMBase.getMMBase();
647:                    builder = mmb.getMMObject("typedef");
648:                    if (builder == null) {
649:                        String msg = "builder 'typedef' not found";
650:                        //throw new NotFoundException(msg);
651:                        throw new SecurityException(msg);
652:                    }
653:                }
654:                MMObjectNode node = builder.getNode(n);
655:                if (node == null) {
656:                    String msg = "node " + n + " not found";
657:                    //throw new NotFoundException(msg);
658:                    throw new SecurityException(msg);
659:                }
660:                return node;
661:            }
662:
663:            protected SortedSet<String> getAllContexts() {
664:                return allContexts;
665:            }
666:
667:            protected SortedSet<String> getDisallowingContexts(
668:                    UserContext user, Operation operation) {
669:                if (operation != Operation.READ)
670:                    throw new UnsupportedOperationException(
671:                            "Currently only implemented for READ");
672:                SortedSet<String> set = new TreeSet<String>();
673:                for (String context : getAllContexts()) {
674:                    if (!check(user, context, operation)) {
675:                        set.add(context);
676:                    }
677:                }
678:                return set;
679:            }
680:
681:            public QueryCheck check(UserContext userContext, Query query,
682:                    Operation operation) {
683:                if (globalAllowedOperations.contains(operation)) {
684:                    return COMPLETE_CHECK;
685:                } else {
686:                    if (operation == Operation.READ) {
687:
688:                        AllowingContexts ac = allowingContextsCache
689:                                .get(userContext.getIdentifier());
690:                        if (ac == null) {
691:                            // smart stuff for query-modification
692:                            SortedSet<String> disallowing = getDisallowingContexts(
693:                                    userContext, operation);
694:                            SortedSet<String> contexts;
695:                            boolean inverse;
696:                            if (log.isDebugEnabled()) {
697:                                log.debug("disallowing: " + disallowing
698:                                        + " all " + getAllContexts());
699:                            }
700:
701:                            // searching which is 'smallest' disallowing contexts, or allowing contexts.
702:                            if (disallowing.size() < (getAllContexts().size() / 2)) {
703:                                contexts = disallowing;
704:                                inverse = true;
705:                            } else {
706:                                contexts = new TreeSet<String>(getAllContexts());
707:                                contexts.removeAll(disallowing);
708:                                inverse = false;
709:                            }
710:                            ac = new AllowingContexts(contexts, inverse);
711:                            allowingContextsCache.put(userContext
712:                                    .getIdentifier(), ac);
713:                        }
714:
715:                        if (ac.contexts.size() == 0) {
716:                            if (ac.inverse) {
717:                                return COMPLETE_CHECK;
718:                            } else {
719:                                // may read nothing
720:                                Constraint mayNothing = query.createConstraint(
721:                                        query.createStepField(query.getSteps()
722:                                                .get(0), "number"), -1);
723:                                return new Authorization.QueryCheck(true,
724:                                        mayNothing);
725:                            }
726:                        }
727:
728:                        List<Step> steps = query.getSteps();
729:                        if (steps.size() * ac.contexts.size() < maxContextsInQuery) {
730:                            Iterator<Step> i = steps.iterator();
731:                            Constraint constraint = null;
732:                            while (i.hasNext()) {
733:                                Step step = i.next();
734:                                StepField field = query.createStepField(step,
735:                                        "owner");
736:                                Constraint newConstraint = query
737:                                        .createConstraint(field, ac.contexts);
738:                                if (ac.inverse)
739:                                    query.setInverse(newConstraint, true);
740:                                if (constraint == null) {
741:                                    constraint = newConstraint;
742:                                } else {
743:                                    constraint = query.createConstraint(
744:                                            constraint,
745:                                            CompositeConstraint.LOGICAL_AND,
746:                                            newConstraint);
747:                                }
748:                            }
749:                            return new Authorization.QueryCheck(true,
750:                                    constraint);
751:                        } else { // query would grow too large
752:                            return Authorization.NO_CHECK;
753:                        }
754:
755:                    } else {
756:                        //not checking for READ: never mind, this is only used for read checks any way
757:                        return Authorization.NO_CHECK;
758:                    }
759:                }
760:            }
761:
762:            private static class AllowingContexts {
763:                private final SortedSet<String> contexts;
764:                private final boolean inverse;
765:
766:                AllowingContexts(SortedSet<String> c, boolean i) {
767:                    contexts = c;
768:                    inverse = i;
769:                }
770:            }
771:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.