1
0
forked from x/icebergs
This commit is contained in:
shaoying 2020-03-17 13:21:41 +08:00
parent 0b9351f5c3
commit b0f8396853
6 changed files with 333 additions and 308 deletions

View File

@ -161,9 +161,9 @@ var Index = &ice.Context{Name: "aaa", Help: "认证模块",
case "create": case "create":
// 创建会话 // 创建会话
h := m.Rich(ice.AAA_SESS, nil, kit.Dict( h := m.Rich(ice.AAA_SESS, nil, kit.Dict(
"username", arg[1], "userrole", kit.Select("", arg, 2), "username", arg[1], "userrole", m.Cmdx(ice.AAA_ROLE, "check", arg[1]),
)) ))
m.Log(ice.LOG_CREATE, "%s: %s", h, arg[1]) m.Log(ice.LOG_CREATE, "sessid: %s username: %s", h, arg[1])
m.Echo(h) m.Echo(h)
} }
}}, }},

View File

@ -7,6 +7,7 @@ import (
var share_template = kit.Dict( var share_template = kit.Dict(
"value", `<img src="/share/%s/value">`, "value", `<img src="/share/%s/value">`,
"share", `<img src="/share/%s/share">`, "share", `<img src="/share/%s/share">`,
"text", `<img src="/share/%s/text">`,
"link", `<a href="/share/%s" target="_blank">%s</a>`, "link", `<a href="/share/%s" target="_blank">%s</a>`,
"simple", `<!DOCTYPE html> "simple", `<!DOCTYPE html>

View File

@ -41,7 +41,7 @@ func Count(m *ice.Message, cmd, key, name string) int {
return count return count
} }
func Render(msg *ice.Message, cmd string, args ...interface{}) *ice.Message { func Render(msg *ice.Message, cmd string, args ...interface{}) *ice.Message {
msg.Info("render %s: %v", cmd, args) msg.Log(ice.LOG_EXPORT, "%s: %v", cmd, args)
switch arg := kit.Simple(args...); cmd { switch arg := kit.Simple(args...); cmd {
case "redirect": case "redirect":
http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), 307) http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), 307)
@ -78,22 +78,30 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) *ice.Message {
msg.Append("_output", "render") msg.Append("_output", "render")
return msg return msg
} }
func IsLocalIP(ip string) bool { func IsLocalIP(msg *ice.Message, ip string) (ok bool) {
return ip == "::1" || strings.HasPrefix(ip, "127.") if ip == "::1" || strings.HasPrefix(ip, "127.") {
return true
}
msg.Cmd("tcp.ifconfig").Table(func(index int, value map[string]string, head []string) {
if value["ip"] == ip {
ok = true
}
})
return ok
} }
func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool { func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool {
msg.Option(ice.MSG_USERNAME, "") msg.Option(ice.MSG_USERNAME, "")
msg.Option(ice.MSG_USERROLE, "") msg.Option(ice.MSG_USERROLE, "")
if msg.Options(ice.WEB_SESS) { if msg.Options(ice.MSG_SESSID) {
// 会话认证 // 会话认证
sub := msg.Cmd(ice.AAA_SESS, "check", msg.Option(ice.WEB_SESS)) sub := msg.Cmd(ice.AAA_SESS, "check", msg.Option(ice.MSG_SESSID))
msg.Log(ice.LOG_LOGIN, "role: %s user: %s", msg.Option(ice.MSG_USERROLE, sub.Append("userrole")), msg.Log(ice.LOG_LOGIN, "role: %s user: %s", msg.Option(ice.MSG_USERROLE, sub.Append("userrole")),
msg.Option(ice.MSG_USERNAME, sub.Append("username"))) msg.Option(ice.MSG_USERNAME, sub.Append("username")))
} }
if (!msg.Options(ice.MSG_SESSID) || !msg.Options(ice.MSG_USERNAME)) && IsLocalIP(msg.Option(ice.MSG_USERIP)) { if !msg.Options(ice.MSG_USERNAME) && IsLocalIP(msg, msg.Option(ice.MSG_USERIP)) {
// 自动认证 // 自动认证
msg.Option(ice.MSG_USERNAME, msg.Conf(ice.CLI_RUNTIME, "boot.username")) msg.Option(ice.MSG_USERNAME, msg.Conf(ice.CLI_RUNTIME, "boot.username"))
msg.Option(ice.MSG_USERROLE, msg.Cmdx(ice.AAA_ROLE, "check", msg.Option(ice.MSG_USERNAME))) msg.Option(ice.MSG_USERROLE, msg.Cmdx(ice.AAA_ROLE, "check", msg.Option(ice.MSG_USERNAME)))
@ -107,7 +115,22 @@ func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request
if s, ok := msg.Target().Commands[ice.WEB_LOGIN]; ok { if s, ok := msg.Target().Commands[ice.WEB_LOGIN]; ok {
// 权限检查 // 权限检查
msg.Target().Run(msg, s, ice.WEB_LOGIN, kit.Simple(msg.Optionv("cmds"))...) msg.Target().Run(msg, s, ice.WEB_LOGIN, kit.Simple(msg.Optionv("cmds"))...)
} else if strings.HasPrefix(msg.Option(ice.MSG_USERURL), "/static/") {
} else if strings.HasPrefix(msg.Option(ice.MSG_USERURL), "/plugin/") {
} else if strings.HasPrefix(msg.Option(ice.MSG_USERURL), "/space/") {
} else if strings.HasPrefix(msg.Option(ice.MSG_USERURL), "/route/") {
} else if strings.HasPrefix(msg.Option(ice.MSG_USERURL), "/share/") {
} else {
if msg.Warn(!msg.Options(ice.MSG_USERNAME), "not login %s", msg.Option(ice.MSG_USERURL)) {
Render(msg, "status", 401, "not login")
return false
} }
if !msg.Right(msg.Option(ice.MSG_USERURL)) {
Render(msg, "status", 403, "not auth")
return false
}
}
return msg.Option(ice.MSG_USERURL) != "" return msg.Option(ice.MSG_USERURL) != ""
} }
func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn, name string) bool { func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn, name string) bool {
@ -216,21 +239,21 @@ func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) {
m.TryCatch(m.Spawns(), true, func(msg *ice.Message) { m.TryCatch(m.Spawns(), true, func(msg *ice.Message) {
defer func() { msg.Cost("%s %v", r.URL.Path, msg.Optionv("cmds")) }() defer func() { msg.Cost("%s %v", r.URL.Path, msg.Optionv("cmds")) }()
// 解析请求 // 请求地址
msg.Option(ice.MSG_USERUA, r.Header.Get("User-Agent")) msg.Option(ice.MSG_USERUA, r.Header.Get("User-Agent"))
msg.Option(ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP)) msg.Option(ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP))
msg.Option(ice.MSG_USERURL, r.URL.Path) msg.Option(ice.MSG_USERURL, r.URL.Path)
msg.Option(ice.WEB_SESS, "") msg.Option(ice.MSG_SESSID, "")
msg.R, msg.W = r, w msg.R, msg.W = r, w
// 请求环境 // 请求变量
for _, v := range r.Cookies() { for _, v := range r.Cookies() {
if v.Value != "" { if v.Value != "" {
msg.Option(v.Name, v.Value) msg.Option(v.Name, v.Value)
} }
} }
// 请求数据 // 解析引擎
switch r.Header.Get("Content-Type") { switch r.Header.Get("Content-Type") {
case "application/json": case "application/json":
var data interface{} var data interface{}
@ -261,22 +284,22 @@ func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) {
} }
} }
if !web.Login(msg, w, r) { // 请求命令
// 登录失败
w.WriteHeader(401)
return
}
// 解析命令
if msg.Optionv("cmds") == nil { if msg.Optionv("cmds") == nil {
msg.Optionv("cmds", strings.Split(msg.Option(ice.MSG_USERURL), "/")[2:]) msg.Optionv("cmds", strings.Split(strings.TrimPrefix(msg.Option(ice.MSG_USERURL), key), "/"))
} }
cmds := kit.Simple(msg.Optionv("cmds")) cmds := kit.Simple(msg.Optionv("cmds"))
// 登录检查
if !web.Login(msg, w, r) {
// Render(msg, "status", 401, "not login")
return
}
// 执行命令 // 执行命令
msg.Target().Run(msg, cmd, msg.Option(ice.MSG_USERURL), cmds...) msg.Target().Run(msg, cmd, msg.Option(ice.MSG_USERURL), cmds...)
// 输出响应 // 渲染引擎
switch msg.Append("_output") { switch msg.Append("_output") {
case "render": case "render":
case "result": case "result":
@ -465,6 +488,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
m.Watch(ice.SYSTEM_INIT, "web.code.git.repos", "volcanos", m.Conf(ice.WEB_SERVE, "meta.volcanos.path"), m.Watch(ice.SYSTEM_INIT, "web.code.git.repos", "volcanos", m.Conf(ice.WEB_SERVE, "meta.volcanos.path"),
m.Conf(ice.WEB_SERVE, "meta.volcanos.repos"), m.Conf(ice.WEB_SERVE, "meta.volcanos.branch")) m.Conf(ice.WEB_SERVE, "meta.volcanos.repos"), m.Conf(ice.WEB_SERVE, "meta.volcanos.branch"))
m.Conf(ice.WEB_FAVOR, "meta.template", favor_template) m.Conf(ice.WEB_FAVOR, "meta.template", favor_template)
m.Conf(ice.WEB_SHARE, "meta.template", share_template)
}}, }},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Save(ice.WEB_SPIDE, ice.WEB_SERVE, m.Save(ice.WEB_SPIDE, ice.WEB_SERVE,
@ -478,9 +502,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
}) })
}}, }},
ice.WEB_SPIDE: {Name: "spide", Help: "蜘蛛侠", Meta: kit.Dict( ice.WEB_SPIDE: {Name: "spide name [msg|raw|cache] POST|GET url [json|form|part|file|data] arg...", Help: "蜘蛛侠", Meta: kit.Dict("remote", "pod"), List: kit.List(
"remote", "pod",
), List: kit.List(
kit.MDB_INPUT, "text", "name", "name", kit.MDB_INPUT, "text", "name", "name",
kit.MDB_INPUT, "button", "value", "查看", "action", "auto", kit.MDB_INPUT, "button", "value", "查看", "action", "auto",
kit.MDB_INPUT, "button", "value", "返回", "cb", "Last", kit.MDB_INPUT, "button", "value", "返回", "cb", "Last",
@ -488,7 +510,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
if len(arg) == 0 { if len(arg) == 0 {
// 爬虫列表 // 爬虫列表
m.Richs(ice.WEB_SPIDE, nil, "*", func(key string, value map[string]interface{}) { m.Richs(ice.WEB_SPIDE, nil, "*", func(key string, value map[string]interface{}) {
m.Push(key, value["client"], []string{"name", "method", "url"}) m.Push(key, value["client"], []string{"name", "login", "share", "method", "url"})
}) })
m.Sort("name") m.Sort("name")
return return
@ -497,6 +519,10 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
// 爬虫详情 // 爬虫详情
m.Richs(ice.WEB_SPIDE, nil, arg[0], func(key string, value map[string]interface{}) { m.Richs(ice.WEB_SPIDE, nil, arg[0], func(key string, value map[string]interface{}) {
m.Push("detail", value) m.Push("detail", value)
if kit.Value(value, "client.share") != nil {
m.Push("key", "share")
m.Push("value", fmt.Sprintf(m.Conf(ice.WEB_SHARE, "meta.template.text"), kit.Value(value, "client.share")))
}
}) })
return return
} }
@ -507,25 +533,28 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
if uri, e := url.Parse(arg[2]); e == nil && arg[2] != "" { if uri, e := url.Parse(arg[2]); e == nil && arg[2] != "" {
dir, file := path.Split(uri.EscapedPath()) dir, file := path.Split(uri.EscapedPath())
m.Rich(ice.WEB_SPIDE, nil, kit.Dict( m.Rich(ice.WEB_SPIDE, nil, kit.Dict(
"cookie", kit.Dict(), "cookie", kit.Dict(), "header", kit.Dict(), "client", kit.Dict(
"header", kit.Dict(), "share", m.Cmdx(ice.WEB_SHARE, "add", ice.TYPE_SPIDE, arg[1], arg[2]),
"client", kit.Dict( "type", "POST", "name", arg[1], "text", arg[2],
"name", arg[1], "name", arg[1], "url", arg[2], "method", "POST",
"logheaders", false, "protocol", uri.Scheme, "hostname", uri.Host,
"timeout", "100s", "path", dir, "file", file, "query", uri.RawQuery,
"method", "POST", "timeout", "100s", "logheaders", false,
"protocol", uri.Scheme,
"hostname", uri.Host,
"path", dir,
"file", file,
"query", uri.RawQuery,
"url", arg[2],
), ),
)) ))
m.Log(ice.LOG_CREATE, "%s: %v", arg[1], arg[2:]) m.Log(ice.LOG_CREATE, "%s: %v", arg[1], arg[2:])
} }
default: return
// spide shy [cache] [POST|GET] uri file|data|form|part|json arg... case "login":
m.Richs(ice.WEB_SPIDE, nil, arg[1], func(key string, value map[string]interface{}) {
kit.Value(value, "client.login", m.Cmdx(ice.WEB_SPIDE, arg[1], "raw", "/route/login", "login", kit.Value(value, "client.login")))
kit.Value(value, "client.share", m.Cmdx(ice.WEB_SHARE, "add", ice.TYPE_SPIDE, arg[1],
kit.Format("%s?sessid=%s", kit.Value(value, "client.url"), kit.Value(value, "cookie.sessid"))))
m.Echo("%s", kit.Value(value, "client.login"))
})
return
}
m.Richs(ice.WEB_SPIDE, nil, arg[0], func(key string, value map[string]interface{}) { m.Richs(ice.WEB_SPIDE, nil, arg[0], func(key string, value map[string]interface{}) {
client := value["client"].(map[string]interface{}) client := value["client"].(map[string]interface{})
// 缓存数据 // 缓存数据
@ -551,11 +580,13 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
// 请求地址 // 请求地址
uri, arg := arg[0], arg[1:] uri, arg := arg[0], arg[1:]
// 请求数据 // 渲染引擎
head := map[string]string{} head := map[string]string{}
body, ok := m.Optionv("body").(io.Reader) body, ok := m.Optionv("body").(io.Reader)
if !ok && len(arg) > 0 && method != "GET" { if !ok && len(arg) > 0 && method != "GET" {
switch arg[0] { switch arg[0] {
case "data":
body, arg = bytes.NewBufferString(arg[1]), arg[2:]
case "file": case "file":
if f, e := os.Open(arg[1]); m.Warn(e != nil, "%s", e) { if f, e := os.Open(arg[1]); m.Warn(e != nil, "%s", e) {
return return
@ -563,15 +594,6 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
defer f.Close() defer f.Close()
body, arg = f, arg[2:] body, arg = f, arg[2:]
} }
case "data":
body, arg = bytes.NewBufferString(arg[1]), arg[2:]
case "form":
data := []string{}
for i := 1; i < len(arg)-1; i += 2 {
data = append(data, url.QueryEscape(arg[i])+"="+url.QueryEscape(arg[i+1]))
}
body = bytes.NewBufferString(strings.Join(data, "&"))
head["Content-Type"] = "application/x-www-form-urlencoded"
case "part": case "part":
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
mp := multipart.NewWriter(buf) mp := multipart.NewWriter(buf)
@ -590,6 +612,13 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
mp.Close() mp.Close()
head["Content-Type"] = mp.FormDataContentType() head["Content-Type"] = mp.FormDataContentType()
body = buf body = buf
case "form":
data := []string{}
for i := 1; i < len(arg)-1; i += 2 {
data = append(data, url.QueryEscape(arg[i])+"="+url.QueryEscape(arg[i+1]))
}
body = bytes.NewBufferString(strings.Join(data, "&"))
head["Content-Type"] = "application/x-www-form-urlencoded"
case "json": case "json":
arg = arg[1:] arg = arg[1:]
fallthrough fallthrough
@ -609,30 +638,26 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
body = bytes.NewBuffer([]byte{}) body = bytes.NewBuffer([]byte{})
} }
// 构造请求 // 请求地址
uri = kit.MergeURL2(kit.Format(client["url"]), uri, arg) uri = kit.MergeURL2(kit.Format(client["url"]), uri, arg)
req, e := http.NewRequest(method, uri, body) req, e := http.NewRequest(method, uri, body)
m.Info("%s %s", req.Method, req.URL) m.Info("%s %s", req.Method, req.URL)
m.Assert(e) m.Assert(e)
// 请求参数 // 请求变量
for k, v := range head { kit.Fetch(value["cookie"], func(key string, value string) {
req.Header.Set(k, v)
}
if list, ok := m.Optionv("header").([]string); ok {
for i := 0; i < len(list)-1; i += 2 {
req.Header.Set(list[i], list[i+1])
}
}
kit.Fetch(client["header"], func(key string, value string) {
req.Header.Set(key, value)
})
kit.Fetch(client["cookie"], func(key string, value string) {
req.AddCookie(&http.Cookie{Name: key, Value: value}) req.AddCookie(&http.Cookie{Name: key, Value: value})
m.Info("%s: %s", key, value) m.Info("%s: %s", key, value)
}) })
if method == "POST" { kit.Fetch(value["header"], func(key string, value string) {
m.Info("%s: %s", req.Header.Get("Content-Length"), req.Header.Get("Content-Type")) req.Header.Set(key, value)
})
list := kit.Simple(m.Optionv("header"))
for i := 0; i < len(list)-1; i += 2 {
req.Header.Set(list[i], list[i+1])
}
for k, v := range head {
req.Header.Set(k, v)
} }
// 请求代理 // 请求代理
@ -640,50 +665,46 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
if web.Client == nil { if web.Client == nil {
web.Client = &http.Client{Timeout: kit.Duration(kit.Format(client["timeout"]))} web.Client = &http.Client{Timeout: kit.Duration(kit.Format(client["timeout"]))}
} }
if method == "POST" {
m.Info("%s: %s", req.Header.Get("Content-Length"), req.Header.Get("Content-Type"))
}
// 发送请求 // 发送请求
res, e := web.Client.Do(req) res, e := web.Client.Do(req)
if m.Warn(e != nil, "%s", e) { if m.Warn(e != nil, "%s", e) {
m.Set("result")
return return
} }
// 验证结果 // 检查结果
if m.Cost("%s %s: %s", res.Status, res.Header.Get("Content-Length"), res.Header.Get("Content-Type")); m.Warn(res.StatusCode != http.StatusOK, "%s", res.Status) { if m.Cost("%s %s: %s", res.Status, res.Header.Get("Content-Length"), res.Header.Get("Content-Type")); m.Warn(res.StatusCode != http.StatusOK, "%s", res.Status) {
if cache != "" {
m.Set("result")
}
return return
} }
// 缓存参数 // 缓存变量
for _, v := range res.Cookies() { for _, v := range res.Cookies() {
kit.Value(client, "cookie."+v.Name, v.Value) kit.Value(value, "cookie."+v.Name, v.Value)
m.Info("%s: %s", v.Name, v.Value) m.Log(ice.LOG_IMPORT, "%s: %s", v.Name, v.Value)
} }
// 解析引擎
switch cache { switch cache {
case "msg": case "cache":
var data map[string][]string m.Optionv("response", res)
m.Assert(json.NewDecoder(res.Body).Decode(&data)) m.Echo(m.Cmd(ice.WEB_CACHE, "download", res.Header.Get("Content-Type"), uri).Append("data"))
m.Info("res: %s", kit.Formats(data))
if len(data[ice.MSG_APPEND]) > 0 {
for i := range data[data[ice.MSG_APPEND][0]] {
for _, k := range data[ice.MSG_APPEND] {
m.Push(k, data[k][i])
}
}
}
m.Resultv(data[ice.MSG_RESULT])
case "raw": case "raw":
if b, e := ioutil.ReadAll(res.Body); m.Assert(e) { if b, e := ioutil.ReadAll(res.Body); m.Assert(e) {
m.Echo(string(b)) m.Echo(string(b))
} }
case "cache": case "msg":
// 缓存结果 var data map[string][]string
m.Optionv("response", res) m.Assert(json.NewDecoder(res.Body).Decode(&data))
m.Echo(m.Cmd(ice.WEB_CACHE, "download", res.Header.Get("Content-Type"), uri).Append("data")) m.Info("res: %s", kit.Formats(data))
for _, k := range data[ice.MSG_APPEND] {
for i := range data[k] {
m.Push(k, data[k][i])
}
}
m.Resultv(data[ice.MSG_RESULT])
default: default:
if strings.HasPrefix(res.Header.Get("Content-Type"), "text/html") { if strings.HasPrefix(res.Header.Get("Content-Type"), "text/html") {
b, _ := ioutil.ReadAll(res.Body) b, _ := ioutil.ReadAll(res.Body)
@ -691,22 +712,13 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
break break
} }
// 解析结果
var data interface{} var data interface{}
m.Assert(json.NewDecoder(res.Body).Decode(&data)) m.Assert(json.NewDecoder(res.Body).Decode(&data))
data = kit.KeyValue(map[string]interface{}{}, "", data) data = kit.KeyValue(map[string]interface{}{}, "", data)
m.Info("res: %s", kit.Formats(data)) m.Info("res: %s", kit.Formats(data))
kit.Fetch(data, func(key string, value interface{}) { m.Push("", data)
switch value := value.(type) {
case []interface{}:
m.Push(key, value)
default:
m.Push(key, kit.Format(value))
} }
}) })
}
})
}
}}, }},
ice.WEB_SERVE: {Name: "serve [shy|dev|self]", Help: "服务器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.WEB_SERVE: {Name: "serve [shy|dev|self]", Help: "服务器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
// 节点信息 // 节点信息
@ -748,16 +760,16 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
web := m.Target().Server().(*Frame) web := m.Target().Server().(*Frame)
switch arg[0] { switch arg[0] {
case "auth": // case "auth":
m.Richs(ice.WEB_SPACE, nil, arg[1], func(key string, value map[string]interface{}) { // m.Richs(ice.WEB_SPACE, nil, arg[1], func(key string, value map[string]interface{}) {
sessid := kit.Format(kit.Value(value, "sessid")) // sessid := kit.Format(kit.Value(value, "sessid"))
if value["user"] = arg[2]; sessid == "" || m.Cmdx(ice.AAA_SESS, "check", sessid) != arg[1] { // if value["user"] = arg[2]; sessid == "" || m.Cmdx(ice.AAA_SESS, "check", sessid) != arg[1] {
sessid = m.Cmdx(ice.AAA_SESS, "create", arg[2:]) // sessid = m.Cmdx(ice.AAA_SESS, "create", arg[2:])
value["sessid"] = sessid // value["sessid"] = sessid
} // }
m.Cmd(ice.WEB_SPACE, arg[1], "sessid", sessid) // m.Cmd(ice.WEB_SPACE, arg[1], "sessid", sessid)
}) // })
//
case "share": case "share":
switch arg[1] { switch arg[1] {
case "add": case "add":
@ -781,10 +793,10 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
proto := kit.Select("ws", "wss", kit.Format(kit.Value(value, "client.protocol")) == "https") proto := kit.Select("ws", "wss", kit.Format(kit.Value(value, "client.protocol")) == "https")
host := kit.Format(kit.Value(value, "client.hostname")) host := kit.Format(kit.Value(value, "client.hostname"))
for i := 0; i < msg.Confi(ice.WEB_SPACE, "meta.redial.c"); i++ { for i := 0; i < kit.Int(msg.Conf(ice.WEB_SPACE, "meta.redial.c")); i++ {
if u, e := url.Parse(kit.MergeURL(proto+"://"+host+"/space/", "node", node, "name", name, "user", user, "share", value["share"])); msg.Assert(e) { if u, e := url.Parse(kit.MergeURL(proto+"://"+host+"/space/", "node", node, "name", name, "user", user, "share", value["share"])); msg.Assert(e) {
if s, e := net.Dial("tcp", host); !msg.Warn(e != nil, "%s", e) { if s, e := net.Dial("tcp", host); !msg.Warn(e != nil, "%s", e) {
if s, _, e := websocket.NewClient(s, u, nil, msg.Confi(ice.WEB_SPACE, "meta.buffer.r"), msg.Confi(ice.WEB_SPACE, "meta.buffer.w")); !msg.Warn(e != nil, "%s", e) { if s, _, e := websocket.NewClient(s, u, nil, kit.Int(msg.Conf(ice.WEB_SPACE, "meta.buffer.r")), kit.Int(msg.Conf(ice.WEB_SPACE, "meta.buffer.w"))); !msg.Warn(e != nil, "%s", e) {
msg = m.Spawn() msg = m.Spawn()
// 连接成功 // 连接成功
@ -800,7 +812,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
} }
// 断线重连 // 断线重连
sleep := time.Duration(rand.Intn(msg.Confi(ice.WEB_SPACE, "meta.redial.a"))*i+i*msg.Confi(ice.WEB_SPACE, "meta.redial.b")) * time.Millisecond sleep := time.Duration(rand.Intn(kit.Int(msg.Conf(ice.WEB_SPACE, "meta.redial.a"))*i)+kit.Int(msg.Conf(ice.WEB_SPACE, "meta.redial.b"))) * time.Millisecond
msg.Info("%d sleep: %s reconnect: %s", i, sleep, u) msg.Info("%d sleep: %s reconnect: %s", i, sleep, u)
time.Sleep(sleep) time.Sleep(sleep)
} }
@ -818,12 +830,6 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
}) })
m.Append("name", list) m.Append("name", list)
break break
// 空间详情
m.Richs(ice.WEB_SPACE, nil, arg[0], func(key string, value map[string]interface{}) {
m.Push("detail", value)
})
break
} }
if arg[0] == "" { if arg[0] == "" {
@ -834,14 +840,14 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
target := strings.Split(arg[0], ".") target := strings.Split(arg[0], ".")
m.Warn(m.Richs(ice.WEB_SPACE, nil, target[0], func(key string, value map[string]interface{}) { m.Warn(m.Richs(ice.WEB_SPACE, nil, target[0], func(key string, value map[string]interface{}) {
if socket, ok := value["socket"].(*websocket.Conn); ok { if socket, ok := value["socket"].(*websocket.Conn); !m.Warn(!ok, "socket err") {
// 复制选项 // 复制选项
for _, k := range kit.Simple(m.Optionv("_option")) { for _, k := range kit.Simple(m.Optionv("_option")) {
if m.Options(k) { if m.Options(k) {
switch k { switch k {
case "detail", "cmds": case "detail", "cmds":
default: default:
if m.Option(k) != "" { if m.Option(k) == "" {
m.Option(k, m.Option(k)) m.Option(k, m.Option(k))
} }
} }
@ -859,17 +865,15 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
m.Target().Server().(*Frame).send[id] = m m.Target().Server().(*Frame).send[id] = m
socket.WriteMessage(MSG_MAPS, []byte(m.Format("meta"))) socket.WriteMessage(MSG_MAPS, []byte(m.Format("meta")))
t := time.AfterFunc(kit.Duration(m.Conf(ice.WEB_SPACE, "meta.timeout.c")), func() { t := time.AfterFunc(kit.Duration(m.Conf(ice.WEB_SPACE, "meta.timeout.c")), func() {
m.TryCatch(m, true, func(m *ice.Message) {
m.Log(ice.LOG_WARN, "timeout") m.Log(ice.LOG_WARN, "timeout")
}) })
})
m.Call(true, func(msg *ice.Message) *ice.Message { m.Call(true, func(msg *ice.Message) *ice.Message {
if msg != nil { m.Log("cost", "%s: %s %v", m.Format("cost"), arg[0], arg[1:])
if t.Stop(); msg != nil && m != nil {
// 返回结果
m.Copy(msg) m.Copy(msg)
} }
// 返回结果
m.Log("cost", "%s: %s %v", m.Format("cost"), arg[0], arg[1:])
t.Stop()
return nil return nil
}) })
} }
@ -884,48 +888,18 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
kit.MDB_INPUT, "button", "value", "创建", "action", "auto", kit.MDB_INPUT, "button", "value", "创建", "action", "auto",
kit.MDB_INPUT, "button", "value", "返回", "cb", "Last", kit.MDB_INPUT, "button", "value", "返回", "cb", "Last",
), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) > 1 { if len(arg) > 1 && arg[0] == "action" {
switch arg[1] { switch arg[1] {
case "启动": case "启动", "start":
arg = []string{arg[4]} arg = []string{arg[4]}
case "停止", "stop": case "停止", "stop":
m.Cmd(ice.WEB_SPACE, kit.Select(m.Option("name"), arg, 4), "exit", "1") m.Cmd(ice.WEB_SPACE, kit.Select(m.Option("name"), arg, 4), "exit", "1")
time.Sleep(time.Second * 3)
m.Event(ice.DREAM_CLOSE, arg[4]) m.Event(ice.DREAM_CLOSE, arg[4])
arg = arg[:0]
}
}
if len(arg) > 0 {
// 规范命名
if !strings.Contains(arg[0], "-") || !strings.HasPrefix(arg[0], "20") {
arg[0] = m.Time("20060102-") + arg[0]
}
// 创建目录
p := path.Join(m.Conf(ice.WEB_DREAM, "meta.path"), arg[0])
if _, e := os.Stat(p); e != nil {
os.MkdirAll(p, 0777)
}
if m.Richs(ice.WEB_SPACE, nil, arg[0], nil) == nil {
// 启动任务
m.Option("cmd_dir", p)
m.Option("cmd_type", "daemon")
m.Optionv("cmd_env",
"ctx_log", "boot.log",
"ctx_mod", "ctx,log,gdb,ssh",
"ctx_dev", m.Conf(ice.CLI_RUNTIME, "conf.ctx_dev"),
"PATH", kit.Path(path.Join(p, "bin"))+":"+os.Getenv("PATH"),
)
m.Cmd(m.Confv(ice.WEB_DREAM, "meta.cmd"), "self", arg[0])
time.Sleep(time.Second * 1)
m.Event(ice.DREAM_START, arg...)
}
m.Cmdy("nfs.dir", p)
return return
} }
}
if len(arg) == 0 {
// 任务列表 // 任务列表
m.Cmdy("nfs.dir", m.Conf(ice.WEB_DREAM, "meta.path"), "time name") m.Cmdy("nfs.dir", m.Conf(ice.WEB_DREAM, "meta.path"), "time name")
m.Table(func(index int, value map[string]string, head []string) { m.Table(func(index int, value map[string]string, head []string) {
@ -938,7 +912,32 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
} }
}) })
m.Sort("name") m.Sort("name")
m.Sort("status") return
}
// 规范命名
if !strings.Contains(arg[0], "-") || !strings.HasPrefix(arg[0], "20") {
arg[0] = m.Time("20060102-") + arg[0]
}
// 创建目录
p := path.Join(m.Conf(ice.WEB_DREAM, "meta.path"), arg[0])
os.MkdirAll(p, 0777)
if m.Richs(ice.WEB_SPACE, nil, arg[0], nil) == nil {
// 启动任务
m.Option("cmd_dir", p)
m.Option("cmd_type", "daemon")
m.Optionv("cmd_env",
"ctx_dev", m.Conf(ice.CLI_RUNTIME, "conf.ctx_dev"),
"ctx_log", "boot.log", "ctx_mod", "ctx,log,gdb,ssh",
"PATH", kit.Path(path.Join(p, "bin"))+":"+os.Getenv("PATH"),
)
m.Cmd(m.Confv(ice.WEB_DREAM, "meta.cmd"), "self", arg[0])
time.Sleep(time.Second * 1)
m.Event(ice.DREAM_START, arg...)
}
m.Cmdy("nfs.dir", p)
}}, }},
ice.WEB_FAVOR: {Name: "favor [path [type name [text [key value]....]]", Help: "收藏夹", Meta: kit.Dict( ice.WEB_FAVOR: {Name: "favor [path [type name [text [key value]....]]", Help: "收藏夹", Meta: kit.Dict(
@ -1231,8 +1230,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
switch arg[1] { switch arg[1] {
case "share", "共享": case "share", "共享":
m.Echo("share: ") if m.Echo("share: "); list == "" {
if list == "" {
msg := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, story) msg := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, story)
m.Cmdy(ice.WEB_SHARE, "add", "story", story, msg.Append("list")) m.Cmdy(ice.WEB_SHARE, "add", "story", story, msg.Append("list"))
} else { } else {
@ -1602,6 +1600,17 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
} }
switch arg[0] { switch arg[0] {
case "auth":
m.Richs(ice.WEB_SHARE, nil, arg[1], func(key string, value map[string]interface{}) {
if value["type"] == "login" {
m.Richs(ice.AAA_SESS, nil, value["text"], func(key string, value map[string]interface{}) {
value["userrole"] = m.Cmdx(ice.AAA_ROLE, "check", arg[2])
m.Echo("%s", value["userrole"])
value["username"] = arg[2]
})
}
})
case "add": case "add":
arg = arg[1:] arg = arg[1:]
fallthrough fallthrough
@ -1688,10 +1697,13 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
Render(m, kit.Formats(value)) Render(m, kit.Formats(value))
return return
case "share", "共享码": case "share", "共享码":
Render(m, "qrcode", kit.Format("%s/%s/", m.Conf(ice.WEB_SHARE, "meta.domain"), key)) Render(m, "qrcode", kit.Format("%s/share/%s/", m.Conf(ice.WEB_SHARE, "meta.domain"), key))
return return
case "value", "数据值": case "value", "数据值":
Render(m, "%s", value["text"]) Render(m, "qrcode", kit.Format(value))
return
case "text":
Render(m, "qrcode", kit.Format(value["text"]))
return return
} }
@ -1771,6 +1783,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
}) })
}}, }},
"/story/": {Name: "/story/", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/story/": {Name: "/story/", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] { switch arg[0] {
case ice.STORY_PULL: case ice.STORY_PULL:
// 下载节点 // 下载节点
@ -1833,6 +1846,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
} }
}}, }},
"/favor/": {Name: "/story/", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/favor/": {Name: "/story/", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] { switch arg[0] {
case "pull": case "pull":
m.Richs(ice.WEB_FAVOR, nil, m.Option("favor"), func(key string, value map[string]interface{}) { m.Richs(ice.WEB_FAVOR, nil, m.Option("favor"), func(key string, value map[string]interface{}) {
@ -1853,18 +1867,22 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
}) })
} }
}}, }},
"/space/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
list := strings.Split(cmd, "/")
switch list[2] { "/route/": {Name: "/route/", Help: "路由器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] {
case "login": case "login":
m.Option(ice.MSG_SESSID, Render(m, "cookie", m.Cmdx(ice.AAA_USER, "login", m.Option("username"), m.Option("password")))) if m.Richs(ice.WEB_ROUTE, nil, kit.Select(m.Option("login"), arg, 1), func(key string, value map[string]interface{}) {
return m.Echo("%s", value["share"])
case "share": }) == nil {
m.Cmdy(ice.WEB_SHARE, list[3:]) sessid := m.Cmdx(ice.AAA_SESS, "create", "")
return share := m.Cmdx(ice.WEB_SHARE, "add", "login", m.Option(ice.MSG_USERIP), sessid)
m.Rich(ice.WEB_ROUTE, nil, kit.Dict("share", share, "sessid", sessid))
Render(m, "cookie", sessid)
Render(m, share)
} }
}
}},
"/space/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if s, e := websocket.Upgrade(m.W, m.R, nil, m.Confi(ice.WEB_SPACE, "meta.buffer.r"), m.Confi(ice.WEB_SPACE, "meta.buffer.w")); m.Assert(e) { if s, e := websocket.Upgrade(m.W, m.R, nil, m.Confi(ice.WEB_SPACE, "meta.buffer.r"), m.Confi(ice.WEB_SPACE, "meta.buffer.w")); m.Assert(e) {
m.Option("name", strings.Replace(m.Option("name"), ".", "_", -1)) m.Option("name", strings.Replace(m.Option("name"), ".", "_", -1))
if !m.Options("name") { if !m.Options("name") {
@ -1882,7 +1900,6 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
kit.MDB_TYPE, m.Option("node"), kit.MDB_TYPE, m.Option("node"),
kit.MDB_NAME, m.Option("name"), kit.MDB_NAME, m.Option("name"),
kit.MDB_TEXT, m.Option("user"), kit.MDB_TEXT, m.Option("user"),
"sessid", m.Option("sessid"),
"share", share, "socket", s, "share", share, "socket", s,
)) ))
m.Log(ice.LOG_CREATE, "space: %s share: %s", m.Option(kit.MDB_NAME), share) m.Log(ice.LOG_CREATE, "space: %s share: %s", m.Option(kit.MDB_NAME), share)
@ -1903,6 +1920,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
m.Echo(share) m.Echo(share)
} }
}}, }},
"/static/volcanos/plugin/github.com/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/static/volcanos/plugin/github.com/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
file := strings.TrimPrefix(cmd, "/static/volcanos/") file := strings.TrimPrefix(cmd, "/static/volcanos/")
if _, e := os.Stat(path.Join("usr/volcanos", file)); e != nil { if _, e := os.Stat(path.Join("usr/volcanos", file)); e != nil {

View File

@ -176,7 +176,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心",
} }
// 登录检查 // 登录检查
if m.Warn(!m.Options(ice.MSG_SESSID) || !m.Options(ice.MSG_USERNAME), "not login") { if m.Warn(!m.Options(ice.MSG_USERNAME), "not login") {
web.Render(m, "status", 401, "not login") web.Render(m, "status", 401, "not login")
m.Option(ice.MSG_USERURL, "") m.Option(ice.MSG_USERURL, "")
return return

View File

@ -42,6 +42,7 @@ var Index = &ice.Context{Name: "code", Help: "编程中心",
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Save("login") m.Save("login")
}}, }},
"login": {Name: "login", Help: "登录", List: ice.ListLook("key"), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "login": {Name: "login", Help: "登录", List: ice.ListLook("key"), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) > 0 && arg[0] == "action" { if len(arg) > 0 && arg[0] == "action" {
switch arg[1] { switch arg[1] {
@ -58,7 +59,6 @@ var Index = &ice.Context{Name: "code", Help: "编程中心",
} }
switch kit.Select("list", arg, 0) { switch kit.Select("list", arg, 0) {
case "open":
case "init": case "init":
if m.Option("sid") != "" && m.Confs("login", []string{"hash", m.Option("sid"), "status"}) { if m.Option("sid") != "" && m.Confs("login", []string{"hash", m.Option("sid"), "status"}) {
// 复用会话 // 复用会话
@ -96,6 +96,11 @@ var Index = &ice.Context{Name: "code", Help: "编程中心",
m.Push(key, value, []string{"pid", "pane", "hostname", "username"}) m.Push(key, value, []string{"pid", "pane", "hostname", "username"})
}) })
case "check":
m.Richs("login", nil, m.Option("sid"), func(key string, value map[string]interface{}) {
})
case "prune": case "prune":
list := []string{} list := []string{}
m.Richs("login", nil, "*", func(key string, value map[string]interface{}) { m.Richs("login", nil, "*", func(key string, value map[string]interface{}) {

View File

@ -17,7 +17,7 @@ var Index = &ice.Context{Name: "zsh", Help: "命令行",
"zsh": {Name: "zsh", Help: "命令行", Value: kit.Data(kit.MDB_SHORT, "name", "history", "zsh.history")}, "zsh": {Name: "zsh", Help: "命令行", Value: kit.Data(kit.MDB_SHORT, "name", "history", "zsh.history")},
}, },
Commands: map[string]*ice.Command{ Commands: map[string]*ice.Command{
ice.WEB_LOGIN: {Name: "_login", Help: "_login", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.WEB_LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if f, _, e := m.R.FormFile("sub"); e == nil { if f, _, e := m.R.FormFile("sub"); e == nil {
defer f.Close() defer f.Close()
if b, e := ioutil.ReadAll(f); e == nil { if b, e := ioutil.ReadAll(f); e == nil {
@ -35,6 +35,7 @@ var Index = &ice.Context{Name: "zsh", Help: "命令行",
m.Info("%s %s cmd: %v sub: %v", m.Option("you"), m.Option(ice.MSG_USERURL), m.Optionv("cmds"), m.Optionv("sub")) m.Info("%s %s cmd: %v sub: %v", m.Option("you"), m.Option(ice.MSG_USERURL), m.Optionv("cmds"), m.Optionv("sub"))
m.Append("_output", "result") m.Append("_output", "result")
}}, }},
"/help": {Name: "/help", Help: "帮助", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { "/help": {Name: "/help", Help: "帮助", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmdy("help") m.Cmdy("help")
}}, }},