合并token校验逻辑

社团注册表增加创建人
社团注册逻辑完善
master
pan 4 years ago
parent 1b5c6cb58a
commit 9fe8fcad7b
  1. 38
      src/Controller.kt
  2. 4
      src/Dao.kt
  3. 48
      src/Service.kt
  4. 31
      src/Vo.kt
  5. 2
      test/ApplicationTest.kt

@ -6,9 +6,9 @@ import io.ktor.request.*
import io.ktor.response.* import io.ktor.response.*
import io.ktor.routing.* import io.ktor.routing.*
suspend inline fun <reified T : BaseVo> withToken(call: ApplicationCall, callback: (vo: T) -> Unit) { suspend inline fun <reified T : ClientBaseVo> withToken(call: ApplicationCall, callback: (vo: T) -> Unit) {
val levelVo = call.receive<T>() val levelVo = call.receive<T>()
if (AccountService.validToken(levelVo.token)) { if (AccountService.validToken(levelVo)) {
callback(levelVo) callback(levelVo)
} else { } else {
call.respond(Simple.error("token校验失败")) call.respond(Simple.error("token校验失败"))
@ -52,7 +52,7 @@ fun Application.AccountController() {
//TODO 封装前后台登录逻辑 //TODO 封装前后台登录逻辑
route(path = "/login") { route(path = "/login") {
route(path = ReceiverType.Foreground.name.toLowerCase()){ route(path = ClientType.Foreground.name.toLowerCase()){
post { post {
val userLoginVo = call.receive<UserLoginVo>() val userLoginVo = call.receive<UserLoginVo>()
val token = AccountService.login(userLoginVo, call.request.host()) val token = AccountService.login(userLoginVo, call.request.host())
@ -60,12 +60,12 @@ fun Application.AccountController() {
} }
post("/token"){ post("/token"){
val tokenVo = call.receive<Token>() val tokenVo = call.receive<Token>()
val isValid = AccountService.validToken(tokenVo) val isValid = AccountService.validUserToken(tokenVo)
call.respond(ApiResponse(message = if (isValid) "令牌合法" else "令牌不合法", body = isValid)) call.respond(ApiResponse(message = if (isValid) "令牌合法" else "令牌不合法", body = isValid))
} }
} }
route(path = ReceiverType.Background.name.toLowerCase()){ route(path = ClientType.Background.name.toLowerCase()){
post{ post{
val managerLoginVo = call.receive<ManagerLoginVo>() val managerLoginVo = call.receive<ManagerLoginVo>()
val token = AccountService.login(managerLoginVo, call.request.host()) val token = AccountService.login(managerLoginVo, call.request.host())
@ -83,9 +83,9 @@ fun Application.AccountController() {
post(path = "/logout") { post(path = "/logout") {
environment.log.info("退出登录") environment.log.info("退出登录")
val userLogoutVo = call.receive<UserLogoutVo>() val onlyToken = call.receive<OnlyToken>()
environment.log.info("$userLogoutVo") environment.log.info("$onlyToken")
val flag = AccountService.logout(userLogoutVo.userId) val flag = AccountService.logout(onlyToken)
call.respond(ApiResponse(message = if (flag) "退出成功" else "退出失败", body = flag)) call.respond(ApiResponse(message = if (flag) "退出成功" else "退出失败", body = flag))
} }
} }
@ -146,8 +146,16 @@ fun Application.AssociationController() {
} }
post("/register"){ post("/register"){
withToken<RegAssociationVo>(call = call){ withToken<RegAssociationVo>(call = call){
val flag=AssociationService.register(vo=it) try {
call.respond(ApiResponse(message = if(flag) "社团注册资料已保存,请等待受理" else "社团注册资料保存失败",body=flag)) val flag=AssociationService.register(vo=it)
call.respond(ApiResponse(message = if(flag) "社团注册资料已提交,请等待受理" else "社团注册资料提交失败",body=flag))
} catch (e: UserIdError) {
call.respond(ApiResponse(message = "社团资料提交失败,请联系管理员",body = false))
} catch (e:FileIdError){
call.respond(ApiResponse(message = "社团资料提交失败,请联系管理员",body = false))
}catch (e:HasAssociationError){
call.respond(ApiResponse(message = e.message?:"发生未知错误,请联系管理员",body = false))
}
} }
} }
} }
@ -163,10 +171,10 @@ enum class NotificationType{
} }
/** /**
* 通知接收客户端 * 客户端类型
* *
*/ */
enum class ReceiverType{ enum class ClientType{
//前台 //前台
Foreground, Foreground,
//后台 //后台
@ -179,7 +187,7 @@ enum class ReceiverType{
*/ */
sealed class Receiver{ sealed class Receiver{
protected abstract val id:Int protected abstract val id:Int
abstract val target:ReceiverType abstract val target:ClientType
} }
/** /**
@ -187,14 +195,14 @@ sealed class Receiver{
* *
* @property managerId 管理员id * @property managerId 管理员id
*/ */
data class BackgroundReceiver(val managerId:Int,override val id: Int=managerId, override val target: ReceiverType=ReceiverType.Background):Receiver() data class BackgroundReceiver(val managerId:Int,override val id: Int=managerId, override val target: ClientType=ClientType.Background):Receiver()
/** /**
* 前台客户端接收 * 前台客户端接收
* *
* @property userId 用户id * @property userId 用户id
*/ */
data class ForegroundReceiver(val userId:Int, override val id:Int=userId, override val target: ReceiverType=ReceiverType.Foreground):Receiver() data class ForegroundReceiver(val userId:Int, override val id:Int=userId, override val target: ClientType=ClientType.Foreground):Receiver()
sealed class BaseNotification{ sealed class BaseNotification{
abstract val type:NotificationType abstract val type:NotificationType

@ -131,6 +131,9 @@ object Associations:IntIdTable(){
@TableComment("社团审核状态") @TableComment("社团审核状态")
val status:Column<Boolean> = bool(name="status").default(false) val status:Column<Boolean> = bool(name="status").default(false)
@TableComment("创建人")
val user:Column<EntityID<Int>> = reference("user_id",Users)
} }
class Association(id:EntityID<Int>):IntEntity(id){ class Association(id:EntityID<Int>):IntEntity(id){
@ -139,6 +142,7 @@ class Association(id:EntityID<Int>):IntEntity(id){
var desc by Associations.desc var desc by Associations.desc
var logo by ImageFile referencedOn Associations.logo var logo by ImageFile referencedOn Associations.logo
var status by Associations.status var status by Associations.status
var user by User referencedOn Associations.user
} }
@TableComment("后台管理员") @TableComment("后台管理员")

@ -124,7 +124,7 @@ object AccountService:AbstractService() {
} }
} }
fun validToken(token: Token):Boolean{ fun validUserToken(token: Token):Boolean{
return transaction { return transaction {
!UserToken.find { !UserToken.find {
UserTokens.userId eq token.id UserTokens.userId eq token.id
@ -133,9 +133,20 @@ object AccountService:AbstractService() {
} }
} }
fun logout(userId:Int):Boolean{ fun <T : ClientBaseVo> validToken(vo:T):Boolean{
return if(vo.clientType==ClientType.Foreground){
validUserToken(vo.token)
}else{
validManagerToken(vo.token)
}
}
fun logout(vo:OnlyToken):Boolean{
return transaction { return transaction {
UserTokens.deleteWhere { UserTokens.userId eq userId }>0 if(vo.clientType==ClientType.Foreground)
UserTokens.deleteWhere { UserTokens.userId eq vo.token.id }>0
else
ManagerTokens.deleteWhere { ManagerTokens.managerId eq vo.token.id }>0
} }
} }
@ -264,7 +275,7 @@ object FileService:AbstractService(){
val token= getPartData<PartData.FormItem>(map,"token").value val token= getPartData<PartData.FormItem>(map,"token").value
val createTime= getPartData<PartData.FormItem>(map,"createTime").value val createTime= getPartData<PartData.FormItem>(map,"createTime").value
val tokenVo=Token(token=token,id=userId.toInt(),createTime=createTime.toLong()) val tokenVo=Token(token=token,id=userId.toInt(),createTime=createTime.toLong())
if(AccountService.validToken(tokenVo)){ if(AccountService.validUserToken(tokenVo)){
map.remove("id") map.remove("id")
map.remove("token") map.remove("token")
val fileIds= mutableListOf<Int>() val fileIds= mutableListOf<Int>()
@ -292,6 +303,11 @@ object FileService:AbstractService(){
} }
class UserIdError(id: Int): IllegalArgumentException("用户id${id}不存在")
class FileIdError(id:Int): IllegalArgumentException("文件id${id}不存在!")
class HasAssociationError(s: String) : IllegalArgumentException(s)
/** /**
* 社团服务 * 社团服务
@ -307,24 +323,27 @@ object AssociationService: AbstractService() {
fun register(vo:RegAssociationVo):Boolean{ fun register(vo:RegAssociationVo):Boolean{
return try { return try {
transaction { transaction {
val user=User.findById(vo.token.id)?:throw UserIdError(vo.token.id)
Association.find { Associations.user eq vo.token.id }.apply {
when{
count()!=0L && first().status ->throw HasAssociationError("您是社团团长不能再创建其他社团")
count()!=0L->throw HasAssociationError("您已经提交过社团注册资料,请耐心等待后台管理员处理")
}
}
Association.new { Association.new {
name=vo.name name=vo.name
desc=vo.desc desc=vo.desc
logo=ImageFile.findById(vo.fileId) ?: throw IllegalArgumentException("文件id不存在!") logo=ImageFile.findById(vo.fileId) ?: throw FileIdError(vo.fileId)
this.user=user
} }
Notification.new { Notification.new {
title="注册社团" title="注册社团"
content="您成功提交了一份社团注册资料,请耐心等待后台受理" content="您成功提交了一份社团注册资料,请耐心等待后台受理"
receiverId=vo.token.id receiverId=vo.token.id
receiverClient=ReceiverType.Foreground.name receiverClient=ClientType.Foreground.name
}
val user=User.findById(vo.token.id)
if(user!=null) {
BackgroundService.createBackgroundNotification(title = "审核注册社团",content = "用户${user.name}提交了一份社团资料需要您进行受理",
duty = Duty.PamphaBhusal)
}else{
log.warn("无法根据token id:${vo.token.id}查找到用户名")
} }
BackgroundService.createBackgroundNotification(title = "审核注册社团",content = "用户${user.name}提交了一份社团资料需要您进行受理",
duty = Duty.PamphaBhusal)
return@transaction true return@transaction true
} }
log.info("未审核社团创建成功") log.info("未审核社团创建成功")
@ -360,6 +379,7 @@ object NotificationService:AbstractService(){
*/ */
fun pull(vo:NotificationDto):List<NotificationVo>{ fun pull(vo:NotificationDto):List<NotificationVo>{
return transaction { return transaction {
log.info("通知查询条件[receiverId=${vo.receiverId},receiverClient=${vo.receiverClient.name},pull=false]")
val notifications=Notification.find { Notifications.pull eq false and val notifications=Notification.find { Notifications.pull eq false and
(Notifications.receiverId eq vo.receiverId) and (Notifications.receiverId eq vo.receiverId) and
(Notifications.receiverClient eq vo.receiverClient.name) } (Notifications.receiverClient eq vo.receiverClient.name) }
@ -437,7 +457,7 @@ object BackgroundService:AbstractService(){
this.title = title this.title = title
this.content = content this.content = content
receiverId= it.id.value receiverId= it.id.value
receiverClient=ReceiverType.Background.name receiverClient=ClientType.Background.name
} }
} }
} }

@ -21,36 +21,40 @@ data class UserVo(val studentId:String,val name:String)
sealed class BaseLoginVo{ sealed class BaseLoginVo{
abstract val password: String abstract val password: String
abstract val device: String abstract val device: String
abstract val clientType:ReceiverType abstract val clientType:ClientType
}
sealed class ClientBaseVo {
abstract val token:Token
abstract val clientType:ClientType
} }
data class UserLoginVo(val studentId: String, data class UserLoginVo(val studentId: String,
override val password: String, override val device: String, override val password: String, override val device: String,
override val clientType: ReceiverType=ReceiverType.Foreground override val clientType: ClientType=ClientType.Foreground
):BaseLoginVo() ):BaseLoginVo()
data class UserLogoutVo(val userId:Int)
data class UserResDto(val password:String) data class UserResDto(val password:String)
data class ManagerLoginVo(val account:String, data class ManagerLoginVo(val account:String,
override val password:String, override val device:String):BaseLoginVo() { override val password:String, override val device:String):BaseLoginVo() {
override val clientType: ReceiverType=ReceiverType.Background override val clientType: ClientType=ClientType.Background
} }
data class Token(val token:String, val createTime:Long, val id:Int) data class Token(val token:String, val createTime:Long, val id:Int)
sealed class BaseVo{
abstract val token:Token
}
data class LeaveMessageVo(val message: String, override val token:Token):BaseVo() data class LeaveMessageVo(val message: String, override val token:Token,
override val clientType: ClientType=ClientType.Foreground):ClientBaseVo()
data class OnlyToken(override val token: Token):BaseVo() data class OnlyToken(override val token: Token, override val clientType: ClientType):ClientBaseVo()
data class LeaveMessageDto(val message: String,val user: UserVo) data class LeaveMessageDto(val message: String,val user: UserVo)
data class RegAssociationVo(val name:String, val desc:String,val fileId:Int, override val token: Token):BaseVo() data class RegAssociationVo(val name:String, val desc:String, val fileId:Int, override val token: Token,
override val clientType: ClientType=ClientType.Foreground
):ClientBaseVo()
data class ImageFileDto(val filepath:String,val md5:String,val createTime: Long,val url:String) data class ImageFileDto(val filepath:String,val md5:String,val createTime: Long,val url:String)
@ -60,7 +64,8 @@ data class InitManagerDto(val account: String, val originPassword: String, val d
data class PageDto(val currentPage:Long,val pageSize:Int=10) data class PageDto(val currentPage:Long,val pageSize:Int=10)
data class NotificationDto(val receiverId:Int, val receiverClient:ReceiverType, override val token: Token, data class NotificationDto(val receiverId:Int, val receiverClient:ClientType, override val token: Token,
val page:PageDto?):BaseVo() val page:PageDto?, override val clientType: ClientType=receiverClient
):ClientBaseVo()
data class NotificationVo(val title:String,val content:String,val id:Int,val createTime: Long) data class NotificationVo(val title:String,val content:String,val id:Int,val createTime: Long)

@ -95,7 +95,7 @@ class ApplicationTest {
@Test @Test
fun testLowerCase(){ fun testLowerCase(){
println(ReceiverType.Foreground.name.toLowerCase()) println(ClientType.Foreground.name.toLowerCase())
} }
/** /**

Loading…
Cancel
Save