* 优化图标和LOGO

* 修改登录页面动画的速度为3

* 增加对websocket的异常处理

* 修复了用户组和用户名唯一判断错误的问题

* 提示版本号

* 修复readme错别字

* 修复单词拼写错误的问题

* 修复代码格式

* 修改Windows资产属性名称

* Docker 打包流程增加 upx 压缩

* 升级依赖文件,修改sqlite驱动为 github.com/glebarez/sqlite

* 修复第一次查询「授权令牌」的错误

* 移除无关代码

* 修改docker打包脚本

* 增加打包脚本

* 增加微信群

* 修复单词拼写错误的问题

* 修复代码格式

* 修改Windows资产属性名称

* Docker 打包流程增加 upx 压缩

* 修改docker打包脚本

* - 替换 sqlite 驱动为 github.com/glebarez/sqlite
- 修复数据库锁定的问题
- 修复部分代码不完善的问题
- 修复策略显示不完整的问题
- 修复编辑文件换行符的问题
- 优化guacd连接
This commit is contained in:
dushixiang
2022-03-29 22:40:26 +08:00
committed by GitHub
parent 3ec6e5332e
commit 04f8d0079b
42 changed files with 436 additions and 568 deletions

View File

@ -19,14 +19,9 @@ type accessTokenService struct {
baseService
}
func (service accessTokenService) FindByUserId(userId string) (model.AccessToken, error) {
return repository.AccessTokenRepository.FindByUserId(context.TODO(), userId)
}
func (service accessTokenService) GenAccessToken(userId string) error {
return env.GetDB().Transaction(func(tx *gorm.DB) error {
ctx := service.Context(tx)
user, err := repository.UserRepository.FindById(ctx, userId)
if err != nil {
return err

View File

@ -119,7 +119,7 @@ func (s assetService) FindByIdAndDecrypt(c context.Context, id string) (model.As
func (s assetService) CheckStatus(accessGatewayId string, ip string, port int) (active bool, err error) {
if accessGatewayId != "" && accessGatewayId != "-" {
g, e1 := GatewayService.GetGatewayAndReconnectById(accessGatewayId)
if err != nil {
if e1 != nil {
return false, e1
}
@ -141,7 +141,7 @@ func (s assetService) CheckStatus(accessGatewayId string, ip string, port int) (
return active, err
}
func (s assetService) Create(m echo.Map) (model.Asset, error) {
func (s assetService) Create(ctx context.Context, m echo.Map) (model.Asset, error) {
data, err := json.Marshal(m)
if err != nil {
@ -156,29 +156,36 @@ func (s assetService) Create(m echo.Map) (model.Asset, error) {
item.Created = utils.NowJsonTime()
item.Active = true
return item, env.GetDB().Transaction(func(tx *gorm.DB) error {
c := s.Context(tx)
if s.InTransaction(ctx) {
return item, s.create(ctx, item, m)
} else {
return item, env.GetDB().Transaction(func(tx *gorm.DB) error {
c := s.Context(tx)
return s.create(c, item, m)
})
}
}
if err := s.Encrypt(&item, config.GlobalCfg.EncryptionPassword); err != nil {
return err
}
if err := repository.AssetRepository.Create(c, &item); err != nil {
return err
}
func (s assetService) create(c context.Context, item model.Asset, m echo.Map) error {
if err := s.Encrypt(&item, config.GlobalCfg.EncryptionPassword); err != nil {
return err
}
if err := repository.AssetRepository.Create(c, &item); err != nil {
return err
}
if err := repository.AssetRepository.UpdateAttributes(c, item.ID, item.Protocol, m); err != nil {
return err
}
if err := repository.AssetRepository.UpdateAttributes(c, item.ID, item.Protocol, m); err != nil {
return err
}
go func() {
active, _ := s.CheckStatus(item.AccessGatewayId, item.IP, item.Port)
if item.Active != active {
_ = repository.AssetRepository.UpdateActiveById(context.TODO(), active, item.ID)
}
}()
return nil
})
//go func() {
// active, _ := s.CheckStatus(item.AccessGatewayId, item.IP, item.Port)
//
// if item.Active != active {
// _ = repository.AssetRepository.UpdateActiveById(context.TODO(), active, item.ID)
// }
//}()
return nil
}
func (s assetService) DeleteById(id string) error {

View File

@ -128,12 +128,12 @@ func (service backupService) Export() (error, *dto.Backup) {
func (service backupService) Import(backup *dto.Backup) error {
return env.GetDB().Transaction(func(tx *gorm.DB) error {
c := service.Context(tx)
ctx := service.Context(tx)
var userIdMapping = make(map[string]string)
if len(backup.Users) > 0 {
for _, item := range backup.Users {
oldId := item.ID
exist, err := repository.UserRepository.ExistByUsername(c, item.Username)
exist, err := repository.UserRepository.ExistByUsername(ctx, item.Username)
if err != nil {
return err
}
@ -144,7 +144,7 @@ func (service backupService) Import(backup *dto.Backup) error {
newId := utils.UUID()
item.ID = newId
item.Password = utils.GenPassword()
if err := repository.UserRepository.Create(c, &item); err != nil {
if err := repository.UserRepository.Create(ctx, &item); err != nil {
return err
}
userIdMapping[oldId] = newId
@ -163,7 +163,7 @@ func (service backupService) Import(backup *dto.Backup) error {
}
}
userGroup, err := UserGroupService.Create(item.Name, members)
userGroup, err := UserGroupService.Create(ctx, item.Name, members)
if err != nil {
if errors.Is(constant.ErrNameAlreadyUsed, err) {
// 删除名称重复的用户组
@ -187,7 +187,7 @@ func (service backupService) Import(backup *dto.Backup) error {
item.ID = utils.UUID()
item.Owner = owner
item.Created = utils.NowJsonTime()
if err := repository.StorageRepository.Create(c, &item); err != nil {
if err := repository.StorageRepository.Create(ctx, &item); err != nil {
return err
}
}
@ -200,7 +200,7 @@ func (service backupService) Import(backup *dto.Backup) error {
newId := utils.UUID()
item.ID = newId
item.Created = utils.NowJsonTime()
if err := repository.StrategyRepository.Create(c, &item); err != nil {
if err := repository.StrategyRepository.Create(ctx, &item); err != nil {
return err
}
strategyIdMapping[oldId] = newId
@ -210,7 +210,7 @@ func (service backupService) Import(backup *dto.Backup) error {
if len(backup.AccessSecurities) > 0 {
for _, item := range backup.AccessSecurities {
item.ID = utils.UUID()
if err := repository.SecurityRepository.Create(c, &item); err != nil {
if err := repository.SecurityRepository.Create(ctx, &item); err != nil {
return err
}
// 更新内存中的安全规则
@ -231,7 +231,7 @@ func (service backupService) Import(backup *dto.Backup) error {
newId := utils.UUID()
item.ID = newId
item.Created = utils.NowJsonTime()
if err := repository.GatewayRepository.Create(c, &item); err != nil {
if err := repository.GatewayRepository.Create(ctx, &item); err != nil {
return err
}
accessGatewayIdMapping[oldId] = newId
@ -242,7 +242,7 @@ func (service backupService) Import(backup *dto.Backup) error {
for _, item := range backup.Commands {
item.ID = utils.UUID()
item.Created = utils.NowJsonTime()
if err := repository.CommandRepository.Create(c, &item); err != nil {
if err := repository.CommandRepository.Create(ctx, &item); err != nil {
return err
}
}
@ -254,7 +254,7 @@ func (service backupService) Import(backup *dto.Backup) error {
oldId := item.ID
newId := utils.UUID()
item.ID = newId
if err := CredentialService.Create(&item); err != nil {
if err := CredentialService.Create(ctx, &item); err != nil {
return err
}
credentialIdMapping[oldId] = newId
@ -282,7 +282,7 @@ func (service backupService) Import(backup *dto.Backup) error {
}
oldId := m["id"].(string)
asset, err := AssetService.Create(m)
asset, err := AssetService.Create(ctx, m)
if err != nil {
return err
}
@ -299,7 +299,7 @@ func (service backupService) Import(backup *dto.Backup) error {
strategyId := strategyIdMapping[item.StrategyId]
resourceId := assetIdMapping[item.ResourceId]
if err := repository.ResourceSharerRepository.AddSharerResources(userGroupId, userId, strategyId, item.ResourceType, []string{resourceId}); err != nil {
if err := UserService.AddSharerResources(ctx, userGroupId, userId, strategyId, item.ResourceType, []string{resourceId}); err != nil {
return err
}
}
@ -311,6 +311,7 @@ func (service backupService) Import(backup *dto.Backup) error {
continue
}
item.ID = utils.UUID()
resourceIds := strings.Split(item.ResourceIds, ",")
if len(resourceIds) > 0 {
var newResourceIds = make([]string, 0)
@ -319,7 +320,7 @@ func (service backupService) Import(backup *dto.Backup) error {
}
item.ResourceIds = strings.Join(newResourceIds, ",")
}
if err := JobService.Create(&item); err != nil {
if err := JobService.Create(ctx, &item); err != nil {
return err
}
}

View File

@ -14,3 +14,8 @@ type baseService struct {
func (service baseService) Context(db *gorm.DB) context.Context {
return context.WithValue(context.TODO(), constant.DB, db)
}
func (service baseService) InTransaction(ctx context.Context) bool {
_, ok := ctx.Value(constant.DB).(*gorm.DB)
return ok
}

View File

@ -99,8 +99,8 @@ func (s credentialService) Decrypt(item *model.Credential, password []byte) erro
return nil
}
func (s credentialService) FindByIdAndDecrypt(c context.Context, id string) (o model.Credential, err error) {
credential, err := repository.CredentialRepository.FindById(c, id)
func (s credentialService) FindByIdAndDecrypt(ctx context.Context, id string) (o model.Credential, err error) {
credential, err := repository.CredentialRepository.FindById(ctx, id)
if err != nil {
return o, err
}
@ -110,10 +110,10 @@ func (s credentialService) FindByIdAndDecrypt(c context.Context, id string) (o m
return credential, nil
}
func (s credentialService) Create(item *model.Credential) error {
func (s credentialService) Create(ctx context.Context, item *model.Credential) error {
// 加密密码之后进行存储
if err := s.Encrypt(item, config.GlobalCfg.EncryptionPassword); err != nil {
return err
}
return repository.CredentialRepository.Create(context.TODO(), item)
return repository.CredentialRepository.Create(ctx, item)
}

View File

@ -103,7 +103,7 @@ func (r jobService) InitJob() error {
return nil
}
func (r jobService) Create(o *model.Job) (err error) {
func (r jobService) Create(ctx context.Context, o *model.Job) (err error) {
if o.Status == constant.JobStatusRunning {
j, err := getJob(o)
@ -117,7 +117,7 @@ func (r jobService) Create(o *model.Job) (err error) {
o.CronJobId = int(jobId)
}
return repository.JobRepository.Create(context.TODO(), o)
return repository.JobRepository.Create(ctx, o)
}
func (r jobService) DeleteJobById(id string) error {

View File

@ -2,6 +2,7 @@ package service
import (
"context"
"fmt"
"net/smtp"
"next-terminal/server/constant"
@ -27,7 +28,7 @@ func (r mailService) SendMail(to, subject, text string) {
}
e := email.NewEmail()
e.From = "Next Terminal <" + username + ">"
e.From = fmt.Sprintf("%s <%s>", constant.AppName, username)
e.To = []string{to}
e.Subject = subject
e.Text = []byte(text)

View File

@ -17,161 +17,63 @@ type propertyService struct {
baseService
}
var deprecatedPropertyNames = []string{
guacd.EnableDrive,
guacd.DrivePath,
guacd.DriveName,
guacd.DisableGlyphCaching,
guacd.CreateRecordingPath,
}
var defaultProperties = map[string]string{
guacd.EnableRecording: "true",
guacd.FontName: "menlo",
guacd.FontSize: "12",
guacd.ColorScheme: "gray-black",
guacd.EnableWallpaper: "true",
guacd.EnableTheming: "true",
guacd.EnableFontSmoothing: "true",
guacd.EnableFullWindowDrag: "true",
guacd.EnableDesktopComposition: "true",
guacd.EnableMenuAnimations: "true",
guacd.DisableBitmapCaching: "false",
guacd.DisableOffscreenCaching: "false",
"cron-log-saved-limit": "360",
"login-log-saved-limit": "360",
"session-saved-limit": "360",
"user-default-storage-size": "5120",
}
func (service propertyService) InitProperties() error {
propertyMap := repository.PropertyRepository.FindAllMap(context.TODO())
if len(propertyMap[guacd.EnableRecording]) == 0 {
property := model.Property{
Name: guacd.EnableRecording,
Value: "true",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
for name, value := range defaultProperties {
if err := service.CreateIfAbsent(propertyMap, name, value); err != nil {
return err
}
}
if len(propertyMap[guacd.CreateRecordingPath]) == 0 {
property := model.Property{
Name: guacd.CreateRecordingPath,
Value: "true",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
return nil
}
if len(propertyMap[guacd.FontName]) == 0 {
func (service propertyService) CreateIfAbsent(propertyMap map[string]string, name, value string) error {
if len(propertyMap[name]) == 0 {
property := model.Property{
Name: guacd.FontName,
Value: "menlo",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.FontSize]) == 0 {
property := model.Property{
Name: guacd.FontSize,
Value: "12",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.ColorScheme]) == 0 {
property := model.Property{
Name: guacd.ColorScheme,
Value: "gray-black",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.EnableWallpaper]) == 0 {
property := model.Property{
Name: guacd.EnableWallpaper,
Value: "false",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.EnableTheming]) == 0 {
property := model.Property{
Name: guacd.EnableTheming,
Value: "false",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.EnableFontSmoothing]) == 0 {
property := model.Property{
Name: guacd.EnableFontSmoothing,
Value: "false",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.EnableFullWindowDrag]) == 0 {
property := model.Property{
Name: guacd.EnableFullWindowDrag,
Value: "false",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.EnableDesktopComposition]) == 0 {
property := model.Property{
Name: guacd.EnableDesktopComposition,
Value: "false",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.EnableMenuAnimations]) == 0 {
property := model.Property{
Name: guacd.EnableMenuAnimations,
Value: "false",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.DisableBitmapCaching]) == 0 {
property := model.Property{
Name: guacd.DisableBitmapCaching,
Value: "false",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.DisableOffscreenCaching]) == 0 {
property := model.Property{
Name: guacd.DisableOffscreenCaching,
Value: "false",
}
if err := repository.PropertyRepository.Create(context.TODO(), &property); err != nil {
return err
}
}
if len(propertyMap[guacd.DisableGlyphCaching]) > 0 {
if err := repository.PropertyRepository.DeleteByName(context.TODO(), guacd.DisableGlyphCaching); err != nil {
return err
Name: name,
Value: value,
}
return repository.PropertyRepository.Create(context.TODO(), &property)
}
return nil
}
func (service propertyService) DeleteDeprecatedProperty() error {
propertyMap := repository.PropertyRepository.FindAllMap(context.TODO())
if propertyMap[guacd.EnableDrive] != "" {
if err := repository.PropertyRepository.DeleteByName(context.TODO(), guacd.DriveName); err != nil {
return err
for _, name := range deprecatedPropertyNames {
if propertyMap[name] == "" {
continue
}
}
if propertyMap[guacd.DrivePath] != "" {
if err := repository.PropertyRepository.DeleteByName(context.TODO(), guacd.DrivePath); err != nil {
return err
}
}
if propertyMap[guacd.DriveName] != "" {
if err := repository.PropertyRepository.DeleteByName(context.TODO(), guacd.DriveName); err != nil {
if err := repository.PropertyRepository.DeleteByName(context.TODO(), name); err != nil {
return err
}
}

View File

@ -4,11 +4,14 @@ import (
"bufio"
"context"
"errors"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
"path"
"strconv"
"strings"
"next-terminal/server/config"
@ -33,7 +36,7 @@ func (service storageService) InitStorages() error {
userId := users[i].ID
_, err := repository.StorageRepository.FindByOwnerIdAndDefault(context.TODO(), userId, true)
if errors.Is(err, gorm.ErrRecordNotFound) {
err = service.CreateStorageByUser(&users[i])
err = service.CreateStorageByUser(context.TODO(), &users[i])
if err != nil {
return err
}
@ -58,7 +61,7 @@ func (service storageService) InitStorages() error {
}
if !userExist {
if err := service.DeleteStorageById(storage.ID, true); err != nil {
if err := service.DeleteStorageById(context.TODO(), storage.ID, true); err != nil {
return err
}
}
@ -75,14 +78,29 @@ func (service storageService) InitStorages() error {
return nil
}
func (service storageService) CreateStorageByUser(user *model.User) error {
func (service storageService) CreateStorageByUser(c context.Context, user *model.User) error {
drivePath := service.GetBaseDrivePath()
var limitSize int64 = -1
property, err := repository.PropertyRepository.FindByName(c, "user-default-storage-size")
if err != nil {
return err
}
limitSize, err = strconv.ParseInt(property.Value, 10, 64)
if err != nil {
return err
}
limitSize = limitSize * 1024 * 1024
if limitSize < 0 {
limitSize = -1
}
storage := model.Storage{
ID: user.ID,
Name: user.Nickname + "的默认空间",
IsShare: false,
IsDefault: true,
LimitSize: -1,
LimitSize: limitSize,
Owner: user.ID,
Created: utils.NowJsonTime(),
}
@ -91,8 +109,9 @@ func (service storageService) CreateStorageByUser(user *model.User) error {
return err
}
log.Infof("创建storage:「%v」文件夹: %v", storage.Name, storageDir)
err := repository.StorageRepository.Create(context.TODO(), &storage)
err = repository.StorageRepository.Create(c, &storage)
if err != nil {
_ = os.RemoveAll(storageDir)
return err
}
return nil
@ -135,9 +154,9 @@ func (service storageService) GetBaseDrivePath() string {
return config.GlobalCfg.Guacd.Drive
}
func (service storageService) DeleteStorageById(id string, force bool) error {
func (service storageService) DeleteStorageById(c context.Context, id string, force bool) error {
drivePath := service.GetBaseDrivePath()
storage, err := repository.StorageRepository.FindById(context.TODO(), id)
storage, err := repository.StorageRepository.FindById(c, id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
@ -152,7 +171,7 @@ func (service storageService) DeleteStorageById(id string, force bool) error {
if err := os.RemoveAll(path.Join(drivePath, id)); err != nil {
return err
}
if err := repository.StorageRepository.DeleteById(context.TODO(), id); err != nil {
if err := repository.StorageRepository.DeleteById(c, id); err != nil {
return err
}
return nil
@ -229,14 +248,20 @@ func (service storageService) StorageEdit(file string, fileContent string, stora
return nil
}
func (service storageService) StorageDownload(c echo.Context, remoteFile, storageId string) error {
func (service storageService) StorageDownload(c echo.Context, file, storageId string) error {
drivePath := service.GetBaseDrivePath()
if strings.Contains(remoteFile, "../") {
if strings.Contains(file, "../") {
return errors.New("非法请求 :(")
}
// 获取带后缀的文件名称
filenameWithSuffix := path.Base(remoteFile)
return c.Attachment(path.Join(path.Join(drivePath, storageId), remoteFile), filenameWithSuffix)
filenameWithSuffix := path.Base(file)
p := path.Join(path.Join(drivePath, storageId), file)
//log.Infof("download %v", p)
c.Response().Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filenameWithSuffix))
c.Response().Header().Set("Content-Type", "application/octet-stream")
http.ServeFile(c.Response(), c.Request(), p)
return nil
}
func (service storageService) StorageLs(remoteDir, storageId string) (error, []File) {

View File

@ -90,31 +90,31 @@ func (service userService) FixUserOnlineState() error {
return nil
}
func (service userService) Logout(token string) {
cache.TokenManager.Delete(token)
}
func (service userService) LogoutByToken(token string) (err error) {
return env.GetDB().Transaction(func(tx *gorm.DB) error {
c := service.Context(tx)
loginLog, err := repository.LoginLogRepository.FindById(c, token)
if err != nil {
return err
}
cache.TokenManager.Delete(token)
loginLogForUpdate := &model.LoginLog{LogoutTime: utils.NowJsonTime(), ID: token}
err = repository.LoginLogRepository.Update(c, loginLogForUpdate)
if err != nil {
return err
}
loginLogs, err := repository.LoginLogRepository.FindAliveLoginLogsByUsername(c, loginLog.Username)
if err != nil {
return err
}
if len(loginLogs) == 0 {
err = repository.UserRepository.UpdateOnlineByUsername(c, loginLog.Username, false)
}
loginLog, err := repository.LoginLogRepository.FindById(context.TODO(), token)
if err != nil {
return err
})
}
loginLogForUpdate := &model.LoginLog{LogoutTime: utils.NowJsonTime(), ID: token}
err = repository.LoginLogRepository.Update(context.TODO(), loginLogForUpdate)
if err != nil {
return err
}
loginLogs, err := repository.LoginLogRepository.FindAliveLoginLogsByUsername(context.TODO(), loginLog.Username)
if err != nil {
return err
}
if len(loginLogs) == 0 {
err = repository.UserRepository.UpdateOnlineByUsername(context.TODO(), loginLog.Username, false)
}
return err
}
func (service userService) LogoutById(c context.Context, id string) error {
@ -130,13 +130,26 @@ func (service userService) LogoutById(c context.Context, id string) error {
for j := range loginLogs {
token := loginLogs[j].ID
if err := service.LogoutByToken(token); err != nil {
return err
}
service.Logout(token)
}
return nil
}
func (service userService) GetUserLoginToken(c context.Context, username string) ([]string, error) {
loginLogs, err := repository.LoginLogRepository.FindAliveLoginLogsByUsername(c, username)
if err != nil {
return nil, err
}
var tokens []string
for j := range loginLogs {
token := loginLogs[j].ID
tokens = append(tokens, token)
}
return tokens, nil
}
func (service userService) OnEvicted(token string, value interface{}) {
if strings.HasPrefix(token, "forever") {
@ -144,30 +157,24 @@ func (service userService) OnEvicted(token string, value interface{}) {
} else {
log.Debugf("用户Token「%v」过期", token)
err := service.LogoutByToken(token)
if err != nil {
if err != nil && !errors.Is(gorm.ErrRecordNotFound, err) {
log.Errorf("退出登录失败 %v", err)
}
}
}
func (service userService) UpdateStatusById(id string, status string) error {
return env.GetDB().Transaction(func(tx *gorm.DB) error {
c := service.Context(tx)
if c.Value(constant.DB) == nil {
c = context.WithValue(c, constant.DB, env.GetDB())
if constant.StatusDisabled == status {
// 将该用户下线
if err := service.LogoutById(context.TODO(), id); err != nil {
return err
}
if constant.StatusDisabled == status {
// 将该用户下线
if err := service.LogoutById(c, id); err != nil {
return err
}
}
u := model.User{
ID: id,
Status: status,
}
return repository.UserRepository.Update(c, &u)
})
}
u := model.User{
ID: id,
Status: status,
}
return repository.UserRepository.Update(context.TODO(), &u)
}
@ -231,13 +238,19 @@ func (service userService) CreateUser(user model.User) (err error) {
if err := repository.UserRepository.Create(c, &user); err != nil {
return err
}
err = StorageService.CreateStorageByUser(&user)
err = StorageService.CreateStorageByUser(c, &user)
if err != nil {
return err
}
if user.Mail != "" {
go MailService.SendMail(user.Mail, "[Next Terminal] 注册通知", "你好,"+user.Nickname+"。管理员为你注册了账号:"+user.Username+" 密码:"+password)
subject := fmt.Sprintf("%s 注册通知", constant.AppName)
text := fmt.Sprintf(`您好,%s。
管理员为你开通了账户。
账号:%s
密码:%s
`, user.Username, user.Username, password)
go MailService.SendMail(user.Mail, subject, text)
}
return nil
})
@ -245,16 +258,19 @@ func (service userService) CreateUser(user model.User) (err error) {
}
func (service userService) DeleteUserById(userId string) error {
return env.GetDB().Transaction(func(tx *gorm.DB) error {
user, err := repository.UserRepository.FindById(context.TODO(), userId)
if err != nil {
return err
}
username := user.Username
// 下线该用户
loginTokens, err := service.GetUserLoginToken(context.TODO(), username)
if err != nil {
return err
}
err = env.GetDB().Transaction(func(tx *gorm.DB) error {
c := service.Context(tx)
// 下线该用户
if err := service.LogoutById(c, userId); err != nil {
return err
}
// 删除用户
if err := repository.UserRepository.DeleteById(c, userId); err != nil {
return err
}
// 删除用户与用户组的关系
if err := repository.UserGroupMemberRepository.DeleteByUserId(c, userId); err != nil {
return err
@ -264,19 +280,37 @@ func (service userService) DeleteUserById(userId string) error {
return err
}
// 删除用户的默认磁盘空间
if err := StorageService.DeleteStorageById(userId, true); err != nil {
if err := StorageService.DeleteStorageById(c, userId, true); err != nil {
return err
}
// 删除用户
if err := repository.UserRepository.DeleteById(c, userId); err != nil {
return err
}
return nil
})
if err != nil {
return err
}
for _, token := range loginTokens {
service.Logout(token)
}
return nil
}
func (service userService) DeleteLoginLogs(tokens []string) error {
if len(tokens) > 0 {
for _, token := range tokens {
// 手动触发用户退出登录
if err := service.LogoutByToken(token); err != nil {
return err
}
// 移除缓存中的token
service.Logout(token)
// 删除登录日志
if err := repository.LoginLogRepository.DeleteById(context.TODO(), token); err != nil {
return err
}
@ -337,3 +371,37 @@ func (service userService) UpdateUser(id string, user model.User) error {
})
}
func (service userService) AddSharerResources(ctx context.Context, userGroupId, userId, strategyId, resourceType string, resourceIds []string) error {
if service.InTransaction(ctx) {
return service.addSharerResources(ctx, resourceIds, userGroupId, userId, strategyId, resourceType)
} else {
return env.GetDB().Transaction(func(tx *gorm.DB) error {
ctx2 := service.Context(tx)
return service.addSharerResources(ctx2, resourceIds, userGroupId, userId, strategyId, resourceType)
})
}
}
func (service userService) addSharerResources(ctx context.Context, resourceIds []string, userGroupId string, userId string, strategyId string, resourceType string) error {
for i := range resourceIds {
resourceId := resourceIds[i]
// 保证同一个资产只能分配给一个用户或者组
id := utils.Sign([]string{resourceId, resourceType, userId, userGroupId})
if err := repository.ResourceSharerRepository.DeleteById(ctx, id); err != nil {
return err
}
rs := &model.ResourceSharer{
ID: id,
ResourceId: resourceId,
ResourceType: resourceType,
StrategyId: strategyId,
UserId: userId,
UserGroupId: userGroupId,
}
if err := repository.ResourceSharerRepository.AddSharerResource(ctx, rs); err != nil {
return err
}
}
return nil
}

View File

@ -13,11 +13,12 @@ import (
)
type userGroupService struct {
baseService
}
func (service userGroupService) DeleteById(userGroupId string) error {
return env.GetDB().Transaction(func(tx *gorm.DB) error {
c := context.WithValue(context.TODO(), constant.DB, tx)
c := service.Context(tx)
// 删除用户组
if err := repository.UserGroupRepository.DeleteById(c, userGroupId); err != nil {
return err
@ -34,8 +35,8 @@ func (service userGroupService) DeleteById(userGroupId string) error {
})
}
func (service userGroupService) Create(name string, members []string) (model.UserGroup, error) {
exist, err := repository.UserGroupRepository.ExistByName(context.TODO(), name)
func (service userGroupService) Create(ctx context.Context, name string, members []string) (model.UserGroup, error) {
exist, err := repository.UserGroupRepository.ExistByName(ctx, name)
if err != nil {
return model.UserGroup{}, err
}
@ -51,26 +52,33 @@ func (service userGroupService) Create(name string, members []string) (model.Use
Name: name,
}
return userGroup, env.GetDB().Transaction(func(tx *gorm.DB) error {
c := context.WithValue(context.TODO(), constant.DB, tx)
if err := repository.UserGroupRepository.Create(c, &userGroup); err != nil {
return err
}
if len(members) > 0 {
for _, member := range members {
userGroupMember := model.UserGroupMember{
ID: utils.Sign([]string{userGroupId, member}),
UserId: member,
UserGroupId: userGroupId,
}
if err := repository.UserGroupMemberRepository.Create(c, &userGroupMember); err != nil {
return err
}
if service.InTransaction(ctx) {
return userGroup, service.create(ctx, userGroup, members, userGroupId)
} else {
return userGroup, env.GetDB().Transaction(func(tx *gorm.DB) error {
c := service.Context(tx)
return service.create(c, userGroup, members, userGroupId)
})
}
}
func (service userGroupService) create(c context.Context, userGroup model.UserGroup, members []string, userGroupId string) error {
if err := repository.UserGroupRepository.Create(c, &userGroup); err != nil {
return err
}
if len(members) > 0 {
for _, member := range members {
userGroupMember := model.UserGroupMember{
ID: utils.Sign([]string{userGroupId, member}),
UserId: member,
UserGroupId: userGroupId,
}
if err := repository.UserGroupMemberRepository.Create(c, &userGroupMember); err != nil {
return err
}
}
return nil
})
}
return nil
}
func (service userGroupService) Update(userGroupId string, name string, members []string) (err error) {
@ -91,7 +99,7 @@ func (service userGroupService) Update(userGroupId string, name string, members
}
return env.GetDB().Transaction(func(tx *gorm.DB) error {
c := context.WithValue(context.TODO(), constant.DB, tx)
c := service.Context(tx)
userGroup := model.UserGroup{
ID: userGroupId,
Name: name,