Commit 0072239c authored by Adam Paulen's avatar Adam Paulen
Browse files

Merge branch 'configure-auth-user' into 'main'

Configure auth user

See merge request !28
parents afcbd27e 949eb43d
Loading
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        <version>2.3.3.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
@@ -90,6 +91,7 @@
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
        <version>3.4.4</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
@@ -188,6 +190,40 @@
        <artifactId>artemis-jms-client</artifactId>
        <version>${artemis-jms.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-text</artifactId>
        <version>1.13.1</version>
      </dependency>
      <dependency>
        <groupId>com.google.code.findbugs</groupId>
        <artifactId>jsr305</artifactId>
        <version>3.0.2</version>
      </dependency>
      <dependency>
        <groupId>org.openapitools</groupId>
        <artifactId>jackson-databind-nullable</artifactId>
        <version>0.2.6</version>
      </dependency>
      <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
      </dependency>
      <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.3.2</version>
      </dependency>
      <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.18.1</version>
      </dependency>
      <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
      </dependency>
    </dependencies>
  </dependencyManagement>

@@ -248,6 +284,18 @@
    </pluginManagement>

    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <excludes>
            <exclude>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
            </exclude>
          </excludes>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
+65 −1
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@
    <name>user-service</name>
    <description>user</description>



    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
@@ -48,12 +50,24 @@
            <artifactId>mapstruct-processor</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
@@ -64,6 +78,56 @@
            <artifactId>mockito-core</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>jakarta.validation</groupId>
            <artifactId>jakarta.validation-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-observation-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

    <build>
+61 −0
Original line number Diff line number Diff line
package cz.muni.fi.pa165.user.config;

import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.web.SecurityFilterChain;


import static cz.muni.fi.pa165.commons.enums.OAuthScopes.*;


@Configuration
@EnableWebSecurity
public class SecurityConfig {


    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(x -> x
                        .requestMatchers(
                                "/swagger-ui.html",
                                "/swagger-ui/**",
                                "/v3/api-docs/**",
                                "/webjars/**",
                                "/swagger-resources/**",
                                "/swagger-ui/index.html",
                                "/swagger-ui/swagger-initializer.js",
                                "/actuator/**"
                        ).permitAll()
                        .requestMatchers(HttpMethod.POST, "/librarians/**").hasAuthority(ADMIN_SCOPE)
                        .requestMatchers(HttpMethod.DELETE, "/librarians/**").hasAuthority(ADMIN_SCOPE)
                        .requestMatchers(HttpMethod.PUT, "/librarians/**").hasAuthority(ADMIN_SCOPE)
                        .requestMatchers(HttpMethod.GET, "/librarians/**").hasAnyAuthority(ADMIN_SCOPE, LIBRARIAN_SCOPE, MEMBER_SCOPE)
                        .requestMatchers(HttpMethod.POST, "/members/**").hasAnyAuthority(ADMIN_SCOPE, LIBRARIAN_SCOPE)
                        .requestMatchers(HttpMethod.DELETE, "/members/**").hasAnyAuthority(ADMIN_SCOPE, LIBRARIAN_SCOPE)
                        .requestMatchers(HttpMethod.GET, "/members/**").hasAnyAuthority(ADMIN_SCOPE, LIBRARIAN_SCOPE, MEMBER_SCOPE)
                        .requestMatchers(HttpMethod.PUT, "/members/**").hasAnyAuthority(ADMIN_SCOPE, LIBRARIAN_SCOPE)

                )
                .oauth2ResourceServer(oauth2 -> oauth2.opaqueToken(Customizer.withDefaults()));

        return http.build();
    }

    @Bean
    public OpenApiCustomizer openAPICustomizer() {
        return openApi -> {
            openApi.getComponents().addSecuritySchemes(SECURITY_SCHEME_BEARER,
                    new SecurityScheme()
                            .type(SecurityScheme.Type.HTTP)
                            .scheme("bearer")
                            .description("provide a valid access token"));
        };
    }
}
+16 −8
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
@@ -40,7 +41,8 @@ public class LibrarianRestController {
    @GetMapping("/")
    @Operation(
            summary = "List all librarians",
            description = "Returns a paginated list of all registered librarians"
            description = "Returns a paginated list of all registered librarians",
            security = @SecurityRequirement(name = "Bearer")
    )
    @ApiResponse(responseCode = "200", description = "Successfully retrieved librarian list")
    public ResponseEntity<Page<LibrarianDto>> findAll(
@@ -52,7 +54,8 @@ public class LibrarianRestController {
    @PostMapping("/ids")
    @Operation(
            summary = "Find librarians by IDs",
            description = "Returns multiple librarians using a list of their UUID identifiers"
            description = "Returns multiple librarians using a list of their UUID identifiers",
            security = @SecurityRequirement(name = "Bearer")
    )
    @ApiResponse(responseCode = "200", description = "Successfully retrieved librarians")
    @ApiResponse(responseCode = "400", description = "Invalid ID format")
@@ -69,7 +72,8 @@ public class LibrarianRestController {
    @GetMapping("/email/{email}")
    @Operation(
            summary = "Find librarian by email",
            description = "Returns a single librarian using their unique email address"
            description = "Returns a single librarian using their unique email address",
            security = @SecurityRequirement(name = "Bearer")
    )
    @ApiResponse(responseCode = "200", description = "Librarian found")
    @ApiResponse(responseCode = "404", description = "Librarian not found")
@@ -86,7 +90,8 @@ public class LibrarianRestController {
    @GetMapping("/{id}")
    @Operation(
            summary = "Get librarian by ID",
            description = "Returns detailed information about a specific librarian"
            description = "Returns detailed information about a specific librarian",
            security = @SecurityRequirement(name = "Bearer")
    )
    @ApiResponse(responseCode = "200", description = "Librarian found")
    @ApiResponse(responseCode = "404", description = "Librarian not found")
@@ -105,7 +110,8 @@ public class LibrarianRestController {
    @PostMapping("/")
    @Operation(
            summary = "Create new librarian",
            description = "Registers a new librarian in the system"
            description = "Registers a new librarian in the system",
            security = @SecurityRequirement(name = "Bearer")
    )
    @ApiResponse(
            responseCode = "201",
@@ -127,7 +133,8 @@ public class LibrarianRestController {
    @PutMapping("/{id}")
    @Operation(
            summary = "Update librarian profile",
            description = "Updates personal information and credentials of an existing librarian"
            description = "Updates personal information and credentials of an existing librarian",
            security = @SecurityRequirement(name = "Bearer")
    )
    @ApiResponse(responseCode = "200", description = "Librarian updated successfully")
    @ApiResponse(responseCode = "400", description = "Invalid input data")
@@ -151,7 +158,8 @@ public class LibrarianRestController {
    @DeleteMapping("/{id}")
    @Operation(
            summary = "Delete librarian",
            description = "Permanently removes a librarian from the system"
            description = "Permanently removes a librarian from the system",
            security = @SecurityRequirement(name = "Bearer")
    )
    @ApiResponse(responseCode = "200", description = "Librarian deleted successfully")
    @ApiResponse(responseCode = "404", description = "Librarian not found")
+15 −7
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.servers.Server;
import io.swagger.v3.oas.annotations.servers.ServerVariable;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
@@ -52,7 +53,8 @@ public class MemberRestController {
    }

    @GetMapping(path = "/{id}")
    @Operation(summary = "Find member by ID", description = "Returns a member with the corresponding ID.")
    @Operation(summary = "Find member by ID", description = "Returns a member with the corresponding ID.",
            security = @SecurityRequirement(name = "Bearer"))
    @ApiResponse(responseCode = "200", description = "Member found")
    @ApiResponse(responseCode = "404", description = "Member not found")
    public ResponseEntity<MemberDto> findById(
@@ -62,7 +64,8 @@ public class MemberRestController {
    }

    @GetMapping(path = "/detailed/{id}")
    @Operation(summary = "Find detailed member by ID", description = "Returns a detailed member object with the corresponding ID.")
    @Operation(summary = "Find detailed member by ID", description = "Returns a detailed member object with the corresponding ID.",
            security = @SecurityRequirement(name = "Bearer"))
    @ApiResponse(responseCode = "200", description = "Member found")
    @ApiResponse(responseCode = "404", description = "Member not found")
    public ResponseEntity<MemberDto> findByIdDetailed(
@@ -72,14 +75,16 @@ public class MemberRestController {
    }

    @GetMapping(path = "/")
    @Operation(summary = "Find all members", description = "Returns a page of all registered library members.")
    @Operation(summary = "Find all members", description = "Returns a page of all registered library members.",
            security = @SecurityRequirement(name = "Bearer"))
    @ApiResponse(responseCode = "200", description = "Successfully retrieved list of members")
    public ResponseEntity<Page<MemberDto>> findAll(Pageable pageable) {
        return new ResponseEntity<>(memberFacade.findAll(pageable), HttpStatus.OK);
    }

    @PostMapping(path = "/")
    @Operation(summary = "Register a new member", description = "Registers a new library member using user creation data.")
    @Operation(summary = "Register a new member", description = "Registers a new library member using user creation data.",
            security = @SecurityRequirement(name = "Bearer"))
    @ApiResponse(responseCode = "201", description = "Member registered successfully")
    @ApiResponse(responseCode = "400", description = "Invalid input")
    public ResponseEntity<MemberDto> registerMember(
@@ -89,7 +94,8 @@ public class MemberRestController {
    }

    @PostMapping(path = "/ids")
    @Operation(summary = "Find members by a list of IDs", description = "Returns members matching the provided set of UUIDs.")
    @Operation(summary = "Find members by a list of IDs", description = "Returns members matching the provided set of UUIDs.",
            security = @SecurityRequirement(name = "Bearer"))
    @ApiResponse(responseCode = "200", description = "Successfully retrieved list of members")
    @ApiResponse(responseCode = "400", description = "Invalid input")
    public ResponseEntity<List<MemberDto>> findMembersByIds(
@@ -99,7 +105,8 @@ public class MemberRestController {
    }

    @PutMapping(path = "/{id}")
    @Operation(summary = "Update member", description = "Updates an existing library member's information.")
    @Operation(summary = "Update member", description = "Updates an existing library member's information.",
            security = @SecurityRequirement(name = "Bearer"))
    @ApiResponse(responseCode = "200", description = "Member updated successfully")
    @ApiResponse(responseCode = "400", description = "Invalid input")
    @ApiResponse(responseCode = "404", description = "Member not found")
@@ -113,7 +120,8 @@ public class MemberRestController {
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "Delete member", description = "Deletes a library member by ID.")
    @Operation(summary = "Delete member", description = "Deletes a library member by ID.",
            security = @SecurityRequirement(name = "Bearer"))
    @ApiResponse(responseCode = "200", description = "Member deleted successfully")
    @ApiResponse(responseCode = "404", description = "Member not found")
    public ResponseEntity<MemberDto> deleteMember(
Loading