322 lines
8.4 KiB
Go
322 lines
8.4 KiB
Go
package service
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/gin-gonic/gin"
|
|
"hy2xs-admin/dao"
|
|
"hy2xs-admin/model/bo"
|
|
"hy2xs-admin/model/constant"
|
|
"hy2xs-admin/model/dto"
|
|
"hy2xs-admin/model/entity"
|
|
"hy2xs-admin/model/vo"
|
|
"hy2xs-admin/util"
|
|
"time"
|
|
)
|
|
|
|
func Login(username string, plainPassword string) (string, bool, error) {
|
|
account, err := dao.GetAdminUser("username = ? and status = 1", username)
|
|
if err != nil {
|
|
return "", false, err
|
|
}
|
|
|
|
verified, legacy := util.VerifyPassword(plainPassword, *account.PasswordHash)
|
|
if !verified {
|
|
return "", false, errors.New(constant.WrongPassword)
|
|
}
|
|
|
|
if legacy {
|
|
hash, hashErr := util.HashPassword(plainPassword)
|
|
if hashErr == nil {
|
|
_ = dao.UpdateAdminUser([]int64{*account.Id}, map[string]interface{}{"password_hash": hash})
|
|
}
|
|
}
|
|
|
|
accountBo := bo.AccountBo{
|
|
Id: *account.Id,
|
|
Username: *account.Username,
|
|
Roles: []string{"admin"},
|
|
Deleted: 0,
|
|
}
|
|
token, tokenErr := GenToken(accountBo)
|
|
if tokenErr != nil {
|
|
return "", false, tokenErr
|
|
}
|
|
|
|
requirePasswordChange := legacy
|
|
if account.ForcePasswordChange != nil {
|
|
requirePasswordChange = *account.ForcePasswordChange != 0
|
|
}
|
|
return token, requirePasswordChange, nil
|
|
}
|
|
|
|
func PagePeer(peerPageDto dto.PeerPageDto) ([]entity.Account, int64, error) {
|
|
peers, total, err := dao.PagePeer(peerPageDto)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
accounts := make([]entity.Account, 0, len(peers))
|
|
for _, p := range peers {
|
|
role := "user"
|
|
acc := entity.Account{
|
|
BaseEntity: p.BaseEntity,
|
|
Username: p.Name,
|
|
ConPass: p.SecretCiphertext,
|
|
Quota: p.QuotaBytes,
|
|
Download: p.DownloadBytes,
|
|
Upload: p.UploadBytes,
|
|
ExpireTime: p.ExpiresAt,
|
|
KickUtilTime: p.BannedUntil,
|
|
DeviceNo: p.MaxDevices,
|
|
Role: &role,
|
|
Deleted: p.Disabled,
|
|
ConAt: p.LastConnectionAt,
|
|
Remark: p.Remark,
|
|
}
|
|
accounts = append(accounts, acc)
|
|
}
|
|
return accounts, total, nil
|
|
}
|
|
|
|
func SavePeer(account entity.Account) error {
|
|
if account.Username == nil || *account.Username == "" {
|
|
return errors.New(constant.InvalidError)
|
|
}
|
|
secret := ""
|
|
if account.ConPass != nil && *account.ConPass != "" {
|
|
secret = *account.ConPass
|
|
} else {
|
|
generated, genErr := util.RandomString(24)
|
|
if genErr != nil {
|
|
return genErr
|
|
}
|
|
secret = fmt.Sprintf("%s.%s", *account.Username, generated)
|
|
}
|
|
authId, authErr := util.RandomString(18)
|
|
if authErr != nil {
|
|
return authErr
|
|
}
|
|
secretDigest := util.PeerSecretDigest(secret)
|
|
peer := entity.Peer{
|
|
Name: account.Username,
|
|
Remark: account.Remark,
|
|
AuthId: &authId,
|
|
SecretDigest: &secretDigest,
|
|
SecretCiphertext: &secret,
|
|
QuotaBytes: account.Quota,
|
|
ExpiresAt: account.ExpireTime,
|
|
MaxDevices: account.DeviceNo,
|
|
Disabled: account.Deleted,
|
|
}
|
|
_, err := dao.SavePeer(peer)
|
|
return err
|
|
}
|
|
|
|
func DeletePeer(ids []int64) error {
|
|
return dao.DeletePeer(ids)
|
|
}
|
|
|
|
func UpdatePeer(account entity.Account) error {
|
|
updates := map[string]interface{}{}
|
|
if account.Username != nil && *account.Username != "" {
|
|
updates["username"] = *account.Username
|
|
}
|
|
_ = account.Pass
|
|
if account.ConPass != nil && *account.ConPass != "" {
|
|
updates["secret_ciphertext"] = *account.ConPass
|
|
updates["secret_digest"] = util.PeerSecretDigest(*account.ConPass)
|
|
}
|
|
if account.Quota != nil {
|
|
updates["quota_bytes"] = *account.Quota
|
|
}
|
|
if account.ExpireTime != nil {
|
|
updates["expires_at"] = *account.ExpireTime
|
|
}
|
|
if account.Download != nil {
|
|
updates["download_bytes"] = *account.Download
|
|
}
|
|
if account.Upload != nil {
|
|
updates["upload_bytes"] = *account.Upload
|
|
}
|
|
if account.DeviceNo != nil {
|
|
updates["max_devices"] = *account.DeviceNo
|
|
}
|
|
if account.Deleted != nil {
|
|
updates["disabled"] = *account.Deleted
|
|
}
|
|
if account.LoginAt != nil && *account.LoginAt > 0 {
|
|
updates["login_at"] = *account.LoginAt
|
|
}
|
|
if account.ConAt != nil && *account.ConAt > 0 {
|
|
updates["last_connection_at"] = *account.ConAt
|
|
}
|
|
if account.Remark != nil {
|
|
updates["remark"] = *account.Remark
|
|
}
|
|
return dao.UpdatePeer([]int64{*account.Id}, updates)
|
|
}
|
|
|
|
func ResetTraffic(id int64) error {
|
|
return dao.UpdatePeer([]int64{id}, map[string]interface{}{"download_bytes": 0, "upload_bytes": 0})
|
|
}
|
|
|
|
func ExistPeerName(username string, id int64) bool {
|
|
var err error
|
|
if id != 0 {
|
|
_, err = dao.GetPeer("name = ? and id != ?", username, id)
|
|
} else {
|
|
_, err = dao.GetPeer("name = ?", username)
|
|
}
|
|
if err != nil {
|
|
if err.Error() == constant.WrongPassword {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func GetPeer(id int64) (entity.Account, error) {
|
|
peer, err := dao.GetPeer("id = ?", id)
|
|
if err != nil {
|
|
return entity.Account{}, err
|
|
}
|
|
role := "user"
|
|
return entity.Account{
|
|
BaseEntity: peer.BaseEntity,
|
|
Username: peer.Name,
|
|
ConPass: peer.SecretCiphertext,
|
|
Quota: peer.QuotaBytes,
|
|
Download: peer.DownloadBytes,
|
|
Upload: peer.UploadBytes,
|
|
ExpireTime: peer.ExpiresAt,
|
|
DeviceNo: peer.MaxDevices,
|
|
KickUtilTime: peer.BannedUntil,
|
|
ConAt: peer.LastConnectionAt,
|
|
Deleted: peer.Disabled,
|
|
Remark: peer.Remark,
|
|
Role: &role,
|
|
}, nil
|
|
}
|
|
|
|
func GetAdminAccount(id int64) (entity.AdminUser, error) {
|
|
return dao.GetAdminUser("id = ?", id)
|
|
}
|
|
|
|
func ListExportPeer() ([]bo.AccountExport, error) {
|
|
peers, err := dao.ListPeer("1=1")
|
|
if err != nil {
|
|
return nil, errors.New(constant.SysError)
|
|
}
|
|
var accountExports []bo.AccountExport
|
|
for _, item := range peers {
|
|
role := "user"
|
|
conPass := ""
|
|
if item.SecretCiphertext != nil {
|
|
conPass = *item.SecretCiphertext
|
|
}
|
|
accountExport := bo.AccountExport{
|
|
Id: *item.Id,
|
|
Username: *item.Name,
|
|
Pass: "",
|
|
ConPass: conPass,
|
|
Quota: *item.QuotaBytes,
|
|
Download: *item.DownloadBytes,
|
|
Upload: *item.UploadBytes,
|
|
ExpireTime: *item.ExpiresAt,
|
|
DeviceNo: *item.MaxDevices,
|
|
KickUtilTime: *item.BannedUntil,
|
|
Role: role,
|
|
Deleted: *item.Disabled,
|
|
CreateTime: *item.CreateTime,
|
|
UpdateTime: *item.UpdateTime,
|
|
LoginAt: 0,
|
|
ConAt: *item.LastConnectionAt,
|
|
Remark: *item.Remark,
|
|
}
|
|
accountExports = append(accountExports, accountExport)
|
|
}
|
|
return accountExports, nil
|
|
}
|
|
|
|
func ReleaseKickPeer(id int64) error {
|
|
return dao.UpdatePeer([]int64{id}, map[string]interface{}{"banned_until": 0})
|
|
}
|
|
|
|
func UpsertPeer(accounts []entity.Account) error {
|
|
for _, account := range accounts {
|
|
if account.Id != nil && *account.Id > 0 {
|
|
if err := UpdatePeer(account); err != nil {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
if err := SavePeer(account); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetAdminInfo(c *gin.Context) (vo.AccountInfoVo, error) {
|
|
myClaims, err := ParseToken(GetToken(c))
|
|
if err != nil {
|
|
return vo.AccountInfoVo{}, err
|
|
}
|
|
if myClaims.Admin.Deleted != 0 {
|
|
return vo.AccountInfoVo{}, errors.New("this account has been disabled")
|
|
}
|
|
admin, err := dao.GetAdminUser("id = ?", myClaims.Admin.Id)
|
|
if err != nil {
|
|
return vo.AccountInfoVo{}, err
|
|
}
|
|
if admin.Status != nil && *admin.Status == 0 {
|
|
return vo.AccountInfoVo{}, errors.New("this account has been disabled")
|
|
}
|
|
return vo.AccountInfoVo{
|
|
Id: myClaims.Admin.Id,
|
|
Username: myClaims.Admin.Username,
|
|
Roles: myClaims.Admin.Roles,
|
|
}, nil
|
|
}
|
|
|
|
func UpdatePeerLastConnectionAt(id int64, conAt int64) error {
|
|
return dao.UpdatePeer([]int64{id}, map[string]interface{}{"last_connection_at": conAt})
|
|
}
|
|
|
|
func UpdateAdminLastLoginAt(id int64, loginAt int64) error {
|
|
return dao.UpdateAdminUser([]int64{id}, map[string]interface{}{"last_login_at": loginAt})
|
|
}
|
|
|
|
func ChangeAdminPassword(c *gin.Context, oldPassword string, newPassword string) error {
|
|
info, err := GetAdminInfo(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
admin, err := dao.GetAdminUser("id = ?", info.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if admin.PasswordHash == nil {
|
|
return errors.New(constant.SysError)
|
|
}
|
|
verified, _ := util.VerifyPassword(oldPassword, *admin.PasswordHash)
|
|
if !verified {
|
|
return errors.New(constant.WrongPassword)
|
|
}
|
|
hash, hashErr := util.HashPassword(newPassword)
|
|
if hashErr != nil {
|
|
return hashErr
|
|
}
|
|
nowMs := time.Now().UnixMilli()
|
|
currentTokenVersion := int64(1)
|
|
if admin.TokenVersion != nil && *admin.TokenVersion > 0 {
|
|
currentTokenVersion = *admin.TokenVersion
|
|
}
|
|
return dao.UpdateAdminUser([]int64{info.Id}, map[string]interface{}{
|
|
"password_hash": hash,
|
|
"force_password_change": 0,
|
|
"password_changed_at": nowMs,
|
|
"token_version": currentTokenVersion + 1,
|
|
})
|
|
}
|