diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/Constants.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/Constants.kt index d7853b7..73fe84c 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/Constants.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/Constants.kt @@ -3,15 +3,16 @@ package dev.fyloz.colorrecipesexplorer object Constants { object ControllerPaths { const val COMPANY = "/api/company" + const val GROUP_TOKEN = "/api/account/group/token" const val FILE = "/api/file" - const val GROUP = "/api/user/group" + const val GROUP = "/api/account/group" const val INVENTORY = "/api/inventory" const val MATERIAL = "/api/material" const val MATERIAL_TYPE = "/api/materialtype" const val MIX = "/api/recipe/mix" const val RECIPE = "/api/recipe" const val TOUCH_UP_KIT = "/api/touchupkit" - const val USER = "/api/user" + const val USER = "/api/account/user" } object FilePaths { @@ -25,6 +26,7 @@ object Constants { object ModelNames { const val COMPANY = "Company" + const val GROUP_TOKEN = "GroupToken" const val GROUP = "Group" const val MATERIAL = "Material" const val MATERIAL_TYPE = "MaterialType" @@ -47,4 +49,4 @@ object Constants { object ValidationRegexes { const val VALIDATION_COLOR_PATTERN = "^#([0-9a-f]{6})$" } -} \ No newline at end of file +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/annotations/PermissionAnnotations.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/annotations/PermissionAnnotations.kt index 8f78572..71fdd01 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/annotations/PermissionAnnotations.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/annotations/PermissionAnnotations.kt @@ -2,6 +2,12 @@ package dev.fyloz.colorrecipesexplorer.config.annotations import org.springframework.security.access.prepost.PreAuthorize +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +@MustBeDocumented +@PreAuthorize("hasAuthority('ADMIN')") +annotation class PreAuthorizeAdmin + @Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) @Retention(AnnotationRetention.RUNTIME) @MustBeDocumented diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/security/JwtFilters.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/security/JwtFilters.kt index 47f997f..b7b5f48 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/security/JwtFilters.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/security/JwtFilters.kt @@ -2,12 +2,12 @@ package dev.fyloz.colorrecipesexplorer.config.security import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import dev.fyloz.colorrecipesexplorer.config.properties.CreSecurityProperties -import dev.fyloz.colorrecipesexplorer.dtos.UserDetails -import dev.fyloz.colorrecipesexplorer.dtos.UserDto -import dev.fyloz.colorrecipesexplorer.dtos.UserLoginRequestDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDetails +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserLoginRequestDto import dev.fyloz.colorrecipesexplorer.exception.NotFoundException -import dev.fyloz.colorrecipesexplorer.logic.users.JwtLogic -import dev.fyloz.colorrecipesexplorer.logic.users.UserDetailsLogic +import dev.fyloz.colorrecipesexplorer.logic.account.JwtLogic +import dev.fyloz.colorrecipesexplorer.logic.account.UserDetailsLogic import dev.fyloz.colorrecipesexplorer.utils.addCookie import io.jsonwebtoken.ExpiredJwtException import org.springframework.security.authentication.AuthenticationManager diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/security/SecurityConfig.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/security/SecurityConfig.kt index c17ee93..188e57b 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/security/SecurityConfig.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/config/security/SecurityConfig.kt @@ -1,11 +1,11 @@ package dev.fyloz.colorrecipesexplorer.config.security import dev.fyloz.colorrecipesexplorer.config.properties.CreSecurityProperties -import dev.fyloz.colorrecipesexplorer.dtos.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto import dev.fyloz.colorrecipesexplorer.emergencyMode -import dev.fyloz.colorrecipesexplorer.logic.users.JwtLogic -import dev.fyloz.colorrecipesexplorer.logic.users.UserDetailsLogic -import dev.fyloz.colorrecipesexplorer.logic.users.UserLogic +import dev.fyloz.colorrecipesexplorer.logic.account.JwtLogic +import dev.fyloz.colorrecipesexplorer.logic.account.UserDetailsLogic +import dev.fyloz.colorrecipesexplorer.logic.account.UserLogic import dev.fyloz.colorrecipesexplorer.model.account.Permission import mu.KotlinLogging import org.slf4j.Logger diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/RecipeDto.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/RecipeDto.kt index 0a76be4..5a9d8d4 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/RecipeDto.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/RecipeDto.kt @@ -2,6 +2,7 @@ package dev.fyloz.colorrecipesexplorer.dtos import com.fasterxml.jackson.annotation.JsonIgnore import dev.fyloz.colorrecipesexplorer.Constants +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto import java.time.LocalDate import javax.validation.constraints.Max import javax.validation.constraints.Min @@ -118,4 +119,4 @@ data class RecipePublicDataDto( val notes: List, val mixesLocation: List -) \ No newline at end of file +) diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/GroupDto.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/GroupDto.kt similarity index 85% rename from src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/GroupDto.kt rename to src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/GroupDto.kt index 78ab227..8e5a61c 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/GroupDto.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/GroupDto.kt @@ -1,6 +1,7 @@ -package dev.fyloz.colorrecipesexplorer.dtos +package dev.fyloz.colorrecipesexplorer.dtos.account import com.fasterxml.jackson.annotation.JsonIgnore +import dev.fyloz.colorrecipesexplorer.dtos.EntityDto import dev.fyloz.colorrecipesexplorer.model.account.Permission import javax.validation.constraints.NotBlank import javax.validation.constraints.NotEmpty diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/GroupTokenDto.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/GroupTokenDto.kt new file mode 100644 index 0000000..8708ed2 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/GroupTokenDto.kt @@ -0,0 +1,21 @@ +package dev.fyloz.colorrecipesexplorer.dtos.account + +import java.util.UUID +import javax.validation.constraints.NotBlank + +data class GroupTokenDto( + val id: UUID, + + val name: String, + + val isValid: Boolean, + + val group: GroupDto +) + +data class GroupTokenSaveDto( + @field:NotBlank + val name: String, + + val groupId: Long +) diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/UserDto.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/UserDto.kt similarity index 93% rename from src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/UserDto.kt rename to src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/UserDto.kt index edfaef4..32f2a5f 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/UserDto.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/UserDto.kt @@ -1,8 +1,9 @@ -package dev.fyloz.colorrecipesexplorer.dtos +package dev.fyloz.colorrecipesexplorer.dtos.account import com.fasterxml.jackson.annotation.JsonIgnore import dev.fyloz.colorrecipesexplorer.Constants import dev.fyloz.colorrecipesexplorer.SpringUserDetails +import dev.fyloz.colorrecipesexplorer.dtos.EntityDto import dev.fyloz.colorrecipesexplorer.model.account.Permission import dev.fyloz.colorrecipesexplorer.model.account.toAuthority import java.time.LocalDateTime @@ -57,8 +58,6 @@ data class UserSaveDto( val permissions: List, - // TODO WN: Test if working - // @JsonProperty(access = JsonProperty.Access.READ_ONLY) @field:JsonIgnore val isSystemUser: Boolean = false, @@ -91,4 +90,4 @@ class UserDetails(val user: UserDto) : SpringUserDetails { override fun isAccountNonLocked() = true override fun isCredentialsNonExpired() = true override fun isEnabled() = true -} \ No newline at end of file +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/RecipeLogic.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/RecipeLogic.kt index 2687249..e444250 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/RecipeLogic.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/RecipeLogic.kt @@ -5,7 +5,7 @@ import dev.fyloz.colorrecipesexplorer.config.annotations.LogicComponent import dev.fyloz.colorrecipesexplorer.dtos.* import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException import dev.fyloz.colorrecipesexplorer.logic.files.WriteableFileLogic -import dev.fyloz.colorrecipesexplorer.logic.users.GroupLogic +import dev.fyloz.colorrecipesexplorer.logic.account.GroupLogic import dev.fyloz.colorrecipesexplorer.service.RecipeService import dev.fyloz.colorrecipesexplorer.utils.collections.LazyMapList import dev.fyloz.colorrecipesexplorer.utils.merge diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/RecipeStepLogic.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/RecipeStepLogic.kt index 4aaf79f..eb24212 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/RecipeStepLogic.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/RecipeStepLogic.kt @@ -2,13 +2,12 @@ package dev.fyloz.colorrecipesexplorer.logic import dev.fyloz.colorrecipesexplorer.Constants import dev.fyloz.colorrecipesexplorer.config.annotations.LogicComponent -import dev.fyloz.colorrecipesexplorer.dtos.GroupDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto import dev.fyloz.colorrecipesexplorer.dtos.RecipeGroupInformationDto import dev.fyloz.colorrecipesexplorer.dtos.RecipeStepDto import dev.fyloz.colorrecipesexplorer.exception.InvalidPositionError import dev.fyloz.colorrecipesexplorer.exception.InvalidPositionsException import dev.fyloz.colorrecipesexplorer.exception.RestException -import dev.fyloz.colorrecipesexplorer.model.account.Group import dev.fyloz.colorrecipesexplorer.service.RecipeStepService import dev.fyloz.colorrecipesexplorer.utils.PositionUtils import org.springframework.http.HttpStatus @@ -46,4 +45,4 @@ class InvalidGroupStepsPositionsException( ) { val errors: Set get() = exception.errors -} \ No newline at end of file +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/GroupLogic.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupLogic.kt similarity index 92% rename from src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/GroupLogic.kt rename to src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupLogic.kt index b421223..1a734df 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/GroupLogic.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupLogic.kt @@ -1,14 +1,14 @@ -package dev.fyloz.colorrecipesexplorer.logic.users +package dev.fyloz.colorrecipesexplorer.logic.account import dev.fyloz.colorrecipesexplorer.Constants import dev.fyloz.colorrecipesexplorer.config.annotations.LogicComponent import dev.fyloz.colorrecipesexplorer.config.security.defaultGroupCookieName -import dev.fyloz.colorrecipesexplorer.dtos.GroupDto -import dev.fyloz.colorrecipesexplorer.dtos.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto import dev.fyloz.colorrecipesexplorer.exception.NoDefaultGroupException import dev.fyloz.colorrecipesexplorer.logic.BaseLogic import dev.fyloz.colorrecipesexplorer.logic.Logic -import dev.fyloz.colorrecipesexplorer.service.GroupService +import dev.fyloz.colorrecipesexplorer.service.account.GroupService import org.springframework.transaction.annotation.Transactional import org.springframework.web.util.WebUtils import javax.servlet.http.HttpServletRequest @@ -77,4 +77,4 @@ class DefaultGroupLogic(service: GroupService, private val userLogic: UserLogic) throw alreadyExistsException(value = name) } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupTokenLogic.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupTokenLogic.kt new file mode 100644 index 0000000..12211ca --- /dev/null +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupTokenLogic.kt @@ -0,0 +1,85 @@ +package dev.fyloz.colorrecipesexplorer.logic.account + +import dev.fyloz.colorrecipesexplorer.Constants +import dev.fyloz.colorrecipesexplorer.config.annotations.LogicComponent +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupTokenDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupTokenSaveDto +import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException +import dev.fyloz.colorrecipesexplorer.exception.NotFoundException +import dev.fyloz.colorrecipesexplorer.logic.BaseLogic +import dev.fyloz.colorrecipesexplorer.service.account.GroupTokenService +import java.util.UUID + +interface GroupTokenLogic { + fun getAll(): Collection + fun getById(id: String): GroupTokenDto + fun save(dto: GroupTokenSaveDto): GroupTokenDto + fun deleteById(id: String) +} + +@LogicComponent +class DefaultGroupTokenLogic(private val service: GroupTokenService, private val groupLogic: GroupLogic) : + GroupTokenLogic { + private val typeName = Constants.ModelNames.GROUP_TOKEN + private val typeNameLowerCase = typeName.lowercase() + + override fun getAll() = service.getAll() + + override fun getById(id: String) = + service.getById(UUID.fromString(id)) ?: throw notFoundException(value = id) + + override fun save(dto: GroupTokenSaveDto): GroupTokenDto { + throwIfNameAlreadyExists(dto.name) + + val token = GroupTokenDto( + generateUniqueUUIDForName(dto.name), + dto.name, + true, + groupLogic.getById(dto.groupId) + ) + + return service.save(token) + } + + override fun deleteById(id: String) { + service.deleteById(UUID.fromString(id)) + } + + private fun generateUniqueUUIDForName(name: String): UUID { + var id = generateUUIDForName(name) + + // UUIDs do not guarantee that collisions can't happen + while (service.existsById(id)) { + id = generateUUIDForName(name) + } + + return id + } + + private fun generateUUIDForName(name: String) = + UUID.nameUUIDFromBytes(name.toByteArray()) + + private fun throwIfNameAlreadyExists(name: String) { + if (service.existsByName(name)) { + throw alreadyExistsException(value = name) + } + } + + private fun notFoundException(identifierName: String = BaseLogic.ID_IDENTIFIER_NAME, value: Any) = + NotFoundException( + typeNameLowerCase, + "$typeName not found", + "A $typeNameLowerCase with the $identifierName '$value' could not be found", + value, + identifierName + ) + + private fun alreadyExistsException(identifierName: String = BaseLogic.NAME_IDENTIFIER_NAME, value: Any) = + AlreadyExistsException( + typeNameLowerCase, + "$typeName already exists", + "A $typeNameLowerCase with the $identifierName '$value' already exists", + value, + identifierName + ) +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/JwtLogic.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/JwtLogic.kt similarity index 92% rename from src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/JwtLogic.kt rename to src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/JwtLogic.kt index 47469bf..3efbf51 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/JwtLogic.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/JwtLogic.kt @@ -1,10 +1,10 @@ -package dev.fyloz.colorrecipesexplorer.logic.users +package dev.fyloz.colorrecipesexplorer.logic.account import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import dev.fyloz.colorrecipesexplorer.config.properties.CreSecurityProperties -import dev.fyloz.colorrecipesexplorer.dtos.UserDetails -import dev.fyloz.colorrecipesexplorer.dtos.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDetails +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto import dev.fyloz.colorrecipesexplorer.utils.base64encode import dev.fyloz.colorrecipesexplorer.utils.toDate import io.jsonwebtoken.Jwts diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/UserDetailsLogic.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/UserDetailsLogic.kt similarity index 93% rename from src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/UserDetailsLogic.kt rename to src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/UserDetailsLogic.kt index 25b8369..8a621ab 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/UserDetailsLogic.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/UserDetailsLogic.kt @@ -1,11 +1,11 @@ -package dev.fyloz.colorrecipesexplorer.logic.users +package dev.fyloz.colorrecipesexplorer.logic.account import dev.fyloz.colorrecipesexplorer.SpringUserDetails import dev.fyloz.colorrecipesexplorer.SpringUserDetailsService import dev.fyloz.colorrecipesexplorer.config.annotations.RequireDatabase import dev.fyloz.colorrecipesexplorer.config.properties.CreSecurityProperties -import dev.fyloz.colorrecipesexplorer.dtos.UserDetails -import dev.fyloz.colorrecipesexplorer.dtos.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDetails +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto import dev.fyloz.colorrecipesexplorer.exception.NotFoundException import dev.fyloz.colorrecipesexplorer.model.account.Permission import dev.fyloz.colorrecipesexplorer.model.account.User diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/UserLogic.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/UserLogic.kt similarity index 94% rename from src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/UserLogic.kt rename to src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/UserLogic.kt index bd17f04..49d3f5d 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/users/UserLogic.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/UserLogic.kt @@ -1,20 +1,19 @@ -package dev.fyloz.colorrecipesexplorer.logic.users +package dev.fyloz.colorrecipesexplorer.logic.account import dev.fyloz.colorrecipesexplorer.Constants import dev.fyloz.colorrecipesexplorer.config.annotations.LogicComponent import dev.fyloz.colorrecipesexplorer.config.security.authorizationCookieName import dev.fyloz.colorrecipesexplorer.config.security.blacklistedJwtTokens -import dev.fyloz.colorrecipesexplorer.dtos.GroupDto -import dev.fyloz.colorrecipesexplorer.dtos.UserDto -import dev.fyloz.colorrecipesexplorer.dtos.UserSaveDto -import dev.fyloz.colorrecipesexplorer.dtos.UserUpdateDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserSaveDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserUpdateDto import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException import dev.fyloz.colorrecipesexplorer.logic.BaseLogic import dev.fyloz.colorrecipesexplorer.logic.Logic import dev.fyloz.colorrecipesexplorer.model.account.Permission -import dev.fyloz.colorrecipesexplorer.service.UserService +import dev.fyloz.colorrecipesexplorer.service.account.UserService import org.springframework.context.annotation.Lazy -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.web.util.WebUtils import java.time.LocalDateTime @@ -166,4 +165,4 @@ class DefaultUserLogic( ) } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/model/account/GroupToken.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/model/account/GroupToken.kt new file mode 100644 index 0000000..0820672 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/model/account/GroupToken.kt @@ -0,0 +1,26 @@ +package dev.fyloz.colorrecipesexplorer.model.account + +import java.util.UUID +import javax.persistence.Column +import javax.persistence.Entity +import javax.persistence.Id +import javax.persistence.JoinColumn +import javax.persistence.ManyToOne +import javax.persistence.Table + +@Entity +@Table(name = "group_token") +data class GroupToken( + @Id + val id: UUID, + + @Column(unique = true) + val name: String, + + @Column(name = "is_valid") + val isValid: Boolean, + + @ManyToOne + @JoinColumn(name = "group_id") + val group: Group +) diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/repository/AccountRepository.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/repository/AccountRepository.kt index 82575bd..31e8d9f 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/repository/AccountRepository.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/repository/AccountRepository.kt @@ -1,10 +1,12 @@ package dev.fyloz.colorrecipesexplorer.repository +import dev.fyloz.colorrecipesexplorer.model.account.GroupToken import dev.fyloz.colorrecipesexplorer.model.account.Group import dev.fyloz.colorrecipesexplorer.model.account.User import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.Query import org.springframework.stereotype.Repository +import java.util.UUID @Repository interface UserRepository : JpaRepository { @@ -28,3 +30,9 @@ interface GroupRepository : JpaRepository { /** Checks if a group with the given [name] and a different [id] exists. */ fun existsByNameAndIdNot(name: String, id: Long): Boolean } + +@Repository +interface GroupTokenRepository : JpaRepository { + /** Checks if a token with the given [name] exists. */ + fun existsByName(name: String): Boolean +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/account/GroupController.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/account/GroupController.kt new file mode 100644 index 0000000..ac3971c --- /dev/null +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/account/GroupController.kt @@ -0,0 +1,82 @@ +package dev.fyloz.colorrecipesexplorer.rest.account + +import dev.fyloz.colorrecipesexplorer.Constants +import dev.fyloz.colorrecipesexplorer.config.annotations.PreAuthorizeEditUsers +import dev.fyloz.colorrecipesexplorer.config.annotations.PreAuthorizeViewUsers +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto +import dev.fyloz.colorrecipesexplorer.logic.account.GroupLogic +import dev.fyloz.colorrecipesexplorer.logic.account.UserLogic +import dev.fyloz.colorrecipesexplorer.rest.created +import dev.fyloz.colorrecipesexplorer.rest.noContent +import dev.fyloz.colorrecipesexplorer.rest.ok +import org.springframework.context.annotation.Profile +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.* +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse +import javax.validation.Valid + + +@RestController +@RequestMapping(Constants.ControllerPaths.GROUP) +@Profile("!emergency") +class GroupController( + private val groupLogic: GroupLogic, + private val userLogic: UserLogic +) { + @GetMapping + @PreAuthorize("hasAnyAuthority('VIEW_RECIPES', 'VIEW_USERS')") + fun getAll() = + ok(groupLogic.getAll()) + + @GetMapping("{id}") + @PreAuthorizeViewUsers + fun getById(@PathVariable id: Long) = + ok(groupLogic.getById(id)) + + @GetMapping("{id}/users") + @PreAuthorizeViewUsers + fun getUsersForGroup(@PathVariable id: Long) = + ok(groupLogic.getUsersForGroup(id)) + + @PostMapping("default/{groupId}") + @PreAuthorizeViewUsers + fun setDefaultGroup(@PathVariable groupId: Long, response: HttpServletResponse) = + noContent { + groupLogic.setResponseDefaultGroup(groupId, response) + } + + @GetMapping("default") + @PreAuthorizeViewUsers + fun getRequestDefaultGroup(request: HttpServletRequest) = + ok(with(groupLogic) { + getRequestDefaultGroup(request) + }) + + @GetMapping("currentuser") + fun getCurrentGroupUser(request: HttpServletRequest) = + ok(with(groupLogic.getRequestDefaultGroup(request)) { + userLogic.getDefaultGroupUser(this) + }) + + @PostMapping + @PreAuthorizeEditUsers + fun save(@Valid @RequestBody group: GroupDto) = + created(Constants.ControllerPaths.GROUP) { + groupLogic.save(group) + } + + @PutMapping + @PreAuthorizeEditUsers + fun update(@Valid @RequestBody group: GroupDto) = + noContent { + groupLogic.update(group) + } + + @DeleteMapping("{id}") + @PreAuthorizeEditUsers + fun deleteById(@PathVariable id: Long) = + noContent { + groupLogic.deleteById(id) + } +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/account/GroupTokenController.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/account/GroupTokenController.kt new file mode 100644 index 0000000..e2b24aa --- /dev/null +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/account/GroupTokenController.kt @@ -0,0 +1,40 @@ +package dev.fyloz.colorrecipesexplorer.rest.account + +import dev.fyloz.colorrecipesexplorer.Constants +import dev.fyloz.colorrecipesexplorer.config.annotations.PreAuthorizeAdmin +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupTokenSaveDto +import dev.fyloz.colorrecipesexplorer.logic.account.GroupTokenLogic +import dev.fyloz.colorrecipesexplorer.rest.created +import dev.fyloz.colorrecipesexplorer.rest.noContent +import dev.fyloz.colorrecipesexplorer.rest.ok +import org.springframework.context.annotation.Profile +import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController +import javax.validation.Valid + +@RestController +@RequestMapping(Constants.ControllerPaths.GROUP_TOKEN) +@PreAuthorizeAdmin +@Profile("!emergency") +class GroupTokenController(private val groupTokenLogic: GroupTokenLogic) { + @GetMapping + fun getAll() = ok(groupTokenLogic.getAll()) + + @GetMapping("{id}") + fun getById(@PathVariable id: String) = ok(groupTokenLogic.getById(id)) + + @PostMapping + fun save(@RequestBody @Valid dto: GroupTokenSaveDto) = with(groupTokenLogic.save(dto)) { + created(Constants.ControllerPaths.GROUP_TOKEN, this, this.id) + } + + @DeleteMapping("{id}") + fun deleteById(@PathVariable id: String) = noContent { + groupTokenLogic.deleteById(id) + } +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/AccountControllers.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/account/UserController.kt similarity index 53% rename from src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/AccountControllers.kt rename to src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/account/UserController.kt index dd423b4..d611e82 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/AccountControllers.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/rest/account/UserController.kt @@ -1,21 +1,21 @@ -package dev.fyloz.colorrecipesexplorer.rest +package dev.fyloz.colorrecipesexplorer.rest.account import dev.fyloz.colorrecipesexplorer.Constants import dev.fyloz.colorrecipesexplorer.config.annotations.PreAuthorizeEditUsers import dev.fyloz.colorrecipesexplorer.config.annotations.PreAuthorizeViewUsers -import dev.fyloz.colorrecipesexplorer.dtos.GroupDto -import dev.fyloz.colorrecipesexplorer.dtos.UserDto -import dev.fyloz.colorrecipesexplorer.dtos.UserSaveDto -import dev.fyloz.colorrecipesexplorer.dtos.UserUpdateDto -import dev.fyloz.colorrecipesexplorer.logic.users.GroupLogic -import dev.fyloz.colorrecipesexplorer.logic.users.UserLogic +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserSaveDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserUpdateDto +import dev.fyloz.colorrecipesexplorer.logic.account.UserLogic import dev.fyloz.colorrecipesexplorer.model.account.Permission +import dev.fyloz.colorrecipesexplorer.rest.created +import dev.fyloz.colorrecipesexplorer.rest.noContent +import dev.fyloz.colorrecipesexplorer.rest.ok import org.springframework.context.annotation.Profile import org.springframework.http.MediaType import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.* import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse import javax.validation.Valid @RestController @@ -77,70 +77,6 @@ class UserController(private val userLogic: UserLogic) { userLogic.deleteById(id) } -@RestController -@RequestMapping(Constants.ControllerPaths.GROUP) -@Profile("!emergency") -class GroupsController( - private val groupLogic: GroupLogic, - private val userLogic: UserLogic -) { - @GetMapping - @PreAuthorize("hasAnyAuthority('VIEW_RECIPES', 'VIEW_USERS')") - fun getAll() = - ok(groupLogic.getAll()) - - @GetMapping("{id}") - @PreAuthorizeViewUsers - fun getById(@PathVariable id: Long) = - ok(groupLogic.getById(id)) - - @GetMapping("{id}/users") - @PreAuthorizeViewUsers - fun getUsersForGroup(@PathVariable id: Long) = - ok(groupLogic.getUsersForGroup(id)) - - @PostMapping("default/{groupId}") - @PreAuthorizeViewUsers - fun setDefaultGroup(@PathVariable groupId: Long, response: HttpServletResponse) = - noContent { - groupLogic.setResponseDefaultGroup(groupId, response) - } - - @GetMapping("default") - @PreAuthorizeViewUsers - fun getRequestDefaultGroup(request: HttpServletRequest) = - ok(with(groupLogic) { - getRequestDefaultGroup(request) - }) - - @GetMapping("currentuser") - fun getCurrentGroupUser(request: HttpServletRequest) = - ok(with(groupLogic.getRequestDefaultGroup(request)) { - userLogic.getDefaultGroupUser(this) - }) - - @PostMapping - @PreAuthorizeEditUsers - fun save(@Valid @RequestBody group: GroupDto) = - created(Constants.ControllerPaths.GROUP) { - groupLogic.save(group) - } - - @PutMapping - @PreAuthorizeEditUsers - fun update(@Valid @RequestBody group: GroupDto) = - noContent { - groupLogic.update(group) - } - - @DeleteMapping("{id}") - @PreAuthorizeEditUsers - fun deleteById(@PathVariable id: Long) = - noContent { - groupLogic.deleteById(id) - } -} - @RestController @RequestMapping("api") @Profile("!emergency") diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/RecipeService.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/RecipeService.kt index 8532a02..e0edbf0 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/RecipeService.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/RecipeService.kt @@ -8,6 +8,7 @@ import dev.fyloz.colorrecipesexplorer.model.ConfigurationType import dev.fyloz.colorrecipesexplorer.model.Recipe import dev.fyloz.colorrecipesexplorer.model.RecipeGroupInformation import dev.fyloz.colorrecipesexplorer.repository.RecipeRepository +import dev.fyloz.colorrecipesexplorer.service.account.GroupService import dev.fyloz.colorrecipesexplorer.utils.collections.lazyMap import org.springframework.transaction.annotation.Transactional import java.time.LocalDate @@ -89,4 +90,4 @@ class DefaultRecipeService( with(Period.parse(configLogic.getContent(ConfigurationType.RECIPE_APPROBATION_EXPIRATION))) { recipe.approbationDate?.plus(this)?.isBefore(LocalDate.now()) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/GroupService.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/GroupService.kt similarity index 84% rename from src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/GroupService.kt rename to src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/GroupService.kt index 1b13ced..5772c5f 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/GroupService.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/GroupService.kt @@ -1,11 +1,13 @@ -package dev.fyloz.colorrecipesexplorer.service +package dev.fyloz.colorrecipesexplorer.service.account import dev.fyloz.colorrecipesexplorer.config.annotations.ServiceComponent -import dev.fyloz.colorrecipesexplorer.dtos.GroupDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto import dev.fyloz.colorrecipesexplorer.model.account.Group import dev.fyloz.colorrecipesexplorer.model.account.Permission import dev.fyloz.colorrecipesexplorer.model.account.flat import dev.fyloz.colorrecipesexplorer.repository.GroupRepository +import dev.fyloz.colorrecipesexplorer.service.BaseService +import dev.fyloz.colorrecipesexplorer.service.Service interface GroupService : Service { /** Checks if a group with the given [name] and a different [id] exists. */ @@ -28,4 +30,4 @@ class DefaultGroupService(repository: GroupRepository) : BaseService + fun getById(id: UUID): GroupTokenDto? + fun save(token: GroupTokenDto): GroupTokenDto + fun deleteById(id: UUID) + + fun toDto(entity: GroupToken): GroupTokenDto + fun toEntity(dto: GroupTokenDto): GroupToken +} + +@ServiceComponent +class DefaultGroupTokenService(private val repository: GroupTokenRepository, private val groupService: GroupService) : + GroupTokenService { + override fun existsById(id: UUID) = repository.existsById(id) + override fun existsByName(name: String) = repository.existsByName(name) + + override fun getAll() = repository.findAll().map(::toDto) + + override fun getById(id: UUID): GroupTokenDto? { + val entity = repository.findByIdOrNull(id) + + return if (entity != null) toDto(entity) else null + } + + override fun save(token: GroupTokenDto): GroupTokenDto { + val entity = repository.save(toEntity(token)) + return toDto(entity) + } + + override fun deleteById(id: UUID) = repository.deleteById(id) + + override fun toDto(entity: GroupToken) = + GroupTokenDto(entity.id, entity.name, entity.isValid, groupService.toDto(entity.group)) + + override fun toEntity(dto: GroupTokenDto) = + GroupToken(dto.id, dto.name, dto.isValid, groupService.toEntity(dto.group)) +} diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/UserService.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/UserService.kt similarity index 93% rename from src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/UserService.kt rename to src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/UserService.kt index 4792397..d942ab7 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/UserService.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/UserService.kt @@ -1,12 +1,14 @@ -package dev.fyloz.colorrecipesexplorer.service +package dev.fyloz.colorrecipesexplorer.service.account import dev.fyloz.colorrecipesexplorer.config.annotations.ServiceComponent -import dev.fyloz.colorrecipesexplorer.dtos.GroupDto -import dev.fyloz.colorrecipesexplorer.dtos.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto import dev.fyloz.colorrecipesexplorer.model.account.Permission import dev.fyloz.colorrecipesexplorer.model.account.User import dev.fyloz.colorrecipesexplorer.model.account.flat import dev.fyloz.colorrecipesexplorer.repository.UserRepository +import dev.fyloz.colorrecipesexplorer.service.BaseService +import dev.fyloz.colorrecipesexplorer.service.Service import org.springframework.data.repository.findByIdOrNull interface UserService : Service { @@ -100,4 +102,4 @@ class DefaultUserService(repository: UserRepository, private val groupService: G return perms } -} \ No newline at end of file +} diff --git a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultJwtLogicTest.kt b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultJwtLogicTest.kt index e5ddab7..1e91082 100644 --- a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultJwtLogicTest.kt +++ b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultJwtLogicTest.kt @@ -3,10 +3,10 @@ package dev.fyloz.colorrecipesexplorer.logic import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import dev.fyloz.colorrecipesexplorer.config.properties.CreSecurityProperties -import dev.fyloz.colorrecipesexplorer.dtos.UserDetails -import dev.fyloz.colorrecipesexplorer.dtos.UserDto -import dev.fyloz.colorrecipesexplorer.logic.users.DefaultJwtLogic -import dev.fyloz.colorrecipesexplorer.logic.users.jwtClaimUser +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDetails +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto +import dev.fyloz.colorrecipesexplorer.logic.account.DefaultJwtLogic +import dev.fyloz.colorrecipesexplorer.logic.account.jwtClaimUser import dev.fyloz.colorrecipesexplorer.utils.base64encode import dev.fyloz.colorrecipesexplorer.utils.isAround import io.jsonwebtoken.Jwts diff --git a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultRecipeLogicTest.kt b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultRecipeLogicTest.kt index 101da52..47f5ee1 100644 --- a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultRecipeLogicTest.kt +++ b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultRecipeLogicTest.kt @@ -2,7 +2,7 @@ package dev.fyloz.colorrecipesexplorer.logic import dev.fyloz.colorrecipesexplorer.dtos.* import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException -import dev.fyloz.colorrecipesexplorer.logic.users.GroupLogic +import dev.fyloz.colorrecipesexplorer.logic.account.GroupLogic import dev.fyloz.colorrecipesexplorer.service.RecipeService import io.mockk.* import org.junit.jupiter.api.AfterEach @@ -213,4 +213,4 @@ class DefaultRecipeLogicTest { mixLogicMock.updateLocations(any()) } } -} \ No newline at end of file +} diff --git a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultRecipeStepLogicTest.kt b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultRecipeStepLogicTest.kt index 23aac43..ba93fe6 100644 --- a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultRecipeStepLogicTest.kt +++ b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultRecipeStepLogicTest.kt @@ -1,6 +1,6 @@ package dev.fyloz.colorrecipesexplorer.logic -import dev.fyloz.colorrecipesexplorer.dtos.GroupDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto import dev.fyloz.colorrecipesexplorer.dtos.RecipeGroupInformationDto import dev.fyloz.colorrecipesexplorer.dtos.RecipeStepDto import dev.fyloz.colorrecipesexplorer.exception.InvalidPositionError @@ -57,4 +57,4 @@ class DefaultRecipeStepLogicTest { // Assert assertThrows { recipeStepLogic.validateGroupInformationSteps(groupInfo) } } -} \ No newline at end of file +} diff --git a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupLogicTest.kt b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupLogicTest.kt index 1f208b1..fa5d8bf 100644 --- a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupLogicTest.kt +++ b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupLogicTest.kt @@ -1,11 +1,9 @@ package dev.fyloz.colorrecipesexplorer.logic.account -import dev.fyloz.colorrecipesexplorer.dtos.GroupDto -import dev.fyloz.colorrecipesexplorer.dtos.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException -import dev.fyloz.colorrecipesexplorer.logic.users.DefaultGroupLogic -import dev.fyloz.colorrecipesexplorer.logic.users.UserLogic -import dev.fyloz.colorrecipesexplorer.service.GroupService +import dev.fyloz.colorrecipesexplorer.service.account.GroupService import io.mockk.* import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test @@ -84,4 +82,4 @@ class DefaultGroupLogicTest { userLogicMock.deleteById(group.defaultGroupUserId) } } -} \ No newline at end of file +} diff --git a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultUserLogicTest.kt b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultUserLogicTest.kt index d4f8b32..d288021 100644 --- a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultUserLogicTest.kt +++ b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultUserLogicTest.kt @@ -1,15 +1,13 @@ package dev.fyloz.colorrecipesexplorer.logic.account -import dev.fyloz.colorrecipesexplorer.dtos.GroupDto -import dev.fyloz.colorrecipesexplorer.dtos.UserDto -import dev.fyloz.colorrecipesexplorer.dtos.UserSaveDto -import dev.fyloz.colorrecipesexplorer.dtos.UserUpdateDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserSaveDto +import dev.fyloz.colorrecipesexplorer.dtos.account.UserUpdateDto import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException import dev.fyloz.colorrecipesexplorer.exception.NotFoundException -import dev.fyloz.colorrecipesexplorer.logic.users.DefaultUserLogic -import dev.fyloz.colorrecipesexplorer.logic.users.GroupLogic import dev.fyloz.colorrecipesexplorer.model.account.Permission -import dev.fyloz.colorrecipesexplorer.service.UserService +import dev.fyloz.colorrecipesexplorer.service.account.UserService import io.mockk.* import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test @@ -303,4 +301,4 @@ class DefaultUserLogicTest { userLogic.update(user) } } -} \ No newline at end of file +}