1
0
forked from x/icebergs

opt token

This commit is contained in:
IT 老营长 @云轩领航-创始人 2024-01-15 16:14:12 +08:00
parent ef822f0c5b
commit a3328f8e83
6 changed files with 42 additions and 62 deletions

View File

@ -70,7 +70,7 @@ func _space_agent(m *ice.Message, args ...string) []string {
func _space_fork(m *ice.Message) { func _space_fork(m *ice.Message) {
addr := kit.Select(m.R.RemoteAddr, m.R.Header.Get(ice.MSG_USERADDR)) addr := kit.Select(m.R.RemoteAddr, m.R.Header.Get(ice.MSG_USERADDR))
text := strings.ReplaceAll(kit.Select(addr, m.Option(mdb.TEXT)), "%2F", nfs.PS) text := strings.ReplaceAll(kit.Select(addr, m.Option(mdb.TEXT)), "%2F", nfs.PS)
name := kit.ReplaceAll(kit.Select(addr, m.Option(mdb.NAME)), "[", "_", "]", "_", nfs.DF, "_", nfs.PT, "_") name := SpaceName(kit.Select(addr, m.Option(mdb.NAME)))
if m.OptionDefault(mdb.TYPE, SERVER) == WORKER && (!nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, name)) || !tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP))) { if m.OptionDefault(mdb.TYPE, SERVER) == WORKER && (!nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, name)) || !tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP))) {
m.Option(mdb.TYPE, SERVER) m.Option(mdb.TYPE, SERVER)
} }
@ -88,7 +88,7 @@ func _space_fork(m *ice.Message) {
} else if m.Option(TOKEN) != "" { } else if m.Option(TOKEN) != "" {
if msg := m.Cmd(TOKEN, m.Option(TOKEN)); msg.Append(mdb.TIME) > m.Time() && kit.IsIn(msg.Append(mdb.TYPE), SERVER, SPIDE) { if msg := m.Cmd(TOKEN, m.Option(TOKEN)); msg.Append(mdb.TIME) > m.Time() && kit.IsIn(msg.Append(mdb.TYPE), SERVER, SPIDE) {
aaa.SessAuth(m, kit.Dict(m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME, msg.Append(mdb.NAME))).AppendSimple())) aaa.SessAuth(m, kit.Dict(m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME, msg.Append(mdb.NAME))).AppendSimple()))
name = kit.ReplaceAll(kit.Select(name, msg.Append(mdb.TEXT)), "[", "_", "]", "_", nfs.DF, "_", nfs.PT, "_", nfs.PS, "_") name = SpaceName(kit.Select(name, msg.Append(mdb.TEXT)))
} }
} }
args := kit.Simple(mdb.TYPE, m.Option(mdb.TYPE), mdb.NAME, name, mdb.TEXT, text, m.OptionSimple(nfs.MODULE, nfs.VERSION, cli.DAEMON)) args := kit.Simple(mdb.TYPE, m.Option(mdb.TYPE), mdb.NAME, name, mdb.TEXT, text, m.OptionSimple(nfs.MODULE, nfs.VERSION, cli.DAEMON))
@ -269,6 +269,8 @@ func init() {
m.Cmd(SPACE, func(value ice.Maps) { m.Cmd(SPACE, func(value ice.Maps) {
kit.If(kit.IsIn(value[mdb.TYPE], WORKER, SERVER), func() { m.Push(arg[0], value[mdb.NAME]) }) kit.If(kit.IsIn(value[mdb.TYPE], WORKER, SERVER), func() { m.Push(arg[0], value[mdb.NAME]) })
}) })
case ORIGIN:
m.Cmdy(SPIDE, kit.Dict(ice.MSG_FIELDS, CLIENT_ORIGIN)).CutTo(CLIENT_ORIGIN, arg[0]).Sort(arg[0])
case mdb.ICONS: case mdb.ICONS:
m.Options(nfs.DIR_REG, kit.ExtReg(nfs.PNG, nfs.JPG, nfs.JPEG), nfs.DIR_DEEP, ice.TRUE) m.Options(nfs.DIR_REG, kit.ExtReg(nfs.PNG, nfs.JPG, nfs.JPEG), nfs.DIR_DEEP, ice.TRUE)
m.Cmdy(nfs.DIR, nfs.SRC, nfs.PATH) m.Cmdy(nfs.DIR, nfs.SRC, nfs.PATH)
@ -299,8 +301,6 @@ func init() {
m.Push(arg[0], "shy@shylinux.com", "shylinux@163.com") m.Push(arg[0], "shy@shylinux.com", "shylinux@163.com")
case aaa.PASSWORD: case aaa.PASSWORD:
m.SetAppend() m.SetAppend()
case "origin":
m.Cmdy(SPIDE, kit.Dict(ice.MSG_FIELDS, CLIENT_ORIGIN)).CutTo(CLIENT_ORIGIN, arg[0])
} }
}) })
ctx.PodCmd = func(m *ice.Message, arg ...ice.Any) bool { ctx.PodCmd = func(m *ice.Message, arg ...ice.Any) bool {
@ -422,3 +422,6 @@ func PodCmd(m *ice.Message, key string, arg ...string) bool {
return false return false
} }
} }
func SpaceName(name string) string {
return kit.ReplaceAll(name, nfs.DF, "_", nfs.PS, "_", nfs.PT, "_", "[", "_", "]", "_")
}

