forked from x/icebergs
221 lines
6.8 KiB
Go
221 lines
6.8 KiB
Go
package aaa
|
|
|
|
import (
|
|
"github.com/shylinux/icebergs"
|
|
"github.com/shylinux/toolkits"
|
|
|
|
"strings"
|
|
)
|
|
|
|
func _role_list(m *ice.Message) {
|
|
kit.Fetch(m.Confv("role", "meta.root"), func(key string, value string) {
|
|
m.Push("userrole", "root").Push("username", key)
|
|
})
|
|
kit.Fetch(m.Confv("role", "meta.tech"), func(key string, value string) {
|
|
m.Push("userrole", "tech").Push("username", key)
|
|
})
|
|
}
|
|
func _role_black(m *ice.Message, userrole, chain, status string) {
|
|
m.Rich(ice.AAA_ROLE, kit.Keys("black", userrole), kit.Dict(
|
|
"chain", chain, "status", status,
|
|
))
|
|
m.Logs(ice.LOG_ENABLE, "role", userrole, "black", chain)
|
|
}
|
|
func _role_white(m *ice.Message, userrole, chain, status string) {
|
|
m.Rich(ice.AAA_ROLE, kit.Keys("white", userrole), kit.Dict(
|
|
"chain", chain, "status", status,
|
|
))
|
|
m.Logs(ice.LOG_ENABLE, "role", userrole, "white", chain)
|
|
}
|
|
func _role_check(m *ice.Message, username string) {
|
|
m.Echo(kit.Select(kit.Select("void",
|
|
"tech", m.Confs(ice.AAA_ROLE, kit.Keys("meta.tech", username))),
|
|
"root", m.Confs(ice.AAA_ROLE, kit.Keys("meta.root", username))))
|
|
}
|
|
func _role_right(m *ice.Message, userrole string, keys ...string) bool {
|
|
ok := true
|
|
for i := 0; i < len(keys); i++ {
|
|
// 黑名单
|
|
m.Richs(ice.AAA_ROLE, kit.Keys("black", userrole), kit.Keys(keys[:i+1]), func(key string, value map[string]interface{}) {
|
|
if value["status"] == "true" {
|
|
ok = false
|
|
}
|
|
})
|
|
}
|
|
if m.Warn(!ok, "black right %s", keys) {
|
|
return false
|
|
}
|
|
|
|
if m.Option(ice.MSG_USERROLE) == ice.ROLE_TECH {
|
|
// 管理用户
|
|
return true
|
|
}
|
|
|
|
ok = false
|
|
for i := 0; i < len(keys); i++ {
|
|
// 白名单
|
|
m.Richs(ice.AAA_ROLE, kit.Keys("white", userrole), kit.Keys(keys[:i+1]), func(key string, value map[string]interface{}) {
|
|
if value["status"] == "true" {
|
|
ok = true
|
|
}
|
|
})
|
|
}
|
|
if m.Warn(!ok, "no white right %s", keys) {
|
|
return false
|
|
}
|
|
|
|
// 普通用户
|
|
return true
|
|
}
|
|
func _role_auth(m *ice.Message, userrole, username, status string) {
|
|
m.Conf(ice.AAA_ROLE, kit.Keys("meta", userrole, username), status)
|
|
}
|
|
|
|
var Index = &ice.Context{Name: "aaa", Help: "认证模块",
|
|
Caches: map[string]*ice.Cache{},
|
|
Configs: map[string]*ice.Config{
|
|
ice.AAA_ROLE: {Name: "role", Help: "角色", Value: kit.Data(kit.MDB_SHORT, "chain")},
|
|
ice.AAA_USER: {Name: "user", Help: "用户", Value: kit.Data(kit.MDB_SHORT, "username")},
|
|
ice.AAA_SESS: {Name: "sess", Help: "会话", Value: kit.Data(kit.MDB_SHORT, "uniq", "expire", "720h")},
|
|
},
|
|
Commands: map[string]*ice.Command{
|
|
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
m.Load()
|
|
// 权限索引
|
|
m.Conf(ice.AAA_ROLE, "black.tech.meta.short", "chain")
|
|
m.Conf(ice.AAA_ROLE, "white.tech.meta.short", "chain")
|
|
m.Conf(ice.AAA_ROLE, "black.void.meta.short", "chain")
|
|
m.Conf(ice.AAA_ROLE, "white.void.meta.short", "chain")
|
|
}},
|
|
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
m.Save(ice.AAA_ROLE, ice.AAA_USER, ice.AAA_SESS)
|
|
}},
|
|
|
|
ice.AAA_ROLE: {Name: []string{
|
|
"role black|white userrole chain",
|
|
"role check|userrole username",
|
|
}, Help: "角色", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
if len(arg) == 0 {
|
|
_role_list(m)
|
|
return
|
|
}
|
|
|
|
switch arg[0] {
|
|
case "right":
|
|
if m.Option(ice.MSG_USERROLE) == ice.ROLE_ROOT {
|
|
// 超级用户
|
|
m.Echo("ok")
|
|
} else if _role_right(m, kit.Select("void", arg, 1), strings.Split(kit.Keys(arg[2:]), ".")...) {
|
|
// 其它用户
|
|
m.Echo("ok")
|
|
}
|
|
case "check":
|
|
if len(arg) > 1 && arg[1] != "" {
|
|
_role_check(m, arg[1])
|
|
}
|
|
case "white":
|
|
_role_white(m, arg[1], kit.Keys(arg[2:]), "true")
|
|
case "black":
|
|
_role_black(m, arg[1], kit.Keys(arg[2:]), "true")
|
|
default:
|
|
_role_auth(m, arg[0], arg[1], kit.Select("true", arg, 2))
|
|
}
|
|
}},
|
|
ice.AAA_USER: {Name: "user first|login", Help: "用户", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
if len(arg) == 0 {
|
|
// 用户列表
|
|
m.Richs(ice.AAA_USER, nil, "*", func(key string, value map[string]interface{}) {
|
|
m.Push(key, value, []string{"time", "username", "usernode"})
|
|
})
|
|
return
|
|
}
|
|
|
|
switch arg[0] {
|
|
case "first":
|
|
// 超级用户
|
|
if m.Richs(ice.AAA_USER, nil, "%", nil) == nil {
|
|
m.Rich(ice.AAA_USER, nil, kit.Dict("username", arg[1],
|
|
"usernode", m.Conf(ice.CLI_RUNTIME, "boot.hostname"),
|
|
))
|
|
user := m.Richs(ice.AAA_USER, nil, arg[1], nil)
|
|
m.Info("create user: %s %s", arg[1], kit.Format(user))
|
|
m.Event(ice.USER_CREATE, arg[1])
|
|
}
|
|
|
|
case "login":
|
|
// 用户认证
|
|
user := m.Richs(ice.AAA_USER, nil, arg[1], nil)
|
|
if word := kit.Select("", arg, 2); user == nil {
|
|
nick := arg[1]
|
|
if len(nick) > 8 {
|
|
nick = nick[:8]
|
|
}
|
|
// 创建用户
|
|
m.Rich(ice.AAA_USER, nil, kit.Dict(
|
|
"usernick", nick, "username", arg[1], "password", word,
|
|
"usernode", m.Conf(ice.CLI_RUNTIME, "boot.hostname"),
|
|
))
|
|
user = m.Richs(ice.AAA_USER, nil, arg[1], nil)
|
|
m.Log(ice.LOG_CREATE, "%s: %s", arg[1], kit.Format(user))
|
|
m.Event(ice.USER_CREATE, arg[1])
|
|
|
|
} else if word != "" {
|
|
if kit.Format(user["password"]) == "" {
|
|
// 设置密码
|
|
user["password"] = word
|
|
} else if kit.Format(user["password"]) != word {
|
|
// 认证失败
|
|
m.Info("login fail user: %s", arg[1])
|
|
break
|
|
}
|
|
}
|
|
|
|
if m.Options(ice.MSG_SESSID) && m.Cmdx(ice.AAA_SESS, "check", m.Option(ice.MSG_SESSID)) == arg[1] {
|
|
// 复用会话
|
|
m.Echo(m.Option(ice.MSG_SESSID))
|
|
break
|
|
}
|
|
|
|
// 创建会话
|
|
m.Echo(m.Cmdx(ice.AAA_SESS, "create", arg[1]))
|
|
}
|
|
}},
|
|
ice.AAA_SESS: {Name: "sess check|login", Help: "会话", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
if len(arg) == 0 {
|
|
// 会话列表
|
|
m.Richs(ice.AAA_SESS, nil, "*", func(key string, value map[string]interface{}) {
|
|
m.Push(key, value, []string{"key", "time", "username", "userrole"})
|
|
})
|
|
return
|
|
}
|
|
|
|
switch arg[0] {
|
|
case "auth":
|
|
m.Richs(ice.AAA_SESS, nil, arg[1], func(value map[string]interface{}) {
|
|
value["username"], value["userrole"] = arg[2], m.Cmdx(ice.AAA_ROLE, "check", arg[2])
|
|
m.Log(ice.LOG_AUTH, "sessid: %s username: %s userrole: %s", arg[1], arg[2], value["userrole"])
|
|
m.Echo("%v", value["userrole"])
|
|
})
|
|
|
|
case "check":
|
|
// 查看会话
|
|
m.Richs(ice.AAA_SESS, nil, arg[1], func(value map[string]interface{}) {
|
|
m.Push(arg[1], value, []string{"username", "userrole"})
|
|
m.Echo("%s", value["username"])
|
|
})
|
|
|
|
case "create":
|
|
// 创建会话
|
|
h := m.Rich(ice.AAA_SESS, nil, kit.Dict(
|
|
"username", arg[1], "userrole", m.Cmdx(ice.AAA_ROLE, "check", arg[1]),
|
|
"from", m.Option(ice.MSG_SESSID),
|
|
))
|
|
m.Log(ice.LOG_CREATE, "sessid: %s username: %s", h, arg[1])
|
|
m.Echo(h)
|
|
}
|
|
}},
|
|
},
|
|
}
|
|
|
|
func init() { ice.Index.Register(Index, nil) }
|