From 9fe8fcad7be0bec26276832168cb7343e630de64 Mon Sep 17 00:00:00 2001 From: pan <1029559041@qq.com> Date: Fri, 28 May 2021 02:22:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6token=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E9=80=BB=E8=BE=91=20=E7=A4=BE=E5=9B=A2=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E8=A1=A8=E5=A2=9E=E5=8A=A0=E5=88=9B=E5=BB=BA=E4=BA=BA=20?= =?UTF-8?q?=E7=A4=BE=E5=9B=A2=E6=B3=A8=E5=86=8C=E9=80=BB=E8=BE=91=E5=AE=8C?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Controller.kt | 38 +++++++++++++++++++------------- src/Dao.kt | 4 ++++ src/Service.kt | 48 +++++++++++++++++++++++++++++------------ src/Vo.kt | 31 +++++++++++++++----------- test/ApplicationTest.kt | 2 +- 5 files changed, 80 insertions(+), 43 deletions(-) diff --git a/src/Controller.kt b/src/Controller.kt index f412029..0656f60 100644 --- a/src/Controller.kt +++ b/src/Controller.kt @@ -6,9 +6,9 @@ import io.ktor.request.* import io.ktor.response.* import io.ktor.routing.* -suspend inline fun withToken(call: ApplicationCall, callback: (vo: T) -> Unit) { +suspend inline fun withToken(call: ApplicationCall, callback: (vo: T) -> Unit) { val levelVo = call.receive() - if (AccountService.validToken(levelVo.token)) { + if (AccountService.validToken(levelVo)) { callback(levelVo) } else { call.respond(Simple.error("token校验失败")) @@ -52,7 +52,7 @@ fun Application.AccountController() { //TODO 封装前后台登录逻辑 route(path = "/login") { - route(path = ReceiverType.Foreground.name.toLowerCase()){ + route(path = ClientType.Foreground.name.toLowerCase()){ post { val userLoginVo = call.receive() val token = AccountService.login(userLoginVo, call.request.host()) @@ -60,12 +60,12 @@ fun Application.AccountController() { } post("/token"){ val tokenVo = call.receive() - val isValid = AccountService.validToken(tokenVo) + val isValid = AccountService.validUserToken(tokenVo) call.respond(ApiResponse(message = if (isValid) "令牌合法" else "令牌不合法", body = isValid)) } } - route(path = ReceiverType.Background.name.toLowerCase()){ + route(path = ClientType.Background.name.toLowerCase()){ post{ val managerLoginVo = call.receive() val token = AccountService.login(managerLoginVo, call.request.host()) @@ -83,9 +83,9 @@ fun Application.AccountController() { post(path = "/logout") { environment.log.info("退出登录") - val userLogoutVo = call.receive() - environment.log.info("$userLogoutVo") - val flag = AccountService.logout(userLogoutVo.userId) + val onlyToken = call.receive() + environment.log.info("$onlyToken") + val flag = AccountService.logout(onlyToken) call.respond(ApiResponse(message = if (flag) "退出成功" else "退出失败", body = flag)) } } @@ -146,8 +146,16 @@ fun Application.AssociationController() { } post("/register"){ withToken(call = call){ - val flag=AssociationService.register(vo=it) - call.respond(ApiResponse(message = if(flag) "社团注册资料已保存,请等待受理" else "社团注册资料保存失败",body=flag)) + try { + 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, //后台 @@ -179,7 +187,7 @@ enum class ReceiverType{ */ sealed class Receiver{ protected abstract val id:Int - abstract val target:ReceiverType + abstract val target:ClientType } /** @@ -187,14 +195,14 @@ sealed class Receiver{ * * @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 */ -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{ abstract val type:NotificationType diff --git a/src/Dao.kt b/src/Dao.kt index 0cd8a2b..5563b60 100644 --- a/src/Dao.kt +++ b/src/Dao.kt @@ -131,6 +131,9 @@ object Associations:IntIdTable(){ @TableComment("社团审核状态") val status:Column = bool(name="status").default(false) + + @TableComment("创建人") + val user:Column> = reference("user_id",Users) } class Association(id:EntityID):IntEntity(id){ @@ -139,6 +142,7 @@ class Association(id:EntityID):IntEntity(id){ var desc by Associations.desc var logo by ImageFile referencedOn Associations.logo var status by Associations.status + var user by User referencedOn Associations.user } @TableComment("后台管理员") diff --git a/src/Service.kt b/src/Service.kt index ffaad85..b895aaa 100644 --- a/src/Service.kt +++ b/src/Service.kt @@ -124,7 +124,7 @@ object AccountService:AbstractService() { } } - fun validToken(token: Token):Boolean{ + fun validUserToken(token: Token):Boolean{ return transaction { !UserToken.find { UserTokens.userId eq token.id @@ -133,9 +133,20 @@ object AccountService:AbstractService() { } } - fun logout(userId:Int):Boolean{ + fun validToken(vo:T):Boolean{ + return if(vo.clientType==ClientType.Foreground){ + validUserToken(vo.token) + }else{ + validManagerToken(vo.token) + } + } + + fun logout(vo:OnlyToken):Boolean{ 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(map,"token").value val createTime= getPartData(map,"createTime").value val tokenVo=Token(token=token,id=userId.toInt(),createTime=createTime.toLong()) - if(AccountService.validToken(tokenVo)){ + if(AccountService.validUserToken(tokenVo)){ map.remove("id") map.remove("token") val fileIds= mutableListOf() @@ -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{ return try { 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 { name=vo.name 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 { title="注册社团" content="您成功提交了一份社团注册资料,请耐心等待后台受理" receiverId=vo.token.id - receiverClient=ReceiverType.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}查找到用户名") + receiverClient=ClientType.Foreground.name } + BackgroundService.createBackgroundNotification(title = "审核注册社团",content = "用户${user.name}提交了一份社团资料需要您进行受理", + duty = Duty.PamphaBhusal) return@transaction true } log.info("未审核社团创建成功") @@ -360,6 +379,7 @@ object NotificationService:AbstractService(){ */ fun pull(vo:NotificationDto):List{ return transaction { + log.info("通知查询条件[receiverId=${vo.receiverId},receiverClient=${vo.receiverClient.name},pull=false]") val notifications=Notification.find { Notifications.pull eq false and (Notifications.receiverId eq vo.receiverId) and (Notifications.receiverClient eq vo.receiverClient.name) } @@ -437,7 +457,7 @@ object BackgroundService:AbstractService(){ this.title = title this.content = content receiverId= it.id.value - receiverClient=ReceiverType.Background.name + receiverClient=ClientType.Background.name } } } diff --git a/src/Vo.kt b/src/Vo.kt index 64833ce..fbcefd0 100644 --- a/src/Vo.kt +++ b/src/Vo.kt @@ -21,36 +21,40 @@ data class UserVo(val studentId:String,val name:String) sealed class BaseLoginVo{ abstract val password: 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, override val password: String, override val device: String, - override val clientType: ReceiverType=ReceiverType.Foreground + override val clientType: ClientType=ClientType.Foreground ):BaseLoginVo() -data class UserLogoutVo(val userId:Int) - data class UserResDto(val password:String) data class ManagerLoginVo(val account:String, 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) -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 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) @@ -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 NotificationDto(val receiverId:Int, val receiverClient:ReceiverType, override val token: Token, -val page:PageDto?):BaseVo() +data class NotificationDto(val receiverId:Int, val receiverClient:ClientType, override val token: Token, + val page:PageDto?, override val clientType: ClientType=receiverClient +):ClientBaseVo() data class NotificationVo(val title:String,val content:String,val id:Int,val createTime: Long) \ No newline at end of file diff --git a/test/ApplicationTest.kt b/test/ApplicationTest.kt index 62c2243..34ce8fa 100644 --- a/test/ApplicationTest.kt +++ b/test/ApplicationTest.kt @@ -95,7 +95,7 @@ class ApplicationTest { @Test fun testLowerCase(){ - println(ReceiverType.Foreground.name.toLowerCase()) + println(ClientType.Foreground.name.toLowerCase()) } /**