Source Code Cross Referenced for UserManager.java in  » Wiki-Engine » JSPWiki » com » ecyrd » jspwiki » auth » 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 » Wiki Engine » JSPWiki » com.ecyrd.jspwiki.auth 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:          JSPWiki - a JSP-based WikiWiki clone.
003:
004:          Copyright (C) 2001-2005 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.security.Permission;
023:        import java.security.Principal;
024:        import java.text.MessageFormat;
025:        import java.util.*;
026:
027:        import javax.mail.MessagingException;
028:        import javax.mail.internet.AddressException;
029:        import javax.servlet.http.HttpServletRequest;
030:
031:        import org.apache.log4j.Logger;
032:
033:        import com.ecyrd.jspwiki.*;
034:        import com.ecyrd.jspwiki.auth.permissions.AllPermission;
035:        import com.ecyrd.jspwiki.auth.permissions.WikiPermission;
036:        import com.ecyrd.jspwiki.auth.user.AbstractUserDatabase;
037:        import com.ecyrd.jspwiki.auth.user.DuplicateUserException;
038:        import com.ecyrd.jspwiki.auth.user.UserDatabase;
039:        import com.ecyrd.jspwiki.auth.user.UserProfile;
040:        import com.ecyrd.jspwiki.event.WikiEventListener;
041:        import com.ecyrd.jspwiki.event.WikiEventManager;
042:        import com.ecyrd.jspwiki.event.WikiSecurityEvent;
043:        import com.ecyrd.jspwiki.filters.PageFilter;
044:        import com.ecyrd.jspwiki.filters.SpamFilter;
045:        import com.ecyrd.jspwiki.i18n.InternationalizationManager;
046:        import com.ecyrd.jspwiki.rpc.RPCCallable;
047:        import com.ecyrd.jspwiki.rpc.json.JSONRPCManager;
048:        import com.ecyrd.jspwiki.ui.InputValidator;
049:        import com.ecyrd.jspwiki.util.ClassUtil;
050:        import com.ecyrd.jspwiki.util.MailUtil;
051:        import com.ecyrd.jspwiki.workflow.*;
052:
053:        /**
054:         * Provides a facade for obtaining user information.
055:         * @author Janne Jalkanen
056:         * @author Andrew Jaquith
057:         * @since 2.3
058:         */
059:        public final class UserManager {
060:            private static final String USERDATABASE_PACKAGE = "com.ecyrd.jspwiki.auth.user";
061:            private static final String SESSION_MESSAGES = "profile";
062:            private static final String PARAM_EMAIL = "email";
063:            private static final String PARAM_FULLNAME = "fullname";
064:            private static final String PARAM_PASSWORD = "password";
065:            private static final String PARAM_LOGINNAME = "loginname";
066:            private static final String UNKNOWN_CLASS = "<unknown>";
067:
068:            private WikiEngine m_engine;
069:
070:            private static Logger log = Logger.getLogger(UserManager.class);
071:
072:            /** Message key for the "save profile" message. */
073:            public static final String SAVE_APPROVER = "workflow.createUserProfile";
074:            private static final String PROP_DATABASE = "jspwiki.userdatabase";
075:            protected static final String SAVE_TASK_MESSAGE_KEY = "task.createUserProfile";
076:            protected static final String SAVED_PROFILE = "userProfile";
077:            protected static final String SAVE_DECISION_MESSAGE_KEY = "decision.createUserProfile";
078:            protected static final String FACT_SUBMITTER = "fact.submitter";
079:            protected static final String PREFS_LOGIN_NAME = "prefs.loginname";
080:            protected static final String PREFS_FULL_NAME = "prefs.fullname";
081:            protected static final String PREFS_EMAIL = "prefs.email";
082:
083:            // private static final String  PROP_ACLMANAGER     = "jspwiki.aclManager";
084:
085:            /** Associateds wiki sessions with profiles */
086:            private final Map m_profiles = new WeakHashMap();
087:
088:            /** The user database loads, manages and persists user identities */
089:            private UserDatabase m_database;
090:
091:            private boolean m_useJAAS = true;
092:
093:            /**
094:             * Constructs a new UserManager instance.
095:             */
096:            public UserManager() {
097:            }
098:
099:            /**
100:             * Initializes the engine for its nefarious purposes.
101:             * @param engine the current wiki engine
102:             * @param props the wiki engine initialization properties
103:             */
104:            public final void initialize(WikiEngine engine, Properties props) {
105:                m_engine = engine;
106:
107:                m_useJAAS = AuthenticationManager.SECURITY_JAAS.equals(props
108:                        .getProperty(AuthenticationManager.PROP_SECURITY,
109:                                AuthenticationManager.SECURITY_JAAS));
110:
111:                // Attach the PageManager as a listener
112:                // TODO: it would be better if we did this in PageManager directly
113:                addWikiEventListener(engine.getPageManager());
114:
115:                JSONRPCManager.registerGlobalObject("users",
116:                        new JSONUserModule(), new AllPermission(null));
117:            }
118:
119:            /**
120:             * Returns the UserDatabase employed by this WikiEngine. The UserDatabase is
121:             * lazily initialized by this method, if it does not exist yet. If the
122:             * initialization fails, this method will use the inner class
123:             * DummyUserDatabase as a default (which is enough to get JSPWiki running).
124:             * @return the dummy user database
125:             * @since 2.3
126:             */
127:            public final UserDatabase getUserDatabase() {
128:                // FIXME: Must not throw RuntimeException, but something else.
129:                if (m_database != null) {
130:                    return m_database;
131:                }
132:
133:                if (!m_useJAAS) {
134:                    m_database = new DummyUserDatabase();
135:                    return m_database;
136:                }
137:
138:                String dbClassName = UNKNOWN_CLASS;
139:
140:                try {
141:                    dbClassName = WikiEngine.getRequiredProperty(m_engine
142:                            .getWikiProperties(), PROP_DATABASE);
143:
144:                    log.info("Attempting to load user database class "
145:                            + dbClassName);
146:                    Class dbClass = ClassUtil.findClass(USERDATABASE_PACKAGE,
147:                            dbClassName);
148:                    m_database = (UserDatabase) dbClass.newInstance();
149:                    m_database.initialize(m_engine, m_engine
150:                            .getWikiProperties());
151:                    log.info("UserDatabase initialized.");
152:                } catch (NoRequiredPropertyException e) {
153:                    log
154:                            .error("You have not set the '"
155:                                    + PROP_DATABASE
156:                                    + "'. You need to do this if you want to enable user management by JSPWiki.");
157:                } catch (ClassNotFoundException e) {
158:                    log.error("UserDatabase class " + dbClassName
159:                            + " cannot be found", e);
160:                } catch (InstantiationException e) {
161:                    log.error("UserDatabase class " + dbClassName
162:                            + " cannot be created", e);
163:                } catch (IllegalAccessException e) {
164:                    log
165:                            .error(
166:                                    "You are not allowed to access this user database class",
167:                                    e);
168:                } finally {
169:                    if (m_database == null) {
170:                        log
171:                                .info("I could not create a database object you specified (or didn't specify), so I am falling back to a default.");
172:                        m_database = new DummyUserDatabase();
173:                    }
174:                }
175:
176:                return m_database;
177:            }
178:
179:            /**
180:             * <p>Retrieves the {@link com.ecyrd.jspwiki.auth.user.UserProfile}for the
181:             * user in a wiki session. If the user is authenticated, the UserProfile
182:             * returned will be the one stored in the user database; if one does not
183:             * exist, a new one will be initialized and returned. If the user is
184:             * anonymous or asserted, the UserProfile will <i>always</i> be newly
185:             * initialized to prevent spoofing of identities. If a UserProfile needs to
186:             * be initialized, its
187:             * {@link com.ecyrd.jspwiki.auth.user.UserProfile#isNew()} method will
188:             * return <code>true</code>, and its login name will will be set
189:             * automatically if the user is authenticated. Note that this method does
190:             * not modify the retrieved (or newly created) profile otherwise; other
191:             * fields in the user profile may be <code>null</code>.</p>
192:             * <p>If a new UserProfile was created, but its
193:             * {@link com.ecyrd.jspwiki.auth.user.UserProfile#isNew()} method returns
194:             * <code>false</code>, this method throws an {@link IllegalStateException}.
195:             * This is meant as a quality check for UserDatabase providers;
196:             * it should only be thrown if the implementation is faulty.</p>
197:             * @param session the wiki session, which may not be <code>null</code>
198:             * @return the user's profile, which will be newly initialized if the user
199:             * is anonymous or asserted, or if the user cannot be found in the user
200:             * database
201:             */
202:            public final UserProfile getUserProfile(WikiSession session) {
203:                // Look up cached user profile
204:                UserProfile profile = (UserProfile) m_profiles.get(session);
205:                boolean newProfile = profile == null;
206:                Principal user = null;
207:
208:                // If user is authenticated, figure out if this is an existing profile
209:                if (session.isAuthenticated()) {
210:                    user = session.getUserPrincipal();
211:                    try {
212:                        profile = getUserDatabase().find(user.getName());
213:                        newProfile = false;
214:                    } catch (NoSuchPrincipalException e) {
215:                    }
216:                }
217:
218:                if (newProfile) {
219:                    profile = getUserDatabase().newProfile();
220:                    if (user != null) {
221:                        profile.setLoginName(user.getName());
222:                    }
223:                    if (!profile.isNew()) {
224:                        throw new IllegalStateException(
225:                                "New profile should be marked 'new'. Check your UserProfile implementation.");
226:                    }
227:                }
228:
229:                // Stash the profile for next time
230:                m_profiles.put(session, profile);
231:                return profile;
232:            }
233:
234:            /**
235:             * <p>
236:             * Saves the {@link com.ecyrd.jspwiki.auth.user.UserProfile}for the user in
237:             * a wiki session. This method verifies that a user profile to be saved
238:             * doesn't collide with existing profiles; that is, the login name
239:             * or full name is already used by another profile. If the profile
240:             * collides, a <code>DuplicateUserException</code> is thrown. After saving
241:             * the profile, the user database changes are committed, and the user's
242:             * credential set is refreshed; if custom authentication is used, this means
243:             * the user will be automatically be logged in.
244:             * </p>
245:             * <p>
246:             * When the user's profile is saved succcessfully, this method fires a
247:             * {@link WikiSecurityEvent#PROFILE_SAVE} event with the WikiSession as the
248:             * source and the UserProfile as target. For existing profiles, if the
249:             * user's full name changes, this method also fires a "name changed"
250:             * event ({@link WikiSecurityEvent#PROFILE_NAME_CHANGED}) with the
251:             * WikiSession as the source and an array containing the old and new
252:             * UserProfiles, respectively. The <code>NAME_CHANGED</code> event allows
253:             * the GroupManager and PageManager can change group memberships and
254:             * ACLs if needed.
255:             * </p>
256:             * <p>
257:             * Note that WikiSessions normally attach event listeners to the
258:             * UserManager, so changes to the profile will automatically cause the
259:             * correct Principals to be reloaded into the current WikiSession's Subject.
260:             * </p>
261:             * @param session the wiki session, which may not be <code>null</code>
262:             * @param profile the user profile, which may not be <code>null</code>
263:             * @throws DuplicateUserException if the proposed profile's login name or full name collides with another
264:             * @throws WikiException if the save fails for some reason. If the current user does not have
265:             * permission to save the profile, this will be a {@link com.ecyrd.jspwiki.auth.WikiSecurityException};
266:             * if if the user profile must be approved before it can be saved, it will be a
267:             * {@link com.ecyrd.jspwiki.workflow.DecisionRequiredException}. All other WikiException
268:             * indicate a condition that is not normal is probably due to mis-configuration
269:             */
270:            public final void setUserProfile(WikiSession session,
271:                    UserProfile profile) throws DuplicateUserException,
272:                    WikiException {
273:                // Verify user is allowed to save profile!
274:                Permission p = new WikiPermission(
275:                        m_engine.getApplicationName(),
276:                        WikiPermission.EDIT_PROFILE_ACTION);
277:                if (!m_engine.getAuthorizationManager().checkPermission(
278:                        session, p)) {
279:                    throw new WikiSecurityException(
280:                            "You are not allowed to save wiki profiles.");
281:                }
282:
283:                // Check if profile is new, and see if container allows creation
284:                boolean newProfile = profile.isNew();
285:
286:                // Check if another user profile already has the fullname or loginname
287:                UserProfile oldProfile = getUserProfile(session);
288:                boolean nameChanged = (oldProfile == null || oldProfile
289:                        .getFullname() == null) ? false
290:                        : !(oldProfile.getFullname().equals(
291:                                profile.getFullname()) && oldProfile
292:                                .getLoginName().equals(profile.getLoginName()));
293:                UserProfile otherProfile;
294:                try {
295:                    otherProfile = getUserDatabase().findByLoginName(
296:                            profile.getLoginName());
297:                    if (otherProfile != null
298:                            && !otherProfile.equals(oldProfile)) {
299:                        throw new DuplicateUserException("The login name '"
300:                                + profile.getLoginName()
301:                                + "' is already taken.");
302:                    }
303:                } catch (NoSuchPrincipalException e) {
304:                }
305:                try {
306:                    otherProfile = getUserDatabase().findByFullName(
307:                            profile.getFullname());
308:                    if (otherProfile != null
309:                            && !otherProfile.equals(oldProfile)) {
310:                        throw new DuplicateUserException("The full name '"
311:                                + profile.getFullname() + "' is already taken.");
312:                    }
313:                } catch (NoSuchPrincipalException e) {
314:                }
315:
316:                // For new accounts, create approval workflow for user profile save.
317:                if (newProfile && oldProfile != null && oldProfile.isNew()) {
318:                    WorkflowBuilder builder = WorkflowBuilder
319:                            .getBuilder(m_engine);
320:                    Principal submitter = session.getUserPrincipal();
321:                    Task completionTask = new SaveUserProfileTask(m_engine);
322:
323:                    // Add user profile attribute as Facts for the approver (if required)
324:                    boolean hasEmail = profile.getEmail() != null;
325:                    Fact[] facts = new Fact[hasEmail ? 4 : 3];
326:                    facts[0] = new Fact(PREFS_FULL_NAME, profile.getFullname());
327:                    facts[1] = new Fact(PREFS_LOGIN_NAME, profile
328:                            .getLoginName());
329:                    facts[2] = new Fact(FACT_SUBMITTER, submitter.getName());
330:                    if (hasEmail) {
331:                        facts[3] = new Fact(PREFS_EMAIL, profile.getEmail());
332:                    }
333:                    Workflow workflow = builder.buildApprovalWorkflow(
334:                            submitter, SAVE_APPROVER, null,
335:                            SAVE_DECISION_MESSAGE_KEY, facts, completionTask,
336:                            null);
337:
338:                    workflow.setAttribute(SAVED_PROFILE, profile);
339:                    m_engine.getWorkflowManager().start(workflow);
340:
341:                    boolean approvalRequired = workflow.getCurrentStep() instanceof  Decision;
342:
343:                    // If the profile requires approval, redirect user to message page
344:                    if (approvalRequired) {
345:                        throw new DecisionRequiredException(
346:                                "This profile must be approved before it becomes active");
347:                    }
348:
349:                    // If the profile doesn't need approval, then just log the user in
350:
351:                    try {
352:                        AuthenticationManager mgr = m_engine
353:                                .getAuthenticationManager();
354:                        if (newProfile && !mgr.isContainerAuthenticated()) {
355:                            mgr.login(session, profile.getLoginName(), profile
356:                                    .getPassword());
357:                        }
358:                    } catch (WikiException e) {
359:                        throw new WikiSecurityException(e.getMessage());
360:                    }
361:
362:                    // Alert all listeners that the profile changed...
363:                    // ...this will cause credentials to be reloaded in the wiki session
364:                    fireEvent(WikiSecurityEvent.PROFILE_SAVE, session, profile);
365:                }
366:
367:                // For existing accounts, just save the profile
368:                else {
369:                    // If login name changed, rename it first
370:                    if (nameChanged
371:                            && oldProfile != null
372:                            && !oldProfile.getLoginName().equals(
373:                                    profile.getLoginName())) {
374:                        getUserDatabase().rename(oldProfile.getLoginName(),
375:                                profile.getLoginName());
376:                    }
377:
378:                    // Now, save the profile (userdatabase will take care of timestamps for us)
379:                    getUserDatabase().save(profile);
380:
381:                    if (nameChanged) {
382:                        // Fire an event if the login name or full name changed
383:                        UserProfile[] profiles = new UserProfile[] {
384:                                oldProfile, profile };
385:                        fireEvent(WikiSecurityEvent.PROFILE_NAME_CHANGED,
386:                                session, profiles);
387:                    } else {
388:                        // Fire an event that says we have new a new profile (new principals)
389:                        fireEvent(WikiSecurityEvent.PROFILE_SAVE, session,
390:                                profile);
391:                    }
392:                }
393:            }
394:
395:            /**
396:             * <p> Extracts user profile parameters from the HTTP request and populates
397:             * a UserProfile with them. The UserProfile will either be a copy of the
398:             * user's existing profile (if one can be found), or a new profile (if not).
399:             * The rules for populating the profile as as follows: </p> <ul> <li>If the
400:             * <code>email</code> or <code>password</code> parameter values differ
401:             * from those in the existing profile, the passed parameters override the
402:             * old values.</li> <li>For new profiles, the user-supplied
403:             * <code>fullname</code parameter is always
404:             * used; for existing profiles the existing value is used, and whatever
405:             * value the user supplied is discarded. The wiki name is automatically
406:             * computed by taking the full name and extracting all whitespace.</li>
407:             * <li>In all cases, the
408:             * created/last modified timestamps of the user's existing or new profile
409:             * always override whatever values the user supplied.</li> <li>If
410:             * container authentication is used, the login name property of the profile
411:             * is set to the name of
412:             * {@link com.ecyrd.jspwiki.WikiSession#getLoginPrincipal()}. Otherwise,
413:             * the value of the <code>loginname</code> parameter is used.</li> </ul>
414:             * @param context the current wiki context
415:             * @return a new, populated user profile
416:             */
417:            public final UserProfile parseProfile(WikiContext context) {
418:                // Retrieve the user's profile (may have been previously cached)
419:                UserProfile profile = getUserProfile(context.getWikiSession());
420:                HttpServletRequest request = context.getHttpRequest();
421:
422:                // Extract values from request stream (cleanse whitespace as needed)
423:                String loginName = request.getParameter(PARAM_LOGINNAME);
424:                String password = request.getParameter(PARAM_PASSWORD);
425:                String fullname = request.getParameter(PARAM_FULLNAME);
426:                String email = request.getParameter(PARAM_EMAIL);
427:                loginName = InputValidator.isBlank(loginName) ? null
428:                        : loginName;
429:                password = InputValidator.isBlank(password) ? null : password;
430:                fullname = InputValidator.isBlank(fullname) ? null : fullname;
431:                email = InputValidator.isBlank(email) ? null : email;
432:
433:                // A special case if we have container authentication
434:                if (m_engine.getAuthenticationManager()
435:                        .isContainerAuthenticated()) {
436:                    // If authenticated, login name is always taken from container
437:                    if (context.getWikiSession().isAuthenticated()) {
438:                        loginName = context.getWikiSession()
439:                                .getLoginPrincipal().getName();
440:                    }
441:                }
442:
443:                // Set the profile fields!
444:                profile.setLoginName(loginName);
445:                profile.setEmail(email);
446:                profile.setFullname(fullname);
447:                profile.setPassword(password);
448:                return profile;
449:            }
450:
451:            /**
452:             * Validates a user profile, and appends any errors to the session errors
453:             * list. If the profile is new, the password will be checked to make sure it
454:             * isn't null. Otherwise, the password is checked for length and that it
455:             * matches the value of the 'password2' HTTP parameter. Note that we have a
456:             * special case when container-managed authentication is used and the user
457:             * is not authenticated; this will always cause validation to fail. Any
458:             * validation errors are added to the wiki session's messages collection
459:             * (see {@link WikiSession#getMessages()}.
460:             * @param context the current wiki context
461:             * @param profile the supplied UserProfile
462:             */
463:            public final void validateProfile(WikiContext context,
464:                    UserProfile profile) {
465:                boolean isNew = profile.isNew();
466:                WikiSession session = context.getWikiSession();
467:                InputValidator validator = new InputValidator(SESSION_MESSAGES,
468:                        session);
469:                ResourceBundle rb = context
470:                        .getBundle(InternationalizationManager.CORE_BUNDLE);
471:
472:                //
473:                //  Query the SpamFilter first
474:                //
475:
476:                List ls = m_engine.getFilterManager().getFilterList();
477:                for (Iterator i = ls.iterator(); i.hasNext();) {
478:                    PageFilter pf = (PageFilter) i.next();
479:
480:                    if (pf instanceof  SpamFilter) {
481:                        if (((SpamFilter) pf).isValidUserProfile(context,
482:                                profile) == false) {
483:                            session.addMessage(SESSION_MESSAGES,
484:                                    "Invalid userprofile");
485:                            return;
486:                        }
487:                        break;
488:                    }
489:                }
490:
491:                // If container-managed auth and user not logged in, throw an error
492:                // unless we're allowed to add profiles to the container
493:                if (m_engine.getAuthenticationManager()
494:                        .isContainerAuthenticated()
495:                        && !context.getWikiSession().isAuthenticated()
496:                        && !getUserDatabase().isSharedWithContainer()) {
497:                    session
498:                            .addMessage(
499:                                    SESSION_MESSAGES,
500:                                    rb
501:                                            .getString("security.error.createprofilebeforelogin"));
502:                }
503:
504:                validator.validateNotNull(profile.getLoginName(), rb
505:                        .getString("security.user.loginname"));
506:                validator.validateNotNull(profile.getFullname(), rb
507:                        .getString("security.user.fullname"));
508:                validator
509:                        .validate(profile.getEmail(), rb
510:                                .getString("security.user.email"),
511:                                InputValidator.EMAIL);
512:
513:                // If new profile, passwords must match and can't be null
514:                if (!m_engine.getAuthenticationManager()
515:                        .isContainerAuthenticated()) {
516:                    String password = profile.getPassword();
517:                    if (password == null) {
518:                        if (isNew) {
519:                            session.addMessage(SESSION_MESSAGES, rb
520:                                    .getString("security.error.blankpassword"));
521:                        }
522:                    } else {
523:                        HttpServletRequest request = context.getHttpRequest();
524:                        String password2 = (request == null) ? null : request
525:                                .getParameter("password2");
526:                        if (!password.equals(password2)) {
527:                            session
528:                                    .addMessage(
529:                                            SESSION_MESSAGES,
530:                                            rb
531:                                                    .getString("security.error.passwordnomatch"));
532:                        }
533:                    }
534:                }
535:
536:                UserProfile otherProfile;
537:                String fullName = profile.getFullname();
538:                String loginName = profile.getLoginName();
539:
540:                // It's illegal to use as a full name someone else's login name
541:                try {
542:                    otherProfile = getUserDatabase().find(fullName);
543:                    if (otherProfile != null && !profile.equals(otherProfile)
544:                            && !fullName.equals(otherProfile.getFullname())) {
545:                        Object[] args = { fullName };
546:                        session
547:                                .addMessage(
548:                                        SESSION_MESSAGES,
549:                                        MessageFormat
550:                                                .format(
551:                                                        rb
552:                                                                .getString("security.error.illegalfullname"),
553:                                                        args));
554:                    }
555:                } catch (NoSuchPrincipalException e) { /* It's clean */
556:                }
557:
558:                // It's illegal to use as a login name someone else's full name
559:                try {
560:                    otherProfile = getUserDatabase().find(loginName);
561:                    if (otherProfile != null && !profile.equals(otherProfile)
562:                            && !loginName.equals(otherProfile.getLoginName())) {
563:                        Object[] args = { loginName };
564:                        session
565:                                .addMessage(
566:                                        SESSION_MESSAGES,
567:                                        MessageFormat
568:                                                .format(
569:                                                        rb
570:                                                                .getString("security.error.illegalloginname"),
571:                                                        args));
572:                    }
573:                } catch (NoSuchPrincipalException e) { /* It's clean */
574:                }
575:            }
576:
577:            public Principal[] listWikiNames() throws WikiSecurityException {
578:                return getUserDatabase().getWikiNames();
579:            }
580:
581:            /**
582:             * This is a database that gets used if nothing else is available. It does
583:             * nothing of note - it just mostly thorws NoSuchPrincipalExceptions if
584:             * someone tries to log in.
585:             * @author Janne Jalkanen
586:             */
587:            public static class DummyUserDatabase extends AbstractUserDatabase {
588:
589:                /**
590:                 * No-op.
591:                 * @throws WikiSecurityException never...
592:                 */
593:                public void commit() throws WikiSecurityException {
594:                    // No operation
595:                }
596:
597:                /**
598:                 * No-op.
599:                 * @param loginName the login name to delete
600:                 * @throws WikiSecurityException never...
601:                 */
602:                public void deleteByLoginName(String loginName)
603:                        throws WikiSecurityException {
604:                    // No operation
605:                }
606:
607:                /**
608:                 * No-op; always throws <code>NoSuchPrincipalException</code>.
609:                 * @param index the name to search for
610:                 * @return the user profile
611:                 * @throws NoSuchPrincipalException never...
612:                 */
613:                public UserProfile findByEmail(String index)
614:                        throws NoSuchPrincipalException {
615:                    throw new NoSuchPrincipalException(
616:                            "No user profiles available");
617:                }
618:
619:                /**
620:                 * No-op; always throws <code>NoSuchPrincipalException</code>.
621:                 * @param index the name to search for
622:                 * @return the user profile
623:                 * @throws NoSuchPrincipalException never...
624:                 */
625:                public UserProfile findByFullName(String index)
626:                        throws NoSuchPrincipalException {
627:                    throw new NoSuchPrincipalException(
628:                            "No user profiles available");
629:                }
630:
631:                /**
632:                 * No-op; always throws <code>NoSuchPrincipalException</code>.
633:                 * @param index the name to search for
634:                 * @return the user profile
635:                 * @throws NoSuchPrincipalException never...
636:                 */
637:                public UserProfile findByLoginName(String index)
638:                        throws NoSuchPrincipalException {
639:                    throw new NoSuchPrincipalException(
640:                            "No user profiles available");
641:                }
642:
643:                /**
644:                 * No-op; always throws <code>NoSuchPrincipalException</code>.
645:                 * @param index the name to search for
646:                 * @return the user profile
647:                 * @throws NoSuchPrincipalException never...
648:                 */
649:                public UserProfile findByWikiName(String index)
650:                        throws NoSuchPrincipalException {
651:                    throw new NoSuchPrincipalException(
652:                            "No user profiles available");
653:                }
654:
655:                /**
656:                 * No-op.
657:                 * @return a zero-length array
658:                 * @throws WikiSecurityException never...
659:                 */
660:                public Principal[] getWikiNames() throws WikiSecurityException {
661:                    return new Principal[0];
662:                }
663:
664:                /**
665:                 * No-op.
666:                 * @param engine the wiki engine
667:                 * @param props the properties used to initialize the wiki engine
668:                 * @throws NoRequiredPropertyException never...
669:                 */
670:                public void initialize(WikiEngine engine, Properties props)
671:                        throws NoRequiredPropertyException {
672:                }
673:
674:                /**
675:                 * No-op.
676:                 * @return <code>false</code>
677:                 */
678:                public boolean isSharedWithContainer() {
679:                    return false;
680:                }
681:
682:                /**
683:                 * No-op; always throws <code>NoSuchPrincipalException</code>.
684:                 * @param loginName the login name
685:                 * @param newName the proposed new login name
686:                 * @throws DuplicateUserException never...
687:                 * @throws WikiSecurityException never...
688:                 */
689:                public void rename(String loginName, String newName)
690:                        throws DuplicateUserException, WikiSecurityException {
691:                    throw new NoSuchPrincipalException(
692:                            "No user profiles available");
693:                }
694:
695:                /**
696:                 * No-op.
697:                 * @param profile the user profile
698:                 * @throws WikiSecurityException never...
699:                 */
700:                public void save(UserProfile profile)
701:                        throws WikiSecurityException {
702:                }
703:
704:            }
705:
706:            // workflow task inner classes....................................................
707:
708:            /**
709:             * Inner class that handles the actual profile save action. Instances
710:             * of this class are assumed to have been added to an approval workflow via
711:             * {@link com.ecyrd.jspwiki.workflow.WorkflowBuilder#buildApprovalWorkflow(Principal, String, Task, String, com.ecyrd.jspwiki.workflow.Fact[], Task, String)};
712:             * they will not function correctly otherwise.
713:             *
714:             * @author Andrew Jaquith
715:             */
716:            public static class SaveUserProfileTask extends Task {
717:                private final UserDatabase m_db;
718:                private final WikiEngine m_engine;
719:
720:                /**
721:                 * Constructs a new Task for saving a user profile.
722:                 * @param engine the wiki engine
723:                 */
724:                public SaveUserProfileTask(WikiEngine engine) {
725:                    super (SAVE_TASK_MESSAGE_KEY);
726:                    m_engine = engine;
727:                    m_db = engine.getUserManager().getUserDatabase();
728:                }
729:
730:                /**
731:                 * Saves the user profile to the user database.
732:                 * @return {@link com.ecyrd.jspwiki.workflow.Outcome#STEP_COMPLETE} if the
733:                 * task completed successfully
734:                 * @throws WikiException if the save did not complete for some reason
735:                 */
736:                public Outcome execute() throws WikiException {
737:                    // Retrieve user profile
738:                    UserProfile profile = (UserProfile) getWorkflow()
739:                            .getAttribute(SAVED_PROFILE);
740:
741:                    // Save the profile (userdatabase will take care of timestamps for us)
742:                    m_db.save(profile);
743:
744:                    // Send e-mail if user supplied an e-mail address
745:                    if (profile.getEmail() != null) {
746:                        try {
747:                            String app = m_engine.getApplicationName();
748:                            String to = profile.getEmail();
749:                            String subject = "Welcome to " + app;
750:                            String content = "Congratulations! Your new profile on "
751:                                    + app
752:                                    + " has been created. Your profile details are as follows: \n\n"
753:                                    + "Login name: "
754:                                    + profile.getLoginName()
755:                                    + "\n"
756:                                    + "Your name : "
757:                                    + profile.getFullname()
758:                                    + "\n"
759:                                    + "E-mail    : "
760:                                    + profile.getEmail()
761:                                    + "\n\n"
762:                                    + "If you forget your password, you can reset it at "
763:                                    + m_engine.getURL(WikiContext.LOGIN, null,
764:                                            null, true);
765:                            MailUtil
766:                                    .sendMessage(m_engine, to, subject, content);
767:                        } catch (AddressException e) {
768:                        } catch (MessagingException e) {
769:                            log
770:                                    .error("Could not send registration confirmation e-mail. Is the e-mail server running?");
771:                        }
772:                    }
773:
774:                    return Outcome.STEP_COMPLETE;
775:                }
776:            }
777:
778:            // events processing .......................................................
779:
780:            /**
781:             * Registers a WikiEventListener with this instance.
782:             * This is a convenience method.
783:             * @param listener the event listener
784:             */
785:            public final synchronized void addWikiEventListener(
786:                    WikiEventListener listener) {
787:                WikiEventManager.addWikiEventListener(this , listener);
788:            }
789:
790:            /**
791:             * Un-registers a WikiEventListener with this instance.
792:             * This is a convenience method.
793:             * @param listener the event listener
794:             */
795:            public final synchronized void removeWikiEventListener(
796:                    WikiEventListener listener) {
797:                WikiEventManager.removeWikiEventListener(this , listener);
798:            }
799:
800:            /**
801:             *  Fires a WikiSecurityEvent of the provided type, Principal and target Object
802:             *  to all registered listeners.
803:             *
804:             * @see com.ecyrd.jspwiki.event.WikiSecurityEvent
805:             * @param type       the event type to be fired
806:             * @param session    the wiki session supporting the event
807:             * @param profile    the user profile (or array of user profiles), which may be <code>null</code>
808:             */
809:            protected final void fireEvent(int type, WikiSession session,
810:                    Object profile) {
811:                if (WikiEventManager.isListening(this )) {
812:                    WikiEventManager.fireEvent(this , new WikiSecurityEvent(
813:                            session, type, profile));
814:                }
815:            }
816:
817:            /**
818:             *  Implements the JSON API for usermanager.
819:             *
820:             *  @author Janne Jalkanen
821:             */
822:            public final class JSONUserModule implements  RPCCallable {
823:                /**
824:                 *  Directly returns the UserProfile object attached to an uid.
825:                 *
826:                 *  @param uid The user id (e.g. WikiName)
827:                 *  @return A UserProfile object
828:                 *  @throws NoSuchPrincipalException If such a name does not exist.
829:                 */
830:                public UserProfile getUserInfo(String uid)
831:                        throws NoSuchPrincipalException {
832:                    log.info("request " + uid);
833:                    UserProfile prof = getUserDatabase().find(uid);
834:
835:                    log.info("answer " + prof);
836:
837:                    return prof;
838:                }
839:            }
840:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.