Skip to content

Commit

Permalink
register user auto-inject create user and update user
Browse files Browse the repository at this point in the history
  • Loading branch information
cgglyle committed Feb 24, 2024
1 parent 8eb78a8 commit 4d45140
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import jakarta.validation.constraints.NotBlank
import org.hibernate.validator.constraints.Length
import top.cgglyle.boson.security.authorization.RID
import top.cgglyle.boson.security.common.Expiration
import top.cgglyle.boson.security.common.UID
import java.io.Serializable

/**
Expand All @@ -34,5 +35,6 @@ data class CreateAccountDto(
val roles: Set<RID> = mutableSetOf(),
val expiration: Expiration = Expiration.NEVER,
val locked: Boolean = false,
val enable: Boolean = true
val enable: Boolean = true,
val uid: UID? = null,
) : Serializable
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import jakarta.validation.constraints.Max
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Size
import top.cgglyle.boson.security.common.Expiration
import top.cgglyle.boson.security.common.UID

data class CreateAccountQuery(
@Max(64)
Expand All @@ -36,4 +37,5 @@ data class CreateAccountQuery(
val locked: Boolean = false,
val accountExpiration: Expiration = Expiration.NEVER,
val credentialExpiration: Expiration = Expiration.NEVER,
val uid: UID? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ import java.util.*

@Entity
@Table(name = "sys_account")
class Account(command: CreateAccountCommand) : AbstractModifiedAuditingEntity() {
class Account(
command: CreateAccountCommand,
@Embedded
@AttributeOverride(
name = "value",
column = Column(name = "uid", updatable = false, nullable = false, unique = true)
)
val uid: UID = UID.randomUID()
) : AbstractModifiedAuditingEntity() {

@NotBlank
@Length(max = 64)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import top.cgglyle.boson.security.account.domain.AccountRepository
import top.cgglyle.boson.security.common.UID
import top.cgglyle.boson.security.common.UsernameFindable
import top.cgglyle.boson.security.exception.DataNotFoundException
import top.cgglyle.boson.security.exception.IllegalArgumentException

/**
* @author: Lyle Liu
Expand Down Expand Up @@ -65,7 +66,23 @@ class AccountService(
if (existUid(uid)) Unit else throw DataNotFoundException("Uid: $uid not found!")

override fun save(accountDto: CreateAccountDto): UID {
val newAccount = Account(
val newAccount = if (accountDto.uid == null) {
createAccount(accountDto)
} else createAccountUseUid(accountDto)
val account = accountRepository.save(newAccount)
return account.uid
}

override fun delete(uid: UID) {
accountRepository.deleteByUid(uid)
}

override fun findNameByUid(uid: UID): String? {
return findByUid(uid)?.username
}

private fun createAccount(accountDto: CreateAccountDto): Account {
return Account(
CreateAccountCommand(
accountDto.username,
accountDto.email,
Expand All @@ -75,15 +92,22 @@ class AccountService(
accountDto.enable
)
)
val account = accountRepository.save(newAccount)
return account.uid
}

override fun delete(uid: UID) {
accountRepository.deleteByUid(uid)
}

override fun findNameByUid(uid: UID): String? {
return findByUid(uid)?.username
private fun createAccountUseUid(accountDto: CreateAccountDto): Account {
if (accountDto.uid == null) {
throw IllegalArgumentException("uid must not be null!")
}
return Account(
CreateAccountCommand(
accountDto.username,
accountDto.email,
accountDto.roles,
accountDto.expiration,
accountDto.locked,
accountDto.enable
),
accountDto.uid,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ object CurrentLoginUidUtil {

private fun getAnonymousUid(authentication: Authentication): UID {
return when (authentication) {
is SystemAuthenticationToken -> {
is OnceAuthenticationToken -> {
val (uid) = authentication.principal as UidDetailUser
return uid
}

is AnonymousAuthenticationToken -> {
UID(authentication.toString())
UID(authentication.name)
}

else -> {
Expand All @@ -70,11 +70,9 @@ object CurrentLoginUidUtil {

private fun getUid(uidDetailUser: UidDetailUser) = uidDetailUser.uid

fun newSystemAuthenticationToken(): SystemAuthenticationToken {
fun newSystemAuthenticationToken(): OnceAuthenticationToken {
val systemUserDetail = createSystemUserDetail()
return SystemAuthenticationToken(
systemUserDetail.hashCode().toString(), systemUserDetail, systemUserDetail.authorities
)
return OnceAuthenticationToken(systemUserDetail)
}

private fun createSystemUserDetail(): UidDetailUser {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
package top.cgglyle.boson.security.auth

import org.springframework.security.authentication.AnonymousAuthenticationToken
import org.springframework.security.core.GrantedAuthority

class SystemAuthenticationToken(
key: String, principal: Any,
authorities: MutableCollection<out GrantedAuthority>?
) : AnonymousAuthenticationToken(key, principal, authorities)
class OnceAuthenticationToken(
userDetails: UidDetailUser,
) : AnonymousAuthenticationToken(userDetails.hashCode().toString(), userDetails, userDetails.authorities)
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ class UserService(
rids,
query.accountExpiration,
query.locked,
query.enable
query.enable,
query.uid,
)
)

Expand Down
32 changes: 30 additions & 2 deletions src/main/kotlin/top/cgglyle/boson/security/web/AuthController.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
package top.cgglyle.boson.security.web

import jakarta.validation.Valid
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.http.MediaType
import org.springframework.security.core.CredentialsContainer
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.User
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
import top.cgglyle.boson.security.account.CreateAccountQuery
import top.cgglyle.boson.security.auth.AuthUserManager
import top.cgglyle.boson.security.auth.OnceAuthenticationToken
import top.cgglyle.boson.security.auth.UidDetailUser
import top.cgglyle.boson.security.common.UID
import top.cgglyle.boson.security.exception.IllegalArgumentException
import top.cgglyle.boson.security.web.query.LoginQuery
import top.cgglyle.boson.security.web.query.RegisterQuery
import java.security.Principal

@RestController
@RequestMapping("/api")
Expand All @@ -22,11 +29,17 @@ class AuthController(
) {

@PostMapping("register")
fun createUser(@Valid @RequestBody query: RegisterQuery): UID {
fun createUser(@Valid @RequestBody query: RegisterQuery, principal: Principal?): UID {
if (query.email == null && query.username == null) throw IllegalArgumentException("Both username and password must not be null!")
val uid: UID? = if (principal == null) {
logger.info("[Register User] Current login user is null!")
val randomUID = UID.randomUID()
createOnceAuthenticationToken(query.username!!, randomUID)
randomUID
} else null
return authUserManager.createUser(
CreateAccountQuery(
query.username, query.email, query.password, setOf()
query.username, query.email, query.password, setOf(), uid = uid,
)
)
}
Expand All @@ -46,4 +59,19 @@ class AuthController(
credentialsContainer.eraseCredentials()
return userDetails
}

private fun createOnceAuthenticationToken(username: String, uid: UID) {
val userDetails = User.withUsername(username)
.password("")
.authorities(SimpleGrantedAuthority("USER"))
.build()
val uidDetails = UidDetailUser(uid, userDetails)
val onceAuthenticationToken = OnceAuthenticationToken(uidDetails)
val contextHolderStrategy = SecurityContextHolder.getContextHolderStrategy()
contextHolderStrategy.context.authentication = onceAuthenticationToken
}

companion object {
private val logger: Logger = LoggerFactory.getLogger(AuthController::class.java)
}
}

0 comments on commit 4d45140

Please sign in to comment.