1
0
mirror of https://shylinux.com/x/icebergs synced 2025-04-25 17:18:05 +08:00
This commit is contained in:
IT 老营长 @云轩领航-创始人 2023-08-18 13:04:17 +08:00
parent 71624742e8
commit f0aeaa6784
15 changed files with 219 additions and 39 deletions

View File

@ -14,6 +14,7 @@ func _user_create(m *ice.Message, name string, arg ...string) {
const (
BACKGROUND = "background"
AVATAR_URL = "avatar_url"
AVATAR = "avatar"
GENDER = "gender"
MOBILE = "mobile"
@ -22,6 +23,7 @@ const (
COUNTRY = "country"
PROVINCE = "province"
LANGUAGE = "language"
THEME = "theme"
)
const (
USERNICK = "usernick"
@ -46,7 +48,7 @@ func init() {
}
}},
mdb.CREATE: {Name: "create usernick username* userrole=void,tech userzone background", Hand: func(m *ice.Message, arg ...string) {
_user_create(m, m.Option(USERNAME), m.OptionSimple(USERNICK, USERROLE, USERZONE, BACKGROUND)...)
_user_create(m, m.Option(USERNAME), m.OptionSimple(USERNICK, USERROLE, USERZONE, BACKGROUND, AVATAR, AVATAR_URL, EMAIL, LANGUAGE)...)
}},
}, mdb.ImportantHashAction(mdb.SHORT, USERNAME, mdb.FIELD, "time,usernick,username,userrole,userzone"))},
})

View File

