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);