diff --git a/src/main/java/org/wise/portal/domain/run/Run.java b/src/main/java/org/wise/portal/domain/run/Run.java index 0aa552c9c..09bf4822b 100644 --- a/src/main/java/org/wise/portal/domain/run/Run.java +++ b/src/main/java/org/wise/portal/domain/run/Run.java @@ -120,7 +120,7 @@ public interface Run extends Persistable { /** * Returns the period with periodName that is associated with this run - * + * * @param periodName * @return Group the period with the periodName that is associated with this run * @throws PeriodNotFoundException @@ -214,32 +214,42 @@ public interface Run extends Persistable { /** * Sets whether or not student asset uploading is enabled for this run. - * + * * @return */ void setStudentAssetUploaderEnabled(boolean isStudentAssetUploaderEnabled); /** * Returns whether or not student asset uploading is enabled for this run. - * + * * @return */ boolean isStudentAssetUploaderEnabled(); /** * Sets whether or not idea manager is enabled for this run. - * + * * @return */ void setIdeaManagerEnabled(boolean isIdeaManagerEnabled); /** * Returns whether or not idea manager is enabled for this run. - * + * * @return */ boolean isIdeaManagerEnabled(); + /** + * @return Whether or not the run a survey + */ + boolean isSurvey(); + + /** + * @param isSurvey + */ + void setIsSurvey(boolean isSurvey); + /** * @return Integer maxWorkgroupSize */ @@ -341,7 +351,7 @@ public interface Run extends Persistable { /** * sets student attendance for this run - * + * * @param studentAttendance */ void setStudentAttendance(List studentAttendance); @@ -353,14 +363,14 @@ public interface Run extends Persistable { /** * Gets private notes for this run - * + * * @return String private notes for this run */ String getPrivateNotes(); /** * Sets private notes for this run - * + * * @param privateNotes * private notes for this run */ @@ -368,14 +378,14 @@ public interface Run extends Persistable { /** * Gets survey for this run - * + * * @return String survey for this run */ String getSurvey(); /** * Sets survey for this run - * + * * @return String survey for this run */ void setSurvey(String survey); diff --git a/src/main/java/org/wise/portal/domain/run/impl/RunImpl.java b/src/main/java/org/wise/portal/domain/run/impl/RunImpl.java index 3262db1cf..5300ac46e 100644 --- a/src/main/java/org/wise/portal/domain/run/impl/RunImpl.java +++ b/src/main/java/org/wise/portal/domain/run/impl/RunImpl.java @@ -100,6 +100,9 @@ public class RunImpl implements Run { @Transient private static final String COLUMN_NAME_EXTRAS = "extras"; + @Transient + private static final String COLUMN_NAME_IS_SURVEY = "isSurvey"; + @Transient private static final String COLUMN_NAME_MAX_WORKGROUP_SIZE = "maxWorkgroupSize"; @@ -199,6 +202,9 @@ public class RunImpl implements Run { @Setter private String info; // other info pertaining to the run + @Column(name = COLUMN_NAME_IS_SURVEY) + private boolean isSurvey; + @Column(name = COLUMN_NAME_MAX_WORKGROUP_SIZE, nullable = true) @Getter @Setter @@ -427,7 +433,7 @@ public static class UserAlphabeticalComparator implements Comparator { /** * Compares the user names of two User objects - * + * * @param user1 * a user object * @param user2 @@ -480,4 +486,12 @@ public boolean isLockedAfterEndDate() { public void setLockedAfterEndDate(boolean isLockedAfterEndDate) { this.isLockedAfterEndDate = isLockedAfterEndDate; } + + public boolean isSurvey() { + return isSurvey; + } + + public void setIsSurvey(boolean isSurvey) { + this.isSurvey = isSurvey; + } } diff --git a/src/main/java/org/wise/portal/domain/run/impl/RunParameters.java b/src/main/java/org/wise/portal/domain/run/impl/RunParameters.java index 188792166..dec931f3e 100644 --- a/src/main/java/org/wise/portal/domain/run/impl/RunParameters.java +++ b/src/main/java/org/wise/portal/domain/run/impl/RunParameters.java @@ -30,7 +30,6 @@ import org.wise.portal.domain.project.Project; import org.wise.portal.domain.user.User; -import java.io.Serializable; import java.util.*; /** @@ -70,6 +69,8 @@ public class RunParameters implements Serializable { private Boolean isLockedAfterEndDate = false; + private boolean isSurvey = false; + public String printAllPeriods() { String allPeriods = null; diff --git a/src/main/java/org/wise/portal/domain/user/User.java b/src/main/java/org/wise/portal/domain/user/User.java index 016fd85d6..9c2de34a7 100644 --- a/src/main/java/org/wise/portal/domain/user/User.java +++ b/src/main/java/org/wise/portal/domain/user/User.java @@ -48,6 +48,8 @@ public interface User extends Persistable, Comparable { boolean isStudent(); + boolean isSurveyStudent(); + boolean isTeacher(); boolean isTrustedAuthor(); diff --git a/src/main/java/org/wise/portal/domain/user/impl/UserImpl.java b/src/main/java/org/wise/portal/domain/user/impl/UserImpl.java index 83a164a63..813fe67cc 100644 --- a/src/main/java/org/wise/portal/domain/user/impl/UserImpl.java +++ b/src/main/java/org/wise/portal/domain/user/impl/UserImpl.java @@ -78,6 +78,10 @@ public boolean isStudent() { return userDetails.hasGrantedAuthority(UserDetailsService.STUDENT_ROLE); } + public boolean isSurveyStudent() { + return userDetails.hasGrantedAuthority(UserDetailsService.SURVEY_STUDENT_ROLE); + } + public boolean isTeacher() { return userDetails.hasGrantedAuthority(UserDetailsService.TEACHER_ROLE); } @@ -111,6 +115,9 @@ public List getRoles() { if (this.isStudent()) { roles.add("student"); } + if (this.isSurveyStudent()) { + roles.add("surveyStudent"); + } return roles; } diff --git a/src/main/java/org/wise/portal/presentation/web/controllers/InformationController.java b/src/main/java/org/wise/portal/presentation/web/controllers/InformationController.java index f7e272ee1..b0fb2d753 100644 --- a/src/main/java/org/wise/portal/presentation/web/controllers/InformationController.java +++ b/src/main/java/org/wise/portal/presentation/web/controllers/InformationController.java @@ -679,6 +679,7 @@ private void getRunConfigParameters(HttpServletRequest request, JSONObject confi config.put("startTime", run.getStartTimeMilliseconds()); config.put("endTime", run.getEndTimeMilliseconds()); config.put("isLockedAfterEndDate", run.isLockedAfterEndDate()); + config.put("isSurvey", run.isSurvey()); } private void printConfigToResponse(HttpServletResponse response, JSONObject config) @@ -785,6 +786,7 @@ private void addDummyUserInfoToConfig(JSONObject config) { /** * Gets the workgroup for the logged in user + * * @param run * @return Workgroup for the logged in user */ diff --git a/src/main/java/org/wise/portal/presentation/web/controllers/run/RunInfoAPIController.java b/src/main/java/org/wise/portal/presentation/web/controllers/run/RunInfoAPIController.java index bf6993fda..061c36f08 100644 --- a/src/main/java/org/wise/portal/presentation/web/controllers/run/RunInfoAPIController.java +++ b/src/main/java/org/wise/portal/presentation/web/controllers/run/RunInfoAPIController.java @@ -62,6 +62,7 @@ private HashMap getRunInfo(Run run) { info.put("teacherFirstName", owner.getUserDetails().getFirstname()); info.put("teacherLastName", owner.getUserDetails().getLastname()); info.put("wiseVersion", run.getProject().getWiseVersion()); + info.put("isSurvey", run.isSurvey()); return info; } diff --git a/src/main/java/org/wise/portal/presentation/web/controllers/survey/SurveyAPIController.java b/src/main/java/org/wise/portal/presentation/web/controllers/survey/SurveyAPIController.java new file mode 100644 index 000000000..a475e5c71 --- /dev/null +++ b/src/main/java/org/wise/portal/presentation/web/controllers/survey/SurveyAPIController.java @@ -0,0 +1,150 @@ +package org.wise.portal.presentation.web.controllers.survey; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.wise.portal.dao.ObjectNotFoundException; +import org.wise.portal.domain.PeriodNotFoundException; +import org.wise.portal.domain.RunHasEndedException; +import org.wise.portal.domain.StudentUserAlreadyAssociatedWithRunException; +import org.wise.portal.domain.authentication.Gender; +import org.wise.portal.domain.authentication.impl.StudentUserDetails; +import org.wise.portal.domain.project.impl.Projectcode; +import org.wise.portal.domain.run.Run; +import org.wise.portal.domain.user.User; +import org.wise.portal.service.authentication.AuthorityNotFoundException; +import org.wise.portal.service.authentication.DuplicateUsernameException; +import org.wise.portal.service.authentication.UserDetailsService; +import org.wise.portal.service.run.RunService; +import org.wise.portal.service.student.StudentService; +import org.wise.portal.service.user.UserService; +import org.wise.portal.service.workgroup.WorkgroupService; + +import java.io.IOException; +import java.util.Date; +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +@RestController +@RequestMapping("/run-survey") +public class SurveyAPIController { + @Autowired + private AuthenticationManager authenticationManager; + + @Autowired + private RunService runService; + + @Autowired + private StudentService studentService; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private UserService userService; + + @Autowired + private WorkgroupService workgroupService; + + @GetMapping("/{code}") + public void launchSurveyRun(@PathVariable String code, HttpServletResponse response, + HttpServletRequest request) throws AuthorityNotFoundException, IOException, + DuplicateUsernameException, ObjectNotFoundException, PeriodNotFoundException, + StudentUserAlreadyAssociatedWithRunException, RunHasEndedException { + Projectcode projectCode = new Projectcode(code); + Run run = runService.retrieveRunByRuncode(projectCode.getRuncode()); + if (run.isSurvey() && isActive(run)) { + handleSurveyLaunched(response, request, run, projectCode); + } else { + sendRedirect(response, "/"); + } + } + + private boolean isActive(Run run) { + Date now = new Date(); + Date endTime = run.getEndtime(); + return run.getStarttime().before(now) && (endTime == null || endTime.after(now)); + } + + private void handleSurveyLaunched(HttpServletResponse response, HttpServletRequest request, + Run run, Projectcode projectCode) throws AuthorityNotFoundException, IOException, + DuplicateUsernameException, ObjectNotFoundException, PeriodNotFoundException, + StudentUserAlreadyAssociatedWithRunException, RunHasEndedException { + + Object principal = getSecurityContextHolderPrincipal(); + if (principal instanceof StudentUserDetails + && isStudentAssociatedWithRun(run, (StudentUserDetails) principal)) { + sendRedirect(response, "/student/unit/" + run.getId()); + return; + } else { + SecurityContextHolder.getContext().setAuthentication(null); + } + if (underWorkgroupLimit(run)) { + String password = RandomStringUtils.randomAlphanumeric(10); + User user = this.createNewStudentAccount(request.getLocale(), password); + loginStudent(request, user, password); + studentService.addStudentToRun(user, projectCode); + sendRedirect(response, "/student/unit/" + run.getId()); + } else { + sendRedirect(response, "/survey/workgroupLimitReached"); + } + } + + private void sendRedirect(HttpServletResponse response, String redirectUrl) throws IOException { + response.sendRedirect(redirectUrl); + } + + private Object getSecurityContextHolderPrincipal() { + return SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + } + + private boolean isStudentAssociatedWithRun(Run run, StudentUserDetails principal) { + return run.isStudentAssociatedToThisRun(userService.retrieveStudentById((principal).getId())); + } + + private boolean underWorkgroupLimit(Run run) { + return workgroupService.getWorkgroupsForRun(run).size() <= 1000; + } + + private void loginStudent(HttpServletRequest request, User user, String password) { + UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken( + user.getUserDetails().getUsername(), password); + Authentication auth = authenticationManager.authenticate(authReq); + SecurityContext sc = SecurityContextHolder.getContext(); + sc.setAuthentication(auth); + HttpSession session = request.getSession(true); + session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, sc); + } + + private User createNewStudentAccount(Locale locale, String password) + throws AuthorityNotFoundException, DuplicateUsernameException { + StudentUserDetails sud = new StudentUserDetails(); + sud.setFirstname("survey_student_" + RandomStringUtils.randomAlphanumeric(10)); + sud.setLastname(RandomStringUtils.randomAlphanumeric(10)); + sud.setBirthday(new Date()); + sud.setPassword(password); + sud.setGender(Gender.UNSPECIFIED); + sud.setEmailAddress("null@null.com"); + sud.setLanguage(locale.getLanguage()); + sud.setNumberOfLogins(1); + sud.setLastLoginTime(new Date()); + + User user = userService.createUser(sud); + user.getUserDetails().addAuthority( + userDetailsService.loadAuthorityByName(UserDetailsService.SURVEY_STUDENT_ROLE)); + return user; + } +} 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 b715857a5..559ba9040 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 @@ -255,6 +255,7 @@ private List getSharedOwnerPermissionsList(Run run, User user) { @PostMapping("/run/create") HashMap createRun(Authentication auth, HttpServletRequest request, @RequestParam("projectId") Long projectId, @RequestParam("periods") String periods, + @RequestParam boolean isSurvey, @RequestParam("maxStudentsPerTeam") Integer maxStudentsPerTeam, @RequestParam("startDate") Long startDate, @RequestParam(value = "endDate", required = false) Long endDate, @@ -263,8 +264,8 @@ HashMap createRun(Authentication auth, HttpServletRequest reques User user = userService.retrieveUserByUsername(auth.getName()); Locale locale = request.getLocale(); Set periodNames = createPeriodNamesSet(periods); - Run run = runService.createRun(projectId, user, periodNames, maxStudentsPerTeam, startDate, - endDate, isLockedAfterEndDate, locale); + Run run = runService.createRun(projectId, user, periodNames, isSurvey, maxStudentsPerTeam, + startDate, endDate, isLockedAfterEndDate, locale); return getRunMap(user, run); } diff --git a/src/main/java/org/wise/portal/presentation/web/controllers/user/UserAPIController.java b/src/main/java/org/wise/portal/presentation/web/controllers/user/UserAPIController.java index b53aeb566..ca965b81f 100644 --- a/src/main/java/org/wise/portal/presentation/web/controllers/user/UserAPIController.java +++ b/src/main/java/org/wise/portal/presentation/web/controllers/user/UserAPIController.java @@ -30,7 +30,6 @@ import org.wise.portal.domain.authentication.MutableUserDetails; import org.wise.portal.domain.authentication.impl.StudentUserDetails; import org.wise.portal.domain.authentication.impl.TeacherUserDetails; -import org.wise.portal.domain.group.Group; import org.wise.portal.domain.project.Project; import org.wise.portal.domain.run.Run; import org.wise.portal.domain.user.User; @@ -262,6 +261,7 @@ protected HashMap getRunMap(User user, Run run) { HashMap map = new HashMap(); map.put("id", run.getId()); map.put("name", run.getName()); + map.put("isSurvey", run.isSurvey()); map.put("maxStudentsPerTeam", run.getMaxWorkgroupSize()); map.put("runCode", run.getRuncode()); map.put("startTime", run.getStartTimeMilliseconds()); diff --git a/src/main/java/org/wise/portal/service/authentication/UserDetailsService.java b/src/main/java/org/wise/portal/service/authentication/UserDetailsService.java index 488f5141e..d303291f1 100644 --- a/src/main/java/org/wise/portal/service/authentication/UserDetailsService.java +++ b/src/main/java/org/wise/portal/service/authentication/UserDetailsService.java @@ -46,6 +46,8 @@ public interface UserDetailsService String STUDENT_ROLE = "ROLE_STUDENT"; + String SURVEY_STUDENT_ROLE = "ROLE_SURVEY_STUDENT"; + String AUTHOR_ROLE = "ROLE_AUTHOR"; String TRUSTED_AUTHOR_ROLE = "ROLE_TRUSTED_AUTHOR"; diff --git a/src/main/java/org/wise/portal/service/run/RunService.java b/src/main/java/org/wise/portal/service/run/RunService.java index 52ad5c438..e16c73998 100644 --- a/src/main/java/org/wise/portal/service/run/RunService.java +++ b/src/main/java/org/wise/portal/service/run/RunService.java @@ -58,8 +58,9 @@ public interface RunService { */ Run createRun(RunParameters runParameters) throws ObjectNotFoundException; - Run createRun(Long projectId, User user, Set periodNames, Integer maxStudentsPerTeam, - Long startDate, Long endDate, Boolean isLockedAfterEndDate, Locale locale) throws Exception; + Run createRun(Long projectId, User user, Set periodNames, boolean isSurvey, + Integer maxStudentsPerTeam, Long startDate, Long endDate, Boolean isLockedAfterEndDate, + Locale locale) throws Exception; /** * Ends this run. The side effect is that the run's endtime gets set. A Run that has ended is no diff --git a/src/main/java/org/wise/portal/service/run/impl/RunServiceImpl.java b/src/main/java/org/wise/portal/service/run/impl/RunServiceImpl.java index ea1f40187..0a7b47392 100644 --- a/src/main/java/org/wise/portal/service/run/impl/RunServiceImpl.java +++ b/src/main/java/org/wise/portal/service/run/impl/RunServiceImpl.java @@ -199,6 +199,7 @@ public Run createRun(RunParameters runParameters) { run.setStarttime(runParameters.getStartTime()); run.setRuncode(generateUniqueRunCode(runParameters.getLocale())); run.setOwner(runParameters.getOwner()); + run.setIsSurvey(runParameters.isSurvey()); run.setMaxWorkgroupSize(runParameters.getMaxWorkgroupSize()); run.setProject(project); run.setName("" + runParameters.getProject().getName()); @@ -239,11 +240,11 @@ public Run createRun(RunParameters runParameters) { } @Transactional() - public Run createRun(Long projectId, User user, Set periodNames, + public Run createRun(Long projectId, User user, Set periodNames, boolean isSurvey, Integer maxStudentsPerTeam, Long startDate, Long endDate, Boolean isLockedAfterEndDate, Locale locale) throws Exception { Project project = projectService.copyProject(projectId, user); - RunParameters runParameters = createRunParameters(project, user, periodNames, + RunParameters runParameters = createRunParameters(project, user, periodNames, isSurvey, maxStudentsPerTeam, startDate, endDate, isLockedAfterEndDate, locale); Run run = createRun(runParameters); createTeacherWorkgroup(run, user); @@ -252,8 +253,8 @@ public Run createRun(Long projectId, User user, Set periodNames, } public RunParameters createRunParameters(Project project, User user, Set periodNames, - Integer maxStudentsPerTeam, Long startDate, Long endDate, Boolean isLockedAfterEndDate, - Locale locale) { + boolean isSurvey, Integer maxStudentsPerTeam, Long startDate, Long endDate, + Boolean isLockedAfterEndDate, Locale locale) { RunParameters runParameters = new RunParameters(); runParameters.setOwner(user); runParameters.setName(project.getName()); @@ -261,6 +262,7 @@ public RunParameters createRunParameters(Project project, User user, Set runParameters.setLocale(locale); runParameters.setPostLevel(5); runParameters.setPeriodNames(periodNames); + runParameters.setSurvey(isSurvey); runParameters.setMaxWorkgroupSize(maxStudentsPerTeam); runParameters.setStartTime(new Date(startDate)); if (endDate == null || endDate <= startDate) { diff --git a/src/main/resources/wise_db_init.sql b/src/main/resources/wise_db_init.sql index 829b54663..c3339e802 100644 --- a/src/main/resources/wise_db_init.sql +++ b/src/main/resources/wise_db_init.sql @@ -330,6 +330,7 @@ create table runs ( end_time datetime, extras mediumtext, info varchar(255), + isSurvey bit not null default 0, lastRun datetime, loggingLevel integer, maxWorkgroupSize integer, @@ -563,7 +564,7 @@ CREATE TABLE `acl_object_identity_to_user_tags` ( -- initial data for wise below -INSERT INTO granted_authorities VALUES (1,'ROLE_USER',0),(2,'ROLE_ADMINISTRATOR',0),(3,'ROLE_TEACHER',0),(4,'ROLE_STUDENT',0),(5,'ROLE_AUTHOR',0),(6,'ROLE_RESEARCHER',0),(7,'ROLE_TRUSTED_AUTHOR',0),(8,'ROLE_TRANSLATOR',0); +INSERT INTO granted_authorities VALUES (1,'ROLE_USER',0),(2,'ROLE_ADMINISTRATOR',0),(3,'ROLE_TEACHER',0),(4,'ROLE_STUDENT',0),(5,'ROLE_AUTHOR',0),(6,'ROLE_RESEARCHER',0),(7,'ROLE_TRUSTED_AUTHOR',0),(8,'ROLE_TRANSLATOR',0),(9, 'ROLE_SURVEY_STUDENT'); INSERT INTO portal (id,portalname,settings,announcement,projectLibraryGroups,projectMetadataSettings,run_survey_template,sendmail_on_exception,OPTLOCK) VALUES (1,'My Production WISE Site (change me)','{isLoginAllowed:true}','{"visible":false,"bannerText":"","bannerButton":"","title":"","content":"","buttons":[]}','[]','{"fields":[{"name":"Title","key":"title","type":"input"},{"name":"Summary","key":"summary","type":"textarea"},{"name":"Language","key":"language","type":"radio","choices":["English","Chinese (Simplified)","Chinese (Traditional)","Dutch","German","Greek","Hebrew","Japanese","Korean","Portuguese","Spanish","Thai","Turkish"]},{"name":"Subject","key":"subject","type":"radio","choices":["Life Science","Physical Science","Earth Science","General Science","Biology","Chemistry","Physics","Other"]},{"name":"Time Required to Complete Project","key":"time","type":"input"},{"name":"Supported Devices","key":"supportedDevices","type":"checkbox","choices":["PC","Tablet"]}],"i18n":{"lifeScience":{"en":"Life Science","ja":"ライフサイエンス"},"earthScience":{"en":"Earth Science","ja":"地球科学"},"physicalScience":{"en":"Physical Science","ja":"物理科学","es":"ciencia física"}}}','{"save_time":null,"items":[{"id":"recommendProjectToOtherTeachers","type":"radio","prompt":"How likely would you recommend this project to other teachers?","choices":[{"id":"5","text":"Extremely likely"},{"id":"4","text":"Very likely"},{"id":"3","text":"Moderately likely"},{"id":"2","text":"Slightly likely"},{"id":"1","text":"Not at all likely"}],"answer":null},{"id":"runProjectAgain","type":"radio","prompt":"How likely would you run this project again?","choices":[{"id":"5","text":"Extremely likely"},{"id":"4","text":"Very likely"},{"id":"3","text":"Moderately likely"},{"id":"2","text":"Slightly likely"},{"id":"1","text":"Not at all likely"}],"answer":null},{"id":"useWISEAgain","type":"radio","prompt":"How likely would you use WISE again in your classroom?","choices":[{"id":"5","text":"Extremely likely"},{"id":"4","text":"Very likely"},{"id":"3","text":"Moderately likely"},{"id":"2","text":"Slightly likely"},{"id":"1","text":"Not at all likely"}],"answer":null},{"id":"adviceForOtherTeachers","type":"textarea","prompt":"Please share any advice for other teachers about this project or about WISE in general.","answer":null},{"id":"technicalProblems","type":"textarea","prompt":"Please write about any technical problems that you had while running this project.","answer":null},{"id":"generalFeedback","type":"textarea","prompt":"Please provide any other feedback to WISE staff.","answer":null}]}',1,0); diff --git a/src/test/java/org/wise/portal/presentation/web/controllers/survey/SurveyAPIControllerTest.java b/src/test/java/org/wise/portal/presentation/web/controllers/survey/SurveyAPIControllerTest.java new file mode 100644 index 000000000..511c3d5de --- /dev/null +++ b/src/test/java/org/wise/portal/presentation/web/controllers/survey/SurveyAPIControllerTest.java @@ -0,0 +1,214 @@ +package org.wise.portal.presentation.web.controllers.survey; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpServletRequest; + +import org.easymock.EasyMockExtension; +import org.easymock.Mock; +import org.easymock.TestSubject; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.context.SecurityContextImpl; +import org.wise.portal.domain.authentication.impl.StudentUserDetails; +import org.wise.portal.domain.group.Group; +import org.wise.portal.domain.group.impl.PersistentGroup; +import org.wise.portal.domain.project.impl.Projectcode; +import org.wise.portal.domain.run.Run; +import org.wise.portal.domain.run.impl.RunImpl; +import org.wise.portal.domain.user.User; +import org.wise.portal.domain.user.impl.UserImpl; +import org.wise.portal.domain.workgroup.Workgroup; +import org.wise.portal.domain.workgroup.impl.WorkgroupImpl; +import org.wise.portal.service.authentication.UserDetailsService; +import org.wise.portal.service.run.RunService; +import org.wise.portal.service.student.StudentService; +import org.wise.portal.service.user.UserService; +import org.wise.portal.service.workgroup.WorkgroupService; + +@ExtendWith(EasyMockExtension.class) +public class SurveyAPIControllerTest { + private Run run; + private TestingAuthenticationToken authority; + private SecurityContext securityContext; + private UserImpl studentUser = new UserImpl(); + private StudentUserDetails studentUserDetails = new StudentUserDetails(); + List workgroups; + + @TestSubject + SurveyAPIController surveyAPIController = new SurveyAPIController(); + + @Mock + AuthenticationManager authenticationManager; + + @Mock + HttpServletResponse httpServletResponse; + + @Mock + HttpServletRequest httpServletRequest; + + @Mock + HttpSession httpSession; + + @Mock + RunService runService; + + @Mock + StudentService studentService; + + @Mock + UserService userService; + + @Mock + UserDetailsService userDetailsService; + + @Mock + WorkgroupService workgroupService; + + private static final String[] periodnames = { "1", "2", "3", "6", "9", "10", "sunflower" }; + + @BeforeEach + public void setUp() { + run = new RunImpl(); + run.setId(1L); + run.setIsSurvey(true); + run.setStarttime(new Date(System.currentTimeMillis() - 3600 * 1000)); + Set periods = new TreeSet(); + for (String periodname : periodnames) { + Group period = new PersistentGroup(); + period.setName(periodname); + if (periodname.equals("1")) { + period.addMember(studentUser); + } + periods.add(period); + } + run.setPeriods(periods); + workgroups = new ArrayList(); + } + + SecurityContext getSecurityContext(Object principal, String authorityName) { + authority = new TestingAuthenticationToken(principal, + new GrantedAuthority[] { new SimpleGrantedAuthority(authorityName) }); + authority.setAuthenticated(true); + authority.setDetails(new StudentUserDetails()); + securityContext = new SecurityContextImpl(); + securityContext.setAuthentication(authority); + return securityContext; + } + + @Test + public void launchSurveyRun_NotASurvey_RedirectHomePage() throws Exception { + httpServletResponse.sendRedirect("/"); + expectLastCall(); + replay(httpServletResponse); + run.setIsSurvey(false); + expect(runService.retrieveRunByRuncode("dog1234")).andReturn(run); + replay(runService); + surveyAPIController.launchSurveyRun("dog1234-1", httpServletResponse, httpServletRequest); + verify(httpServletResponse); + verify(runService); + } + + @Test + public void launchSurveyRun_RunInFuture_RedirectHomePage() throws Exception { + httpServletResponse.sendRedirect("/"); + expectLastCall(); + replay(httpServletResponse); + run.setStarttime(new Date(System.currentTimeMillis() + 3600 * 1000)); // Future start time + expect(runService.retrieveRunByRuncode("dog1234")).andReturn(run); + replay(runService); + surveyAPIController.launchSurveyRun("dog1234-1", httpServletResponse, httpServletRequest); + verify(httpServletResponse); + verify(runService); + } + + @Test + public void launchSurveyRun_RunInPast_RedirectHomePage() throws Exception { + httpServletResponse.sendRedirect("/"); + expectLastCall(); + replay(httpServletResponse); + run.setEndtime(new Date(System.currentTimeMillis() - 3600 * 1000)); // Past end time + expect(runService.retrieveRunByRuncode("dog1234")).andReturn(run); + replay(runService); + surveyAPIController.launchSurveyRun("dog1234-1", httpServletResponse, httpServletRequest); + verify(httpServletResponse); + verify(runService); + } + + @Test + public void launchSurveyRun_AlreadyAssociatedWithRun_RedirectUnit() throws Exception { + httpServletResponse.sendRedirect("/student/unit/1"); + expectLastCall(); + replay(httpServletResponse); + expect(runService.retrieveRunByRuncode("dog1234")).andReturn(run); + replay(runService); + expect(userService.retrieveStudentById(null)).andReturn(studentUser); + replay(userService); + SecurityContextHolder.setContext(getSecurityContext(studentUserDetails, "ROLE_STUDENT")); + surveyAPIController.launchSurveyRun("dog1234-1", httpServletResponse, httpServletRequest); + verify(httpServletResponse, runService, userService); + } + + @Test + public void launchSurveyRun_OverWorkgroupLimit_RedirectWorkgroupLimitPage() throws Exception { + httpServletResponse.sendRedirect("/survey/workgroupLimitReached"); + expectLastCall(); + replay(httpServletResponse); + expect(userService.retrieveStudentById(1L)).andReturn(new UserImpl()); + expect(runService.retrieveRunByRuncode("dog1234")).andReturn(run); + replay(runService); + SecurityContextHolder.setContext(getSecurityContext("anonymousUser", "ROLE_ANONYMOUS")); + for (int i = 0; i < 1005; i++) { + workgroups.add(new WorkgroupImpl()); + } + expect(workgroupService.getWorkgroupsForRun(run)).andReturn(workgroups); + replay(workgroupService); + surveyAPIController.launchSurveyRun("dog1234-1", httpServletResponse, httpServletRequest); + verify(httpServletResponse, runService, workgroupService); + } + + @Test + public void launchSurveyRun_NoIssues_RedirectUnit() throws Exception { + httpServletResponse.sendRedirect("/student/unit/1"); + expectLastCall(); + replay(httpServletResponse); + expect(runService.retrieveRunByRuncode("dog1234")).andReturn(run); + replay(runService); + studentUser.setUserDetails(studentUserDetails); + expect(userService.createUser(studentUserDetails)).andReturn(studentUser); + replay(userService); + SecurityContextHolder.setContext(getSecurityContext("anonymousUser", "ROLE_ANONYMOUS")); + expect(workgroupService.getWorkgroupsForRun(run)).andReturn(new ArrayList()); + replay(workgroupService); + expect(userDetailsService.loadAuthorityByName("ROLE_SURVEY_STUDENT")).andReturn(null); + replay(userDetailsService); + expect(httpServletRequest.getLocale()).andReturn(new Locale("en")); + expect(httpServletRequest.getSession(true)).andReturn(httpSession); + replay(httpServletRequest); + studentService.addStudentToRun(isA(User.class), isA(Projectcode.class)); + expectLastCall(); + replay(studentService); + surveyAPIController.launchSurveyRun("dog1234-1", httpServletResponse, httpServletRequest); + verify(httpServletResponse, runService, workgroupService, studentService); + } +} 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 0f421c595..d07076070 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 @@ -364,10 +364,10 @@ public void createRun_ThreePeriods_CreateRun() throws Exception { periodNamesSet.add("1"); periodNamesSet.add("2"); periodNamesSet.add("free"); - expect(runService.createRun(projectId, teacher1, periodNamesSet, maxStudentsPerTeam, startDate, + expect(runService.createRun(projectId, teacher1, periodNamesSet, false, maxStudentsPerTeam, startDate, endDate, isLockedAfterEndDate, Locale.US)).andReturn(run1); replay(runService); - teacherAPIController.createRun(teacherAuth, request, projectId, periods, maxStudentsPerTeam, + teacherAPIController.createRun(teacherAuth, request, projectId, periods, false, maxStudentsPerTeam, startDate, endDate, isLockedAfterEndDate); verify(userService); verify(request);