Skip to content

Commit

Permalink
Modify JWT
Browse files Browse the repository at this point in the history
  • Loading branch information
sdikyarts committed May 26, 2024
1 parent 55e4ef9 commit 85b8c74
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 35 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jobs:
sed -i "s|JDBC_DATABASE_USERNAME=.*|JDBC_DATABASE_USERNAME=${{ secrets.JDBC_DATABASE_USERNAME }}|g" src/main/resources/application.properties
sed -i "s|JDBC_DATABASE_PASSWORD=.*|JDBC_DATABASE_PASSWORD=${{ secrets.JDBC_DATABASE_PASSWORD }}|g" src/main/resources/application.properties
sed -i "s|PRODUCTION=.*|PRODUCTION=${{ secrets.PRODUCTION }}|g" src/main/resources/application.properties
sed -i 's|${JWT_SECRET}|'"${{ secrets.JWT_SECRET }}"'|g' src/main/resources/application-prod.properties
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Build with Gradle
Expand Down Expand Up @@ -107,7 +108,7 @@ jobs:
run: export DOCKER_BUILDKIT=1
- name: Build Docker Image
run: |
docker build --build-arg PRODUCTION=$PRODUCTION --build-arg JDBC_DATABASE_PASSWORD=$JDBC_DATABASE_PASSWORD --build-arg JDBC_DATABASE_URL=$JDBC_DATABASE_URL --build-arg JDBC_DATABASE_USERNAME=$JDBC_DATABASE_USERNAME -t ${{ secrets.REGISTRY_USER }}/${{ secrets.IMAGE_NAME }}:${{ secrets.IMAGE_TAG }} .
docker build --build-arg PRODUCTION=$PRODUCTION --build-arg JDBC_DATABASE_PASSWORD=$JDBC_DATABASE_PASSWORD --build-arg JDBC_DATABASE_URL=$JDBC_DATABASE_URL --build-arg JDBC_DATABASE_USERNAME=$JDBC_DATABASE_USERNAME --build-arg JWT_SECRET=${{ secrets.JWT_SECRET }} -t ${{ secrets.REGISTRY_USER }}/${{ secrets.IMAGE_NAME }}:${{ secrets.IMAGE_TAG }} .
docker push ${{ secrets.REGISTRY_USER }}/${{ secrets.IMAGE_NAME }}:${{ secrets.IMAGE_TAG }}
deploy:
Expand Down
16 changes: 8 additions & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ dependencies {
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.5")
}

sonar {
properties {
property("sonar.projectKey", "ADPRO-C11_snackscription-subscription-admin")
property("sonar.organization", "adpro-c11")
property("sonar.host.url", "https://sonarcloud.io")
}
}

tasks.register<Test>("unitTest") {
description = "Runs unit tests."
group = "verification"
Expand All @@ -70,14 +78,6 @@ tasks.register<Test>("functionalTest") {
}
}

sonar {
properties {
property("sonar.projectKey", "ADPRO-C11_snackscription-subscription-admin")
property("sonar.organization", "adpro-c11")
property("sonar.host.url", "https://sonarcloud.io")
}
}

tasks.withType<Test>().configureEach() {
useJUnitPlatform()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package snackscription.subscriptionadmin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
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.UsernamePasswordAuthenticationFilter;
import snackscription.subscriptionadmin.utils.JWTUtils;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final JWTUtils jwtUtils;

Expand All @@ -18,8 +23,9 @@ public SecurityConfig(JWTUtils jwtUtils) {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable)
.cors(Customizer.withDefaults())
.authorizeHttpRequests(authorizeRequests ->
authorizeRequests.requestMatchers("/adminSubscription/**", "/public/**").permitAll()
authorizeRequests.requestMatchers("/admin/**", "/public/**").permitAll()
.anyRequest().authenticated())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(new JWTAuthFilter(jwtUtils), UsernamePasswordAuthenticationFilter.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import snackscription.subscriptionadmin.dto.AdminDTO;
import snackscription.subscriptionadmin.model.AdminSubscription;
import snackscription.subscriptionadmin.service.AdminService;
import snackscription.subscriptionadmin.utils.JWTUtils;

import java.util.List;
import java.util.Optional;
Expand All @@ -16,9 +17,18 @@
@CrossOrigin(origins = "http://localhost:3000")
public class AdminController {
private final AdminService adminService;
private final JWTUtils jwtUtils;

public AdminController(AdminService adminService) {
public AdminController(AdminService adminService, JWTUtils jwtUtils) {
this.adminService = adminService;
this.jwtUtils = jwtUtils;
}

private void validateToken(String token) throws IllegalAccessException {
String jwt = token.replace("Bearer ", "");
if (!jwtUtils.isTokenValid(jwt)) {
throw new IllegalAccessException("You have no permission.");
}
}

@GetMapping("")
Expand All @@ -27,19 +37,23 @@ public ResponseEntity<String> home() {
}

@PostMapping("/create")
public CompletableFuture<ResponseEntity<AdminSubscription>> create(@RequestBody AdminDTO adminDTO) {
public CompletableFuture<ResponseEntity<AdminSubscription>> create(@RequestHeader(value="Authorization") String token, @RequestBody AdminDTO adminDTO)
throws IllegalAccessException {
validateToken(token);
return adminService.create(adminDTO).thenApply(ResponseEntity::ok)
.exceptionally(ex -> ResponseEntity.badRequest().build());

}

@GetMapping("/list")
public CompletableFuture<ResponseEntity<List<AdminDTO>>> findAll() {
public CompletableFuture<ResponseEntity<List<AdminDTO>>> findAll(@RequestHeader(value="Authorization") String token) throws IllegalAccessException {
validateToken(token);
return adminService.findAll().thenApply(ResponseEntity::ok);
}

@GetMapping("/{subscriptionId}")
public CompletableFuture<ResponseEntity<AdminDTO>> findById(@PathVariable String subscriptionId) {
public CompletableFuture<ResponseEntity<AdminDTO>> findById(@RequestHeader(value="Authorization") String token, @PathVariable String subscriptionId) throws IllegalAccessException {
validateToken(token);
try {
UUID.fromString(subscriptionId);
} catch (IllegalArgumentException e) {
Expand All @@ -50,7 +64,8 @@ public CompletableFuture<ResponseEntity<AdminDTO>> findById(@PathVariable String
}

@PutMapping("/update")
public CompletableFuture<ResponseEntity<AdminSubscription>> update(@RequestBody AdminDTO adminDTO) {
public CompletableFuture<ResponseEntity<AdminSubscription>> update(@RequestHeader(value="Authorization") String token, @RequestBody AdminDTO adminDTO) throws IllegalAccessException {
validateToken(token);
if (adminDTO.getSubscriptionId() == null) {
return CompletableFuture.completedFuture(ResponseEntity.badRequest().build());
}
Expand All @@ -65,7 +80,8 @@ public CompletableFuture<ResponseEntity<AdminSubscription>> update(@RequestBody
}

@DeleteMapping("/{subscriptionId}")
public CompletableFuture<ResponseEntity<String>> delete(@PathVariable String subscriptionId) {
public CompletableFuture<ResponseEntity<String>> delete(@RequestHeader(value="Authorization") String token, @PathVariable String subscriptionId) throws IllegalAccessException{
validateToken(token);
try {
UUID.fromString(subscriptionId);
} catch (IllegalArgumentException e) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application-prod.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ spring.datasource.password=YouMakeStrayKidsStay
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.format_sql=true

JWT_SECRET=${JWT_SECRET}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import snackscription.subscriptionadmin.dto.AdminDTO;
import snackscription.subscriptionadmin.model.AdminSubscription;
import snackscription.subscriptionadmin.service.AdminService;
import snackscription.subscriptionadmin.utils.JWTUtils;

import java.util.Collections;
import java.util.List;
Expand All @@ -22,11 +23,16 @@ public class AdminControllerTest {
@Mock
private AdminService adminService;

@Mock
private JWTUtils jwtUtils;

@InjectMocks
private AdminController adminController;

private AdminDTO adminDTO;
private AdminSubscription adminSubscription;
private final String validToken =
"eyJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiQURNSU4iLCJzdWIiOiJhZG1pbkBnbWFpbC5jb20iLCJpYXQiOjE3MTY0NTUyMzgsImV4cCI6MTcxNjU0MTYzOH0.D5PKsxm3jr7SybMfsBylQqd2lT8S_cuX3jQWGolOD78";

@BeforeEach
void setUp(){
Expand All @@ -47,6 +53,8 @@ void setUp(){
adminSubscription.setSubscriberId("0325");
adminSubscription.setSubscriptionBoxId("143ily");
adminSubscription.setSubscriptionStatus("PENDING");

when(jwtUtils.isTokenValid(validToken)).thenReturn(true);
}

@Test
Expand All @@ -57,99 +65,99 @@ void testHome(){
}

@Test
void testCreate(){
void testCreate() throws IllegalAccessException{
when(adminService.create(adminDTO)).thenReturn(CompletableFuture.completedFuture(adminSubscription));

CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.create(adminDTO);
CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.create(validToken, adminDTO);
assertNotNull(response);
assertEquals(ResponseEntity.ok(adminSubscription), response.join());
}

@Test
void testFindAll(){
void testFindAll() throws IllegalAccessException{
List<AdminDTO> adminDTOList = Collections.singletonList(adminDTO);
when(adminService.findAll()).thenReturn(CompletableFuture.completedFuture(adminDTOList));

CompletableFuture<ResponseEntity<List<AdminDTO>>> response = adminController.findAll();
CompletableFuture<ResponseEntity<List<AdminDTO>>> response = adminController.findAll(validToken);
assertNotNull(response);
assertEquals(ResponseEntity.ok(adminDTOList), response.join());
}

@Test
void testFindById(){
void testFindById() throws IllegalAccessException{
String validUUID = "8a56e04b-d0c8-4e43-b2e0-fdf43e304d9e";
adminDTO.setSubscriptionId(validUUID);
adminSubscription.setSubscriptionId(validUUID);
when(adminService.findById(validUUID)).thenReturn(CompletableFuture.completedFuture(adminDTO));

CompletableFuture<ResponseEntity<AdminDTO>> result = adminController.findById(validUUID);
CompletableFuture<ResponseEntity<AdminDTO>> result = adminController.findById(validToken, validUUID);

assertNotNull(result);
assertTrue(result.isDone());
assertEquals(ResponseEntity.ok(adminDTO), result.join());
}

@Test
void testUpdate(){
void testUpdate() throws IllegalAccessException{
when(adminService.update(adminDTO)).thenReturn(CompletableFuture.completedFuture(adminSubscription));

CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.update(adminDTO);
CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.update(validToken, adminDTO);
assertNotNull(response);
assertEquals(ResponseEntity.ok(adminSubscription), response.join());
}

@Test
void testDelete(){
void testDelete() throws IllegalAccessException{
String validUUID = "8a56e04b-d0c8-4e43-b2e0-fdf43e304d9e";
when(adminService.delete(validUUID)).thenReturn(CompletableFuture.completedFuture(null));

CompletableFuture<ResponseEntity<String>> response = adminController.delete(validUUID);
CompletableFuture<ResponseEntity<String>> response = adminController.delete(validToken, validUUID);
assertNotNull(response);
assertEquals(ResponseEntity.ok("DELETE SUCCESS"), response.join());
}

@Test
void testUpdateInvalidSubscriptionId(){
void testUpdateInvalidSubscriptionId() throws IllegalAccessException{
AdminDTO adminDTO = new AdminDTO();

CompletableFuture<ResponseEntity<AdminSubscription>> expectedResponse = CompletableFuture.completedFuture(ResponseEntity.badRequest().build());
CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.update(adminDTO);
CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.update(validToken, adminDTO);

assertTrue(response.isDone());
assertEquals(expectedResponse.join(), response.join());
}

@Test
void testUpdateNonexistentSubscription(){
void testUpdateNonexistentSubscription() throws IllegalAccessException{
AdminDTO adminDTO = new AdminDTO();
adminDTO.setSubscriptionId(UUID.randomUUID().toString());
CompletableFuture<ResponseEntity<AdminSubscription>> expectedResponse = CompletableFuture.completedFuture(ResponseEntity.notFound().build());

when(adminService.findById(adminDTO.getSubscriptionId())).thenReturn(CompletableFuture.completedFuture(null));

CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.update(adminDTO);
CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.update(validToken, adminDTO);

assertTrue(response.isDone());
assertEquals(expectedResponse.join(), response.join());
}

@Test
void testDeleteInvalidSubscriptionId(){
void testDeleteInvalidSubscriptionId() throws IllegalAccessException{
CompletableFuture<ResponseEntity<String>> expectedResponse = CompletableFuture.completedFuture(ResponseEntity.badRequest().build());
CompletableFuture<ResponseEntity<String>> response = adminController.delete("invalid-id");
CompletableFuture<ResponseEntity<String>> response = adminController.delete(validToken, "invalid-id");

assertTrue(response.isDone());
assertEquals(expectedResponse.join(), response.join());
}

@Test
void testDeleteNonexistentSubscription(){
void testDeleteNonexistentSubscription() throws IllegalAccessException{
String validUUID = UUID.randomUUID().toString();
CompletableFuture<ResponseEntity<String>> expectedResponse = CompletableFuture.completedFuture(ResponseEntity.notFound().build());

when(adminService.delete(validUUID)).thenThrow(new IllegalArgumentException("Subscription not found"));

CompletableFuture<ResponseEntity<String>> response = adminController.delete(validUUID);
CompletableFuture<ResponseEntity<String>> response = adminController.delete(validToken, validUUID);

assertTrue(response.isDone());
assertEquals(expectedResponse.join(), response.join());
Expand Down

0 comments on commit 85b8c74

Please sign in to comment.