Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,19 @@
<version>4.9.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.github.iskrendev.insuranceprogram.controllers;

import com.github.iskrendev.insuranceprogram.models.AppUser;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/auth")
public class AuthenticationController {

@GetMapping("/me")
public AppUser getMe() {
var principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof DefaultOAuth2User defaultOAuth2User) {
return AppUser.builder()
.id(Integer.parseInt(defaultOAuth2User.getAttributes().get("id").toString()))
.login(defaultOAuth2User.getAttributes().get("login").toString())
.build();
}
throw new IllegalArgumentException("No user logged in");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.github.iskrendev.insuranceprogram.models;

import lombok.Builder;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Builder
@Document(collection = "users")
public record AppUser(
@Id
int id,
String login
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.github.iskrendev.insuranceprogram.security;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Value("local")
private String environment;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(a -> a
.requestMatchers("/api/**").authenticated()
.anyRequest().permitAll()
)
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.ALWAYS))
.exceptionHandling(exceptionHandlingConfigurer ->
exceptionHandlingConfigurer.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)))
.logout(l -> {
if (environment.equals("prod")) {
l.logoutSuccessUrl("/").permitAll();
} else {
l.logoutSuccessUrl("http://localhost:5173").permitAll();
}
})
.oauth2Login(o -> {
try {
o.init(http);
if (environment.equals("prod")) {
o.defaultSuccessUrl("/home", true);
} else {
o.defaultSuccessUrl("http://localhost:5173/home", true);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
});
return http.build();
}
}
6 changes: 5 additions & 1 deletion backend/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
spring.data.mongodb.uri=${MONGODB_URI}
spring.mvc.hiddenmethod.filter.enabled= true
spring.mvc.hiddenmethod.filter.enabled= true
spring.security.oauth2.client.registration.github.client-id=${GITHUB_ID}
spring.security.oauth2.client.registration.github.client-secret=${GITHUB_SECRET}
spring.security.oauth2.client.registration.github.scope=none
myapp.environment=local
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.web.servlet.MockMvc;

