From ec7c9b1da05c486ce9ea90037c09d72c0fdc1b7e Mon Sep 17 00:00:00 2001 From: KenCacciabueOrif Date: Fri, 12 Sep 2025 10:24:21 +0200 Subject: [PATCH 1/9] fix7local build error --- application.properties-dist | 28 ----------------- env-dist | 9 +++++- pom.xml | 8 ++++- .../auth/user/UserController.java | 2 +- src/main/resources/application.properties | 2 +- .../UserAuthenticationProviderTest.java | 31 ++----------------- .../auth/user/UserMapperTest.java | 2 +- 7 files changed, 20 insertions(+), 62 deletions(-) diff --git a/application.properties-dist b/application.properties-dist index a459d4df..4661b1a4 100644 --- a/application.properties-dist +++ b/application.properties-dist @@ -1,31 +1,3 @@ -# ╭──────────────────────────────────────────────────────────╮ -# │ oauth2 │ -# ╰──────────────────────────────────────────────────────────╯ -### Azure ### -custom.azure.account.tenant-id= - -# Azure Provider Configuration -spring.security.oauth2.client.provider.azure.issuer-uri=https://login.microsoftonline.com/${custom.azure.account.tenant-id}/v2.0 -spring.security.oauth2.client.provider.azure.authorization-uri=https://login.microsoftonline.com/${custom.azure.account.tenant-id}/oauth2/v2.0/authorize -spring.security.oauth2.client.provider.azure.token-uri=https://login.microsoftonline.com/${custom.azure.account.tenant-id}/oauth2/v2.0/token -spring.security.oauth2.client.provider.azure.user-info-uri=https://graph.microsoft.com/oidc/userinfo -spring.security.oauth2.client.provider.azure.jwk-set-uri=https://login.microsoftonline.com/${custom.azure.account.tenant-id}/discovery/v2.0/keys -spring.security.oauth2.client.provider.azure.user-name-attribute=email - -# Azure Client Configuration -spring.security.oauth2.client.registration.azure.client-id= -spring.security.oauth2.client.registration.azure.client-secret= -spring.security.oauth2.client.registration.azure.client-authentication-method=client_secret_post -spring.security.oauth2.client.registration.azure.authorization-grant-type=authorization_code -spring.security.oauth2.client.registration.azure.redirect-uri={baseUrl}/login/oauth2/code/{registrationId} -spring.security.oauth2.client.registration.azure.scope=openid,profile,email,User.Read -spring.security.oauth2.client.registration.azure.client-name=Azure - -### Google exemple for multiple provider login ### -spring.security.oauth2.client.registration.google.client-id=0 -spring.security.oauth2.client.registration.google.client-secret=0 -spring.security.oauth2.client.registration.google.scope=0 - ### Logging levels ### logging.level.root=ERROR logging.level.ch.sectioninformatique=ERROR diff --git a/env-dist b/env-dist index 40f46805..95150116 100644 --- a/env-dist +++ b/env-dist @@ -15,4 +15,11 @@ TEST_SPRING_DATASOURCE_URL=jdbc:mariadb://db:3306/test_db # User name and password used by Docker to create the database container DB_USERNAME=root -DB_PASSWORD=pwd \ No newline at end of file +DB_PASSWORD=pwd + +# Azure OAuth2 settings +# Set these values according to your Azure app registration +AZURE_REDIRECT_BASE_URL=http://localhost:8080 +AZURE_TENANT_ID= +AZURE_CLIENT_ID= +AZURE_CLIENT_SECRET= \ No newline at end of file diff --git a/pom.xml b/pom.xml index c93fd5e5..f112abcc 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ ch.sectioninformatique spring-auth - 0.1.0 + 0.1.1-SNAPSHOT spring-auth Authentication API to be used by other applications to identify their users @@ -115,6 +115,12 @@ org.springframework.security spring-security-oauth2-jose + + me.paulschwarz + spring-dotenv + 4.0.0 + test + diff --git a/src/main/java/ch/sectioninformatique/auth/user/UserController.java b/src/main/java/ch/sectioninformatique/auth/user/UserController.java index bb4edd5e..5eb58763 100644 --- a/src/main/java/ch/sectioninformatique/auth/user/UserController.java +++ b/src/main/java/ch/sectioninformatique/auth/user/UserController.java @@ -155,7 +155,7 @@ public ResponseEntity promoteToAdmin(@PathVariable Long userId) { public ResponseEntity revokeAdminRole(@PathVariable Long userId) { try { userService.revokeAdminRole(userId); - return ResponseEntity.ok().body("admin role revoked successfully"); + return ResponseEntity.ok().body("Admin role revoked successfully"); } catch (RuntimeException e) { return ResponseEntity.badRequest().body(e.getMessage()); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f418ca24..89fb601b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -47,6 +47,6 @@ spring.security.oauth2.client.registration.azure.client-id=${AZURE_CLIENT_ID} spring.security.oauth2.client.registration.azure.client-secret=${AZURE_CLIENT_SECRET} spring.security.oauth2.client.registration.azure.client-authentication-method=client_secret_post spring.security.oauth2.client.registration.azure.authorization-grant-type=authorization_code -spring.security.oauth2.client.registration.azure.redirect-uri={baseUrl}/login/oauth2/code/{registrationId} +spring.security.oauth2.client.registration.azure.redirect-uri=${AZURE_REDIRECT_BASE_URL}/login/oauth2/code/{registrationId} spring.security.oauth2.client.registration.azure.scope=openid,profile,email,User.Read spring.security.oauth2.client.registration.azure.client-name=Azure diff --git a/src/test/java/ch/sectioninformatique/auth/security/UserAuthenticationProviderTest.java b/src/test/java/ch/sectioninformatique/auth/security/UserAuthenticationProviderTest.java index 1d9a2ea4..f47b0613 100644 --- a/src/test/java/ch/sectioninformatique/auth/security/UserAuthenticationProviderTest.java +++ b/src/test/java/ch/sectioninformatique/auth/security/UserAuthenticationProviderTest.java @@ -17,6 +17,8 @@ import java.util.List; import java.util.Base64; +import java.util.ArrayList; + import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -169,33 +171,4 @@ void testValidateTokenStrongly_NewUser() { verify(userService).createAzureUser(any()); } - /** - * Tests the authority building functionality. - * Verifies that: - * - Role is properly prefixed with "ROLE_" - * - Permissions are correctly converted to authorities - * - All authorities are included in the result - */ - @Test - void testBuildAuthorities() throws Exception { - // Given - String role = "USER"; - List permissions = Arrays.asList("read", "write"); - - // When - Method method = UserAuthenticationProvider.class.getDeclaredMethod("buildAuthorities", String.class, List.class); - method.setAccessible(true); - @SuppressWarnings("unchecked") - List authorities = (List) method.invoke(authenticationProvider, role, permissions); - - // Then - assertNotNull(authorities); - assertEquals(3, authorities.size()); // ROLE_USER + 2 permissions - assertTrue(authorities.stream() - .anyMatch(auth -> auth.getAuthority().equals("ROLE_USER"))); - assertTrue(authorities.stream() - .anyMatch(auth -> auth.getAuthority().equals("read"))); - assertTrue(authorities.stream() - .anyMatch(auth -> auth.getAuthority().equals("write"))); - } } \ No newline at end of file diff --git a/src/test/java/ch/sectioninformatique/auth/user/UserMapperTest.java b/src/test/java/ch/sectioninformatique/auth/user/UserMapperTest.java index 45238a80..430814d0 100644 --- a/src/test/java/ch/sectioninformatique/auth/user/UserMapperTest.java +++ b/src/test/java/ch/sectioninformatique/auth/user/UserMapperTest.java @@ -111,7 +111,7 @@ void testSignUpToUser() { assertEquals("Smith", user.getLastName()); assertEquals("janesmith", user.getLogin()); assertNull(user.getPassword()); // Password should be ignored as per mapping - assertTrue(user.getMainRole() == null); // Roles should be empty as per mapping + assertTrue(user.getMainRole().getName() == null); // Roles should be empty as per mapping } /** From 3f08689110fca48dd019be91508da6b708268be6 Mon Sep 17 00:00:00 2001 From: KenCacciabueOrif Date: Tue, 30 Sep 2025 09:25:22 +0200 Subject: [PATCH 2/9] feat: added automated documentation for users/me --- compose.yml | 6 +- docs-output/users/me/curl-request.adoc | 5 + docs-output/users/me/http-request.adoc | 7 + docs-output/users/me/http-response.adoc | 8 + docs-output/users/me/httpie-request.adoc | 5 + docs-output/users/me/request-body.adoc | 4 + docs-output/users/me/response-body.adoc | 4 + pom.xml | 70 +++- .../auth/user/UserControllerTest.java | 322 +++--------------- 9 files changed, 150 insertions(+), 281 deletions(-) create mode 100644 docs-output/users/me/curl-request.adoc create mode 100644 docs-output/users/me/http-request.adoc create mode 100644 docs-output/users/me/http-response.adoc create mode 100644 docs-output/users/me/httpie-request.adoc create mode 100644 docs-output/users/me/request-body.adoc create mode 100644 docs-output/users/me/response-body.adoc diff --git a/compose.yml b/compose.yml index e3cffe45..d31ec81e 100644 --- a/compose.yml +++ b/compose.yml @@ -9,6 +9,8 @@ services: context: . dockerfile: Dockerfile target: "${ENVIRONMENT}" # Use the environment variable to target the desired stage + volumes: + - ./docs-output:/app/build/generated-snippets environment: # Pass environment variables to the container and the Spring Boot app SPRING_PROFILES_ACTIVE: "${ENVIRONMENT}" @@ -32,11 +34,11 @@ services: MARIADB_ROOT_PASSWORD: "${DB_PASSWORD}" MARIADB_DATABASE: "${ENVIRONMENT}_db" volumes: - - ./init.sql:/docker-entrypoint-initdb.d/init.sql + - ./init.sql:/docker-entrypoint-initdb.d/init.sql networks: - spring_network healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ] interval: 10s timeout: 5s retries: 5 diff --git a/docs-output/users/me/curl-request.adoc b/docs-output/users/me/curl-request.adoc new file mode 100644 index 00000000..95b249a1 --- /dev/null +++ b/docs-output/users/me/curl-request.adoc @@ -0,0 +1,5 @@ +[source,bash] +---- +$ curl 'http://localhost:8080/users/me' -i -X GET \ + -H 'Accept: application/json' +---- \ No newline at end of file diff --git a/docs-output/users/me/http-request.adoc b/docs-output/users/me/http-request.adoc new file mode 100644 index 00000000..79620cb9 --- /dev/null +++ b/docs-output/users/me/http-request.adoc @@ -0,0 +1,7 @@ +[source,http,options="nowrap"] +---- +GET /users/me HTTP/1.1 +Accept: application/json +Host: localhost:8080 + +---- \ No newline at end of file diff --git a/docs-output/users/me/http-response.adoc b/docs-output/users/me/http-response.adoc new file mode 100644 index 00000000..6dcb6ce8 --- /dev/null +++ b/docs-output/users/me/http-response.adoc @@ -0,0 +1,8 @@ +[source,http,options="nowrap"] +---- +HTTP/1.1 200 OK +Content-Type: application/json +Content-Length: 138 + +{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null} +---- \ No newline at end of file diff --git a/docs-output/users/me/httpie-request.adoc b/docs-output/users/me/httpie-request.adoc new file mode 100644 index 00000000..6200d74c --- /dev/null +++ b/docs-output/users/me/httpie-request.adoc @@ -0,0 +1,5 @@ +[source,bash] +---- +$ http GET 'http://localhost:8080/users/me' \ + 'Accept:application/json' +---- \ No newline at end of file diff --git a/docs-output/users/me/request-body.adoc b/docs-output/users/me/request-body.adoc new file mode 100644 index 00000000..dab5f81d --- /dev/null +++ b/docs-output/users/me/request-body.adoc @@ -0,0 +1,4 @@ +[source,options="nowrap"] +---- + +---- \ No newline at end of file diff --git a/docs-output/users/me/response-body.adoc b/docs-output/users/me/response-body.adoc new file mode 100644 index 00000000..9132868c --- /dev/null +++ b/docs-output/users/me/response-body.adoc @@ -0,0 +1,4 @@ +[source,json,options="nowrap"] +---- +{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null} +---- \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6cfc776b..d2c1d930 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot @@ -37,6 +37,12 @@ dotenv-java 3.0.0 + + + org.springframework.restdocs + spring-restdocs-mockmvc + test + org.springframework.boot spring-boot-starter-data-jpa @@ -46,7 +52,7 @@ spring-boot-starter-web - org.springframework.boot + org.springframework.boot spring-boot-starter-validation @@ -57,7 +63,6 @@ org.projectlombok lombok - 1.18.36 provided @@ -81,6 +86,12 @@ org.springframework.boot spring-boot-starter-test test + + + org.junit.vintage + junit-vintage-engine + + org.springframework.security @@ -95,7 +106,6 @@ jakarta.validation jakarta.validation-api - 3.0.2 org.mapstruct @@ -121,6 +131,7 @@ 4.0.0 provided + @@ -143,6 +154,55 @@ + + org.asciidoctor + asciidoctor-maven-plugin + 2.2.1 + + + generate-docs + prepare-package + + process-asciidoc + + + html + book + + + + + + org.springframework.restdocs + spring-restdocs-asciidoctor + {project-version} + + + + + maven-resources-plugin + + + copy-resources + prepare-package + + copy-resources + + + + ${project.build.outputDirectory}/static/docs + + + + + ${project.build.directory}/generated-docs + + + + + + + diff --git a/src/test/java/ch/sectioninformatique/auth/user/UserControllerTest.java b/src/test/java/ch/sectioninformatique/auth/user/UserControllerTest.java index 4c5524bd..42f0bea8 100644 --- a/src/test/java/ch/sectioninformatique/auth/user/UserControllerTest.java +++ b/src/test/java/ch/sectioninformatique/auth/user/UserControllerTest.java @@ -1,303 +1,77 @@ package ch.sectioninformatique.auth.user; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.junit.jupiter.MockitoSettings; -import org.mockito.quality.Strictness; -import org.springframework.http.ResponseEntity; +import org.mockito.Mockito; +import org.springframework.restdocs.RestDocumentationExtension; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import ch.sectioninformatique.auth.security.RoleRepository; +import ch.sectioninformatique.auth.security.UserAuthenticationProvider; -import org.springframework.http.HttpStatus; -import java.util.Arrays; -import java.util.List; +import org.springframework.http.MediaType; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import org.junit.jupiter.api.Test; -@ExtendWith(MockitoExtension.class) -@MockitoSettings(strictness = Strictness.LENIENT) -public class UserControllerTest { +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.MockMvc; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; - @Mock - private UserService userService; - @Mock - private SecurityContext securityContext; - @Mock - private Authentication authentication; +@ExtendWith(RestDocumentationExtension.class) +@WebMvcTest(controllers = UserController.class, + excludeAutoConfiguration = {SecurityAutoConfiguration.class, OAuth2ClientAutoConfiguration.class}) +@AutoConfigureMockMvc(addFilters = false) +@AutoConfigureRestDocs(outputDir = "build/generated-snippets") +class UserControllerTest { - @Mock - private UserRepository userRepository; + @Autowired + private MockMvc mockMvc; - @Mock - private RoleRepository roleRepository; + @MockBean + private UserService userService; - @Mock + @MockBean private UserMapper userMapper; - @InjectMocks - private UserController userController; - - @BeforeEach - void setUp() { - SecurityContextHolder.setContext(securityContext); - } - - @Test - void authenticatedUser_ReturnsCurrentUser() { - // Arrange - UserDto currentUser = new UserDto(1L, "John", "Doe", "john@test.com", null, null, "USER", null); - when(securityContext.getAuthentication()).thenReturn(authentication); - when(authentication.getPrincipal()).thenReturn(currentUser); - - // Act - ResponseEntity response = userController.authenticatedUser(); - - // Assert - assertEquals(200, response.getStatusCode().value()); - assertEquals(currentUser, response.getBody()); - } - - @Test - void allUsers_ReturnsListOfUsers() { - // Arrange - List users = Arrays.asList( - new User(1L, "John", "Doe", "john@test.com", "pass", null, null, null), - new User(2L, "Jane", "Smith", "jane@test.com", "pass", null, null, null) - ); - when(userService.allUsers()).thenReturn(users); - - // Act - ResponseEntity> response = userController.allUsers(); - - // Assert - assertEquals(200, response.getStatusCode().value()); - assertEquals(users, response.getBody()); - } - - @Test - void promoteToManager_Successful_ReturnsUserDto() { - // Arrange - Long userId = 1L; - UserDto expectedDto = new UserDto(1L, "John", "Doe", "john@test.com", null, null, "ROLE_MANAGER", null); - - when(userService.promoteToManager(userId)).thenReturn(expectedDto); - - // Act - ResponseEntity response = userController.promoteToManager(userId); - - // Assert - assertEquals(HttpStatus.OK, response.getStatusCode()); - assertEquals("User promoted to manager successfully", response.getBody()); - verify(userService).promoteToManager(userId); - } - - @Test - void promoteToManager_UserNotFound_ReturnsBadRequest() { - // Arrange - Long userId = 1L; - doThrow(new RuntimeException("User not found")).when(userService).promoteToManager(userId); - - // Act - ResponseEntity response = userController.promoteToManager(userId); - - // Assert - assertEquals(400, response.getStatusCode().value()); - assertEquals("User not found", response.getBody()); - verify(userService, times(1)).promoteToManager(userId); - } - - @Test - void revokeManagerRole_SuccessfulRevocation_ReturnsOkResponse() { - // Arrange - Long userId = 1L; - doNothing().when(userService).revokeManagerRole(userId); - - // Act - ResponseEntity response = userController.revokeManagerRole(userId); - - // Assert - assertEquals(200, response.getStatusCode().value()); - assertEquals("Manager role revoked successfully", response.getBody()); - verify(userService, times(1)).revokeManagerRole(userId); - } - - @Test - void revokeManagerRole_UserNotFound_ReturnsBadRequest() { - // Arrange - Long userId = 1L; - doThrow(new RuntimeException("User not found")).when(userService).revokeManagerRole(userId); - - // Act - ResponseEntity response = userController.revokeManagerRole(userId); - - // Assert - assertEquals(400, response.getStatusCode().value()); - assertEquals("User not found", response.getBody()); - verify(userService, times(1)).revokeManagerRole(userId); - } - - @Test - void promoteToSuperManager_SuccessfulPromotion_ReturnsOkResponse() { - // Arrange - Long userId = 1L; - UserDto expectedUser = new UserDto(userId, "John", "Doe", "john@test.com", null, null, "ROLE_ADMIN", null); - when(userService.promoteToAdmin(userId)).thenReturn(expectedUser); - - // Act - ResponseEntity response = userController.promoteToAdmin(userId); - - // Assert - assertEquals(200, response.getStatusCode().value()); - assertEquals("Admin role assigned successfully", response.getBody()); - verify(userService, times(1)).promoteToAdmin(userId); - } - - @Test - void promoteToAdmin_UserNotFound_ReturnsBadRequest() { - // Arrange - Long userId = 1L; - doThrow(new RuntimeException("User not found")).when(userService).promoteToAdmin(userId); - - // Act - ResponseEntity response = userController.promoteToAdmin(userId); - - // Assert - assertEquals(400, response.getStatusCode().value()); - assertEquals("User not found", response.getBody()); - verify(userService, times(1)).promoteToAdmin(userId); - } - - @Test - void revokeAdminRole_SuccessfulRevocation_ReturnsOkResponse() { - // Arrange - Long userId = 1L; - doNothing().when(userService).revokeAdminRole(userId); - - // Act - ResponseEntity response = userController.revokeAdminRole(userId); - - // Assert - assertEquals(200, response.getStatusCode().value()); - assertEquals("Admin role revoked successfully", response.getBody()); - verify(userService, times(1)).revokeAdminRole(userId); - } - - @Test - void revokeAdminRole_UserNotFound_ReturnsBadRequest() { - // Arrange - Long userId = 1L; - doThrow(new RuntimeException("User not found")).when(userService).revokeAdminRole(userId); - - // Act - ResponseEntity response = userController.revokeAdminRole(userId); - - // Assert - assertEquals(400, response.getStatusCode().value()); - assertEquals("User not found", response.getBody()); - verify(userService, times(1)).revokeAdminRole(userId); - } - - @Test - void downgradeAdminRole_SuccessfulDowngrade_ReturnsOkResponse() { - // Arrange - Long userId = 1L; - doNothing().when(userService).downgradeAdminRole(userId); - - // Act - ResponseEntity response = userController.downgradeAdminRole(userId); - - // Assert - assertEquals(200, response.getStatusCode().value()); - assertEquals("Admin role downgraded successfully", response.getBody()); - verify(userService, times(1)).downgradeAdminRole(userId); - } - - @Test - void downgradeAdminRole_UserNotFound_ReturnsBadRequest() { - // Arrange - Long userId = 1L; - doThrow(new RuntimeException("User not found")).when(userService).downgradeAdminRole(userId); - - // Act - ResponseEntity response = userController.downgradeAdminRole(userId); - - // Assert - assertEquals(400, response.getStatusCode().value()); - assertEquals("User not found", response.getBody()); - verify(userService, times(1)).downgradeAdminRole(userId); - } - - @Test - void deleteUser_SuccessfulDeletion_ReturnsOkResponse() { - // Arrange - Long userId = 1L; - UserDto authenticatedUser = new UserDto(userId, null, null, null, null, null, null, null); - authenticatedUser.setLogin("manager@test.com"); - authenticatedUser.setMainRole("ROLE_MANAGER"); - - when(securityContext.getAuthentication()).thenReturn(authentication); - when(authentication.getPrincipal()).thenReturn(authenticatedUser); - doNothing().when(userService).deleteUser(userId); + @MockBean + private RoleRepository roleRepository; - // Act - ResponseEntity response = userController.deleteUser(userId); + @MockBean + private UserRepository userRepository; - // Assert - assertEquals(200, response.getStatusCode().value()); - assertEquals("User deleted successfully", response.getBody()); - verify(userService, times(1)).deleteUser(userId); - } + @MockBean + private UserAuthenticationProvider userAuthenticationProvider; - @Test - void deleteUser_UserNotFound_ReturnsBadRequest() { - // Arrange - Long userId = 1L; - UserDto authenticatedUser = new UserDto(userId, null, null, null, null, null, null, null); - authenticatedUser.setLogin("manager@test.com"); - authenticatedUser.setMainRole("ROLE_MANAGER"); + @BeforeEach + void setUp() { + UserDto mockUser = new UserDto(1L, "John", "Doe", "john@test.com", null, null, "USER", null); - when(securityContext.getAuthentication()).thenReturn(authentication); - when(authentication.getPrincipal()).thenReturn(authenticatedUser); - doThrow(new RuntimeException("User not found")).when(userService).deleteUser(userId); + Authentication authentication = Mockito.mock(Authentication.class); + Mockito.when(authentication.getPrincipal()).thenReturn(mockUser); - // Act - ResponseEntity response = userController.deleteUser(userId); + SecurityContext securityContext = Mockito.mock(SecurityContext.class); + Mockito.when(securityContext.getAuthentication()).thenReturn(authentication); - // Assert - assertEquals(400, response.getStatusCode().value()); - assertEquals("User not found", response.getBody()); - verify(userService, times(1)).deleteUser(userId); + SecurityContextHolder.setContext(securityContext); } @Test - void deleteUser_UnauthorizedAccess_ReturnsBadRequest() { - // Arrange - Long userId = 1L; - UserDto authenticatedUser = new UserDto(userId, null, null, null, null, null, null, null); - authenticatedUser.setLogin("user@test.com"); - authenticatedUser.setMainRole("USER"); - - when(securityContext.getAuthentication()).thenReturn(authentication); - when(authentication.getPrincipal()).thenReturn(authenticatedUser); - doThrow(new RuntimeException("You don't have the necessary rights to perform this action")) - .when(userService).deleteUser(userId); - - // Act - ResponseEntity response = userController.deleteUser(userId); - - // Assert - assertEquals(400, response.getStatusCode().value()); - assertEquals("You don't have the necessary rights to perform this action", response.getBody()); - verify(userService, times(1)).deleteUser(userId); + void authenticatedUser_ReturnsCurrentUser_Doc() throws Exception { + this.mockMvc.perform(get("/users/me") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(document("users/me")); } -} \ No newline at end of file +} From 888a467577bf8f9100f738f8cc9a5a51b22f88d5 Mon Sep 17 00:00:00 2001 From: KenCacciabueOrif Date: Tue, 30 Sep 2025 09:44:15 +0200 Subject: [PATCH 3/9] feat: added index for the automated doc --- docs-output/index.adoc | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs-output/index.adoc diff --git a/docs-output/index.adoc b/docs-output/index.adoc new file mode 100644 index 00000000..137e60c3 --- /dev/null +++ b/docs-output/index.adoc @@ -0,0 +1,11 @@ += Getting Started With Spring REST Docs + +This is an example output for the /users/me endpoint: + +.request +include::users/me/http-request.adoc[] + +.response +include::users/me/http-response.adoc[] + +It shows the the data of the currently authenticated user. From 395cf258044f793fe2f8cd896075b5be29fb6c60 Mon Sep 17 00:00:00 2001 From: KenCacciabueOrif Date: Tue, 30 Sep 2025 10:53:03 +0200 Subject: [PATCH 4/9] feat: added automated index.html doc --- compose.yml | 2 +- docs-output/index.adoc | 11 - pom.xml | 14 +- src/asciidoc/html/html/index.html | 474 ++++++++++++++++++ src/asciidoc/html/index.html | 474 ++++++++++++++++++ src/asciidoc/index.adoc | 11 + .../asciidoc}/users/me/curl-request.adoc | 0 .../asciidoc}/users/me/http-request.adoc | 0 .../asciidoc}/users/me/http-response.adoc | 0 .../asciidoc}/users/me/httpie-request.adoc | 0 .../asciidoc}/users/me/request-body.adoc | 0 .../asciidoc}/users/me/response-body.adoc | 0 12 files changed, 973 insertions(+), 13 deletions(-) delete mode 100644 docs-output/index.adoc create mode 100644 src/asciidoc/html/html/index.html create mode 100644 src/asciidoc/html/index.html create mode 100644 src/asciidoc/index.adoc rename {docs-output => src/asciidoc}/users/me/curl-request.adoc (100%) rename {docs-output => src/asciidoc}/users/me/http-request.adoc (100%) rename {docs-output => src/asciidoc}/users/me/http-response.adoc (100%) rename {docs-output => src/asciidoc}/users/me/httpie-request.adoc (100%) rename {docs-output => src/asciidoc}/users/me/request-body.adoc (100%) rename {docs-output => src/asciidoc}/users/me/response-body.adoc (100%) diff --git a/compose.yml b/compose.yml index d31ec81e..28295822 100644 --- a/compose.yml +++ b/compose.yml @@ -10,7 +10,7 @@ services: dockerfile: Dockerfile target: "${ENVIRONMENT}" # Use the environment variable to target the desired stage volumes: - - ./docs-output:/app/build/generated-snippets + - ./src/asciidoc:/app/build/generated-snippets environment: # Pass environment variables to the container and the Spring Boot app SPRING_PROFILES_ACTIVE: "${ENVIRONMENT}" diff --git a/docs-output/index.adoc b/docs-output/index.adoc deleted file mode 100644 index 137e60c3..00000000 --- a/docs-output/index.adoc +++ /dev/null @@ -1,11 +0,0 @@ -= Getting Started With Spring REST Docs - -This is an example output for the /users/me endpoint: - -.request -include::users/me/http-request.adoc[] - -.response -include::users/me/http-response.adoc[] - -It shows the the data of the currently authenticated user. diff --git a/pom.xml b/pom.xml index d2c1d930..8a28cd0b 100644 --- a/pom.xml +++ b/pom.xml @@ -170,12 +170,24 @@ book + + convert-to-html + generate-resources + + process-asciidoc + + + src/asciidoc + index.adoc + /app/build/generated-snippets/html + + org.springframework.restdocs spring-restdocs-asciidoctor - {project-version} + ${spring-restdocs.version} diff --git a/src/asciidoc/html/html/index.html b/src/asciidoc/html/html/index.html new file mode 100644 index 00000000..40628ef3 --- /dev/null +++ b/src/asciidoc/html/html/index.html @@ -0,0 +1,474 @@ + + + + + + + +Getting Started With Spring REST Docs + + + + + +
+
+

