67: merge from develop

This commit is contained in:
Tom Zhao 2025-02-12 13:35:21 +01:00
commit 1b692f87fb
10 changed files with 113 additions and 58 deletions

@ -13,12 +13,6 @@ COPY view/pom.xml view/pom.xml
COPY war/pom.xml war/pom.xml
COPY daisy-integration/pom.xml daisy-integration/pom.xml
# Download dependencies in a separate layer to allow caching for future builds
RUN ./mvnw dependency:go-offline \
--batch-mode \
--define includeScope=compile \
--activate-profiles docker-dependencies
COPY api/src/ api/src/
COPY core/src/ core/src/
COPY view/src/ view/src/
@ -26,7 +20,6 @@ COPY war/src/ war/src/
COPY daisy-integration/src/ daisy-integration/src/
RUN ./mvnw package \
--offline \
--define skipTests \
--activate-profiles branch,DEV \
--define skip.npm \

@ -21,6 +21,8 @@ services:
- OAUTH2_RESOURCE_SERVER_ID=scipro_api_client
- OAUTH2_RESOURCE_SERVER_SECRET=scipro_api_secret
- OAUTH2_RESOURCE_SERVER_INTROSPECTION_URI=https://oauth2-${VHOST}/introspect
- OAUTH2_GS_AUTHORIZATION_URI=https://oauth2-gs-${VHOST}
- OAUTH2_GS_CLIENT_REDIRECT_URI=https://${VHOST}/oauth/callback
networks:
- traefik
- internal
@ -64,6 +66,25 @@ services:
- "traefik.http.routers.oauth2-${COMPOSE_PROJECT_NAME}.rule=Host(`oauth2-${VHOST}`)"
- "traefik.http.routers.oauth2-${COMPOSE_PROJECT_NAME}.tls.certresolver=letsencrypt"
oauth2-gs:
build:
context: https://github.com/dsv-su/toker.git
dockerfile: embedded.Dockerfile
restart: unless-stopped
environment:
- CLIENT_ID=scipro_client
- CLIENT_SECRET=scipro_secret
- CLIENT_REDIRECT_URI=https://${VHOST}/oauth/callback
- RESOURCE_SERVER_ID=scipro_api_client
- RESOURCE_SERVER_SECRET=scipro_api_secret
- CLIENT_SCOPES=grade:read grade:write
networks:
- traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.oauth2-gs-${COMPOSE_PROJECT_NAME}.rule=Host(`oauth2-gs-${VHOST}`)"
- "traefik.http.routers.oauth2-gs-${COMPOSE_PROJECT_NAME}.tls.certresolver=letsencrypt"
networks:
traefik:
name: traefik

