You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
365 lines
12 KiB
365 lines
12 KiB
package com.gyf.csams
|
|
|
|
import io.ktor.application.*
|
|
import io.ktor.http.content.*
|
|
import org.jetbrains.exposed.sql.deleteWhere
|
|
import org.jetbrains.exposed.sql.transactions.transaction
|
|
import org.slf4j.Logger
|
|
import java.io.File
|
|
import java.time.ZoneOffset
|
|
import kotlin.properties.Delegates
|
|
|
|
interface BaseService{
|
|
fun init(environment:ApplicationEnvironment)
|
|
}
|
|
|
|
|
|
abstract class AbstractService:BaseService{
|
|
protected lateinit var log:Logger
|
|
override fun init(environment: ApplicationEnvironment) {
|
|
this.log=environment.log
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 账号服务
|
|
*/
|
|
object AccountService:AbstractService() {
|
|
/**
|
|
* 检查学号是否已注册,true=已注册
|
|
*/
|
|
fun registered(selectId: String): Boolean {
|
|
return transaction {
|
|
return@transaction !User.find { Users.studentId eq selectId }.empty()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 注册
|
|
*/
|
|
fun register(userVo: UserVo): UserResDto? {
|
|
try {
|
|
return transaction {
|
|
val originPassword = randomNum(8)
|
|
User.new {
|
|
studentId=userVo.studentId
|
|
name=userVo.name
|
|
password=originPassword.md5()
|
|
}
|
|
return@transaction UserResDto(password=originPassword)
|
|
}
|
|
} catch (e: Exception) {
|
|
log.error("注册失败,发生异常:$e")
|
|
return null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 登录
|
|
*
|
|
* @param userLoginVo 登陆表单
|
|
*/
|
|
fun login(userLoginVo: UserLoginVo,_ip:String):Token?{
|
|
return transaction {
|
|
val matchUser=User.find { Users.studentId eq userLoginVo.studentId }.firstOrNull()
|
|
|
|
when {
|
|
matchUser==null -> {
|
|
log.warn("学号:${userLoginVo.studentId}不存在")
|
|
return@transaction null
|
|
}
|
|
userLoginVo.password.md5() != matchUser.password -> {
|
|
log.warn("密码:${userLoginVo.password}错误")
|
|
return@transaction null
|
|
}
|
|
else -> {
|
|
val token=UserToken.new{
|
|
user=matchUser
|
|
ip=_ip
|
|
device=userLoginVo.device
|
|
token=listOf(matchUser.id,ip,device).joinToString(separator = ('a' .. 'z').random().toString()).md5()
|
|
}
|
|
token.flush()
|
|
return@transaction Token(userId = matchUser.id.value,token = token.token,
|
|
createTime = token.createTime.toEpochSecond(
|
|
ZoneOffset.of("+8")))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fun validToken(token: Token):Boolean{
|
|
return validToken(TokenVo(token = token.token,userId = token.userId))
|
|
}
|
|
|
|
/**
|
|
* 令牌校验
|
|
*
|
|
* @param tokenVo
|
|
* @return
|
|
*/
|
|
fun validToken(tokenVo: TokenVo):Boolean{
|
|
return transaction {
|
|
!UserToken.find {
|
|
UserTokens.userId eq tokenVo.userId
|
|
UserTokens.token eq tokenVo.token
|
|
}.empty()
|
|
}
|
|
}
|
|
|
|
fun logout(userId:Int):Boolean{
|
|
return transaction {
|
|
UserTokens.deleteWhere { UserTokens.userId eq userId }>0
|
|
}
|
|
}
|
|
|
|
fun test(){
|
|
log.info("开始测试")
|
|
transaction {
|
|
log.info("查询到个${User.count()}用户")
|
|
}
|
|
log.info("结束测试")
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* 主页服务
|
|
*/
|
|
object MainService:AbstractService(){
|
|
private var maxSize by Delegates.notNull<Int>()
|
|
|
|
override fun init(environment:ApplicationEnvironment){
|
|
super.init(environment)
|
|
this.maxSize=environment.config.property("ktor.deployment.leaveMessage.maxSize").getString().toInt()
|
|
}
|
|
|
|
|
|
/**
|
|
* 创建留言信息
|
|
*
|
|
* @param leaveMessageVo
|
|
* @return
|
|
*/
|
|
fun createMessage(leaveMessageVo: LeaveMessageVo):Boolean{
|
|
return if(leaveMessageVo.message.isNotEmpty()){
|
|
return transaction {
|
|
val count=LeaveMessage.count().toInt()
|
|
log.info("系统留言数:$count,限制数:$maxSize")
|
|
if(count>= maxSize){
|
|
LeaveMessage.all().sortedBy { it.createTime }.subList(0, count-maxSize).forEach {
|
|
it.delete()
|
|
}
|
|
|
|
}
|
|
log.info("保存留言:${leaveMessageVo.message}")
|
|
LeaveMessage.new {
|
|
user= User.findById(leaveMessageVo.token.userId)?:throw IllegalArgumentException("非法id")
|
|
message = leaveMessageVo.message
|
|
}
|
|
log.info("留言保存成功")
|
|
return@transaction true
|
|
}
|
|
}else{
|
|
log.info("留言不能为空")
|
|
false
|
|
}
|
|
}
|
|
|
|
fun getAllLeaveMessage():List<LeaveMessageDto>{
|
|
return transaction {
|
|
log.info("获取所有留言")
|
|
|
|
return@transaction LeaveMessage.all().toList().map {
|
|
LeaveMessageDto(
|
|
message = "${it.user.name}说:${it.message}",
|
|
user = UserVo(studentId = it.user.studentId, name = it.user.name)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 文件管理服务
|
|
*/
|
|
object FileService:AbstractService(){
|
|
private lateinit var uploadDir:String
|
|
private lateinit var filePath:String
|
|
|
|
override fun init(environment:ApplicationEnvironment){
|
|
super.init(environment)
|
|
this.uploadDir= environment.config.property("ktor.deployment.filePath").getString()
|
|
val resourcePath =this::class.java.classLoader.getResource("")?.path ?: throw IllegalArgumentException("初始化资源目录失败")
|
|
File(resourcePath, uploadDir).apply {
|
|
when{
|
|
!exists()&&mkdir()-> {
|
|
log.info("图片上传路径[${absolutePath}]初始化成功")
|
|
this@FileService.filePath=absolutePath
|
|
}
|
|
exists()->{
|
|
log.info("图片上传路径[${absolutePath}]已存在")
|
|
this@FileService.filePath=absolutePath
|
|
}
|
|
else->throw IllegalArgumentException("图片上传路径[${absolutePath}]初始化失败")
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun save(id: String, path:String, file: File):Int{
|
|
return transaction {
|
|
return@transaction ImageFile.new {
|
|
userId = id
|
|
filepath = path
|
|
md5 = file.readBytes().md5()
|
|
}
|
|
}.id.value
|
|
}
|
|
|
|
|
|
private inline fun <reified T:PartData> getPartData(map:Map<String?, PartData>, key:String):T{
|
|
if(map.containsKey(key)){
|
|
val obj= map[key]
|
|
if(obj is T){
|
|
return obj
|
|
}else{
|
|
throw IllegalArgumentException("类型错误")
|
|
}
|
|
}
|
|
throw IllegalArgumentException("找不到key:${key}")
|
|
}
|
|
|
|
fun storeFile(data:List<PartData>):List<Int>?{
|
|
val map=data.associateBy {
|
|
it.name
|
|
}.toMutableMap()
|
|
log.info("map=${map}")
|
|
val userId=getPartData<PartData.FormItem>(map,"id").value
|
|
val token= getPartData<PartData.FormItem>(map,"token").value
|
|
val tokenVo=TokenVo(token=token,userId=userId.toInt())
|
|
if(AccountService.validToken(tokenVo)){
|
|
map.remove("id")
|
|
map.remove("token")
|
|
val fileIds= mutableListOf<Int>()
|
|
map.forEach{
|
|
val value=it.value
|
|
if(value is PartData.FileItem){
|
|
val fileBytes = value.streamProvider().readBytes()
|
|
val fileName=value.originalFileName?:throw IllegalArgumentException("参数异常")
|
|
val format = fileBytes.getFormat()
|
|
val fullFileName="${fileName}.${format.format}"
|
|
log.info("fullFileName=$fullFileName")
|
|
val file=File(filePath,fullFileName).apply {
|
|
writeBytes(fileBytes)
|
|
}
|
|
val fileId= save(id = userId,"${uploadDir}/${fullFileName}",file=file)
|
|
fileIds.add(fileId)
|
|
}
|
|
}
|
|
return fileIds
|
|
}else{
|
|
return null
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 社团服务
|
|
*/
|
|
object AssociationService: AbstractService() {
|
|
|
|
fun register(vo:RegAssociationVo):Boolean{
|
|
return try {
|
|
transaction {
|
|
Association.new {
|
|
name=vo.name
|
|
desc=vo.desc
|
|
logo=ImageFile.findById(vo.fileId) ?: throw IllegalArgumentException("文件id不存在!")
|
|
}
|
|
}
|
|
log.info("未审核社团创建成功")
|
|
true
|
|
} catch (e: Exception) {
|
|
log.error(e.stackTraceToString())
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
enum class ManagerType(val desc:String,val level:Int){
|
|
Teacher("老师",1),
|
|
PamphaBhusal("总部长",2),
|
|
SecretaryOfTheMinister("秘书部部长",3),
|
|
PropagandaDepartment("宣传部部长",3),
|
|
LiaisonMinister("外联部部长",3),
|
|
SecretaryDepartmentOfficer("秘书部干事",4),
|
|
PublicityDepartmentOfficer("宣传部干事",4),
|
|
LiaisonOfficer("外联部干事",4)
|
|
}
|
|
|
|
object NotificationService:AbstractService(){
|
|
|
|
}
|
|
|
|
/**
|
|
* 后台服务
|
|
*/
|
|
object BackgroundService:AbstractService(){
|
|
|
|
|
|
|
|
override fun init(environment: ApplicationEnvironment) {
|
|
super.init(environment)
|
|
initManager()
|
|
}
|
|
|
|
private fun createManager(type:ManagerType, num:Int=1): MutableList<InitManagerDto> {
|
|
val managerList= mutableListOf<InitManagerDto>()
|
|
repeat(num){
|
|
val originPassword=randomNum()
|
|
Manager.new {
|
|
account= randomNum()
|
|
password = originPassword.md5()
|
|
duty=type.name
|
|
level=type.level
|
|
}.apply {
|
|
managerList.add(InitManagerDto(account=account,originPassword=originPassword))
|
|
}
|
|
}
|
|
return managerList
|
|
}
|
|
|
|
//初始化管理员
|
|
private fun initManager(){
|
|
transaction {
|
|
val resourcePath =this::class.java.classLoader.getResource("")?.path ?: throw IllegalArgumentException("初始化资源目录失败")
|
|
val file=File(resourcePath,"管理员账号.txt")
|
|
if(!file.exists()) {
|
|
Manager.count().let { it ->
|
|
if (it.toInt() == 0) {
|
|
val allManager = mutableListOf<InitManagerDto>()
|
|
allManager.addAll(createManager(ManagerType.Teacher, 1))
|
|
allManager.addAll(createManager(ManagerType.PamphaBhusal, 1))
|
|
allManager.addAll(createManager(ManagerType.SecretaryOfTheMinister, 1))
|
|
allManager.addAll(createManager(ManagerType.PropagandaDepartment, 1))
|
|
allManager.addAll(createManager(ManagerType.LiaisonMinister, 1))
|
|
arrayOf(
|
|
ManagerType.SecretaryDepartmentOfficer,
|
|
ManagerType.PublicityDepartmentOfficer,
|
|
ManagerType.LiaisonOfficer
|
|
).forEach {
|
|
allManager.addAll(createManager(it, 3))
|
|
}
|
|
allManager.forEach {
|
|
file.appendText("${it.account}------${it.originPassword}\n")
|
|
}
|
|
log.info("共生成${allManager.size}个管理员账号")
|
|
} else {
|
|
log.info("不需要生成管理员")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|