Employee -> User
This commit is contained in:
parent
a59bad7a7a
commit
8f761a4be4
|
@ -2,13 +2,13 @@ package dev.fyloz.colorrecipesexplorer.config
|
|||
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
|
||||
import dev.fyloz.colorrecipesexplorer.model.Employee
|
||||
import dev.fyloz.colorrecipesexplorer.model.EmployeeLoginRequest
|
||||
import dev.fyloz.colorrecipesexplorer.model.EmployeePermission
|
||||
import dev.fyloz.colorrecipesexplorer.service.EmployeeService
|
||||
import dev.fyloz.colorrecipesexplorer.service.EmployeeServiceImpl
|
||||
import dev.fyloz.colorrecipesexplorer.service.EmployeeUserDetailsService
|
||||
import dev.fyloz.colorrecipesexplorer.service.EmployeeUserDetailsServiceImpl
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.UserLoginRequest
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.Permission
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.User
|
||||
import dev.fyloz.colorrecipesexplorer.service.UserService
|
||||
import dev.fyloz.colorrecipesexplorer.service.UserServiceImpl
|
||||
import dev.fyloz.colorrecipesexplorer.service.CreUserDetailsService
|
||||
import dev.fyloz.colorrecipesexplorer.service.CreUserDetailsServiceImpl
|
||||
import io.jsonwebtoken.ExpiredJwtException
|
||||
import io.jsonwebtoken.Jwts
|
||||
import io.jsonwebtoken.SignatureAlgorithm
|
||||
|
@ -31,7 +31,7 @@ import org.springframework.security.config.http.SessionCreationPolicy
|
|||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.core.userdetails.User
|
||||
import org.springframework.security.core.userdetails.User as SpringUser
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||
|
@ -52,11 +52,11 @@ import javax.servlet.http.HttpServletResponse
|
|||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@EnableConfigurationProperties(SecurityConfigurationProperties::class)
|
||||
class WebSecurityConfig(
|
||||
val securityConfigurationProperties: SecurityConfigurationProperties,
|
||||
@Lazy val userDetailsService: EmployeeUserDetailsServiceImpl,
|
||||
@Lazy val employeeService: EmployeeServiceImpl,
|
||||
val environment: Environment,
|
||||
val logger: Logger
|
||||
val securityConfigurationProperties: SecurityConfigurationProperties,
|
||||
@Lazy val userDetailsService: CreUserDetailsServiceImpl,
|
||||
@Lazy val userService: UserServiceImpl,
|
||||
val environment: Environment,
|
||||
val logger: Logger
|
||||
) : WebSecurityConfigurerAdapter() {
|
||||
var debugMode = false
|
||||
|
||||
|
@ -95,15 +95,15 @@ class WebSecurityConfig(
|
|||
credentials: SecurityConfigurationProperties.SystemUserCredentials?,
|
||||
firstName: String,
|
||||
lastName: String,
|
||||
permissions: List<EmployeePermission>
|
||||
permissions: List<Permission>
|
||||
) {
|
||||
Assert.notNull(credentials, "No root user has been defined.")
|
||||
credentials!!
|
||||
Assert.notNull(credentials.id, "The root user has no identifier defined.")
|
||||
Assert.notNull(credentials.password, "The root user has no password defined.")
|
||||
if (!employeeService.existsById(credentials.id!!)) {
|
||||
employeeService.save(
|
||||
Employee(
|
||||
if (!userService.existsById(credentials.id!!)) {
|
||||
userService.save(
|
||||
User(
|
||||
id = credentials.id!!,
|
||||
firstName = firstName,
|
||||
lastName = lastName,
|
||||
|
@ -115,7 +115,7 @@ class WebSecurityConfig(
|
|||
}
|
||||
}
|
||||
|
||||
createUser(securityConfigurationProperties.root, "Root", "User", listOf(EmployeePermission.ADMIN))
|
||||
createUser(securityConfigurationProperties.root, "Root", "User", listOf(Permission.ADMIN))
|
||||
debugMode = "debug" in environment.activeProfiles
|
||||
if (debugMode) logger.warn("Debug mode is enabled, security will be disabled!")
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ class WebSecurityConfig(
|
|||
.addFilter(
|
||||
JwtAuthenticationFilter(
|
||||
authenticationManager(),
|
||||
employeeService,
|
||||
userService,
|
||||
securityConfigurationProperties
|
||||
)
|
||||
)
|
||||
|
@ -145,7 +145,7 @@ class WebSecurityConfig(
|
|||
http.authorizeRequests()
|
||||
.antMatchers("/api/login").permitAll()
|
||||
.antMatchers("/api/logout").authenticated()
|
||||
.antMatchers("/api/employee/current").authenticated()
|
||||
.antMatchers("/api/user/current").authenticated()
|
||||
.anyRequest().authenticated()
|
||||
} else {
|
||||
http
|
||||
|
@ -171,9 +171,9 @@ const val defaultGroupCookieName = "Default-Group"
|
|||
val blacklistedJwtTokens = mutableListOf<String>()
|
||||
|
||||
class JwtAuthenticationFilter(
|
||||
private val authManager: AuthenticationManager,
|
||||
private val employeeService: EmployeeService,
|
||||
private val securityConfigurationProperties: SecurityConfigurationProperties
|
||||
private val authManager: AuthenticationManager,
|
||||
private val userService: UserService,
|
||||
private val securityConfigurationProperties: SecurityConfigurationProperties
|
||||
) : UsernamePasswordAuthenticationFilter() {
|
||||
private var debugMode = false
|
||||
|
||||
|
@ -183,7 +183,7 @@ class JwtAuthenticationFilter(
|
|||
}
|
||||
|
||||
override fun attemptAuthentication(request: HttpServletRequest, response: HttpServletResponse): Authentication {
|
||||
val loginRequest = jacksonObjectMapper().readValue(request.inputStream, EmployeeLoginRequest::class.java)
|
||||
val loginRequest = jacksonObjectMapper().readValue(request.inputStream, UserLoginRequest::class.java)
|
||||
return authManager.authenticate(UsernamePasswordAuthenticationToken(loginRequest.id, loginRequest.password))
|
||||
}
|
||||
|
||||
|
@ -197,12 +197,12 @@ class JwtAuthenticationFilter(
|
|||
val jwtDuration = securityConfigurationProperties.jwtDuration
|
||||
Assert.notNull(jwtSecret, "No JWT secret has been defined.")
|
||||
Assert.notNull(jwtDuration, "No JWT duration has been defined.")
|
||||
val employeeId = (authResult.principal as User).username
|
||||
employeeService.updateLastLoginTime(employeeId.toLong())
|
||||
val userId = (authResult.principal as SpringUser).username
|
||||
userService.updateLastLoginTime(userId.toLong())
|
||||
val expirationMs = System.currentTimeMillis() + jwtDuration!!
|
||||
val expirationDate = Date(expirationMs)
|
||||
val token = Jwts.builder()
|
||||
.setSubject(employeeId)
|
||||
.setSubject(userId)
|
||||
.setExpiration(expirationDate)
|
||||
.signWith(SignatureAlgorithm.HS512, jwtSecret!!.toByteArray())
|
||||
.compact()
|
||||
|
@ -220,9 +220,9 @@ class JwtAuthenticationFilter(
|
|||
}
|
||||
|
||||
class JwtAuthorizationFilter(
|
||||
private val userDetailsService: EmployeeUserDetailsService,
|
||||
private val securityConfigurationProperties: SecurityConfigurationProperties,
|
||||
authenticationManager: AuthenticationManager
|
||||
private val userDetailsService: CreUserDetailsService,
|
||||
private val securityConfigurationProperties: SecurityConfigurationProperties,
|
||||
authenticationManager: AuthenticationManager
|
||||
) : BasicAuthenticationFilter(authenticationManager) {
|
||||
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
|
||||
fun tryLoginFromBearer(): Boolean {
|
||||
|
@ -259,20 +259,20 @@ class JwtAuthorizationFilter(
|
|||
val jwtSecret = securityConfigurationProperties.jwtSecret
|
||||
Assert.notNull(jwtSecret, "No JWT secret has been defined.")
|
||||
return try {
|
||||
val employeeId = Jwts.parser()
|
||||
val userId = Jwts.parser()
|
||||
.setSigningKey(jwtSecret!!.toByteArray())
|
||||
.parseClaimsJws(token.replace("Bearer", ""))
|
||||
.body
|
||||
.subject
|
||||
if (employeeId != null) getAuthenticationToken(employeeId) else null
|
||||
if (userId != null) getAuthenticationToken(userId) else null
|
||||
} catch (_: ExpiredJwtException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAuthenticationToken(employeeId: String): UsernamePasswordAuthenticationToken? = try {
|
||||
val employeeDetails = userDetailsService.loadUserByEmployeeId(employeeId.toLong(), false)
|
||||
UsernamePasswordAuthenticationToken(employeeDetails.username, null, employeeDetails.authorities)
|
||||
private fun getAuthenticationToken(userId: String): UsernamePasswordAuthenticationToken? = try {
|
||||
val userDetails = userDetailsService.loadUserById(userId.toLong(), false)
|
||||
UsernamePasswordAuthenticationToken(userDetails.username, null, userDetails.authorities)
|
||||
} catch (_: NotFoundException) {
|
||||
null
|
||||
}
|
||||
|
|
|
@ -1,193 +0,0 @@
|
|||
package dev.fyloz.colorrecipesexplorer.model
|
||||
|
||||
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
|
||||
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
|
||||
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrNotBlank
|
||||
import org.hibernate.annotations.Fetch
|
||||
import org.hibernate.annotations.FetchMode
|
||||
import org.springframework.security.core.GrantedAuthority
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import java.time.LocalDateTime
|
||||
import javax.persistence.*
|
||||
import javax.validation.constraints.NotBlank
|
||||
import javax.validation.constraints.NotNull
|
||||
import javax.validation.constraints.Size
|
||||
|
||||
private const val EMPLOYEE_ID_NULL_MESSAGE = "Un numéro d'employé est requis"
|
||||
private const val EMPLOYEE_LAST_NAME_EMPTY_MESSAGE = "Un nom est requis"
|
||||
private const val EMPLOYEE_FIRST_NAME_EMPTY_MESSAGE = "Un prénom est requis"
|
||||
private const val EMPLOYEE_PASSWORD_EMPTY_MESSAGE = "Un mot de passe est requis"
|
||||
private const val EMPLOYEE_PASSWORD_TOO_SHORT_MESSAGE = "Le mot de passe doit contenir au moins 8 caractères"
|
||||
|
||||
@Entity
|
||||
@Table(name = "employee")
|
||||
data class Employee(
|
||||
@Id
|
||||
override val id: Long,
|
||||
|
||||
@Column(name = "first_name")
|
||||
val firstName: String = "",
|
||||
|
||||
@Column(name = "last_name")
|
||||
val lastName: String = "",
|
||||
|
||||
val password: String = "",
|
||||
|
||||
@Column(name = "default_group_user")
|
||||
val isDefaultGroupUser: Boolean = false,
|
||||
|
||||
@Column(name = "system_user")
|
||||
val isSystemUser: Boolean = false,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "group_id")
|
||||
@Fetch(FetchMode.SELECT)
|
||||
var group: EmployeeGroup? = null,
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "employee_permission", joinColumns = [JoinColumn(name = "employee_id")])
|
||||
@Column(name = "permission")
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
val permissions: MutableSet<EmployeePermission> = mutableSetOf(),
|
||||
|
||||
@Column(name = "last_login_time")
|
||||
var lastLoginTime: LocalDateTime? = null
|
||||
) : Model {
|
||||
val flatPermissions: Set<EmployeePermission>
|
||||
get() = permissions
|
||||
.flatMap { it.flat() }
|
||||
.filter { !it.deprecated }
|
||||
.toMutableSet()
|
||||
.apply {
|
||||
if (group != null) this.addAll(group!!.flatPermissions)
|
||||
}
|
||||
|
||||
val authorities: Set<GrantedAuthority>
|
||||
get() = flatPermissions.map { it.toAuthority() }.toMutableSet()
|
||||
}
|
||||
|
||||
/** DTO for creating employees. Allows a [password] a [groupId]. */
|
||||
open class EmployeeSaveDto(
|
||||
@field:NotNull(message = EMPLOYEE_ID_NULL_MESSAGE)
|
||||
val id: Long,
|
||||
|
||||
@field:NotBlank(message = EMPLOYEE_FIRST_NAME_EMPTY_MESSAGE)
|
||||
val firstName: String,
|
||||
|
||||
@field:NotBlank(message = EMPLOYEE_LAST_NAME_EMPTY_MESSAGE)
|
||||
val lastName: String,
|
||||
|
||||
@field:NotBlank(message = EMPLOYEE_PASSWORD_EMPTY_MESSAGE)
|
||||
@field:Size(min = 8, message = EMPLOYEE_PASSWORD_TOO_SHORT_MESSAGE)
|
||||
val password: String,
|
||||
|
||||
val groupId: Long?,
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
val permissions: MutableSet<EmployeePermission> = mutableSetOf()
|
||||
) : EntityDto<Employee>
|
||||
|
||||
open class EmployeeUpdateDto(
|
||||
@field:NotNull(message = EMPLOYEE_ID_NULL_MESSAGE)
|
||||
val id: Long,
|
||||
|
||||
@field:NullOrNotBlank(message = EMPLOYEE_FIRST_NAME_EMPTY_MESSAGE)
|
||||
val firstName: String?,
|
||||
|
||||
@field:NullOrNotBlank(message = EMPLOYEE_LAST_NAME_EMPTY_MESSAGE)
|
||||
val lastName: String?,
|
||||
|
||||
val groupId: Long?,
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
val permissions: Set<EmployeePermission>?
|
||||
) : EntityDto<Employee>
|
||||
|
||||
data class EmployeeOutputDto(
|
||||
override val id: Long,
|
||||
val firstName: String,
|
||||
val lastName: String,
|
||||
val group: EmployeeGroup?,
|
||||
val permissions: Set<EmployeePermission>,
|
||||
val explicitPermissions: Set<EmployeePermission>,
|
||||
val lastLoginTime: LocalDateTime?
|
||||
) : Model
|
||||
|
||||
data class EmployeeLoginRequest(val id: Long, val password: String)
|
||||
|
||||
// ==== DSL ====
|
||||
fun employee(
|
||||
passwordEncoder: PasswordEncoder = BCryptPasswordEncoder(),
|
||||
id: Long = 0L,
|
||||
firstName: String = "firstName",
|
||||
lastName: String = "lastName",
|
||||
password: String = passwordEncoder.encode("password"),
|
||||
isDefaultGroupUser: Boolean = false,
|
||||
isSystemUser: Boolean = false,
|
||||
group: EmployeeGroup? = null,
|
||||
permissions: MutableSet<EmployeePermission> = mutableSetOf(),
|
||||
lastLoginTime: LocalDateTime? = null,
|
||||
op: Employee.() -> Unit = {}
|
||||
) = Employee(
|
||||
id,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
isDefaultGroupUser,
|
||||
isSystemUser,
|
||||
group,
|
||||
permissions,
|
||||
lastLoginTime
|
||||
).apply(op)
|
||||
|
||||
fun employeeSaveDto(
|
||||
passwordEncoder: PasswordEncoder = BCryptPasswordEncoder(),
|
||||
id: Long = 0L,
|
||||
firstName: String = "firstName",
|
||||
lastName: String = "lastName",
|
||||
password: String = passwordEncoder.encode("password"),
|
||||
groupId: Long? = null,
|
||||
permissions: MutableSet<EmployeePermission> = mutableSetOf(),
|
||||
op: EmployeeSaveDto.() -> Unit = {}
|
||||
) = EmployeeSaveDto(id, firstName, lastName, password, groupId, permissions).apply(op)
|
||||
|
||||
fun employeeUpdateDto(
|
||||
id: Long = 0L,
|
||||
firstName: String = "firstName",
|
||||
lastName: String = "lastName",
|
||||
groupId: Long? = null,
|
||||
permissions: MutableSet<EmployeePermission> = mutableSetOf(),
|
||||
op: EmployeeUpdateDto.() -> Unit = {}
|
||||
) = EmployeeUpdateDto(id, firstName, lastName, groupId, permissions).apply(op)
|
||||
|
||||
// ==== Exceptions ====
|
||||
private const val EMPLOYEE_NOT_FOUND_EXCEPTION_TITLE = "Employee not found"
|
||||
private const val EMPLOYEE_ALREADY_EXISTS_EXCEPTION_TITLE = "Employee already exists"
|
||||
private const val EMPLOYEE_EXCEPTION_ERROR_CODE = "employee"
|
||||
|
||||
fun employeeIdNotFoundException(id: Long) =
|
||||
NotFoundException(
|
||||
EMPLOYEE_EXCEPTION_ERROR_CODE,
|
||||
EMPLOYEE_NOT_FOUND_EXCEPTION_TITLE,
|
||||
"An employee with the id $id could not be found",
|
||||
id
|
||||
)
|
||||
|
||||
fun employeeIdAlreadyExistsException(id: Long) =
|
||||
AlreadyExistsException(
|
||||
EMPLOYEE_EXCEPTION_ERROR_CODE,
|
||||
EMPLOYEE_ALREADY_EXISTS_EXCEPTION_TITLE,
|
||||
"An employee with the id $id already exists",
|
||||
id
|
||||
)
|
||||
|
||||
fun employeeFullNameAlreadyExistsException(firstName: String, lastName: String) =
|
||||
AlreadyExistsException(
|
||||
EMPLOYEE_EXCEPTION_ERROR_CODE,
|
||||
EMPLOYEE_ALREADY_EXISTS_EXCEPTION_TITLE,
|
||||
"An employee with the name '$firstName $lastName' already exists",
|
||||
"$firstName $lastName",
|
||||
"fullName"
|
||||
)
|
|
@ -1,141 +0,0 @@
|
|||
package dev.fyloz.colorrecipesexplorer.model
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
|
||||
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
|
||||
import dev.fyloz.colorrecipesexplorer.exception.RestException
|
||||
import org.hibernate.annotations.Fetch
|
||||
import org.hibernate.annotations.FetchMode
|
||||
import org.springframework.http.HttpStatus
|
||||
import javax.persistence.*
|
||||
import javax.validation.constraints.NotBlank
|
||||
import javax.validation.constraints.NotNull
|
||||
import javax.validation.constraints.Size
|
||||
|
||||
private const val GROUP_ID_NULL_MESSAGE = "Un identifiant est requis"
|
||||
private const val GROUP_NAME_NULL_MESSAGE = "Un nom est requis"
|
||||
private const val GROUP_PERMISSIONS_EMPTY_MESSAGE = "Au moins une permission est requise"
|
||||
|
||||
@Entity
|
||||
@Table(name = "employee_group")
|
||||
data class EmployeeGroup(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
override var id: Long? = null,
|
||||
|
||||
@Column(unique = true)
|
||||
override val name: String = "",
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "group_permission", joinColumns = [JoinColumn(name = "group_id")])
|
||||
@Column(name = "permission")
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
val permissions: MutableSet<EmployeePermission> = mutableSetOf(),
|
||||
) : NamedModel {
|
||||
val flatPermissions: Set<EmployeePermission>
|
||||
get() = this.permissions
|
||||
.flatMap { it.flat() }
|
||||
.filter { !it.deprecated }
|
||||
.toSet()
|
||||
}
|
||||
|
||||
open class EmployeeGroupSaveDto(
|
||||
@field:NotBlank(message = GROUP_NAME_NULL_MESSAGE)
|
||||
@field:Size(min = 3)
|
||||
val name: String,
|
||||
|
||||
@field:Size(min = 1, message = GROUP_PERMISSIONS_EMPTY_MESSAGE)
|
||||
val permissions: MutableSet<EmployeePermission>
|
||||
) : EntityDto<EmployeeGroup> {
|
||||
override fun toEntity(): EmployeeGroup =
|
||||
EmployeeGroup(null, name, permissions)
|
||||
}
|
||||
|
||||
open class EmployeeGroupUpdateDto(
|
||||
@field:NotNull(message = GROUP_ID_NULL_MESSAGE)
|
||||
val id: Long,
|
||||
|
||||
@field:NotBlank(message = GROUP_NAME_NULL_MESSAGE)
|
||||
@field:Size(min = 3)
|
||||
val name: String,
|
||||
|
||||
@field:Size(min = 1, message = GROUP_PERMISSIONS_EMPTY_MESSAGE)
|
||||
val permissions: MutableSet<EmployeePermission>
|
||||
) : EntityDto<EmployeeGroup> {
|
||||
override fun toEntity(): EmployeeGroup =
|
||||
EmployeeGroup(id, name, permissions)
|
||||
}
|
||||
|
||||
data class EmployeeGroupOutputDto(
|
||||
override val id: Long,
|
||||
val name: String,
|
||||
val permissions: Set<EmployeePermission>,
|
||||
val explicitPermissions: Set<EmployeePermission>
|
||||
): Model
|
||||
|
||||
fun employeeGroup(
|
||||
id: Long? = null,
|
||||
name: String = "name",
|
||||
permissions: MutableSet<EmployeePermission> = mutableSetOf(),
|
||||
op: EmployeeGroup.() -> Unit = {}
|
||||
) = EmployeeGroup(id, name, permissions).apply(op)
|
||||
|
||||
fun employeeGroupSaveDto(
|
||||
name: String = "name",
|
||||
permissions: MutableSet<EmployeePermission> = mutableSetOf(),
|
||||
op: EmployeeGroupSaveDto.() -> Unit = {}
|
||||
) = EmployeeGroupSaveDto(name, permissions).apply(op)
|
||||
|
||||
fun employeeGroupUpdateDto(
|
||||
id: Long = 0L,
|
||||
name: String = "name",
|
||||
permissions: MutableSet<EmployeePermission> = mutableSetOf(),
|
||||
op: EmployeeGroupUpdateDto.() -> Unit = {}
|
||||
) = EmployeeGroupUpdateDto(id, name, permissions).apply(op)
|
||||
|
||||
// ==== Exceptions ====
|
||||
private const val EMPLOYEE_NOT_FOUND_EXCEPTION_TITLE = "Employee group not found"
|
||||
private const val EMPLOYEE_ALREADY_EXISTS_EXCEPTION_TITLE = "Employee group already exists"
|
||||
private const val EMPLOYEE_EXCEPTION_ERROR_CODE = "employeegroup"
|
||||
|
||||
class NoDefaultGroupException : RestException(
|
||||
"nodefaultgroup",
|
||||
"No default group",
|
||||
HttpStatus.NOT_FOUND,
|
||||
"No default group cookie is defined in the current request"
|
||||
)
|
||||
|
||||
fun employeeGroupIdNotFoundException(id: Long) =
|
||||
NotFoundException(
|
||||
EMPLOYEE_EXCEPTION_ERROR_CODE,
|
||||
EMPLOYEE_NOT_FOUND_EXCEPTION_TITLE,
|
||||
"An employee group with the id $id could not be found",
|
||||
id
|
||||
)
|
||||
|
||||
fun employeeGroupNameNotFoundException(name: String) =
|
||||
NotFoundException(
|
||||
EMPLOYEE_EXCEPTION_ERROR_CODE,
|
||||
EMPLOYEE_NOT_FOUND_EXCEPTION_TITLE,
|
||||
"An employee group with the name $name could not be found",
|
||||
name,
|
||||
"name"
|
||||
)
|
||||
|
||||
fun employeeGroupIdAlreadyExistsException(id: Long) =
|
||||
AlreadyExistsException(
|
||||
EMPLOYEE_EXCEPTION_ERROR_CODE,
|
||||
EMPLOYEE_ALREADY_EXISTS_EXCEPTION_TITLE,
|
||||
"An employee group with the id $id already exists",
|
||||
id,
|
||||
)
|
||||
|
||||
fun employeeGroupNameAlreadyExistsException(name: String) =
|
||||
AlreadyExistsException(
|
||||
EMPLOYEE_EXCEPTION_ERROR_CODE,
|
||||
EMPLOYEE_ALREADY_EXISTS_EXCEPTION_TITLE,
|
||||
"An employee group with the name $name already exists",
|
||||
name,
|
||||
"name"
|
||||
)
|
|
@ -3,6 +3,8 @@ package dev.fyloz.colorrecipesexplorer.model
|
|||
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
|
||||
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.Group
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.group
|
||||
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrNotBlank
|
||||
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrSize
|
||||
import dev.fyloz.colorrecipesexplorer.rest.CRE_PROPERTIES
|
||||
|
@ -176,7 +178,7 @@ data class RecipeGroupInformation(
|
|||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "group_id")
|
||||
val group: EmployeeGroup,
|
||||
val group: Group,
|
||||
|
||||
var note: String?,
|
||||
|
||||
|
@ -264,7 +266,7 @@ fun recipeUpdateDto(
|
|||
|
||||
fun recipeGroupInformation(
|
||||
id: Long? = null,
|
||||
group: EmployeeGroup = employeeGroup(),
|
||||
group: Group = group(),
|
||||
note: String? = null,
|
||||
steps: MutableSet<RecipeStep>? = mutableSetOf(),
|
||||
op: RecipeGroupInformation.() -> Unit = {}
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
package dev.fyloz.colorrecipesexplorer.model.account
|
||||
|
||||
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
|
||||
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
|
||||
import dev.fyloz.colorrecipesexplorer.exception.RestException
|
||||
import dev.fyloz.colorrecipesexplorer.model.EntityDto
|
||||
import dev.fyloz.colorrecipesexplorer.model.Model
|
||||
import dev.fyloz.colorrecipesexplorer.model.NamedModel
|
||||
import org.hibernate.annotations.Fetch
|
||||
import org.hibernate.annotations.FetchMode
|
||||
import org.springframework.http.HttpStatus
|
||||
import javax.persistence.*
|
||||
import javax.validation.constraints.NotBlank
|
||||
import javax.validation.constraints.NotNull
|
||||
import javax.validation.constraints.Size
|
||||
|
||||
private const val GROUP_ID_NULL_MESSAGE = "Un identifiant est requis"
|
||||
private const val GROUP_NAME_NULL_MESSAGE = "Un nom est requis"
|
||||
private const val GROUP_PERMISSIONS_EMPTY_MESSAGE = "Au moins une permission est requise"
|
||||
|
||||
@Entity
|
||||
@Table(name = "user_group")
|
||||
data class Group(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
override var id: Long? = null,
|
||||
|
||||
@Column(unique = true)
|
||||
override val name: String = "",
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "group_permission", joinColumns = [JoinColumn(name = "group_id")])
|
||||
@Column(name = "permission")
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
val permissions: MutableSet<Permission> = mutableSetOf(),
|
||||
) : NamedModel {
|
||||
val flatPermissions: Set<Permission>
|
||||
get() = this.permissions
|
||||
.flatMap { it.flat() }
|
||||
.filter { !it.deprecated }
|
||||
.toSet()
|
||||
}
|
||||
|
||||
open class GroupSaveDto(
|
||||
@field:NotBlank(message = GROUP_NAME_NULL_MESSAGE)
|
||||
@field:Size(min = 3)
|
||||
val name: String,
|
||||
|
||||
@field:Size(min = 1, message = GROUP_PERMISSIONS_EMPTY_MESSAGE)
|
||||
val permissions: MutableSet<Permission>
|
||||
) : EntityDto<Group> {
|
||||
override fun toEntity(): Group =
|
||||
Group(null, name, permissions)
|
||||
}
|
||||
|
||||
open class GroupUpdateDto(
|
||||
@field:NotNull(message = GROUP_ID_NULL_MESSAGE)
|
||||
val id: Long,
|
||||
|
||||
@field:NotBlank(message = GROUP_NAME_NULL_MESSAGE)
|
||||
@field:Size(min = 3)
|
||||
val name: String,
|
||||
|
||||
@field:Size(min = 1, message = GROUP_PERMISSIONS_EMPTY_MESSAGE)
|
||||
val permissions: MutableSet<Permission>
|
||||
) : EntityDto<Group> {
|
||||
override fun toEntity(): Group =
|
||||
Group(id, name, permissions)
|
||||
}
|
||||
|
||||
data class GroupOutputDto(
|
||||
override val id: Long,
|
||||
val name: String,
|
||||
val permissions: Set<Permission>,
|
||||
val explicitPermissions: Set<Permission>
|
||||
): Model
|
||||
|
||||
fun group(
|
||||
id: Long? = null,
|
||||
name: String = "name",
|
||||
permissions: MutableSet<Permission> = mutableSetOf(),
|
||||
op: Group.() -> Unit = {}
|
||||
) = Group(id, name, permissions).apply(op)
|
||||
|
||||
fun groupSaveDto(
|
||||
name: String = "name",
|
||||
permissions: MutableSet<Permission> = mutableSetOf(),
|
||||
op: GroupSaveDto.() -> Unit = {}
|
||||
) = GroupSaveDto(name, permissions).apply(op)
|
||||
|
||||
fun groupUpdateDto(
|
||||
id: Long = 0L,
|
||||
name: String = "name",
|
||||
permissions: MutableSet<Permission> = mutableSetOf(),
|
||||
op: GroupUpdateDto.() -> Unit = {}
|
||||
) = GroupUpdateDto(id, name, permissions).apply(op)
|
||||
|
||||
// ==== Exceptions ====
|
||||
private const val GROUP_NOT_FOUND_EXCEPTION_TITLE = "Group not found"
|
||||
private const val GROUP_ALREADY_EXISTS_EXCEPTION_TITLE = "Group already exists"
|
||||
private const val GROUP_EXCEPTION_ERROR_CODE = "group"
|
||||
|
||||
class NoDefaultGroupException : RestException(
|
||||
"nodefaultgroup",
|
||||
"No default group",
|
||||
HttpStatus.NOT_FOUND,
|
||||
"No default group cookie is defined in the current request"
|
||||
)
|
||||
|
||||
fun groupIdNotFoundException(id: Long) =
|
||||
NotFoundException(
|
||||
GROUP_EXCEPTION_ERROR_CODE,
|
||||
GROUP_NOT_FOUND_EXCEPTION_TITLE,
|
||||
"A group with the id $id could not be found",
|
||||
id
|
||||
)
|
||||
|
||||
fun groupNameNotFoundException(name: String) =
|
||||
NotFoundException(
|
||||
GROUP_EXCEPTION_ERROR_CODE,
|
||||
GROUP_NOT_FOUND_EXCEPTION_TITLE,
|
||||
"A group with the name $name could not be found",
|
||||
name,
|
||||
"name"
|
||||
)
|
||||
|
||||
fun groupIdAlreadyExistsException(id: Long) =
|
||||
AlreadyExistsException(
|
||||
GROUP_EXCEPTION_ERROR_CODE,
|
||||
GROUP_ALREADY_EXISTS_EXCEPTION_TITLE,
|
||||
"A group with the id $id already exists",
|
||||
id,
|
||||
)
|
||||
|
||||
fun groupNameAlreadyExistsException(name: String) =
|
||||
AlreadyExistsException(
|
||||
GROUP_EXCEPTION_ERROR_CODE,
|
||||
GROUP_ALREADY_EXISTS_EXCEPTION_TITLE,
|
||||
"A group with the name $name already exists",
|
||||
name,
|
||||
"name"
|
||||
)
|
|
@ -1,10 +1,10 @@
|
|||
package dev.fyloz.colorrecipesexplorer.model
|
||||
package dev.fyloz.colorrecipesexplorer.model.account
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||
|
||||
enum class EmployeePermission(
|
||||
val impliedPermissions: List<EmployeePermission> = listOf(),
|
||||
enum class Permission(
|
||||
val impliedPermissions: List<Permission> = listOf(),
|
||||
val deprecated: Boolean = false
|
||||
) {
|
||||
READ_FILE,
|
||||
|
@ -80,12 +80,12 @@ enum class EmployeePermission(
|
|||
SET_BROWSER_DEFAULT_GROUP(listOf(VIEW_USERS), true),
|
||||
;
|
||||
|
||||
operator fun contains(permission: EmployeePermission): Boolean {
|
||||
operator fun contains(permission: Permission): Boolean {
|
||||
return permission == this || impliedPermissions.any { permission in it }
|
||||
}
|
||||
}
|
||||
|
||||
fun EmployeePermission.flat(): Iterable<EmployeePermission> {
|
||||
fun Permission.flat(): Iterable<Permission> {
|
||||
return mutableSetOf(this).apply {
|
||||
impliedPermissions.forEach {
|
||||
addAll(it.flat())
|
||||
|
@ -93,7 +93,7 @@ fun EmployeePermission.flat(): Iterable<EmployeePermission> {
|
|||
}
|
||||
}
|
||||
|
||||
/** Converts the given [EmployeePermission] to a [GrantedAuthority]. */
|
||||
fun EmployeePermission.toAuthority(): GrantedAuthority {
|
||||
/** Converts the given [Permission] to a [GrantedAuthority]. */
|
||||
fun Permission.toAuthority(): GrantedAuthority {
|
||||
return SimpleGrantedAuthority(name)
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
package dev.fyloz.colorrecipesexplorer.model.account
|
||||
|
||||
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
|
||||
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
|
||||
import dev.fyloz.colorrecipesexplorer.model.EntityDto
|
||||
import dev.fyloz.colorrecipesexplorer.model.Model
|
||||
import dev.fyloz.colorrecipesexplorer.model.validation.NullOrNotBlank
|
||||
import org.hibernate.annotations.Fetch
|
||||
import org.hibernate.annotations.FetchMode
|
||||
import org.springframework.security.core.GrantedAuthority
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import java.time.LocalDateTime
|
||||
import javax.persistence.*
|
||||
import javax.validation.constraints.NotBlank
|
||||
import javax.validation.constraints.NotNull
|
||||
import javax.validation.constraints.Size
|
||||
|
||||
private const val USER_ID_NULL_MESSAGE = "Un numéro d'utilisateur est requis"
|
||||
private const val USER_LAST_NAME_EMPTY_MESSAGE = "Un nom est requis"
|
||||
private const val USER_FIRST_NAME_EMPTY_MESSAGE = "Un prénom est requis"
|
||||
private const val USER_PASSWORD_EMPTY_MESSAGE = "Un mot de passe est requis"
|
||||
private const val USER_PASSWORD_TOO_SHORT_MESSAGE = "Le mot de passe doit contenir au moins 8 caractères"
|
||||
|
||||
@Entity
|
||||
@Table(name = "user")
|
||||
data class User(
|
||||
@Id
|
||||
override val id: Long,
|
||||
|
||||
@Column(name = "first_name")
|
||||
val firstName: String = "",
|
||||
|
||||
@Column(name = "last_name")
|
||||
val lastName: String = "",
|
||||
|
||||
val password: String = "",
|
||||
|
||||
@Column(name = "default_group_user")
|
||||
val isDefaultGroupUser: Boolean = false,
|
||||
|
||||
@Column(name = "system_user")
|
||||
val isSystemUser: Boolean = false,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "group_id")
|
||||
@Fetch(FetchMode.SELECT)
|
||||
var group: Group? = null,
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "user_permission", joinColumns = [JoinColumn(name = "user_id")])
|
||||
@Column(name = "permission")
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
val permissions: MutableSet<Permission> = mutableSetOf(),
|
||||
|
||||
@Column(name = "last_login_time")
|
||||
var lastLoginTime: LocalDateTime? = null
|
||||
) : Model {
|
||||
val flatPermissions: Set<Permission>
|
||||
get() = permissions
|
||||
.flatMap { it.flat() }
|
||||
.filter { !it.deprecated }
|
||||
.toMutableSet()
|
||||
.apply {
|
||||
if (group != null) this.addAll(group!!.flatPermissions)
|
||||
}
|
||||
|
||||
val authorities: Set<GrantedAuthority>
|
||||
get() = flatPermissions.map { it.toAuthority() }.toMutableSet()
|
||||
}
|
||||
|
||||
/** DTO for creating users. Allows a [password] a [groupId]. */
|
||||
open class UserSaveDto(
|
||||
@field:NotNull(message = USER_ID_NULL_MESSAGE)
|
||||
val id: Long,
|
||||
|
||||
@field:NotBlank(message = USER_FIRST_NAME_EMPTY_MESSAGE)
|
||||
val firstName: String,
|
||||
|
||||
@field:NotBlank(message = USER_LAST_NAME_EMPTY_MESSAGE)
|
||||
val lastName: String,
|
||||
|
||||
@field:NotBlank(message = USER_PASSWORD_EMPTY_MESSAGE)
|
||||
@field:Size(min = 8, message = USER_PASSWORD_TOO_SHORT_MESSAGE)
|
||||
val password: String,
|
||||
|
||||
val groupId: Long?,
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
val permissions: MutableSet<Permission> = mutableSetOf()
|
||||
) : EntityDto<User>
|
||||
|
||||
open class UserUpdateDto(
|
||||
@field:NotNull(message = USER_ID_NULL_MESSAGE)
|
||||
val id: Long,
|
||||
|
||||
@field:NullOrNotBlank(message = USER_FIRST_NAME_EMPTY_MESSAGE)
|
||||
val firstName: String?,
|
||||
|
||||
@field:NullOrNotBlank(message = USER_LAST_NAME_EMPTY_MESSAGE)
|
||||
val lastName: String?,
|
||||
|
||||
val groupId: Long?,
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
val permissions: Set<Permission>?
|
||||
) : EntityDto<User>
|
||||
|
||||
data class UserOutputDto(
|
||||
override val id: Long,
|
||||
val firstName: String,
|
||||
val lastName: String,
|
||||
val group: Group?,
|
||||
val permissions: Set<Permission>,
|
||||
val explicitPermissions: Set<Permission>,
|
||||
val lastLoginTime: LocalDateTime?
|
||||
) : Model
|
||||
|
||||
data class UserLoginRequest(val id: Long, val password: String)
|
||||
|
||||
// ==== DSL ====
|
||||
fun user(
|
||||
passwordEncoder: PasswordEncoder = BCryptPasswordEncoder(),
|
||||
id: Long = 0L,
|
||||
firstName: String = "firstName",
|
||||
lastName: String = "lastName",
|
||||
password: String = passwordEncoder.encode("password"),
|
||||
isDefaultGroupUser: Boolean = false,
|
||||
isSystemUser: Boolean = false,
|
||||
group: Group? = null,
|
||||
permissions: MutableSet<Permission> = mutableSetOf(),
|
||||
lastLoginTime: LocalDateTime? = null,
|
||||
op: User.() -> Unit = {}
|
||||
) = User(
|
||||
id,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
isDefaultGroupUser,
|
||||
isSystemUser,
|
||||
group,
|
||||
permissions,
|
||||
lastLoginTime
|
||||
).apply(op)
|
||||
|
||||
fun userSaveDto(
|
||||
passwordEncoder: PasswordEncoder = BCryptPasswordEncoder(),
|
||||
id: Long = 0L,
|
||||
firstName: String = "firstName",
|
||||
lastName: String = "lastName",
|
||||
password: String = passwordEncoder.encode("password"),
|
||||
groupId: Long? = null,
|
||||
permissions: MutableSet<Permission> = mutableSetOf(),
|
||||
op: UserSaveDto.() -> Unit = {}
|
||||
) = UserSaveDto(id, firstName, lastName, password, groupId, permissions).apply(op)
|
||||
|
||||
fun userUpdateDto(
|
||||
id: Long = 0L,
|
||||
firstName: String = "firstName",
|
||||
lastName: String = "lastName",
|
||||
groupId: Long? = null,
|
||||
permissions: MutableSet<Permission> = mutableSetOf(),
|
||||
op: UserUpdateDto.() -> Unit = {}
|
||||
) = UserUpdateDto(id, firstName, lastName, groupId, permissions).apply(op)
|
||||
|
||||
// ==== Exceptions ====
|
||||
private const val USER_NOT_FOUND_EXCEPTION_TITLE = "User not found"
|
||||
private const val USER_ALREADY_EXISTS_EXCEPTION_TITLE = "User already exists"
|
||||
private const val USER_EXCEPTION_ERROR_CODE = "user"
|
||||
|
||||
fun userIdNotFoundException(id: Long) =
|
||||
NotFoundException(
|
||||
USER_EXCEPTION_ERROR_CODE,
|
||||
USER_NOT_FOUND_EXCEPTION_TITLE,
|
||||
"An user with the id $id could not be found",
|
||||
id
|
||||
)
|
||||
|
||||
fun userIdAlreadyExistsException(id: Long) =
|
||||
AlreadyExistsException(
|
||||
USER_EXCEPTION_ERROR_CODE,
|
||||
USER_ALREADY_EXISTS_EXCEPTION_TITLE,
|
||||
"An user with the id $id already exists",
|
||||
id
|
||||
)
|
||||
|
||||
fun userFullNameAlreadyExistsException(firstName: String, lastName: String) =
|
||||
AlreadyExistsException(
|
||||
USER_EXCEPTION_ERROR_CODE,
|
||||
USER_ALREADY_EXISTS_EXCEPTION_TITLE,
|
||||
"An user with the name '$firstName $lastName' already exists",
|
||||
"$firstName $lastName",
|
||||
"fullName"
|
||||
)
|
|
@ -1,20 +1,20 @@
|
|||
package dev.fyloz.colorrecipesexplorer.repository
|
||||
|
||||
import dev.fyloz.colorrecipesexplorer.model.Employee
|
||||
import dev.fyloz.colorrecipesexplorer.model.EmployeeGroup
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.Group
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.User
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
interface EmployeeRepository : JpaRepository<Employee, Long> {
|
||||
interface UserRepository : JpaRepository<User, Long> {
|
||||
fun existsByFirstNameAndLastName(firstName: String, lastName: String): Boolean
|
||||
|
||||
fun findByFirstNameAndLastName(firstName: String, lastName: String): Employee?
|
||||
fun findByFirstNameAndLastName(firstName: String, lastName: String): User?
|
||||
|
||||
fun findAllByGroup(group: EmployeeGroup): Collection<Employee>
|
||||
fun findAllByGroup(group: Group): Collection<User>
|
||||
|
||||
fun findByIsDefaultGroupUserIsTrueAndGroupIs(group: EmployeeGroup): Employee
|
||||
fun findByIsDefaultGroupUserIsTrueAndGroupIs(group: Group): User
|
||||
}
|
||||
|
||||
@Repository
|
||||
interface EmployeeGroupRepository : NamedJpaRepository<EmployeeGroup>
|
||||
interface GroupRepository : NamedJpaRepository<Group>
|
||||
|
|
|
@ -3,9 +3,9 @@ package dev.fyloz.colorrecipesexplorer.rest
|
|||
import dev.fyloz.colorrecipesexplorer.config.annotations.PreAuthorizeEditUsers
|
||||
import dev.fyloz.colorrecipesexplorer.config.annotations.PreAuthorizeRemoveUsers
|
||||
import dev.fyloz.colorrecipesexplorer.config.annotations.PreAuthorizeViewUsers
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.service.EmployeeGroupService
|
||||
import dev.fyloz.colorrecipesexplorer.service.EmployeeService
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.*
|
||||
import dev.fyloz.colorrecipesexplorer.service.UserService
|
||||
import dev.fyloz.colorrecipesexplorer.service.GroupService
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
@ -14,29 +14,29 @@ import javax.servlet.http.HttpServletRequest
|
|||
import javax.servlet.http.HttpServletResponse
|
||||
import javax.validation.Valid
|
||||
|
||||
private const val EMPLOYEE_CONTROLLER_PATH = "api/employee"
|
||||
private const val EMPLOYEE_GROUP_CONTROLLER_PATH = "api/employee/group"
|
||||
private const val USER_CONTROLLER_PATH = "api/user"
|
||||
private const val GROUP_CONTROLLER_PATH = "api/user/group"
|
||||
|
||||
@RestController
|
||||
@RequestMapping(EMPLOYEE_CONTROLLER_PATH)
|
||||
class EmployeeController(private val employeeService: EmployeeService) {
|
||||
@RequestMapping(USER_CONTROLLER_PATH)
|
||||
class UserController(private val userService: UserService) {
|
||||
@GetMapping
|
||||
@PreAuthorizeViewUsers
|
||||
fun getAll() =
|
||||
ok(employeeService.getAllForOutput())
|
||||
ok(userService.getAllForOutput())
|
||||
|
||||
@GetMapping("{id}")
|
||||
@PreAuthorizeViewUsers
|
||||
fun getById(@PathVariable id: Long) =
|
||||
ok(employeeService.getByIdForOutput(id))
|
||||
ok(userService.getByIdForOutput(id))
|
||||
|
||||
@GetMapping("current")
|
||||
fun getCurrent(loggedInEmployee: Principal?) =
|
||||
if (loggedInEmployee != null)
|
||||
fun getCurrent(loggedInUser: Principal?) =
|
||||
if (loggedInUser != null)
|
||||
ok(
|
||||
with(employeeService) {
|
||||
with(userService) {
|
||||
getById(
|
||||
loggedInEmployee.name.toLong(),
|
||||
loggedInUser.name.toLong(),
|
||||
ignoreDefaultGroupUsers = false,
|
||||
ignoreSystemUsers = false
|
||||
).toOutput()
|
||||
|
@ -47,56 +47,56 @@ class EmployeeController(private val employeeService: EmployeeService) {
|
|||
|
||||
@PostMapping
|
||||
@PreAuthorizeEditUsers
|
||||
fun save(@Valid @RequestBody employee: EmployeeSaveDto) =
|
||||
created<EmployeeOutputDto>(EMPLOYEE_CONTROLLER_PATH) {
|
||||
with(employeeService) {
|
||||
save(employee).toOutput()
|
||||
fun save(@Valid @RequestBody user: UserSaveDto) =
|
||||
created<UserOutputDto>(USER_CONTROLLER_PATH) {
|
||||
with(userService) {
|
||||
save(user).toOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@PreAuthorizeEditUsers
|
||||
fun update(@Valid @RequestBody employee: EmployeeUpdateDto) =
|
||||
fun update(@Valid @RequestBody user: UserUpdateDto) =
|
||||
noContent {
|
||||
employeeService.update(employee)
|
||||
userService.update(user)
|
||||
}
|
||||
|
||||
@PutMapping("{id}/password", consumes = [MediaType.TEXT_PLAIN_VALUE])
|
||||
@PreAuthorizeEditUsers
|
||||
fun updatePassword(@PathVariable id: Long, @RequestBody password: String) =
|
||||
noContent {
|
||||
employeeService.updatePassword(id, password)
|
||||
userService.updatePassword(id, password)
|
||||
}
|
||||
|
||||
@PutMapping("{employeeId}/permissions/{permission}")
|
||||
@PutMapping("{userId}/permissions/{permission}")
|
||||
@PreAuthorizeEditUsers
|
||||
fun addPermission(
|
||||
@PathVariable employeeId: Long,
|
||||
@PathVariable permission: EmployeePermission
|
||||
@PathVariable userId: Long,
|
||||
@PathVariable permission: Permission
|
||||
) = noContent {
|
||||
employeeService.addPermission(employeeId, permission)
|
||||
userService.addPermission(userId, permission)
|
||||
}
|
||||
|
||||
@DeleteMapping("{employeeId}/permissions/{permission}")
|
||||
@DeleteMapping("{userId}/permissions/{permission}")
|
||||
@PreAuthorizeEditUsers
|
||||
fun removePermission(
|
||||
@PathVariable employeeId: Long,
|
||||
@PathVariable permission: EmployeePermission
|
||||
@PathVariable userId: Long,
|
||||
@PathVariable permission: Permission
|
||||
) = noContent {
|
||||
employeeService.removePermission(employeeId, permission)
|
||||
userService.removePermission(userId, permission)
|
||||
}
|
||||
|
||||
@DeleteMapping("{id}")
|
||||
@PreAuthorizeRemoveUsers
|
||||
fun deleteById(@PathVariable id: Long) =
|
||||
employeeService.deleteById(id)
|
||||
userService.deleteById(id)
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping(EMPLOYEE_GROUP_CONTROLLER_PATH)
|
||||
@RequestMapping(GROUP_CONTROLLER_PATH)
|
||||
class GroupsController(
|
||||
private val groupService: EmployeeGroupService,
|
||||
private val employeeService: EmployeeService
|
||||
private val groupService: GroupService,
|
||||
private val userService: UserService
|
||||
) {
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyAuthority('VIEW_RECIPES', 'VIEW_USERS')")
|
||||
|
@ -108,11 +108,11 @@ class GroupsController(
|
|||
fun getById(@PathVariable id: Long) =
|
||||
ok(groupService.getByIdForOutput(id))
|
||||
|
||||
@GetMapping("{id}/employees")
|
||||
@GetMapping("{id}/users")
|
||||
@PreAuthorizeViewUsers
|
||||
fun getEmployeesForGroup(@PathVariable id: Long) =
|
||||
ok(with(employeeService) {
|
||||
groupService.getEmployeesForGroup(id)
|
||||
fun getUsersForGroup(@PathVariable id: Long) =
|
||||
ok(with(userService) {
|
||||
groupService.getUsersForGroup(id)
|
||||
.map { it.toOutput() }
|
||||
})
|
||||
|
||||
|
@ -132,8 +132,8 @@ class GroupsController(
|
|||
|
||||
@PostMapping
|
||||
@PreAuthorizeEditUsers
|
||||
fun save(@Valid @RequestBody group: EmployeeGroupSaveDto) =
|
||||
created<EmployeeGroupOutputDto>(EMPLOYEE_GROUP_CONTROLLER_PATH) {
|
||||
fun save(@Valid @RequestBody group: GroupSaveDto) =
|
||||
created<GroupOutputDto>(GROUP_CONTROLLER_PATH) {
|
||||
with(groupService) {
|
||||
save(group).toOutput()
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ class GroupsController(
|
|||
|
||||
@PutMapping
|
||||
@PreAuthorizeEditUsers
|
||||
fun update(@Valid @RequestBody group: EmployeeGroupUpdateDto) =
|
||||
fun update(@Valid @RequestBody group: GroupUpdateDto) =
|
||||
noContent {
|
||||
groupService.update(group)
|
||||
}
|
||||
|
@ -156,10 +156,10 @@ class GroupsController(
|
|||
|
||||
@RestController
|
||||
@RequestMapping("api")
|
||||
class LogoutController(private val employeeService: EmployeeService) {
|
||||
class LogoutController(private val userService: UserService) {
|
||||
@GetMapping("logout")
|
||||
fun logout(request: HttpServletRequest) =
|
||||
ok<Void> {
|
||||
employeeService.logout(request)
|
||||
userService.logout(request)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,11 @@ package dev.fyloz.colorrecipesexplorer.service
|
|||
import dev.fyloz.colorrecipesexplorer.config.blacklistedJwtTokens
|
||||
import dev.fyloz.colorrecipesexplorer.config.defaultGroupCookieName
|
||||
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.*
|
||||
import dev.fyloz.colorrecipesexplorer.model.validation.or
|
||||
import dev.fyloz.colorrecipesexplorer.repository.EmployeeGroupRepository
|
||||
import dev.fyloz.colorrecipesexplorer.repository.EmployeeRepository
|
||||
import dev.fyloz.colorrecipesexplorer.repository.UserRepository
|
||||
import dev.fyloz.colorrecipesexplorer.repository.GroupRepository
|
||||
import org.springframework.context.annotation.Lazy
|
||||
import org.springframework.security.core.userdetails.User
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.security.core.userdetails.UserDetailsService
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException
|
||||
|
@ -19,73 +18,74 @@ import java.time.LocalDateTime
|
|||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
import javax.transaction.Transactional
|
||||
import org.springframework.security.core.userdetails.User as SpringUser
|
||||
|
||||
interface EmployeeService :
|
||||
ExternalModelService<Employee, EmployeeSaveDto, EmployeeUpdateDto, EmployeeOutputDto, EmployeeRepository> {
|
||||
/** Check if an [Employee] with the given [firstName] and [lastName] exists. */
|
||||
interface UserService :
|
||||
ExternalModelService<User, UserSaveDto, UserUpdateDto, UserOutputDto, UserRepository> {
|
||||
/** Check if an [User] with the given [firstName] and [lastName] exists. */
|
||||
fun existsByFirstNameAndLastName(firstName: String, lastName: String): Boolean
|
||||
|
||||
/** Gets the employee with the given [id]. */
|
||||
fun getById(id: Long, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): Employee
|
||||
/** Gets the user with the given [id]. */
|
||||
fun getById(id: Long, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): User
|
||||
|
||||
/** Gets all employees which have the given [group]. */
|
||||
fun getByGroup(group: EmployeeGroup): Collection<Employee>
|
||||
/** Gets all users which have the given [group]. */
|
||||
fun getByGroup(group: Group): Collection<User>
|
||||
|
||||
/** Gets the default user of the given [group]. */
|
||||
fun getDefaultGroupEmployee(group: EmployeeGroup): Employee
|
||||
fun getDefaultGroupUser(group: Group): User
|
||||
|
||||
/** Save a default group employee for the given [group]. */
|
||||
fun saveDefaultGroupEmployee(group: EmployeeGroup)
|
||||
/** Save a default group user for the given [group]. */
|
||||
fun saveDefaultGroupUser(group: Group)
|
||||
|
||||
/** Updates de given [entity]. **/
|
||||
fun update(entity: Employee, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): Employee
|
||||
fun update(entity: User, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): User
|
||||
|
||||
/** Updates the last login time of the employee with the given [employeeId]. */
|
||||
fun updateLastLoginTime(employeeId: Long, time: LocalDateTime = LocalDateTime.now()): Employee
|
||||
/** Updates the last login time of the user with the given [userId]. */
|
||||
fun updateLastLoginTime(userId: Long, time: LocalDateTime = LocalDateTime.now()): User
|
||||
|
||||
/** Updates the password of the employee with the given [id]. */
|
||||
fun updatePassword(id: Long, password: String): Employee
|
||||
/** Updates the password of the user with the given [id]. */
|
||||
fun updatePassword(id: Long, password: String): User
|
||||
|
||||
/** Adds the given [permission] to the employee with the given [employeeId]. */
|
||||
fun addPermission(employeeId: Long, permission: EmployeePermission): Employee
|
||||
/** Adds the given [permission] to the user with the given [userId]. */
|
||||
fun addPermission(userId: Long, permission: Permission): User
|
||||
|
||||
/** Removes the given [permission] from the employee with the given [employeeId]. */
|
||||
fun removePermission(employeeId: Long, permission: EmployeePermission): Employee
|
||||
/** Removes the given [permission] from the user with the given [userId]. */
|
||||
fun removePermission(userId: Long, permission: Permission): User
|
||||
|
||||
/** Logout an user. Add the authorization token of the given [request] to the blacklisted tokens. */
|
||||
fun logout(request: HttpServletRequest)
|
||||
}
|
||||
|
||||
interface EmployeeGroupService :
|
||||
ExternalNamedModelService<EmployeeGroup, EmployeeGroupSaveDto, EmployeeGroupUpdateDto, EmployeeGroupOutputDto, EmployeeGroupRepository> {
|
||||
/** Gets all the employees of the group with the given [id]. */
|
||||
fun getEmployeesForGroup(id: Long): Collection<Employee>
|
||||
interface GroupService :
|
||||
ExternalNamedModelService<Group, GroupSaveDto, GroupUpdateDto, GroupOutputDto, GroupRepository> {
|
||||
/** Gets all the users of the group with the given [id]. */
|
||||
fun getUsersForGroup(id: Long): Collection<User>
|
||||
|
||||
/** Gets the default group from a cookie in the given HTTP [request]. */
|
||||
fun getRequestDefaultGroup(request: HttpServletRequest): EmployeeGroup
|
||||
fun getRequestDefaultGroup(request: HttpServletRequest): Group
|
||||
|
||||
/** Sets the default group cookie for the given HTTP [response]. */
|
||||
fun setResponseDefaultGroup(groupId: Long, response: HttpServletResponse)
|
||||
}
|
||||
|
||||
interface EmployeeUserDetailsService : UserDetailsService {
|
||||
/** Loads an [User] for the given [employeeId]. */
|
||||
fun loadUserByEmployeeId(employeeId: Long, ignoreDefaultGroupUsers: Boolean = false): UserDetails
|
||||
interface CreUserDetailsService : UserDetailsService {
|
||||
/** Loads an [User] for the given [id]. */
|
||||
fun loadUserById(id: Long, ignoreDefaultGroupUsers: Boolean = false): UserDetails
|
||||
}
|
||||
|
||||
@Service
|
||||
class EmployeeServiceImpl(
|
||||
employeeRepository: EmployeeRepository,
|
||||
@Lazy val groupService: EmployeeGroupService,
|
||||
class UserServiceImpl(
|
||||
userRepository: UserRepository,
|
||||
@Lazy val groupService: GroupService,
|
||||
@Lazy val passwordEncoder: PasswordEncoder,
|
||||
) : AbstractExternalModelService<Employee, EmployeeSaveDto, EmployeeUpdateDto, EmployeeOutputDto, EmployeeRepository>(
|
||||
employeeRepository
|
||||
) : AbstractExternalModelService<User, UserSaveDto, UserUpdateDto, UserOutputDto, UserRepository>(
|
||||
userRepository
|
||||
),
|
||||
EmployeeService {
|
||||
override fun idNotFoundException(id: Long) = employeeIdNotFoundException(id)
|
||||
override fun idAlreadyExistsException(id: Long) = employeeIdAlreadyExistsException(id)
|
||||
UserService {
|
||||
override fun idNotFoundException(id: Long) = userIdNotFoundException(id)
|
||||
override fun idAlreadyExistsException(id: Long) = userIdAlreadyExistsException(id)
|
||||
|
||||
override fun Employee.toOutput() = EmployeeOutputDto(
|
||||
override fun User.toOutput() = UserOutputDto(
|
||||
this.id,
|
||||
this.firstName,
|
||||
this.lastName,
|
||||
|
@ -98,29 +98,29 @@ class EmployeeServiceImpl(
|
|||
override fun existsByFirstNameAndLastName(firstName: String, lastName: String): Boolean =
|
||||
repository.existsByFirstNameAndLastName(firstName, lastName)
|
||||
|
||||
override fun getAll(): Collection<Employee> =
|
||||
override fun getAll(): Collection<User> =
|
||||
super.getAll().filter { !it.isSystemUser && !it.isDefaultGroupUser }
|
||||
|
||||
override fun getById(id: Long): Employee =
|
||||
override fun getById(id: Long): User =
|
||||
getById(id, ignoreDefaultGroupUsers = true, ignoreSystemUsers = true)
|
||||
|
||||
override fun getById(id: Long, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): Employee =
|
||||
override fun getById(id: Long, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): User =
|
||||
super.getById(id).apply {
|
||||
if (ignoreSystemUsers && isSystemUser || ignoreDefaultGroupUsers && isDefaultGroupUser)
|
||||
throw idNotFoundException(id)
|
||||
}
|
||||
|
||||
override fun getByGroup(group: EmployeeGroup): Collection<Employee> =
|
||||
override fun getByGroup(group: Group): Collection<User> =
|
||||
repository.findAllByGroup(group).filter {
|
||||
!it.isSystemUser && !it.isDefaultGroupUser
|
||||
}
|
||||
|
||||
override fun getDefaultGroupEmployee(group: EmployeeGroup): Employee =
|
||||
override fun getDefaultGroupUser(group: Group): User =
|
||||
repository.findByIsDefaultGroupUserIsTrueAndGroupIs(group)
|
||||
|
||||
override fun save(entity: EmployeeSaveDto): Employee =
|
||||
override fun save(entity: UserSaveDto): User =
|
||||
save(with(entity) {
|
||||
Employee(
|
||||
User(
|
||||
id,
|
||||
firstName,
|
||||
lastName,
|
||||
|
@ -132,20 +132,20 @@ class EmployeeServiceImpl(
|
|||
)
|
||||
})
|
||||
|
||||
override fun save(entity: Employee): Employee {
|
||||
override fun save(entity: User): User {
|
||||
if (existsById(entity.id))
|
||||
throw employeeIdAlreadyExistsException(entity.id)
|
||||
throw userIdAlreadyExistsException(entity.id)
|
||||
if (existsByFirstNameAndLastName(entity.firstName, entity.lastName))
|
||||
throw employeeFullNameAlreadyExistsException(entity.firstName, entity.lastName)
|
||||
throw userFullNameAlreadyExistsException(entity.firstName, entity.lastName)
|
||||
return super<AbstractExternalModelService>.save(entity)
|
||||
}
|
||||
|
||||
override fun saveDefaultGroupEmployee(group: EmployeeGroup) {
|
||||
override fun saveDefaultGroupUser(group: Group) {
|
||||
save(
|
||||
employee(
|
||||
user(
|
||||
id = 1000000L + group.id!!,
|
||||
firstName = group.name,
|
||||
lastName = "EmployeeModel",
|
||||
lastName = "User",
|
||||
password = passwordEncoder.encode(group.name),
|
||||
group = group,
|
||||
isDefaultGroupUser = true
|
||||
|
@ -153,49 +153,49 @@ class EmployeeServiceImpl(
|
|||
)
|
||||
}
|
||||
|
||||
override fun updateLastLoginTime(employeeId: Long, time: LocalDateTime): Employee {
|
||||
val employee = getById(employeeId, ignoreDefaultGroupUsers = true, ignoreSystemUsers = false)
|
||||
employee.lastLoginTime = time
|
||||
override fun updateLastLoginTime(userId: Long, time: LocalDateTime): User {
|
||||
val user = getById(userId, ignoreDefaultGroupUsers = true, ignoreSystemUsers = false)
|
||||
user.lastLoginTime = time
|
||||
return update(
|
||||
employee,
|
||||
user,
|
||||
ignoreDefaultGroupUsers = true,
|
||||
ignoreSystemUsers = false
|
||||
)
|
||||
}
|
||||
|
||||
override fun update(entity: EmployeeUpdateDto): Employee {
|
||||
val persistedEmployee by lazy { getById(entity.id) }
|
||||
override fun update(entity: UserUpdateDto): User {
|
||||
val persistedUser by lazy { getById(entity.id) }
|
||||
return update(with(entity) {
|
||||
Employee(
|
||||
User(
|
||||
id = id,
|
||||
firstName = firstName or persistedEmployee.firstName,
|
||||
lastName = lastName or persistedEmployee.lastName,
|
||||
password = persistedEmployee.password,
|
||||
firstName = firstName or persistedUser.firstName,
|
||||
lastName = lastName or persistedUser.lastName,
|
||||
password = persistedUser.password,
|
||||
isDefaultGroupUser = false,
|
||||
isSystemUser = false,
|
||||
group = if (entity.groupId != null) groupService.getById(entity.groupId) else persistedEmployee.group,
|
||||
permissions = permissions?.toMutableSet() ?: persistedEmployee.permissions,
|
||||
lastLoginTime = persistedEmployee.lastLoginTime
|
||||
group = if (entity.groupId != null) groupService.getById(entity.groupId) else persistedUser.group,
|
||||
permissions = permissions?.toMutableSet() ?: persistedUser.permissions,
|
||||
lastLoginTime = persistedUser.lastLoginTime
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
override fun update(entity: Employee): Employee =
|
||||
override fun update(entity: User): User =
|
||||
update(entity, ignoreDefaultGroupUsers = true, ignoreSystemUsers = true)
|
||||
|
||||
override fun update(entity: Employee, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): Employee {
|
||||
override fun update(entity: User, ignoreDefaultGroupUsers: Boolean, ignoreSystemUsers: Boolean): User {
|
||||
with(repository.findByFirstNameAndLastName(entity.firstName, entity.lastName)) {
|
||||
if (this != null && id != entity.id)
|
||||
throw employeeFullNameAlreadyExistsException(entity.firstName, entity.lastName)
|
||||
throw userFullNameAlreadyExistsException(entity.firstName, entity.lastName)
|
||||
}
|
||||
|
||||
return super<AbstractExternalModelService>.update(entity)
|
||||
return super.update(entity)
|
||||
}
|
||||
|
||||
override fun updatePassword(id: Long, password: String): Employee {
|
||||
val persistedEmployee = getById(id, ignoreDefaultGroupUsers = true, ignoreSystemUsers = true)
|
||||
return super<AbstractExternalModelService>.update(with(persistedEmployee) {
|
||||
Employee(
|
||||
override fun updatePassword(id: Long, password: String): User {
|
||||
val persistedUser = getById(id, ignoreDefaultGroupUsers = true, ignoreSystemUsers = true)
|
||||
return super.update(with(persistedUser) {
|
||||
User(
|
||||
id,
|
||||
firstName,
|
||||
lastName,
|
||||
|
@ -209,11 +209,11 @@ class EmployeeServiceImpl(
|
|||
})
|
||||
}
|
||||
|
||||
override fun addPermission(employeeId: Long, permission: EmployeePermission): Employee =
|
||||
super<AbstractExternalModelService>.update(getById(employeeId).apply { permissions += permission })
|
||||
override fun addPermission(userId: Long, permission: Permission): User =
|
||||
super.update(getById(userId).apply { permissions += permission })
|
||||
|
||||
override fun removePermission(employeeId: Long, permission: EmployeePermission): Employee =
|
||||
super<AbstractExternalModelService>.update(getById(employeeId).apply { permissions -= permission })
|
||||
override fun removePermission(userId: Long, permission: Permission): User =
|
||||
super.update(getById(userId).apply { permissions -= permission })
|
||||
|
||||
override fun logout(request: HttpServletRequest) {
|
||||
val authorizationCookie = WebUtils.getCookie(request, "Authorization")
|
||||
|
@ -229,19 +229,19 @@ class EmployeeServiceImpl(
|
|||
const val defaultGroupCookieMaxAge = 10 * 365 * 24 * 60 * 60 // 10 ans
|
||||
|
||||
@Service
|
||||
class EmployeeGroupServiceImpl(
|
||||
private val employeeService: EmployeeService,
|
||||
employeeGroupRepository: EmployeeGroupRepository
|
||||
) : AbstractExternalNamedModelService<EmployeeGroup, EmployeeGroupSaveDto, EmployeeGroupUpdateDto, EmployeeGroupOutputDto, EmployeeGroupRepository>(
|
||||
employeeGroupRepository
|
||||
class GroupServiceImpl(
|
||||
private val userService: UserService,
|
||||
groupRepository: GroupRepository
|
||||
) : AbstractExternalNamedModelService<Group, GroupSaveDto, GroupUpdateDto, GroupOutputDto, GroupRepository>(
|
||||
groupRepository
|
||||
),
|
||||
EmployeeGroupService {
|
||||
override fun idNotFoundException(id: Long) = employeeGroupIdNotFoundException(id)
|
||||
override fun idAlreadyExistsException(id: Long) = employeeGroupIdAlreadyExistsException(id)
|
||||
override fun nameNotFoundException(name: String) = employeeGroupNameNotFoundException(name)
|
||||
override fun nameAlreadyExistsException(name: String) = employeeGroupNameAlreadyExistsException(name)
|
||||
GroupService {
|
||||
override fun idNotFoundException(id: Long) = groupIdNotFoundException(id)
|
||||
override fun idAlreadyExistsException(id: Long) = groupIdAlreadyExistsException(id)
|
||||
override fun nameNotFoundException(name: String) = groupNameNotFoundException(name)
|
||||
override fun nameAlreadyExistsException(name: String) = groupNameAlreadyExistsException(name)
|
||||
|
||||
override fun EmployeeGroup.toOutput() = EmployeeGroupOutputDto(
|
||||
override fun Group.toOutput() = GroupOutputDto(
|
||||
this.id!!,
|
||||
this.name,
|
||||
this.permissions,
|
||||
|
@ -249,20 +249,20 @@ class EmployeeGroupServiceImpl(
|
|||
)
|
||||
|
||||
override fun existsByName(name: String): Boolean = repository.existsByName(name)
|
||||
override fun getEmployeesForGroup(id: Long): Collection<Employee> =
|
||||
employeeService.getByGroup(getById(id))
|
||||
override fun getUsersForGroup(id: Long): Collection<User> =
|
||||
userService.getByGroup(getById(id))
|
||||
|
||||
@Transactional
|
||||
override fun save(entity: EmployeeGroup): EmployeeGroup {
|
||||
override fun save(entity: Group): Group {
|
||||
return super<AbstractExternalNamedModelService>.save(entity).apply {
|
||||
employeeService.saveDefaultGroupEmployee(this)
|
||||
userService.saveDefaultGroupUser(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(entity: EmployeeGroupUpdateDto): EmployeeGroup {
|
||||
override fun update(entity: GroupUpdateDto): Group {
|
||||
val persistedGroup by lazy { getById(entity.id) }
|
||||
return update(with(entity) {
|
||||
EmployeeGroup(
|
||||
Group(
|
||||
entity.id,
|
||||
if (name.isNotBlank()) entity.name else persistedGroup.name,
|
||||
if (permissions.isNotEmpty()) entity.permissions else persistedGroup.permissions
|
||||
|
@ -271,15 +271,15 @@ class EmployeeGroupServiceImpl(
|
|||
}
|
||||
|
||||
@Transactional
|
||||
override fun delete(entity: EmployeeGroup) {
|
||||
employeeService.delete(employeeService.getDefaultGroupEmployee(entity))
|
||||
override fun delete(entity: Group) {
|
||||
userService.delete(userService.getDefaultGroupUser(entity))
|
||||
super.delete(entity)
|
||||
}
|
||||
|
||||
override fun getRequestDefaultGroup(request: HttpServletRequest): EmployeeGroup {
|
||||
override fun getRequestDefaultGroup(request: HttpServletRequest): Group {
|
||||
val defaultGroupCookie = WebUtils.getCookie(request, defaultGroupCookieName)
|
||||
?: throw NoDefaultGroupException()
|
||||
val defaultGroupUser = employeeService.getById(
|
||||
val defaultGroupUser = userService.getById(
|
||||
defaultGroupCookie.value.toLong(),
|
||||
ignoreDefaultGroupUsers = false,
|
||||
ignoreSystemUsers = true
|
||||
|
@ -289,7 +289,7 @@ class EmployeeGroupServiceImpl(
|
|||
|
||||
override fun setResponseDefaultGroup(groupId: Long, response: HttpServletResponse) {
|
||||
val group = getById(groupId)
|
||||
val defaultGroupUser = employeeService.getDefaultGroupEmployee(group)
|
||||
val defaultGroupUser = userService.getDefaultGroupUser(group)
|
||||
response.addHeader(
|
||||
"Set-Cookie",
|
||||
"$defaultGroupCookieName=${defaultGroupUser.id}; Max-Age=${defaultGroupCookieMaxAge}; Path=/api; HttpOnly; Secure; SameSite=strict"
|
||||
|
@ -298,13 +298,13 @@ class EmployeeGroupServiceImpl(
|
|||
}
|
||||
|
||||
@Service
|
||||
class EmployeeUserDetailsServiceImpl(
|
||||
private val employeeService: EmployeeService
|
||||
class CreUserDetailsServiceImpl(
|
||||
private val userService: UserService
|
||||
) :
|
||||
EmployeeUserDetailsService {
|
||||
CreUserDetailsService {
|
||||
override fun loadUserByUsername(username: String): UserDetails {
|
||||
try {
|
||||
return loadUserByEmployeeId(username.toLong(), true)
|
||||
return loadUserById(username.toLong(), true)
|
||||
} catch (ex: NotFoundException) {
|
||||
throw UsernameNotFoundException(username)
|
||||
} catch (ex: NotFoundException) {
|
||||
|
@ -312,12 +312,12 @@ class EmployeeUserDetailsServiceImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override fun loadUserByEmployeeId(employeeId: Long, ignoreDefaultGroupUsers: Boolean): UserDetails {
|
||||
val employee = employeeService.getById(
|
||||
employeeId,
|
||||
override fun loadUserById(id: Long, ignoreDefaultGroupUsers: Boolean): UserDetails {
|
||||
val user = userService.getById(
|
||||
id,
|
||||
ignoreDefaultGroupUsers = ignoreDefaultGroupUsers,
|
||||
ignoreSystemUsers = false
|
||||
)
|
||||
return User(employee.id.toString(), employee.password, employee.authorities)
|
||||
return SpringUser(user.id.toString(), user.password, user.authorities)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package dev.fyloz.colorrecipesexplorer.service
|
||||
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.Group
|
||||
import dev.fyloz.colorrecipesexplorer.model.validation.or
|
||||
import dev.fyloz.colorrecipesexplorer.repository.RecipeRepository
|
||||
import dev.fyloz.colorrecipesexplorer.service.files.FileService
|
||||
|
@ -38,7 +39,7 @@ class RecipeServiceImpl(
|
|||
val companyService: CompanyService,
|
||||
val mixService: MixService,
|
||||
val recipeStepService: RecipeStepService,
|
||||
@Lazy val groupService: EmployeeGroupService,
|
||||
@Lazy val groupService: GroupService,
|
||||
val recipeImageService: RecipeImageService
|
||||
) :
|
||||
AbstractExternalModelService<Recipe, RecipeSaveDto, RecipeUpdateDto, RecipeOutputDto, RecipeRepository>(
|
||||
|
@ -157,7 +158,7 @@ class RecipeServiceImpl(
|
|||
if (publicDataDto.notes != null) {
|
||||
val recipe = getById(publicDataDto.recipeId)
|
||||
|
||||
fun noteForGroup(group: EmployeeGroup) =
|
||||
fun noteForGroup(group: Group) =
|
||||
publicDataDto.notes.firstOrNull { it.groupId == group.id }?.content
|
||||
|
||||
// Notes
|
||||
|
|
|
@ -2,6 +2,7 @@ package dev.fyloz.colorrecipesexplorer.service
|
|||
|
||||
import dev.fyloz.colorrecipesexplorer.exception.RestException
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.Group
|
||||
import dev.fyloz.colorrecipesexplorer.repository.RecipeStepRepository
|
||||
import dev.fyloz.colorrecipesexplorer.utils.findDuplicated
|
||||
import dev.fyloz.colorrecipesexplorer.utils.hasGaps
|
||||
|
@ -81,8 +82,8 @@ class InvalidStepsPositionsException(
|
|||
)
|
||||
|
||||
class InvalidGroupStepsPositionsException(
|
||||
val group: EmployeeGroup,
|
||||
val exception: InvalidStepsPositionsException
|
||||
val group: Group,
|
||||
val exception: InvalidStepsPositionsException
|
||||
) : RestException(
|
||||
"invalid-groupinformation-recipestep-position",
|
||||
"Invalid steps positions",
|
||||
|
|
|
@ -4,15 +4,14 @@ import com.nhaarman.mockitokotlin2.*
|
|||
import dev.fyloz.colorrecipesexplorer.config.defaultGroupCookieName
|
||||
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
|
||||
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.repository.EmployeeGroupRepository
|
||||
import dev.fyloz.colorrecipesexplorer.repository.EmployeeRepository
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.*
|
||||
import dev.fyloz.colorrecipesexplorer.repository.UserRepository
|
||||
import dev.fyloz.colorrecipesexplorer.repository.GroupRepository
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import org.springframework.mock.web.MockHttpServletResponse
|
||||
import org.springframework.security.core.userdetails.User
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
||||
import java.util.*
|
||||
|
@ -22,24 +21,25 @@ import kotlin.test.assertEquals
|
|||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
import org.springframework.security.core.userdetails.User as SpringUser
|
||||
|
||||
class EmployeeServiceTest :
|
||||
AbstractExternalModelServiceTest<Employee, EmployeeSaveDto, EmployeeUpdateDto, EmployeeService, EmployeeRepository>() {
|
||||
class UserServiceTest :
|
||||
AbstractExternalModelServiceTest<User, UserSaveDto, UserUpdateDto, UserService, UserRepository>() {
|
||||
private val passwordEncoder = BCryptPasswordEncoder()
|
||||
|
||||
override val entity: Employee = employee(passwordEncoder, id = 0L)
|
||||
override val anotherEntity: Employee = employee(passwordEncoder, id = 1L)
|
||||
private val entityDefaultGroupUser = employee(passwordEncoder, id = 2L, isDefaultGroupUser = true)
|
||||
private val entitySystemUser = employee(passwordEncoder, id = 3L, isSystemUser = true)
|
||||
private val group = employeeGroup(id = 0L)
|
||||
override val entitySaveDto: EmployeeSaveDto = spy(employeeSaveDto(passwordEncoder, id = 0L))
|
||||
override val entityUpdateDto: EmployeeUpdateDto = spy(employeeUpdateDto(id = 0L))
|
||||
override val entity: User = user(passwordEncoder, id = 0L)
|
||||
override val anotherEntity: User = user(passwordEncoder, id = 1L)
|
||||
private val entityDefaultGroupUser = user(passwordEncoder, id = 2L, isDefaultGroupUser = true)
|
||||
private val entitySystemUser = user(passwordEncoder, id = 3L, isSystemUser = true)
|
||||
private val group = group(id = 0L)
|
||||
override val entitySaveDto: UserSaveDto = spy(userSaveDto(passwordEncoder, id = 0L))
|
||||
override val entityUpdateDto: UserUpdateDto = spy(userUpdateDto(id = 0L))
|
||||
|
||||
override val repository: EmployeeRepository = mock()
|
||||
private val employeeGroupService: EmployeeGroupService = mock()
|
||||
override val service: EmployeeService = spy(EmployeeServiceImpl(repository, employeeGroupService, passwordEncoder))
|
||||
override val repository: UserRepository = mock()
|
||||
private val groupService: GroupService = mock()
|
||||
override val service: UserService = spy(UserServiceImpl(repository, groupService, passwordEncoder))
|
||||
|
||||
private val entitySaveDtoEmployee = Employee(
|
||||
private val entitySaveDtoUser = User(
|
||||
entitySaveDto.id,
|
||||
entitySaveDto.firstName,
|
||||
entitySaveDto.lastName,
|
||||
|
@ -52,14 +52,14 @@ class EmployeeServiceTest :
|
|||
|
||||
@AfterEach
|
||||
override fun afterEach() {
|
||||
reset(employeeGroupService)
|
||||
reset(groupService)
|
||||
super.afterEach()
|
||||
}
|
||||
|
||||
// existsByFirstNameAndLastName()
|
||||
|
||||
@Test
|
||||
fun `existsByFirstNameAndLastName() returns true when an employee with the given first name and last name exists`() {
|
||||
fun `existsByFirstNameAndLastName() returns true when an user with the given first name and last name exists`() {
|
||||
whenever(repository.existsByFirstNameAndLastName(entity.firstName, entity.lastName)).doReturn(true)
|
||||
|
||||
val found = service.existsByFirstNameAndLastName(entity.firstName, entity.lastName)
|
||||
|
@ -68,7 +68,7 @@ class EmployeeServiceTest :
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `existsByFirstNameAndLastName() returns false when no employee with the given first name and last name exists`() {
|
||||
fun `existsByFirstNameAndLastName() returns false when no user with the given first name and last name exists`() {
|
||||
whenever(repository.existsByFirstNameAndLastName(entity.firstName, entity.lastName)).doReturn(false)
|
||||
|
||||
val found = service.existsByFirstNameAndLastName(entity.firstName, entity.lastName)
|
||||
|
@ -79,7 +79,7 @@ class EmployeeServiceTest :
|
|||
// getById()
|
||||
|
||||
@Test
|
||||
fun `getById() throws NotFoundException when the corresponding employee is a default group user`() {
|
||||
fun `getById() throws NotFoundException when the corresponding user is a default group user`() {
|
||||
whenever(repository.findById(entityDefaultGroupUser.id)).doReturn(Optional.of(entityDefaultGroupUser))
|
||||
|
||||
assertThrows<NotFoundException> {
|
||||
|
@ -92,7 +92,7 @@ class EmployeeServiceTest :
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `getById() throws NotFoundException when the corresponding employee is a system user`() {
|
||||
fun `getById() throws NotFoundException when the corresponding user is a system user`() {
|
||||
whenever(repository.findById(entitySystemUser.id)).doReturn(Optional.of(entitySystemUser))
|
||||
|
||||
assertThrows<NotFoundException> {
|
||||
|
@ -107,7 +107,7 @@ class EmployeeServiceTest :
|
|||
// getByGroup()
|
||||
|
||||
@Test
|
||||
fun `getByGroup() returns all the employees with the given group from the repository`() {
|
||||
fun `getByGroup() returns all the users with the given group from the repository`() {
|
||||
whenever(repository.findAllByGroup(group)).doReturn(entityList)
|
||||
|
||||
val found = service.getByGroup(group)
|
||||
|
@ -117,7 +117,7 @@ class EmployeeServiceTest :
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `getByGroup() returns an empty list when there is no employee with the given group in the repository`() {
|
||||
fun `getByGroup() returns an empty list when there is no user with the given group in the repository`() {
|
||||
whenever(repository.findAllByGroup(group)).doReturn(listOf())
|
||||
|
||||
val found = service.getByGroup(group)
|
||||
|
@ -128,10 +128,10 @@ class EmployeeServiceTest :
|
|||
// getDefaultGroupUser()
|
||||
|
||||
@Test
|
||||
fun `getDefaultGroupUser() returns the default employee of the given group from the repository`() {
|
||||
fun `getDefaultGroupUser() returns the default user of the given group from the repository`() {
|
||||
whenever(repository.findByIsDefaultGroupUserIsTrueAndGroupIs(group)).doReturn(entityDefaultGroupUser)
|
||||
|
||||
val found = service.getDefaultGroupEmployee(group)
|
||||
val found = service.getDefaultGroupUser(group)
|
||||
|
||||
assertEquals(entityDefaultGroupUser, found)
|
||||
}
|
||||
|
@ -166,13 +166,13 @@ class EmployeeServiceTest :
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `save(dto) calls and returns save() with the created employee`() {
|
||||
doReturn(entitySaveDtoEmployee).whenever(service).save(any<Employee>())
|
||||
fun `save(dto) calls and returns save() with the created user`() {
|
||||
doReturn(entitySaveDtoUser).whenever(service).save(any<User>())
|
||||
|
||||
val found = service.save(entitySaveDto)
|
||||
|
||||
verify(service).save(argThat<Employee> { this.id == entity.id && this.firstName == entity.firstName && this.lastName == entity.lastName })
|
||||
assertEquals(entitySaveDtoEmployee, found)
|
||||
verify(service).save(argThat<User> { this.id == entity.id && this.firstName == entity.firstName && this.lastName == entity.lastName })
|
||||
assertEquals(entitySaveDtoUser, found)
|
||||
}
|
||||
|
||||
// update()
|
||||
|
@ -182,7 +182,7 @@ class EmployeeServiceTest :
|
|||
withBaseUpdateDtoTest(entity, entityUpdateDto, service, { any() })
|
||||
|
||||
@Test
|
||||
fun `update() throws AlreadyExistsException when a different employee with the given first name and last name exists`() {
|
||||
fun `update() throws AlreadyExistsException when a different user with the given first name and last name exists`() {
|
||||
whenever(repository.findByFirstNameAndLastName(entity.firstName, entity.lastName)).doReturn(
|
||||
entityDefaultGroupUser
|
||||
)
|
||||
|
@ -198,47 +198,47 @@ class EmployeeServiceTest :
|
|||
}
|
||||
}
|
||||
|
||||
class EmployeeGroupServiceTest :
|
||||
AbstractExternalNamedModelServiceTest<EmployeeGroup, EmployeeGroupSaveDto, EmployeeGroupUpdateDto, EmployeeGroupService, EmployeeGroupRepository>() {
|
||||
private val employeeService: EmployeeService = mock()
|
||||
override val repository: EmployeeGroupRepository = mock()
|
||||
override val service: EmployeeGroupServiceImpl = spy(EmployeeGroupServiceImpl(employeeService, repository))
|
||||
class GroupServiceTest :
|
||||
AbstractExternalNamedModelServiceTest<Group, GroupSaveDto, GroupUpdateDto, GroupService, GroupRepository>() {
|
||||
private val userService: UserService = mock()
|
||||
override val repository: GroupRepository = mock()
|
||||
override val service: GroupServiceImpl = spy(GroupServiceImpl(userService, repository))
|
||||
|
||||
override val entity: EmployeeGroup = employeeGroup(id = 0L, name = "group")
|
||||
override val anotherEntity: EmployeeGroup = employeeGroup(id = 1L, name = "another group")
|
||||
override val entitySaveDto: EmployeeGroupSaveDto = spy(employeeGroupSaveDto(name = "group"))
|
||||
override val entityUpdateDto: EmployeeGroupUpdateDto = spy(employeeGroupUpdateDto(id = 0L, name = "group"))
|
||||
override val entityWithEntityName: EmployeeGroup = employeeGroup(id = 2L, name = entity.name)
|
||||
override val entity: Group = group(id = 0L, name = "group")
|
||||
override val anotherEntity: Group = group(id = 1L, name = "another group")
|
||||
override val entitySaveDto: GroupSaveDto = spy(groupSaveDto(name = "group"))
|
||||
override val entityUpdateDto: GroupUpdateDto = spy(groupUpdateDto(id = 0L, name = "group"))
|
||||
override val entityWithEntityName: Group = group(id = 2L, name = entity.name)
|
||||
|
||||
private val groupEmployeeId = 1000000L + entity.id!!
|
||||
private val groupEmployee = employee(BCryptPasswordEncoder(), id = groupEmployeeId, group = entity)
|
||||
private val groupUserId = 1000000L + entity.id!!
|
||||
private val groupUser = user(BCryptPasswordEncoder(), id = groupUserId, group = entity)
|
||||
|
||||
@BeforeEach
|
||||
override fun afterEach() {
|
||||
reset(employeeService)
|
||||
reset(userService)
|
||||
super.afterEach()
|
||||
}
|
||||
|
||||
// getEmployeesForGroup()
|
||||
// getUsersForGroup()
|
||||
|
||||
@Test
|
||||
fun `getEmployeesForGroup() returns all employees in the given group`() {
|
||||
val group = employeeGroup(id = 1L)
|
||||
fun `getUsersForGroup() returns all users in the given group`() {
|
||||
val group = group(id = 1L)
|
||||
|
||||
doReturn(group).whenever(service).getById(group.id!!)
|
||||
whenever(employeeService.getByGroup(group)).doReturn(listOf(groupEmployee))
|
||||
whenever(userService.getByGroup(group)).doReturn(listOf(groupUser))
|
||||
|
||||
val found = service.getEmployeesForGroup(group.id!!)
|
||||
val found = service.getUsersForGroup(group.id!!)
|
||||
|
||||
assertTrue(found.contains(groupEmployee))
|
||||
assertTrue(found.contains(groupUser))
|
||||
assertTrue(found.size == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getEmployeesForGroup() returns empty collection when the given group contains any employee`() {
|
||||
fun `getUsersForGroup() returns empty collection when the given group contains any user`() {
|
||||
doReturn(entity).whenever(service).getById(entity.id!!)
|
||||
|
||||
val found = service.getEmployeesForGroup(entity.id!!)
|
||||
val found = service.getUsersForGroup(entity.id!!)
|
||||
|
||||
assertTrue(found.isEmpty())
|
||||
}
|
||||
|
@ -247,11 +247,11 @@ class EmployeeGroupServiceTest :
|
|||
|
||||
@Test
|
||||
fun `getRequestDefaultGroup() returns the group contained in the cookie of the HTTP request`() {
|
||||
val cookies: Array<Cookie> = arrayOf(Cookie(defaultGroupCookieName, groupEmployeeId.toString()))
|
||||
val cookies: Array<Cookie> = arrayOf(Cookie(defaultGroupCookieName, groupUserId.toString()))
|
||||
val request: HttpServletRequest = mock()
|
||||
|
||||
whenever(request.cookies).doReturn(cookies)
|
||||
whenever(employeeService.getById(eq(groupEmployeeId), any(), any())).doReturn(groupEmployee)
|
||||
whenever(userService.getById(eq(groupUserId), any(), any())).doReturn(groupUser)
|
||||
|
||||
val found = service.getRequestDefaultGroup(request)
|
||||
|
||||
|
@ -273,7 +273,7 @@ class EmployeeGroupServiceTest :
|
|||
fun `setResponseDefaultGroup() the default group cookie has been added to the given HTTP response with the given group id`() {
|
||||
val response = MockHttpServletResponse()
|
||||
|
||||
whenever(employeeService.getDefaultGroupEmployee(entity)).doReturn(groupEmployee)
|
||||
whenever(userService.getDefaultGroupUser(entity)).doReturn(groupUser)
|
||||
doReturn(entity).whenever(service).getById(entity.id!!)
|
||||
|
||||
service.setResponseDefaultGroup(entity.id!!, response)
|
||||
|
@ -281,7 +281,7 @@ class EmployeeGroupServiceTest :
|
|||
|
||||
assertNotNull(found)
|
||||
assertEquals(defaultGroupCookieName, found.name)
|
||||
assertEquals(groupEmployeeId.toString(), found.value)
|
||||
assertEquals(groupUserId.toString(), found.value)
|
||||
assertEquals(defaultGroupCookieMaxAge, found.maxAge)
|
||||
assertTrue(found.isHttpOnly)
|
||||
assertTrue(found.secure)
|
||||
|
@ -301,48 +301,48 @@ class EmployeeGroupServiceTest :
|
|||
withBaseUpdateDtoTest(entity, entityUpdateDto, service, { any() })
|
||||
}
|
||||
|
||||
class EmployeeUserDetailsServiceTest {
|
||||
private val employeeService: EmployeeService = mock()
|
||||
private val service = spy(EmployeeUserDetailsServiceImpl(employeeService))
|
||||
class UserUserDetailsServiceTest {
|
||||
private val userService: UserService = mock()
|
||||
private val service = spy(CreUserDetailsServiceImpl(userService))
|
||||
|
||||
private val employee = employee(id = 0L)
|
||||
private val user = user(id = 0L)
|
||||
|
||||
@BeforeEach
|
||||
fun beforeEach() {
|
||||
reset(employeeService, service)
|
||||
reset(userService, service)
|
||||
}
|
||||
|
||||
// loadUserByUsername()
|
||||
|
||||
@Test
|
||||
fun `loadUserByUsername() calls loadUserByEmployeeId() with the given username as an id`() {
|
||||
whenever(employeeService.getById(eq(employee.id), any(), any())).doReturn(employee)
|
||||
doReturn(User(employee.id.toString(), employee.password, listOf())).whenever(service)
|
||||
.loadUserByEmployeeId(employee.id)
|
||||
fun `loadUserByUsername() calls loadUserByUserId() with the given username as an id`() {
|
||||
whenever(userService.getById(eq(user.id), any(), any())).doReturn(user)
|
||||
doReturn(SpringUser(user.id.toString(), user.password, listOf())).whenever(service)
|
||||
.loadUserById(user.id)
|
||||
|
||||
service.loadUserByUsername(employee.id.toString())
|
||||
service.loadUserByUsername(user.id.toString())
|
||||
|
||||
verify(service).loadUserByEmployeeId(eq(employee.id), any())
|
||||
verify(service).loadUserById(eq(user.id), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `loadUserByUsername() throws UsernameNotFoundException when no employee with the given id exists`() {
|
||||
whenever(employeeService.getById(eq(employee.id), any(), any())).doThrow(
|
||||
employeeIdNotFoundException(employee.id)
|
||||
fun `loadUserByUsername() throws UsernameNotFoundException when no user with the given id exists`() {
|
||||
whenever(userService.getById(eq(user.id), any(), any())).doThrow(
|
||||
userIdNotFoundException(user.id)
|
||||
)
|
||||
|
||||
assertThrows<UsernameNotFoundException> { service.loadUserByUsername(employee.id.toString()) }
|
||||
assertThrows<UsernameNotFoundException> { service.loadUserByUsername(user.id.toString()) }
|
||||
}
|
||||
|
||||
// loadUserByEmployeeId
|
||||
// loadUserByUserId
|
||||
|
||||
@Test
|
||||
fun `loadUserByEmployeeId() returns an User corresponding to the employee with the given id`() {
|
||||
whenever(employeeService.getById(eq(employee.id), any(), any())).doReturn(employee)
|
||||
fun `loadUserByUserId() returns an User corresponding to the user with the given id`() {
|
||||
whenever(userService.getById(eq(user.id), any(), any())).doReturn(user)
|
||||
|
||||
val found = service.loadUserByEmployeeId(employee.id)
|
||||
val found = service.loadUserById(user.id)
|
||||
|
||||
assertEquals(employee.id, found.username.toLong())
|
||||
assertEquals(employee.password, found.password)
|
||||
assertEquals(user.id, found.username.toLong())
|
||||
assertEquals(user.password, found.password)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package dev.fyloz.colorrecipesexplorer.service
|
|||
import com.nhaarman.mockitokotlin2.*
|
||||
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.group
|
||||
import dev.fyloz.colorrecipesexplorer.repository.RecipeRepository
|
||||
import dev.fyloz.colorrecipesexplorer.service.files.FileService
|
||||
import io.mockk.*
|
||||
|
@ -21,7 +22,7 @@ class RecipeServiceTest :
|
|||
override val repository: RecipeRepository = mock()
|
||||
private val companyService: CompanyService = mock()
|
||||
private val mixService: MixService = mock()
|
||||
private val groupService: EmployeeGroupService = mock()
|
||||
private val groupService: GroupService = mock()
|
||||
private val recipeStepService: RecipeStepService = mock()
|
||||
override val service: RecipeService =
|
||||
spy(RecipeServiceImpl(repository, companyService, mixService, recipeStepService, groupService, mock()))
|
||||
|
@ -129,9 +130,9 @@ class RecipeServiceTest :
|
|||
fun `updatePublicData() updates the notes of a recipe groups information according to the RecipePublicDataDto`() {
|
||||
val recipe = recipe(
|
||||
id = 0L, groupsInformation = setOf(
|
||||
recipeGroupInformation(id = 0L, group = employeeGroup(id = 1L), note = "Old note"),
|
||||
recipeGroupInformation(id = 1L, group = employeeGroup(id = 2L), note = "Another note"),
|
||||
recipeGroupInformation(id = 2L, group = employeeGroup(id = 3L), note = "Up to date note")
|
||||
recipeGroupInformation(id = 0L, group = group(id = 1L), note = "Old note"),
|
||||
recipeGroupInformation(id = 1L, group = group(id = 2L), note = "Another note"),
|
||||
recipeGroupInformation(id = 2L, group = group(id = 3L), note = "Up to date note")
|
||||
)
|
||||
)
|
||||
val notes = setOf(
|
||||
|
|
|
@ -2,6 +2,7 @@ package dev.fyloz.colorrecipesexplorer.service
|
|||
|
||||
import com.nhaarman.mockitokotlin2.*
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.model.account.group
|
||||
import dev.fyloz.colorrecipesexplorer.repository.RecipeStepRepository
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
|
@ -80,7 +81,7 @@ class RecipeStepServiceTest :
|
|||
|
||||
private fun withGroupInformation(steps: MutableSet<RecipeStep>? = null, test: RecipeGroupInformation.() -> Unit) {
|
||||
recipeGroupInformation(
|
||||
group = employeeGroup(id = 0L),
|
||||
group = group(id = 0L),
|
||||
steps = steps ?: mutableSetOf(
|
||||
recipeStep(id = 0L, position = 1),
|
||||
recipeStep(id = 1L, position = 2),
|
||||
|
|
Loading…
Reference in New Issue