This is an example output for a service running at http://localhost:8080:

+
+
+
request
+
+
GET /users/me HTTP/1.1
+Accept: application/json
+Host: localhost:8080
+
+
+
+
response
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 138
+
+{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
+
+
+
+

As you can see the format is very simple. In fact, you always get the same message.

+
+
+ + + \ No newline at end of file diff --git a/src/asciidoc/html/index.html b/src/asciidoc/html/index.html new file mode 100644 index 00000000..b022d106 --- /dev/null +++ b/src/asciidoc/html/index.html @@ -0,0 +1,474 @@ + + + + + + + +Spring Auth API Documentation + + + + + +
+
+

This is an example output for the GET /users/me endpoint.

+
+
+
request
+
+
GET /users/me HTTP/1.1
+Accept: application/json
+Host: localhost:8080
+
+
+
+
response
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 138
+
+{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
+
+
+
+

It gives information about the authenticated user.

+
+
+ + + \ No newline at end of file diff --git a/src/asciidoc/index.adoc b/src/asciidoc/index.adoc new file mode 100644 index 00000000..d4cfe928 --- /dev/null +++ b/src/asciidoc/index.adoc @@ -0,0 +1,11 @@ += Spring Auth API Documentation + +This is an example output for the `GET /users/me` endpoint. + +.request +include::users/me/http-request.adoc[] + +.response +include::users/me/http-response.adoc[] + +It gives informations about the authenticated user. diff --git a/docs-output/users/me/curl-request.adoc b/src/asciidoc/users/me/curl-request.adoc similarity index 100% rename from docs-output/users/me/curl-request.adoc rename to src/asciidoc/users/me/curl-request.adoc diff --git a/docs-output/users/me/http-request.adoc b/src/asciidoc/users/me/http-request.adoc similarity index 100% rename from docs-output/users/me/http-request.adoc rename to src/asciidoc/users/me/http-request.adoc diff --git a/docs-output/users/me/http-response.adoc b/src/asciidoc/users/me/http-response.adoc similarity index 100% rename from docs-output/users/me/http-response.adoc rename to src/asciidoc/users/me/http-response.adoc diff --git a/docs-output/users/me/httpie-request.adoc b/src/asciidoc/users/me/httpie-request.adoc similarity index 100% rename from docs-output/users/me/httpie-request.adoc rename to src/asciidoc/users/me/httpie-request.adoc diff --git a/docs-output/users/me/request-body.adoc b/src/asciidoc/users/me/request-body.adoc similarity index 100% rename from docs-output/users/me/request-body.adoc rename to src/asciidoc/users/me/request-body.adoc diff --git a/docs-output/users/me/response-body.adoc b/src/asciidoc/users/me/response-body.adoc similarity index 100% rename from docs-output/users/me/response-body.adoc rename to src/asciidoc/users/me/response-body.adoc From 5d9ce8f66eed9111d111fb523470093c15290743 Mon Sep 17 00:00:00 2001 From: KenCacciabueOrif Date: Tue, 30 Sep 2025 11:18:59 +0200 Subject: [PATCH 5/9] feat: added prettier json in doc --- .../html/html/html/html/html/index.html | 474 ++++++++++++++++++ src/asciidoc/html/html/html/html/index.html | 474 ++++++++++++++++++ src/asciidoc/html/html/html/index.html | 474 ++++++++++++++++++ src/asciidoc/html/html/index.html | 10 +- src/asciidoc/html/index.html | 39 +- src/asciidoc/index.adoc | 15 + src/asciidoc/users/all/curl-request.adoc | 5 + src/asciidoc/users/all/http-request.adoc | 7 + src/asciidoc/users/all/http-response.adoc | 38 ++ src/asciidoc/users/all/httpie-request.adoc | 5 + src/asciidoc/users/all/request-body.adoc | 4 + src/asciidoc/users/all/response-body.adoc | 34 ++ src/asciidoc/users/me/http-response.adoc | 13 +- src/asciidoc/users/me/response-body.adoc | 11 +- .../auth/user/UserControllerTest.java | 32 +- 15 files changed, 1618 insertions(+), 17 deletions(-) create mode 100644 src/asciidoc/html/html/html/html/html/index.html create mode 100644 src/asciidoc/html/html/html/html/index.html create mode 100644 src/asciidoc/html/html/html/index.html create mode 100644 src/asciidoc/users/all/curl-request.adoc create mode 100644 src/asciidoc/users/all/http-request.adoc create mode 100644 src/asciidoc/users/all/http-response.adoc create mode 100644 src/asciidoc/users/all/httpie-request.adoc create mode 100644 src/asciidoc/users/all/request-body.adoc create mode 100644 src/asciidoc/users/all/response-body.adoc diff --git a/src/asciidoc/html/html/html/html/html/index.html b/src/asciidoc/html/html/html/html/html/index.html new file mode 100644 index 00000000..40628ef3 --- /dev/null +++ b/src/asciidoc/html/html/html/html/html/index.html @@ -0,0 +1,474 @@ + + + + + + + +Getting Started With Spring REST Docs + + + + + +
+
+

This is an example output for a service running at http://localhost:8080:

+
+
+
request
+
+
GET /users/me HTTP/1.1
+Accept: application/json
+Host: localhost:8080
+
+
+
+
response
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 138
+
+{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
+
+
+
+

As you can see the format is very simple. In fact, you always get the same message.

+
+
+ + + \ No newline at end of file diff --git a/src/asciidoc/html/html/html/html/index.html b/src/asciidoc/html/html/html/html/index.html new file mode 100644 index 00000000..40628ef3 --- /dev/null +++ b/src/asciidoc/html/html/html/html/index.html @@ -0,0 +1,474 @@ + + + + + + + +Getting Started With Spring REST Docs + + + + + +
+
+

This is an example output for a service running at http://localhost:8080:

+
+
+
request
+
+
GET /users/me HTTP/1.1
+Accept: application/json
+Host: localhost:8080
+
+
+
+
response
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 138
+
+{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
+
+
+
+

As you can see the format is very simple. In fact, you always get the same message.

+
+
+ + + \ No newline at end of file diff --git a/src/asciidoc/html/html/html/index.html b/src/asciidoc/html/html/html/index.html new file mode 100644 index 00000000..810bd91f --- /dev/null +++ b/src/asciidoc/html/html/html/index.html @@ -0,0 +1,474 @@ + + + + + + + +Spring Auth API Documentation + + + + + +
+
+

This is an example output for the GET /users/me endpoint.

+
+
+
request
+
+
GET /users/me HTTP/1.1
+Accept: application/json
+Host: localhost:8080
+
+
+
+
response
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 138
+
+{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
+
+
+
+

It gives informations about the authenticated user.

+
+
+ + + \ No newline at end of file diff --git a/src/asciidoc/html/html/index.html b/src/asciidoc/html/html/index.html index 40628ef3..810bd91f 100644 --- a/src/asciidoc/html/html/index.html +++ b/src/asciidoc/html/html/index.html @@ -5,7 +5,7 @@ -Getting Started With Spring REST Docs +Spring Auth API Documentation + + + +
+
+

This is an example output for a service running at http://localhost:8080:

+
+
+
request
+
+
GET /users/me HTTP/1.1
+Accept: application/json
+Host: localhost:8080
+
+
+
+
response
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 138
+
+{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
+
+
+
+

As you can see the format is very simple. In fact, you always get the same message.

+
+
+ + + \ No newline at end of file diff --git a/src/asciidoc/html/html/html/html/html/html/index.html b/src/asciidoc/html/html/html/html/html/html/index.html new file mode 100644 index 00000000..40628ef3 --- /dev/null +++ b/src/asciidoc/html/html/html/html/html/html/index.html @@ -0,0 +1,474 @@ + + + + + + + +Getting Started With Spring REST Docs + + + + + +
+
+

This is an example output for a service running at http://localhost:8080:

+
+
+
request
+
+
GET /users/me HTTP/1.1
+Accept: application/json
+Host: localhost:8080
+
+
+
+
response
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 138
+
+{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
+
+
+
+

As you can see the format is very simple. In fact, you always get the same message.

+
+
+ + + \ No newline at end of file diff --git a/src/asciidoc/html/html/html/html/html/index.html b/src/asciidoc/html/html/html/html/html/index.html index 40628ef3..810bd91f 100644 --- a/src/asciidoc/html/html/html/html/html/index.html +++ b/src/asciidoc/html/html/html/html/html/index.html @@ -5,7 +5,7 @@ -Getting Started With Spring REST Docs +Spring Auth API Documentation - - - -
-
-

This is an example output for a service running at http://localhost:8080:

-
-
-
request
-
-
GET /users/me HTTP/1.1
-Accept: application/json
-Host: localhost:8080
-
-
-
-
response
-
-
HTTP/1.1 200 OK
-Content-Type: application/json
-Content-Length: 138
-
-{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
-
-
-
-

As you can see the format is very simple. In fact, you always get the same message.

-
-
- - - \ No newline at end of file diff --git a/src/asciidoc/html/html/html/html/html/html/index.html b/src/asciidoc/html/html/html/html/html/html/index.html deleted file mode 100644 index 40628ef3..00000000 --- a/src/asciidoc/html/html/html/html/html/html/index.html +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - -Getting Started With Spring REST Docs - - - - - -
-
-

This is an example output for a service running at http://localhost:8080:

-
-
-
request
-
-
GET /users/me HTTP/1.1
-Accept: application/json
-Host: localhost:8080
-
-
-
-
response
-
-
HTTP/1.1 200 OK
-Content-Type: application/json
-Content-Length: 138
-
-{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
-
-
-
-

As you can see the format is very simple. In fact, you always get the same message.

-
-
- - - \ No newline at end of file diff --git a/src/asciidoc/html/html/html/html/html/index.html b/src/asciidoc/html/html/html/html/html/index.html deleted file mode 100644 index 810bd91f..00000000 --- a/src/asciidoc/html/html/html/html/html/index.html +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - -Spring Auth API Documentation - - - - - -
-
-

This is an example output for the GET /users/me endpoint.

-
-
-
request
-
-
GET /users/me HTTP/1.1
-Accept: application/json
-Host: localhost:8080
-
-
-
-
response
-
-
HTTP/1.1 200 OK
-Content-Type: application/json
-Content-Length: 138
-
-{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
-
-
-
-

It gives informations about the authenticated user.

-
-
- - - \ No newline at end of file diff --git a/src/asciidoc/html/html/html/html/index.html b/src/asciidoc/html/html/html/html/index.html deleted file mode 100644 index 810bd91f..00000000 --- a/src/asciidoc/html/html/html/html/index.html +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - -Spring Auth API Documentation - - - - - -
-
-

This is an example output for the GET /users/me endpoint.

-
-
-
request
-
-
GET /users/me HTTP/1.1
-Accept: application/json
-Host: localhost:8080
-
-
-
-
response
-
-
HTTP/1.1 200 OK
-Content-Type: application/json
-Content-Length: 138
-
-{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
-
-
-
-

It gives informations about the authenticated user.

-
-
- - - \ No newline at end of file diff --git a/src/asciidoc/html/html/html/index.html b/src/asciidoc/html/html/html/index.html deleted file mode 100644 index 641934ca..00000000 --- a/src/asciidoc/html/html/html/index.html +++ /dev/null @@ -1,509 +0,0 @@ - - - - - - - -Spring Auth API Documentation - - - - - -
-
-

User Endpoints

-
-
-

Get Authenticated User

-
-

This is an example output for the GET /users/me endpoint.

-
-
-
request
-
-
GET /users/me HTTP/1.1
-Accept: application/json
-Host: localhost:8080
-
-
-
-
response
-
-
HTTP/1.1 200 OK
-Content-Type: application/json
-Content-Length: 138
-
-{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
-
-
-
-

It gives informations about the authenticated user.

-
-
-
-

Get All Users

-
-

This is an example output for the GET /users/all endpoint.

-
-
-
request
-
-
GET /users/all HTTP/1.1
-Accept: application/json
-Host: localhost:8080
-
-
-
-
response
-
-
HTTP/1.1 200 OK
-Content-Type: application/json
-Content-Length: 551
-
-[{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","password":"pass","createdAt":null,"updatedAt":null,"mainRole":null,"authorities":[],"credentialsNonExpired":true,"accountNonExpired":true,"accountNonLocked":true,"username":"john@test.com","enabled":true},{"id":2,"firstName":"Jane","lastName":"Smith","login":"jane@test.com","password":"pass","createdAt":null,"updatedAt":null,"mainRole":null,"authorities":[],"credentialsNonExpired":true,"accountNonExpired":true,"accountNonLocked":true,"username":"jane@test.com","enabled":true}]
-
-
-
-

It gives informations about all users.

-
-
-
-
-
- - - \ No newline at end of file diff --git a/src/asciidoc/html/html/index.html b/src/asciidoc/html/html/index.html deleted file mode 100644 index 641934ca..00000000 --- a/src/asciidoc/html/html/index.html +++ /dev/null @@ -1,509 +0,0 @@ - - - - - - - -Spring Auth API Documentation - - - - - -
-
-

User Endpoints

-
-
-

Get Authenticated User

-
-

This is an example output for the GET /users/me endpoint.

-
-
-
request
-
-
GET /users/me HTTP/1.1
-Accept: application/json
-Host: localhost:8080
-
-
-
-
response
-
-
HTTP/1.1 200 OK
-Content-Type: application/json
-Content-Length: 138
-
-{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","token":null,"refreshToken":null,"mainRole":"USER","permissions":null}
-
-
-
-

It gives informations about the authenticated user.

-
-
-
-

Get All Users

-
-

This is an example output for the GET /users/all endpoint.

-
-
-
request
-
-
GET /users/all HTTP/1.1
-Accept: application/json
-Host: localhost:8080
-
-
-
-
response
-
-
HTTP/1.1 200 OK
-Content-Type: application/json
-Content-Length: 551
-
-[{"id":1,"firstName":"John","lastName":"Doe","login":"john@test.com","password":"pass","createdAt":null,"updatedAt":null,"mainRole":null,"authorities":[],"credentialsNonExpired":true,"accountNonExpired":true,"accountNonLocked":true,"username":"john@test.com","enabled":true},{"id":2,"firstName":"Jane","lastName":"Smith","login":"jane@test.com","password":"pass","createdAt":null,"updatedAt":null,"mainRole":null,"authorities":[],"credentialsNonExpired":true,"accountNonExpired":true,"accountNonLocked":true,"username":"jane@test.com","enabled":true}]
-
-
-
-

It gives informations about all users.

-
-
-
-
-
- - - \ No newline at end of file diff --git a/src/asciidoc/index.adoc b/src/asciidoc/index.adoc index b2589cca..b3c67a86 100644 --- a/src/asciidoc/index.adoc +++ b/src/asciidoc/index.adoc @@ -24,3 +24,14 @@ include::users/all/http-request.adoc[] include::users/all/http-response.adoc[] It gives informations about all users. + +=== Promote User to Manager +This is an example output for the `PUT /users/{userId}/promote-manager` endpoint. + +.request +include::users/promote-manager/http-request.adoc[] + +.response +include::users/promote-manager/http-response.adoc[] + +It promotes a user to the "MANAGER" role. diff --git a/src/asciidoc/users/promote-manager/curl-request.adoc b/src/asciidoc/users/promote-manager/curl-request.adoc new file mode 100644 index 00000000..92a731c0 --- /dev/null +++ b/src/asciidoc/users/promote-manager/curl-request.adoc @@ -0,0 +1,5 @@ +[source,bash] +---- +$ curl 'http://localhost:8080/users/2/promote-manager' -i -X PUT \ + -H 'Accept: application/json' +---- \ No newline at end of file diff --git a/src/asciidoc/users/promote-manager/http-request.adoc b/src/asciidoc/users/promote-manager/http-request.adoc new file mode 100644 index 00000000..587ea3a2 --- /dev/null +++ b/src/asciidoc/users/promote-manager/http-request.adoc @@ -0,0 +1,8 @@ +[source,http,options="nowrap"] +---- +PUT /users/2/promote-manager HTTP/1.1 +Accept: application/json +Host: localhost:8080 +Content-Type: application/x-www-form-urlencoded + +---- \ No newline at end of file diff --git a/src/asciidoc/users/promote-manager/http-response.adoc b/src/asciidoc/users/promote-manager/http-response.adoc new file mode 100644 index 00000000..b07b7150 --- /dev/null +++ b/src/asciidoc/users/promote-manager/http-response.adoc @@ -0,0 +1,8 @@ +[source,http,options="nowrap"] +---- +HTTP/1.1 200 OK +Content-Type: application/json +Content-Length: 37 + +User promoted to manager successfully +---- \ No newline at end of file diff --git a/src/asciidoc/users/promote-manager/httpie-request.adoc b/src/asciidoc/users/promote-manager/httpie-request.adoc new file mode 100644 index 00000000..fae8140e --- /dev/null +++ b/src/asciidoc/users/promote-manager/httpie-request.adoc @@ -0,0 +1,5 @@ +[source,bash] +---- +$ http PUT 'http://localhost:8080/users/2/promote-manager' \ + 'Accept:application/json' +---- \ No newline at end of file diff --git a/src/asciidoc/users/promote-manager/request-body.adoc b/src/asciidoc/users/promote-manager/request-body.adoc new file mode 100644 index 00000000..dab5f81d --- /dev/null +++ b/src/asciidoc/users/promote-manager/request-body.adoc @@ -0,0 +1,4 @@ +[source,options="nowrap"] +---- + +---- \ No newline at end of file diff --git a/src/asciidoc/users/promote-manager/response-body.adoc b/src/asciidoc/users/promote-manager/response-body.adoc new file mode 100644 index 00000000..57621213 --- /dev/null +++ b/src/asciidoc/users/promote-manager/response-body.adoc @@ -0,0 +1,4 @@ +[source,json,options="nowrap"] +---- +User promoted to manager successfully +---- \ No newline at end of file diff --git a/src/test/java/ch/sectioninformatique/auth/user/UserControllerTest.java b/src/test/java/ch/sectioninformatique/auth/user/UserControllerTest.java index ed937653..2bdac36e 100644 --- a/src/test/java/ch/sectioninformatique/auth/user/UserControllerTest.java +++ b/src/test/java/ch/sectioninformatique/auth/user/UserControllerTest.java @@ -17,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.util.Arrays; @@ -94,4 +95,28 @@ void allUsers_ReturnsListOfUsers_Doc() throws Exception { .andExpect(status().isOk()) .andDo(document("users/all", preprocessResponse(prettyPrint()))); } + + @Test + void promoteToManager_Successful_ReturnsUserDto_Doc() throws Exception { + UserDto mockUser = new UserDto(1L, "John", "Doe", "john@test.com", null, null, "Admin", null); + + Authentication authentication = Mockito.mock(Authentication.class); + Mockito.when(authentication.getPrincipal()).thenReturn(mockUser); + + SecurityContext securityContext = Mockito.mock(SecurityContext.class); + Mockito.when(securityContext.getAuthentication()).thenReturn(authentication); + + SecurityContextHolder.setContext(securityContext); + // Arrange + Long userId = 2L; + UserDto expectedDto = new UserDto(2L, "Jane", "Smith", "jane@test.com", null, null, "MANAGER", null); + + when(userService.promoteToManager(userId)).thenReturn(expectedDto); + + this.mockMvc.perform(put("/users/{userId}/promote-manager", userId) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(document("users/promote-manager", preprocessResponse(prettyPrint()))); + } + } From a057837227dc2af47138e402172092c2ab54581f Mon Sep 17 00:00:00 2001 From: KenCacciabueOrif Date: Tue, 30 Sep 2025 13:25:35 +0200 Subject: [PATCH 8/9] docs: ajout lien automated doc on github --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 72352bf5..c1942c02 100644 --- a/README.md +++ b/README.md @@ -178,4 +178,6 @@ It creates an .adoc file in src/asciidoc and an html page in the docs that can b Link to the generated .adoc : [src/asciidoc/index.adoc](src/asciidoc/index.adoc) -Link to the generated .html : [src/asciidoc/index.html](docs/index.html) \ No newline at end of file +Link to the generated .html : [src/asciidoc/index.html](docs/index.html) + +Link to the doc : [https://orifinformatique.github.io/spring-auth/](https://orifinformatique.github.io/spring-auth/) \ No newline at end of file From fda10c407808bdddb09587b1fa890badf63397f0 Mon Sep 17 00:00:00 2001 From: Didier Viret Date: Wed, 1 Oct 2025 09:02:53 +0200 Subject: [PATCH 9/9] docs: rework Spring REST Docs informations in README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c1942c02..cbbdb16b 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ This project provides an authentication API to be used by other applications to - [Microsoft Entra Azure AD oAuth2](#microsoft-entra-azure-ad-oauth2) - [Commands cheat-sheet](#commands-cheat-sheet) - [Simplified sequence diagram](#simplified-sequence-diagram) + - [Spring REST Docs](#spring-rest-docs) - [Sources](#sources) ## Getting Started @@ -172,12 +173,12 @@ Check if the project's structure is valid ## Spring REST Docs -The application work with an automated documentation from the Spring REST Docs package that is created when it run with docker and the test environment +The application contains an automated documentation from the Spring REST Docs package. The documentation is created when running the application in test environment. -It creates an .adoc file in src/asciidoc and an html page in the docs that can be consulted in github +It creates an index.adoc file in the "src/asciidoc" folder and an index.html page in the "docs" folder. -Link to the generated .adoc : [src/asciidoc/index.adoc](src/asciidoc/index.adoc) +Link to the generated index.adoc : [src/asciidoc/index.adoc](src/asciidoc/index.adoc) -Link to the generated .html : [src/asciidoc/index.html](docs/index.html) +Link to the generated index.html : [docs/index.html](docs/index.html) -Link to the doc : [https://orifinformatique.github.io/spring-auth/](https://orifinformatique.github.io/spring-auth/) \ No newline at end of file +Link to the doc on GitHub : [https://orifinformatique.github.io/spring-auth/](https://orifinformatique.github.io/spring-auth/) \ No newline at end of file