View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.administration;
18  
19  import java.io.FileReader;
20  import java.io.StringWriter;
21  import java.security.Principal;
22  import java.security.PrivilegedAction;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.prefs.Preferences;
29  
30  import javax.portlet.PortletConfig;
31  import javax.portlet.PortletRequest;
32  import javax.portlet.PortletResponse;
33  
34  import org.apache.commons.configuration.Configuration;
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.apache.jetspeed.Jetspeed;
38  import org.apache.jetspeed.PortalReservedParameters;
39  import org.apache.jetspeed.exception.JetspeedException;
40  import org.apache.jetspeed.om.folder.Folder;
41  import org.apache.jetspeed.om.folder.FolderNotFoundException;
42  import org.apache.jetspeed.om.folder.InvalidFolderException;
43  import org.apache.jetspeed.page.PageManager;
44  import org.apache.jetspeed.page.document.NodeException;
45  import org.apache.jetspeed.prefs.PreferencesProvider;
46  import org.apache.jetspeed.prefs.om.Node;
47  import org.apache.jetspeed.profiler.Profiler;
48  import org.apache.jetspeed.profiler.rules.ProfilingRule;
49  import org.apache.jetspeed.request.RequestContext;
50  import org.apache.jetspeed.security.GroupManager;
51  import org.apache.jetspeed.security.JSSubject;
52  import org.apache.jetspeed.security.RoleManager;
53  import org.apache.jetspeed.security.SecurityHelper;
54  import org.apache.jetspeed.security.User;
55  import org.apache.jetspeed.security.UserManager;
56  import org.apache.jetspeed.security.UserPrincipal;
57  import org.apache.velocity.VelocityContext;
58  import org.apache.velocity.app.VelocityEngine;
59  import org.springframework.mail.MailException;
60  import org.springframework.mail.SimpleMailMessage;
61  import org.springframework.mail.javamail.JavaMailSender;
62  
63  /***
64   * PortalAdministrationImpl
65   * Implements aggregate portal administration functions:
66   *  - Emails
67   *  - Registration
68   *  - Password Generation
69   *  - 
70   * 
71   * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
72   * @author <a href="mailto:chris@bluesunrise.com">Chris Schaefer</a>
73   * @version $Id: $
74   */
75  
76  public class PortalAdministrationImpl implements PortalAdministration
77  {
78      private final static Log log = LogFactory.getLog(PortalAdministrationImpl.class);
79      
80      /*** administration services */
81      protected Configuration config;
82      protected UserManager userManager;
83      protected RoleManager roleManager;
84      protected GroupManager groupManager;
85      protected PageManager pageManager;
86      private PreferencesProvider preferences;    
87      protected Profiler profiler;
88      protected JavaMailSender mailSender;
89      protected VelocityEngine velocityEngine;
90      protected AdminUtil adminUtil;
91      
92      /*** list of default roles for a registered user */
93      protected List defaultRoles;
94      /*** list of default groups for a registered user */
95      protected List defaultGroups;
96      /*** map of default profiling rules for a registered user */
97      protected Map defaultRules;
98      /*** name of PSML Folder Template to clone from when registering new user */
99      protected String folderTemplate;
100     /*** default administrative user */
101     protected String adminUser;
102         
103     public PortalAdministrationImpl( UserManager userManager,
104                                      RoleManager roleManager,
105                                      GroupManager groupManager, 
106                                      PageManager pageManager,
107                                      PreferencesProvider preferences,
108                                      Profiler profiler,
109                                      JavaMailSender mailSender,
110                                      VelocityEngine velocityEngine)
111     {
112         this.userManager = userManager;
113         this.roleManager = roleManager;
114         this.groupManager = groupManager;
115         this.pageManager = pageManager;
116         this.preferences = preferences;
117         this.profiler = profiler;
118         this.mailSender = mailSender;
119         this.velocityEngine = velocityEngine;
120         this.adminUtil = new AdminUtil();
121     }
122 
123     public void start()
124     {
125         this.config = (Configuration) Jetspeed.getComponentManager().getComponent("portal_configuration");
126         
127         this.defaultRoles = 
128             config.getList(PortalConfigurationConstants.REGISTRATION_ROLES_DEFAULT);
129         this.defaultGroups = 
130             config.getList(PortalConfigurationConstants.REGISTRATION_GROUPS_DEFAULT);
131     
132         Object[] profileRuleNames = config.getList(PortalConfigurationConstants.PROFILER_RULE_NAMES_DEFAULT).toArray();
133         Object[] profileRuleValues = config.getList(PortalConfigurationConstants.PROFILER_RULE_VALUES_DEFAULT).toArray();
134         defaultRules = new HashMap();
135         if (profileRuleNames != null && profileRuleValues != null)
136         {
137             for (int ix = 0; ix < ((profileRuleNames.length < profileRuleValues.length) ? profileRuleNames.length : profileRuleValues.length); ix++)
138             {
139                 defaultRules.put(profileRuleNames[ix], profileRuleValues[ix]);
140             }
141         }
142         this.folderTemplate = 
143             config.getString(PortalConfigurationConstants.PSML_TEMPLATE_FOLDER);
144         this.adminUser = config.getString(PortalConfigurationConstants.USERS_DEFAULT_ADMIN);
145         
146     }
147     
148     public void registerUser(String userName, String password)
149     throws RegistrationException
150     {
151         registerUser(userName, password, (List)null, null, null, null, null);
152     }
153 
154     public void registerUser(
155             String userName, 
156             String password, 
157             List roles, 
158             List groups, 
159             Map userInfo, 
160             Map rules, 
161             String folderTemplate)
162     throws RegistrationException    
163     {
164         registerUser(userName, password, roles, groups, userInfo, rules, folderTemplate, null);
165     }
166     
167     /* (non-Javadoc)
168      * @see org.apache.jetspeed.administration.PortalAdministration#registerUser(java.lang.String, java.lang.String, java.util.Map, java.awt.List, java.awt.List, java.lang.String)
169      */    
170     public void registerUser(
171             String userName, 
172             String password, 
173             List roles, 
174             List groups, 
175             Map userInfo, 
176             Map rules, 
177             String folderTemplate,
178             String subsite)
179     throws RegistrationException    
180     {
181         try 
182         {
183             // create the user
184             userManager.addUser(userName, password);
185             User user = userManager.getUser(userName);
186                         
187             // assign roles to user
188             if (roles == null || roles.isEmpty())
189             {
190                 roles = this.defaultRoles;
191             }
192             if (roles != null)
193             {
194                 Iterator roleList = roles.iterator();
195                 while (roleList.hasNext())
196                 {
197                     String role = (String)roleList.next();
198                     if (role.trim().length() > 0)
199                         roleManager.addRoleToUser(userName, role);
200                 }
201             }
202             
203             // assign groups to user
204             if (groups == null || groups.isEmpty())
205             {
206                 groups = this.defaultGroups;
207             }
208             if (groups != null)
209             {
210                 Iterator groupsList = groups.iterator();
211                 while (groupsList.hasNext())
212                 {
213                     String group = (String)groupsList.next();
214                     if (group.trim().length() > 0)
215                     {
216                         groupManager.addUserToGroup(userName, group);
217                     }
218                 }
219             }
220             
221             // assign user attributes to user
222             if (userInfo != null)
223             {
224                 Iterator info = userInfo.entrySet().iterator();
225                 while (info.hasNext())
226                 {           
227                     Map.Entry entry = (Map.Entry)info.next();
228                     user.getUserAttributes().put((String)entry.getKey(), (String)entry.getValue());
229                 }
230             }
231             
232             // assign profiling rules to user
233             if (rules == null || rules.isEmpty())
234             {
235                 rules = this.defaultRules;
236             }
237             if (rules != null)
238             {
239                 Iterator ruleEntries = rules.entrySet().iterator();
240                 while (ruleEntries.hasNext())
241                 {           
242                     Map.Entry entry = (Map.Entry)ruleEntries.next();                    
243                     ProfilingRule rule = profiler.getRule((String)entry.getValue());
244                     if (rule != null)
245                     {
246                         Principal principal = SecurityHelper.getBestPrincipal(user.getSubject(), UserPrincipal.class);
247                         profiler.setRuleForPrincipal(principal, rule, (String)entry.getKey());
248                     }
249                 }
250             }
251             
252             if (folderTemplate == null)
253             {
254                 folderTemplate = this.folderTemplate; 
255             }
256             
257             if (subsite == null)
258             {
259                 subsite = Folder.USER_FOLDER + userName;
260             }
261             else
262             {
263                 subsite  = subsite + Folder.USER_FOLDER +  userName;
264             }            
265             
266             
267             // This next chunk of code is the fancy way to force the creation of the user
268             // template pages to be created with subject equal to the new user
269             // otherwise it would be created as guest, and guest does not have enough privs.
270             final String innerFolderTemplate = folderTemplate;
271             final String innerSubsite = subsite;
272             final PageManager innerPageManager = pageManager;
273             final String innerUserName = userName;
274             final User innerUser = user;
275             User powerUser = userManager.getUser(this.adminUser);
276             JetspeedException pe = (JetspeedException) JSSubject.doAsPrivileged(powerUser.getSubject(), new PrivilegedAction()
277                 {
278                     public Object run() 
279                     {
280                          try
281                         {
282                              if (innerSubsite != null)
283                              {
284                                  Preferences attributes = innerUser.getUserAttributes();
285                                  attributes.put(User.USER_INFO_SUBSITE, innerSubsite);                                    
286                              }                                         
287                              // create user's home folder                        
288                              // deep copy from the default folder template tree, creating a deep-copy of the template
289                              // in the new user's folder tree
290                             Folder source = innerPageManager.getFolder(innerFolderTemplate);
291                             
292                             
293                             innerPageManager.deepCopyFolder(source, innerSubsite, innerUserName);
294                             Folder newFolder = pageManager.getFolder(innerSubsite);                            
295                             newFolder.setTitle("Home Folder");
296                             newFolder.setShortTitle("Home");
297                              
298                             return null;
299                         }
300                          catch (FolderNotFoundException e1) {
301                              return e1;
302                          } catch (InvalidFolderException e1){
303                              return e1;
304                          } catch (NodeException e1){
305                              return e1;
306                          }
307                     }
308                 }, null);
309                 
310             if(pe != null)
311             {
312                 // rollback user creation and cascade roles, groups, etc
313                 try
314                 {
315                     if (userManager.getUser(userName) != null)
316                     {
317                         userManager.removeUser(userName);
318                     }
319                 }
320                 catch (Exception e)
321                 {
322                     log.error("Registration Error: Failed to rollback user " + userName);
323                 }
324                 log.error("Registration Error: Failed to create user folders for " + userName + ", " + pe.toString());
325                 throw pe;
326             }
327                         
328         }
329         catch (Exception e) 
330         {
331             log.error("Registration Error: Failed to create registered user " + userName + ", " + e.toString());
332             throw new RegistrationException(e); 
333         }        
334     }
335     
336     
337     /* (non-Javadoc)
338      * @see org.apache.jetspeed.administration.PortalAdministration#generatePassword()
339      */
340     public String generatePassword()
341     {
342         return adminUtil.generatePassword();
343     }
344 
345     /* (non-Javadoc)
346      * @see org.apache.jetspeed.administration.PortalAdministration#sendPassword(java.lang.String)
347      */
348     public void sendEmail(PortletConfig  portletConfig,
349                           String emailAddress, 
350                           String localizedSubject, 
351                           String localizedTemplatePath,
352                           Map userAttributes)                            
353     throws AdministrationEmailException    
354     {       
355         
356         String from = config.getString(PortalConfigurationConstants.EMAIL_SENDER);
357         String subject = localizedSubject;
358         String to = emailAddress;
359         String text = mergeEmailTemplate(portletConfig, userAttributes, "map", localizedTemplatePath);
360         sendEmail(from, subject, to, text);
361         
362     }
363     
364     /***
365      * @param from
366      * @param subject
367      * @param to
368      * @param text
369      * @throws AdministrationEmailException
370      */
371     public void sendEmail(String from, String subject, String to, String text) throws AdministrationEmailException
372     {
373         SimpleMailMessage msg = new SimpleMailMessage();
374         if(from == null) 
375         {
376             from = "jetspeed-admin@apache.org";
377         }
378         msg.setFrom(from);
379         if(subject == null) 
380         {
381             subject = "message from jetspeed";
382         }
383         msg.setSubject(subject);
384         msg.setTo(to);
385         msg.setText(text);
386         try
387         {
388             mailSender.send(msg);
389         } 
390         catch (MailException ex)
391         {
392             throw new AdministrationEmailException(
393                     "Failed to send forgotten password email to user with email address because "+ex.getMessage()
394                             ); //+ user.getEmail());
395         }
396     }
397     
398     public String mergeEmailTemplate(PortletConfig  portletConfig, Map attributes, String attributesName, String template)
399     throws AdministrationEmailException
400     {
401         VelocityContext context = new VelocityContext();
402         context.put(attributesName, attributes);
403         StringWriter writer = new StringWriter();
404         
405         try
406         {
407             String realTemplatePath = portletConfig.getPortletContext().getRealPath(template);
408             FileReader templateReader = new FileReader(realTemplatePath);
409             velocityEngine.evaluate(context, writer, "UserEmailProcessor", templateReader);
410         } catch (Exception e)
411         {
412             throw new AdministrationEmailException(
413                     "Failed to generate email text for email template "
414                             + template, e);
415         }
416         
417         String buffer = writer.getBuffer().toString();
418         
419         return buffer;
420     }
421     
422     private static final String USER_NOT_FOUND_FROM_EMAIL = "User not found for Email address: ";
423     
424     public User lookupUserFromEmail(String email)
425         throws AdministrationEmailException    
426     {
427         Collection result = preferences.lookupPreference("userinfo", "user.business-info.online.email", email);
428         if (result.size() == 0)
429         {
430             throw new AdministrationEmailException(USER_NOT_FOUND_FROM_EMAIL + email);
431         }
432         Iterator nodes = result.iterator();
433         Node node = (Node)nodes.next();
434         String nodePath = node.getFullPath();
435         if (nodePath == null)
436         {
437             throw new AdministrationEmailException(USER_NOT_FOUND_FROM_EMAIL + email);
438         }
439         String[] paths = nodePath.split("/");
440         if (paths == null || paths.length != 4)
441         {
442             throw new AdministrationEmailException(USER_NOT_FOUND_FROM_EMAIL + email);
443         }
444         String userName = paths[2];
445         try
446         {
447             return userManager.getUser(userName);
448         }
449         catch (Exception e)
450         {
451             throw new AdministrationEmailException(USER_NOT_FOUND_FROM_EMAIL + email);
452         }
453     }
454 
455     /***
456      * Helper for admin portlets to generate portal urls
457      */
458     public String getPortalURL(PortletRequest request, PortletResponse response, String path)
459     {
460         // get internal request context
461         RequestContext context = (RequestContext)
462             request.getAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE);
463         String baseUrl = context.getPortalURL().getBaseURL();
464         String jetspeedPath = adminUtil.concatenatePaths(baseUrl, context.getPortalURL().getBasePath());
465         if (path == null)
466             return jetspeedPath;
467         return adminUtil.concatenatePaths(jetspeedPath, response.encodeURL(path));
468     }
469         
470     
471     Map forgottenPasswordData = new HashMap();
472 
473     /* (non-Javadoc)
474      * @see org.apache.jetspeed.administration.PortalAdministration#getNewLoginInfo(java.lang.String)
475      */
476     public Map getNewLoginInfo(String guid)
477     {
478         synchronized(forgottenPasswordData) {
479             return (Map) forgottenPasswordData.get(guid);
480         }
481     }
482 
483     /* (non-Javadoc)
484      * @see org.apache.jetspeed.administration.PortalAdministration#setNewLoginInfo(java.lang.String, org.apache.jetspeed.administration.PortalAdministration.ResetPasswordInfo)
485      */
486     public void putNewLoginInfo(String guid, Map info)
487     {
488         synchronized(forgottenPasswordData) {
489             forgottenPasswordData.put(guid,info);
490         }
491     }
492 
493     /* (non-Javadoc)
494      * @see org.apache.jetspeed.administration.PortalAdministration#removeNewLoginInfo(java.lang.String)
495      */
496     public void removeNewLoginInfo(String guid)
497     {
498         synchronized(forgottenPasswordData) {
499             forgottenPasswordData.remove(guid);
500         }
501     }
502     
503     
504     
505     
506     
507 }