Allow supervisors to request improvements from final seminar opponents #78

Merged
niat8586 merged 41 commits from opponent-completion into develop 2025-03-05 10:05:38 +01:00
44 changed files with 275 additions and 124 deletions
Showing only changes of commit a20455df97 - Show all commits

View File

@ -17,7 +17,7 @@ import se.su.dsv.scipro.checklist.ChecklistAnswerServiceImpl;
import se.su.dsv.scipro.checklist.ChecklistServiceImpl;
import se.su.dsv.scipro.checklist.ChecklistTemplateService;
import se.su.dsv.scipro.checklist.ChecklistTemplateServiceImpl;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPIImpl;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPIImpl;
import se.su.dsv.scipro.date.DateServiceImpl;
import se.su.dsv.scipro.file.FileDescriptionRepo;
import se.su.dsv.scipro.file.FileReferenceRepository;

View File

@ -226,6 +226,11 @@ public class DataInitializer implements Lifecycle {
stina_student = createStudent(STUDENT_2);
sid_student = createStudent(STUDENT_3);
simon_student = createStudent(STUDENT_4);
// Used to test submitting ideas
// can not be used as author on any idea
// can not be used as author on any project
createStudent("Stig");
}
private User createStudent(String firstName) {

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.exceptions;
package se.su.dsv.scipro.daisyexternal.exceptions;
public class ExternalImportException extends RuntimeException {

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http;
package se.su.dsv.scipro.daisyexternal.http;
import jakarta.ws.rs.core.Response;
import java.io.InputStream;
@ -6,7 +6,26 @@ import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import se.su.dsv.scipro.io.dto.*;
import se.su.dsv.scipro.io.dto.AddThesisAuthor;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.CourseRegistration;
import se.su.dsv.scipro.io.dto.Employee;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Program;
import se.su.dsv.scipro.io.dto.ProgramAdmission;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.PublishingConsent;
import se.su.dsv.scipro.io.dto.PublishingConsentLevel;
import se.su.dsv.scipro.io.dto.ResearchArea;
import se.su.dsv.scipro.io.dto.ResearchSubject;
import se.su.dsv.scipro.io.dto.StudentProgramAdmission;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.ThesisPublication;
import se.su.dsv.scipro.io.dto.ThesisRejection;
import se.su.dsv.scipro.io.dto.ThesisToBeCreated;
import se.su.dsv.scipro.io.dto.ThesisToBeUpdated;
import se.su.dsv.scipro.io.dto.Unit;
import se.su.dsv.scipro.io.dto.UserName;
public interface DaisyAPI {
Set<ProjectParticipant> getContributors(Integer projectId);

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http;
package se.su.dsv.scipro.daisyexternal.http;
import static jakarta.ws.rs.client.Entity.xml;
@ -16,9 +16,33 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import se.su.dsv.scipro.io.dto.*;
import se.su.dsv.scipro.io.dto.AddThesisAuthor;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.CourseRegistration;
import se.su.dsv.scipro.io.dto.Employee;
import se.su.dsv.scipro.io.dto.ObjectFactory;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Program;
import se.su.dsv.scipro.io.dto.ProgramAdmission;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.PublishingConsent;
import se.su.dsv.scipro.io.dto.PublishingConsentLevel;
import se.su.dsv.scipro.io.dto.ResearchArea;
import se.su.dsv.scipro.io.dto.ResearchSubject;
import se.su.dsv.scipro.io.dto.StudentProgramAdmission;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.ThesisPublication;
import se.su.dsv.scipro.io.dto.ThesisRejection;
import se.su.dsv.scipro.io.dto.ThesisToBeCreated;
import se.su.dsv.scipro.io.dto.ThesisToBeUpdated;
import se.su.dsv.scipro.io.dto.Unit;
import se.su.dsv.scipro.io.dto.UserName;
public class DaisyAPIImpl implements DaisyAPI {
@ -364,8 +388,7 @@ public class DaisyAPIImpl implements DaisyAPI {
@Override
public OrganisationalUnit orgunit(final int unitId) {
return () ->
target()
.path("orgunit")
units()
.path(Integer.toString(unitId))
.path("researchAreas")
.request(MediaType.APPLICATION_XML_TYPE)

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http;
package se.su.dsv.scipro.daisyexternal.http;
import java.util.List;
import se.su.dsv.scipro.io.dto.ResearchArea;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http;
package se.su.dsv.scipro.daisyexternal.http;
import java.io.InputStream;
import java.util.function.Function;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http;
package se.su.dsv.scipro.daisyexternal.http;
public abstract class Semester {

View File

@ -1,9 +1,6 @@
package se.su.dsv.scipro.workerthreads;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityTransaction;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -58,6 +55,22 @@ public abstract class AbstractWorker implements Worker {
* Do manually transaction-handled work
*/
try {
// When the switch from Guice to Spring happened all workers became singletons
// because that's the default in Spring. In Guice they were "prototype" scoped
// and therefore the worker object was re-created before each execution which
// reset the successfulWorker field to true.
//
// Now that they're singletons the field is never reset to true after a
// failure and the worker will be stuck in a failed state even after a
// subsequent successful run.
//
// TODO:
// In the future this flag should be removed and any execution that does
// not throw an exception should be considered successful.
// If a worker needs to signal a non-exception as a failure that should
// be an internal matter and not something the scheduler should consider.
setSuccessfulWorker(true);
doWork();
} catch (RuntimeException ex) {
LOGGER.info("Worker {} threw an exception", getClass().getSimpleName());

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
version="3.0">
<jaxb:globalBindings>
<!-- Use java.util.Calendar instead of javax.xml.datatype.XMLGregorianCalendar for xs:dateTime -->
@ -12,4 +13,11 @@
<xjc:simple />
<xjc:serializable uid="1" />
</jaxb:globalBindings>
<jaxb:bindings schemaLocation="../xsd/daisy_api.xsd" node="/xs:schema">
<jaxb:bindings node="xs:simpleType[@name='status']" >
<jaxb:typesafeEnumClass name="Status2" />
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema version="1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="addThesisAuthor" type="addThesisAuthor"/>
<xs:element name="courseRegistrationForCourse" type="courseRegistrationGet"/>
@ -62,6 +60,7 @@
<xs:element name="degree" type="degree"/>
<xs:element name="programAdmission" type="programAdmission"/>
<xs:element name="student" type="student"/>
<xs:complexType name="addThesisAuthor">
<xs:sequence>
<xs:element name="student" type="AddThesisAuthorStudent" minOccurs="1">
@ -75,6 +74,8 @@
<xs:sequence>
<xs:element name="level" type="educationalLevel" minOccurs="1">
</xs:element>
<xs:element name="courseCredits" type="xs:decimal" minOccurs="0">
</xs:element>
<xs:element name="department" type="serializableUnit" minOccurs="1">
</xs:element>
</xs:sequence>
@ -615,6 +616,8 @@
</xs:element>
<xs:element name="break" type="xs:boolean" minOccurs="1">
</xs:element>
<xs:element name="reparticipant" type="xs:boolean" minOccurs="1">
</xs:element>
<xs:element name="inactive" type="xs:boolean" minOccurs="1">
</xs:element>
<xs:element name="userName" type="xs:string" minOccurs="0">

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.http;
package se.su.dsv.scipro.daisyexternal.http;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal;
package se.su.dsv.scipro.daisyexternal;
/**
* Specifies interaction of an importing service component.

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal;
package se.su.dsv.scipro.daisyexternal;
import java.util.Map;
import se.su.dsv.scipro.io.dto.Person;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.impl;
package se.su.dsv.scipro.daisyexternal.impl;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
@ -6,10 +6,10 @@ import jakarta.ws.rs.ClientErrorException;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.ExternalImporter;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.exceptions.ExternalImportException;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.ExternalImporter;
import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyexternal.exceptions.ExternalImportException;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Employee;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Thesis;

View File

@ -1,23 +1,43 @@
package se.su.dsv.scipro.daisyExternal.impl;
package se.su.dsv.scipro.daisyexternal.impl;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.core.Response;
import java.util.*;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.*;
import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Course;
import se.su.dsv.scipro.io.dto.CourseRegistration;
import se.su.dsv.scipro.io.dto.EducationalLevel;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProgramType;
import se.su.dsv.scipro.io.dto.ResearchArea;
import se.su.dsv.scipro.io.dto.StudentProgramAdmission;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.UserName;
import se.su.dsv.scipro.match.ProgramService;
import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.project.ProjectService;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.system.*;
import se.su.dsv.scipro.system.DegreeType;
import se.su.dsv.scipro.system.Language;
import se.su.dsv.scipro.system.Program;
import se.su.dsv.scipro.system.ResearchAreaService;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.system.UserNameService;
import se.su.dsv.scipro.system.UserService;
import se.su.dsv.scipro.system.Username;
import se.su.dsv.scipro.util.Pair;
@Named

View File

@ -4,7 +4,7 @@ import jakarta.inject.Inject;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.WebApplicationException;
import java.util.List;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.finalthesis.PublishingConsentService;
import se.su.dsv.scipro.io.dto.PublishingConsentLevel;
import se.su.dsv.scipro.project.Project;

View File

@ -5,11 +5,11 @@ import jakarta.inject.Provider;
import jakarta.persistence.EntityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import se.su.dsv.scipro.daisyExternal.ExternalImporter;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyExternal.impl.ExternalImporterDaisyImpl;
import se.su.dsv.scipro.daisyExternal.impl.ImporterTransactionsImpl;
import se.su.dsv.scipro.daisyexternal.ExternalImporter;
import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.impl.ExternalImporterDaisyImpl;
import se.su.dsv.scipro.daisyexternal.impl.ImporterTransactionsImpl;
import se.su.dsv.scipro.finalseminar.FinalSeminarService;
import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.forum.ProjectForumService;

View File

@ -9,7 +9,7 @@ import java.util.Objects;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.system.UserSearchProvider;

View File

@ -6,7 +6,7 @@ import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import java.util.Objects;
import java.util.Set;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.Role;

View File

@ -9,7 +9,7 @@ import java.util.Optional;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.GradingCompletedEvent;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Course;

View File

@ -3,7 +3,7 @@ package se.su.dsv.scipro.integration.daisy.workers;
import jakarta.inject.Inject;
import java.util.List;
import java.util.Optional;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.NationalSubjectCategory;
import se.su.dsv.scipro.grading.NationalSubjectCategoryService;
import se.su.dsv.scipro.io.dto.ResearchSubject;

View File

@ -16,14 +16,22 @@ import java.util.function.Predicate;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.finalseminar.FinalSeminar;
import se.su.dsv.scipro.finalseminar.FinalSeminarParticipation;
import se.su.dsv.scipro.finalseminar.FinalSeminarService;
import se.su.dsv.scipro.finalthesis.FinalThesis;
import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.io.ExternalExporter;
import se.su.dsv.scipro.io.dto.*;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.ResearchAreaWithID;
import se.su.dsv.scipro.io.dto.ResearchAreas;
import se.su.dsv.scipro.io.dto.Role;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.ThesisToBeUpdated;
import se.su.dsv.scipro.io.dto.UnitWithID;
import se.su.dsv.scipro.io.exceptions.ExternalExportException;
import se.su.dsv.scipro.io.facade.ExporterFacade;
import se.su.dsv.scipro.project.Project;

View File

@ -6,7 +6,7 @@ import java.time.Instant;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.ThesisApprovedHistoryService;
import se.su.dsv.scipro.io.dto.STATUS;
import se.su.dsv.scipro.project.Project;

View File

@ -4,7 +4,7 @@ import jakarta.inject.Inject;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.finalthesis.FinalThesis;
import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.forum.ProjectForumService;

View File

@ -8,10 +8,10 @@ import java.util.*;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.ExternalImporter;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyExternal.http.Semester;
import se.su.dsv.scipro.daisyexternal.ExternalImporter;
import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.Semester;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Program;
import se.su.dsv.scipro.io.dto.ProgramAdmission;

View File

@ -2,18 +2,26 @@ package se.su.dsv.scipro.io.impl;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.ExternalExporter;
import se.su.dsv.scipro.io.dto.*;
import se.su.dsv.scipro.io.dto.AddThesisAuthor;
import se.su.dsv.scipro.io.dto.AddThesisAuthorCourse;
import se.su.dsv.scipro.io.dto.AddThesisAuthorStudent;
import se.su.dsv.scipro.io.dto.EducationalLevel;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.ResearchAreaWithID;
import se.su.dsv.scipro.io.dto.ResearchAreas;
import se.su.dsv.scipro.io.dto.Role;
import se.su.dsv.scipro.io.dto.ThesisToBeCreated;
import se.su.dsv.scipro.io.dto.UnitWithID;
import se.su.dsv.scipro.io.exceptions.ExternalExportException;
import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.reusable.SciProUtilities;
import se.su.dsv.scipro.system.DegreeType;
import se.su.dsv.scipro.system.Unit;
import se.su.dsv.scipro.system.User;
@ -23,14 +31,6 @@ public class ExternalExporterDaisyImpl implements ExternalExporter {
static final int MAX_TITLE_LENGTH = 255;
private static final int DSV = 4;
private static Map<DegreeType, EducationalLevel> classMap = new HashMap<>() {
{
put(DegreeType.NONE, EducationalLevel.UNKNOWN);
put(DegreeType.BACHELOR, EducationalLevel.FIRST_CYCLE);
put(DegreeType.MAGISTER, EducationalLevel.SECOND_CYCLE);
put(DegreeType.MASTER, EducationalLevel.SECOND_CYCLE);
}
};
private final DaisyAPI api;
@ -82,7 +82,21 @@ public class ExternalExporterDaisyImpl implements ExternalExporter {
}
private EducationalLevel toDaisyLevel(Project project) {
return classMap.get(project.getProjectTypeDegreeType());
return switch (project.getProjectTypeDegreeType()) {
case NONE -> EducationalLevel.UNKNOWN;
case BACHELOR -> EducationalLevel.FIRST_CYCLE;
case MAGISTER -> EducationalLevel.SECOND_CYCLE;
case MASTER -> EducationalLevel.SECOND_CYCLE;
};
}
private static BigDecimal toDaisyCredits(Project project) {
return switch (project.getProjectTypeDegreeType()) {
case BACHELOR -> BigDecimal.valueOf(15);
case MAGISTER -> BigDecimal.valueOf(15);
case MASTER -> BigDecimal.valueOf(30);
case NONE -> null;
};
}
@Override
@ -95,6 +109,7 @@ public class ExternalExporterDaisyImpl implements ExternalExporter {
AddThesisAuthorCourse authorCourse = new AddThesisAuthorCourse();
authorCourse.setLevel(toDaisyLevel(project));
authorCourse.setDepartment(department);
authorCourse.setCourseCredits(toDaisyCredits(project));
AddThesisAuthor addThesisAuthor = new AddThesisAuthor();
addThesisAuthor.setCourse(authorCourse);

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.impl;
package se.su.dsv.scipro.daisyexternal.impl;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
@ -9,8 +9,8 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.springdata.services.UnitService;
import se.su.dsv.scipro.system.UserImportService;

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro.daisyExternal.impl;
package se.su.dsv.scipro.daisyexternal.impl;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
@ -12,12 +12,17 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.UserName;
import se.su.dsv.scipro.match.ProgramService;
import se.su.dsv.scipro.project.ProjectService;
import se.su.dsv.scipro.system.*;
import se.su.dsv.scipro.system.ProjectTypeService;
import se.su.dsv.scipro.system.ResearchAreaService;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.system.UserNameService;
import se.su.dsv.scipro.system.UserService;
import se.su.dsv.scipro.system.Username;
@ExtendWith(MockitoExtension.class)
public class ImporterTransactionsImplTest {

View File

@ -11,7 +11,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.GradingCompletedEvent;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Course;

View File

@ -14,11 +14,16 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.finalseminar.FinalSeminarService;
import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.io.ExternalExporter;
import se.su.dsv.scipro.io.dto.*;
import se.su.dsv.scipro.io.dto.AuthorProjectParticipant;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.ProjectParticipant;
import se.su.dsv.scipro.io.dto.Role;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.io.dto.ThesisToBeUpdated;
import se.su.dsv.scipro.io.facade.ExporterFacade;
import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.project.ProjectRepo;

View File

@ -13,7 +13,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.grading.ThesisApprovedHistoryService;
import se.su.dsv.scipro.io.dto.STATUS;
import se.su.dsv.scipro.io.dto.Thesis;

View File

@ -4,15 +4,19 @@ import static java.util.Arrays.asList;
import static org.mockito.Mockito.*;
import jakarta.persistence.EntityManager;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.ExternalImporter;
import se.su.dsv.scipro.daisyExternal.ImporterTransactions;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.ExternalImporter;
import se.su.dsv.scipro.daisyexternal.ImporterTransactions;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.Person;
import se.su.dsv.scipro.io.dto.Thesis;
import se.su.dsv.scipro.match.ProgramService;

View File

@ -16,7 +16,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.io.dto.ThesisToBeCreated;
import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.reusable.SciProUtilities;

View File

@ -72,4 +72,22 @@
</notes>
<cve>CVE-2024-23076</cve>
</suppress>
<suppress>
<notes>
https://nvd.nist.gov/vuln/detail/CVE-2024-49203
https://github.com/querydsl/querydsl/issues/3757
Basically if you allow untrusted user input to be used in the "ORDER BY" clause
you can be vulnerable to SQL injection.
I believe this is nonsense and akin to saying every Java application has a
security vulnerability because JDBC allows you to execute arbitrary SQL if you
do not properly use PreparedStatement with parameters over a string-concatenated
Statement.
Even if this is considered a valid vulnerability we do not, currently, allow
untrusted user input to be used in the "ORDER BY" clause.
</notes>
<cve>CVE-2024-49203</cve>
</suppress>
</suppressions>

View File

@ -24,7 +24,7 @@
<!-- Dependency versions -->
<slf4j.version>2.0.7</slf4j.version>
<log4j2.version>2.20.0</log4j2.version>
<wicket.version>10.1.0</wicket.version>
<wicket.version>10.4.0</wicket.version>
<!-- See https://hibernate.org/orm/releases/ for which version Hibernate implements -->
<jakarta.persistence-api.version>3.1.0</jakarta.persistence-api.version>
@ -39,6 +39,8 @@
<jersey.version>3.1.6</jersey.version>
<poi.version>5.2.5</poi.version>
<jackson.version>2.17.0</jackson.version>
<spring.boot.version>3.4.1</spring.boot.version>
<springdoc.openapi.version>2.8.3</springdoc.openapi.version>
<!-- Database stuff -->
<database.showSql>false</database.showSql>
@ -100,7 +102,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.2.12</version>
<version>${spring.boot.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
@ -261,7 +263,7 @@
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.5.0</version>
<version>${springdoc.openapi.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -178,7 +178,13 @@ class ReflectionModalBodyPanel extends Panel {
public SupervisorEditReflectionForm(String id, IModel<Reflection> reflectionModel) {
super(id, reflectionModel);
IModel<String> reflectionTextModel = new Model<>(getReflectionText(reflectionModel.getObject()));
IModel<String> reflectionTextModel = new Model<>();
Reflection reflection = reflectionModel.getObject();
if (reflection instanceof Reflection.Submitted submitted) {
reflectionTextModel.setObject(submitted.reflection());
} else if (reflection instanceof Reflection.ImprovementsNeeded improvementsNeeded) {
reflectionTextModel.setObject(improvementsNeeded.oldReflection());
}
TextArea<String> reflectionTextArea = new TextArea<>("reflection", reflectionTextModel);
reflectionTextArea.setRequired(true);

View File

@ -20,7 +20,7 @@ import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import se.su.dsv.scipro.components.BootstrapDatePicker;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.file.FileDescription;
import se.su.dsv.scipro.file.FileService;
import se.su.dsv.scipro.finalseminar.FinalSeminar;

View File

@ -8,6 +8,7 @@
<wicket:panel>
<div class="mb-3">
<label class="col-form-label" wicket:for="background">Background</label>
<div wicket:id="background_feedback"></div>
<textarea wicket:id="background" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary">
Describe the background of your topic, preferably both theoretical, empirical and/or practical.
@ -16,6 +17,7 @@
<div class="mb-3">
<label class="col-form-label" wicket:for="literature">Literature</label>
<div wicket:id="literature_feedback"></div>
<textarea wicket:id="literature" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary">
Describe the connection to your background, for example literature, theory and methodology related to the topic, courses that you have taken that relates to the topic.
@ -24,6 +26,7 @@
<div class="mb-3">
<label class="col-form-label" wicket:for="problem">Problem</label>
<div wicket:id="problem_feedback"></div>
<textarea wicket:id="problem" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary">
Here you describe the problem you want to address and solve by your work, preferably formulated as a research question.
@ -32,6 +35,7 @@
<div class="mb-3">
<label class="col-form-label" wicket:for="method">Method</label>
<div wicket:id="method_feedback"></div>
<textarea wicket:id="method" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary">
The method you plan to use in order to solve the problem and answer the research question.
@ -40,6 +44,7 @@
<div class="mb-3">
<label class="col-form-label" wicket:for="interests">My interests</label>
<div wicket:id="interests_feedback"></div>
<textarea wicket:id="interests" class="form-control" rows="4"></textarea>
<small class="form-text text-body-secondary">
Please note that when you propose your own topic, it is not guaranteed that your topic will be approved. In that case, you will be assigned a different topic by your supervisor. Specify which topics of interest you have, relating to the research fields or the courses that you have taken at DSV.

View File

@ -1,6 +1,7 @@
package se.su.dsv.scipro.match;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LambdaModel;
@ -12,36 +13,20 @@ public class IdeaTholanderCompletionPanel extends Panel {
super(id, model);
final IModel<TholanderBox> tholanderBox = model.map(Idea::getTholanderBox);
final StringValidator lengthValidator = StringValidator.maximumLength(TholanderBox.MAX_CHARS);
add(
new TextArea<>(
"background",
LambdaModel.of(tholanderBox, TholanderBox::getBackground, TholanderBox::setBackground)
).add(lengthValidator)
);
add(
new TextArea<>(
"literature",
LambdaModel.of(tholanderBox, TholanderBox::getLiterature, TholanderBox::setLiterature)
).add(lengthValidator)
);
add(
new TextArea<>(
"problem",
LambdaModel.of(tholanderBox, TholanderBox::getProblem, TholanderBox::setProblem)
).add(lengthValidator)
);
add(
new TextArea<>(
"method",
LambdaModel.of(tholanderBox, TholanderBox::getMethod, TholanderBox::setMethod)
).add(lengthValidator)
);
add(
new TextArea<>(
"interests",
LambdaModel.of(tholanderBox, TholanderBox::getInterests, TholanderBox::setInterests)
).add(lengthValidator)
);
textField("background", LambdaModel.of(tholanderBox, TholanderBox::getBackground, TholanderBox::setBackground));
textField("literature", LambdaModel.of(tholanderBox, TholanderBox::getLiterature, TholanderBox::setLiterature));
textField("problem", LambdaModel.of(tholanderBox, TholanderBox::getProblem, TholanderBox::setProblem));
textField("method", LambdaModel.of(tholanderBox, TholanderBox::getMethod, TholanderBox::setMethod));
textField("interests", LambdaModel.of(tholanderBox, TholanderBox::getInterests, TholanderBox::setInterests));
}
private void textField(String id, IModel<String> model) {
TextArea<String> textArea = new TextArea<>(id, model);
textArea.add(StringValidator.maximumLength(TholanderBox.MAX_CHARS));
textArea.setRequired(true);
add(textArea);
ComponentFeedbackPanel feedback = new ComponentFeedbackPanel(id + "_feedback", textArea);
add(feedback);
}
}

View File

@ -17,7 +17,14 @@
an idea if you couldn't find any suitable supervisor provided ideas.
</div>
<form wicket:id="ideaForm">
<!--
Turn off all client-side validation using novalidate.
All input is validated server-side, and we want to validate it
that way to get nice error messages.
However, we also want to maintain the required/minlength/whatever
attributes on the input fields for accessibility.
-->
<form wicket:id="ideaForm" novalidate>
<div class="mb-3">
<label class="col-form-label" wicket:for="title">Title</label>
<p class="form-text">

View File

@ -26,7 +26,7 @@ you.are.partner.on.other.idea= You have already been added as a partner to anoth
too.many.authors= Too many authors for a ${name}-idea. May not be more than ${maxAuthors} including yourself.
too.few.authors= Too few authors for a ${name}-idea. Must be at least ${minAuthors} including yourself.
keywordError= You need to select between 1 and 5 keywords.
submissionFailed= Idea could not be submitted.
submissionFailed= Idea could not be submitted. Correct the highlighted fields and try again.
ideaSubmitted= You have successfully submitted your ${projectType.name} student idea, for the application period \
${applicationPeriod.name}.
ideaUpdated= You have successfully updated your ${projectType.name} student idea, in the application period \

View File

@ -14,8 +14,8 @@ import org.apache.wicket.injection.Injector;
import org.apache.wicket.request.resource.AbstractResource;
import org.apache.wicket.request.resource.IResource;
import org.apache.wicket.request.resource.ResourceReference;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyExternal.http.PhotoResult;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.PhotoResult;
import se.su.dsv.scipro.data.dataobjects.Member;
import se.su.dsv.scipro.finalseminar.FinalSeminarService;
import se.su.dsv.scipro.project.Project;

View File

@ -30,8 +30,8 @@ import se.su.dsv.scipro.checklist.ChecklistCategoryRepo;
import se.su.dsv.scipro.checklist.ChecklistQuestionRepo;
import se.su.dsv.scipro.checklist.ChecklistService;
import se.su.dsv.scipro.checklist.ChecklistTemplateService;
import se.su.dsv.scipro.daisyExternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyExternal.http.PhotoResult;
import se.su.dsv.scipro.daisyexternal.http.DaisyAPI;
import se.su.dsv.scipro.daisyexternal.http.PhotoResult;
import se.su.dsv.scipro.data.enums.DateStyle;
import se.su.dsv.scipro.date.DateService;
import se.su.dsv.scipro.examiner.pages.ExaminerStartPage;