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.
 
csamsserver/src/Service.kt

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("不需要生成管理员")
}
}
}
}
}
}