Skip to content

Commit 690fce5

Browse files
committed
Fix session management, added swagger
1 parent fe5b6f3 commit 690fce5

File tree

6 files changed

+35
-24
lines changed

6 files changed

+35
-24
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ dependencies {
3131
implementation 'org.springframework.boot:spring-boot-starter-web'
3232
implementation 'org.flywaydb:flyway-core:11.13.0'
3333
implementation 'org.flywaydb:flyway-database-postgresql:11.13.0'
34+
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.13'
3435

3536
runtimeOnly 'org.postgresql:postgresql'
3637

src/main/java/net/hackyourfuture/coursehub/SecurityConfig.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
2929
config.setAllowCredentials(true);
3030
return config;
3131
}))
32-
.authorizeHttpRequests(auth -> auth.requestMatchers(HttpMethod.POST, "/login", "/register")
32+
.authorizeHttpRequests(auth -> auth
33+
// allow CORS pre-flight requests to any endpoint
34+
.requestMatchers(HttpMethod.OPTIONS, "/**")
3335
.permitAll()
34-
.requestMatchers(HttpMethod.OPTIONS, "/login", "/register")
36+
// this is an internal mapping to display errors
37+
// allowing it without authentication so that errors are displayed correctly
38+
.requestMatchers("/error")
3539
.permitAll()
36-
.requestMatchers(HttpMethod.GET, "/courses")
40+
.requestMatchers(HttpMethod.POST, "/login", "/register")
3741
.permitAll()
38-
.requestMatchers(HttpMethod.OPTIONS, "/courses")
42+
.requestMatchers(HttpMethod.GET, "/courses", "/swagger/**")
3943
.permitAll()
4044
.requestMatchers("/students/**")
4145
.hasRole("student")

src/main/java/net/hackyourfuture/coursehub/web/StudentController.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@
22

33
import jakarta.validation.constraints.Positive;
44
import net.hackyourfuture.coursehub.service.CourseService;
5-
import net.hackyourfuture.coursehub.web.model.CourseDto;
5+
import net.hackyourfuture.coursehub.web.model.CourseListResponse;
66
import org.springframework.web.bind.annotation.GetMapping;
77
import org.springframework.web.bind.annotation.PathVariable;
88
import org.springframework.web.bind.annotation.RequestMapping;
99
import org.springframework.web.bind.annotation.RestController;
1010

11-
import java.util.List;
12-
1311
@RestController
14-
@RequestMapping("students")
12+
@RequestMapping("/students")
1513
public class StudentController {
1614

1715
private final CourseService courseService;
@@ -21,7 +19,8 @@ public StudentController(CourseService courseService) {
2119
}
2220

2321
@GetMapping("/{studentId}/courses")
24-
public List<CourseDto> getCoursesForStudent(@PathVariable(value = "studentId") @Positive Integer studentId) {
25-
return courseService.getCoursesForStudent(studentId);
22+
public CourseListResponse getCoursesForStudent(@PathVariable @Positive Integer studentId) {
23+
var courses = courseService.getCoursesForStudent(studentId);
24+
return new CourseListResponse(courses);
2625
}
2726
}

src/main/java/net/hackyourfuture/coursehub/web/UserAuthenticationController.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package net.hackyourfuture.coursehub.web;
22

33
import jakarta.servlet.http.HttpServletRequest;
4-
import net.hackyourfuture.coursehub.repository.StudentRepository;
4+
import jakarta.servlet.http.HttpServletResponse;
55
import net.hackyourfuture.coursehub.service.UserAuthenticationService;
66
import net.hackyourfuture.coursehub.web.model.HttpErrorResponse;
77
import net.hackyourfuture.coursehub.web.model.LoginRequest;
@@ -16,6 +16,8 @@
1616
import org.springframework.security.core.Authentication;
1717
import org.springframework.security.core.AuthenticationException;
1818
import org.springframework.security.core.context.SecurityContextHolder;
19+
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
20+
import org.springframework.security.web.context.SecurityContextRepository;
1921
import org.springframework.validation.annotation.Validated;
2022
import org.springframework.web.bind.annotation.PostMapping;
2123
import org.springframework.web.bind.annotation.RequestBody;
@@ -26,21 +28,19 @@
2628
public class UserAuthenticationController {
2729
private final AuthenticationManager authenticationManager;
2830
private final UserAuthenticationService userAuthenticationService;
29-
private final StudentRepository studentRepository;
31+
private final SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();
3032

3133
public UserAuthenticationController(
3234
AuthenticationManager authenticationManager,
33-
UserAuthenticationService userAuthenticationService,
34-
StudentRepository studentRepository) {
35+
UserAuthenticationService userAuthenticationService) {
3536
this.authenticationManager = authenticationManager;
3637
this.userAuthenticationService = userAuthenticationService;
37-
this.studentRepository = studentRepository;
3838
}
3939

4040
@PostMapping("/login")
41-
public ResponseEntity<Object> login(@RequestBody LoginRequest request, HttpServletRequest httpRequest) {
41+
public ResponseEntity<Object> login(@RequestBody LoginRequest request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
4242
try {
43-
var response = authenticate(httpRequest, request.emailAddress(), request.password());
43+
var response = authenticate(httpRequest, httpResponse, request.emailAddress(), request.password());
4444
return ResponseEntity.ok(response);
4545
} catch (AuthenticationException e) {
4646
if (e instanceof BadCredentialsException) {
@@ -64,25 +64,29 @@ public ResponseEntity<?> logout(HttpServletRequest httpRequest) {
6464
}
6565

6666
@PostMapping("/register")
67-
public LoginSuccessResponse register(@RequestBody RegisterRequest request, HttpServletRequest httpRequest) {
67+
public LoginSuccessResponse register(@RequestBody RegisterRequest request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
6868
userAuthenticationService.register(
6969
request.firstName(),
7070
request.lastName(),
7171
request.emailAddress(),
7272
request.password()
7373
);
7474

75-
return authenticate(httpRequest, request.emailAddress(), request.password());
75+
return authenticate(httpRequest, httpResponse, request.emailAddress(), request.password());
7676
}
7777

78-
private LoginSuccessResponse authenticate(HttpServletRequest httpRequest, String email, String password) {
78+
private LoginSuccessResponse authenticate(HttpServletRequest request, HttpServletResponse response, String email, String password) {
7979
// Authenticate the user with the provided credentials (email and password)
8080
Authentication authentication = authenticationManager.authenticate(
8181
new UsernamePasswordAuthenticationToken(email, password));
82+
83+
SecurityContextHolder.clearContext();
84+
var context = SecurityContextHolder.createEmptyContext();
85+
context.setAuthentication(authentication);
86+
SecurityContextHolder.setContext(context);
87+
8288
// Save the authenticated user in the Spring security context
83-
SecurityContextHolder.getContext().setAuthentication(authentication);
84-
// Ensure a session is created for the authenticated user
85-
httpRequest.getSession(true);
89+
securityContextRepository.saveContext(context, request, response);
8690

8791
// Retrieve the corresponding user data to return in a login response
8892
var authenticatedUser = userAuthenticationService.currentAuthenticatedUser();

src/main/resources/application.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ spring.datasource.password=course_user_password
88

99
# Server configuration
1010
server.port=8080
11+
12+
springdoc.swagger-ui.path=/swagger/swagger-ui.html
13+
springdoc.api-docs.path=/swagger/v3/api-docs

ui/src/pages/MyCourses.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function MyCourses({user}: { user: User | null }) {
1313
const {backendUrl} = useConfig();
1414

1515
useEffect(() => {
16-
fetch(`${backendUrl}/student/${user.userId}/courses`, {
16+
fetch(`${backendUrl}/students/${user.userId}/courses`, {
1717
credentials: "include",
1818
}).then(res => res.json())
1919
.then(data => setCourses(data.courses))

0 commit comments

Comments
 (0)