From a8caaf0d6ecb5ec3ff069413df77c7c17c1f551d Mon Sep 17 00:00:00 2001 From: Vilem Gottwald <xvigo.dev@gmail.com> Date: Wed, 8 May 2024 01:35:19 +0200 Subject: [PATCH] user service security --- user-service/pom.xml | 9 +++ .../java/cz/muni/fi/obs/UserManagement.java | 66 +++++++++++++++ .../main/java/cz/muni/fi/obs/api/UserDto.java | 6 +- .../fi/obs/controller/UserController.java | 76 ++++++++++++++++- .../cz/muni/fi/obs/data/UserTableSeeder.java | 12 ++- .../java/cz/muni/fi/obs/data/dbo/User.java | 3 + .../fi/obs/facade/UserManagementFacade.java | 1 - .../cz/muni/fi/obs/security/Security.java | 33 ++++++++ .../AuthorityBankerOrCustomerRead.java | 16 ++++ .../AuthorityBankerOrCustomerWrite.java | 17 ++++ .../annotations/AuthorityBankerRead.java | 15 ++++ .../annotations/AuthorityBankerWrite.java | 15 ++++ .../annotations/AuthorityCustomerRead.java | 15 ++++ .../annotations/AuthorityCustomerWrite.java | 15 ++++ .../muni/fi/obs/security/enums/UserScope.java | 26 ++++++ .../exceptions/AccessDeniedException.java | 7 ++ .../cz/muni/fi/obs/service/UserService.java | 7 +- .../src/main/resources/application.yml | 19 +++++ .../db/migration/V0__initialize_database.sql | 1 + .../fi/obs/controller/UserControllerTest.java | 36 ++++++++- .../controller/UserControllerWebMvcTest.java | 5 ++ .../obs/facade/UserManagementFacadeTest.java | 81 +++++++++++-------- .../muni/fi/obs/service/UserServiceTest.java | 61 +++++++++----- user-service/src/test/resources/seed_db.sql | 15 ++-- 24 files changed, 483 insertions(+), 74 deletions(-) create mode 100644 user-service/src/main/java/cz/muni/fi/obs/security/Security.java create mode 100644 user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerOrCustomerRead.java create mode 100644 user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerOrCustomerWrite.java create mode 100644 user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerRead.java create mode 100644 user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerWrite.java create mode 100644 user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityCustomerRead.java create mode 100644 user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityCustomerWrite.java create mode 100644 user-service/src/main/java/cz/muni/fi/obs/security/enums/UserScope.java create mode 100644 user-service/src/main/java/cz/muni/fi/obs/security/exceptions/AccessDeniedException.java diff --git a/user-service/pom.xml b/user-service/pom.xml index 3b95013..5206fb1 100644 --- a/user-service/pom.xml +++ b/user-service/pom.xml @@ -96,6 +96,10 @@ <artifactId>spring-boot-starter-data-jpa</artifactId> <version>${spring.boot.version}</version> </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> + </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> @@ -106,6 +110,11 @@ <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-test</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/user-service/src/main/java/cz/muni/fi/obs/UserManagement.java b/user-service/src/main/java/cz/muni/fi/obs/UserManagement.java index a9501ef..0bc92ad 100644 --- a/user-service/src/main/java/cz/muni/fi/obs/UserManagement.java +++ b/user-service/src/main/java/cz/muni/fi/obs/UserManagement.java @@ -1,14 +1,80 @@ package cz.muni.fi.obs; +import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springdoc.core.customizers.OpenApiCustomizer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; +@EnableMethodSecurity @EnableFeignClients @SpringBootApplication public class UserManagement { + public static final String SECURITY_SCHEME_BEARER = "Bearer"; public static void main(String[] args) { SpringApplication.run(UserManagement.class, args); } + + @Bean + SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.oauth2ResourceServer(oauth2 -> oauth2.opaqueToken(Customizer.withDefaults())); + return http.build(); + } + +// @Bean +// SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { +// String baseUri = "/v1/users"; +// http +// .authorizeHttpRequests(x -> x +// .requestMatchers(HttpMethod.POST, baseUri + "/**").hasAuthority("SCOPE_test_write") +// .requestMatchers(HttpMethod.PUT, baseUri + "/**").hasAuthority("SCOPE_test_write") +// .requestMatchers(HttpMethod.GET, baseUri + "nationalities").permitAll() +// .requestMatchers(HttpMethod.GET, baseUri + "/**").hasAuthority("SCOPE_test_read") +// .anyRequest().permitAll() +// ) +// .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 an access token") + ) +// .addSecuritySchemes("MUNI OAuth2", +// new SecurityScheme() +// .type(SecurityScheme.Type.OAUTH2) +// .description("Get access token with OAuth2 Authorization Code Grant") +// .flows(new OAuthFlows() +// .authorizationCode(new OAuthFlow() +// .authorizationUrl("https://oidc.muni.cz/oidc/authorize") +// .tokenUrl("https://oidc.muni.cz/oidc/token") +// .scopes(new Scopes() +// .addString +// ("test_read", "reading events") +// .addString +// ("test_write", "creating events") +// .addString +// ("test_1", +// "deleting +// events") +// ) +// ) +// ) +// ) + ; + }; + } } diff --git a/user-service/src/main/java/cz/muni/fi/obs/api/UserDto.java b/user-service/src/main/java/cz/muni/fi/obs/api/UserDto.java index 22a91a8..88eb2e8 100644 --- a/user-service/src/main/java/cz/muni/fi/obs/api/UserDto.java +++ b/user-service/src/main/java/cz/muni/fi/obs/api/UserDto.java @@ -14,6 +14,9 @@ public record UserDto( @Schema(description = "Unique ID of the user", example = "d333c127-470b-4680-8c7c-70988998b329") UUID id, + @Schema(description = "ID of the user from MUNI OAuth2", example = "555222@muni.cz") + String oauthId, + @Schema(description = "First name of the user", example = "John") String firstName, @@ -43,7 +46,8 @@ public record UserDto( if (user == null) { return null; } - return UserDto.builder().id(user.getId()).firstName(user.getFirstName()).lastName(user.getLastName()) + return UserDto.builder().id(user.getId()).oauthId(user.getOauthId()).firstName(user.getFirstName()).lastName( + user.getLastName()) .phoneNumber(user.getPhoneNumber()).email(user.getEmail()).birthDate(user.getBirthDate()) .nationality(user.getNationality()).birthNumber(user.getBirthNumber()).active(user.isActive()) .build(); diff --git a/user-service/src/main/java/cz/muni/fi/obs/controller/UserController.java b/user-service/src/main/java/cz/muni/fi/obs/controller/UserController.java index 83277e7..0968c09 100644 --- a/user-service/src/main/java/cz/muni/fi/obs/controller/UserController.java +++ b/user-service/src/main/java/cz/muni/fi/obs/controller/UserController.java @@ -1,8 +1,12 @@ package cz.muni.fi.obs.controller; +import cz.muni.fi.obs.UserManagement; import cz.muni.fi.obs.api.*; import cz.muni.fi.obs.data.enums.Nationality; import cz.muni.fi.obs.facade.UserManagementFacade; +import cz.muni.fi.obs.security.Security; +import cz.muni.fi.obs.security.annotations.*; +import cz.muni.fi.obs.security.enums.UserScope; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -12,6 +16,7 @@ import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.media.Content; 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 lombok.extern.slf4j.Slf4j; @@ -51,10 +56,12 @@ import java.util.UUID; public class UserController { private final UserManagementFacade userManagementFacade; + private final Security security; @Autowired - public UserController(UserManagementFacade userManagementFacade) { + public UserController(UserManagementFacade userManagementFacade, Security security) { this.userManagementFacade = userManagementFacade; + this.security = security; } @Operation(summary = "Get available nationalities") @@ -64,14 +71,20 @@ public class UserController { return ResponseEntity.ok(Nationality.values()); } + @Operation( summary = "Create a new user", + security = @SecurityRequirement(name = UserManagement.SECURITY_SCHEME_BEARER, + scopes = {UserScope.Const.CUSTOMER_WRITE}), responses = { @ApiResponse(responseCode = "201", description = "User created"), @ApiResponse(responseCode = "400", description = "Invalid input data", content = @Content(schema = @Schema(implementation = ValidationErrors.class))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content()), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content()), } ) + @AuthorityCustomerWrite @PostMapping("/create") @CrossOrigin(origins = "*") public ResponseEntity<UserDto> createUser(@Valid @RequestBody UserCreateDto userCreateDto) { @@ -82,12 +95,17 @@ public class UserController { @Operation( summary = "Get user by ID", + security = @SecurityRequirement(name = UserManagement.SECURITY_SCHEME_BEARER, + scopes = {UserScope.Const.CUSTOMER_READ, UserScope.Const.BANKER_READ}), responses = { @ApiResponse(responseCode = "200", description = "User found"), @ApiResponse(responseCode = "404", description = "User not found", content = @Content(schema = @Schema(implementation = NotFoundResponse.class))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content()), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content()), } ) + @AuthorityBankerOrCustomerRead @GetMapping("/{userId}") @CrossOrigin(origins = "*") public ResponseEntity<UserDto> getUser( @@ -96,19 +114,29 @@ public class UserController { ) { log.info("Getting user with id: " + userId); UserDto user = userManagementFacade.getUser(userId); + + if (!security.isUserBanker()) { + security.checkUserIsOwner(user.oauthId()); + } + return ResponseEntity.ok(user); } @Operation( summary = "Get users by optional search parameters", + security = @SecurityRequirement(name = UserManagement.SECURITY_SCHEME_BEARER, + scopes = {UserScope.Const.BANKER_READ}), responses = { @ApiResponse(responseCode = "200", description = "User found"), @ApiResponse(responseCode = "404", description = "User not found", content = @Content(schema = @Schema(implementation = NotFoundResponse.class))), @ApiResponse(responseCode = "400", description = "Invalid search parameters", content = @Content(schema = @Schema(implementation = ValidationFailedResponse.class))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content()), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content()), } ) + @AuthorityBankerRead @GetMapping("") @CrossOrigin(origins = "*") public Page<UserDto> getUsers(@ParameterObject UserSearchParamsDto searchParams, @@ -119,14 +147,19 @@ public class UserController { @Operation( summary = "Update user by ID", + security = @SecurityRequirement(name = UserManagement.SECURITY_SCHEME_BEARER, + scopes = {UserScope.Const.CUSTOMER_WRITE, UserScope.Const.BANKER_WRITE}), responses = { @ApiResponse(responseCode = "200", description = "User updated"), @ApiResponse(responseCode = "404", description = "User not found", content = @Content(schema = @Schema(implementation = NotFoundResponse.class))), @ApiResponse(responseCode = "400", description = "Invalid input data", content = @Content(schema = @Schema(implementation = ValidationFailedResponse.class))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content()), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content()), } ) + @AuthorityBankerOrCustomerWrite @PutMapping("/{userId}") @CrossOrigin(origins = "*") public ResponseEntity<UserDto> updateUser( @@ -135,17 +168,27 @@ public class UserController { @Valid @RequestBody UserUpdateDto userUpdateDto) { log.info("Updating user with id: " + userId); UserDto user = userManagementFacade.updateUser(userId, userUpdateDto); + + if (!security.isUserBanker()) { + security.checkUserIsOwner(user.oauthId()); + } + return ResponseEntity.ok(user); } @Operation( summary = "Deactivate user by ID", + security = @SecurityRequirement(name = UserManagement.SECURITY_SCHEME_BEARER, + scopes = {UserScope.Const.BANKER_WRITE}), responses = { @ApiResponse(responseCode = "200", description = "User deactivated"), @ApiResponse(responseCode = "404", description = "User not found", - content = @Content(schema = @Schema(implementation = NotFoundResponse.class))) + content = @Content(schema = @Schema(implementation = NotFoundResponse.class))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content()), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content()), } ) + @AuthorityBankerWrite @PostMapping("/{userId}/deactivate") @CrossOrigin(origins = "*") public ResponseEntity<UserDto> deactivateUser( @@ -163,12 +206,17 @@ public class UserController { @Operation( summary = "Activate user by ID", + security = @SecurityRequirement(name = UserManagement.SECURITY_SCHEME_BEARER, + scopes = {UserScope.Const.BANKER_WRITE}), responses = { @ApiResponse(responseCode = "200", description = "User activated"), @ApiResponse(responseCode = "404", description = "User not found", - content = @Content(schema = @Schema(implementation = NotFoundResponse.class))) + content = @Content(schema = @Schema(implementation = NotFoundResponse.class))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content()), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content()), } ) + @AuthorityBankerWrite @PostMapping("/{userId}/activate") @CrossOrigin(origins = "*") public ResponseEntity<UserDto> activateUser( @@ -185,14 +233,19 @@ public class UserController { @Operation( summary = "Create user account for user by ID", + security = @SecurityRequirement(name = UserManagement.SECURITY_SCHEME_BEARER, + scopes = {UserScope.Const.CUSTOMER_WRITE, UserScope.Const.BANKER_WRITE}), responses = { @ApiResponse(responseCode = "201", description = "Account created"), @ApiResponse(responseCode = "404", description = "User not found", content = @Content(schema = @Schema(implementation = NotFoundResponse.class))), @ApiResponse(responseCode = "400", description = "Invalid input data", content = @Content(schema = @Schema(implementation = ValidationFailedResponse.class))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content()), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content()), } ) + @AuthorityBankerOrCustomerWrite @PostMapping("/{userId}/accounts/create") @CrossOrigin(origins = "*") public ResponseEntity<AccountDto> createUserAccount( @@ -202,6 +255,12 @@ public class UserController { @Valid @RequestBody AccountCreateDto accountCreateDto ) { log.info("Creating user account for user with id: " + userId); + + UserDto user = userManagementFacade.getUser(userId); + if (!security.isUserBanker()) { + security.checkUserIsOwner(user.oauthId()); + } + AccountDto account = userManagementFacade.createAccount(userId, accountCreateDto); if (account == null) { log.error("Could not create account for user with id: " + userId); @@ -212,12 +271,17 @@ public class UserController { @Operation( summary = "Get user accounts by user ID", + security = @SecurityRequirement(name = UserManagement.SECURITY_SCHEME_BEARER, + scopes = {UserScope.Const.CUSTOMER_READ, UserScope.Const.BANKER_READ}), responses = { @ApiResponse(responseCode = "200", description = "Accounts found"), @ApiResponse(responseCode = "404", description = "User not found", content = @Content(schema = @Schema(implementation = NotFoundResponse.class))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content()), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content()), } ) + @AuthorityBankerOrCustomerWrite @GetMapping("/{userId}/accounts") @CrossOrigin(origins = "*") public ResponseEntity<List<AccountDto>> getUserAccounts( @@ -225,6 +289,12 @@ public class UserController { example = "4121add0-f5d7-4128-9c8f-e81fa93237c5") @PathVariable("userId") UUID userId ) { log.info("Getting user accounts for user with id: " + userId); + + UserDto user = userManagementFacade.getUser(userId); + if (!security.isUserBanker()) { + security.checkUserIsOwner(user.oauthId()); + } + List<AccountDto> accounts = userManagementFacade.getUserAccounts(userId); if (accounts == null) { log.error("Could not get accounts for user with id: " + userId); diff --git a/user-service/src/main/java/cz/muni/fi/obs/data/UserTableSeeder.java b/user-service/src/main/java/cz/muni/fi/obs/data/UserTableSeeder.java index 710c6bd..a40fab6 100644 --- a/user-service/src/main/java/cz/muni/fi/obs/data/UserTableSeeder.java +++ b/user-service/src/main/java/cz/muni/fi/obs/data/UserTableSeeder.java @@ -40,7 +40,8 @@ public class UserTableSeeder { } private List<User> getUserSeedData() { - User user1 = new User("John", + User user1 = new User("212354@muni.cz", + "John", "Doe", "+420102306985", "JohnDoe@gmail.com", @@ -50,7 +51,8 @@ public class UserTableSeeder { true ); user1.setId(UUID.fromString("4121add0-f5d7-4128-9c8f-e81fa93237c5")); - User user2 = new User("Petr", + User user2 = new User("214354@muni.cz", + "Petr", "Hrach", "+420556991123", "PeteruvMail@gmail.com", @@ -60,7 +62,8 @@ public class UserTableSeeder { true ); user2.setId(UUID.fromString("4121add0-f5d7-4128-9c8f-e81fa93237c6")); - User user3 = new User("Iva", + User user3 = new User("212384@muni.cz", + "Iva", "Dolava", "+421752694158", "IvaDol@gmail.com", @@ -70,7 +73,8 @@ public class UserTableSeeder { true ); user3.setId(UUID.fromString("4121add0-f5d7-4128-9c8f-e81fa93237c7")); - User user4 = new User("Pavel", + User user4 = new User("812354@muni.cz", + "Pavel", "Horel", "+421346952176", "PavelHore@email.sk", diff --git a/user-service/src/main/java/cz/muni/fi/obs/data/dbo/User.java b/user-service/src/main/java/cz/muni/fi/obs/data/dbo/User.java index 30c78fc..8279c86 100644 --- a/user-service/src/main/java/cz/muni/fi/obs/data/dbo/User.java +++ b/user-service/src/main/java/cz/muni/fi/obs/data/dbo/User.java @@ -17,6 +17,9 @@ import java.time.LocalDate; @Table(name = "us_user") public class User extends Dbo { + @Column(nullable = false, unique = true) + private String oauthId; + @Column(nullable = false) private String firstName; diff --git a/user-service/src/main/java/cz/muni/fi/obs/facade/UserManagementFacade.java b/user-service/src/main/java/cz/muni/fi/obs/facade/UserManagementFacade.java index d053cc1..ff0c531 100644 --- a/user-service/src/main/java/cz/muni/fi/obs/facade/UserManagementFacade.java +++ b/user-service/src/main/java/cz/muni/fi/obs/facade/UserManagementFacade.java @@ -60,7 +60,6 @@ public class UserManagementFacade { } public List<AccountDto> getUserAccounts(UUID userId) { - userService.getUser(userId); return userAccountService.getUserAccounts(userId); } } diff --git a/user-service/src/main/java/cz/muni/fi/obs/security/Security.java b/user-service/src/main/java/cz/muni/fi/obs/security/Security.java new file mode 100644 index 0000000..15c2bd4 --- /dev/null +++ b/user-service/src/main/java/cz/muni/fi/obs/security/Security.java @@ -0,0 +1,33 @@ +package cz.muni.fi.obs.security; + +import cz.muni.fi.obs.security.enums.UserScope; +import cz.muni.fi.obs.security.exceptions.AccessDeniedException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + + +@Component +public class Security { + + public String getCurrentUserOauthId() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return authentication.getName(); + } + + public void checkUserIsOwner(String oauthId) throws AccessDeniedException { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (!authentication.getName().equals(oauthId)) { + throw new AccessDeniedException("You are not owner of this resource"); + } + } + + public boolean isUserBanker() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return authentication.getAuthorities() + .stream() + .anyMatch(a -> a.getAuthority().equals(UserScope.Const.BANKER_READ) || + a.getAuthority().equals(UserScope.Const.BANKER_WRITE)); + } +} diff --git a/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerOrCustomerRead.java b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerOrCustomerRead.java new file mode 100644 index 0000000..3db5352 --- /dev/null +++ b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerOrCustomerRead.java @@ -0,0 +1,16 @@ +package cz.muni.fi.obs.security.annotations; + +import cz.muni.fi.obs.security.enums.UserScope; +import org.springframework.security.access.prepost.PreAuthorize; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize( + "hasAuthority('" + UserScope.Const.CUSTOMER_READ + "') or hasAuthority('" + UserScope.Const.BANKER_READ + "')") +public @interface AuthorityBankerOrCustomerRead { +} diff --git a/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerOrCustomerWrite.java b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerOrCustomerWrite.java new file mode 100644 index 0000000..e67479d --- /dev/null +++ b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerOrCustomerWrite.java @@ -0,0 +1,17 @@ +package cz.muni.fi.obs.security.annotations; + +import cz.muni.fi.obs.security.enums.UserScope; +import org.springframework.security.access.prepost.PreAuthorize; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize( + "hasAuthority('" + UserScope.Const.CUSTOMER_WRITE + "') or hasAuthority('" + UserScope.Const.BANKER_WRITE + + "')") +public @interface AuthorityBankerOrCustomerWrite { +} diff --git a/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerRead.java b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerRead.java new file mode 100644 index 0000000..60a7f3a --- /dev/null +++ b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerRead.java @@ -0,0 +1,15 @@ +package cz.muni.fi.obs.security.annotations; + +import cz.muni.fi.obs.security.enums.UserScope; +import org.springframework.security.access.prepost.PreAuthorize; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize("hasAuthority('" + UserScope.Const.BANKER_READ + "')") +public @interface AuthorityBankerRead { +} diff --git a/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerWrite.java b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerWrite.java new file mode 100644 index 0000000..d914ae8 --- /dev/null +++ b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityBankerWrite.java @@ -0,0 +1,15 @@ +package cz.muni.fi.obs.security.annotations; + +import cz.muni.fi.obs.security.enums.UserScope; +import org.springframework.security.access.prepost.PreAuthorize; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize("hasAuthority('" + UserScope.Const.BANKER_WRITE + "')") +public @interface AuthorityBankerWrite { +} diff --git a/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityCustomerRead.java b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityCustomerRead.java new file mode 100644 index 0000000..96f5396 --- /dev/null +++ b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityCustomerRead.java @@ -0,0 +1,15 @@ +package cz.muni.fi.obs.security.annotations; + +import cz.muni.fi.obs.security.enums.UserScope; +import org.springframework.security.access.prepost.PreAuthorize; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize("hasAuthority('" + UserScope.Const.CUSTOMER_READ + "')") +public @interface AuthorityCustomerRead { +} diff --git a/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityCustomerWrite.java b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityCustomerWrite.java new file mode 100644 index 0000000..e68e2d9 --- /dev/null +++ b/user-service/src/main/java/cz/muni/fi/obs/security/annotations/AuthorityCustomerWrite.java @@ -0,0 +1,15 @@ +package cz.muni.fi.obs.security.annotations; + +import cz.muni.fi.obs.security.enums.UserScope; +import org.springframework.security.access.prepost.PreAuthorize; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize("hasAuthority('" + UserScope.Const.CUSTOMER_WRITE + "')") +public @interface AuthorityCustomerWrite { +} diff --git a/user-service/src/main/java/cz/muni/fi/obs/security/enums/UserScope.java b/user-service/src/main/java/cz/muni/fi/obs/security/enums/UserScope.java new file mode 100644 index 0000000..73d393e --- /dev/null +++ b/user-service/src/main/java/cz/muni/fi/obs/security/enums/UserScope.java @@ -0,0 +1,26 @@ +package cz.muni.fi.obs.security.enums; + +public enum UserScope { + BANKER_READ(Const.BANKER_READ), + BANKER_WRITE(Const.BANKER_WRITE), + CUSTOMER_READ(Const.CUSTOMER_READ), + CUSTOMER_WRITE(Const.CUSTOMER_WRITE); + + + private final String scope; + + UserScope(String scope) { + this.scope = scope; + } + + public String toString() { + return this.scope; + } + + public static class Const { + public static final String BANKER_READ = "SCOPE_test_read"; + public static final String BANKER_WRITE = "SCOPE_test_write"; + public static final String CUSTOMER_READ = "SCOPE_test_1"; + public static final String CUSTOMER_WRITE = "SCOPE_test_2"; + } +} \ No newline at end of file diff --git a/user-service/src/main/java/cz/muni/fi/obs/security/exceptions/AccessDeniedException.java b/user-service/src/main/java/cz/muni/fi/obs/security/exceptions/AccessDeniedException.java new file mode 100644 index 0000000..2cae6f3 --- /dev/null +++ b/user-service/src/main/java/cz/muni/fi/obs/security/exceptions/AccessDeniedException.java @@ -0,0 +1,7 @@ +package cz.muni.fi.obs.security.exceptions; + +public class AccessDeniedException extends RuntimeException { + public AccessDeniedException(String message) { + super(message); + } +} diff --git a/user-service/src/main/java/cz/muni/fi/obs/service/UserService.java b/user-service/src/main/java/cz/muni/fi/obs/service/UserService.java index 9f6336b..6fb9fe9 100644 --- a/user-service/src/main/java/cz/muni/fi/obs/service/UserService.java +++ b/user-service/src/main/java/cz/muni/fi/obs/service/UserService.java @@ -5,6 +5,7 @@ import cz.muni.fi.obs.api.UserSearchParamsPaginatedDto; import cz.muni.fi.obs.api.UserUpdateDto; import cz.muni.fi.obs.data.dbo.User; import cz.muni.fi.obs.data.repository.UserRepository; +import cz.muni.fi.obs.security.Security; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; @@ -16,13 +17,17 @@ public class UserService { private final UserRepository userRepository; + private final Security security; + @Autowired - public UserService(UserRepository userRepository) { + public UserService(UserRepository userRepository, Security security) { this.userRepository = userRepository; + this.security = security; } public User createUser(UserCreateDto userCreateDto) { User user = new User( + security.getCurrentUserOauthId(), userCreateDto.firstName(), userCreateDto.lastName(), userCreateDto.phoneNumber(), diff --git a/user-service/src/main/resources/application.yml b/user-service/src/main/resources/application.yml index 58231f6..b08de7f 100644 --- a/user-service/src/main/resources/application.yml +++ b/user-service/src/main/resources/application.yml @@ -20,6 +20,25 @@ spring: hibernate: ddl-auto: validate show-sql: true + security: + oauth2: + resourceserver: + opaque-token: + introspection-uri: https://oidc.muni.cz/oidc/introspect + # Martin Kuba's testing resource server + client-id: d57b3a8f-156e-46de-9f27-39c4daee05e1 + client-secret: fa228ebc-4d54-4cda-901e-4d6287f8b1652a9c9c44-73c9-4502-973f-bcdb4a8ec96a + +springdoc: + swagger-ui: + oauth: + # Martin Kuba's testing client + client-id: 7e02a0a9-446a-412d-ad2b-90add47b0fdd + client-secret: 48a2b2e3-4b2b-471e-b7b7-b81a85b6eeef22f347f2-3fc9-4e16-8698-3e2492701a89 + scopes: + - test_read + - test_write + - test_1 clients: transaction-service: diff --git a/user-service/src/main/resources/db/migration/V0__initialize_database.sql b/user-service/src/main/resources/db/migration/V0__initialize_database.sql index aae645d..9f451d4 100644 --- a/user-service/src/main/resources/db/migration/V0__initialize_database.sql +++ b/user-service/src/main/resources/db/migration/V0__initialize_database.sql @@ -1,6 +1,7 @@ CREATE TABLE us_user ( id uuid primary key, + oauth_id varchar(255) not null unique, first_name varchar(255) not null, last_name varchar(255) not null, phone_number varchar(20) not null unique, diff --git a/user-service/src/test/java/cz/muni/fi/obs/controller/UserControllerTest.java b/user-service/src/test/java/cz/muni/fi/obs/controller/UserControllerTest.java index 944236a..ecafc5f 100644 --- a/user-service/src/test/java/cz/muni/fi/obs/controller/UserControllerTest.java +++ b/user-service/src/test/java/cz/muni/fi/obs/controller/UserControllerTest.java @@ -4,12 +4,15 @@ import cz.muni.fi.obs.api.*; import cz.muni.fi.obs.data.enums.Nationality; import cz.muni.fi.obs.exceptions.UserNotFoundException; import cz.muni.fi.obs.facade.UserManagementFacade; +import cz.muni.fi.obs.security.Security; +import cz.muni.fi.obs.security.enums.UserScope; 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.springframework.http.ResponseEntity; +import org.springframework.security.test.context.support.WithMockUser; import java.time.LocalDate; import java.util.Arrays; @@ -19,8 +22,7 @@ import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class UserControllerTest { @@ -28,9 +30,13 @@ class UserControllerTest { @Mock private UserManagementFacade userManagementFacade; + @Mock + private Security security; @InjectMocks private UserController userController; + @WithMockUser(username = "999888@muni.cz", + authorities = {UserScope.Const.CUSTOMER_READ, UserScope.Const.CUSTOMER_WRITE}) @Test public void createUser_userCreated_returnsUser() { UserCreateDto userCreateDto = new UserCreateDto("Joe", @@ -42,6 +48,7 @@ class UserControllerTest { "900101/1234" ); UserDto userDto = new UserDto(UUID.randomUUID(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -52,16 +59,18 @@ class UserControllerTest { false ); when(userManagementFacade.createUser(userCreateDto)).thenReturn(userDto); - ResponseEntity<UserDto> response = userController.createUser(userCreateDto); verify(userManagementFacade).createUser(userCreateDto); assertThat(response.getBody()).isEqualTo(userDto); } + @WithMockUser(username = "999888@muni.cz", + authorities = {UserScope.Const.CUSTOMER_READ, UserScope.Const.CUSTOMER_WRITE}) @Test public void getUser_userFound_returnsUser() { UserDto userDto = new UserDto(UUID.randomUUID(), + "999888@muni.cz", "Joe", "Doe", "123456789", @@ -71,6 +80,8 @@ class UserControllerTest { "900101/123", false ); + when(security.isUserBanker()).thenReturn(false); + doNothing().when(security).checkUserIsOwner(userDto.oauthId()); when(userManagementFacade.getUser(userDto.id())).thenReturn(userDto); ResponseEntity<UserDto> response = userController.getUser(userDto.id()); @@ -79,6 +90,8 @@ class UserControllerTest { assertThat(response.getBody()).isEqualTo(userDto); } + @WithMockUser(username = "999888@muni.cz", + authorities = {UserScope.Const.CUSTOMER_READ, UserScope.Const.CUSTOMER_WRITE}) @Test public void getUser_userNotFound_returns404() { UUID nonexistentUserId = UUID.randomUUID(); @@ -89,6 +102,8 @@ class UserControllerTest { verify(userManagementFacade).getUser(nonexistentUserId); } + @WithMockUser(username = "553628@muni.cz", + authorities = {UserScope.Const.CUSTOMER_READ, UserScope.Const.CUSTOMER_WRITE}) @Test public void updateUser_userUpdated_returnsUser() { UserUpdateDto userUpdateDto = new UserUpdateDto(Optional.of("Joe"), @@ -97,6 +112,7 @@ class UserControllerTest { Optional.of("test@gmail.com") ); UserDto userDto = new UserDto(UUID.randomUUID(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -106,6 +122,8 @@ class UserControllerTest { "900101/123", false ); + when(security.isUserBanker()).thenReturn(false); + doNothing().when(security).checkUserIsOwner(userDto.oauthId()); when(userManagementFacade.updateUser(userDto.id(), userUpdateDto)).thenReturn(userDto); ResponseEntity<UserDto> response = userController.updateUser(userDto.id(), userUpdateDto); @@ -114,9 +132,12 @@ class UserControllerTest { assertThat(response.getBody()).isEqualTo(userDto); } + @WithMockUser(username = "111111@muni.cz", + authorities = {UserScope.Const.BANKER_WRITE, UserScope.Const.BANKER_READ}) @Test public void deactivateUser_userDeactivated_returnsUser() { UserDto userDto = new UserDto(UUID.randomUUID(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -134,9 +155,12 @@ class UserControllerTest { assertThat(response.getBody()).isEqualTo(userDto); } + @WithMockUser(username = "111111@muni.cz", + authorities = {UserScope.Const.BANKER_WRITE, UserScope.Const.BANKER_READ}) @Test public void activateUser_userActivated_returnsUser() { UserDto userDto = new UserDto(UUID.randomUUID(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -154,11 +178,14 @@ class UserControllerTest { assertThat(response.getBody()).isEqualTo(userDto); } + @WithMockUser(username = "111111@muni.cz", + authorities = {UserScope.Const.BANKER_WRITE, UserScope.Const.BANKER_READ}) @Test public void createUserAccount_accountCreated_returnsAccount() { UUID userId = UUID.randomUUID(); AccountCreateDto accountCreateDto = new AccountCreateDto("1234567890", "Joe's Account"); AccountDto accountDto = new AccountDto(UUID.randomUUID(), "1234567890", "Joe's Account"); + when(security.isUserBanker()).thenReturn(true); when(userManagementFacade.createAccount(userId, accountCreateDto)).thenReturn(accountDto); ResponseEntity<AccountDto> response = userController.createUserAccount(userId, accountCreateDto); @@ -167,12 +194,15 @@ class UserControllerTest { assertThat(response.getBody()).isEqualTo(accountDto); } + @WithMockUser(username = "111111@muni.cz", + authorities = {UserScope.Const.BANKER_WRITE, UserScope.Const.BANKER_READ}) @Test public void getUserAccounts_accountsFound_returnsAccounts() { UUID userId = UUID.randomUUID(); List<AccountDto> accounts = Arrays.asList(new AccountDto(UUID.randomUUID(), "1234567890", "Joe's Account"), new AccountDto(UUID.randomUUID(), "0987654321", "Jane's Account") ); + when(security.isUserBanker()).thenReturn(true); when(userManagementFacade.getUserAccounts(userId)).thenReturn(accounts); ResponseEntity<List<AccountDto>> response = userController.getUserAccounts(userId); diff --git a/user-service/src/test/java/cz/muni/fi/obs/controller/UserControllerWebMvcTest.java b/user-service/src/test/java/cz/muni/fi/obs/controller/UserControllerWebMvcTest.java index e8e3cd4..6acb45f 100644 --- a/user-service/src/test/java/cz/muni/fi/obs/controller/UserControllerWebMvcTest.java +++ b/user-service/src/test/java/cz/muni/fi/obs/controller/UserControllerWebMvcTest.java @@ -48,6 +48,7 @@ public class UserControllerWebMvcTest { "010413/2215" ); UserDto userDto = new UserDto(UUID.randomUUID(), + "553628@muni.cz", userCreateDto.firstName(), userCreateDto.lastName(), userCreateDto.phoneNumber(), @@ -72,6 +73,7 @@ public class UserControllerWebMvcTest { @Test public void getUser_userFound_returnsUser() throws Exception { UserDto userDto = new UserDto(UUID.randomUUID(), + "123456@muni.cz", "Joe", "Doe", "123456789", @@ -118,6 +120,7 @@ public class UserControllerWebMvcTest { userUpdateJson.put("email", "test@gmail.com"); UserDto userDto = new UserDto(UUID.randomUUID(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -144,6 +147,7 @@ public class UserControllerWebMvcTest { @Test public void deactivateUser_userDeactivated_returnsUser() throws Exception { UserDto userDto = new UserDto(UUID.randomUUID(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -169,6 +173,7 @@ public class UserControllerWebMvcTest { @Test public void activateUser_userActivated_returnsUser() throws Exception { UserDto userDto = new UserDto(UUID.randomUUID(), + "553628@muni.cz", "Joe", "Doe", "123456789", diff --git a/user-service/src/test/java/cz/muni/fi/obs/facade/UserManagementFacadeTest.java b/user-service/src/test/java/cz/muni/fi/obs/facade/UserManagementFacadeTest.java index 033a745..276c26a 100644 --- a/user-service/src/test/java/cz/muni/fi/obs/facade/UserManagementFacadeTest.java +++ b/user-service/src/test/java/cz/muni/fi/obs/facade/UserManagementFacadeTest.java @@ -42,7 +42,8 @@ class UserManagementFacadeTest { Nationality.CZ, "900101/1234" ); - User user = new User("Joe", + User user = new User("553628@muni.cz", + "Joe", "Doe", "123456789", "test@gmail.com", @@ -52,6 +53,7 @@ class UserManagementFacadeTest { true ); UserDto userDto = new UserDto(user.getId(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -71,16 +73,19 @@ class UserManagementFacadeTest { @Test public void getUser_userFound_returnsUser() { - User user = new User("Joe", - "Doe", - "123456789", - "test@gmail.com", - LocalDate.now(), - Nationality.CZ, - "900101/123", - true + User user = new User( + "553628@muni.cz", + "Joe", + "Doe", + "123456789", + "test@gmail.com", + LocalDate.now(), + Nationality.CZ, + "900101/123", + true ); UserDto userDto = new UserDto(user.getId(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -105,16 +110,19 @@ class UserManagementFacadeTest { Optional.of("123456789"), Optional.of("test@gmail.com") ); - User user = new User("Joe", - "Doe", - "123456789", - "test@gmail.com", - LocalDate.now(), - Nationality.CZ, - "900101/123", - true + User user = new User( + "553628@muni.cz", + "Joe", + "Doe", + "123456789", + "test@gmail.com", + LocalDate.now(), + Nationality.CZ, + "900101/123", + true ); UserDto userDto = new UserDto(user.getId(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -134,16 +142,19 @@ class UserManagementFacadeTest { @Test public void deactivateUser_userDeactivated_returnsUser() { - User user = new User("Joe", - "Doe", - "123456789", - "test@gmail.com", - LocalDate.now(), - Nationality.CZ, - "900101/123", - true + User user = new User( + "553628@muni.cz", + "Joe", + "Doe", + "123456789", + "test@gmail.com", + LocalDate.now(), + Nationality.CZ, + "900101/123", + true ); UserDto userDto = new UserDto(user.getId(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -163,16 +174,19 @@ class UserManagementFacadeTest { @Test public void activateUser_userActivated_returnsUser() { - User user = new User("Joe", - "Doe", - "123456789", - "test@gmail.com", - LocalDate.now(), - Nationality.CZ, - "900101/123", - true + User user = new User( + "553628@muni.cz", + "Joe", + "Doe", + "123456789", + "test@gmail.com", + LocalDate.now(), + Nationality.CZ, + "900101/123", + true ); UserDto userDto = new UserDto(user.getId(), + "553628@muni.cz", "Joe", "Doe", "123456789", @@ -208,7 +222,6 @@ class UserManagementFacadeTest { List<AccountDto> accounts = Arrays.asList(new AccountDto(UUID.randomUUID(), "1234567890", "CZK"), new AccountDto(UUID.randomUUID(), "0987654321", "EUR") ); - when(userService.getUser(userId)).thenReturn(new User()); when(userAccountService.getUserAccounts(userId)).thenReturn(accounts); List<AccountDto> response = userManagementFacade.getUserAccounts(userId); diff --git a/user-service/src/test/java/cz/muni/fi/obs/service/UserServiceTest.java b/user-service/src/test/java/cz/muni/fi/obs/service/UserServiceTest.java index ee8b819..bbc80a7 100644 --- a/user-service/src/test/java/cz/muni/fi/obs/service/UserServiceTest.java +++ b/user-service/src/test/java/cz/muni/fi/obs/service/UserServiceTest.java @@ -5,6 +5,7 @@ import cz.muni.fi.obs.api.UserUpdateDto; import cz.muni.fi.obs.data.dbo.User; import cz.muni.fi.obs.data.enums.Nationality; import cz.muni.fi.obs.data.repository.UserRepository; +import cz.muni.fi.obs.security.Security; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -23,6 +24,10 @@ class UserServiceTest { @Mock private UserRepository userRepository; + + @Mock + private Security security; + @InjectMocks private UserService userService; @@ -37,7 +42,8 @@ class UserServiceTest { "900101/1234" ); - User user = new User(userCreateDto.firstName(), + User user = new User("553628@muni.cz", + userCreateDto.firstName(), userCreateDto.lastName(), userCreateDto.phoneNumber(), userCreateDto.email(), @@ -46,6 +52,7 @@ class UserServiceTest { userCreateDto.birthNumber(), true ); + when(security.getCurrentUserOauthId()).thenReturn(user.getOauthId()); when(userRepository.save(any(User.class))).thenReturn(user); User response = userService.createUser(userCreateDto); @@ -64,15 +71,18 @@ class UserServiceTest { "900101/1234" ); - User user = new User(userCreateDto.firstName(), - userCreateDto.lastName(), - userCreateDto.phoneNumber(), - userCreateDto.email(), - userCreateDto.birthDate(), - userCreateDto.nationality(), - userCreateDto.birthNumber(), - true + User user = new User( + "553628@muni.cz", + userCreateDto.firstName(), + userCreateDto.lastName(), + userCreateDto.phoneNumber(), + userCreateDto.email(), + userCreateDto.birthDate(), + userCreateDto.nationality(), + userCreateDto.birthNumber(), + true ); + when(security.getCurrentUserOauthId()).thenReturn(user.getOauthId()); when(userRepository.save(any(User.class))).thenReturn(user); User response = userService.createUser(userCreateDto); @@ -82,14 +92,16 @@ class UserServiceTest { @Test void getUser_userFound_returnsUser() { - User user = new User("Joe", - "Doe", - "123456789", - "test@gmail.com", - LocalDate.now(), - Nationality.CZ, - "900101" + "/123", - true + User user = new User( + "553628@muni.cz", + "Joe", + "Doe", + "123456789", + "test@gmail.com", + LocalDate.now(), + Nationality.CZ, + "900101" + "/123", + true ); when(userRepository.findByIdOrThrow(user.getId())).thenReturn(user); @@ -106,7 +118,8 @@ class UserServiceTest { Optional.of("123456789"), Optional.of("test@gmail.com") ); - User user = new User("Joe", + User user = new User("553628@muni.cz", + "Joe", "Doe", "123456789", "test@gmail.com", @@ -126,7 +139,8 @@ class UserServiceTest { @Test void activateUser_userActivated_returnsUser() { - User user = new User("Joe", + User user = new User("553628@muni.cz", + "Joe", "Doe", "123456789", "test@gmail.com", @@ -147,7 +161,8 @@ class UserServiceTest { @Test void activateUser_userDeactivated_returnsUser() { - User user = new User("Joe", + User user = new User("553628@muni.cz", + "Joe", "Doe", "123456789", "test@gmail.com", @@ -168,7 +183,8 @@ class UserServiceTest { @Test void deactivateUser_userActivated_returnsUser() { - User user = new User("Joe", + User user = new User("553628@muni.cz", + "Joe", "Doe", "123456789", "test@gmail.com", @@ -189,7 +205,8 @@ class UserServiceTest { @Test void deactivateUser_userDeactivated_returnsUser() { - User user = new User("Joe", + User user = new User("553628@muni.cz", + "Joe", "Doe", "123456789", "test@gmail.com", diff --git a/user-service/src/test/resources/seed_db.sql b/user-service/src/test/resources/seed_db.sql index 6178244..85ecb48 100644 --- a/user-service/src/test/resources/seed_db.sql +++ b/user-service/src/test/resources/seed_db.sql @@ -1,10 +1,15 @@ -INSERT INTO us_user(id, first_name, last_name, phone_number, email, birth_date, nationality, birth_number, active) -VALUES ('5e4b3326-38b5-4484-8034-33d81f34bec2', 'John', 'Doe', '9707178239', 'example1@domain.com', '1990-01-01', 'CZ', +INSERT INTO us_user(id, oauth_id, first_name, last_name, phone_number, email, birth_date, nationality, birth_number, + active) +VALUES ('5e4b3326-38b5-4484-8034-33d81f34bec2', '111112@muni.cz', 'John', 'Doe', '9707178239', 'example1@domain.com', + '1990-01-01', 'CZ', '900101/1234', true), - ('5e4b3326-38b5-4484-8034-33d81f34bec3', 'Jane', 'Doe', '9707178238', 'example2@domain.com', '1991-02-02', 'SK', + ('5e4b3326-38b5-4484-8034-33d81f34bec3', '111113@muni.cz', 'Jane', 'Doe', '9707178238', 'example2@domain.com', + '1991-02-02', 'SK', '931028/4632', true), - ('5e4b3326-38b5-4484-8034-33d81f34bec4', 'Pete', 'Hel', '9707178237', 'example3@domain.com', '1992-03-03', 'CZ', + ('5e4b3326-38b5-4484-8034-33d81f34bec4', '111114@muni.cz', 'Pete', 'Hel', '9707178237', 'example3@domain.com', + '1992-03-03', 'CZ', '761110/2983', false), - ('5e4b3326-38b5-4484-8034-33d81f34bec5', 'John', 'Doe', '9707178236', 'example4@domain.com', '1993-04-04', 'SK', + ('5e4b3326-38b5-4484-8034-33d81f34bec5', '111115@muni.cz', 'John', 'Doe', '9707178236', 'example4@domain.com', + '1993-04-04', 'SK', '580516/1472', false); -- GitLab