@ -224,6 +224,11 @@ func ConfigSimple(m *ice.Message, key ...string) (res []string) {
return
}
func ConfigFromOption(m *ice.Message, arg ...string) {
if len(arg) == 0 {
kit.For(m.Target().Commands[m.CommandKey()].Actions[m.ActionKey()].List, func(value ice.Any) {
arg = append(arg, kit.Format(kit.Value(value, mdb.NAME)))
})
}
kit.For(arg, func(k string) { mdb.Config(m, k, kit.Select(mdb.Config(m, k), m.Option(k))) })
}
func OptionFromConfig(m *ice.Message, arg ...string) string {

View File

@ -25,7 +25,7 @@ func Display(m displayMessage, file string, arg ...ice.Any) displayMessage {
return DisplayBase(m, file, arg...)
}
func DisplayTable(m displayMessage, arg ...ice.Any) displayMessage {
return DisplayBase(m, "/plugin/table.js", arg...)
return DisplayBase(m, ice.PLUGIN_TABLE_JS, arg...)
}
func DisplayTableCard(m displayMessage, arg ...ice.Any) displayMessage {
return DisplayTable(m, "style", "card")

View File

@ -171,7 +171,9 @@ const SERVE = "serve"
func init() {
Index.MergeCommands(ice.Commands{
"/exit": {Hand: func(m *ice.Message, arg ...string) { m.Cmd(ice.EXIT) }},
P(ice.EXIT): {Hand: func(m *ice.Message, arg ...string) { m.Cmd(ice.EXIT) }},
PP(ice.VOLCANOS): {Hand: func(m *ice.Message, arg ...string) { m.RenderDownload(path.Join(ice.USR_VOLCANOS, path.Join(arg...))) }},
PP(ice.INTSHELL): {Hand: func(m *ice.Message, arg ...string) { m.RenderDownload(path.Join(ice.USR_INTSHELL, path.Join(arg...))) }},
SERVE: {Name: "serve name auto start dark system", Help: "服务器", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
cli.NodeInfo(m, ice.Info.Pathname, WORKER)
@ -227,7 +229,13 @@ func Domain(host, port string) string { return kit.Format("%s://%s:%s", HTTP, ho
func Script(m *ice.Message, str string, arg ...ice.Any) string {
return ice.Render(m, ice.RENDER_SCRIPT, kit.Format(str, arg...))
}
func ChatCmdPath(arg ...string) string { return path.Join("/chat/cmd/", path.Join(arg...)) }
func ChatCmdPath(m *ice.Message, arg ...string) string {
if p := m.Option(ice.MSG_USERPOD); p != "" {
return path.Join("/chat/pod/", p, "/cmd/", kit.Select(m.PrefixKey(), path.Join(arg...)))
}
return path.Join("/chat/cmd/", kit.Select(m.PrefixKey(), path.Join(arg...)))
}
func RequireFile(m *ice.Message, file string) string {
if strings.HasPrefix(file, nfs.PS) || strings.HasPrefix(file, ice.HTTP) {
return file

View File

@ -61,7 +61,7 @@ func _spide_show(m *ice.Message, name string, arg ...string) {
m.Logs("response", v.Name, v.Value)
})
})
if m.Warn(res.StatusCode != http.StatusOK, ice.ErrNotValid, uri, cli.STATUS, res.Status) {
if m.Warn(res.StatusCode != http.StatusOK && res.StatusCode != http.StatusCreated, ice.ErrNotValid, uri, cli.STATUS, res.Status) {
switch res.StatusCode {
case http.StatusNotFound, http.StatusUnauthorized:
return
@ -100,7 +100,9 @@ func _spide_body(m *ice.Message, method string, arg ...string) (io.Reader, ice.M
default:
data := ice.Map{}
kit.For(arg, func(k, v string) { kit.Value(data, k, v) })
head[ContentType], body = ApplicationJSON, bytes.NewBufferString(kit.Format(data))
_data := kit.Format(data)
m.Debug("post %v %v", len(_data), _data)
head[ContentType], body = ApplicationJSON, bytes.NewBufferString(_data)
}
return body, head, arg[:0]
}
@ -168,6 +170,7 @@ func _spide_send(m *ice.Message, name string, req *http.Request, timeout string)
func _spide_save(m *ice.Message, action, file, uri string, res *http.Response) {
switch action {
case SPIDE_RAW:
m.SetResult()
if b, _ := ioutil.ReadAll(res.Body); strings.HasPrefix(res.Header.Get(ContentType), ApplicationJSON) {
m.Echo(kit.Formats(kit.UnMarshal(string(b))))
} else {
@ -209,14 +212,15 @@ const (
SPIDE_JSON = "json"
SPIDE_RES = "content_data"
Basic = "Basic"
Bearer = "Bearer"
Authorization = "Authorization"
ContentType = "Content-Type"
ContentLength = "Content-Length"
UserAgent = "User-Agent"
Referer = "Referer"
Accept = "Accept"
Basic = "Basic"
Bearer = "Bearer"
Authorization = "Authorization"
AcceptLanguage = "Accept-Language"
ContentLength = "Content-Length"
ContentType = "Content-Type"
UserAgent = "User-Agent"
Referer = "Referer"
Accept = "Accept"
ContentFORM = "application/x-www-form-urlencoded"
ContentPNG = "image/png"
@ -256,6 +260,9 @@ func init() {
m.Cmd("", mdb.CREATE, ice.COM, kit.Select("https://contexts.com.cn", conf[cli.CTX_COM]))
m.Cmd("", mdb.CREATE, ice.SHY, kit.Select(kit.Select("https://shylinux.com", ice.Info.Make.Remote), conf[cli.CTX_SHY]))
}},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelectValue(m, func(value ice.Map) { m.Push(kit.Select(ORIGIN, arg, 0), value[ORIGIN]) })
}},
mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) {
if mdb.IsSearchPreview(m, arg) {
m.PushSearch(mdb.TYPE, LINK, mdb.NAME, ice.DEV, mdb.TEXT, mdb.HashSelectField(m, ice.DEV, CLIENT_ORIGIN))

View File

@ -30,7 +30,7 @@ func init() {
}},
CONFIRM: {Hand: func(m *ice.Message, arg ...string) {
msg := m.Cmd("", mdb.CREATE, mdb.TYPE, Basic, mdb.NAME, m.Option(ice.MSG_USERNAME), mdb.TEXT, m.Option(tcp.HOST))
m.ProcessReplace(kit.MergeURL2(m.Option(tcp.HOST), ChatCmdPath(m.PrefixKey(), SET),
m.ProcessReplace(kit.MergeURL2(m.Option(tcp.HOST), ChatCmdPath(m, m.PrefixKey(), SET),
TOKEN, strings.Replace(UserHost(m), "://", kit.Format("://%s:%s@", m.Option(ice.MSG_USERNAME), msg.Result()), 1)))
}},
SET: {Hand: func(m *ice.Message, arg ...string) {

11
conf.go
View File

@ -100,12 +100,13 @@ const ( // DIR
INDEX_SH = "index.sh"
FAVICON_ICO = "/favicon.ico"
PLUGIN_INPUT = "/plugin/input/"
PLUGIN_LOCAL = "/plugin/local/"
PLUGIN_STORY = "/plugin/story/"
REQUIRE_SRC = "/require/src/"
REQUIRE_USR = "/require/usr/"
PLUGIN_INPUT = "/volcanos/plugin/input/"
PLUGIN_LOCAL = "/volcanos/plugin/local/"
PLUGIN_STORY = "/volcanos/plugin/story/"
PLUGIN_TABLE_JS = "/volcanos/plugin/table.js"
REQUIRE_MODULES = "/require/modules/"
REQUIRE_USR = "/require/usr/"
REQUIRE_SRC = "/require/src/"
ISH_PLUGED = ".ish/pluged/"
USR_MODULES = "usr/node_modules/"

View File

@ -1,12 +1,15 @@
package chat
import (
"path"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/base/web/html"
@ -85,14 +88,16 @@ func init() {
m.Cmd(cli.SYSTEM, "osascript", "-e", `tell app "System Events" to tell appearance preferences to set dark mode to `+
kit.Select(ice.FALSE, ice.TRUE, kit.IsIn(kit.Select(html.DARK, arg, 0), html.DARK, html.BLACK)))
}},
}, ctx.ConfAction(SSO, "", aaa.LANGUAGE, "zh")), Hand: func(m *ice.Message, arg ...string) {
}, ctx.ConfAction(SSO, "")), Hand: func(m *ice.Message, arg ...string) {
m.Option("language.list", m.Cmd(nfs.DIR, path.Join(ice.SRC_TEMPLATE, m.PrefixKey(), aaa.LANGUAGE), nfs.FILE).Appendv(nfs.FILE))
m.Option("theme.list", m.Cmd(nfs.DIR, path.Join(ice.SRC_TEMPLATE, m.PrefixKey(), aaa.THEME), nfs.FILE).Appendv(nfs.FILE))
if gdb.Event(m, HEADER_AGENT); !_header_check(m, arg...) {
return
}
msg := m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME))
kit.For([]string{aaa.USERNICK, aaa.LANGUAGE}, func(k string) { m.Option(k, msg.Append(k)) })
kit.For([]string{aaa.AVATAR, aaa.BACKGROUND}, func(k string) { m.Option(k, web.RequireFile(m, msg.Append(k))) })
kit.If(m.Option(aaa.LANGUAGE) == "", func() { m.Option(aaa.LANGUAGE, mdb.Config(m, aaa.LANGUAGE)) })
kit.If(m.Option(aaa.LANGUAGE) == "", func() { m.Option(aaa.LANGUAGE, kit.Split(m.R.Header.Get(web.AcceptLanguage), ",;")[0]) })
m.Echo(mdb.Config(m, TITLE)).Option(MENUS, mdb.Config(m, MENUS))
}},
})

View File

@ -0,0 +1,18 @@
section "oauth"
refer `
官网 https://oauth.net/2/
标准 http://www.rfcreader.com/#rfc6749
博客 https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
服务 https://developers.google.com/identity/protocols/oauth2
服务 https://docs.github.com/cn/developers/apps/building-oauth-apps/authorizing-oauth-apps
应用 https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/github/
`
field web.chat.oauth.apply
field web.chat.oauth.reply
field web.chat.oauth.offer
field web.chat.oauth.authorize
field web.chat.oauth.token
field web.chat.oauth.access

134
core/chat/oauth/client.go Normal file
View File

@ -0,0 +1,134 @@
package oauth
import (
"path"
"strings"
"shylinux.com/x/ice"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
)
const (
CLIENT_ID = "client_id"
CLIENT_SECRET = "client_secret"
OAUTH_URL = "oauth_url"
GRANT_URL = "grant_url"
TOKEN_URL = "token_url"
USERS_URL = "users_url"
REDIRECT_URI = "redirect_uri"
RESPONSE_TYPE = "response_type"
AUTHORIZATION_CODE = "authorization_code"
GRANT_TYPE = "grant_type"
STATE = "state"
CODE = "code"
API = "api"
ACCESS_TOKEN = "access_token"
EXPIRES_IN = "expires_in"
)
type Client struct {
ice.Hash
short string `data:"domain,client_id"`
field string `data:"time,hash,domain,client_id,client_secret,oauth_url,grant_url,token_url,users_url,api,prefix"`
auth string `name:"auth" help:"授权"`
user string `name:"user" help:"用户"`
orgs string `name:"orgs" help:"组织"`
repo string `name:"repo" help:"源码"`
list string `name:"list hash auto"`
}
func (s Client) Init(m *ice.Message, arg ...string) {
aaa.White(m.Message, m.PrefixKey(), ctx.ACTION, aaa.LOGIN)
s.Hash.Init(m, arg...)
}
func (s Client) Inputs(m *ice.Message, arg ...string) {
switch s.Hash.Inputs(m, arg...); arg[0] {
case web.DOMAIN:
m.Cmdy(web.SPIDE, mdb.INPUTS, arg)
m.Push(arg[0], "https://repos.shylinux.com")
case OAUTH_URL:
m.Push(arg[0], "/login/oauth/authorize")
case GRANT_URL:
m.Push(arg[0], "/login/oauth/access_token")
case TOKEN_URL:
m.Push(arg[0], "/login/oauth/access_token")
case USERS_URL:
m.Push(arg[0], "/api/v1/user")
case lex.PREFIX:
m.Push(arg[0], "token")
case API:
m.Push(arg[0], "/api/v1/")
}
}
func (s Client) Auth(m *ice.Message, arg ...string) {
m.Options(REDIRECT_URI, s.RedirectURI(m), RESPONSE_TYPE, CODE, STATE, m.Option(mdb.HASH))
m.ProcessOpen(kit.MergeURL2(m.Option(web.DOMAIN), m.Option(OAUTH_URL), m.OptionSimple(CLIENT_ID, REDIRECT_URI, RESPONSE_TYPE, STATE)))
}
func (s Client) User(m *ice.Message, arg ...string) {
if res := s.Get(m, m.Option(mdb.HASH), m.Option(USERS_URL)); res != nil {
m.Options(res).Cmd(aaa.USER, mdb.CREATE, aaa.USERNICK, m.Option("full_name"), m.OptionSimple(aaa.USERNAME),
aaa.USERROLE, kit.Select(aaa.VOID, aaa.TECH, m.Option("is_admin") == ice.TRUE), aaa.USERZONE, m.Option(web.DOMAIN),
m.OptionSimple(aaa.EMAIL, aaa.LANGUAGE, aaa.AVATAR_URL))
}
}
func (s Client) Orgs(m *ice.Message, arg ...string) {}
func (s Client) Repo(m *ice.Message, arg ...string) {}
func (s Client) List(m *ice.Message, arg ...string) {
if s.Hash.List(m, arg...).PushAction(s.User, s.Auth, s.Remove); len(arg) == 0 {
m.EchoScript(s.RedirectURI(m))
} else {
m.EchoScript("config header sso " + kit.MergeURL2(m.Append(web.DOMAIN), m.Append(OAUTH_URL), m.AppendSimple(CLIENT_ID), REDIRECT_URI, s.RedirectURI(m), RESPONSE_TYPE, CODE, STATE, arg[0]))
}
}
func init() { ice.ChatCtxCmd(Client{}) }
func (s Client) RedirectURI(m *ice.Message) string {
return strings.Split(web.MergeURL2(m, web.ChatCmdPath(m.Message, m.PrefixKey(), ctx.ACTION, aaa.LOGIN)), "?")[0]
}
func (s Client) Login(m *ice.Message, arg ...string) {
if state, code := m.Option(STATE), m.Option(CODE); !m.Warn(state == "" || code == "") {
s.Hash.List(m.Spawn(), m.Option(mdb.HASH, state)).Table(func(value ice.Maps) { m.Options(value) })
m.Options(REDIRECT_URI, s.RedirectURI(m), GRANT_TYPE, AUTHORIZATION_CODE)
if res := s.Post(m, m.Option(mdb.HASH), m.Option(GRANT_URL), m.OptionSimple(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, CODE, GRANT_TYPE)...); !m.Warn(res == nil) {
kit.Value(res, EXPIRES_IN, m.Time(kit.Format("%vs", kit.Value(res, EXPIRES_IN))))
s.Modify(m, kit.Simple(res)...)
m.Options(res)
if s.User(m); !m.Warn(m.Option(aaa.USERNAME) == "") && m.R != nil {
web.RenderCookie(m.Message, aaa.SessCreate(m.Message, m.Option(aaa.USERNAME)))
m.ProcessHistory()
} else {
m.ProcessClose()
}
}
}
}
func (s Client) Get(m *ice.Message, hash, api string, arg ...string) ice.Any {
return web.SpideGet(m.Message, s.request(m, hash, api, arg...))
}
func (s Client) Put(m *ice.Message, hash, api string, arg ...string) ice.Any {
return web.SpidePut(m.Message, s.request(m, hash, api, arg...))
}
func (s Client) Post(m *ice.Message, hash, api string, arg ...string) ice.Any {
return web.SpidePost(m.Message, s.request(m, hash, api, arg...))
}
func (s Client) Delete(m *ice.Message, hash, api string, arg ...string) ice.Any {
return web.SpideDelete(m.Message, s.request(m, hash, api, arg...))
}
func (s Client) request(m *ice.Message, hash, api string, arg ...string) []string {
msg := s.Hash.List(m.Spawn(), hash)
kit.If(msg.Append(ACCESS_TOKEN), func(p string) {
m.Options(web.SPIDE_HEADER, ice.Maps{web.Authorization: msg.Append(lex.PREFIX) + lex.SP + p})
})
kit.If(api == "", func() { api = path.Join(msg.Append(API), strings.ToLower(kit.FuncName(6))) })
return kit.Simple(kit.MergeURL2(msg.Append(web.DOMAIN), api), arg)
}

View File

@ -1,18 +1,6 @@
section "oauth"
chapter "oauth"
refer `
官网 https://oauth.net/2/
标准 http://www.rfcreader.com/#rfc6749
博客 https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
服务 https://developers.google.com/identity/protocols/oauth2
服务 https://docs.github.com/cn/developers/apps/building-oauth-apps/authorizing-oauth-apps
应用 https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/github/
https://oauth.net/2/
https://datatracker.ietf.org/doc/html/rfc6749
https://datatracker.ietf.org/doc/html/rfc5849
`
field web.chat.oauth.apply
field web.chat.oauth.reply
field web.chat.oauth.offer
field web.chat.oauth.authorize
field web.chat.oauth.token
field web.chat.oauth.access

View File

@ -6,6 +6,7 @@ import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
)
@ -90,6 +91,9 @@ func init() {
default:
mdb.ZoneInputs(m, arg)
}
if arg[0] == mdb.ZONE {
m.Push(arg[0], kit.Split(nfs.TemplateText(m, mdb.ZONE)))
}
}},
mdb.INSERT: {Name: "insert space zone* type=once,step,week name* text begin_time@date close_time@date", Hand: func(m *ice.Message, arg ...string) {
if space, arg := arg[1], arg[2:]; space != "" {

View File

@ -97,6 +97,14 @@ func (m *Message) RenameAppend(arg ...string) *Message {
})
return m
}
func (m *Message) RewriteAppend(cb func(value, key string, index int) string) *Message {
m.Table(func(index int, value Maps, head []string) {
for _, key := range head {
m.meta[key][index] = cb(value[key], key, index)
}
})
return m
}
func (m *Message) ToLowerAppend(arg ...string) *Message {
kit.For(m.meta[MSG_APPEND], func(k string) { m.RenameAppend(k, strings.ToLower(k)) })
return m

View File

@ -142,7 +142,7 @@ func init() {
kit.If(m.Option(web.TOKEN), func() { m.Cmd(web.TOKEN, "set") })
}},
OAUTH: {Help: "授权", Hand: func(m *ice.Message, arg ...string) {
m.ProcessOpen(kit.MergeURL2(kit.Select(ice.Info.Make.Domain, m.Cmdx(REPOS, "remoteURL")), web.ChatCmdPath(web.TOKEN, "gen"), tcp.HOST, m.Option(ice.MSG_USERWEB)))
m.ProcessOpen(kit.MergeURL2(kit.Select(ice.Info.Make.Domain, m.Cmdx(REPOS, "remoteURL")), web.ChatCmdPath(m, web.TOKEN, "gen"), tcp.HOST, m.Option(ice.MSG_USERWEB)))
}},
INSTEADOF: {Name: "insteadof remote", Help: "代理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(REPOS, INSTEADOF, arg)