001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001-2003 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package com.ecyrd.jspwiki.auth;
021:
022: import java.io.File;
023: import java.net.URL;
024: import java.security.*;
025: import java.security.cert.Certificate;
026: import java.util.Map;
027: import java.util.Properties;
028: import java.util.WeakHashMap;
029:
030: import org.apache.log4j.Logger;
031: import org.freshcookies.security.policy.LocalPolicy;
032: import org.freshcookies.security.policy.PolicyException;
033:
034: import com.ecyrd.jspwiki.NoRequiredPropertyException;
035: import com.ecyrd.jspwiki.WikiEngine;
036: import com.ecyrd.jspwiki.WikiException;
037: import com.ecyrd.jspwiki.WikiPage;
038: import com.ecyrd.jspwiki.WikiSession;
039: import com.ecyrd.jspwiki.auth.acl.Acl;
040: import com.ecyrd.jspwiki.auth.acl.AclEntry;
041: import com.ecyrd.jspwiki.auth.acl.UnresolvedPrincipal;
042: import com.ecyrd.jspwiki.auth.authorize.Role;
043: import com.ecyrd.jspwiki.auth.permissions.AllPermission;
044: import com.ecyrd.jspwiki.auth.permissions.PagePermission;
045: import com.ecyrd.jspwiki.auth.user.UserDatabase;
046: import com.ecyrd.jspwiki.auth.user.UserProfile;
047: import com.ecyrd.jspwiki.event.WikiEventListener;
048: import com.ecyrd.jspwiki.event.WikiEventManager;
049: import com.ecyrd.jspwiki.event.WikiSecurityEvent;
050: import com.ecyrd.jspwiki.util.ClassUtil;
051:
052: /**
053: * <p>Manages all access control and authorization; determines what authenticated
054: * users are allowed to do.</p>
055: * <p>Privileges in JSPWiki are expressed as Java-standard {@link java.security.Permission}
056: * classes. There are two types of permissions:</p>
057: * <ul>
058: * <li>{@link com.ecyrd.jspwiki.auth.permissions.WikiPermission} - privileges that apply
059: * to an entire wiki instance: <em>e.g.,</em> editing user profiles, creating pages, creating groups</li>
060: * <li>{@link com.ecyrd.jspwiki.auth.permissions.PagePermission} - privileges that apply
061: * to a single wiki page or range of pages: <em>e.g.,</em> reading, editing, renaming
062: * </ul>
063: * <p>Calling classes determine whether they are entitled to perform a particular action
064: * by constructing the appropriate permission first, then passing it and the current
065: * {@link com.ecyrd.jspwiki.WikiSession} to the
066: * {@link #checkPermission(WikiSession, Permission)} method. If the session's
067: * Subject possesses the permission, the action is allowed.</p>
068: * <p>For WikiPermissions, the decision criteria is relatively simple: the caller either
069: * possesses the permission, as granted by the wiki security policy -- or not.</p>
070: * <p>For PagePermissions, the logic is exactly the same if the page being checked
071: * does not have an access control list. However, if the page does have an ACL, the
072: * authorization decision is made based the <em>union</em> of the permissions
073: * granted in the ACL and in the security policy. In other words, the user must
074: * be named in the ACL (or belong to a group or role that is named in the ACL)
075: * <em>and</em> be granted (at least) the same permission in the security policy. We
076: * do this to prevent a user from gaining more permissions than they already
077: * have, based on the security policy.</p>
078: * <p>See the {@link #checkPermission(WikiSession, Permission)} and
079: * {@link #hasRoleOrPrincipal(WikiSession, Principal)} methods for more information
080: * on the authorization logic.</p>
081: * @author Andrew Jaquith
082: * @since 2.3
083: * @see AuthenticationManager
084: */
085: public final class AuthorizationManager {
086: private static final Logger log = Logger
087: .getLogger(AuthorizationManager.class);
088: /**
089: * The default external Authorizer is the {@link com.ecyrd.jspwiki.auth.authorize.WebContainerAuthorizer}
090: */
091: public static final String DEFAULT_AUTHORIZER = "com.ecyrd.jspwiki.auth.authorize.WebContainerAuthorizer";
092:
093: /** Name of the default security policy file, in WEB-INF. */
094: protected static final String DEFAULT_POLICY = "jspwiki.policy";
095:
096: /**
097: * The property name in jspwiki.properties for specifying the external {@link Authorizer}.
098: */
099: public static final String PROP_AUTHORIZER = "jspwiki.authorizer";
100:
101: private Authorizer m_authorizer = null;
102:
103: /** Cache for storing ProtectionDomains used to evaluate the local policy. */
104: private Map m_cachedPds = new WeakHashMap();
105:
106: private WikiEngine m_engine = null;
107:
108: private LocalPolicy m_localPolicy = null;
109:
110: private boolean m_useJAAS = true;
111:
112: /**
113: * Constructs a new AuthorizationManager instance.
114: */
115: public AuthorizationManager() {
116: }
117:
118: /**
119: * Returns <code>true</code> or <code>false</code>, depending on
120: * whether a Permission is allowed for the Subject associated with
121: * a supplied WikiSession. The access control algorithm works this way:
122: * <ol>
123: * <li>The {@link com.ecyrd.jspwiki.auth.acl.Acl} for the page is obtained</li>
124: * <li>The Subject associated with the current
125: * {@link com.ecyrd.jspwiki.WikiSession} is obtained</li>
126: * <li>If the Subject's Principal set includes the Role Principal that is
127: * the administrator group, always allow the Permission</li>
128: * <li>For all permissions, check to see if the Permission is allowed according
129: * to the default security policy. If it isn't, deny the permission and halt
130: * further processing.</li>
131: * <li>If there is an Acl, get the list of Principals assigned this
132: * Permission in the Acl: these will be role, group or user Principals, or
133: * {@link com.ecyrd.jspwiki.auth.acl.UnresolvedPrincipal}s (see below).
134: * Then iterate through the Subject's Principal set and determine whether
135: * the user (Subject) posesses any one of these specified Roles or
136: * Principals. The matching process delegates to
137: * {@link #hasRoleOrPrincipal(WikiSession, Principal)}.
138: * </ol>
139: * <p>
140: * Note that when iterating through the Acl's list of authorized Principals,
141: * it is possible that one or more of the Acl's Principal entries are of
142: * type <code>UnresolvedPrincipal</code>. This means that the last time
143: * the ACL was read, the Principal (user, built-in Role, authorizer Role, or
144: * wiki Group) could not be resolved: the Role was not valid, the user
145: * wasn't found in the UserDatabase, or the Group wasn't known to (e.g.,
146: * cached) in the GroupManager. If an <code>UnresolvedPrincipal</code> is
147: * encountered, this method will attempt to resolve it first <em>before</em>
148: * checking to see if the Subject possesses this principal, by calling
149: * {@link #resolvePrincipal(String)}. If the (re-)resolution does not
150: * succeed, the access check for the principal will fail by definition (the
151: * Subject should never contain UnresolvedPrincipals).
152: * </p>
153: * <p>
154: * If security not set to JAAS, will return true.
155: * </p>
156: * @param session the current wiki session
157: * @param permission the Permission being checked
158: * @see #hasRoleOrPrincipal(WikiSession, Principal)
159: * @return the result of the Permission check
160: */
161: public final boolean checkPermission(WikiSession session,
162: Permission permission) {
163: if (!m_useJAAS) {
164: //
165: // Nobody can login, if JAAS is turned off.
166: //
167:
168: if (permission == null
169: || "login".equals(permission.getActions()))
170: return false;
171:
172: return true;
173: }
174:
175: //
176: // A slight sanity check.
177: //
178: if (session == null || permission == null) {
179: fireEvent(WikiSecurityEvent.ACCESS_DENIED, null, permission);
180: return false;
181: }
182:
183: Principal user = session.getLoginPrincipal();
184:
185: // Always allow the action if user has AllPermission
186: Permission allPermission = new AllPermission(m_engine
187: .getApplicationName());
188: boolean hasAllPermission = checkStaticPermission(session,
189: allPermission);
190: if (hasAllPermission) {
191: fireEvent(WikiSecurityEvent.ACCESS_ALLOWED, user,
192: permission);
193: return true;
194: }
195:
196: // If the user doesn't have *at least* the permission
197: // granted by policy, return false.
198: boolean hasPolicyPermission = checkStaticPermission(session,
199: permission);
200: if (!hasPolicyPermission) {
201: fireEvent(WikiSecurityEvent.ACCESS_DENIED, user, permission);
202: return false;
203: }
204:
205: // If this isn't a PagePermission, it's allowed
206: if (!(permission instanceof PagePermission)) {
207: fireEvent(WikiSecurityEvent.ACCESS_ALLOWED, user,
208: permission);
209: return true;
210: }
211:
212: //
213: // If the page or ACL is null, it's allowed.
214: //
215: String pageName = ((PagePermission) permission).getPage();
216: WikiPage page = m_engine.getPage(pageName);
217: Acl acl = (page == null) ? null : m_engine.getAclManager()
218: .getPermissions(page);
219: if (page == null || acl == null || acl.isEmpty()) {
220: fireEvent(WikiSecurityEvent.ACCESS_ALLOWED, user,
221: permission);
222: return true;
223: }
224:
225: //
226: // Next, iterate through the Principal objects assigned
227: // this permission. If the context's subject possesses
228: // any of these, the action is allowed.
229:
230: Principal[] aclPrincipals = acl.findPrincipals(permission);
231:
232: log.debug("Checking ACL entries...");
233: log.debug("Acl for this page is: " + acl);
234: log.debug("Checking for principal: "
235: + String.valueOf(aclPrincipals));
236: log.debug("Permission: " + permission);
237:
238: for (int i = 0; i < aclPrincipals.length; i++) {
239: Principal aclPrincipal = aclPrincipals[i];
240:
241: // If the ACL principal we're looking at is unresolved,
242: // try to resolve it here & correct the Acl
243: if (aclPrincipal instanceof UnresolvedPrincipal) {
244: AclEntry aclEntry = acl.getEntry(aclPrincipal);
245: aclPrincipal = resolvePrincipal(aclPrincipal.getName());
246: if (aclEntry != null
247: && !(aclPrincipal instanceof UnresolvedPrincipal)) {
248: aclEntry.setPrincipal(aclPrincipal);
249: }
250: }
251:
252: if (hasRoleOrPrincipal(session, aclPrincipal)) {
253: fireEvent(WikiSecurityEvent.ACCESS_ALLOWED, user,
254: permission);
255: return true;
256: }
257: }
258: fireEvent(WikiSecurityEvent.ACCESS_DENIED, user, permission);
259: return false;
260: }
261:
262: /**
263: * <p>Determines if the Subject associated with a
264: * supplied WikiSession contains a desired Role or GroupPrincipal.
265: * The algorithm simply checks to see if the Subject possesses
266: * the Role or GroupPrincipal it in its Principal set. Note that
267: * any user (anyonymous, asserted, authenticated) can possess
268: * a built-in role. But a user <em>must</em> be authenticated to
269: * possess a role other than one of the built-in ones.
270: * We do this to prevent privilege escalation.</p>
271: * <p>For all other cases, this method returns <code>false</code>.</p>
272: * <p>Note that this method does <em>not</em> consult the external
273: * Authorizer or GroupManager; it relies on the Principals that
274: * have been injected into the user's Subject at login time, or
275: * after group creation/modification/deletion.</p>
276: * @param session the current wiki session, which must be non-null. If null,
277: * the result of this method always returns <code>false</code>
278: * @param principal the Principal (role or group principal) to look
279: * for, which must be non-<cor>null</code>. If <code>null</code>,
280: * the result of this method always returns <code>false</code>
281: * @return <code>true</code> if the Subject supplied with the WikiContext
282: * posesses the Role or GroupPrincipal, <code>false</code> otherwise
283: */
284: public final boolean isUserInRole(WikiSession session,
285: Principal principal) {
286: if (session == null || principal == null
287: || AuthenticationManager.isUserPrincipal(principal)) {
288: return false;
289: }
290:
291: // Any type of user can possess a built-in role
292: if (principal instanceof Role
293: && Role.isBuiltInRole((Role) principal)) {
294: return session.hasPrincipal(principal);
295: }
296:
297: // Only authenticated users can posssess groups or custom roles
298: if (session.isAuthenticated()
299: && AuthenticationManager.isRolePrincipal(principal)) {
300: return session.hasPrincipal(principal);
301: }
302: return false;
303: }
304:
305: /**
306: * Returns the current external {@link Authorizer} in use. This method
307: * is guaranteed to return a properly-initialized Authorizer, unless
308: * it could not be initialized. In that case, this method throws
309: * a {@link com.ecyrd.jspwiki.auth.WikiSecurityException}.
310: * @throws com.ecyrd.jspwiki.auth.WikiSecurityException if the Authorizer could
311: * not be initialized
312: * @return the current Authorizer
313: */
314: public final Authorizer getAuthorizer()
315: throws WikiSecurityException {
316: if (m_authorizer != null) {
317: return m_authorizer;
318: }
319: throw new WikiSecurityException(
320: "Authorizer did not initialize properly. Check the logs.");
321: }
322:
323: /**
324: * <p>Determines if the Subject associated with a supplied WikiSession contains
325: * a desired user Principal or built-in Role principal, OR is a member a
326: * Group or external Role. The rules are as follows:</p>
327: * <ol>
328: * <li>First, if desired Principal is a Role or GroupPrincipal, delegate to
329: * {@link #isUserInRole(WikiSession, Principal)} and
330: * return the result.</li>
331: * <li>Otherwise, we're looking for a user Principal,
332: * so iterate through the Principal set and see if
333: * any share the same name as the one we are looking for.</li>
334: * </ol>
335: * <p><em>Note: if the Principal parameter is a user principal, the session
336: * must be authenticated in order for the user to "possess it". Anonymous
337: * or asserted sessions will never posseess a named user principal.</em></p>
338: * @param session the current wiki session, which must be non-null. If null,
339: * the result of this method always returns <code>false</code>
340: * @param principal the Principal (role, group, or user principal) to look
341: * for, which must be non-null. If null, the result of this
342: * method always returns <code>false</code>
343: * @return <code>true</code> if the Subject supplied with the WikiContext
344: * posesses the Role, GroupPrincipal or desired
345: * user Principal, <code>false</code> otherwise
346: */
347: protected boolean hasRoleOrPrincipal(WikiSession session,
348: Principal principal) {
349: // If either parameter is null, always deny
350: if (session == null || principal == null) {
351: return false;
352: }
353:
354: // If principal is role, delegate to isUserInRole
355: if (AuthenticationManager.isRolePrincipal(principal)) {
356: return isUserInRole(session, principal);
357: }
358:
359: // We must be looking for a user principal, assuming that the user
360: // has been properly logged in.
361: // So just look for a name match.
362: if (session.isAuthenticated()
363: && AuthenticationManager.isUserPrincipal(principal)) {
364: String principalName = principal.getName();
365: Principal[] userPrincipals = session.getPrincipals();
366: for (int i = 0; i < userPrincipals.length; i++) {
367: Principal userPrincipal = userPrincipals[i];
368: if (userPrincipal.getName().equals(principalName)) {
369: return true;
370: }
371: }
372: }
373: return false;
374: }
375:
376: /**
377: * Initializes AuthorizationManager with an engine and set of properties.
378: * Expects to find property 'jspwiki.authorizer' with a valid Authorizer
379: * implementation name to take care of group lookup operations.
380: * @param engine the wiki engine
381: * @param properties the set of properties used to initialize the wiki engine
382: * @throws WikiException if the AuthorizationManager cannot be initialized
383: */
384: public final void initialize(WikiEngine engine,
385: Properties properties) throws WikiException {
386: m_engine = engine;
387:
388: m_useJAAS = AuthenticationManager.SECURITY_JAAS
389: .equals(properties.getProperty(
390: AuthenticationManager.PROP_SECURITY,
391: AuthenticationManager.SECURITY_JAAS));
392:
393: if (!m_useJAAS)
394: return;
395:
396: //
397: // JAAS authorization continues
398: //
399: m_authorizer = getAuthorizerImplementation(properties);
400: m_authorizer.initialize(engine, properties);
401:
402: // Initialize local security policy
403: try {
404: URL policyURL = AuthenticationManager.findConfigFile(
405: engine, DEFAULT_POLICY);
406:
407: if (policyURL != null) {
408: File policyFile = new File(policyURL.getPath());
409: m_localPolicy = new LocalPolicy(policyFile, engine
410: .getContentEncoding());
411: m_localPolicy.refresh();
412: log.info("Initialized default security policy: "
413: + policyFile.getAbsolutePath());
414: } else {
415: StringBuffer sb = new StringBuffer(
416: "JSPWiki was unable to initialize the ");
417: sb
418: .append("default security policy (WEB-INF/jspwiki.policy) file. ");
419: sb
420: .append("Please ensure that the jspwiki.policy file exists in the default location. ");
421: sb
422: .append("This file should exist regardless of the existance of a global policy file. ");
423: sb
424: .append("The global policy file is identified by the java.security.policy variable. ");
425: WikiSecurityException wse = new WikiSecurityException(
426: sb.toString());
427: log.fatal(sb.toString(), wse);
428: throw wse;
429: }
430: } catch (PolicyException e) {
431: log.error("Could not initialize local security policy: "
432: + e.getMessage());
433: throw new WikiException(e.getMessage());
434: }
435: }
436:
437: /**
438: * Returns <code>true</code> if JSPWiki's JAAS authorization system
439: * is used for authorization in addition to container controls.
440: * @return the result
441: */
442: protected boolean isJAASAuthorized() {
443: return m_useJAAS;
444: }
445:
446: /**
447: * Attempts to locate and initialize a Authorizer to use with this manager.
448: * Throws a WikiException if no entry is found, or if one fails to
449: * initialize.
450: * @param props jspwiki.properties, containing a
451: * 'jspwiki.authorization.provider' class name
452: * @return a Authorizer used to get page authorization information
453: * @throws WikiException
454: */
455: private final Authorizer getAuthorizerImplementation(
456: Properties props) throws WikiException {
457: String authClassName = props.getProperty(PROP_AUTHORIZER,
458: DEFAULT_AUTHORIZER);
459: return (Authorizer) locateImplementation(authClassName);
460: }
461:
462: private final Object locateImplementation(String clazz)
463: throws WikiException {
464: if (clazz != null) {
465: try {
466: Class authClass = ClassUtil.findClass(
467: "com.ecyrd.jspwiki.auth.authorize", clazz);
468: Object impl = authClass.newInstance();
469: return impl;
470: } catch (ClassNotFoundException e) {
471: log
472: .fatal("Authorizer " + clazz
473: + " cannot be found", e);
474: throw new WikiException("Authorizer " + clazz
475: + " cannot be found");
476: } catch (InstantiationException e) {
477: log.fatal("Authorizer " + clazz + " cannot be created",
478: e);
479: throw new WikiException("Authorizer " + clazz
480: + " cannot be created");
481: } catch (IllegalAccessException e) {
482: log
483: .fatal(
484: "You are not allowed to access this authorizer class",
485: e);
486: throw new WikiException(
487: "You are not allowed to access this authorizer class");
488: }
489: }
490:
491: throw new NoRequiredPropertyException("Unable to find a "
492: + PROP_AUTHORIZER + " entry in the properties.",
493: PROP_AUTHORIZER);
494: }
495:
496: /**
497: * Checks to see if the local security policy allows a particular static Permission.
498: * Do not use this method for normal permission checks; use
499: * {@link #checkPermission(WikiSession, Permission)} instead.
500: * @param principals the Principals to check
501: * @param permission the Permission
502: * @return the result
503: */
504: protected boolean allowedByLocalPolicy(Principal[] principals,
505: Permission permission) {
506: for (int i = 0; i < principals.length; i++) {
507: // Get ProtectionDomain for this Principal from cache, or create new one
508: ProtectionDomain pd = (ProtectionDomain) m_cachedPds
509: .get(principals[i]);
510: if (pd == null) {
511: ClassLoader cl = this .getClass().getClassLoader();
512: CodeSource cs = new CodeSource(null,
513: (Certificate[]) null);
514: pd = new ProtectionDomain(cs, null, cl,
515: new Principal[] { principals[i] });
516: m_cachedPds.put(principals[i], pd);
517: }
518:
519: // Consult the local policy and get the answer
520: if (m_localPolicy.implies(pd, permission)) {
521: return true;
522: }
523: }
524: return false;
525: }
526:
527: /**
528: * Determines whether a Subject posesses a given "static" Permission as
529: * defined in the security policy file. This method uses standard Java 2
530: * security calls to do its work. Note that the current access control
531: * context's <code>codeBase</code> is effectively <em>this class</em>,
532: * not that of the caller. Therefore, this method will work best when what
533: * matters in the policy is <em>who</em> makes the permission check, not
534: * what the caller's code source is. Internally, this method works by
535: * excuting <code>Subject.doAsPrivileged</code> with a privileged action
536: * that simply calls {@link java.security.AccessController#checkPermission(Permission)}.
537: * @link AccessController#checkPermission(java.security.Permission). A
538: * caught exception (or lack thereof) determines whether the privilege
539: * is absent (or present).
540: * @param session the WikiSession whose permission status is being queried
541: * @param permission the Permission the Subject must possess
542: * @return <code>true</code> if the Subject posesses the permission,
543: * <code>false</code> otherwise
544: */
545: protected final boolean checkStaticPermission(
546: final WikiSession session, final Permission permission) {
547: if (!m_useJAAS)
548: return true;
549:
550: Boolean allowed = (Boolean) WikiSession.doPrivileged(session,
551: new PrivilegedAction() {
552: public Object run() {
553: try {
554: // Check the JVM-wide security policy first
555: AccessController
556: .checkPermission(permission);
557: return Boolean.TRUE;
558: } catch (AccessControlException e) {
559: // Global policy denied the permission
560: }
561:
562: // Try the local policy - check each Role/Group and User Principal
563: if (allowedByLocalPolicy(session.getRoles(),
564: permission)
565: || allowedByLocalPolicy(session
566: .getPrincipals(), permission)) {
567: return Boolean.TRUE;
568: }
569: return Boolean.FALSE;
570: }
571: });
572: return allowed.booleanValue();
573: }
574:
575: /**
576: * <p>Given a supplied string representing a Principal's name from an Acl, this
577: * method resolves the correct type of Principal (role, group, or user).
578: * This method is guaranteed to always return a Principal.
579: * The algorithm is straightforward:</p>
580: * <ol>
581: * <li>If the name matches one of the built-in {@link com.ecyrd.jspwiki.auth.authorize.Role} names,
582: * return that built-in Role</li>
583: * <li>If the name matches one supplied by the current
584: * {@link com.ecyrd.jspwiki.auth.Authorizer}, return that Role</li>
585: * <li>If the name matches a group managed by the
586: * current {@link com.ecyrd.jspwiki.auth.authorize.GroupManager}, return that Group</li>
587: * <li>Otherwise, assume that the name represents a user
588: * principal. Using the current {@link com.ecyrd.jspwiki.auth.user.UserDatabase}, find the
589: * first user who matches the supplied name by calling
590: * {@link com.ecyrd.jspwiki.auth.user.UserDatabase#find(String)}.</li>
591: * <li>Finally, if a user cannot be found, manufacture
592: * and return a generic {@link com.ecyrd.jspwiki.auth.acl.UnresolvedPrincipal}</li>
593: * </ol>
594: * @param name the name of the Principal to resolve
595: * @return the fully-resolved Principal
596: */
597: public final Principal resolvePrincipal(String name) {
598: if (!m_useJAAS) {
599: return new UnresolvedPrincipal(name);
600: }
601:
602: // Check built-in Roles first
603: Role role = new Role(name);
604: if (Role.isBuiltInRole(role)) {
605: return role;
606: }
607:
608: // Check Authorizer Roles
609: Principal principal = m_authorizer.findRole(name);
610: if (principal != null) {
611: return principal;
612: }
613:
614: // Check Groups
615: principal = m_engine.getGroupManager().findRole(name);
616: if (principal != null) {
617: return principal;
618: }
619:
620: // Ok, no luck---this must be a user principal
621: Principal[] principals = null;
622: UserProfile profile = null;
623: UserDatabase db = m_engine.getUserManager().getUserDatabase();
624: try {
625: profile = db.find(name);
626: principals = db.getPrincipals(profile.getLoginName());
627: for (int i = 0; i < principals.length; i++) {
628: principal = principals[i];
629: if (principal.getName().equals(name)) {
630: return principal;
631: }
632: }
633: } catch (NoSuchPrincipalException e) {
634: // We couldn't find the user...
635: }
636: // Ok, no luck---mark this as unresolved and move on
637: return new UnresolvedPrincipal(name);
638: }
639:
640: // events processing .......................................................
641:
642: /**
643: * Registers a WikiEventListener with this instance.
644: * @param listener the event listener
645: */
646: public final synchronized void addWikiEventListener(
647: WikiEventListener listener) {
648: WikiEventManager.addWikiEventListener(this , listener);
649: }
650:
651: /**
652: * Un-registers a WikiEventListener with this instance.
653: * @param listener the event listener
654: */
655: public final synchronized void removeWikiEventListener(
656: WikiEventListener listener) {
657: WikiEventManager.removeWikiEventListener(this , listener);
658: }
659:
660: /**
661: * Fires a WikiSecurityEvent of the provided type, user,
662: * and permission to all registered listeners.
663: *
664: * @see com.ecyrd.jspwiki.event.WikiSecurityEvent
665: * @param type the event type to be fired
666: * @param user the user associated with the event
667: * @param permission the permission the subject must possess
668: */
669: protected final void fireEvent(int type, Principal user,
670: Object permission) {
671: if (WikiEventManager.isListening(this )) {
672: WikiEventManager.fireEvent(this , new WikiSecurityEvent(
673: this, type, user, permission));
674: }
675: }
676:
677: }
|