mirror of
https://github.com/bjdgyc/anylink.git
synced 2025-08-11 02:43:13 +08:00
增加管理后台
This commit is contained in:
181
dbdata/db.go
181
dbdata/db.go
@@ -1,137 +1,90 @@
|
||||
package dbdata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/bjdgyc/anylink/common"
|
||||
"github.com/asdine/storm/v3"
|
||||
"github.com/asdine/storm/v3/codec/json"
|
||||
"github.com/bjdgyc/anylink/base"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
const pageSize = 10
|
||||
|
||||
var (
|
||||
db *bolt.DB
|
||||
ErrNoKey = errors.New("db no this key")
|
||||
sdb *storm.DB
|
||||
)
|
||||
|
||||
func initDb() {
|
||||
var err error
|
||||
db, err = bolt.Open(common.ServerCfg.DbFile, 0666, nil)
|
||||
sdb, err = storm.Open(base.Cfg.DbFile, storm.Codec(json.Codec),
|
||||
storm.BoltOptions(0600, &bolt.Options{Timeout: 10 * time.Second}))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
base.Fatal(err)
|
||||
}
|
||||
|
||||
// 创建bucket
|
||||
err = db.Update(func(tx *bolt.Tx) error {
|
||||
var err error
|
||||
_, err = tx.CreateBucketIfNotExists([]byte(BucketUser))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tx.CreateBucketIfNotExists([]byte(BucketGroup))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tx.CreateBucketIfNotExists([]byte(BucketMacIp))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// 初始化数据库
|
||||
err = sdb.Init(&User{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
base.Fatal(err)
|
||||
}
|
||||
|
||||
// fmt.Println("s1")
|
||||
}
|
||||
|
||||
func NextId(bucket string) int {
|
||||
var i int
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket))
|
||||
id, err := b.NextSequence()
|
||||
i = int(id)
|
||||
// discard error
|
||||
return err
|
||||
})
|
||||
return i
|
||||
func initData() {
|
||||
var (
|
||||
err error
|
||||
install bool
|
||||
)
|
||||
|
||||
// 判断是否初次使用
|
||||
err = Get(SettingBucket, Installed, &install)
|
||||
if err == nil && install {
|
||||
// 已经安装过
|
||||
return
|
||||
}
|
||||
|
||||
defer Set(SettingBucket, Installed, true)
|
||||
|
||||
smtp := &SettingSmtp{
|
||||
Host: "127.0.0.1",
|
||||
Port: 25,
|
||||
From: "vpn@xx.com",
|
||||
}
|
||||
SettingSet(smtp)
|
||||
|
||||
other := &SettingOther{
|
||||
Banner: "您已接入公司网络,请按照公司规定使用。\n请勿进行非工作下载及视频行为!",
|
||||
AccountMail: accountMail,
|
||||
}
|
||||
SettingSet(other)
|
||||
|
||||
}
|
||||
|
||||
func GetCount(bucket string) int {
|
||||
count := 0
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket([]byte(bucket))
|
||||
s := bkt.Stats()
|
||||
// fmt.Printf("%+v \n", s)
|
||||
count = s.KeyN
|
||||
return nil
|
||||
})
|
||||
return count
|
||||
func CheckErrNotFound(err error) bool {
|
||||
if err == storm.ErrNotFound {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Set(bucket, key string, v interface{}) error {
|
||||
return db.Update(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket([]byte(bucket))
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return bkt.Put([]byte(key), b)
|
||||
})
|
||||
}
|
||||
|
||||
func Del(bucket, key string) error {
|
||||
return db.Update(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket([]byte(bucket))
|
||||
return bkt.Delete([]byte(key))
|
||||
})
|
||||
}
|
||||
|
||||
func Get(bucket, key string, v interface{}) error {
|
||||
return db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket([]byte(bucket))
|
||||
b := bkt.Get([]byte(key))
|
||||
if b == nil {
|
||||
return ErrNoKey
|
||||
}
|
||||
return json.Unmarshal(b, v)
|
||||
})
|
||||
}
|
||||
|
||||
// 分页获取
|
||||
func getList(bucket, lastKey string, prev bool) [][]byte {
|
||||
res := make([][]byte, 0)
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket([]byte(bucket)).Cursor()
|
||||
size := pageSize
|
||||
k, b := c.Seek([]byte(lastKey))
|
||||
|
||||
if prev {
|
||||
for i := 0; i < size; i++ {
|
||||
k, b = c.Prev()
|
||||
if k == nil {
|
||||
break
|
||||
}
|
||||
res = append(res, b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// next
|
||||
if string(k) != lastKey {
|
||||
// 不相同,说明找出其他的
|
||||
size -= 1
|
||||
res = append(res, b)
|
||||
}
|
||||
for i := 0; i < size; i++ {
|
||||
k, b = c.Next()
|
||||
if k == nil {
|
||||
break
|
||||
}
|
||||
res = append(res, b)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return res
|
||||
}
|
||||
const accountMail = `<p>您好:</p>
|
||||
<p> 您的{{.Issuer}}账号已经审核开通。</p>
|
||||
<p>
|
||||
登陆地址: <b>{{.LinkAddr}}</b> <br/>
|
||||
用户组: <b>{{.Group}}</b> <br/>
|
||||
用户名: <b>{{.Username}}</b> <br/>
|
||||
用户PIN码: <b>{{.PinCode}}</b> <br/>
|
||||
用户动态码(3天后失效):<br/>
|
||||
<img src="{{.OtpImg}}"/>
|
||||
</p>
|
||||
<div>
|
||||
使用说明:
|
||||
<ul>
|
||||
<li>请使用OTP软件扫描动态码二维码</li>
|
||||
<li>然后使用anyconnect客户端进行登陆</li>
|
||||
<li>登陆密码为 【PIN码+动态码】</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
软件下载地址: https://gitee.com/bjdgyc/anylink-soft/blob/master/README.md
|
||||
</p>`
|
||||
|
66
dbdata/db_orm.go
Normal file
66
dbdata/db_orm.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package dbdata
|
||||
|
||||
import "github.com/asdine/storm/v3/index"
|
||||
|
||||
const PageSize = 10
|
||||
|
||||
func Save(data interface{}) error {
|
||||
return sdb.Save(data)
|
||||
}
|
||||
|
||||
func Update(data interface{}) error {
|
||||
return sdb.Update(data)
|
||||
}
|
||||
|
||||
func UpdateField(data interface{}, fieldName string, value interface{}) error {
|
||||
return sdb.UpdateField(data, fieldName, value)
|
||||
}
|
||||
|
||||
func Del(data interface{}) error {
|
||||
return sdb.DeleteStruct(data)
|
||||
}
|
||||
|
||||
func Set(bucket, key string, data interface{}) error {
|
||||
return sdb.Set(bucket, key, data)
|
||||
}
|
||||
|
||||
func Get(bucket, key string, data interface{}) error {
|
||||
return sdb.Get(bucket, key, data)
|
||||
}
|
||||
|
||||
func CountAll(data interface{}) int {
|
||||
n, _ := sdb.Count(data)
|
||||
return n
|
||||
}
|
||||
|
||||
func One(fieldName string, value interface{}, to interface{}) error {
|
||||
return sdb.One(fieldName, value, to)
|
||||
}
|
||||
|
||||
func Find(fieldName string, value interface{}, to interface{}, options ...func(q *index.Options)) error {
|
||||
return sdb.Find(fieldName, value, to, options...)
|
||||
}
|
||||
|
||||
func All(to interface{}, limit, page int) error {
|
||||
opt := getOpt(limit, page)
|
||||
return sdb.All(to, opt)
|
||||
}
|
||||
|
||||
func Prefix(fieldName string, prefix string, to interface{}, limit, page int) error {
|
||||
opt := getOpt(limit, page)
|
||||
return sdb.Prefix(fieldName, prefix, to, opt)
|
||||
}
|
||||
|
||||
func getOpt(limit, page int) func(*index.Options) {
|
||||
skip := (page - 1) * limit
|
||||
opt := func(opt *index.Options) {
|
||||
opt.Reverse = true
|
||||
if limit > 0 {
|
||||
opt.Limit = limit
|
||||
}
|
||||
if skip > 0 {
|
||||
opt.Skip = skip
|
||||
}
|
||||
}
|
||||
return opt
|
||||
}
|
@@ -1,23 +1,22 @@
|
||||
package dbdata
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/bjdgyc/anylink/common"
|
||||
"github.com/bjdgyc/anylink/base"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func preIpData() {
|
||||
tmpDb := path.Join(os.TempDir(), "anylink_test.db")
|
||||
common.ServerCfg.DbFile = tmpDb
|
||||
base.Cfg.DbFile = tmpDb
|
||||
initDb()
|
||||
}
|
||||
|
||||
func closeIpdata() {
|
||||
db.Close()
|
||||
sdb.Close()
|
||||
tmpDb := path.Join(os.TempDir(), "anylink_test.db")
|
||||
os.Remove(tmpDb)
|
||||
}
|
||||
@@ -27,37 +26,8 @@ func TestDb(t *testing.T) {
|
||||
preIpData()
|
||||
defer closeIpdata()
|
||||
|
||||
Set(BucketUser, "a", User{Username: "a"})
|
||||
Set(BucketUser, "b", User{Username: "b"})
|
||||
Set(BucketUser, "c", User{Username: "c"})
|
||||
Set(BucketUser, "d", User{Username: "d"})
|
||||
Set(BucketUser, "e", User{Username: "e"})
|
||||
Set(BucketUser, "f", User{Username: "f"})
|
||||
Set(BucketUser, "g", User{Username: "g"})
|
||||
u := User{Username: "a"}
|
||||
Save(&u)
|
||||
|
||||
c := GetCount(BucketUser)
|
||||
assert.Equal(c, 7)
|
||||
Del(BucketUser, "g")
|
||||
c = GetCount(BucketUser)
|
||||
assert.Equal(c, 6)
|
||||
|
||||
// 分页查询
|
||||
us := GetUsers("d", false)
|
||||
assert.Equal(us[0].Username, "e")
|
||||
assert.Equal(us[1].Username, "f")
|
||||
us = GetUsers("d", true)
|
||||
assert.Equal(us[0].Username, "c")
|
||||
assert.Equal(us[1].Username, "b")
|
||||
assert.Equal(us[2].Username, "a")
|
||||
|
||||
mac1 := MacIp{Ip: net.ParseIP("192.168.3.11"), MacAddr: "mac1"}
|
||||
mac2 := MacIp{Ip: net.ParseIP("192.168.3.12"), MacAddr: "mac2"}
|
||||
Set(BucketMacIp, "mac1", mac1)
|
||||
Set(BucketMacIp, "mac2", mac2)
|
||||
|
||||
mp := GetAllMacIp()
|
||||
assert.Equal(mp[0].MacAddr, "mac1")
|
||||
assert.Equal(mp[1].MacAddr, "mac2")
|
||||
|
||||
os.Exit(0)
|
||||
assert.Equal(u.Id, 1)
|
||||
}
|
||||
|
143
dbdata/group.go
143
dbdata/group.go
@@ -1,36 +1,133 @@
|
||||
package dbdata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bjdgyc/anylink/base"
|
||||
)
|
||||
|
||||
const BucketGroup = "group"
|
||||
const (
|
||||
Allow = "allow"
|
||||
Deny = "deny"
|
||||
)
|
||||
|
||||
type GroupLinkAcl struct {
|
||||
// 自上而下匹配 默认 allow * *
|
||||
Action string `json:"action"` // allow、deny
|
||||
Val string `json:"val"`
|
||||
Port uint8 `json:"port"`
|
||||
IpNet *net.IPNet `json:"-"`
|
||||
}
|
||||
|
||||
type ValData struct {
|
||||
Val string `json:"val"`
|
||||
}
|
||||
|
||||
type Group struct {
|
||||
Id int
|
||||
Name string
|
||||
RouteInclude []string
|
||||
RouteExclude []string
|
||||
AllowLan bool
|
||||
LinkAcl []struct {
|
||||
Action string // allow、deny
|
||||
IpNet string
|
||||
IPNet net.IPNet
|
||||
}
|
||||
Bandwidth int // 带宽限制
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
Id int `json:"id" storm:"id,increment"`
|
||||
Name string `json:"name" storm:"unique"`
|
||||
Note string `json:"note"`
|
||||
AllowLan bool `json:"allow_lan"`
|
||||
ClientDns []ValData `json:"client_dns"`
|
||||
RouteInclude []ValData `json:"route_include"`
|
||||
RouteExclude []ValData `json:"route_exclude"`
|
||||
LinkAcl []GroupLinkAcl `json:"link_acl"`
|
||||
Bandwidth int `json:"bandwidth"` // 带宽限制
|
||||
Status int8 `json:"status"` // 1正常
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func GetGroups(lastKey string, prev bool) []Group {
|
||||
res := getList(BucketUser, lastKey, prev)
|
||||
datas := make([]Group, 0)
|
||||
for _, data := range res {
|
||||
d := Group{}
|
||||
json.Unmarshal(data, &d)
|
||||
datas = append(datas, d)
|
||||
func GetGroupNames() []string {
|
||||
var datas []Group
|
||||
err := All(&datas, 0, 0)
|
||||
if err != nil {
|
||||
base.Error(err)
|
||||
return nil
|
||||
}
|
||||
return datas
|
||||
var names []string
|
||||
for _, v := range datas {
|
||||
names = append(names, v.Name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
func SetGroup(g *Group) error {
|
||||
var err error
|
||||
if g.Name == "" {
|
||||
return errors.New("用户组名错误")
|
||||
}
|
||||
|
||||
// 判断数据
|
||||
clientDns := []ValData{}
|
||||
for _, v := range g.ClientDns {
|
||||
if v.Val != "" {
|
||||
clientDns = append(clientDns, v)
|
||||
}
|
||||
}
|
||||
g.ClientDns = clientDns
|
||||
|
||||
routeInclude := []ValData{}
|
||||
for _, v := range g.RouteInclude {
|
||||
if v.Val != "" {
|
||||
v1, _ := parseIpNet(v.Val)
|
||||
vn := ValData{Val: v1}
|
||||
routeInclude = append(routeInclude, vn)
|
||||
}
|
||||
}
|
||||
g.RouteInclude = routeInclude
|
||||
routeExclude := []ValData{}
|
||||
for _, v := range g.RouteExclude {
|
||||
if v.Val != "" {
|
||||
v1, _ := parseIpNet(v.Val)
|
||||
vn := ValData{Val: v1}
|
||||
routeExclude = append(routeExclude, vn)
|
||||
}
|
||||
}
|
||||
g.RouteExclude = routeExclude
|
||||
// 转换数据
|
||||
linkAcl := []GroupLinkAcl{}
|
||||
for _, v := range g.LinkAcl {
|
||||
if v.Val != "" {
|
||||
v1, v2 := parseIpNet(v.Val)
|
||||
if v2 != nil {
|
||||
vn := v
|
||||
vn.Val = v1
|
||||
vn.IpNet = v2
|
||||
linkAcl = append(linkAcl, vn)
|
||||
}
|
||||
}
|
||||
}
|
||||
g.LinkAcl = linkAcl
|
||||
|
||||
g.UpdatedAt = time.Now()
|
||||
err = Save(g)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func parseIpNet(s string) (string, *net.IPNet) {
|
||||
ips := strings.Split(s, "/")
|
||||
if len(ips) != 2 {
|
||||
return "", nil
|
||||
}
|
||||
ip := net.ParseIP(ips[0])
|
||||
mask := net.ParseIP(ips[1])
|
||||
|
||||
if strings.Contains(ips[0], ".") {
|
||||
ip = ip.To4()
|
||||
mask = mask.To4()
|
||||
}
|
||||
|
||||
ipmask := net.IPMask(mask)
|
||||
ip0 := ip.Mask(ipmask)
|
||||
|
||||
ipNetS := fmt.Sprintf("%s/%s", ip0, mask)
|
||||
ipNet := &net.IPNet{IP: ip0, Mask: ipmask}
|
||||
|
||||
return ipNetS, ipNet
|
||||
}
|
||||
|
18
dbdata/ip_map.go
Normal file
18
dbdata/ip_map.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package dbdata
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IpMap struct {
|
||||
Id int `json:"id" storm:"id,increment"`
|
||||
IpAddr net.IP `json:"ip_addr" storm:"unique"`
|
||||
MacAddr string `json:"mac_addr" storm:"unique"`
|
||||
Username string `json:"username"`
|
||||
Keep bool `json:"keep"` // 保留 ip-mac 绑定
|
||||
KeepTime time.Time `json:"keep_time"`
|
||||
Note string `json:"note"` // 备注
|
||||
LastLogin time.Time `json:"last_login"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
package dbdata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
const BucketMacIp = "macIp"
|
||||
|
||||
type MacIp struct {
|
||||
IsActive bool // db存储没有使用
|
||||
Ip net.IP
|
||||
MacAddr string
|
||||
LastLogin time.Time
|
||||
}
|
||||
|
||||
func GetAllMacIp() []MacIp {
|
||||
datas := make([]MacIp, 0)
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket([]byte(BucketMacIp))
|
||||
bkt.ForEach(func(k, v []byte) error {
|
||||
d := MacIp{}
|
||||
json.Unmarshal(v, &d)
|
||||
datas = append(datas, d)
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
})
|
||||
|
||||
return datas
|
||||
}
|
46
dbdata/setting.go
Normal file
46
dbdata/setting.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package dbdata
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
const (
|
||||
SettingBucket = "SettingBucket"
|
||||
Installed = "Installed"
|
||||
)
|
||||
|
||||
func StructName(data interface{}) string {
|
||||
ref := reflect.ValueOf(data)
|
||||
s := &ref
|
||||
if s.Kind() == reflect.Ptr {
|
||||
e := s.Elem()
|
||||
s = &e
|
||||
}
|
||||
name := s.Type().Name()
|
||||
return name
|
||||
}
|
||||
|
||||
func SettingSet(data interface{}) error {
|
||||
key := StructName(data)
|
||||
err := Set(SettingBucket, key, data)
|
||||
return err
|
||||
}
|
||||
|
||||
func SettingGet(data interface{}) error {
|
||||
key := StructName(data)
|
||||
err := Get(SettingBucket, key, data)
|
||||
return err
|
||||
}
|
||||
|
||||
type SettingSmtp struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
From string `json:"from"`
|
||||
}
|
||||
|
||||
type SettingOther struct {
|
||||
Banner string `json:"banner"`
|
||||
AccountMail string `json:"account_mail"`
|
||||
}
|
@@ -2,8 +2,9 @@ package dbdata
|
||||
|
||||
func Start() {
|
||||
initDb()
|
||||
initData()
|
||||
}
|
||||
|
||||
func Stop() error {
|
||||
return db.Close()
|
||||
return sdb.Close()
|
||||
}
|
||||
|
105
dbdata/user.go
105
dbdata/user.go
@@ -1,29 +1,98 @@
|
||||
package dbdata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/bjdgyc/anylink/pkg/utils"
|
||||
"github.com/xlzd/gotp"
|
||||
)
|
||||
|
||||
const BucketUser = "user"
|
||||
|
||||
type User struct {
|
||||
Id int
|
||||
Username string
|
||||
Password string
|
||||
OtpSecret string
|
||||
Group []string
|
||||
// CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
Id int `json:"id" storm:"id,increment"`
|
||||
Username string `json:"username" storm:"unique"`
|
||||
Nickname string `json:"nickname"`
|
||||
Email string `json:"email"`
|
||||
// Password string `json:"password"`
|
||||
PinCode string `json:"pin_code"`
|
||||
OtpSecret string `json:"otp_secret"`
|
||||
Groups []string `json:"groups"`
|
||||
Status int8 `json:"status"` // 1正常
|
||||
SendEmail bool `json:"send_email"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func GetUsers(lastKey string, prev bool) []User {
|
||||
res := getList(BucketUser, lastKey, prev)
|
||||
datas := make([]User, 0)
|
||||
for _, data := range res {
|
||||
d := User{}
|
||||
json.Unmarshal(data, &d)
|
||||
datas = append(datas, d)
|
||||
// 验证用户登陆信息
|
||||
func CheckUser(name, pwd, group string) error {
|
||||
// return nil
|
||||
|
||||
pl := len(pwd)
|
||||
if name == "" || pl < 6 {
|
||||
return errors.New("密码错误")
|
||||
}
|
||||
return datas
|
||||
v := &User{}
|
||||
err := One("Username", name, v)
|
||||
if err != nil || v.Status != 1 {
|
||||
return errors.New("用户名错误")
|
||||
}
|
||||
pass := pwd[:pl-6]
|
||||
// if !utils.PasswordVerify(pass, v.Password) {
|
||||
if pass != v.PinCode {
|
||||
return errors.New("密码错误")
|
||||
}
|
||||
otp := pwd[pl-6:]
|
||||
totp := gotp.NewDefaultTOTP(v.OtpSecret)
|
||||
unix := time.Now().Unix()
|
||||
verify := totp.Verify(otp, int(unix))
|
||||
if !verify {
|
||||
return errors.New("动态码错误")
|
||||
}
|
||||
|
||||
// 判断用户组信息
|
||||
if !utils.InArrStr(v.Groups, group) {
|
||||
return errors.New("用户组错误")
|
||||
}
|
||||
groupData := &Group{}
|
||||
err = One("Name", group, groupData)
|
||||
if err != nil || groupData.Status != 1 {
|
||||
return errors.New("用户组错误")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetUser(v *User) error {
|
||||
var err error
|
||||
if v.Username == "" || len(v.Groups) == 0 {
|
||||
return errors.New("用户名或组错误")
|
||||
}
|
||||
|
||||
planPass := v.PinCode
|
||||
// 自动生成密码
|
||||
if len(planPass) < 6 {
|
||||
planPass = utils.RandomNum(8)
|
||||
}
|
||||
v.PinCode = planPass
|
||||
|
||||
if v.OtpSecret == "" {
|
||||
v.OtpSecret = gotp.RandomSecret(24)
|
||||
}
|
||||
|
||||
// 判断组是否有效
|
||||
ng := []string{}
|
||||
groups := GetGroupNames()
|
||||
for _, g := range v.Groups {
|
||||
if utils.InArrStr(groups, g) {
|
||||
ng = append(ng, g)
|
||||
}
|
||||
}
|
||||
if len(ng) == 0 {
|
||||
return errors.New("用户名或组错误")
|
||||
}
|
||||
v.Groups = ng
|
||||
|
||||
v.UpdatedAt = time.Now()
|
||||
err = Save(v)
|
||||
|
||||
return err
|
||||
}
|
||||
|
Reference in New Issue
Block a user