commit
bdd59b4fb8
README.md
core
daisy-integration/src/main/java/se/su/dsv/scipro/daisyExternal/impl
docker-compose.ymlpom.xmlview/src
main/java/se/su/dsv/scipro
CurrentUserFromWicketSession.java
applicationperiod
AdminEditApplicationPeriodPage.htmlAdminEditApplicationPeriodPage.javaAdminEditApplicationPeriodPage.properties
grading
loginlogout/pages
security/auth
session
test/java/se/su/dsv/scipro
war
22
README.md
22
README.md
@ -1,3 +1,12 @@
|
|||||||
|
## Working with the web GUI (Wicket)
|
||||||
|
The web GUI is protected by OAuth 2 log in. Run the Docker Compose containers with
|
||||||
|
`docker compose up` to start the authorization server to be able to log in.
|
||||||
|
|
||||||
|
If you run SciPro in development mode (DEV profile) you will be able to log in
|
||||||
|
as the "default" OAuth 2 user populated in the upper form. If you have other
|
||||||
|
data in your database you will have to use the lower form and specify a valid
|
||||||
|
username in the principal field.
|
||||||
|
|
||||||
## Working with the API
|
## Working with the API
|
||||||
The API is protected by OAuth 2 acting as a [resource server](https://www.oauth.com/oauth2-servers/the-resource-server/)
|
The API is protected by OAuth 2 acting as a [resource server](https://www.oauth.com/oauth2-servers/the-resource-server/)
|
||||||
verifying tokens using [token introspection](https://datatracker.ietf.org/doc/html/rfc7662).
|
verifying tokens using [token introspection](https://datatracker.ietf.org/doc/html/rfc7662).
|
||||||
@ -19,9 +28,14 @@ to format all Java code. To reformat the code run
|
|||||||
Yes it's a mouthful but unfortunately the [prettier-maven-plugin](https://github.com/HubSpot/prettier-maven-plugin)
|
Yes it's a mouthful but unfortunately the [prettier-maven-plugin](https://github.com/HubSpot/prettier-maven-plugin)
|
||||||
does not work due to an [outstanding issue](https://github.com/HubSpot/prettier-maven-plugin/issues/79).
|
does not work due to an [outstanding issue](https://github.com/HubSpot/prettier-maven-plugin/issues/79).
|
||||||
|
|
||||||
An easier way to reformat code is to set IntelliJ to do it on save. Go to
|
The formatting is validated by CI, but you should do it beforehand with a simple `./mvnw verify -pl .`.
|
||||||
`Settings -> Language & Frameworks -> JavaScript -> Prettier` and then check
|
|
||||||
|
### Making IntelliJ format for you
|
||||||
|
For this to work you also need to have [Node.js](https://nodejs.org)
|
||||||
|
installed and configured under `Settings -> Language & Frameworks -> Node.js`
|
||||||
|
and the file you're saving *must* be able to compile otherwise no formatting
|
||||||
|
can be performed.
|
||||||
|
|
||||||
|
Go to `Settings -> Language & Frameworks -> JavaScript -> Prettier` and then check
|
||||||
`Automatic Prettier Configuration`, set `Run for files` to `**/*.{java}`,
|
`Automatic Prettier Configuration`, set `Run for files` to `**/*.{java}`,
|
||||||
and finally check `Run on save`.
|
and finally check `Run on save`.
|
||||||
|
|
||||||
The formatting is validated by CI, but you should do it beforehand with a simple `./mvnw verify -pl .`.
|
|
||||||
|
19
core/pom.xml
19
core/pom.xml
@ -86,8 +86,23 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hsqldb</groupId>
|
<groupId>org.testcontainers</groupId>
|
||||||
<artifactId>hsqldb</artifactId>
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testcontainers</groupId>
|
||||||
|
<artifactId>mariadb</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mariadb.jdbc</groupId>
|
||||||
|
<artifactId>mariadb-java-client</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.flywaydb</groupId>
|
||||||
|
<artifactId>flyway-mysql</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ import se.su.dsv.scipro.match.TargetRepository;
|
|||||||
import se.su.dsv.scipro.match.TargetServiceImpl;
|
import se.su.dsv.scipro.match.TargetServiceImpl;
|
||||||
import se.su.dsv.scipro.milestones.MilestoneActivityTemplateRepository;
|
import se.su.dsv.scipro.milestones.MilestoneActivityTemplateRepository;
|
||||||
import se.su.dsv.scipro.milestones.service.ActivateCompletedMilestonesOnNewProjects;
|
import se.su.dsv.scipro.milestones.service.ActivateCompletedMilestonesOnNewProjects;
|
||||||
|
import se.su.dsv.scipro.milestones.service.MilestoneActivator;
|
||||||
import se.su.dsv.scipro.milestones.service.MilestoneActivityTemplateService;
|
import se.su.dsv.scipro.milestones.service.MilestoneActivityTemplateService;
|
||||||
import se.su.dsv.scipro.milestones.service.impl.MilestoneActivityTemplateServiceImpl;
|
import se.su.dsv.scipro.milestones.service.impl.MilestoneActivityTemplateServiceImpl;
|
||||||
import se.su.dsv.scipro.milestones.service.impl.MilestonePhaseTemplateServiceImpl;
|
import se.su.dsv.scipro.milestones.service.impl.MilestonePhaseTemplateServiceImpl;
|
||||||
@ -1129,4 +1130,21 @@ public class CoreConfig {
|
|||||||
public GroupFacadeImpl groupFacade() {
|
public GroupFacadeImpl groupFacade() {
|
||||||
return new GroupFacadeImpl();
|
return new GroupFacadeImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MilestoneActivator milestoneActivator(
|
||||||
|
EventBus eventBus,
|
||||||
|
MilestoneServiceImpl milestoneService,
|
||||||
|
MilestoneActivityTemplateService milestoneActivityTemplateService,
|
||||||
|
FinalSeminarService finalSeminarService,
|
||||||
|
NotificationController notificationController
|
||||||
|
) {
|
||||||
|
return new MilestoneActivator(
|
||||||
|
milestoneActivityTemplateService,
|
||||||
|
milestoneService,
|
||||||
|
eventBus,
|
||||||
|
finalSeminarService,
|
||||||
|
notificationController
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,6 +206,10 @@ public class DataInitializer implements Lifecycle {
|
|||||||
admin.addRole(Roles.SYSADMIN);
|
admin.addRole(Roles.SYSADMIN);
|
||||||
createBeta(admin);
|
createBeta(admin);
|
||||||
passwordService.updatePassword(admin, "aey7ru8aefei0jaW2wo9eX8EiShi0aan");
|
passwordService.updatePassword(admin, "aey7ru8aefei0jaW2wo9eX8EiShi0aan");
|
||||||
|
Username defaultOAuth2Principal = new Username();
|
||||||
|
defaultOAuth2Principal.setUsername("dev@localhost");
|
||||||
|
defaultOAuth2Principal.setUser(admin);
|
||||||
|
save(defaultOAuth2Principal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBeta(User user) {
|
private void createBeta(User user) {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package se.su.dsv.scipro.report;
|
package se.su.dsv.scipro.report;
|
||||||
|
|
||||||
import java.io.Serializable;
|
public interface GradeCalculator {
|
||||||
|
|
||||||
public interface GradeCalculator extends Serializable {
|
|
||||||
GradingReport.Grade getGrade(GradingReport gradingReport);
|
GradingReport.Grade getGrade(GradingReport gradingReport);
|
||||||
|
|
||||||
long getPoints(GradingReport gradingReport);
|
long getPoints(GradingReport gradingReport);
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package se.su.dsv.scipro.system;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about the current authentication context.
|
||||||
|
* <p>
|
||||||
|
* The difference between this and {@link CurrentUser} is that a user can be
|
||||||
|
* authenticated without being a user in the system. This can happen when a
|
||||||
|
* user logs in for the first time via SSO. The {@link #set(User)} method can
|
||||||
|
* be used if the user can be imported based on the {@link #getPrincipalName()}.
|
||||||
|
*/
|
||||||
|
public interface AuthenticationContext extends CurrentUser {
|
||||||
|
void set(User user);
|
||||||
|
|
||||||
|
String getPrincipalName();
|
||||||
|
}
|
@ -4,9 +4,6 @@
|
|||||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
|
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
|
||||||
version="3.0">
|
version="3.0">
|
||||||
|
|
||||||
<!-- NOTE THAT THERE ARE TWO PERSISTENCE UNITS, one default and one test
|
|
||||||
used for either running or unit-tests -->
|
|
||||||
|
|
||||||
<!-- A JPA Persistence Unit -->
|
<!-- A JPA Persistence Unit -->
|
||||||
<persistence-unit name="defaultPersistenceUnit"
|
<persistence-unit name="defaultPersistenceUnit"
|
||||||
transaction-type="RESOURCE_LOCAL">
|
transaction-type="RESOURCE_LOCAL">
|
||||||
@ -17,13 +14,4 @@
|
|||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
|
|
||||||
<!-- A JPA Persistence Unit used for tests -->
|
|
||||||
<persistence-unit name="testPersistenceUnit"
|
|
||||||
transaction-type="RESOURCE_LOCAL">
|
|
||||||
<properties>
|
|
||||||
<property name="jakarta.persistence.jdbc.driver" value="org.hsqldb.jdbc.JDBCDriver"/>
|
|
||||||
<property name="jakarta.persistence.jdbc.url" value="jdbc:hsqldb:mem:test"/>
|
|
||||||
<property name="hibernate.hbm2ddl.auto" value="create"/>
|
|
||||||
</properties>
|
|
||||||
</persistence-unit>
|
|
||||||
</persistence>
|
</persistence>
|
||||||
|
@ -197,6 +197,7 @@ public class FinalSeminarSchedulingTest extends IntegrationTest {
|
|||||||
NonWorkDayPeriod nonWorkDayPeriod = new NonWorkDayPeriod();
|
NonWorkDayPeriod nonWorkDayPeriod = new NonWorkDayPeriod();
|
||||||
nonWorkDayPeriod.setStartDate(date);
|
nonWorkDayPeriod.setStartDate(date);
|
||||||
nonWorkDayPeriod.setEndDate(date);
|
nonWorkDayPeriod.setEndDate(date);
|
||||||
|
nonWorkDayPeriod.setComment("test non work day");
|
||||||
save(nonWorkDayPeriod);
|
save(nonWorkDayPeriod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import se.su.dsv.scipro.file.FileDescription;
|
|||||||
import se.su.dsv.scipro.file.FileReference;
|
import se.su.dsv.scipro.file.FileReference;
|
||||||
import se.su.dsv.scipro.project.Project;
|
import se.su.dsv.scipro.project.Project;
|
||||||
import se.su.dsv.scipro.system.DegreeType;
|
import se.su.dsv.scipro.system.DegreeType;
|
||||||
|
import se.su.dsv.scipro.system.Language;
|
||||||
import se.su.dsv.scipro.system.ProjectType;
|
import se.su.dsv.scipro.system.ProjectType;
|
||||||
import se.su.dsv.scipro.system.User;
|
import se.su.dsv.scipro.system.User;
|
||||||
import se.su.dsv.scipro.test.Dates;
|
import se.su.dsv.scipro.test.Dates;
|
||||||
@ -66,6 +67,7 @@ public class CommentThreadServiceImplTest extends IntegrationTest {
|
|||||||
PeerRequest peerRequest = new PeerRequest();
|
PeerRequest peerRequest = new PeerRequest();
|
||||||
peerRequest.setProject(project);
|
peerRequest.setProject(project);
|
||||||
peerRequest.setRequester(createUser());
|
peerRequest.setRequester(createUser());
|
||||||
|
peerRequest.setLanguage(Language.ENGLISH);
|
||||||
final FileDescription fileDescription = save(new FileDescription());
|
final FileDescription fileDescription = save(new FileDescription());
|
||||||
final FileReference fileReference = new FileReference();
|
final FileReference fileReference = new FileReference();
|
||||||
fileReference.setFileDescription(fileDescription);
|
fileReference.setFileDescription(fileDescription);
|
||||||
|
@ -13,6 +13,7 @@ import se.su.dsv.scipro.file.FileDescription;
|
|||||||
import se.su.dsv.scipro.file.FileReference;
|
import se.su.dsv.scipro.file.FileReference;
|
||||||
import se.su.dsv.scipro.project.Project;
|
import se.su.dsv.scipro.project.Project;
|
||||||
import se.su.dsv.scipro.system.DegreeType;
|
import se.su.dsv.scipro.system.DegreeType;
|
||||||
|
import se.su.dsv.scipro.system.Language;
|
||||||
import se.su.dsv.scipro.system.PageRequest;
|
import se.su.dsv.scipro.system.PageRequest;
|
||||||
import se.su.dsv.scipro.system.ProjectType;
|
import se.su.dsv.scipro.system.ProjectType;
|
||||||
import se.su.dsv.scipro.system.User;
|
import se.su.dsv.scipro.system.User;
|
||||||
@ -158,6 +159,7 @@ public class PeerRequestServiceImplTest extends IntegrationTest {
|
|||||||
peerRequest.setProject(project);
|
peerRequest.setProject(project);
|
||||||
peerRequest.setRequester(requester);
|
peerRequest.setRequester(requester);
|
||||||
peerRequest.setStatus(status);
|
peerRequest.setStatus(status);
|
||||||
|
peerRequest.setLanguage(Language.ENGLISH);
|
||||||
final FileDescription fileDescription = save(new FileDescription());
|
final FileDescription fileDescription = save(new FileDescription());
|
||||||
final FileReference fileReference = new FileReference();
|
final FileReference fileReference = new FileReference();
|
||||||
fileReference.setFileDescription(fileDescription);
|
fileReference.setFileDescription(fileDescription);
|
||||||
|
@ -14,6 +14,7 @@ import se.su.dsv.scipro.file.FileDescription;
|
|||||||
import se.su.dsv.scipro.file.FileReference;
|
import se.su.dsv.scipro.file.FileReference;
|
||||||
import se.su.dsv.scipro.project.Project;
|
import se.su.dsv.scipro.project.Project;
|
||||||
import se.su.dsv.scipro.system.DegreeType;
|
import se.su.dsv.scipro.system.DegreeType;
|
||||||
|
import se.su.dsv.scipro.system.Language;
|
||||||
import se.su.dsv.scipro.system.PageRequest;
|
import se.su.dsv.scipro.system.PageRequest;
|
||||||
import se.su.dsv.scipro.system.ProjectType;
|
import se.su.dsv.scipro.system.ProjectType;
|
||||||
import se.su.dsv.scipro.system.User;
|
import se.su.dsv.scipro.system.User;
|
||||||
@ -102,6 +103,7 @@ public class PeerReviewServiceImplIntegrationTest extends IntegrationTest {
|
|||||||
PeerRequest peerRequest = new PeerRequest();
|
PeerRequest peerRequest = new PeerRequest();
|
||||||
peerRequest.setProject(createProject());
|
peerRequest.setProject(createProject());
|
||||||
peerRequest.setRequester(createUser());
|
peerRequest.setRequester(createUser());
|
||||||
|
peerRequest.setLanguage(Language.ENGLISH);
|
||||||
final FileDescription fileDescription = save(new FileDescription());
|
final FileDescription fileDescription = save(new FileDescription());
|
||||||
final FileReference fileReference = new FileReference();
|
final FileReference fileReference = new FileReference();
|
||||||
fileReference.setFileDescription(fileDescription);
|
fileReference.setFileDescription(fileDescription);
|
||||||
|
@ -14,6 +14,7 @@ import se.su.dsv.scipro.file.FileDescription;
|
|||||||
import se.su.dsv.scipro.file.FileReference;
|
import se.su.dsv.scipro.file.FileReference;
|
||||||
import se.su.dsv.scipro.project.Project;
|
import se.su.dsv.scipro.project.Project;
|
||||||
import se.su.dsv.scipro.system.DegreeType;
|
import se.su.dsv.scipro.system.DegreeType;
|
||||||
|
import se.su.dsv.scipro.system.Language;
|
||||||
import se.su.dsv.scipro.system.PageRequest;
|
import se.su.dsv.scipro.system.PageRequest;
|
||||||
import se.su.dsv.scipro.system.ProjectType;
|
import se.su.dsv.scipro.system.ProjectType;
|
||||||
import se.su.dsv.scipro.system.User;
|
import se.su.dsv.scipro.system.User;
|
||||||
@ -95,6 +96,7 @@ public class PeerReviewServiceImplTest extends IntegrationTest {
|
|||||||
peerRequest.setRequester(
|
peerRequest.setRequester(
|
||||||
save(User.builder().firstName("Bob").lastName("Sponge").emailAddress("bob@example.com").build())
|
save(User.builder().firstName("Bob").lastName("Sponge").emailAddress("bob@example.com").build())
|
||||||
);
|
);
|
||||||
|
peerRequest.setLanguage(Language.ENGLISH);
|
||||||
final FileDescription fileDescription = save(new FileDescription());
|
final FileDescription fileDescription = save(new FileDescription());
|
||||||
final FileReference fileReference = new FileReference();
|
final FileReference fileReference = new FileReference();
|
||||||
fileReference.setFileDescription(fileDescription);
|
fileReference.setFileDescription(fileDescription);
|
||||||
|
@ -19,6 +19,7 @@ import se.su.dsv.scipro.file.FileDescription;
|
|||||||
import se.su.dsv.scipro.file.FileReference;
|
import se.su.dsv.scipro.file.FileReference;
|
||||||
import se.su.dsv.scipro.project.Project;
|
import se.su.dsv.scipro.project.Project;
|
||||||
import se.su.dsv.scipro.project.ProjectStatus;
|
import se.su.dsv.scipro.project.ProjectStatus;
|
||||||
|
import se.su.dsv.scipro.system.Language;
|
||||||
import se.su.dsv.scipro.system.PageRequest;
|
import se.su.dsv.scipro.system.PageRequest;
|
||||||
import se.su.dsv.scipro.system.ProjectType;
|
import se.su.dsv.scipro.system.ProjectType;
|
||||||
import se.su.dsv.scipro.system.User;
|
import se.su.dsv.scipro.system.User;
|
||||||
@ -196,6 +197,7 @@ public class TestPeerReview extends IntegrationTest {
|
|||||||
request.setComment(comment);
|
request.setComment(comment);
|
||||||
request.setRequester(requester);
|
request.setRequester(requester);
|
||||||
request.setProject(project);
|
request.setProject(project);
|
||||||
|
request.setLanguage(Language.ENGLISH);
|
||||||
final FileDescription fileDescription = save(new FileDescription());
|
final FileDescription fileDescription = save(new FileDescription());
|
||||||
final FileReference fileReference = new FileReference();
|
final FileReference fileReference = new FileReference();
|
||||||
fileReference.setFileDescription(fileDescription);
|
fileReference.setFileDescription(fileDescription);
|
||||||
|
@ -13,6 +13,7 @@ import org.hamcrest.TypeSafeMatcher;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import se.su.dsv.scipro.file.FileDescription;
|
import se.su.dsv.scipro.file.FileDescription;
|
||||||
import se.su.dsv.scipro.file.FileReference;
|
import se.su.dsv.scipro.file.FileReference;
|
||||||
|
import se.su.dsv.scipro.system.User;
|
||||||
import se.su.dsv.scipro.test.SpringTest;
|
import se.su.dsv.scipro.test.SpringTest;
|
||||||
|
|
||||||
public class UrkundSubmissionRepositoryTest extends SpringTest {
|
public class UrkundSubmissionRepositoryTest extends SpringTest {
|
||||||
@ -23,11 +24,14 @@ public class UrkundSubmissionRepositoryTest extends SpringTest {
|
|||||||
@Test
|
@Test
|
||||||
public void save() {
|
public void save() {
|
||||||
final Instant submitted = Instant.now();
|
final Instant submitted = Instant.now();
|
||||||
|
User bob = User.builder().firstName("Bob").lastName("Sponge").emailAddress("bob@example.com").build();
|
||||||
|
save(bob);
|
||||||
final UrkundSubmission submission = new UrkundSubmission();
|
final UrkundSubmission submission = new UrkundSubmission();
|
||||||
submission.setState(UrkundSubmission.State.SUBMITTED);
|
submission.setState(UrkundSubmission.State.SUBMITTED);
|
||||||
submission.setMessage("Hi");
|
submission.setMessage("Hi");
|
||||||
submission.setSubmitted(submitted);
|
submission.setSubmitted(submitted);
|
||||||
submission.setNextPoll(submitted);
|
submission.setNextPoll(submitted);
|
||||||
|
submission.setReceiver(bob);
|
||||||
final FileDescription file = save(new FileDescription());
|
final FileDescription file = save(new FileDescription());
|
||||||
final FileReference fileReference = new FileReference();
|
final FileReference fileReference = new FileReference();
|
||||||
fileReference.setFileDescription(file);
|
fileReference.setFileDescription(file);
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package se.su.dsv.scipro.test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import se.su.dsv.scipro.milestones.service.MilestoneActivator;
|
||||||
|
|
||||||
|
public class BeanDefinitionsTest extends IntegrationTest {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
MilestoneActivator milestoneActivator;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void milestone_activator() {
|
||||||
|
assertNotNull(milestoneActivator);
|
||||||
|
}
|
||||||
|
}
|
@ -4,28 +4,47 @@ import jakarta.persistence.EntityManager;
|
|||||||
import jakarta.persistence.EntityManagerFactory;
|
import jakarta.persistence.EntityManagerFactory;
|
||||||
import jakarta.persistence.EntityTransaction;
|
import jakarta.persistence.EntityTransaction;
|
||||||
import jakarta.persistence.Persistence;
|
import jakarta.persistence.Persistence;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import org.flywaydb.core.Flyway;
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.mariadb.jdbc.MariaDbDataSource;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.testcontainers.containers.MariaDBContainer;
|
||||||
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
import se.su.dsv.scipro.CoreConfig;
|
import se.su.dsv.scipro.CoreConfig;
|
||||||
import se.su.dsv.scipro.RepositoryConfiguration;
|
import se.su.dsv.scipro.RepositoryConfiguration;
|
||||||
import se.su.dsv.scipro.profiles.CurrentProfile;
|
import se.su.dsv.scipro.profiles.CurrentProfile;
|
||||||
import se.su.dsv.scipro.sukat.Sukat;
|
import se.su.dsv.scipro.sukat.Sukat;
|
||||||
import se.su.dsv.scipro.system.CurrentUser;
|
import se.su.dsv.scipro.system.CurrentUser;
|
||||||
|
|
||||||
|
@Testcontainers
|
||||||
public abstract class SpringTest {
|
public abstract class SpringTest {
|
||||||
|
|
||||||
private EntityManager entityManager;
|
private EntityManager entityManager;
|
||||||
private EntityManagerFactory entityManagerFactory;
|
private EntityManagerFactory entityManagerFactory;
|
||||||
|
|
||||||
|
@Container
|
||||||
|
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11");
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public final void prepareSpring() {
|
public final void prepareSpring() throws SQLException {
|
||||||
entityManagerFactory = Persistence.createEntityManagerFactory("testPersistenceUnit");
|
MariaDbDataSource dataSource = new MariaDbDataSource(mariaDBContainer.getJdbcUrl());
|
||||||
|
dataSource.setUser(mariaDBContainer.getUsername());
|
||||||
|
dataSource.setPassword(mariaDBContainer.getPassword());
|
||||||
|
|
||||||
|
Flyway.configure().dataSource(dataSource).load().migrate();
|
||||||
|
|
||||||
|
Map<String, Object> jpaProperties = Map.of(Environment.JAKARTA_JTA_DATASOURCE, dataSource);
|
||||||
|
entityManagerFactory = Persistence.createEntityManagerFactory("defaultPersistenceUnit", jpaProperties);
|
||||||
this.entityManager = entityManagerFactory.createEntityManager();
|
this.entityManager = entityManagerFactory.createEntityManager();
|
||||||
EntityTransaction transaction = entityManager.getTransaction();
|
EntityTransaction transaction = entityManager.getTransaction();
|
||||||
transaction.begin();
|
transaction.begin();
|
||||||
|
@ -171,6 +171,7 @@ public class ImporterTransactionsImpl implements ImporterTransactions {
|
|||||||
username.setUsername(completeUsername);
|
username.setUsername(completeUsername);
|
||||||
username.setUser(local);
|
username.setUser(local);
|
||||||
userNameService.save(username);
|
userNameService.save(username);
|
||||||
|
local.getUsernames().add(username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,3 +13,14 @@ services:
|
|||||||
- CLIENT_REDIRECT_URI=http://localhost:59732/
|
- CLIENT_REDIRECT_URI=http://localhost:59732/
|
||||||
- RESOURCE_SERVER_ID=scipro-api-client
|
- RESOURCE_SERVER_ID=scipro-api-client
|
||||||
- RESOURCE_SERVER_SECRET=scipro-api-secret
|
- RESOURCE_SERVER_SECRET=scipro-api-secret
|
||||||
|
oauth2-wicket:
|
||||||
|
build:
|
||||||
|
context: https://github.com/dsv-su/toker.git
|
||||||
|
dockerfile: embedded.Dockerfile
|
||||||
|
restart: on-failure
|
||||||
|
ports:
|
||||||
|
- '59734:8080'
|
||||||
|
environment:
|
||||||
|
- CLIENT_ID=scipro
|
||||||
|
- CLIENT_SECRET=s3cr3t
|
||||||
|
- CLIENT_REDIRECT_URI=http://localhost:8080/login/oauth2/code/scipro
|
||||||
|
11
pom.xml
11
pom.xml
@ -34,7 +34,6 @@
|
|||||||
<querydsl.version>5.0.0</querydsl.version>
|
<querydsl.version>5.0.0</querydsl.version>
|
||||||
<jakarta.servlet.version>5.0.0</jakarta.servlet.version>
|
<jakarta.servlet.version>5.0.0</jakarta.servlet.version>
|
||||||
<junit.version>5.9.3</junit.version>
|
<junit.version>5.9.3</junit.version>
|
||||||
<hsqldb.version>2.7.1</hsqldb.version>
|
|
||||||
<mockito.version>5.3.1</mockito.version>
|
<mockito.version>5.3.1</mockito.version>
|
||||||
<flyway.version>9.19.1</flyway.version>
|
<flyway.version>9.19.1</flyway.version>
|
||||||
<jersey.version>3.1.6</jersey.version>
|
<jersey.version>3.1.6</jersey.version>
|
||||||
@ -101,7 +100,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-dependencies</artifactId>
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
<version>3.2.5</version>
|
<version>3.2.12</version>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
@ -133,14 +132,6 @@
|
|||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Database stuff -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hsqldb</groupId>
|
|
||||||
<artifactId>hsqldb</artifactId>
|
|
||||||
<version>${hsqldb.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mariadb.jdbc</groupId>
|
<groupId>org.mariadb.jdbc</groupId>
|
||||||
<artifactId>mariadb-java-client</artifactId>
|
<artifactId>mariadb-java-client</artifactId>
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
package se.su.dsv.scipro;
|
|
||||||
|
|
||||||
import org.apache.wicket.Session;
|
|
||||||
import se.su.dsv.scipro.session.SciProSession;
|
|
||||||
import se.su.dsv.scipro.system.CurrentUser;
|
|
||||||
import se.su.dsv.scipro.system.User;
|
|
||||||
|
|
||||||
public class CurrentUserFromWicketSession implements CurrentUser {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User get() {
|
|
||||||
return Session.exists() ? SciProSession.get().getUser() : null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,10 +16,8 @@
|
|||||||
|
|
||||||
<fieldset class="mb-3">
|
<fieldset class="mb-3">
|
||||||
<legend><wicket:message key="projectTypes"/></legend>
|
<legend><wicket:message key="projectTypes"/></legend>
|
||||||
<div class="form-check" wicket:id="projectTypes">
|
<div wicket:id="projectTypes"></div>
|
||||||
<input type="checkbox" wicket:id="checkbox" class="form-check-input"/>
|
<div wicket:id="projectTypesFeedback"></div>
|
||||||
<label class="form-check-label" wicket:for="checkbox"><span wicket:id="name"></span></label>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
|
@ -4,17 +4,14 @@ import jakarta.inject.Inject;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.wicket.extensions.model.AbstractCheckBoxModel;
|
|
||||||
import org.apache.wicket.feedback.FencedFeedbackPanel;
|
import org.apache.wicket.feedback.FencedFeedbackPanel;
|
||||||
import org.apache.wicket.markup.html.basic.Label;
|
|
||||||
import org.apache.wicket.markup.html.form.*;
|
import org.apache.wicket.markup.html.form.*;
|
||||||
import org.apache.wicket.markup.html.list.ListItem;
|
|
||||||
import org.apache.wicket.markup.html.list.ListView;
|
|
||||||
import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
|
import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
|
||||||
import org.apache.wicket.model.IModel;
|
import org.apache.wicket.model.IModel;
|
||||||
import org.apache.wicket.model.LambdaModel;
|
import org.apache.wicket.model.LambdaModel;
|
||||||
import org.apache.wicket.model.LoadableDetachableModel;
|
import org.apache.wicket.model.LoadableDetachableModel;
|
||||||
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
||||||
|
import se.su.dsv.scipro.components.BootstrapCheckBoxMultipleChoice;
|
||||||
import se.su.dsv.scipro.components.BootstrapDatePicker;
|
import se.su.dsv.scipro.components.BootstrapDatePicker;
|
||||||
import se.su.dsv.scipro.components.BootstrapTimePicker;
|
import se.su.dsv.scipro.components.BootstrapTimePicker;
|
||||||
import se.su.dsv.scipro.components.DatesValidator;
|
import se.su.dsv.scipro.components.DatesValidator;
|
||||||
@ -39,7 +36,6 @@ public class AdminEditApplicationPeriodPage
|
|||||||
public static final String TITLE = "title";
|
public static final String TITLE = "title";
|
||||||
public static final String FEEDBACK = "Feedback";
|
public static final String FEEDBACK = "Feedback";
|
||||||
public static final String TITLE_FEEDBACK = "titleFeedback";
|
public static final String TITLE_FEEDBACK = "titleFeedback";
|
||||||
public static final String CHECKBOX = "checkbox";
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProjectTypeService projectTypeService;
|
private ProjectTypeService projectTypeService;
|
||||||
@ -62,19 +58,15 @@ public class AdminEditApplicationPeriodPage
|
|||||||
);
|
);
|
||||||
add(new ComponentFeedbackPanel(TITLE_FEEDBACK, title));
|
add(new ComponentFeedbackPanel(TITLE_FEEDBACK, title));
|
||||||
add(title);
|
add(title);
|
||||||
add(
|
BootstrapCheckBoxMultipleChoice<ProjectType> projectTypeChoice = new BootstrapCheckBoxMultipleChoice<>(
|
||||||
new ListView<>(PROJECT_TYPES, availableProjectTypes()) {
|
PROJECT_TYPES,
|
||||||
@Override
|
LambdaModel.of(getModel(), ApplicationPeriod::getProjectTypes, ApplicationPeriod::setProjectTypes),
|
||||||
protected void populateItem(ListItem<ProjectType> item) {
|
availableProjectTypes(),
|
||||||
item.add(
|
new LambdaChoiceRenderer<>(ProjectType::getName, ProjectType::getId)
|
||||||
new CheckBox(CHECKBOX, new ProjectTypeSelectionModel(item.getModel())).setOutputMarkupId(
|
|
||||||
true
|
|
||||||
)
|
|
||||||
);
|
|
||||||
item.add(new Label("name", item.getModel().map(ProjectType::getName)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
projectTypeChoice.setRequired(true);
|
||||||
|
add(projectTypeChoice);
|
||||||
|
add(new FencedFeedbackPanel("projectTypesFeedback", projectTypeChoice));
|
||||||
final FormComponent<LocalDate> startDate = addDateField(
|
final FormComponent<LocalDate> startDate = addDateField(
|
||||||
START_DATE,
|
START_DATE,
|
||||||
LambdaModel.of(getModel(), ApplicationPeriod::getStartDate, ApplicationPeriod::setStartDate)
|
LambdaModel.of(getModel(), ApplicationPeriod::getStartDate, ApplicationPeriod::setStartDate)
|
||||||
@ -139,30 +131,6 @@ public class AdminEditApplicationPeriodPage
|
|||||||
getRootForm().error(getString("overlapping"));
|
getRootForm().error(getString("overlapping"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ProjectTypeSelectionModel extends AbstractCheckBoxModel {
|
|
||||||
|
|
||||||
private final IModel<ProjectType> model;
|
|
||||||
|
|
||||||
public ProjectTypeSelectionModel(IModel<ProjectType> model) {
|
|
||||||
this.model = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSelected() {
|
|
||||||
return getModelObject().getProjectTypes().contains(model.getObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void select() {
|
|
||||||
getModelObject().addProjectType(model.getObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unselect() {
|
|
||||||
getModelObject().removeProjectType(model.getObject());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoadableDetachableModel<ApplicationPeriod> getLoaded(final PageParameters pp) {
|
private LoadableDetachableModel<ApplicationPeriod> getLoaded(final PageParameters pp) {
|
||||||
|
@ -14,4 +14,5 @@ success= Application period saved.
|
|||||||
overlapping= Overlapping application period already exists.
|
overlapping= Overlapping application period already exists.
|
||||||
date.Required= You need to specify a valid date.
|
date.Required= You need to specify a valid date.
|
||||||
hours.Required= Hours field is required.
|
hours.Required= Hours field is required.
|
||||||
minutes.Required= Minutes field is required.
|
minutes.Required= Minutes field is required.
|
||||||
|
projectTypes.Required=You must select at least one project type.
|
||||||
|
@ -4,7 +4,6 @@ import org.apache.wicket.markup.html.WebMarkupContainer;
|
|||||||
import org.apache.wicket.markup.html.basic.Label;
|
import org.apache.wicket.markup.html.basic.Label;
|
||||||
import org.apache.wicket.markup.html.panel.Panel;
|
import org.apache.wicket.markup.html.panel.Panel;
|
||||||
import org.apache.wicket.model.IModel;
|
import org.apache.wicket.model.IModel;
|
||||||
import org.apache.wicket.model.LoadableDetachableModel;
|
|
||||||
import se.su.dsv.scipro.components.OppositeVisibility;
|
import se.su.dsv.scipro.components.OppositeVisibility;
|
||||||
import se.su.dsv.scipro.report.GradeCalculator;
|
import se.su.dsv.scipro.report.GradeCalculator;
|
||||||
import se.su.dsv.scipro.report.GradingReport;
|
import se.su.dsv.scipro.report.GradingReport;
|
||||||
@ -18,15 +17,13 @@ public class GradingReportPointsPanel extends Panel {
|
|||||||
public GradingReportPointsPanel(
|
public GradingReportPointsPanel(
|
||||||
String id,
|
String id,
|
||||||
final IModel<? extends GradingReport> gradingReportIModel,
|
final IModel<? extends GradingReport> gradingReportIModel,
|
||||||
final GradeCalculator gradeCalculator
|
final IModel<GradeCalculator> gradeCalculator
|
||||||
) {
|
) {
|
||||||
super(id, gradingReportIModel);
|
super(id, gradingReportIModel);
|
||||||
final IModel<GradingReport.Grade> gradeModel = new LoadableDetachableModel<>() {
|
final IModel<GradingReport.Grade> gradeModel = gradingReportIModel.combineWith(
|
||||||
@Override
|
gradeCalculator,
|
||||||
protected GradingReport.Grade load() {
|
GradingReport::getGrade
|
||||||
return gradingReportIModel.getObject().getGrade(gradeCalculator);
|
);
|
||||||
}
|
|
||||||
};
|
|
||||||
final Label grade = new Label(GRADE, gradeModel.map(GradingReport.Grade::name)) {
|
final Label grade = new Label(GRADE, gradeModel.map(GradingReport.Grade::name)) {
|
||||||
@Override
|
@Override
|
||||||
protected void onConfigure() {
|
protected void onConfigure() {
|
||||||
@ -36,12 +33,7 @@ public class GradingReportPointsPanel extends Panel {
|
|||||||
};
|
};
|
||||||
add(grade);
|
add(grade);
|
||||||
|
|
||||||
final IModel<Long> points = new LoadableDetachableModel<>() {
|
final IModel<Long> points = gradingReportIModel.combineWith(gradeCalculator, GradingReport::getPoints);
|
||||||
@Override
|
|
||||||
protected Long load() {
|
|
||||||
return gradingReportIModel.getObject().getPoints(gradeCalculator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
add(new Label(POINTS_LABEL, points));
|
add(new Label(POINTS_LABEL, points));
|
||||||
|
|
||||||
add(new WebMarkupContainer(NO_GRADE_EXPLANATION).add(new OppositeVisibility(grade)));
|
add(new WebMarkupContainer(NO_GRADE_EXPLANATION).add(new OppositeVisibility(grade)));
|
||||||
|
@ -271,8 +271,8 @@ public class IndividualAuthorAssessmentPanel extends GenericPanel<User> {
|
|||||||
new TemplatePanel("points_to_grade_conversion", gradingReport.map(SupervisorGradingReport::getProject))
|
new TemplatePanel("points_to_grade_conversion", gradingReport.map(SupervisorGradingReport::getProject))
|
||||||
);
|
);
|
||||||
|
|
||||||
GradeCalculator supervisorCalculator = gradeCalculatorService.getSupervisorCalculator(
|
IModel<GradeCalculator> supervisorCalculator = LoadableDetachableModel.of(() ->
|
||||||
gradingReport.getObject().getProject()
|
gradeCalculatorService.getSupervisorCalculator(gradingReport.getObject().getProject())
|
||||||
);
|
);
|
||||||
add(new GradingReportPointsPanel("points", gradingReport, supervisorCalculator));
|
add(new GradingReportPointsPanel("points", gradingReport, supervisorCalculator));
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package se.su.dsv.scipro.loginlogout.pages;
|
package se.su.dsv.scipro.loginlogout.pages;
|
||||||
|
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import se.su.dsv.scipro.basepages.PublicPage;
|
import se.su.dsv.scipro.basepages.PublicPage;
|
||||||
import se.su.dsv.scipro.security.auth.Authorization;
|
import se.su.dsv.scipro.security.auth.Authorization;
|
||||||
import se.su.dsv.scipro.session.SciProSession;
|
import se.su.dsv.scipro.session.SciProSession;
|
||||||
|
import se.su.dsv.scipro.system.AuthenticationContext;
|
||||||
import se.su.dsv.scipro.system.User;
|
import se.su.dsv.scipro.system.User;
|
||||||
import se.su.dsv.scipro.system.UserImportService;
|
import se.su.dsv.scipro.system.UserImportService;
|
||||||
import se.su.dsv.scipro.system.UserService;
|
import se.su.dsv.scipro.system.UserService;
|
||||||
@ -20,8 +20,11 @@ public class SSOPage extends PublicPage {
|
|||||||
@Inject
|
@Inject
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AuthenticationContext authenticationContext;
|
||||||
|
|
||||||
public SSOPage() {
|
public SSOPage() {
|
||||||
String remoteUserName = ((HttpServletRequest) getRequest().getContainerRequest()).getRemoteUser();
|
String remoteUserName = authenticationContext.getPrincipalName();
|
||||||
User user = userService.findByUsername(remoteUserName);
|
User user = userService.findByUsername(remoteUserName);
|
||||||
|
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
package se.su.dsv.scipro.security.auth;
|
|
||||||
|
|
||||||
import jakarta.servlet.*;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
|
||||||
import java.io.IOException;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throw-away implementation of a servlet filter, main task is to fake the getRemoteUser() call for the request chain.
|
|
||||||
*/
|
|
||||||
public final class MockRemoteUserFilter implements Filter {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(MockRemoteUserFilter.class);
|
|
||||||
//Default value unless supplied via init parameter
|
|
||||||
private String fakedUser = "SOME_GUY";
|
|
||||||
private FilterConfig cfg = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor.
|
|
||||||
*/
|
|
||||||
public MockRemoteUserFilter() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Filter#destroy()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
cfg = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps the passed request and alters the behavior of getRemoteUser() for later links of the chain.
|
|
||||||
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
LOGGER.debug("Faking external authentication user: " + fakedUser);
|
|
||||||
if (cfg != null) {
|
|
||||||
HttpServletRequestWrapper wrapper = new ModifiedRemoteUserRequestWrapper(
|
|
||||||
(HttpServletRequest) request,
|
|
||||||
fakedUser
|
|
||||||
);
|
|
||||||
// pass the request along the filter chain
|
|
||||||
chain.doFilter(wrapper, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Filter#init(FilterConfig)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void init(FilterConfig fConfig) {
|
|
||||||
cfg = fConfig;
|
|
||||||
if (cfg != null) {
|
|
||||||
fakedUser = cfg.getInitParameter("fakedUser");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private RequestWrapper, of no interest to anyone outside of this class.
|
|
||||||
*/
|
|
||||||
static class ModifiedRemoteUserRequestWrapper extends HttpServletRequestWrapper {
|
|
||||||
|
|
||||||
private final String fakedUser;
|
|
||||||
|
|
||||||
ModifiedRemoteUserRequestWrapper(final HttpServletRequest request, final String fakedUser) {
|
|
||||||
super(request);
|
|
||||||
this.fakedUser = fakedUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRemoteUser() {
|
|
||||||
return fakedUser;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,24 +5,21 @@ import java.util.Collections;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.apache.wicket.MetaDataKey;
|
|
||||||
import org.apache.wicket.Session;
|
import org.apache.wicket.Session;
|
||||||
import org.apache.wicket.injection.Injector;
|
import org.apache.wicket.injection.Injector;
|
||||||
import org.apache.wicket.protocol.http.WebSession;
|
import org.apache.wicket.protocol.http.WebSession;
|
||||||
import org.apache.wicket.request.Request;
|
import org.apache.wicket.request.Request;
|
||||||
import se.su.dsv.scipro.security.auth.roles.IRole;
|
import se.su.dsv.scipro.security.auth.roles.IRole;
|
||||||
import se.su.dsv.scipro.security.auth.roles.Roles;
|
import se.su.dsv.scipro.security.auth.roles.Roles;
|
||||||
|
import se.su.dsv.scipro.system.AuthenticationContext;
|
||||||
import se.su.dsv.scipro.system.ProjectModule;
|
import se.su.dsv.scipro.system.ProjectModule;
|
||||||
import se.su.dsv.scipro.system.SystemModule;
|
import se.su.dsv.scipro.system.SystemModule;
|
||||||
import se.su.dsv.scipro.system.User;
|
import se.su.dsv.scipro.system.User;
|
||||||
import se.su.dsv.scipro.system.UserService;
|
|
||||||
|
|
||||||
public class SciProSession extends WebSession {
|
public class SciProSession extends WebSession {
|
||||||
|
|
||||||
private static final MetaDataKey<Long> LOGGED_IN_USER_ID = new MetaDataKey<>() {};
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private UserService userService;
|
private AuthenticationContext authenticationContext;
|
||||||
|
|
||||||
private Set<ProjectModule> projectModules = new HashSet<>();
|
private Set<ProjectModule> projectModules = new HashSet<>();
|
||||||
private Set<SystemModule> systemModules = new HashSet<>();
|
private Set<SystemModule> systemModules = new HashSet<>();
|
||||||
@ -37,15 +34,15 @@ public class SciProSession extends WebSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setUser(User user) {
|
public synchronized void setUser(User user) {
|
||||||
setMetaData(LOGGED_IN_USER_ID, user.getId());
|
authenticationContext.set(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized User getUser() {
|
public synchronized User getUser() {
|
||||||
return isLoggedIn() ? userService.findOne(getMetaData(LOGGED_IN_USER_ID)) : null;
|
return authenticationContext.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean isLoggedIn() {
|
public synchronized boolean isLoggedIn() {
|
||||||
return getMetaData(LOGGED_IN_USER_ID) != null;
|
return authenticationContext.get() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean authorizedForRole(Roles role) {
|
public synchronized boolean authorizedForRole(Roles role) {
|
||||||
|
@ -3,7 +3,6 @@ package se.su.dsv.scipro;
|
|||||||
import static org.mockito.ArgumentMatchers.*;
|
import static org.mockito.ArgumentMatchers.*;
|
||||||
import static org.mockito.Mockito.lenient;
|
import static org.mockito.Mockito.lenient;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -119,12 +118,11 @@ import se.su.dsv.scipro.springdata.services.UnitService;
|
|||||||
import se.su.dsv.scipro.springdata.services.UserProfileService;
|
import se.su.dsv.scipro.springdata.services.UserProfileService;
|
||||||
import se.su.dsv.scipro.supervisor.pages.SupervisorStartPage;
|
import se.su.dsv.scipro.supervisor.pages.SupervisorStartPage;
|
||||||
import se.su.dsv.scipro.survey.SurveyService;
|
import se.su.dsv.scipro.survey.SurveyService;
|
||||||
import se.su.dsv.scipro.system.CurrentUser;
|
import se.su.dsv.scipro.system.AuthenticationContext;
|
||||||
import se.su.dsv.scipro.system.ExternalResourceService;
|
import se.su.dsv.scipro.system.ExternalResourceService;
|
||||||
import se.su.dsv.scipro.system.FooterAddressRepo;
|
import se.su.dsv.scipro.system.FooterAddressRepo;
|
||||||
import se.su.dsv.scipro.system.FooterLinkService;
|
import se.su.dsv.scipro.system.FooterLinkService;
|
||||||
import se.su.dsv.scipro.system.GenericService;
|
import se.su.dsv.scipro.system.GenericService;
|
||||||
import se.su.dsv.scipro.system.Lifecycle;
|
|
||||||
import se.su.dsv.scipro.system.PasswordRepo;
|
import se.su.dsv.scipro.system.PasswordRepo;
|
||||||
import se.su.dsv.scipro.system.PasswordService;
|
import se.su.dsv.scipro.system.PasswordService;
|
||||||
import se.su.dsv.scipro.system.ProjectModule;
|
import se.su.dsv.scipro.system.ProjectModule;
|
||||||
@ -369,7 +367,7 @@ public abstract class SciProTest {
|
|||||||
protected ChecklistAnswerService checklistAnswerService;
|
protected ChecklistAnswerService checklistAnswerService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
protected CurrentUser currentUser;
|
protected AuthenticationContext authenticationContext;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private Scheduler scheduler;
|
private Scheduler scheduler;
|
||||||
|
@ -7,8 +7,10 @@ import java.io.Serializable;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.apache.wicket.Component;
|
||||||
import org.apache.wicket.Page;
|
import org.apache.wicket.Page;
|
||||||
import org.apache.wicket.feedback.FeedbackMessage;
|
import org.apache.wicket.feedback.FeedbackMessage;
|
||||||
|
import org.apache.wicket.markup.html.form.CheckBoxMultipleChoice;
|
||||||
import org.apache.wicket.markup.html.form.RequiredTextField;
|
import org.apache.wicket.markup.html.form.RequiredTextField;
|
||||||
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
||||||
import org.apache.wicket.util.tester.FormTester;
|
import org.apache.wicket.util.tester.FormTester;
|
||||||
@ -36,6 +38,7 @@ public class AdminEditApplicationPeriodPageTest extends SciProTest {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
bachelor = new ProjectType(DegreeType.BACHELOR, "Bachelor", "Bachelor");
|
bachelor = new ProjectType(DegreeType.BACHELOR, "Bachelor", "Bachelor");
|
||||||
|
bachelor.setId(8L);
|
||||||
bachelor.addModule(ProjectModule.MATCH);
|
bachelor.addModule(ProjectModule.MATCH);
|
||||||
when(projectTypeService.findWithModule(ProjectModule.MATCH)).thenReturn(Collections.singletonList(bachelor));
|
when(projectTypeService.findWithModule(ProjectModule.MATCH)).thenReturn(Collections.singletonList(bachelor));
|
||||||
startPage();
|
startPage();
|
||||||
@ -47,8 +50,12 @@ public class AdminEditApplicationPeriodPageTest extends SciProTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void contains_project_type_selection() {
|
public void contains_project_type_selection() {
|
||||||
tester.assertModelValue(path(FORM, PROJECT_TYPES), projectTypeService.findWithModule(ProjectModule.MATCH));
|
tester.assertComponent(path(FORM, PROJECT_TYPES), CheckBoxMultipleChoice.class);
|
||||||
|
Component component = tester.getComponentFromLastRenderedPage(path(FORM, PROJECT_TYPES));
|
||||||
|
CheckBoxMultipleChoice<ProjectType> choice = (CheckBoxMultipleChoice<ProjectType>) component;
|
||||||
|
Assertions.assertEquals(projectTypeService.findWithModule(ProjectModule.MATCH), choice.getChoices());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -105,7 +112,7 @@ public class AdminEditApplicationPeriodPageTest extends SciProTest {
|
|||||||
);
|
);
|
||||||
FormTester formTester = tester.newFormTester(FORM);
|
FormTester formTester = tester.newFormTester(FORM);
|
||||||
fillInForm("Title", 0, 1, 2, formTester);
|
fillInForm("Title", 0, 1, 2, formTester);
|
||||||
formTester.setValue(path(PROJECT_TYPES, 0, CHECKBOX), true);
|
formTester.setValue(path(PROJECT_TYPES), String.valueOf(bachelor.getId()));
|
||||||
formTester.submit();
|
formTester.submit();
|
||||||
|
|
||||||
ArgumentCaptor<ApplicationPeriod> captor = ArgumentCaptor.forClass(ApplicationPeriod.class);
|
ArgumentCaptor<ApplicationPeriod> captor = ArgumentCaptor.forClass(ApplicationPeriod.class);
|
||||||
@ -113,12 +120,25 @@ public class AdminEditApplicationPeriodPageTest extends SciProTest {
|
|||||||
MatcherAssert.assertThat(captor.getValue().getProjectTypes(), Matchers.hasItem(bachelor));
|
MatcherAssert.assertThat(captor.getValue().getProjectTypes(), Matchers.hasItem(bachelor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requires_at_least_one_project_type_to_be_selected() {
|
||||||
|
FormTester formTester = tester.newFormTester(FORM);
|
||||||
|
fillInFormWithValidValues(formTester);
|
||||||
|
formTester.setValue(path(PROJECT_TYPES), "");
|
||||||
|
formTester.submit();
|
||||||
|
tester.assertErrorMessages(tester.getLastRenderedPage().getString("projectTypes.Required"));
|
||||||
|
}
|
||||||
|
|
||||||
private void submitForm(String title, int startDate, int endDate, int courseStartDate) {
|
private void submitForm(String title, int startDate, int endDate, int courseStartDate) {
|
||||||
FormTester formTester = tester.newFormTester(FORM);
|
FormTester formTester = tester.newFormTester(FORM);
|
||||||
fillInForm(title, startDate, endDate, courseStartDate, formTester);
|
fillInForm(title, startDate, endDate, courseStartDate, formTester);
|
||||||
formTester.submit();
|
formTester.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fillInFormWithValidValues(FormTester formTester) {
|
||||||
|
fillInForm("Title", 0, 1, 2, formTester);
|
||||||
|
}
|
||||||
|
|
||||||
private void fillInForm(String title, int startDate, int endDate, int courseStartDate, FormTester formTester) {
|
private void fillInForm(String title, int startDate, int endDate, int courseStartDate, FormTester formTester) {
|
||||||
formTester.setValue(TITLE, title);
|
formTester.setValue(TITLE, title);
|
||||||
final LocalDate now = LocalDate.now();
|
final LocalDate now = LocalDate.now();
|
||||||
@ -126,6 +146,7 @@ public class AdminEditApplicationPeriodPageTest extends SciProTest {
|
|||||||
formTester.setValue(END_DATE, now.plusDays(endDate).toString());
|
formTester.setValue(END_DATE, now.plusDays(endDate).toString());
|
||||||
formTester.setValue(COURSE_START_DATE, now.plusDays(courseStartDate).toString());
|
formTester.setValue(COURSE_START_DATE, now.plusDays(courseStartDate).toString());
|
||||||
formTester.setValue("courseStartTime", "08:00");
|
formTester.setValue("courseStartTime", "08:00");
|
||||||
|
formTester.setValue(PROJECT_TYPES, String.valueOf(bachelor.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startPage() {
|
private void startPage() {
|
||||||
|
@ -62,7 +62,7 @@ public class GradingReportPointsPanelTest extends SciProTest {
|
|||||||
|
|
||||||
private void startPanel() {
|
private void startPanel() {
|
||||||
panel = tester.startComponentInPage(
|
panel = tester.startComponentInPage(
|
||||||
new GradingReportPointsPanel("id", Model.of(gradingReport), gradeCalculator)
|
new GradingReportPointsPanel("id", Model.of(gradingReport), () -> gradeCalculator)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,10 @@
|
|||||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-oauth2-client</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-orm</artifactId>
|
<artifactId>spring-orm</artifactId>
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
package se.su.dsv.scipro.war;
|
||||||
|
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.inject.Provider;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.Collections;
|
||||||
|
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.core.context.SecurityContextHolderStrategy;
|
||||||
|
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||||
|
import org.springframework.security.web.context.SecurityContextRepository;
|
||||||
|
import se.su.dsv.scipro.system.AuthenticationContext;
|
||||||
|
import se.su.dsv.scipro.system.User;
|
||||||
|
import se.su.dsv.scipro.system.UserService;
|
||||||
|
import se.su.dsv.scipro.system.Username;
|
||||||
|
|
||||||
|
public class CurrentUserFromSpringSecurity implements AuthenticationContext {
|
||||||
|
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
|
// injecting providers since this is a singleton and the request and response are not
|
||||||
|
private final Provider<HttpServletRequest> currentRequest;
|
||||||
|
private final Provider<HttpServletResponse> currentResponse;
|
||||||
|
|
||||||
|
// hardcoded since that is what Spring Security does (see SwitchUserFilter)
|
||||||
|
private final SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CurrentUserFromSpringSecurity(
|
||||||
|
UserService userService,
|
||||||
|
Provider<HttpServletRequest> currentRequest,
|
||||||
|
Provider<HttpServletResponse> currentResponse
|
||||||
|
) {
|
||||||
|
this.userService = userService;
|
||||||
|
this.currentRequest = currentRequest;
|
||||||
|
this.currentResponse = currentResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User get() {
|
||||||
|
SecurityContext context = SecurityContextHolder.getContext();
|
||||||
|
Authentication authentication = context.getAuthentication();
|
||||||
|
if (authentication == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String username = authentication.getName();
|
||||||
|
return userService.findByUsername(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementing switch user manually rather than using the built-in Spring Security switch user feature
|
||||||
|
// due to compatibility with Wicket.
|
||||||
|
// Wicket does not supply a form with a username field since it has some JavaScript based auto-complete
|
||||||
|
// person finder.
|
||||||
|
// See Spring's SwitchUserFilter for the built-in switch user feature from where most of the code is copied.
|
||||||
|
@Override
|
||||||
|
public void set(User user) {
|
||||||
|
SecurityContextHolderStrategy strategy = SecurityContextHolder.getContextHolderStrategy();
|
||||||
|
SecurityContext context = strategy.createEmptyContext();
|
||||||
|
WicketControlledPrincipal principal = new WicketControlledPrincipal(user);
|
||||||
|
UsernamePasswordAuthenticationToken targetUser = UsernamePasswordAuthenticationToken.authenticated(
|
||||||
|
principal,
|
||||||
|
null,
|
||||||
|
Collections.emptyList()
|
||||||
|
);
|
||||||
|
context.setAuthentication(targetUser);
|
||||||
|
strategy.setContext(context);
|
||||||
|
this.securityContextRepository.saveContext(context, currentRequest.get(), currentResponse.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrincipalName() {
|
||||||
|
SecurityContext context = SecurityContextHolder.getContext();
|
||||||
|
Authentication authentication = context.getAuthentication();
|
||||||
|
if (authentication == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return authentication.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class WicketControlledPrincipal implements Principal {
|
||||||
|
|
||||||
|
private final String username;
|
||||||
|
|
||||||
|
public WicketControlledPrincipal(User user) {
|
||||||
|
// extract any username so that we can look it up later
|
||||||
|
this.username = user.getUsernames().stream().findAny().map(Username::getUsername).orElse("<unknown>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,6 @@ import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
|||||||
import org.springframework.orm.jpa.SharedEntityManagerCreator;
|
import org.springframework.orm.jpa.SharedEntityManagerCreator;
|
||||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
|
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
|
||||||
import se.su.dsv.scipro.CoreConfig;
|
import se.su.dsv.scipro.CoreConfig;
|
||||||
import se.su.dsv.scipro.CurrentUserFromWicketSession;
|
|
||||||
import se.su.dsv.scipro.FileSystemStore;
|
import se.su.dsv.scipro.FileSystemStore;
|
||||||
import se.su.dsv.scipro.RepositoryConfiguration;
|
import se.su.dsv.scipro.RepositoryConfiguration;
|
||||||
import se.su.dsv.scipro.file.FileStore;
|
import se.su.dsv.scipro.file.FileStore;
|
||||||
@ -85,11 +84,6 @@ public class Main extends SpringBootServletInitializer implements ServletContain
|
|||||||
return currentProfile;
|
return currentProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public CurrentUserFromWicketSession currentUserFromWicketSession() {
|
|
||||||
return new CurrentUserFromWicketSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public FileStore fileStore() {
|
public FileStore fileStore() {
|
||||||
return new FileSystemStore();
|
return new FileSystemStore();
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package se.su.dsv.scipro.war;
|
package se.su.dsv.scipro.war;
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
import jakarta.inject.Provider;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.wicket.protocol.http.WebApplication;
|
import org.apache.wicket.protocol.http.WebApplication;
|
||||||
import org.apache.wicket.protocol.http.WicketFilter;
|
import org.apache.wicket.protocol.http.WicketFilter;
|
||||||
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
|
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
|
||||||
@ -8,6 +11,10 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import se.su.dsv.scipro.SciProApplication;
|
import se.su.dsv.scipro.SciProApplication;
|
||||||
import se.su.dsv.scipro.crosscutting.ForwardPhase2Feedback;
|
import se.su.dsv.scipro.crosscutting.ForwardPhase2Feedback;
|
||||||
import se.su.dsv.scipro.crosscutting.NotifyFailedReflection;
|
import se.su.dsv.scipro.crosscutting.NotifyFailedReflection;
|
||||||
@ -21,6 +28,7 @@ import se.su.dsv.scipro.notifications.NotificationController;
|
|||||||
import se.su.dsv.scipro.profiles.CurrentProfile;
|
import se.su.dsv.scipro.profiles.CurrentProfile;
|
||||||
import se.su.dsv.scipro.reviewing.FinalSeminarApprovalService;
|
import se.su.dsv.scipro.reviewing.FinalSeminarApprovalService;
|
||||||
import se.su.dsv.scipro.reviewing.RoughDraftApprovalService;
|
import se.su.dsv.scipro.reviewing.RoughDraftApprovalService;
|
||||||
|
import se.su.dsv.scipro.system.UserService;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class WicketConfiguration {
|
public class WicketConfiguration {
|
||||||
@ -49,6 +57,25 @@ public class WicketConfiguration {
|
|||||||
return new SciProApplication(currentProfile);
|
return new SciProApplication(currentProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(3) // make sure it's after the API security filters
|
||||||
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
http.authorizeHttpRequests(requests -> requests.anyRequest().authenticated());
|
||||||
|
http.oauth2Login(Customizer.withDefaults());
|
||||||
|
http.csrf(csrf -> csrf.disable()); // Wicket has its own CSRF protection
|
||||||
|
http.logout(logout -> logout.logoutUrl("/logout").logoutSuccessUrl("/"));
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CurrentUserFromSpringSecurity currentUserFromSpringSecurity(
|
||||||
|
UserService userService,
|
||||||
|
Provider<HttpServletRequest> httpServletRequestProvider,
|
||||||
|
Provider<HttpServletResponse> httpServletResponseProvider
|
||||||
|
) {
|
||||||
|
return new CurrentUserFromSpringSecurity(userService, httpServletRequestProvider, httpServletResponseProvider);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ReviewingNotifications reviewingNotifications(
|
public ReviewingNotifications reviewingNotifications(
|
||||||
EventBus eventBus,
|
EventBus eventBus,
|
||||||
|
@ -19,3 +19,14 @@ springdoc.swagger-ui.persist-authorization=true
|
|||||||
spring.security.oauth2.resourceserver.opaquetoken.client-id=scipro-api-client
|
spring.security.oauth2.resourceserver.opaquetoken.client-id=scipro-api-client
|
||||||
spring.security.oauth2.resourceserver.opaquetoken.client-secret=scipro-api-secret
|
spring.security.oauth2.resourceserver.opaquetoken.client-secret=scipro-api-secret
|
||||||
spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=http://localhost:59733/introspect
|
spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=http://localhost:59733/introspect
|
||||||
|
|
||||||
|
# Log in via local OAuth 2 authorization server
|
||||||
|
spring.security.oauth2.client.provider.docker.user-info-uri=http://localhost:59734/verify
|
||||||
|
spring.security.oauth2.client.provider.docker.user-name-attribute=sub
|
||||||
|
spring.security.oauth2.client.provider.docker.token-uri=http://localhost:59734/exchange
|
||||||
|
spring.security.oauth2.client.provider.docker.authorization-uri=http://localhost:59734/authorize
|
||||||
|
spring.security.oauth2.client.registration.scipro.redirect-uri={baseUrl}/login/oauth2/code/{registrationId}
|
||||||
|
spring.security.oauth2.client.registration.scipro.provider=docker
|
||||||
|
spring.security.oauth2.client.registration.scipro.client-id=scipro
|
||||||
|
spring.security.oauth2.client.registration.scipro.client-secret=s3cr3t
|
||||||
|
spring.security.oauth2.client.registration.scipro.authorization-grant-type=authorization_code
|
||||||
|
Loading…
x
Reference in New Issue
Block a user