feature/#30-group-authentication #31
|
@ -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})$"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<RecipeGroupNoteDto>,
|
||||
|
||||
val mixesLocation: List<MixLocationDto>
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
)
|
|
@ -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<Permission>,
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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<InvalidPositionError>
|
||||
get() = exception.errors
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<GroupTokenDto>
|
||||
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
|
||||
)
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
)
|
|
@ -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<User, Long> {
|
||||
|
@ -28,3 +30,9 @@ interface GroupRepository : JpaRepository<Group, Long> {
|
|||
/** Checks if a group with the given [name] and a different [id] exists. */
|
||||
fun existsByNameAndIdNot(name: String, id: Long): Boolean
|
||||
}
|
||||
|
||||
@Repository
|
||||
interface GroupTokenRepository : JpaRepository<GroupToken, UUID> {
|
||||
/** Checks if a token with the given [name] exists. */
|
||||
fun existsByName(name: String): Boolean
|
||||
}
|
||||
|
|
|
@ -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<GroupDto>(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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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<GroupDto>(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")
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<GroupDto, Group, GroupRepository> {
|
||||
/** Checks if a group with the given [name] and a different [id] exists. */
|
||||
|
@ -28,4 +30,4 @@ class DefaultGroupService(repository: GroupRepository) : BaseService<GroupDto, G
|
|||
|
||||
override fun flattenPermissions(group: Group) =
|
||||
group.permissions.flatMap { it.flat() }.filter { !it.deprecated }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package dev.fyloz.colorrecipesexplorer.service.account
|
||||
|
||||
import dev.fyloz.colorrecipesexplorer.config.annotations.ServiceComponent
|
||||
import dev.fyloz.colorrecipesexplorer.dtos.account.GroupTokenDto
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.GroupToken
|
||||
import dev.fyloz.colorrecipesexplorer.repository.GroupTokenRepository
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import java.util.UUID
|
||||
|
||||
interface GroupTokenService {
|
||||
fun existsById(id: UUID): Boolean
|
||||
fun existsByName(name: String): Boolean
|
||||
fun getAll(): Collection<GroupTokenDto>
|
||||
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))
|
||||
}
|
|
@ -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<UserDto, User, UserRepository> {
|
||||
|
@ -100,4 +102,4 @@ class DefaultUserService(repository: UserRepository, private val groupService: G
|
|||
|
||||
return perms
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<InvalidGroupStepsPositionsException> { recipeStepLogic.validateGroupInformationSteps(groupInfo) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue