From 92e45aba109fd0ee30506fa441a7b151b41533b4 Mon Sep 17 00:00:00 2001 From: Aaron Detre Date: Fri, 17 Jul 2026 09:56:23 -0700 Subject: [PATCH 1/4] Move teacher registration into separate class --- .../teacher/TeacherAPIController.java | 109 --------------- .../TeacherRegistrationAPIController.java | 127 ++++++++++++++++++ .../teacher/TeacherAPIControllerTest.java | 43 ------ .../TeacherRegistrationAPIControllerTest.java | 77 +++++++++++ 4 files changed, 204 insertions(+), 152 deletions(-) create mode 100644 src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java create mode 100644 src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIControllerTest.java diff --git a/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherAPIController.java b/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherAPIController.java index 559ba9040..92e6baadd 100644 --- a/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherAPIController.java +++ b/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherAPIController.java @@ -4,24 +4,19 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Set; import java.util.TreeSet; -import javax.mail.MessagingException; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; import org.springframework.security.acls.model.Permission; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -32,13 +27,8 @@ import org.wise.portal.domain.group.Group; import org.wise.portal.domain.run.Run; import org.wise.portal.domain.user.User; -import org.wise.portal.domain.usertag.UserTag; -import org.wise.portal.presentation.web.controllers.ControllerUtil; import org.wise.portal.presentation.web.controllers.user.UserAPIController; -import org.wise.portal.presentation.web.exception.InvalidNameException; -import org.wise.portal.presentation.web.response.ResponseEntityGenerator; import org.wise.portal.presentation.web.response.SimpleResponse; -import org.wise.portal.service.authentication.DuplicateUsernameException; import org.wise.portal.service.authentication.UserDetailsService; import org.wise.portal.service.usertags.UserTagsService; @@ -129,105 +119,6 @@ List getAllTeacherUsernames() { return userDetailsService.retrieveAllTeacherUsernames(); } - @PostMapping("/register") - @Secured({ "ROLE_ANONYMOUS" }) - ResponseEntity> createTeacherAccount( - @RequestBody Map teacherFields, HttpServletRequest request) - throws DuplicateUsernameException, InvalidNameException { - if (ControllerUtil.isReCaptchaEnabled()) { - String token = teacherFields.get("token"); - if (!ControllerUtil.isReCaptchaResponseValid(token)) { - return ResponseEntityGenerator.createError("recaptchaResponseInvalid"); - } - } - TeacherUserDetails tud = new TeacherUserDetails(); - String firstName = teacherFields.get("firstName"); - String lastName = teacherFields.get("lastName"); - if (!isFirstNameAndLastNameValid(firstName, lastName)) { - String messageCode = this.getInvalidNameMessageCode(firstName, lastName); - throw new InvalidNameException(messageCode); - } - tud.setFirstname(firstName); - tud.setLastname(lastName); - String email = teacherFields.get("email"); - tud.setEmailAddress(email); - tud.setCity(teacherFields.get("city")); - tud.setState(teacherFields.get("state")); - tud.setCountry(teacherFields.get("country")); - String googleUserId = teacherFields.get("googleUserId"); - String microsoftUserId = teacherFields.get("microsoftUserId"); - if (isSet(googleUserId)) { - tud.setGoogleUserId(googleUserId); - tud.setPassword(RandomStringUtils.random(10, true, true)); - } else if (isSet(microsoftUserId)) { - tud.setMicrosoftUserId(microsoftUserId); - tud.setPassword(RandomStringUtils.random(10, true, true)); - } else { - String password = teacherFields.get("password"); - if (!passwordService.isValid(password)) { - return ResponseEntityGenerator.createError(passwordService.getErrors(password)); - } else { - tud.setPassword(password); - } - } - String displayName = firstName + " " + lastName; - tud.setDisplayname(displayName); - tud.setEmailValid(true); - tud.setSchoollevel(Schoollevel.valueOf(teacherFields.get("schoolLevel"))); - tud.setSchoolname(teacherFields.get("schoolName")); - tud.setHowDidYouHearAboutUs(teacherFields.get("howDidYouHearAboutUs")); - Locale locale = request.getLocale(); - tud.setLanguage(locale.getLanguage()); - User createdUser = this.userService.createUser(tud); - String username = createdUser.getUserDetails().getUsername(); - String sendEmailEnabledStr = appProperties.getProperty("send_email_enabled", "false"); - Boolean iSendEmailEnabled = Boolean.valueOf(sendEmailEnabledStr); - boolean socialAccount = this.isSet(googleUserId) || this.isSet(microsoftUserId); - if (iSendEmailEnabled) { - sendCreateTeacherAccountEmail(email, displayName, username, socialAccount, locale, request); - } - return createRegisterSuccessResponse(username); - } - - private void sendCreateTeacherAccountEmail(String email, String displayName, String username, - boolean socialAccount, Locale locale, HttpServletRequest request) { - String fromEmail = appProperties.getProperty("portalemailaddress"); - String[] recipients = { email }; - 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, locale); - String defaultBody = messageSource.getMessage( - "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBody", - new Object[] { username }, Locale.US); - String gettingStartedUrl = getGettingStartedUrl(request); - String message; - if (socialAccount) { - message = messageSource.getMessage( - "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBodyNoUsername", - new Object[] { displayName, gettingStartedUrl }, defaultBody, locale); - } else { - message = messageSource.getMessage( - "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBody", - new Object[] { displayName, username, gettingStartedUrl }, defaultBody, locale); - } - try { - mailService.postMail(recipients, subject, message, fromEmail); - } catch (MessagingException e) { - e.printStackTrace(); - } - } - - private String getGettingStartedUrl(HttpServletRequest request) { - return ControllerUtil.getPortalUrlString(request) + "/help/getting-started"; - } - - private boolean isSet(String value) { - return value != null && !value.isEmpty(); - } - private List> getRunSharedOwnersList(Run run) { List> sharedOwners = new ArrayList>(); for (User sharedOwner : run.getSharedowners()) { diff --git a/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java b/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java new file mode 100644 index 000000000..d5dc363c5 --- /dev/null +++ b/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java @@ -0,0 +1,127 @@ +package org.wise.portal.presentation.web.controllers.teacher; + +import java.util.Locale; +import java.util.Map; + +import javax.mail.MessagingException; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.wise.portal.domain.authentication.Schoollevel; +import org.wise.portal.domain.authentication.impl.TeacherUserDetails; +import org.wise.portal.domain.user.User; +import org.wise.portal.presentation.web.controllers.ControllerUtil; +import org.wise.portal.presentation.web.exception.InvalidNameException; +import org.wise.portal.presentation.web.response.ResponseEntityGenerator; +import org.wise.portal.service.authentication.DuplicateUsernameException; + + +@RestController +@RequestMapping("/api/teacher/register") +public class TeacherRegistrationAPIController extends TeacherAPIController { + + @PostMapping() + @Secured({ "ROLE_ANONYMOUS" }) + ResponseEntity> createTeacherAccount( + @RequestBody Map teacherFields, HttpServletRequest request) + throws DuplicateUsernameException, InvalidNameException { + if (ControllerUtil.isReCaptchaEnabled()) { + String token = teacherFields.get("token"); + if (!ControllerUtil.isReCaptchaResponseValid(token)) { + return ResponseEntityGenerator.createError("recaptchaResponseInvalid"); + } + } + TeacherUserDetails tud = new TeacherUserDetails(); + String firstName = teacherFields.get("firstName"); + String lastName = teacherFields.get("lastName"); + if (!isFirstNameAndLastNameValid(firstName, lastName)) { + String messageCode = this.getInvalidNameMessageCode(firstName, lastName); + throw new InvalidNameException(messageCode); + } + tud.setFirstname(firstName); + tud.setLastname(lastName); + String email = teacherFields.get("email"); + tud.setEmailAddress(email); + tud.setCity(teacherFields.get("city")); + tud.setState(teacherFields.get("state")); + tud.setCountry(teacherFields.get("country")); + String googleUserId = teacherFields.get("googleUserId"); + String microsoftUserId = teacherFields.get("microsoftUserId"); + if (isSet(googleUserId)) { + tud.setGoogleUserId(googleUserId); + tud.setPassword(RandomStringUtils.random(10, true, true)); + } else if (isSet(microsoftUserId)) { + tud.setMicrosoftUserId(microsoftUserId); + tud.setPassword(RandomStringUtils.random(10, true, true)); + } else { + String password = teacherFields.get("password"); + if (!passwordService.isValid(password)) { + return ResponseEntityGenerator.createError(passwordService.getErrors(password)); + } else { + tud.setPassword(password); + } + } + String displayName = firstName + " " + lastName; + tud.setDisplayname(displayName); + tud.setEmailValid(true); + tud.setSchoollevel(Schoollevel.valueOf(teacherFields.get("schoolLevel"))); + tud.setSchoolname(teacherFields.get("schoolName")); + tud.setHowDidYouHearAboutUs(teacherFields.get("howDidYouHearAboutUs")); + Locale locale = request.getLocale(); + tud.setLanguage(locale.getLanguage()); + User createdUser = this.userService.createUser(tud); + String username = createdUser.getUserDetails().getUsername(); + String sendEmailEnabledStr = appProperties.getProperty("send_email_enabled", "false"); + Boolean iSendEmailEnabled = Boolean.valueOf(sendEmailEnabledStr); + boolean socialAccount = this.isSet(googleUserId) || this.isSet(microsoftUserId); + if (iSendEmailEnabled) { + sendCreateTeacherAccountEmail(email, displayName, username, socialAccount, locale, request); + } + return createRegisterSuccessResponse(username); + } + + private void sendCreateTeacherAccountEmail(String email, String displayName, String username, + boolean socialAccount, Locale locale, HttpServletRequest request) { + String fromEmail = appProperties.getProperty("portalemailaddress"); + String[] recipients = { email }; + 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, locale); + String defaultBody = messageSource.getMessage( + "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBody", + new Object[] { username }, Locale.US); + String gettingStartedUrl = getGettingStartedUrl(request); + String message; + if (socialAccount) { + message = messageSource.getMessage( + "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBodyNoUsername", + new Object[] { displayName, gettingStartedUrl }, defaultBody, locale); + } else { + message = messageSource.getMessage( + "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBody", + new Object[] { displayName, username, gettingStartedUrl }, defaultBody, locale); + } + try { + mailService.postMail(recipients, subject, message, fromEmail); + } catch (MessagingException e) { + e.printStackTrace(); + } + } + + private String getGettingStartedUrl(HttpServletRequest request) { + return ControllerUtil.getPortalUrlString(request) + "/help/getting-started"; + } + + private boolean isSet(String value) { + return value != null && !value.isEmpty(); + } +} diff --git a/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherAPIControllerTest.java b/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherAPIControllerTest.java index d07076070..76902310e 100644 --- a/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherAPIControllerTest.java +++ b/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherAPIControllerTest.java @@ -16,7 +16,6 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Set; import org.easymock.EasyMockExtension; @@ -25,8 +24,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.test.util.ReflectionTestUtils; import org.wise.portal.dao.ObjectNotFoundException; import org.wise.portal.domain.PeriodNotFoundException; @@ -35,9 +32,7 @@ import org.wise.portal.domain.run.Run; import org.wise.portal.domain.user.User; import org.wise.portal.presentation.web.controllers.APIControllerTest; -import org.wise.portal.presentation.web.exception.InvalidNameException; import org.wise.portal.presentation.web.response.SimpleResponse; -import org.wise.portal.service.authentication.DuplicateUsernameException; import org.wise.portal.service.authentication.UserDetailsService; import org.wise.portal.service.password.impl.PasswordServiceImpl; import org.wise.portal.service.usertags.UserTagsService; @@ -375,33 +370,6 @@ public void createRun_ThreePeriods_CreateRun() throws Exception { verify(runService); } - @Test - public void createTeacherAccount_InvalidPassword_ReturnError() - throws DuplicateUsernameException, InvalidNameException { - HashMap teacherFields = createDefaultTeacherFields(); - teacherFields.put("password", PasswordServiceImpl.INVALID_PASSWORD_TOO_SHORT); - ResponseEntity> response = teacherAPIController - .createTeacherAccount(teacherFields, request); - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertEquals("invalidPassword", response.getBody().get("messageCode")); - } - - @Test - public void createTeacherAccount_WithGoogleUserId_CreateUser() - throws DuplicateUsernameException, InvalidNameException { - HashMap teacherFields = createDefaultTeacherFields(); - teacherFields.put("googleUserId", "123456789"); - expect(request.getLocale()).andReturn(Locale.US); - replay(request); - expect(userService.createUser(isA(TeacherUserDetails.class))).andReturn(teacher1); - replay(userService); - ResponseEntity> response = teacherAPIController - .createTeacherAccount(teacherFields, request); - assertEquals(TEACHER_USERNAME, response.getBody().get("username")); - verify(request); - verify(userService); - } - @Test public void editRunEndTime_WithNullEndTime_ChangeEndTime() throws ObjectNotFoundException { expect(userService.retrieveUserByUsername(teacherAuth.getName())).andReturn(teacher1); @@ -456,17 +424,6 @@ public void editRunIsLockedAfterEndDate_WithFalse_ChangeValue() throws ObjectNot verify(runService); } - private HashMap createDefaultTeacherFields() { - HashMap fields = new HashMap(); - fields.put("firstName", TEACHER_FIRSTNAME); - fields.put("lastName", TEACHER_LASTNAME); - fields.put("schoolLevel", "COLLEGE"); - fields.put("birthMonth", "1"); - fields.put("birthDay", "1"); - fields.put("gender", "MALE"); - return fields; - } - private void expectGetRunMapToBeCalled() { expect(projectService.getProjectPath(isA(Project.class))).andReturn("/1/project.json"); expect(projectService.getProjectSharedOwnersList(isA(Project.class))) diff --git a/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIControllerTest.java b/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIControllerTest.java new file mode 100644 index 000000000..032b81551 --- /dev/null +++ b/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIControllerTest.java @@ -0,0 +1,77 @@ +package org.wise.portal.presentation.web.controllers.teacher; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import org.easymock.EasyMockExtension; +import org.easymock.Mock; +import org.easymock.TestSubject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.wise.portal.domain.authentication.impl.TeacherUserDetails; +import org.wise.portal.presentation.web.controllers.APIControllerTest; +import org.wise.portal.presentation.web.exception.InvalidNameException; +import org.wise.portal.service.authentication.DuplicateUsernameException; +import org.wise.portal.service.authentication.UserDetailsService; +import org.wise.portal.service.password.impl.PasswordServiceImpl; +import org.wise.portal.service.usertags.UserTagsService; + +@ExtendWith(EasyMockExtension.class) +public class TeacherRegistrationAPIControllerTest extends APIControllerTest { + + @TestSubject + private TeacherRegistrationAPIController teacherRegistrationAPIController = new TeacherRegistrationAPIController(); + + @Mock + private UserDetailsService userDetailsService; + + @Mock + private UserTagsService userTagsService; + + @Test + public void createTeacherAccount_InvalidPassword_ReturnError() + throws DuplicateUsernameException, InvalidNameException { + HashMap teacherFields = createDefaultTeacherFields(); + teacherFields.put("password", PasswordServiceImpl.INVALID_PASSWORD_TOO_SHORT); + ResponseEntity> response = teacherRegistrationAPIController + .createTeacherAccount(teacherFields, request); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + assertEquals("invalidPassword", response.getBody().get("messageCode")); + } + + @Test + public void createTeacherAccount_WithGoogleUserId_CreateUser() + throws DuplicateUsernameException, InvalidNameException { + HashMap teacherFields = createDefaultTeacherFields(); + teacherFields.put("googleUserId", "123456789"); + expect(request.getLocale()).andReturn(Locale.US); + replay(request); + expect(userService.createUser(isA(TeacherUserDetails.class))).andReturn(teacher1); + replay(userService); + ResponseEntity> response = teacherRegistrationAPIController + .createTeacherAccount(teacherFields, request); + assertEquals(TEACHER_USERNAME, response.getBody().get("username")); + verify(request); + verify(userService); + } + + private HashMap createDefaultTeacherFields() { + HashMap fields = new HashMap(); + fields.put("firstName", TEACHER_FIRSTNAME); + fields.put("lastName", TEACHER_LASTNAME); + fields.put("schoolLevel", "COLLEGE"); + fields.put("birthMonth", "1"); + fields.put("birthDay", "1"); + fields.put("gender", "MALE"); + return fields; + } +} From 907d6836eb5f95cb23e0fa88e878923b54eea9ef Mon Sep 17 00:00:00 2001 From: Aaron Detre Date: Fri, 17 Jul 2026 09:58:48 -0700 Subject: [PATCH 2/4] Refactor teacher registration --- .../TeacherRegistrationAPIController.java | 185 +++++++++++------- 1 file changed, 115 insertions(+), 70 deletions(-) diff --git a/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java b/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java index d5dc363c5..3f3fe8458 100644 --- a/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java +++ b/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java @@ -18,110 +18,155 @@ import org.wise.portal.domain.user.User; import org.wise.portal.presentation.web.controllers.ControllerUtil; import org.wise.portal.presentation.web.exception.InvalidNameException; +import org.wise.portal.presentation.web.exception.InvalidPasswordException; +import org.wise.portal.presentation.web.exception.RecaptchaVerificationException; import org.wise.portal.presentation.web.response.ResponseEntityGenerator; import org.wise.portal.service.authentication.DuplicateUsernameException; - @RestController @RequestMapping("/api/teacher/register") public class TeacherRegistrationAPIController extends TeacherAPIController { + private final String emailCodePrefix = + "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmail"; + private final String welcomeBodyCode = this.emailCodePrefix + "Body"; + private final String welcomeSocialAccountBodyCode = this.emailCodePrefix + "BodyNoUsername"; + private final String welcomeSubjectCode = this.emailCodePrefix + "Subject"; + @PostMapping() @Secured({ "ROLE_ANONYMOUS" }) ResponseEntity> createTeacherAccount( @RequestBody Map teacherFields, HttpServletRequest request) throws DuplicateUsernameException, InvalidNameException { + try { + validateTeacherFields(teacherFields); + } catch (RecaptchaVerificationException e) { + return ResponseEntityGenerator.createError("recaptchaResponseInvalid"); + } catch (InvalidPasswordException e) { + return ResponseEntityGenerator.createError( + passwordService.getErrors(teacherFields.get("password"))); + } + Locale locale = request.getLocale(); + TeacherUserDetails tud = createTeacherUserDetails(teacherFields, locale); + User createdUser = this.userService.createUser(tud); + String username = createdUser.getUserDetails().getUsername(); + if (isSendEmailEnabled()) { + boolean socialAccount = isSet(tud.getGoogleUserId()) || isSet(tud.getMicrosoftUserId()); + sendWelcomeTeacherEmail(tud.getEmailAddress(), tud.getDisplayname(), username, + socialAccount, locale, request); + } + return createRegisterSuccessResponse(username); + } + + private Boolean isSendEmailEnabled() { + String sendEmailEnabledStr = appProperties.getProperty("send_email_enabled", "false"); + return Boolean.valueOf(sendEmailEnabledStr); + } + + private void sendWelcomeTeacherEmail(String email, String displayName, String username, + boolean socialAccount, Locale locale, + HttpServletRequest request) { + String subject = getEmailMessage(this.welcomeSubjectCode, this.welcomeSubjectCode, null, locale); + String body = getWelcomeTeacherBody(displayName, username, socialAccount, locale, request); + this.sendEmail(email, subject, body); + } + + private String getEmailMessage(String defaultCode, String code, Object[] args, Locale locale) { + String defaultMessage = messageSource.getMessage(defaultCode, args, Locale.US); + return messageSource.getMessage(code, args, defaultMessage, locale); + } + + private String getWelcomeTeacherBody(String displayName, String username, boolean socialAccount, + Locale locale, HttpServletRequest request) { + String gettingStartedUrl = getGettingStartedUrl(request); + String code = socialAccount ? this.welcomeSocialAccountBodyCode : this.welcomeBodyCode; + Object[] args = socialAccount + ? new Object[] { displayName, gettingStartedUrl } + : new Object[] { displayName, username, gettingStartedUrl }; + return getEmailMessage(this.welcomeBodyCode, code, args, locale); + } + + private String getGettingStartedUrl(HttpServletRequest request) { + return ControllerUtil.getPortalUrlString(request) + "/help/getting-started"; + } + + private void sendEmail(String email, String subject, String body) { + String fromEmail = appProperties.getProperty("portalemailaddress"); + String[] recipients = { email }; + try { + mailService.postMail(recipients, subject, body, fromEmail); + } catch (MessagingException e) { + e.printStackTrace(); + } + } + + private void validateTeacherFields(Map teacherFields) + throws RecaptchaVerificationException, InvalidNameException, InvalidPasswordException { + validateReCaptcha(teacherFields.get("token")); + validateFirstAndLastName(teacherFields.get("firstName"), teacherFields.get("lastName")); + validatePassword(teacherFields.get("password")); + } + + private void validateReCaptcha(String token) throws RecaptchaVerificationException { if (ControllerUtil.isReCaptchaEnabled()) { - String token = teacherFields.get("token"); if (!ControllerUtil.isReCaptchaResponseValid(token)) { - return ResponseEntityGenerator.createError("recaptchaResponseInvalid"); + throw new RecaptchaVerificationException("Invalid ReCaptcha Response"); } } - TeacherUserDetails tud = new TeacherUserDetails(); - String firstName = teacherFields.get("firstName"); - String lastName = teacherFields.get("lastName"); + } + + private void validateFirstAndLastName(String firstName, String lastName) + throws InvalidNameException { if (!isFirstNameAndLastNameValid(firstName, lastName)) { String messageCode = this.getInvalidNameMessageCode(firstName, lastName); throw new InvalidNameException(messageCode); } - tud.setFirstname(firstName); - tud.setLastname(lastName); - String email = teacherFields.get("email"); - tud.setEmailAddress(email); + } + + private void validatePassword(String password) throws InvalidPasswordException { + if (password != null && !passwordService.isValid(password)) { + throw new InvalidPasswordException(); + } + } + + private TeacherUserDetails createTeacherUserDetails(Map teacherFields, + Locale locale) { + TeacherUserDetails tud = new TeacherUserDetails(); + tud.setFirstname(teacherFields.get("firstName")); + tud.setLastname(teacherFields.get("lastName")); + tud.setEmailAddress(teacherFields.get("email")); tud.setCity(teacherFields.get("city")); tud.setState(teacherFields.get("state")); tud.setCountry(teacherFields.get("country")); - String googleUserId = teacherFields.get("googleUserId"); - String microsoftUserId = teacherFields.get("microsoftUserId"); - if (isSet(googleUserId)) { - tud.setGoogleUserId(googleUserId); - tud.setPassword(RandomStringUtils.random(10, true, true)); - } else if (isSet(microsoftUserId)) { - tud.setMicrosoftUserId(microsoftUserId); - tud.setPassword(RandomStringUtils.random(10, true, true)); - } else { - String password = teacherFields.get("password"); - if (!passwordService.isValid(password)) { - return ResponseEntityGenerator.createError(passwordService.getErrors(password)); - } else { - tud.setPassword(password); - } - } - String displayName = firstName + " " + lastName; - tud.setDisplayname(displayName); - tud.setEmailValid(true); + tud.setDisplayname(tud.getFirstname() + " " + tud.getLastname()); tud.setSchoollevel(Schoollevel.valueOf(teacherFields.get("schoolLevel"))); tud.setSchoolname(teacherFields.get("schoolName")); tud.setHowDidYouHearAboutUs(teacherFields.get("howDidYouHearAboutUs")); - Locale locale = request.getLocale(); tud.setLanguage(locale.getLanguage()); - User createdUser = this.userService.createUser(tud); - String username = createdUser.getUserDetails().getUsername(); - String sendEmailEnabledStr = appProperties.getProperty("send_email_enabled", "false"); - Boolean iSendEmailEnabled = Boolean.valueOf(sendEmailEnabledStr); - boolean socialAccount = this.isSet(googleUserId) || this.isSet(microsoftUserId); - if (iSendEmailEnabled) { - sendCreateTeacherAccountEmail(email, displayName, username, socialAccount, locale, request); - } - return createRegisterSuccessResponse(username); + setPassword(teacherFields, tud); + tud.setEmailValid(true); + return tud; } - private void sendCreateTeacherAccountEmail(String email, String displayName, String username, - boolean socialAccount, Locale locale, HttpServletRequest request) { - String fromEmail = appProperties.getProperty("portalemailaddress"); - String[] recipients = { email }; - 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, locale); - String defaultBody = messageSource.getMessage( - "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBody", - new Object[] { username }, Locale.US); - String gettingStartedUrl = getGettingStartedUrl(request); - String message; - if (socialAccount) { - message = messageSource.getMessage( - "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBodyNoUsername", - new Object[] { displayName, gettingStartedUrl }, defaultBody, locale); + private void setPassword(Map teacherFields, TeacherUserDetails tud) { + String googleUserId = teacherFields.get("googleUserId"); + String microsoftUserId = teacherFields.get("microsoftUserId"); + if (isSet(googleUserId)) { + tud.setGoogleUserId(googleUserId); + setRandomPassword(tud); + } else if (isSet(microsoftUserId)) { + tud.setMicrosoftUserId(microsoftUserId); + setRandomPassword(tud); } else { - message = messageSource.getMessage( - "presentation.web.controllers.teacher.registerTeacherController.welcomeTeacherEmailBody", - new Object[] { displayName, username, gettingStartedUrl }, defaultBody, locale); - } - try { - mailService.postMail(recipients, subject, message, fromEmail); - } catch (MessagingException e) { - e.printStackTrace(); + tud.setPassword(teacherFields.get("password")); } } - private String getGettingStartedUrl(HttpServletRequest request) { - return ControllerUtil.getPortalUrlString(request) + "/help/getting-started"; - } - private boolean isSet(String value) { return value != null && !value.isEmpty(); } + + private void setRandomPassword(TeacherUserDetails tud) { + tud.setPassword(RandomStringUtils.random(10, true, true)); + } } From ad53a48f759567e18e5ee223921c0df5c2ac93a2 Mon Sep 17 00:00:00 2001 From: Aaron Detre Date: Fri, 17 Jul 2026 09:58:55 -0700 Subject: [PATCH 3/4] Fix tests --- .../TeacherRegistrationAPIControllerTest.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIControllerTest.java b/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIControllerTest.java index 032b81551..87bb71b75 100644 --- a/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIControllerTest.java +++ b/src/test/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIControllerTest.java @@ -22,12 +22,13 @@ import org.wise.portal.presentation.web.exception.InvalidNameException; import org.wise.portal.service.authentication.DuplicateUsernameException; import org.wise.portal.service.authentication.UserDetailsService; +import org.wise.portal.service.password.PasswordService; import org.wise.portal.service.password.impl.PasswordServiceImpl; import org.wise.portal.service.usertags.UserTagsService; @ExtendWith(EasyMockExtension.class) public class TeacherRegistrationAPIControllerTest extends APIControllerTest { - + @TestSubject private TeacherRegistrationAPIController teacherRegistrationAPIController = new TeacherRegistrationAPIController(); @@ -37,11 +38,19 @@ public class TeacherRegistrationAPIControllerTest extends APIControllerTest { @Mock private UserTagsService userTagsService; + @Mock + private PasswordService passwordService; + @Test public void createTeacherAccount_InvalidPassword_ReturnError() throws DuplicateUsernameException, InvalidNameException { HashMap teacherFields = createDefaultTeacherFields(); teacherFields.put("password", PasswordServiceImpl.INVALID_PASSWORD_TOO_SHORT); + expect(passwordService.isValid(PasswordServiceImpl.INVALID_PASSWORD_TOO_SHORT)).andReturn(false); + Map errors = new HashMap<>(); + errors.put("messageCode", "invalidPassword"); + expect(passwordService.getErrors(PasswordServiceImpl.INVALID_PASSWORD_TOO_SHORT)).andReturn(errors); + replay(passwordService); ResponseEntity> response = teacherRegistrationAPIController .createTeacherAccount(teacherFields, request); assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); @@ -62,7 +71,7 @@ public void createTeacherAccount_WithGoogleUserId_CreateUser() assertEquals(TEACHER_USERNAME, response.getBody().get("username")); verify(request); verify(userService); - } + } private HashMap createDefaultTeacherFields() { HashMap fields = new HashMap(); From 92b951b18d07502a0ea83d5406a9b02809a4ed07 Mon Sep 17 00:00:00 2001 From: Aaron Detre Date: Fri, 17 Jul 2026 10:03:28 -0700 Subject: [PATCH 4/4] Minor change --- .../teacher/TeacherRegistrationAPIController.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java b/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java index 3f3fe8458..cc18cd734 100644 --- a/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java +++ b/src/main/java/org/wise/portal/presentation/web/controllers/teacher/TeacherRegistrationAPIController.java @@ -51,18 +51,21 @@ ResponseEntity> createTeacherAccount( User createdUser = this.userService.createUser(tud); String username = createdUser.getUserDetails().getUsername(); if (isSendEmailEnabled()) { - boolean socialAccount = isSet(tud.getGoogleUserId()) || isSet(tud.getMicrosoftUserId()); sendWelcomeTeacherEmail(tud.getEmailAddress(), tud.getDisplayname(), username, - socialAccount, locale, request); + isSocialAccount(tud), locale, request); } return createRegisterSuccessResponse(username); } - private Boolean isSendEmailEnabled() { + private boolean isSendEmailEnabled() { String sendEmailEnabledStr = appProperties.getProperty("send_email_enabled", "false"); return Boolean.valueOf(sendEmailEnabledStr); } + private boolean isSocialAccount(TeacherUserDetails tud) { + return isSet(tud.getGoogleUserId()) || isSet(tud.getMicrosoftUserId()); + } + private void sendWelcomeTeacherEmail(String email, String displayName, String username, boolean socialAccount, Locale locale, HttpServletRequest request) {