@ -4,12 +4,18 @@ import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Month;
import java.util.*;
import java.util.function.Function;
import se.su.dsv.scipro.checklist.ChecklistCategory;
import se.su.dsv.scipro.file.FileUpload;
import se.su.dsv.scipro.match.*;
import se.su.dsv.scipro.match.ApplicationPeriod;
import se.su.dsv.scipro.match.Keyword;
import se.su.dsv.scipro.milestones.dataobjects.MilestoneActivityTemplate;
import se.su.dsv.scipro.milestones.dataobjects.MilestonePhaseTemplate;
import se.su.dsv.scipro.milestones.service.MilestoneActivityTemplateService;
@ -19,6 +25,8 @@ import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.report.AbstractGradingCriterion;
import se.su.dsv.scipro.report.GradingCriterionPointTemplate;
import se.su.dsv.scipro.report.GradingReportTemplate;
import se.su.dsv.scipro.reviewing.ReviewerAssignmentService;
import se.su.dsv.scipro.reviewing.RoughDraftApprovalService;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.system.*;
@ -47,6 +55,12 @@ public class DataInitializer implements Lifecycle {
@Inject
private Provider<EntityManager> em;
@Inject
private RoughDraftApprovalService roughDraftApprovalService;
@Inject
private ReviewerAssignmentService reviewerAssignmentService;
private static final String MAIL = "@example.com";
private static final String ADMIN = "admin";
@ -82,6 +96,7 @@ public class DataInitializer implements Lifecycle {
private ProjectType masterClass;
private ProjectType magisterClass;
private ApplicationPeriod applicationPeriod;
private Project project2;
@Transactional
@Override
@ -99,12 +114,23 @@ public class DataInitializer implements Lifecycle {
createProjects();
createTarget();
createStudentIdea();
createRoughDraftApproval();
}
if (profile.getCurrentProfile() == Profiles.DEV && noAdminUser()) {
createAdmin();
}
}
private void createRoughDraftApproval() {
roughDraftApprovalService.requestApproval(
project2,
new SimpleTextFile(project2.getHeadSupervisor(), "thesis.txt", "text/plain"),
"Please approve"
);
reviewerAssignmentService.assignReviewer(project2, eric_employee);
}
@Override
public void stop() {}
@ -165,10 +191,10 @@ public class DataInitializer implements Lifecycle {
private void createProjects() {
createProject(PROJECT_1, eric_employee, sture_student, stina_student, eve_employee);
createProject(PROJECT_2, eve_employee, sid_student, simon_student, eric_employee);
project2 = createProject(PROJECT_2, eve_employee, sid_student, simon_student, eric_employee);
}
private void createProject(String title, User headSupervisor, User student1, User student2, User reviewer) {
private Project createProject(String title, User headSupervisor, User student1, User student2, User reviewer) {
Project project = Project.builder()
.title(title)
.projectType(bachelorClass)
@ -179,6 +205,7 @@ public class DataInitializer implements Lifecycle {
project.addProjectParticipant(student1);
project.addReviewer(reviewer);
save(project);
return project;
}
private void createUsers() {
@ -1960,4 +1987,42 @@ public class DataInitializer implements Lifecycle {
em.get().persist(entity);
return entity;
}
private static final class SimpleTextFile implements FileUpload {
private final User uploader;
private final String fileName;
private final String content;
private SimpleTextFile(User uploader, String fileName, String content) {
this.uploader = uploader;
this.fileName = fileName;
this.content = content;
}
@Override
public String getFileName() {
return fileName;
}
@Override
public String getContentType() {
return "text/plain";
}
@Override
public User getUploader() {
return uploader;
}
@Override
public long getSize() {
return content.length();
}
@Override
public <T> T handleData(Function<InputStream, T> handler) {
return handler.apply(new ByteArrayInputStream(content.getBytes()));
}
}
}

@ -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>

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

@ -4,6 +4,7 @@
<wicket:panel>
<strong>Current thesis:</strong> <span wicket:id="currentThesis">[thesis.pdf (2014-08-08)]</span><br>
<strong>Status:</strong> <span wicket:id="currentStatus">[Undecided]</span> <br>
<strong>Deadline:</strong> <span wicket:id="deadline">[Undecided]</span> <br>
<strong>Supervisor comment:</strong> <span wicket:id="currentDecision.comment">[Undecided]</span> <br>
<wicket:enclosure>
<strong>Reason:</strong> <span wicket:id="currentReason">[I need more time]</span><br>

@ -28,6 +28,7 @@ public class FinalSeminarApprovalProcessPanel extends GenericPanel<ReviewerAppro
)
);
add(new EnumLabel<>("currentStatus", process.map(ReviewerApproval::getCurrentStatus)));
add(new DateLabel("deadline", process.map(ReviewerApproval::getCurrentDeadline)));
add(
new MultiLineLabel(
"currentDecision.comment",

@ -10,6 +10,7 @@ import org.apache.wicket.model.LoadableDetachableModel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import se.su.dsv.scipro.SciProTest;
import se.su.dsv.scipro.components.DateLabel;
import se.su.dsv.scipro.file.FileDescription;
import se.su.dsv.scipro.file.FileReference;
import se.su.dsv.scipro.project.Project;
@ -44,6 +45,12 @@ public class FinalSeminarApprovalProcessPanelTest extends SciProTest {
tester.assertModelValue(path(panel, "currentStatus"), finalSeminarApproval.getCurrentStatus());
}
@Test
public void shows_deadline() {
tester.assertComponent(path(panel, "deadline"), DateLabel.class);
tester.assertModelValue(path(panel, "deadline"), finalSeminarApproval.getCurrentDeadline());
}
@Test
public void shows_current_reason_if_a_decision_has_been_made() {
startPanelWithApprovedFinalSeminar();

@ -140,46 +140,5 @@
<spring.profile.active>branch</spring.profile.active>
</properties>
</profile>
<profile>
<id>docker-dependencies</id>
<!--
Some dependencies are not discovered by default when running dependency:go-offline.
They are added here manually to allow Docker build layers to be cached properly.
-->
<dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml</groupId>
<artifactId>classmate</artifactId>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<classifier>jakarta</classifier>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

@ -7,10 +7,10 @@ profile=DEV
# No secrets available for branch deployment to branch.dsv.su.se
# Will have to set up some mock API for this later
service.grading.url=
oauth.uri=
oauth.clientId=
oauth.clientSecret=
oauth.redirectUri=
oauth.uri=${OAUTH2_GS_AUTHORIZATION_URI:http://localhost:59734/authorize}
oauth.clientId=${OAUTH2_CLIENT_ID:scipro}
oauth.clientSecret=${OAUTH2_CLIENT_SECRET:s3cr3t}
oauth.redirectUri=${OAUTH2_GS_CLIENT_REDIRECT_URI}
# No secrets available for branch deployment to branch.dsv.su.se
# Will have to set up some mock API for this later