View File

@ -350,10 +350,11 @@ func init() {
m.Cmd(SPACE, cli.CLOSE, kit.Dict(mdb.NAME, m.Option(CLIENT_NAME))) m.Cmd(SPACE, cli.CLOSE, kit.Dict(mdb.NAME, m.Option(CLIENT_NAME)))
mdb.HashModify(m, mdb.NAME, m.Option(CLIENT_NAME), TOKEN, "") mdb.HashModify(m, mdb.NAME, m.Option(CLIENT_NAME), TOKEN, "")
}}, }},
"devCreateToken": {Hand: func(m *ice.Message, arg ...string) { DEV_REQUEST_TEXT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(SpaceName(ice.Info.NodeName)) }},
DEV_CREATE_TOKEN: {Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE, tcp.DIAL, ice.DEV, m.Option(CLIENT_NAME), m.OptionSimple(TOKEN)) m.Cmd(SPACE, tcp.DIAL, ice.DEV, m.Option(CLIENT_NAME), m.OptionSimple(TOKEN))
}}, }},
}, devTokenAction(CLIENT_NAME, CLIENT_URL), mdb.HashAction(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url,token")), Hand: func(m *ice.Message, arg ...string) { }, DevTokenAction(CLIENT_NAME, CLIENT_URL), mdb.HashAction(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url,token")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") { if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") {
list := m.CmdMap(SPACE, mdb.NAME) list := m.CmdMap(SPACE, mdb.NAME)
mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Sort(CLIENT_NAME) mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Sort(CLIENT_NAME)

View File

@ -2,15 +2,11 @@ package web
import ( import (
"net/http" "net/http"
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web/html" "shylinux.com/x/icebergs/base/web/html"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -18,36 +14,8 @@ import (
const TOKEN = "token" const TOKEN = "token"
func init() { func init() {
const (
GEN = "gen"
SET = "set"
CONFIRM = "confirm"
FILE = ".git-credentials"
LOCAL = "http://localhost:9020"
)
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
TOKEN: {Help: "令牌桶", Actions: ice.MergeActions(ice.Actions{ TOKEN: {Help: "令牌桶", Actions: mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,type,name,text", mdb.EXPIRE, mdb.MONTH), Hand: func(m *ice.Message, arg ...string) {
GEN: {Hand: func(m *ice.Message, arg ...string) {
m.EchoInfoButton(kit.Format("请授权 %s\n访问 %s\n", m.Option(tcp.HOST), m.Option(mdb.TYPE)), CONFIRM)
}},
CONFIRM: {Hand: func(m *ice.Message, arg ...string) {
if m.Warn(m.R.Method != http.MethodPost, ice.ErrNotAllow) {
return
}
msg := m.Cmd("", mdb.CREATE, mdb.TYPE, m.Option(mdb.TYPE), mdb.NAME, m.Option(ice.MSG_USERNAME), mdb.TEXT, m.Option(tcp.HOST))
m.ProcessReplace(kit.MergeURL2(m.Option(tcp.HOST), C(m.PrefixKey()), ctx.ACTION, 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) {
host, list := ice.Map{kit.ParseURL(m.Option(TOKEN)).Host: true}, []string{m.Option(TOKEN)}
m.Cmd(nfs.CAT, kit.HomePath(FILE), func(line string) {
line = strings.ReplaceAll(line, "%3a", ":")
kit.IfNoKey(host, kit.ParseURL(line).Host, func(p string) { list = append(list, line) })
}).Cmd(nfs.SAVE, kit.HomePath(FILE), strings.Join(list, lex.NL)+lex.NL)
m.Cmd(cli.SYSTEM, "git", "config", "--global", "credential.helper", "store")
m.ProcessClose()
}},
}, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,type,name,text", mdb.EXPIRE, mdb.MONTH)), Hand: func(m *ice.Message, arg ...string) {
if mdb.HashSelect(m, arg...); len(arg) > 0 { if mdb.HashSelect(m, arg...); len(arg) > 0 {
m.EchoScript(kit.Format("ish_miss_serve_log dev %s token %s", UserHost(m), arg[0])) m.EchoScript(kit.Format("ish_miss_serve_log dev %s token %s", UserHost(m), arg[0]))
} }
@ -55,13 +23,19 @@ func init() {
}) })
} }
func devTokenAction(name, origin string) ice.Actions { const (
DEV_REQUEST_TEXT = "devRequestText"
DEV_CREATE_TOKEN = "devCreateToken"
)
func DevTokenAction(name, origin string) ice.Actions {
return ice.Actions{ return ice.Actions{
"devRequestText": {Hand: func(m *ice.Message, arg ...string) { m.Echo(ice.Info.NodeName) }}, DEV_REQUEST_TEXT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(UserHost(m)) }},
"devCreateToken": {Hand: func(m *ice.Message, arg ...string) {}}, DEV_CREATE_TOKEN: {Hand: func(m *ice.Message, arg ...string) {}},
mdb.DEV_REQUEST: {Name: "dev.request", Help: "连接", Hand: func(m *ice.Message, arg ...string) { mdb.DEV_REQUEST: {Name: "dev.request", Help: "连接", Icon: "bi bi-person-down", Hand: func(m *ice.Message, arg ...string) {
m.ProcessOpen(m.Options(ice.MSG_USERWEB, m.Option(origin)).MergePodCmd("", m.PrefixKey(), ctx.ACTION, mdb.DEV_CHOOSE, cli.BACK, m.Option(ice.MSG_USERHOST), cli.DAEMON, m.Option(ice.MSG_DAEMON), m.ProcessOpen(m.Options(ice.MSG_USERWEB, m.Option(origin)).MergePodCmd("", m.PrefixKey(),
m.OptionSimple(name), mdb.TEXT, m.Cmdx("", "dev.request.text"), ctx.ACTION, mdb.DEV_CHOOSE, cli.BACK, m.Option(ice.MSG_USERHOST), cli.DAEMON, m.Option(ice.MSG_DAEMON),
m.OptionSimple(name), mdb.TEXT, m.Cmdx("", DEV_REQUEST_TEXT),
)) ))
}}, }},
mdb.DEV_CHOOSE: {Hand: func(m *ice.Message, arg ...string) { mdb.DEV_CHOOSE: {Hand: func(m *ice.Message, arg ...string) {
@ -80,8 +54,7 @@ func devTokenAction(name, origin string) ice.Actions {
if !m.Warn(m.Option(ice.MSG_METHOD) != http.MethodPost, ice.ErrNotAllow) { if !m.Warn(m.Option(ice.MSG_METHOD) != http.MethodPost, ice.ErrNotAllow) {
defer kit.If(m.Option(cli.DAEMON), func(p string) { m.Cmd(SPACE, p, html.REFRESH) }) defer kit.If(m.Option(cli.DAEMON), func(p string) { m.Cmd(SPACE, p, html.REFRESH) })
mdb.HashModify(m, m.OptionSimple(name, TOKEN)) mdb.HashModify(m, m.OptionSimple(name, TOKEN))
m.Cmd("", "dev.create.token") m.Cmdy("", DEV_CREATE_TOKEN).ProcessClose()
m.ProcessClose()
} }
}}, }},
} }

View File

@ -481,21 +481,17 @@ func init() {
m.Echo(_repos_remote(m, _repos_origin(m, _repos_open(m, path.Base(kit.Path("")))))) m.Echo(_repos_remote(m, _repos_origin(m, _repos_open(m, path.Base(kit.Path(""))))))
}}, }},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
switch m.Option(ctx.ACTION) { switch mdb.HashInputs(m, arg); m.Option(ctx.ACTION) {
case INIT: case INIT:
m.Cmd(web.SPIDE, ice.OptionFields(web.CLIENT_ORIGIN), func(value ice.Maps) { m.Push(arg[0], value[web.CLIENT_ORIGIN]+web.X(path.Base(kit.Path("")))) }) m.Cmd(web.SPIDE, ice.OptionFields(web.CLIENT_ORIGIN), func(value ice.Maps) { m.Push(arg[0], value[web.CLIENT_ORIGIN]+web.X(path.Base(kit.Path("")))) })
m.Push(arg[0], kit.MergeURL2(web.UserHost(m), web.X(path.Base(kit.Path(""))))) m.Push(arg[0], kit.MergeURL2(web.UserHost(m), web.X(path.Base(kit.Path("")))))
m.Sort(arg[0]) m.Sort(arg[0])
case INSTEADOF, OAUTH: case INSTEADOF:
m.Cmd(web.SPIDE, ice.OptionFields(web.CLIENT_ORIGIN), func(value ice.Maps) { m.Push(arg[0], value[web.CLIENT_ORIGIN]+web.X()) }) m.Cmd(web.SPIDE, ice.OptionFields(web.CLIENT_ORIGIN), func(value ice.Maps) { m.Push(arg[0], value[web.CLIENT_ORIGIN]+web.X()) })
m.Push(arg[0], kit.MergeURL2(web.UserHost(m), web.X())) m.Push(arg[0], kit.MergeURL2(web.UserHost(m), web.X()))
m.Sort(arg[0]) m.Sort(arg[0])
default: default:
switch arg[0] { switch arg[0] {
case ORIGIN:
m.Cmd(web.SPIDE, ice.OptionFields(web.CLIENT_ORIGIN), func(value ice.Maps) { m.Push(arg[0], value[web.CLIENT_ORIGIN]+web.X(path.Base(kit.Path("")))) })
m.Push(arg[0], kit.MergeURL2(web.UserHost(m), web.X(path.Base(kit.Path("")))))
m.Sort(arg[0])
case MESSAGE: case MESSAGE:
ls := kit.Split(m.Option(nfs.FILE), " /") ls := kit.Split(m.Option(nfs.FILE), " /")
m.Push(arg[0], kit.Select("", ls, -2)) m.Push(arg[0], kit.Select("", ls, -2))

View File

@ -125,7 +125,7 @@ func init() {
switch repos, service := _service_param(m, arg...); service { switch repos, service := _service_param(m, arg...); service {
case RECEIVE_PACK: case RECEIVE_PACK:
if !web.BasicCheck(m, "git server", func(msg *ice.Message) bool { if !web.BasicCheck(m, "git server", func(msg *ice.Message) bool {
return msg.Append(mdb.TYPE) == "web.code.git.status" || (msg.Append(mdb.TYPE) == web.SERVER && msg.Append(mdb.TEXT) == path.Base(repos)) return msg.Append(mdb.TYPE) == STATUS || (msg.Append(mdb.TYPE) == web.SERVER && msg.Append(mdb.TEXT) == path.Base(repos))
}) { }) {
return return
} else if !nfs.Exists(m, repos) { } else if !nfs.Exists(m, repos) {
@ -134,7 +134,7 @@ func init() {
case UPLOAD_PACK: case UPLOAD_PACK:
if mdb.Conf(m, Prefix(SERVICE), kit.Keym(aaa.AUTH)) == aaa.PRIVATE { if mdb.Conf(m, Prefix(SERVICE), kit.Keym(aaa.AUTH)) == aaa.PRIVATE {
if !web.BasicCheck(m, "git server", func(msg *ice.Message) bool { if !web.BasicCheck(m, "git server", func(msg *ice.Message) bool {
return msg.Append(mdb.TYPE) == "web.code.git.status" || msg.Append(mdb.TYPE) == web.SERVER && msg.Append(mdb.TEXT) == path.Base(repos) return msg.Append(mdb.TYPE) == STATUS || msg.Append(mdb.TYPE) == web.SERVER && msg.Append(mdb.TEXT) == path.Base(repos)
}) { }) {
return return
} }

View File

@ -9,9 +9,9 @@ import (
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/lex"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/base/web/html" "shylinux.com/x/icebergs/base/web/html"
"shylinux.com/x/icebergs/core/code" "shylinux.com/x/icebergs/core/code"
@ -42,10 +42,6 @@ func init() {
m.Cmdy(REPOS, mdb.INPUTS, arg) m.Cmdy(REPOS, mdb.INPUTS, arg)
} }
}}, }},
OAUTH: {Name: "oauth remote", Help: "授权", Icon: "bi bi-person-check", Hand: func(m *ice.Message, arg ...string) {
m.ProcessOpen(kit.MergeURL2(kit.Select(ice.Info.Make.Domain, m.Cmdx(REPOS, REMOTE_URL), m.Option(REMOTE)),
web.C(web.TOKEN), ctx.ACTION, "gen", mdb.TYPE, web.CODE_GIT_STATUS, tcp.HOST, web.UserHost(m)))
}},
CONFIGS: {Name: "configs email* username*", Help: "配置", Hand: func(m *ice.Message, arg ...string) { CONFIGS: {Name: "configs email* username*", Help: "配置", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(nfs.DEFS, kit.HomePath(_GITCONFIG), kit.Format(nfs.Template(m, "gitconfig"), m.Option(aaa.USERNAME), m.Option(aaa.EMAIL))) m.Cmd(nfs.DEFS, kit.HomePath(_GITCONFIG), kit.Format(nfs.Template(m, "gitconfig"), m.Option(aaa.USERNAME), m.Option(aaa.EMAIL)))
mdb.Config(m, aaa.USERNAME, m.Option(aaa.USERNAME)) mdb.Config(m, aaa.USERNAME, m.Option(aaa.USERNAME))
@ -70,7 +66,18 @@ func init() {
m.PushButton(kit.Dict(m.CommandKey(), "源码")) m.PushButton(kit.Dict(m.CommandKey(), "源码"))
}}, }},
web.DREAM_ACTION: {Hand: func(m *ice.Message, arg ...string) { web.DreamProcess(m, nil, arg...) }}, web.DREAM_ACTION: {Hand: func(m *ice.Message, arg ...string) { web.DreamProcess(m, nil, arg...) }},
}, ctx.ConfAction(ctx.TOOLS, "xterm,compile"), Prefix(REPOS)), Hand: func(m *ice.Message, arg ...string) { mdb.DEV_REQUEST: {Name: "dev.request origin*", Help: "授权"},
web.DEV_CREATE_TOKEN: {Hand: func(m *ice.Message, arg ...string) {
const FILE = ".git-credentials"
host, list := ice.Map{kit.ParseURL(m.Option(web.ORIGIN)).Host: true}, []string{strings.Replace(m.Option(web.ORIGIN), "://", kit.Format("://%s:%s@", m.Option(ice.MSG_USERNAME), m.Option(web.TOKEN)), 1)}
m.Cmd(nfs.CAT, kit.HomePath(FILE), func(line string) {
line = strings.ReplaceAll(line, "%3a", ":")
kit.IfNoKey(host, kit.ParseURL(line).Host, func(p string) { list = append(list, line) })
}).Cmd(nfs.SAVE, kit.HomePath(FILE), strings.Join(list, lex.NL)+lex.NL)
m.Cmd(CONFIGS, mdb.CREATE, "credential.helper", "store")
m.ProcessClose()
}},
}, web.DevTokenAction(web.ORIGIN, web.ORIGIN), ctx.ConfAction(ctx.TOOLS, "xterm,compile"), Prefix(REPOS)), Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 && arg[0] == ctx.ACTION { if len(arg) > 0 && arg[0] == ctx.ACTION {
m.Cmdy(REPOS, arg) m.Cmdy(REPOS, arg)
} else if config, err := config.LoadConfig(config.GlobalScope); err == nil && config.User.Email == "" && mdb.Config(m, aaa.EMAIL) == "" { } else if config, err := config.LoadConfig(config.GlobalScope); err == nil && config.User.Email == "" && mdb.Config(m, aaa.EMAIL) == "" {
@ -79,7 +86,7 @@ func init() {
m.EchoInfoButton("please init repos. ", INIT) m.EchoInfoButton("please init repos. ", INIT)
} else if len(arg) == 0 { } else if len(arg) == 0 {
kit.If(config != nil, func() { m.Option(aaa.EMAIL, kit.Select(mdb.Config(m, aaa.EMAIL), config.User.Email)) }) kit.If(config != nil, func() { m.Option(aaa.EMAIL, kit.Select(mdb.Config(m, aaa.EMAIL), config.User.Email)) })
m.Cmdy(REPOS, STATUS).Action(PULL, PUSH, INSTEADOF, OAUTH, CONFIGS) m.Cmdy(REPOS, STATUS).Action(PULL, PUSH, INSTEADOF, mdb.DEV_REQUEST, CONFIGS)
kit.If(!m.IsCliUA(), func() { m.Cmdy(code.PUBLISH, ice.CONTEXTS, ice.DEV) }) kit.If(!m.IsCliUA(), func() { m.Cmdy(code.PUBLISH, ice.CONTEXTS, ice.DEV) })
ctx.Toolkit(m) ctx.Toolkit(m)
} else { } else {