Expand Down Expand Up @@ -44,6 +45,7 @@ class AllInsurancesControllerTest {

@Test
@DirtiesContext
@WithMockUser
void getAllInsurances_whenNoInsurancesAreInLists_thenReturnEmptyLists() throws Exception {
mockMvc.perform(get(BASE_URI))
.andExpect(jsonPath("$.lifeInsurances", hasSize(0)))
Expand All @@ -53,6 +55,7 @@ void getAllInsurances_whenNoInsurancesAreInLists_thenReturnEmptyLists() throws E

@Test
@DirtiesContext
@WithMockUser
void getAllInsurances_whenOneInsuranceIsInEachList_thenReturnLists() throws Exception {
LifeInsurance lifeInsurance = LifeInsurance.builder()
.id("1")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.github.iskrendev.insuranceprogram.controllers;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.iskrendev.insuranceprogram.models.AppUser;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oidcLogin;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class AuthenticationControllerTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private ObjectMapper objectMapper;

@Test
@DirtiesContext
void getMe_whenLoggedIn_expectStatus200() throws Exception {
AppUser expectedAppUser = new AppUser(1, "test");
String expectedJson = objectMapper.writeValueAsString(expectedAppUser);
mockMvc.perform(get("/api/auth/me")
.with(oidcLogin().userInfoToken(token -> {
token.claims(claim -> {
claim.put("id", "1");
claim.put("login", "test");
});
}))
)
.andExpect(status().isOk())
.andExpect(content().json(expectedJson));
}

@Test
@DirtiesContext
void getMe_whenNotLoggedIn_expectStatus401() throws Exception {
mockMvc.perform(get("/api/auth/me"))
.andExpect(status().isUnauthorized());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.web.servlet.MockMvc;

Expand All @@ -34,6 +35,7 @@ class LifeInsuranceControllerTest {

@Test
@DirtiesContext
@WithMockUser
void getAllLifeInsurances_whenNoLifeInsuranceIsInList_thenReturnEmptyList() throws Exception {
mockMvc.perform(get(BASE_URI))
.andExpect(status().isOk())
Expand All @@ -42,6 +44,7 @@ void getAllLifeInsurances_whenNoLifeInsuranceIsInList_thenReturnEmptyList() thro

@Test
@DirtiesContext
@WithMockUser
void getAllLifeInsurances_whenOneLifeInsuranceIsInList_thenReturnList() throws Exception {
LifeInsurance lifeInsurance = LifeInsurance.builder()
.id("1")
Expand Down Expand Up @@ -72,6 +75,7 @@ void getAllLifeInsurances_whenOneLifeInsuranceIsInList_thenReturnList() throws E

@Test
@DirtiesContext
@WithMockUser
void getLifeInsuranceById_whenIdIsValid_thenReturnInsurance() throws Exception {
LifeInsurance lifeInsurance = LifeInsurance.builder()
.id("1")
Expand Down Expand Up @@ -100,6 +104,7 @@ void getLifeInsuranceById_whenIdIsValid_thenReturnInsurance() throws Exception {

@Test
@DirtiesContext
@WithMockUser
void getLifeInsuranceById_whenIdIsNotValid_thenThrowException() throws Exception {
mockMvc.perform(get(BASE_URI + "/invalidId"))
.andExpect(status().isNotFound())
Expand All @@ -108,6 +113,7 @@ void getLifeInsuranceById_whenIdIsNotValid_thenThrowException() throws Exception

@Test
@DirtiesContext
@WithMockUser
void addLifeInsurance_whenDataIsComplete_thenReturnCompleteInsurance() throws Exception {
LifeInsuranceDTO newLifeInsurance = LifeInsuranceDTO.builder()
.firstName("TestFirstName")
Expand Down Expand Up @@ -136,6 +142,7 @@ void addLifeInsurance_whenDataIsComplete_thenReturnCompleteInsurance() throws Ex

@Test
@DirtiesContext
@WithMockUser
void addLifeInsurance_whenJustOneFieldIsFilledOut_thenReturnNullForEmptyFields() throws Exception {
LifeInsuranceDTO newLifeInsurance = LifeInsuranceDTO.builder()
.firstName("TestFirstName")
Expand Down Expand Up @@ -163,6 +170,7 @@ void addLifeInsurance_whenJustOneFieldIsFilledOut_thenReturnNullForEmptyFields()

@Test
@DirtiesContext
@WithMockUser
void updateLifeInsurance_whenInsuranceIdExistsInDb_thenReturnUpdatedInsurance() throws Exception {
LifeInsurance lifeInsuranceBefore = LifeInsurance.builder()
.id("1")
Expand Down Expand Up @@ -233,6 +241,7 @@ void updateLifeInsurance_whenInsuranceIdExistsInDb_thenReturnUpdatedInsurance()

@Test
@DirtiesContext
@WithMockUser
void updateLifeInsurance_whenInsuranceIdDoesNotExistsInDb_thenThrowException() throws Exception {
LifeInsuranceUpdateDTO lifeInsuranceUpdateDTO = LifeInsuranceUpdateDTO.builder()
.firstName("TestFirstName")
Expand Down Expand Up @@ -260,6 +269,7 @@ void updateLifeInsurance_whenInsuranceIdDoesNotExistsInDb_thenThrowException() t

@Test
@DirtiesContext
@WithMockUser
void deleteLifeInsurance() throws Exception {
LifeInsurance lifeInsurance = LifeInsurance.builder()
.id("1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.web.servlet.MockMvc;

Expand All @@ -32,6 +33,7 @@ class PropertyInsuranceControllerTest {

@Test
@DirtiesContext
@WithMockUser
void getAllPropertyInsurances_whenNoPropertyInsuranceIsInList_thenReturnEmptyList() throws Exception {
mockMvc.perform(get(BASE_URI))
.andExpect(status().isOk())
Expand All @@ -40,6 +42,7 @@ void getAllPropertyInsurances_whenNoPropertyInsuranceIsInList_thenReturnEmptyLis

@Test
@DirtiesContext
@WithMockUser
void getAllPropertyInsurances_whenOnePropertyInsuranceIsInList_thenReturnList() throws Exception {
PropertyInsurance propertyInsurance = PropertyInsurance.builder()
.id("1")
Expand Down Expand Up @@ -71,6 +74,7 @@ void getAllPropertyInsurances_whenOnePropertyInsuranceIsInList_thenReturnList()

@Test
@DirtiesContext
@WithMockUser
void getPropertyInsuranceById_whenIdIsValid_thenReturnInsurance() throws Exception {
PropertyInsurance propertyInsurance = PropertyInsurance.builder()
.id("1")
Expand Down Expand Up @@ -100,6 +104,7 @@ void getPropertyInsuranceById_whenIdIsValid_thenReturnInsurance() throws Excepti

@Test
@DirtiesContext
@WithMockUser
void getPropertyInsuranceById_whenIdIsNotValid_thenThrowException() throws Exception {
mockMvc.perform(get(BASE_URI + "/invalidId"))
.andExpect(status().isNotFound())
Expand All @@ -108,6 +113,7 @@ void getPropertyInsuranceById_whenIdIsNotValid_thenThrowException() throws Excep

@Test
@DirtiesContext
@WithMockUser
void addPropertyInsurance_whenDataIsComplete_thenReturnCompleteInsurance() throws Exception {
PropertyInsuranceDTO newPropertyInsurance = PropertyInsuranceDTO.builder()
.firstName("TestFirstName")
Expand Down Expand Up @@ -137,6 +143,7 @@ void addPropertyInsurance_whenDataIsComplete_thenReturnCompleteInsurance() throw

@Test
@DirtiesContext
@WithMockUser
void addPropertyInsurance_whenJustOneFieldIsFilledOut_thenReturnNullForEmptyFields() throws Exception {
PropertyInsuranceDTO newPropertyInsurance = PropertyInsuranceDTO.builder()
.firstName("TestFirstName")
Expand Down Expand Up @@ -166,6 +173,7 @@ void addPropertyInsurance_whenJustOneFieldIsFilledOut_thenReturnNullForEmptyFiel

@Test
@DirtiesContext
@WithMockUser
void updatePropertyInsurance_whenInsuranceIdExistsInDb_thenReturnUpdatedInsurance() throws Exception {
PropertyInsurance propertyInsuranceBefore = PropertyInsurance.builder()
.id("1")
Expand Down Expand Up @@ -239,6 +247,7 @@ void updatePropertyInsurance_whenInsuranceIdExistsInDb_thenReturnUpdatedInsuranc

@Test
@DirtiesContext
@WithMockUser
void updatePropertyInsurance_whenInsuranceIdDoesNotExistsInDb_thenThrowException() throws Exception {
PropertyInsuranceUpdateDTO propertyInsuranceUpdateDTO = PropertyInsuranceUpdateDTO.builder()
.firstName("TestFirstName")
Expand Down Expand Up @@ -267,6 +276,7 @@ void updatePropertyInsurance_whenInsuranceIdDoesNotExistsInDb_thenThrowException

@Test
@DirtiesContext
@WithMockUser
void deletePropertyInsurance() throws Exception {
PropertyInsurance propertyInsurance = PropertyInsurance.builder()
.id("1")
Expand Down
Loading