/
TeacherAccountController.java
364 lines (333 loc) · 16 KB
/
TeacherAccountController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
/**
* Copyright (c) 2007-2017 Regents of the University of California (Regents).
* Created by WISE, Graduate School of Education, University of California, Berkeley.
*
* This software is distributed under the GNU General Public License, v3,
* or (at your option) any later version.
*
* Permission is hereby granted, without written agreement and without license
* or royalty fees, to use, copy, modify, and distribute this software and its
* documentation for any purpose, provided that the above copyright notice and
* the following two paragraphs appear in all copies of this software.
*
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
* HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
* SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
* REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.wise.portal.presentation.web.controllers.teacher;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpSessionRequiredException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.view.RedirectView;
import org.wise.portal.dao.ObjectNotFoundException;
import org.wise.portal.domain.authentication.Curriculumsubjects;
import org.wise.portal.domain.authentication.Schoollevel;
import org.wise.portal.domain.authentication.impl.ChangePasswordParameters;
import org.wise.portal.domain.authentication.impl.TeacherUserDetails;
import org.wise.portal.domain.user.User;
import org.wise.portal.presentation.validators.ChangePasswordParametersValidator;
import org.wise.portal.presentation.validators.TeacherAccountFormValidator;
import org.wise.portal.presentation.web.TeacherAccountForm;
import org.wise.portal.presentation.web.controllers.ControllerUtil;
import org.wise.portal.service.authentication.DuplicateUsernameException;
import org.wise.portal.service.mail.IMailFacade;
import org.wise.portal.service.user.UserService;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;
import java.util.Locale;
import java.util.Properties;
/**
* Controller for creating and updating WISE teacher accounts
*
* @author Hiroki Terashima
*/
@Controller
@SessionAttributes({"teacherAccountForm", "changePasswordParameters"})
public class TeacherAccountController {
@Autowired
protected Properties wiseProperties;
@Autowired
protected IMailFacade mailService;
@Autowired
protected MessageSource messageSource;
@Autowired
protected UserService userService;
@Autowired
protected TeacherAccountFormValidator teacherAccountFormValidator;
@Autowired
protected ChangePasswordParametersValidator changePasswordParametersValidator;
/**
* Called before the page is loaded to initialize values.
* Adds the TeacherAccountForm object to the model.
* This object will be filled out and submitted for creating
* the new teacher
* @param modelMap the model object that contains values for the page to use when rendering the view
* @return the path of the view to display
*/
@RequestMapping(value = "/teacher/join", method = RequestMethod.GET)
public String initializeFormNewTeacher(ModelMap modelMap) throws Exception {
TeacherAccountForm teacherAccountForm = new TeacherAccountForm();
modelMap.addAttribute("teacherAccountForm", teacherAccountForm);
populateModelMap(modelMap);
return "teacher/join";
}
/**
* Shows page where teacher can update account information
* Switched user (e.g. admin/researcher logged in as this user) should not be able to view/modify
* user account.
*/
@RequestMapping(value = "/teacher/account", method = RequestMethod.GET)
public String updateMyAccountPage(ModelMap modelMap) {
if (ControllerUtil.isUserPreviousAdministrator()) {
return "errors/accessdenied";
} else {
User signedInUser = ControllerUtil.getSignedInUser();
if (signedInUser.isTeacher()) {
TeacherUserDetails teacherUserDetails = (TeacherUserDetails) signedInUser.getUserDetails();
TeacherAccountForm teacherAccountForm = new TeacherAccountForm(teacherUserDetails);
modelMap.addAttribute("teacherAccountForm", teacherAccountForm);
setChangePasswordParametersInModelMap(modelMap, signedInUser);
populateModelMap(modelMap);
return "teacher/account";
}
return "errors/accessdenied";
}
}
/**
* Populate the model map with objects the form requires
* @param modelMap the model to populate
* @return the model
*/
protected ModelMap populateModelMap(ModelMap modelMap) {
try {
modelMap.put("schoollevels", Schoollevel.values());
modelMap.put("curriculumsubjects",Curriculumsubjects.values());
String supportedLocales = wiseProperties
.getProperty("supportedLocales", "en,zh_TW,zh_CN,nl,he,ja,ko,es,pt,tr");
modelMap.put("languages", supportedLocales.split(","));
} catch (Exception e) {
e.printStackTrace();
}
return modelMap;
}
private void setChangePasswordParametersInModelMap(ModelMap modelMap, User user) {
ChangePasswordParameters params = new ChangePasswordParameters();
params.setUser(user);
modelMap.addAttribute("changePasswordParameters", params);
}
/**
* Creates a new teacher user and saves to data store
* @param accountForm the model object that contains values for the page to use when rendering the view
* @param bindingResult the object used for validation in which errors will be stored
* @param request the http request object
* @param modelMap the object that contains values to be displayed on the page
* @return the path of the view to display
*/
@RequestMapping(value = "/teacher/join", method = RequestMethod.POST)
protected String createNewTeacher(
@ModelAttribute("teacherAccountForm") TeacherAccountForm accountForm,
BindingResult bindingResult,
HttpServletRequest request,
ModelMap modelMap) {
TeacherUserDetails userDetails = (TeacherUserDetails) accountForm.getUserDetails();
userDetails.setSignupdate(Calendar.getInstance().getTime());
teacherAccountFormValidator.validate(accountForm, bindingResult);
if (bindingResult.hasErrors()) {
populateModelMap(modelMap);
return "teacher/join";
}
try {
userDetails.setDisplayname(userDetails.getFirstname() + " " + userDetails.getLastname());
userDetails.setEmailValid(true);
userDetails.setLanguage(wiseProperties.getProperty("defaultLocale", "en"));
User createdUser = this.userService.createUser(userDetails);
NewAccountEmailService newAccountEmailService = new NewAccountEmailService(createdUser, request.getLocale(), request);
Thread thread = new Thread(newAccountEmailService);
thread.start();
modelMap.addAttribute("username", userDetails.getUsername());
modelMap.addAttribute("displayname", userDetails.getDisplayname());
return "teacher/joinsuccess";
} catch (DuplicateUsernameException e) {
bindingResult.rejectValue("username", "error.duplicate-username", new Object[] { userDetails.getUsername() }, "Duplicate Username.");
populateModelMap(modelMap);
return "teacher/join";
}
}
/**
* Updates an existing teacher record
* @param accountForm the model object that contains values for the page to use when rendering the view
* @param bindingResult the object used for validation in which errors will be stored
* @param request the http request object
* @param modelMap the object that contains values to be displayed on the page
* @return the path of the view to display
*/
@RequestMapping(value = "/teacher/account", method = RequestMethod.POST)
protected String updateExistingTeacher(
@ModelAttribute("teacherAccountForm") TeacherAccountForm accountForm,
BindingResult bindingResult,
HttpServletRequest request,
ModelMap modelMap) {
TeacherUserDetails userDetails = (TeacherUserDetails) accountForm.getUserDetails();
teacherAccountFormValidator.validate(accountForm, bindingResult);
if (bindingResult.hasErrors()) {
populateModelMap(modelMap);
return "teacher/account";
}
User user = userService.retrieveUserByUsername(userDetails.getUsername());
updateTeacherUserDetails(user, userDetails);
updateUserLocaleInSession(user, request);
userService.updateUser(user);
request.getSession().setAttribute(User.CURRENT_USER_SESSION_KEY, user);
setChangePasswordParametersInModelMap(modelMap, user);
modelMap.put("accountInfoSavedMessage", "Changes saved!");
populateModelMap(modelMap);
return "teacher/account";
}
/**
* Updates an existing teacher record
* @param bindingResult the object used for validation in which errors will be stored
* @param request the http request object
* @param modelMap the object that contains values to be displayed on the page
* @return the path of the view to display
*/
@RequestMapping(value = "/teacher/account/password", method = RequestMethod.POST)
protected String updateExistingTeacherPassword(
@ModelAttribute("changePasswordParameters") ChangePasswordParameters params,
BindingResult bindingResult,
HttpServletRequest request,
ModelMap modelMap) throws ObjectNotFoundException {
changePasswordParametersValidator.validate(params, bindingResult);
if (bindingResult.hasErrors()) {
populateModelMap(modelMap);
return "teacher/account";
} else {
User user = userService.retrieveById(params.getUser().getId());
userService.updateUserPassword(user, params.getPasswd1());
request.getSession().setAttribute(User.CURRENT_USER_SESSION_KEY, user);
setChangePasswordParametersInModelMap(modelMap, user);
modelMap.put("passwordSavedMessage", "Password changes saved!");
populateModelMap(modelMap);
return "teacher/account";
}
}
private void updateTeacherUserDetails(User user, TeacherUserDetails newUserDetails) {
TeacherUserDetails teacherUserDetails = (TeacherUserDetails) user.getUserDetails();
teacherUserDetails.setCity(newUserDetails.getCity());
teacherUserDetails.setCountry(newUserDetails.getCountry());
teacherUserDetails.setCurriculumsubjects(newUserDetails.getCurriculumsubjects());
teacherUserDetails.setEmailAddress(newUserDetails.getEmailAddress());
teacherUserDetails.setSchoollevel(newUserDetails.getSchoollevel());
teacherUserDetails.setSchoolname(newUserDetails.getSchoolname());
teacherUserDetails.setState(newUserDetails.getState());
teacherUserDetails.setDisplayname(newUserDetails.getDisplayname());
teacherUserDetails.setEmailValid(true);
if ("default".equals(newUserDetails.getLanguage())) {
teacherUserDetails.setLanguage(null);
} else {
teacherUserDetails.setLanguage(newUserDetails.getLanguage());
}
}
private void updateUserLocaleInSession(User user, HttpServletRequest request) {
Locale locale;
String userLanguage = user.getUserDetails().getLanguage();
if (userLanguage != null) {
if (userLanguage.contains("_")) {
String language = userLanguage.substring(0, userLanguage.indexOf("_"));
String country = userLanguage.substring(userLanguage.indexOf("_")+1);
locale = new Locale(language, country);
} else {
locale = new Locale(userLanguage);
}
} else {
// user default browser locale setting if user hasn't specified locale
locale = request.getLocale();
}
request.getSession()
.setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, locale);
}
@ExceptionHandler(HttpSessionRequiredException.class)
public ModelAndView handleSessionExpired(HttpServletRequest request) {
String contextPath = request.getContextPath();
ModelAndView mav = new ModelAndView();
if (isOnRegisterNewTeacherPage(request)) {
mav.setView(new RedirectView(contextPath + "/teacher/join"));
} else {
mav.setView(new RedirectView(contextPath + "/index.html"));
}
return mav;
}
public boolean isOnRegisterNewTeacherPage(HttpServletRequest request) {
String domain = ControllerUtil.getBaseUrlString(request);
String domainWithPort = domain + ":" + request.getLocalPort();
String referrer = request.getHeader("referer");
String contextPath = request.getContextPath();
String registerUrl = contextPath + "/teacher/join";
return referrer != null &&
(referrer.contains(domain + registerUrl) || referrer.contains(domainWithPort + registerUrl));
}
class NewAccountEmailService implements Runnable {
private User newUser;
private Locale locale;
private HttpServletRequest request;
public NewAccountEmailService(User newUser, Locale locale, HttpServletRequest request) {
this.newUser = newUser;
this.locale = locale;
this.request = request;
}
public void run() {
String sendEmailEnabledStr = wiseProperties.getProperty("send_email_enabled", "false");
Boolean sendEmailEnabled = Boolean.valueOf(sendEmailEnabledStr);
if (!sendEmailEnabled) {
return;
} else {
this.sendEmail(this.request);
}
}
/**
* Sends a welcome email to the new user with WISE resources.
*/
private void sendEmail(HttpServletRequest request) {
TeacherUserDetails newUserDetails = (TeacherUserDetails) newUser.getUserDetails();
String userUsername = newUserDetails.getUsername();
String userEmailAddress[] = {newUserDetails.getEmailAddress()};
String[] recipients = (String[]) ArrayUtils.addAll(userEmailAddress,
wiseProperties.getProperty("uber_admin").split(","));
String defaultSubject = messageSource.getMessage("presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailSubject", null, Locale.US);
String subject = messageSource.getMessage("presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailSubject", null, defaultSubject, this.locale);
String portalString = ControllerUtil.getPortalUrlString(request);
String gettingStartedUrl = portalString + "/pages/gettingstarted.html";
String defaultBody = messageSource.getMessage("presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBody", new Object[] {userUsername,gettingStartedUrl}, Locale.US);
String message = messageSource.getMessage("presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBody", new Object[] {userUsername,gettingStartedUrl}, defaultBody, this.locale);
if (wiseProperties.containsKey("discourse_url")) {
String discourseURL = wiseProperties.getProperty("discourse_url");
if (discourseURL != null && !discourseURL.isEmpty()) {
// if this WISE instance uses discourse for teacher community, append link to it in the P.S. section of the email
String defaultPS = messageSource.getMessage("teacherEmailPSCommunity", new Object[] {discourseURL}, Locale.US);
String pS = messageSource.getMessage("teacherEmailPSCommunity", new Object[] {discourseURL}, defaultPS, this.locale);
message += "\n\n"+pS;
}
}
String fromEmail = wiseProperties.getProperty("portalemailaddress");
try {
mailService.postMail(recipients, subject, message, fromEmail);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
}