forked from x/icebergs
109 lines
2.9 KiB
Go
109 lines
2.9 KiB
Go
package auth
|
|
|
|
import (
|
|
"github.com/shylinux/icebergs"
|
|
"github.com/shylinux/icebergs/base/aaa"
|
|
"github.com/shylinux/toolkits"
|
|
|
|
"bytes"
|
|
"crypto/hmac"
|
|
"crypto/sha1"
|
|
"encoding/base32"
|
|
"encoding/binary"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func gen() string {
|
|
buf := bytes.NewBuffer([]byte{})
|
|
binary.Write(buf, binary.BigEndian, time.Now().Unix()/30)
|
|
b := hmac.New(sha1.New, buf.Bytes()).Sum(nil)
|
|
return strings.ToUpper(base32.StdEncoding.EncodeToString(b[:]))
|
|
}
|
|
|
|
func get(key string) string {
|
|
buf := []byte{}
|
|
now := kit.Int64(time.Now().Unix() / 30)
|
|
for i := 0; i < 8; i++ {
|
|
buf = append(buf, byte((now >> ((7 - i) * 8))))
|
|
}
|
|
|
|
s, _ := base32.StdEncoding.DecodeString(strings.ToUpper(key))
|
|
|
|
hm := hmac.New(sha1.New, s)
|
|
hm.Write(buf)
|
|
b := hm.Sum(nil)
|
|
|
|
o := b[len(b)-1] & 0x0F
|
|
p := b[o : o+4]
|
|
p[0] = p[0] & 0x7f
|
|
res := int64(p[0])<<24 + int64(p[1])<<16 + int64(p[2])<<8 + int64(p[3])
|
|
return kit.Format("%06d", res%1000000)
|
|
}
|
|
|
|
var Index = &ice.Context{Name: "auth", Help: "auth",
|
|
Caches: map[string]*ice.Cache{},
|
|
Configs: map[string]*ice.Config{
|
|
"auth": {Name: "auth", Help: "auth", Value: kit.Data(kit.MDB_SHORT, "name")},
|
|
},
|
|
Commands: map[string]*ice.Command{
|
|
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
m.Load()
|
|
}},
|
|
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
m.Save("auth")
|
|
}},
|
|
|
|
"new": {Name: "new user [secrete]", Help: "创建动态码", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
if len(arg) == 0 {
|
|
m.Richs("auth", nil, "*", func(key string, value map[string]interface{}) {
|
|
m.Push(key, value, []string{"name", "username", "website"})
|
|
})
|
|
return
|
|
}
|
|
|
|
m.Append("_output", "qrcode")
|
|
if len(arg) == 1 {
|
|
if m.Richs("auth", nil, arg[0], func(key string, value map[string]interface{}) {
|
|
m.Echo("otpauth://totp/%s?secret=%s", value["name"], value["secrete"])
|
|
}) != nil {
|
|
return
|
|
}
|
|
arg = append(arg, gen())
|
|
}
|
|
|
|
data := kit.Dict("name", arg[0], "secrete", arg[1])
|
|
for i := 2; i < len(arg)-1; i += 2 {
|
|
kit.Value(data, arg[i], arg[i+1])
|
|
}
|
|
|
|
n := m.Rich("auth", nil, data)
|
|
m.Log(ice.LOG_CREATE, "%s", n)
|
|
|
|
m.Cmdy(ice.WEB_SHARE, "optauth", arg[0], kit.Format("otpauth://totp/%s?secret=%s", arg[0], arg[1]))
|
|
}},
|
|
"get": {Name: "get user [secrete]", Help: "获取动态码", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
if len(arg) == 0 {
|
|
m.Richs("auth", nil, "*", func(key string, value map[string]interface{}) {
|
|
m.Push("name", value["name"])
|
|
m.Push("code", m.Cmdx("get", value["name"], value["secrete"]))
|
|
})
|
|
return
|
|
}
|
|
|
|
if len(arg) == 1 {
|
|
m.Richs("auth", nil, arg[0], func(key string, value map[string]interface{}) {
|
|
arg = append(arg, kit.Format(value["secrete"]))
|
|
})
|
|
}
|
|
if len(arg) == 1 {
|
|
arg = append(arg, m.Cmdx("new", arg[0]))
|
|
}
|
|
|
|
m.Echo(get(arg[1]))
|
|
}},
|
|
},
|
|
}
|
|
|
|
func init() { aaa.Index.Register(Index, nil) }
|