From 4abad1ec71617e2bd5994af4028737aacd8aefc7 Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Fri, 5 Sep 2014 14:33:43 +0800 Subject: [PATCH] . --- conf/wide.go | 1 + main.go | 1 + shell/shells.go | 64 +++++++++++++++++++++++++++++++++++++------- static/css/shell.css | 3 +++ static/js/shell.js | 36 +++++++++++++++++++++++++ static/js/wide.js | 40 +++++---------------------- view/shell.html | 28 +++++++++++++++++++ 7 files changed, 130 insertions(+), 43 deletions(-) create mode 100644 static/css/shell.css create mode 100644 static/js/shell.js create mode 100644 view/shell.html diff --git a/conf/wide.go b/conf/wide.go index 51fbb3c..83e54a8 100644 --- a/conf/wide.go +++ b/conf/wide.go @@ -1,3 +1,4 @@ +// Wide 配置相关,所有配置(包括用户配置)都是保存在 wide.json 中. package conf import ( diff --git a/main.go b/main.go index 1e43b6a..e71f0fc 100644 --- a/main.go +++ b/main.go @@ -93,6 +93,7 @@ func main() { // Shell http.HandleFunc("/shell/ws", shell.WSHandler) + http.HandleFunc("/shell", shell.IndexHandler) // 用户 http.HandleFunc("/user/new", user.AddUser) diff --git a/shell/shells.go b/shell/shells.go index 9796a31..8ebff1a 100644 --- a/shell/shells.go +++ b/shell/shells.go @@ -2,19 +2,58 @@ package shell import ( "github.com/b3log/wide/conf" + "github.com/b3log/wide/i18n" "github.com/b3log/wide/user" "github.com/golang/glog" "github.com/gorilla/websocket" + "html/template" + "math/rand" "net/http" "os" "os/exec" + "runtime" + "strconv" "strings" ) var shellWS = map[string]*websocket.Conn{} +func IndexHandler(w http.ResponseWriter, r *http.Request) { + i18n.Load() + + model := map[string]interface{}{"Wide": conf.Wide, "i18n": i18n.GetLangs(r), "locale": i18n.GetLocale(r)} + + session, _ := user.Session.Get(r, "wide-session") + + if session.IsNew { + // TODO: 写死以 admin 作为用户登录 + name := conf.Wide.Users[0].Name + + session.Values["username"] = name + session.Values["id"] = strconv.Itoa(rand.Int()) + // 一天过期 + session.Options.MaxAge = 60 * 60 * 24 + + glog.Infof("Created a session [%s] for user [%s]", session.Values["id"].(string), name) + } + + session.Save(r, w) + + t, err := template.ParseFiles("view/shell.html") + + if nil != err { + glog.Error(err) + http.Error(w, err.Error(), 500) + + return + } + + t.Execute(w, model) +} + func WSHandler(w http.ResponseWriter, r *http.Request) { session, _ := user.Session.Get(r, "wide-session") + username := session.Values["username"].(string) sid := session.Values["id"].(string) shellWS[sid], _ = websocket.Upgrade(w, r, nil, 1024, 1024) @@ -58,7 +97,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) { output := "" if !strings.Contains(inputCmd, "clear") { - output = pipeCommands(commands...) + output = pipeCommands(username, commands...) } ret = map[string]interface{}{"output": output, "cmd": "shell-output"} @@ -70,9 +109,9 @@ func WSHandler(w http.ResponseWriter, r *http.Request) { } } -func pipeCommands(commands ...*exec.Cmd) string { +func pipeCommands(username string, commands ...*exec.Cmd) string { for i, command := range commands[:len(commands)-1] { - setCmdEnv(command) + setCmdEnv(command, username) out, err := command.StdoutPipe() @@ -85,9 +124,10 @@ func pipeCommands(commands ...*exec.Cmd) string { } last := commands[len(commands)-1] - setCmdEnv(last) + setCmdEnv(last, username) out, err := last.Output() + if err != nil { return err.Error() } @@ -95,10 +135,16 @@ func pipeCommands(commands ...*exec.Cmd) string { return string(out) } -func setCmdEnv(cmd *exec.Cmd) { - // TODO: 使用用户自己的仓库路径设置 GOPATH - cmd.Env = append(cmd.Env, "TERM=xterm", "GOPATH="+conf.Wide.Workspace, - "GOROOT="+os.Getenv("GOROOT")) +func setCmdEnv(cmd *exec.Cmd, username string) { + userWorkspace := conf.Wide.GetUserWorkspace(username) - cmd.Dir = conf.Wide.Workspace + cmd.Env = append(cmd.Env, + "TERM=xterm", + "GOPATH="+userWorkspace, + "GOOS="+runtime.GOOS, + "GOARCH="+runtime.GOARCH, + "GOROOT="+runtime.GOROOT(), + "PATH="+os.Getenv("PATH")) + + cmd.Dir = userWorkspace } diff --git a/static/css/shell.css b/static/css/shell.css new file mode 100644 index 0000000..08c0bcb --- /dev/null +++ b/static/css/shell.css @@ -0,0 +1,3 @@ +#shellOutput, #shellInput { + width: 100%; +} \ No newline at end of file diff --git a/static/js/shell.js b/static/js/shell.js new file mode 100644 index 0000000..3f4bdda --- /dev/null +++ b/static/js/shell.js @@ -0,0 +1,36 @@ +var shellWS = new WebSocket(config.channel.shell + '/shell/ws'); +shellWS.onopen = function() { + console.log('[shell onopen] connected'); +}; +shellWS.onmessage = function(e) { + console.log('[shell onmessage]' + e.data); + var data = JSON.parse(e.data); + if ('init-shell' !== data.cmd) { + $('#shellOutput').val(data.output); + } +}; +shellWS.onclose = function(e) { + console.log('[shell onclose] disconnected (' + e.code + ')'); + delete shellWS; +}; +shellWS.onerror = function(e) { + console.log('[shell onerror] ' + e); +}; + +var shell = { + init: function() { + $('#shellInput').keydown(function(event) { + if (13 === event.which) { + var input = { + cmd: $('#shellInput').val() + }; + shellWS.send(JSON.stringify(input)); + $('#shellInput').val(''); + } + }); + } +}; + +$(document).ready(function() { + shell.init(); +}); \ No newline at end of file diff --git a/static/js/wide.js b/static/js/wide.js index ad27e5e..64f3a13 100644 --- a/static/js/wide.js +++ b/static/js/wide.js @@ -16,8 +16,8 @@ outputWS.onmessage = function(e) { return; } } else if ('go get' === data.cmd) { - $('#output').text($('#output').text() + data.output); - } + $('#output').text($('#output').text() + data.output); + } if ('build' === data.cmd) { if ('run' === data.nextCmd) { @@ -48,45 +48,17 @@ outputWS.onerror = function(e) { console.log('[output onerror] ' + e); }; -var shellWS = new WebSocket(config.channel.shell + '/shell/ws'); -shellWS.onopen = function() { - console.log('[shell onopen] connected'); -}; -shellWS.onmessage = function(e) { - console.log('[shell onmessage]' + e.data); - var data = JSON.parse(e.data); - if ('init-shell' !== data.cmd) { - $('#shellOutput').val(data.output); - } -}; -shellWS.onclose = function(e) { - console.log('[shell onclose] disconnected (' + e.code + ')'); - delete shellWS; -}; -shellWS.onerror = function(e) { - console.log('[shell onerror] ' + e); -}; - var wide = { curNode: undefined, curEditor: undefined, - _initLayout: function () { + _initLayout: function() { var mainH = $(window).height() - $(".menu").height() - $(".footer").height() - 2; $(".content, .ztree").height(mainH); - + $(".edit-panel").height(mainH - $(".output").height()); }, init: function() { this._initLayout(); - $('#shellInput').keydown(function(event) { - if (13 === event.which) { - var input = { - cmd: $('#shellInput').val() - }; - shellWS.send(JSON.stringify(input)); - $('#shellInput').val(''); - } - }); $("body").bind("mousedown", function(event) { if (!(event.target.id === "dirRMenu" || $(event.target).closest("#dirRMenu").length > 0)) { @@ -127,11 +99,11 @@ var wide = { beforeSend: function(data) { $('#output').text(''); }, - success: function(data) { + success: function(data) { } }); }, - goget: function() { + goget: function() { var request = { "file": wide.curNode.path }; diff --git a/view/shell.html b/view/shell.html new file mode 100644 index 0000000..253f393 --- /dev/null +++ b/view/shell.html @@ -0,0 +1,28 @@ + + + + + {{.i18n.wide}} + + + + + +
+ +
+ + + + + + + + +