完成重构数据库操作代码
This commit is contained in:
324
server/service/job.go
Normal file
324
server/service/job.go
Normal file
@ -0,0 +1,324 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/robfig/cron/v3"
|
||||
"github.com/sirupsen/logrus"
|
||||
"next-terminal/server/api"
|
||||
"next-terminal/server/constant"
|
||||
"next-terminal/server/global"
|
||||
"next-terminal/server/model"
|
||||
"next-terminal/server/repository"
|
||||
"next-terminal/server/term"
|
||||
"next-terminal/server/utils"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type JobService struct {
|
||||
jobRepository *repository.JobRepository
|
||||
jobLogRepository *repository.JobLogRepository
|
||||
assetRepository *repository.AssetRepository
|
||||
credentialRepository *repository.CredentialRepository
|
||||
}
|
||||
|
||||
func NewJobService(jobRepository *repository.JobRepository, jobLogRepository *repository.JobLogRepository, assetRepository *repository.AssetRepository, credentialRepository *repository.CredentialRepository) *JobService {
|
||||
return &JobService{jobRepository: jobRepository, jobLogRepository: jobLogRepository, assetRepository: assetRepository, credentialRepository: credentialRepository}
|
||||
}
|
||||
|
||||
func (r JobService) ChangeJobStatusById(id, status string) error {
|
||||
job, err := r.jobRepository.FindById(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if status == constant.JobStatusRunning {
|
||||
j, err := getJob(&job, &r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
entryID, err := global.Cron.AddJob(job.Cron, j)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("开启计划任务「%v」,运行中计划任务数量「%v」", job.Name, len(global.Cron.Entries()))
|
||||
|
||||
jobForUpdate := model.Job{ID: id, Status: constant.JobStatusRunning, CronJobId: int(entryID)}
|
||||
|
||||
return r.jobRepository.UpdateById(&jobForUpdate)
|
||||
} else {
|
||||
global.Cron.Remove(cron.EntryID(job.CronJobId))
|
||||
logrus.Debugf("关闭计划任务「%v」,运行中计划任务数量「%v」", job.Name, len(global.Cron.Entries()))
|
||||
jobForUpdate := model.Job{ID: id, Status: constant.JobStatusNotRunning}
|
||||
return r.jobRepository.UpdateById(&jobForUpdate)
|
||||
}
|
||||
}
|
||||
|
||||
func getJob(j *model.Job, jobService *JobService) (job cron.Job, err error) {
|
||||
switch j.Func {
|
||||
case constant.FuncCheckAssetStatusJob:
|
||||
job = CheckAssetStatusJob{ID: j.ID, Mode: j.Mode, ResourceIds: j.ResourceIds, Metadata: j.Metadata, jobService: jobService}
|
||||
case constant.FuncShellJob:
|
||||
job = ShellJob{ID: j.ID, Mode: j.Mode, ResourceIds: j.ResourceIds, Metadata: j.Metadata, jobService: jobService}
|
||||
default:
|
||||
return nil, errors.New("未识别的任务")
|
||||
}
|
||||
return job, err
|
||||
}
|
||||
|
||||
type CheckAssetStatusJob struct {
|
||||
ID string
|
||||
Mode string
|
||||
ResourceIds string
|
||||
Metadata string
|
||||
jobService *JobService
|
||||
}
|
||||
|
||||
func (r CheckAssetStatusJob) Run() {
|
||||
if r.ID == "" {
|
||||
return
|
||||
}
|
||||
|
||||
var assets []model.Asset
|
||||
if r.Mode == constant.JobModeAll {
|
||||
assets, _ = r.jobService.assetRepository.FindAll()
|
||||
} else {
|
||||
assets, _ = r.jobService.assetRepository.FindByIds(strings.Split(r.ResourceIds, ","))
|
||||
}
|
||||
|
||||
if len(assets) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
msgChan := make(chan string)
|
||||
for i := range assets {
|
||||
asset := assets[i]
|
||||
go func() {
|
||||
t1 := time.Now()
|
||||
active := utils.Tcping(asset.IP, asset.Port)
|
||||
elapsed := time.Since(t1)
|
||||
msg := fmt.Sprintf("资产「%v」存活状态检测完成,存活「%v」,耗时「%v」", asset.Name, active, elapsed)
|
||||
|
||||
_ = r.jobService.assetRepository.UpdateActiveById(active, asset.ID)
|
||||
logrus.Infof(msg)
|
||||
msgChan <- msg
|
||||
}()
|
||||
}
|
||||
|
||||
var message = ""
|
||||
for i := 0; i < len(assets); i++ {
|
||||
message += <-msgChan + "\n"
|
||||
}
|
||||
|
||||
_ = r.jobService.jobRepository.UpdateLastUpdatedById(r.ID)
|
||||
jobLog := model.JobLog{
|
||||
ID: utils.UUID(),
|
||||
JobId: r.ID,
|
||||
Timestamp: utils.NowJsonTime(),
|
||||
Message: message,
|
||||
}
|
||||
|
||||
_ = r.jobService.jobLogRepository.Create(&jobLog)
|
||||
}
|
||||
|
||||
type ShellJob struct {
|
||||
ID string
|
||||
Mode string
|
||||
ResourceIds string
|
||||
Metadata string
|
||||
jobService *JobService
|
||||
}
|
||||
|
||||
type MetadataShell struct {
|
||||
Shell string
|
||||
}
|
||||
|
||||
func (r ShellJob) Run() {
|
||||
if r.ID == "" {
|
||||
return
|
||||
}
|
||||
|
||||
var assets []model.Asset
|
||||
if r.Mode == constant.JobModeAll {
|
||||
assets, _ = r.jobService.assetRepository.FindByProtocol("ssh")
|
||||
} else {
|
||||
assets, _ = r.jobService.assetRepository.FindByProtocolAndIds("ssh", strings.Split(r.ResourceIds, ","))
|
||||
}
|
||||
|
||||
if len(assets) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var metadataShell MetadataShell
|
||||
err := json.Unmarshal([]byte(r.Metadata), &metadataShell)
|
||||
if err != nil {
|
||||
logrus.Errorf("JSON数据解析失败 %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
msgChan := make(chan string)
|
||||
for i := range assets {
|
||||
asset, err := r.jobService.assetRepository.FindById(assets[i].ID)
|
||||
if err != nil {
|
||||
msgChan <- fmt.Sprintf("资产「%v」Shell执行失败,查询数据异常「%v」", assets[i].Name, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
username = asset.Username
|
||||
password = asset.Password
|
||||
privateKey = asset.PrivateKey
|
||||
passphrase = asset.Passphrase
|
||||
ip = asset.IP
|
||||
port = asset.Port
|
||||
)
|
||||
|
||||
if asset.AccountType == "credential" {
|
||||
credential, err := r.jobService.credentialRepository.FindById(asset.CredentialId)
|
||||
if err != nil {
|
||||
msgChan <- fmt.Sprintf("资产「%v」Shell执行失败,查询授权凭证数据异常「%v」", assets[i].Name, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if credential.Type == constant.Custom {
|
||||
username = credential.Username
|
||||
password = credential.Password
|
||||
} else {
|
||||
username = credential.Username
|
||||
privateKey = credential.PrivateKey
|
||||
passphrase = credential.Passphrase
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
||||
t1 := time.Now()
|
||||
result, err := ExecCommandBySSH(metadataShell.Shell, ip, port, username, password, privateKey, passphrase)
|
||||
elapsed := time.Since(t1)
|
||||
var msg string
|
||||
if err != nil {
|
||||
msg = fmt.Sprintf("资产「%v」Shell执行失败,返回值「%v」,耗时「%v」", asset.Name, err.Error(), elapsed)
|
||||
logrus.Infof(msg)
|
||||
} else {
|
||||
msg = fmt.Sprintf("资产「%v」Shell执行成功,返回值「%v」,耗时「%v」", asset.Name, result, elapsed)
|
||||
logrus.Infof(msg)
|
||||
}
|
||||
|
||||
msgChan <- msg
|
||||
}()
|
||||
}
|
||||
|
||||
var message = ""
|
||||
for i := 0; i < len(assets); i++ {
|
||||
message += <-msgChan + "\n"
|
||||
}
|
||||
|
||||
_ = r.jobService.jobRepository.UpdateLastUpdatedById(r.ID)
|
||||
jobLog := model.JobLog{
|
||||
ID: utils.UUID(),
|
||||
JobId: r.ID,
|
||||
Timestamp: utils.NowJsonTime(),
|
||||
Message: message,
|
||||
}
|
||||
|
||||
_ = r.jobService.jobLogRepository.Create(&jobLog)
|
||||
}
|
||||
|
||||
func ExecCommandBySSH(cmd, ip string, port int, username, password, privateKey, passphrase string) (result string, err error) {
|
||||
sshClient, err := term.NewSshClient(ip, port, username, password, privateKey, passphrase)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
session, err := sshClient.NewSession()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer session.Close()
|
||||
//执行远程命令
|
||||
combo, err := session.CombinedOutput(cmd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(combo), nil
|
||||
}
|
||||
|
||||
func (r JobService) ExecJobById(id string) (err error) {
|
||||
job, err := r.jobRepository.FindById(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
j, err := getJob(&job, &r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
j.Run()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r JobService) InitJob() error {
|
||||
jobs, _ := r.jobRepository.FindByFunc(constant.FuncCheckAssetStatusJob)
|
||||
if jobs == nil || len(jobs) == 0 {
|
||||
job := model.Job{
|
||||
ID: utils.UUID(),
|
||||
Name: "资产状态检测",
|
||||
Func: constant.FuncCheckAssetStatusJob,
|
||||
Cron: "0 0 0/1 * * ?",
|
||||
Mode: constant.JobModeAll,
|
||||
Status: constant.JobStatusRunning,
|
||||
Created: utils.NowJsonTime(),
|
||||
Updated: utils.NowJsonTime(),
|
||||
}
|
||||
if err := r.jobRepository.Create(&job); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("创建计划任务「%v」cron「%v」", job.Name, job.Cron)
|
||||
} else {
|
||||
for i := range jobs {
|
||||
if jobs[i].Status == constant.JobStatusRunning {
|
||||
err := r.ChangeJobStatusById(jobs[i].ID, constant.JobStatusRunning)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("启动计划任务「%v」cron「%v」", jobs[i].Name, jobs[i].Cron)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO 可能存在循环引用
|
||||
func (r UserService) ReloadToken() error {
|
||||
loginLogs, err := r.loginLogRepository.FindAliveLoginLogs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range loginLogs {
|
||||
loginLog := loginLogs[i]
|
||||
token := loginLog.ID
|
||||
user, err := r.userRepository.FindById(loginLog.UserId)
|
||||
if err != nil {
|
||||
logrus.Debugf("用户「%v」获取失败,忽略", loginLog.UserId)
|
||||
continue
|
||||
}
|
||||
|
||||
authorization := api.Authorization{
|
||||
Token: token,
|
||||
Remember: loginLog.Remember,
|
||||
User: user,
|
||||
}
|
||||
|
||||
cacheKey := api.BuildCacheKeyByToken(token)
|
||||
|
||||
if authorization.Remember {
|
||||
// 记住登录有效期两周
|
||||
global.Cache.Set(cacheKey, authorization, api.RememberEffectiveTime)
|
||||
} else {
|
||||
global.Cache.Set(cacheKey, authorization, api.NotRememberEffectiveTime)
|
||||
}
|
||||
logrus.Debugf("重新加载用户「%v」授权Token「%v」到缓存", user.Nickname, token)
|
||||
}
|
||||
return nil
|
||||
}
|
236
server/service/property.go
Normal file
236
server/service/property.go
Normal file
@ -0,0 +1,236 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"next-terminal/server/guacd"
|
||||
"next-terminal/server/model"
|
||||
"next-terminal/server/repository"
|
||||
"next-terminal/server/utils"
|
||||
"os"
|
||||
)
|
||||
|
||||
type PropertyService struct {
|
||||
propertyRepository *repository.PropertyRepository
|
||||
}
|
||||
|
||||
func NewPropertyService(propertyRepository *repository.PropertyRepository) *PropertyService {
|
||||
return &PropertyService{propertyRepository: propertyRepository}
|
||||
}
|
||||
|
||||
func (r PropertyService) InitProperties() error {
|
||||
propertyMap := r.propertyRepository.FindAllMap()
|
||||
|
||||
if len(propertyMap[guacd.Host]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.Host,
|
||||
Value: "127.0.0.1",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.Port]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.Port,
|
||||
Value: "4822",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.EnableRecording]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.EnableRecording,
|
||||
Value: "true",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.RecordingPath]) == 0 {
|
||||
path, _ := os.Getwd()
|
||||
property := model.Property{
|
||||
Name: guacd.RecordingPath,
|
||||
Value: path + "/recording/",
|
||||
}
|
||||
if !utils.FileExists(property.Value) {
|
||||
if err := os.Mkdir(property.Value, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.CreateRecordingPath]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.CreateRecordingPath,
|
||||
Value: "true",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.DriveName]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.DriveName,
|
||||
Value: "File-System",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.DrivePath]) == 0 {
|
||||
|
||||
path, _ := os.Getwd()
|
||||
|
||||
property := model.Property{
|
||||
Name: guacd.DrivePath,
|
||||
Value: path + "/drive/",
|
||||
}
|
||||
if !utils.FileExists(property.Value) {
|
||||
if err := os.Mkdir(property.Value, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.FontName]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.FontName,
|
||||
Value: "menlo",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.FontSize]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.FontSize,
|
||||
Value: "12",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.ColorScheme]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.ColorScheme,
|
||||
Value: "gray-black",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.EnableDrive]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.EnableDrive,
|
||||
Value: "true",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.EnableWallpaper]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.EnableWallpaper,
|
||||
Value: "false",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.EnableTheming]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.EnableTheming,
|
||||
Value: "false",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.EnableFontSmoothing]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.EnableFontSmoothing,
|
||||
Value: "false",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.EnableFullWindowDrag]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.EnableFullWindowDrag,
|
||||
Value: "false",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.EnableDesktopComposition]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.EnableDesktopComposition,
|
||||
Value: "false",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.EnableMenuAnimations]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.EnableMenuAnimations,
|
||||
Value: "false",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.DisableBitmapCaching]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.DisableBitmapCaching,
|
||||
Value: "false",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.DisableOffscreenCaching]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.DisableOffscreenCaching,
|
||||
Value: "false",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(propertyMap[guacd.DisableGlyphCaching]) == 0 {
|
||||
property := model.Property{
|
||||
Name: guacd.DisableGlyphCaching,
|
||||
Value: "false",
|
||||
}
|
||||
if err := r.propertyRepository.Create(&property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
32
server/service/session.go
Normal file
32
server/service/session.go
Normal file
@ -0,0 +1,32 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"next-terminal/server/constant"
|
||||
"next-terminal/server/model"
|
||||
"next-terminal/server/repository"
|
||||
"next-terminal/server/utils"
|
||||
)
|
||||
|
||||
type SessionService struct {
|
||||
sessionRepository *repository.SessionRepository
|
||||
}
|
||||
|
||||
func NewSessionService(sessionRepository *repository.SessionRepository) *SessionService {
|
||||
return &SessionService{sessionRepository: sessionRepository}
|
||||
}
|
||||
|
||||
func (r SessionService) Fix() {
|
||||
sessions, _ := r.sessionRepository.FindByStatus(constant.Connected)
|
||||
if sessions == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i := range sessions {
|
||||
session := model.Session{
|
||||
Status: constant.Disconnected,
|
||||
DisconnectedTime: utils.NowJsonTime(),
|
||||
}
|
||||
|
||||
_ = r.sessionRepository.UpdateById(&session, sessions[i].ID)
|
||||
}
|
||||
}
|
104
server/service/user.go
Normal file
104
server/service/user.go
Normal file
@ -0,0 +1,104 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"next-terminal/server/constant"
|
||||
"next-terminal/server/model"
|
||||
"next-terminal/server/repository"
|
||||
"next-terminal/server/utils"
|
||||
)
|
||||
|
||||
type UserService struct {
|
||||
userRepository *repository.UserRepository
|
||||
loginLogRepository *repository.LoginLogRepository
|
||||
}
|
||||
|
||||
func NewUserService(userRepository *repository.UserRepository) *UserService {
|
||||
return &UserService{userRepository: userRepository}
|
||||
}
|
||||
|
||||
func (r UserService) InitUser() (err error) {
|
||||
|
||||
users := r.userRepository.FindAll()
|
||||
|
||||
if len(users) == 0 {
|
||||
initPassword := "admin"
|
||||
var pass []byte
|
||||
if pass, err = utils.Encoder.Encode([]byte(initPassword)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := model.User{
|
||||
ID: utils.UUID(),
|
||||
Username: "admin",
|
||||
Password: string(pass),
|
||||
Nickname: "超级管理员",
|
||||
Type: constant.TypeAdmin,
|
||||
Created: utils.NowJsonTime(),
|
||||
}
|
||||
if err := r.userRepository.Create(&user); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("初始用户创建成功,账号:「%v」密码:「%v」", user.Username, initPassword)
|
||||
} else {
|
||||
for i := range users {
|
||||
// 修正默认用户类型为管理员
|
||||
if users[i].Type == "" {
|
||||
user := model.User{
|
||||
Type: constant.TypeAdmin,
|
||||
ID: users[i].ID,
|
||||
}
|
||||
if err := r.userRepository.Update(&user); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("自动修正用户「%v」ID「%v」类型为管理员", users[i].Nickname, users[i].ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r UserService) FixedOnlineState() error {
|
||||
// 修正用户登录状态
|
||||
onlineUsers, err := r.userRepository.FindOnlineUsers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range onlineUsers {
|
||||
logs, err := r.loginLogRepository.FindAliveLoginLogsByUserId(onlineUsers[i].ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(logs) == 0 {
|
||||
if err := r.userRepository.UpdateOnline(onlineUsers[i].ID, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r UserService) Logout(token string) (err error) {
|
||||
|
||||
loginLog, err := r.loginLogRepository.FindById(token)
|
||||
if err != nil {
|
||||
logrus.Warnf("登录日志「%v」获取失败", token)
|
||||
return
|
||||
}
|
||||
|
||||
loginLogForUpdate := &model.LoginLog{LogoutTime: utils.NowJsonTime(), ID: token}
|
||||
err = r.loginLogRepository.Update(loginLogForUpdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginLogs, err := r.loginLogRepository.FindAliveLoginLogsByUserId(loginLog.UserId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(loginLogs) == 0 {
|
||||
err = r.userRepository.UpdateOnline(loginLog.UserId, false)
|
||||
}
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user