This commit is contained in:
parent
912c5821f1
commit
b5aa4f9a7d
|
@ -1,8 +1,6 @@
|
||||||
/wide.exe
|
/wide.exe
|
||||||
/wide
|
/wide
|
||||||
|
|
||||||
/static/user/admin/style.css
|
|
||||||
|
|
||||||
/header
|
/header
|
||||||
/header.exe
|
/header.exe
|
||||||
|
|
||||||
|
|
60
conf/user.go
60
conf/user.go
|
@ -15,9 +15,6 @@
|
||||||
package conf
|
package conf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
|
||||||
"crypto/sha1"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -25,8 +22,6 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/b3log/wide/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Panel represents a UI panel.
|
// Panel represents a UI panel.
|
||||||
|
@ -52,11 +47,9 @@ type LatestSessionContent struct {
|
||||||
|
|
||||||
// User configuration.
|
// User configuration.
|
||||||
type User struct {
|
type User struct {
|
||||||
|
Id string
|
||||||
Name string
|
Name string
|
||||||
Password string
|
Avatar string
|
||||||
Salt string
|
|
||||||
Email string
|
|
||||||
Gravatar string // see http://gravatar.com
|
|
||||||
Workspace string // the GOPATH of this user (maybe contain several paths splitted by os.PathListSeparator)
|
Workspace string // the GOPATH of this user (maybe contain several paths splitted by os.PathListSeparator)
|
||||||
Locale string
|
Locale string
|
||||||
GoFormat string
|
GoFormat string
|
||||||
|
@ -83,27 +76,6 @@ type editor struct {
|
||||||
TabSize string
|
TabSize string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUser creates a user with the specified username, password, email and workspace.
|
|
||||||
func NewUser(username, password, email, workspace string) *User {
|
|
||||||
md5hash := md5.New()
|
|
||||||
md5hash.Write([]byte(email))
|
|
||||||
gravatar := hex.EncodeToString(md5hash.Sum(nil))
|
|
||||||
|
|
||||||
salt := util.Rand.String(16)
|
|
||||||
password = Salt(password, salt)
|
|
||||||
|
|
||||||
now := time.Now().UnixNano()
|
|
||||||
|
|
||||||
return &User{Name: username, Password: password, Salt: salt, Email: email, Gravatar: gravatar, Workspace: workspace,
|
|
||||||
Locale: Wide.Locale, GoFormat: "gofmt",
|
|
||||||
GoBuildArgsForLinux: "-i", GoBuildArgsForWindows: "-i", GoBuildArgsForDarwin: "-i",
|
|
||||||
FontFamily: "Helvetica", FontSize: "13px", Theme: "default",
|
|
||||||
Keymap: "wide",
|
|
||||||
Created: now, Updated: now, Lived: now,
|
|
||||||
Editor: &editor{FontFamily: "Consolas, 'Courier New', monospace", FontSize: "inherit", LineHeight: "17px",
|
|
||||||
Theme: "wide", TabSize: "4"}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save saves the user's configurations in conf/users/{username}.json.
|
// Save saves the user's configurations in conf/users/{username}.json.
|
||||||
func (u *User) Save() bool {
|
func (u *User) Save() bool {
|
||||||
bytes, err := json.MarshalIndent(u, "", " ")
|
bytes, err := json.MarshalIndent(u, "", " ")
|
||||||
|
@ -115,12 +87,12 @@ func (u *User) Save() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if "" == string(bytes) {
|
if "" == string(bytes) {
|
||||||
logger.Error("Truncated user [" + u.Name + "]")
|
logger.Error("Truncated user [" + u.Id + "]")
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = ioutil.WriteFile(filepath.Join(Wide.Users, u.Name+".json"), bytes, 0644); nil != err {
|
if err = ioutil.WriteFile(filepath.Join(Wide.Users, u.Id+".json"), bytes, 0644); nil != err {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
@ -129,6 +101,20 @@ func (u *User) Save() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewUser creates a user with the specified username and workspace.
|
||||||
|
func NewUser(id, name, avatar, workspace string) *User {
|
||||||
|
now := time.Now().UnixNano()
|
||||||
|
|
||||||
|
return &User{Id: id, Name: name, Avatar: avatar, Workspace: workspace,
|
||||||
|
Locale: Wide.Locale, GoFormat: "gofmt",
|
||||||
|
GoBuildArgsForLinux: "-i", GoBuildArgsForWindows: "-i", GoBuildArgsForDarwin: "-i",
|
||||||
|
FontFamily: "Helvetica", FontSize: "13px", Theme: "default",
|
||||||
|
Keymap: "wide",
|
||||||
|
Created: now, Updated: now, Lived: now,
|
||||||
|
Editor: &editor{FontFamily: "Consolas, 'Courier New', monospace", FontSize: "inherit", LineHeight: "17px",
|
||||||
|
Theme: "wide", TabSize: "4"}}
|
||||||
|
}
|
||||||
|
|
||||||
// WorkspacePath gets workspace path of the user.
|
// WorkspacePath gets workspace path of the user.
|
||||||
//
|
//
|
||||||
// Compared to the use of Wide.Workspace, this function will be processed as follows:
|
// Compared to the use of Wide.Workspace, this function will be processed as follows:
|
||||||
|
@ -168,17 +154,9 @@ func (u *User) BuildArgs(os string) []string {
|
||||||
func GetOwner(path string) string {
|
func GetOwner(path string) string {
|
||||||
for _, user := range Users {
|
for _, user := range Users {
|
||||||
if strings.HasPrefix(path, user.WorkspacePath()) {
|
if strings.HasPrefix(path, user.WorkspacePath()) {
|
||||||
return user.Name
|
return user.Id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Salt salts the specified password with the specified salt.
|
|
||||||
func Salt(password, salt string) string {
|
|
||||||
sha1hash := sha1.New()
|
|
||||||
sha1hash.Write([]byte(password + salt))
|
|
||||||
|
|
||||||
return hex.EncodeToString(sha1hash.Sum(nil))
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
{
|
|
||||||
"Name": "admin",
|
|
||||||
"Password": "d1bfca21893c908e64fabda01d71294b1ccdcaa7",
|
|
||||||
"Salt": "dnoyeb",
|
|
||||||
"Email": "",
|
|
||||||
"Gravatar": "d41d8cd98f00b204e9800998ecf8427e",
|
|
||||||
"Workspace": "${GOPATH}",
|
|
||||||
"Locale": "en_US",
|
|
||||||
"GoFormat": "gofmt",
|
|
||||||
"GoBuildArgsForLinux": "-i",
|
|
||||||
"GoBuildArgsForWindows": "-i",
|
|
||||||
"GoBuildArgsForDarwin": "-i",
|
|
||||||
"FontFamily": "Helvetica",
|
|
||||||
"FontSize": "13px",
|
|
||||||
"Theme": "default",
|
|
||||||
"Keymap": "wide",
|
|
||||||
"Created": 1414080000000000000,
|
|
||||||
"Updated": 1492963306222604966,
|
|
||||||
"Lived": 1492963306222604966,
|
|
||||||
"Editor": {
|
|
||||||
"FontFamily": "Consolas, 'Courier New', monospace",
|
|
||||||
"FontSize": "13px",
|
|
||||||
"LineHeight": "17px",
|
|
||||||
"Theme": "wide",
|
|
||||||
"TabSize": "4"
|
|
||||||
},
|
|
||||||
"LatestSessionContent": {
|
|
||||||
"fileTree": [
|
|
||||||
"/Users/Vanessa/Work/Code/GoGoGo/src",
|
|
||||||
"/Users/Vanessa/Work/Code/GoGoGo/src/github.com",
|
|
||||||
"/Users/Vanessa/Work/Code/GoGoGo/src/github.com/b3log",
|
|
||||||
"/Users/Vanessa/Work/Code/GoGoGo/src/github.com/b3log/wide",
|
|
||||||
"/Users/Vanessa/Work/Code/GoGoGo/src/github.com/b3log/wide/.idea",
|
|
||||||
"/Users/Vanessa/Work/Code/GoGoGo/src/github.com/b3log/wide/static",
|
|
||||||
"/Users/Vanessa/Work/Code/GoGoGo/src/github.com/b3log/wide/static/css",
|
|
||||||
"/Users/Vanessa/Work/Code/GoGoGo/src/github.com/b3log/wide/static/js"
|
|
||||||
],
|
|
||||||
"files": [],
|
|
||||||
"currentFile": "",
|
|
||||||
"layout": {
|
|
||||||
"side": {
|
|
||||||
"state": "normal",
|
|
||||||
"size": 200
|
|
||||||
},
|
|
||||||
"sideRight": {
|
|
||||||
"state": "normal",
|
|
||||||
"size": 200
|
|
||||||
},
|
|
||||||
"bottom": {
|
|
||||||
"state": "normal",
|
|
||||||
"size": 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
33
conf/wide.go
33
conf/wide.go
|
@ -42,6 +42,8 @@ const (
|
||||||
WideVersion = "1.5.3"
|
WideVersion = "1.5.3"
|
||||||
// CodeMirrorVer holds the current editor version.
|
// CodeMirrorVer holds the current editor version.
|
||||||
CodeMirrorVer = "5.1"
|
CodeMirrorVer = "5.1"
|
||||||
|
// UserAgent represents HTTP client user agent.
|
||||||
|
UserAgent = "Wide/" + WideVersion + "; +https://github.com/b3log/wide"
|
||||||
|
|
||||||
HelloWorld = `package main
|
HelloWorld = `package main
|
||||||
|
|
||||||
|
@ -70,7 +72,7 @@ type conf struct {
|
||||||
Locale string // default locale
|
Locale string // default locale
|
||||||
Playground string // playground directory
|
Playground string // playground directory
|
||||||
Users string // users directory
|
Users string // users directory
|
||||||
UsersWorkspaces string // users' workspaces directory (admin defaults to ${GOPATH}, others using this)
|
UsersWorkspaces string // users' workspaces directory
|
||||||
AllowRegister bool // allow register or not
|
AllowRegister bool // allow register or not
|
||||||
Autocomplete bool // default autocomplete
|
Autocomplete bool // default autocomplete
|
||||||
}
|
}
|
||||||
|
@ -335,10 +337,10 @@ func checkEnv() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserWorkspace gets workspace path with the specified username, returns "" if not found.
|
// GetUserWorkspace gets workspace path with the specified user id, returns "" if not found.
|
||||||
func GetUserWorkspace(username string) string {
|
func GetUserWorkspace(userId string) string {
|
||||||
for _, user := range Users {
|
for _, user := range Users {
|
||||||
if user.Name == username {
|
if user.Id == userId {
|
||||||
return user.WorkspacePath()
|
return user.WorkspacePath()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,9 +349,9 @@ func GetUserWorkspace(username string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetGoFmt gets the path of Go format tool, returns "gofmt" if not found "goimports".
|
// GetGoFmt gets the path of Go format tool, returns "gofmt" if not found "goimports".
|
||||||
func GetGoFmt(username string) string {
|
func GetGoFmt(userId string) string {
|
||||||
for _, user := range Users {
|
for _, user := range Users {
|
||||||
if user.Name == username {
|
if user.Id == userId {
|
||||||
switch user.GoFormat {
|
switch user.GoFormat {
|
||||||
case "gofmt":
|
case "gofmt":
|
||||||
return "gofmt"
|
return "gofmt"
|
||||||
|
@ -365,15 +367,14 @@ func GetGoFmt(username string) string {
|
||||||
return "gofmt"
|
return "gofmt"
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUser gets configuration of the user specified by the given username, returns nil if not found.
|
// GetUser gets configuration of the user specified by the given user id, returns nil if not found.
|
||||||
func GetUser(username string) *User {
|
func GetUser(id string) *User {
|
||||||
if "playground" == username { // reserved user for Playground
|
if "playground" == id { // reserved user for Playground
|
||||||
// mock it
|
return NewUser("playground", "playground", "", "")
|
||||||
return NewUser("playground", "", "", "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range Users {
|
for _, user := range Users {
|
||||||
if user.Name == username {
|
if user.Id == id {
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,17 +385,17 @@ func GetUser(username string) *User {
|
||||||
// initCustomizedConfs initializes the user customized configurations.
|
// initCustomizedConfs initializes the user customized configurations.
|
||||||
func initCustomizedConfs() {
|
func initCustomizedConfs() {
|
||||||
for _, user := range Users {
|
for _, user := range Users {
|
||||||
UpdateCustomizedConf(user.Name)
|
UpdateCustomizedConf(user.Id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCustomizedConf creates (if not exists) or updates user customized configuration files.
|
// UpdateCustomizedConf creates (if not exists) or updates user customized configuration files.
|
||||||
//
|
//
|
||||||
// 1. /static/user/{username}/style.css
|
// 1. /static/user/{username}/style.css
|
||||||
func UpdateCustomizedConf(username string) {
|
func UpdateCustomizedConf(userId string) {
|
||||||
var u *User
|
var u *User
|
||||||
for _, user := range Users { // maybe it is a beauty of the trade-off of the another world between design and implementation
|
for _, user := range Users { // maybe it is a beauty of the trade-off of the another world between design and implementation
|
||||||
if user.Name == username {
|
if user.Id == userId {
|
||||||
u = user
|
u = user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,7 +414,7 @@ func UpdateCustomizedConf(username string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
wd := util.OS.Pwd()
|
wd := util.OS.Pwd()
|
||||||
dir := filepath.Clean(wd + "/static/user/" + u.Name)
|
dir := filepath.Clean(wd + "/static/user/" + u.Id)
|
||||||
if err := os.MkdirAll(dir, 0755); nil != err {
|
if err := os.MkdirAll(dir, 0755); nil != err {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := session.Values["username"].(string)
|
uid := session.Values["uid"].(string)
|
||||||
|
|
||||||
path := args["path"].(string)
|
path := args["path"].(string)
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
logger.Tracef("offset: %d", offset)
|
logger.Tracef("offset: %d", offset)
|
||||||
|
|
||||||
userWorkspace := conf.GetUserWorkspace(username)
|
userWorkspace := conf.GetUserWorkspace(uid)
|
||||||
workspaces := filepath.SplitList(userWorkspace)
|
workspaces := filepath.SplitList(userWorkspace)
|
||||||
libPath := ""
|
libPath := ""
|
||||||
for _, workspace := range workspaces {
|
for _, workspace := range workspaces {
|
||||||
|
@ -183,7 +183,7 @@ func GetExprInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
defer util.RetResult(w, r, result)
|
defer util.RetResult(w, r, result)
|
||||||
|
|
||||||
session, _ := session.HTTPSession.Get(r, "wide-session")
|
session, _ := session.HTTPSession.Get(r, "wide-session")
|
||||||
username := session.Values["username"].(string)
|
uid := session.Values["uid"].(string)
|
||||||
|
|
||||||
var args map[string]interface{}
|
var args map[string]interface{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
||||||
|
@ -228,7 +228,7 @@ func GetExprInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := exec.Command(ideStub, argv...)
|
cmd := exec.Command(ideStub, argv...)
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
|
|
||||||
setCmdEnv(cmd, username)
|
setCmdEnv(cmd, uid)
|
||||||
|
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -259,7 +259,7 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := session.Values["username"].(string)
|
uid := session.Values["uid"].(string)
|
||||||
|
|
||||||
var args map[string]interface{}
|
var args map[string]interface{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
||||||
|
@ -304,7 +304,7 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := exec.Command(ideStub, argv...)
|
cmd := exec.Command(ideStub, argv...)
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
|
|
||||||
setCmdEnv(cmd, username)
|
setCmdEnv(cmd, uid)
|
||||||
|
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -347,7 +347,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := session.Values["username"].(string)
|
uid := session.Values["uid"].(string)
|
||||||
|
|
||||||
var args map[string]interface{}
|
var args map[string]interface{}
|
||||||
|
|
||||||
|
@ -392,7 +392,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := exec.Command(ideStub, argv...)
|
cmd := exec.Command(ideStub, argv...)
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
|
|
||||||
setCmdEnv(cmd, username)
|
setCmdEnv(cmd, uid)
|
||||||
|
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -453,8 +453,8 @@ func getCursorOffset(code string, line, ch int) (offset int) {
|
||||||
return offset
|
return offset
|
||||||
}
|
}
|
||||||
|
|
||||||
func setCmdEnv(cmd *exec.Cmd, username string) {
|
func setCmdEnv(cmd *exec.Cmd, userId string) {
|
||||||
userWorkspace := conf.GetUserWorkspace(username)
|
userWorkspace := conf.GetUserWorkspace(userId)
|
||||||
|
|
||||||
cmd.Env = append(cmd.Env,
|
cmd.Env = append(cmd.Env,
|
||||||
"GOPATH="+userWorkspace,
|
"GOPATH="+userWorkspace,
|
||||||
|
|
|
@ -80,12 +80,12 @@ func GetFilesHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
|
|
||||||
result := util.NewResult()
|
result := util.NewResult()
|
||||||
defer util.RetGzResult(w, r, result)
|
defer util.RetGzResult(w, r, result)
|
||||||
|
|
||||||
userWorkspace := conf.GetUserWorkspace(username)
|
userWorkspace := conf.GetUserWorkspace(uid)
|
||||||
workspaces := filepath.SplitList(userWorkspace)
|
workspaces := filepath.SplitList(userWorkspace)
|
||||||
|
|
||||||
root := Node{Name: "root", Path: "", IconSkin: "ico-ztree-dir ", Type: "d", IsParent: true, Children: []*Node{}}
|
root := Node{Name: "root", Path: "", IconSkin: "ico-ztree-dir ", Type: "d", IsParent: true, Children: []*Node{}}
|
||||||
|
@ -129,12 +129,12 @@ func RefreshDirectoryHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
|
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
path := r.FormValue("path")
|
path := r.FormValue("path")
|
||||||
|
|
||||||
if !util.Go.IsAPI(path) && !session.CanAccess(username, path) {
|
if !util.Go.IsAPI(path) && !session.CanAccess(uid, path) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -162,7 +162,7 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
|
|
||||||
result := util.NewResult()
|
result := util.NewResult()
|
||||||
defer util.RetResult(w, r, result)
|
defer util.RetResult(w, r, result)
|
||||||
|
@ -178,7 +178,7 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
path := args["path"].(string)
|
path := args["path"].(string)
|
||||||
|
|
||||||
if !util.Go.IsAPI(path) && !session.CanAccess(username, path) {
|
if !util.Go.IsAPI(path) && !session.CanAccess(uid, path) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -212,7 +212,7 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user := conf.GetUser(username)
|
user := conf.GetUser(uid)
|
||||||
|
|
||||||
data["path"] = "/workspace/" + user.Name + "/" + strings.Replace(path, user.WorkspacePath(), "", 1)
|
data["path"] = "/workspace/" + user.Name + "/" + strings.Replace(path, user.WorkspacePath(), "", 1)
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ func SaveFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
|
|
||||||
result := util.NewResult()
|
result := util.NewResult()
|
||||||
defer util.RetResult(w, r, result)
|
defer util.RetResult(w, r, result)
|
||||||
|
@ -255,7 +255,7 @@ func SaveFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
filePath := args["file"].(string)
|
filePath := args["file"].(string)
|
||||||
sid := args["sid"].(string)
|
sid := args["sid"].(string)
|
||||||
|
|
||||||
if util.Go.IsAPI(filePath) || !session.CanAccess(username, filePath) {
|
if util.Go.IsAPI(filePath) || !session.CanAccess(uid, filePath) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -294,7 +294,7 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
|
|
||||||
result := util.NewResult()
|
result := util.NewResult()
|
||||||
defer util.RetResult(w, r, result)
|
defer util.RetResult(w, r, result)
|
||||||
|
@ -310,7 +310,7 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
path := args["path"].(string)
|
path := args["path"].(string)
|
||||||
|
|
||||||
if util.Go.IsAPI(path) || !session.CanAccess(username, path) {
|
if util.Go.IsAPI(path) || !session.CanAccess(uid, path) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -331,9 +331,9 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if "f" == fileType {
|
if "f" == fileType {
|
||||||
logger.Debugf("Created a file [%s] by user [%s]", path, wSession.Username)
|
logger.Debugf("Created a file [%s] by user [%s]", path, wSession.UserId)
|
||||||
} else {
|
} else {
|
||||||
logger.Debugf("Created a dir [%s] by user [%s]", path, wSession.Username)
|
logger.Debugf("Created a dir [%s] by user [%s]", path, wSession.UserId)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
|
|
||||||
result := util.NewResult()
|
result := util.NewResult()
|
||||||
defer util.RetResult(w, r, result)
|
defer util.RetResult(w, r, result)
|
||||||
|
@ -362,7 +362,7 @@ func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
path := args["path"].(string)
|
path := args["path"].(string)
|
||||||
|
|
||||||
if util.Go.IsAPI(path) || !session.CanAccess(username, path) {
|
if util.Go.IsAPI(path) || !session.CanAccess(uid, path) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -381,7 +381,7 @@ func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debugf("Removed a file [%s] by user [%s]", path, wSession.Username)
|
logger.Debugf("Removed a file [%s] by user [%s]", path, wSession.UserId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenameFileHandler handles request of renaming file or directory.
|
// RenameFileHandler handles request of renaming file or directory.
|
||||||
|
@ -392,7 +392,7 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
|
|
||||||
result := util.NewResult()
|
result := util.NewResult()
|
||||||
defer util.RetResult(w, r, result)
|
defer util.RetResult(w, r, result)
|
||||||
|
@ -408,14 +408,14 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
oldPath := args["oldPath"].(string)
|
oldPath := args["oldPath"].(string)
|
||||||
if util.Go.IsAPI(oldPath) ||
|
if util.Go.IsAPI(oldPath) ||
|
||||||
!session.CanAccess(username, oldPath) {
|
!session.CanAccess(uid, oldPath) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
newPath := args["newPath"].(string)
|
newPath := args["newPath"].(string)
|
||||||
if util.Go.IsAPI(newPath) || !session.CanAccess(username, newPath) {
|
if util.Go.IsAPI(newPath) || !session.CanAccess(uid, newPath) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -434,7 +434,7 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debugf("Renamed a file [%s] to [%s] by user [%s]", oldPath, newPath, wSession.Username)
|
logger.Debugf("Renamed a file [%s] to [%s] by user [%s]", oldPath, newPath, wSession.UserId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use to find results sorting.
|
// Use to find results sorting.
|
||||||
|
@ -457,7 +457,7 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
|
|
||||||
result := util.NewResult()
|
result := util.NewResult()
|
||||||
defer util.RetResult(w, r, result)
|
defer util.RetResult(w, r, result)
|
||||||
|
@ -471,7 +471,7 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
path := args["path"].(string) // path of selected file in file tree
|
path := args["path"].(string) // path of selected file in file tree
|
||||||
if !util.Go.IsAPI(path) && !session.CanAccess(username, path) {
|
if !util.Go.IsAPI(path) && !session.CanAccess(uid, path) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -479,7 +479,7 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
name := args["name"].(string)
|
name := args["name"].(string)
|
||||||
|
|
||||||
userWorkspace := conf.GetUserWorkspace(username)
|
userWorkspace := conf.GetUserWorkspace(uid)
|
||||||
workspaces := filepath.SplitList(userWorkspace)
|
workspaces := filepath.SplitList(userWorkspace)
|
||||||
|
|
||||||
if "" != path && !util.File.IsDir(path) {
|
if "" != path && !util.File.IsDir(path) {
|
||||||
|
@ -536,7 +536,7 @@ func SearchTextHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
dir := args["dir"].(string)
|
dir := args["dir"].(string)
|
||||||
if "" == dir {
|
if "" == dir {
|
||||||
userWorkspace := conf.GetUserWorkspace(wSession.Username)
|
userWorkspace := conf.GetUserWorkspace(wSession.UserId)
|
||||||
workspaces := filepath.SplitList(userWorkspace)
|
workspaces := filepath.SplitList(userWorkspace)
|
||||||
dir = workspaces[0]
|
dir = workspaces[0]
|
||||||
}
|
}
|
||||||
|
|
7
go.mod
7
go.mod
|
@ -3,12 +3,19 @@ module github.com/b3log/wide
|
||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f // indirect
|
||||||
|
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect
|
||||||
github.com/fsnotify/fsnotify v1.4.7
|
github.com/fsnotify/fsnotify v1.4.7
|
||||||
github.com/gorilla/context v0.0.0-20141217160251-215affda49ad // indirect
|
github.com/gorilla/context v0.0.0-20141217160251-215affda49ad // indirect
|
||||||
github.com/gorilla/securecookie v0.0.0-20150327155805-8e98dd730fc4 // indirect
|
github.com/gorilla/securecookie v0.0.0-20150327155805-8e98dd730fc4 // indirect
|
||||||
github.com/gorilla/sessions v0.0.0-20150417174705-f61c3ec2cf65
|
github.com/gorilla/sessions v0.0.0-20150417174705-f61c3ec2cf65
|
||||||
github.com/gorilla/websocket v0.0.0-20150530030352-a3ec486e6a7a
|
github.com/gorilla/websocket v0.0.0-20150530030352-a3ec486e6a7a
|
||||||
github.com/hashicorp/go-version v1.2.0
|
github.com/hashicorp/go-version v1.2.0
|
||||||
|
github.com/moul/http2curl v1.0.0 // indirect
|
||||||
|
github.com/parnurzeal/gorequest v0.2.15
|
||||||
|
github.com/pkg/errors v0.8.1 // indirect
|
||||||
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect
|
||||||
|
golang.org/x/net v0.0.0-20190514140710-3ec191127204 // indirect
|
||||||
golang.org/x/sys v0.0.0-20190515190549-87c872767d25 // indirect
|
golang.org/x/sys v0.0.0-20190515190549-87c872767d25 // indirect
|
||||||
golang.org/x/text v0.3.2
|
golang.org/x/text v0.3.2
|
||||||
)
|
)
|
||||||
|
|
26
go.sum
26
go.sum
|
@ -1,5 +1,11 @@
|
||||||
|
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs=
|
||||||
|
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||||
|
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f h1:AUj1VoZUfhPhOPHULCQQDnGhRelpFWHMLhQVWDsS0v4=
|
||||||
|
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/context v0.0.0-20141217160251-215affda49ad h1:wJwKN6X6iRRVnjdBgrkWjhBOvYm7yw5boqXwFUnBtbE=
|
github.com/gorilla/context v0.0.0-20141217160251-215affda49ad h1:wJwKN6X6iRRVnjdBgrkWjhBOvYm7yw5boqXwFUnBtbE=
|
||||||
github.com/gorilla/context v0.0.0-20141217160251-215affda49ad/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v0.0.0-20141217160251-215affda49ad/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/securecookie v0.0.0-20150327155805-8e98dd730fc4 h1:X0DbEdoaUJT+NZ8mLHRNMSLmogzqLhsA1Eh6gs7Y7Zg=
|
github.com/gorilla/securecookie v0.0.0-20150327155805-8e98dd730fc4 h1:X0DbEdoaUJT+NZ8mLHRNMSLmogzqLhsA1Eh6gs7Y7Zg=
|
||||||
|
@ -10,8 +16,28 @@ github.com/gorilla/websocket v0.0.0-20150530030352-a3ec486e6a7a h1:p/PGT+3UGSK7e
|
||||||
github.com/gorilla/websocket v0.0.0-20150530030352-a3ec486e6a7a/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v0.0.0-20150530030352-a3ec486e6a7a/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
|
||||||
|
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
||||||
|
github.com/parnurzeal/gorequest v0.2.15 h1:oPjDCsF5IkD4gUk6vIgsxYNaSgvAnIh1EJeROn3HdJU=
|
||||||
|
github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE=
|
||||||
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
|
||||||
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190514140710-3ec191127204 h1:4yG6GqBtw9C+UrLp6s2wtSniayy/Vd/3F7ffLE427XI=
|
||||||
|
golang.org/x/net v0.0.0-20190514140710-3ec191127204/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190515190549-87c872767d25 h1:SSKQq5sjDoW0L0NaDoVl7d7HmtTxM0ezm0Ef9azs4uQ=
|
golang.org/x/sys v0.0.0-20190515190549-87c872767d25 h1:SSKQq5sjDoW0L0NaDoVl7d7HmtTxM0ezm0Ef9azs4uQ=
|
||||||
golang.org/x/sys v0.0.0-20190515190549-87c872767d25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190515190549-87c872767d25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
|
32
main.go
32
main.go
|
@ -158,9 +158,7 @@ func main() {
|
||||||
http.HandleFunc(conf.Wide.Context+"/notification/ws", handlerWrapper(notification.WSHandler))
|
http.HandleFunc(conf.Wide.Context+"/notification/ws", handlerWrapper(notification.WSHandler))
|
||||||
|
|
||||||
// user
|
// user
|
||||||
http.HandleFunc(conf.Wide.Context+"/login", handlerWrapper(session.LoginHandler))
|
|
||||||
http.HandleFunc(conf.Wide.Context+"/logout", handlerWrapper(session.LogoutHandler))
|
http.HandleFunc(conf.Wide.Context+"/logout", handlerWrapper(session.LogoutHandler))
|
||||||
http.HandleFunc(conf.Wide.Context+"/signup", handlerWrapper(session.SignUpUserHandler))
|
|
||||||
http.HandleFunc(conf.Wide.Context+"/preference", handlerWrapper(session.PreferenceHandler))
|
http.HandleFunc(conf.Wide.Context+"/preference", handlerWrapper(session.PreferenceHandler))
|
||||||
|
|
||||||
// playground
|
// playground
|
||||||
|
@ -197,8 +195,8 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
if "playground" == username { // reserved user for Playground
|
if "playground" == uid { // reserved user for Playground
|
||||||
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound)
|
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -210,9 +208,9 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
httpSession.Save(r, w)
|
httpSession.Save(r, w)
|
||||||
|
|
||||||
user := conf.GetUser(username)
|
user := conf.GetUser(uid)
|
||||||
if nil == user {
|
if nil == user {
|
||||||
logger.Warnf("Not found user [%s]", username)
|
logger.Warnf("Not found user [%s]", uid)
|
||||||
|
|
||||||
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound)
|
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound)
|
||||||
|
|
||||||
|
@ -221,14 +219,14 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
locale := user.Locale
|
locale := user.Locale
|
||||||
|
|
||||||
wideSessions := session.WideSessions.GetByUsername(username)
|
wideSessions := session.WideSessions.GetByUserId(uid)
|
||||||
|
|
||||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale,
|
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale,
|
||||||
"username": username, "sid": session.WideSessions.GenId(), "latestSessionContent": user.LatestSessionContent,
|
"uid": uid, "sid": session.WideSessions.GenId(), "latestSessionContent": user.LatestSessionContent,
|
||||||
"pathSeparator": conf.PathSeparator, "codeMirrorVer": conf.CodeMirrorVer,
|
"pathSeparator": conf.PathSeparator, "codeMirrorVer": conf.CodeMirrorVer,
|
||||||
"user": user, "editorThemes": conf.GetEditorThemes(), "crossPlatforms": util.Go.GetCrossPlatforms()}
|
"user": user, "editorThemes": conf.GetEditorThemes(), "crossPlatforms": util.Go.GetCrossPlatforms()}
|
||||||
|
|
||||||
logger.Debugf("User [%s] has [%d] sessions", username, len(wideSessions))
|
logger.Debugf("User [%s] has [%d] sessions", uid, len(wideSessions))
|
||||||
|
|
||||||
t, err := template.ParseFiles("views/index.html")
|
t, err := template.ParseFiles("views/index.html")
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -279,9 +277,9 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
httpSession.Save(r, w)
|
httpSession.Save(r, w)
|
||||||
|
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
locale := conf.GetUser(username).Locale
|
locale := conf.GetUser(uid).Locale
|
||||||
userWorkspace := conf.GetUserWorkspace(username)
|
userWorkspace := conf.GetUserWorkspace(uid)
|
||||||
|
|
||||||
sid := r.URL.Query()["sid"][0]
|
sid := r.URL.Query()["sid"][0]
|
||||||
wSession := session.WideSessions.Get(sid)
|
wSession := session.WideSessions.Get(sid)
|
||||||
|
@ -290,7 +288,7 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale,
|
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale,
|
||||||
"username": username, "workspace": userWorkspace, "ver": conf.WideVersion, "sid": sid}
|
"uid": uid, "workspace": userWorkspace, "ver": conf.WideVersion, "sid": sid}
|
||||||
|
|
||||||
t, err := template.ParseFiles("views/start.html")
|
t, err := template.ParseFiles("views/start.html")
|
||||||
|
|
||||||
|
@ -319,8 +317,8 @@ func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
httpSession.Save(r, w)
|
httpSession.Save(r, w)
|
||||||
|
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
locale := conf.GetUser(username).Locale
|
locale := conf.GetUser(uid).Locale
|
||||||
|
|
||||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale}
|
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale}
|
||||||
|
|
||||||
|
@ -351,8 +349,8 @@ func aboutHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
httpSession.Save(r, w)
|
httpSession.Save(r, w)
|
||||||
|
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
locale := conf.GetUser(username).Locale
|
locale := conf.GetUser(uid).Locale
|
||||||
|
|
||||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale,
|
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale,
|
||||||
"ver": conf.WideVersion, "goos": runtime.GOOS, "goarch": runtime.GOARCH, "gover": runtime.Version()}
|
"ver": conf.WideVersion, "goos": runtime.GOOS, "goarch": runtime.GOARCH, "gover": runtime.Version()}
|
||||||
|
|
|
@ -63,8 +63,8 @@ func event2Notification(e *event.Event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
httpSession, _ := session.HTTPSession.Get(wsChannel.Request, "wide-session")
|
httpSession, _ := session.HTTPSession.Get(wsChannel.Request, "wide-session")
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
locale := conf.GetUser(username).Locale
|
locale := conf.GetUser(uid).Locale
|
||||||
|
|
||||||
var notification *Notification
|
var notification *Notification
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,8 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
user := conf.GetUser(username)
|
user := conf.GetUser(uid)
|
||||||
locale := user.Locale
|
locale := user.Locale
|
||||||
|
|
||||||
var args map[string]interface{}
|
var args map[string]interface{}
|
||||||
|
@ -61,7 +61,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
filePath := args["file"].(string)
|
filePath := args["file"].(string)
|
||||||
|
|
||||||
if util.Go.IsAPI(filePath) || !session.CanAccess(username, filePath) {
|
if util.Go.IsAPI(filePath) || !session.CanAccess(uid, filePath) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -101,7 +101,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := exec.Command("go", goBuildArgs...)
|
cmd := exec.Command("go", goBuildArgs...)
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
|
|
||||||
setCmdEnv(cmd, username)
|
setCmdEnv(cmd, uid)
|
||||||
|
|
||||||
executable := filepath.Base(curDir) + suffix
|
executable := filepath.Base(curDir) + suffix
|
||||||
executable = filepath.Join(curDir, executable)
|
executable = filepath.Join(curDir, executable)
|
||||||
|
|
|
@ -43,8 +43,8 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
locale := conf.GetUser(username).Locale
|
locale := conf.GetUser(uid).Locale
|
||||||
|
|
||||||
var args map[string]interface{}
|
var args map[string]interface{}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
sid := args["sid"].(string)
|
sid := args["sid"].(string)
|
||||||
filePath := args["path"].(string)
|
filePath := args["path"].(string)
|
||||||
|
|
||||||
if util.Go.IsAPI(filePath) || !session.CanAccess(username, filePath) {
|
if util.Go.IsAPI(filePath) || !session.CanAccess(uid, filePath) {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -75,7 +75,7 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
suffix = ".exe"
|
suffix = ".exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
user := conf.GetUser(username)
|
user := conf.GetUser(uid)
|
||||||
goBuildArgs := []string{}
|
goBuildArgs := []string{}
|
||||||
goBuildArgs = append(goBuildArgs, "build")
|
goBuildArgs = append(goBuildArgs, "build")
|
||||||
goBuildArgs = append(goBuildArgs, user.BuildArgs(goos)...)
|
goBuildArgs = append(goBuildArgs, user.BuildArgs(goos)...)
|
||||||
|
@ -83,7 +83,7 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := exec.Command("go", goBuildArgs...)
|
cmd := exec.Command("go", goBuildArgs...)
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
|
|
||||||
setCmdEnv(cmd, username)
|
setCmdEnv(cmd, uid)
|
||||||
|
|
||||||
for i, env := range cmd.Env {
|
for i, env := range cmd.Env {
|
||||||
if strings.HasPrefix(env, "GOOS=") {
|
if strings.HasPrefix(env, "GOOS=") {
|
||||||
|
|
|
@ -41,8 +41,8 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
locale := conf.GetUser(username).Locale
|
locale := conf.GetUser(uid).Locale
|
||||||
|
|
||||||
var args map[string]interface{}
|
var args map[string]interface{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
||||||
|
@ -60,7 +60,7 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := exec.Command("go", "get")
|
cmd := exec.Command("go", "get")
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
|
|
||||||
setCmdEnv(cmd, username)
|
setCmdEnv(cmd, uid)
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -114,7 +114,7 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
defer cmd.Wait()
|
defer cmd.Wait()
|
||||||
|
|
||||||
logger.Debugf("User [%s, %s] is running [go get] [runningId=%d]", username, sid, runningId)
|
logger.Debugf("User [%s, %s] is running [go get] [runningId=%d]", uid, sid, runningId)
|
||||||
|
|
||||||
channelRet := map[string]interface{}{}
|
channelRet := map[string]interface{}{}
|
||||||
channelRet["cmd"] = "go get"
|
channelRet["cmd"] = "go get"
|
||||||
|
@ -123,11 +123,11 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
buf, _ := ioutil.ReadAll(reader)
|
buf, _ := ioutil.ReadAll(reader)
|
||||||
|
|
||||||
if 0 != len(buf) {
|
if 0 != len(buf) {
|
||||||
logger.Debugf("User [%s, %s] 's [go get] [runningId=%d] has done (with error)", username, sid, runningId)
|
logger.Debugf("User [%s, %s] 's [go get] [runningId=%d] has done (with error)", uid, sid, runningId)
|
||||||
|
|
||||||
channelRet["output"] = "<span class='get-error'>" + i18n.Get(locale, "get-error").(string) + "</span>\n" + string(buf)
|
channelRet["output"] = "<span class='get-error'>" + i18n.Get(locale, "get-error").(string) + "</span>\n" + string(buf)
|
||||||
} else {
|
} else {
|
||||||
logger.Debugf("User [%s, %s] 's running [go get] [runningId=%d] has done", username, sid, runningId)
|
logger.Debugf("User [%s, %s] 's running [go get] [runningId=%d] has done", uid, sid, runningId)
|
||||||
|
|
||||||
channelRet["output"] = "<span class='get-succ'>" + i18n.Get(locale, "get-succ").(string) + "</span>\n"
|
channelRet["output"] = "<span class='get-succ'>" + i18n.Get(locale, "get-succ").(string) + "</span>\n"
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,8 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
locale := conf.GetUser(username).Locale
|
locale := conf.GetUser(uid).Locale
|
||||||
|
|
||||||
var args map[string]interface{}
|
var args map[string]interface{}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := exec.Command("go", "install")
|
cmd := exec.Command("go", "install")
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
|
|
||||||
setCmdEnv(cmd, username)
|
setCmdEnv(cmd, uid)
|
||||||
|
|
||||||
logger.Debugf("go install %s", curDir)
|
logger.Debugf("go install %s", curDir)
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
defer cmd.Wait()
|
defer cmd.Wait()
|
||||||
|
|
||||||
logger.Debugf("User [%s, %s] is running [go install] [id=%d, dir=%s]", username, sid, runningId, curDir)
|
logger.Debugf("User [%s, %s] is running [go install] [id=%d, dir=%s]", uid, sid, runningId, curDir)
|
||||||
|
|
||||||
// read all
|
// read all
|
||||||
buf, _ := ioutil.ReadAll(reader)
|
buf, _ := ioutil.ReadAll(reader)
|
||||||
|
@ -183,7 +183,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if nil != session.OutputWS[sid] {
|
if nil != session.OutputWS[sid] {
|
||||||
logger.Debugf("User [%s, %s] 's running [go install] [id=%d, dir=%s] has done", username, sid, runningId, curDir)
|
logger.Debugf("User [%s, %s] 's running [go install] [id=%d, dir=%s] has done", uid, sid, runningId, curDir)
|
||||||
|
|
||||||
wsChannel := session.OutputWS[sid]
|
wsChannel := session.OutputWS[sid]
|
||||||
err := wsChannel.WriteJSON(&channelRet)
|
err := wsChannel.WriteJSON(&channelRet)
|
||||||
|
|
|
@ -104,8 +104,8 @@ func parsePath(curDir, outputLine string) string {
|
||||||
return tagStart + text + tagEnd + msgPart
|
return tagStart + text + tagEnd + msgPart
|
||||||
}
|
}
|
||||||
|
|
||||||
func setCmdEnv(cmd *exec.Cmd, username string) {
|
func setCmdEnv(cmd *exec.Cmd, uid string) {
|
||||||
userWorkspace := conf.GetUserWorkspace(username)
|
userWorkspace := conf.GetUserWorkspace(uid)
|
||||||
cache, err := os.UserCacheDir()
|
cache, err := os.UserCacheDir()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
logger.Warnf("Get user cache dir failed [" + err.Error() + "]")
|
logger.Warnf("Get user cache dir failed [" + err.Error() + "]")
|
||||||
|
|
|
@ -86,7 +86,7 @@ func (procs *procs) Kill(wSession *session.WideSession, pid int) {
|
||||||
for i, p := range userProcesses {
|
for i, p := range userProcesses {
|
||||||
if p.Pid == pid {
|
if p.Pid == pid {
|
||||||
if err := p.Kill(); nil != err {
|
if err := p.Kill(); nil != err {
|
||||||
logger.Errorf("Kill a process [pid=%d] of user [%s, %s] failed [error=%v]", pid, wSession.Username, sid, err)
|
logger.Errorf("Kill a process [pid=%d] of user [%s, %s] failed [error=%v]", pid, wSession.UserId, sid, err)
|
||||||
} else {
|
} else {
|
||||||
var newProcesses []*os.Process
|
var newProcesses []*os.Process
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ func (procs *procs) Kill(wSession *session.WideSession, pid int) {
|
||||||
// bind process with wide session
|
// bind process with wide session
|
||||||
wSession.SetProcesses(newProcesses)
|
wSession.SetProcesses(newProcesses)
|
||||||
|
|
||||||
logger.Debugf("Killed a process [pid=%d] of user [%s, %s]", pid, wSession.Username, sid)
|
logger.Debugf("Killed a process [pid=%d] of user [%s, %s]", pid, wSession.UserId, sid)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -106,7 +106,7 @@ func RunHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
go func(runningId int) {
|
go func(runningId int) {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
|
|
||||||
logger.Debugf("User [%s, %s] is running [id=%d, file=%s]", wSession.Username, sid, runningId, filePath)
|
logger.Debugf("User [%s, %s] is running [id=%d, file=%s]", wSession.UserId, sid, runningId, filePath)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
|
|
|
@ -41,8 +41,8 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
locale := conf.GetUser(username).Locale
|
locale := conf.GetUser(uid).Locale
|
||||||
|
|
||||||
var args map[string]interface{}
|
var args map[string]interface{}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := exec.Command("go", "test", "-v")
|
cmd := exec.Command("go", "test", "-v")
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
|
|
||||||
setCmdEnv(cmd, username)
|
setCmdEnv(cmd, uid)
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -114,7 +114,7 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
go func(runningId int) {
|
go func(runningId int) {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
|
|
||||||
logger.Debugf("User [%s, %s] is running [go test] [runningId=%d]", username, sid, runningId)
|
logger.Debugf("User [%s, %s] is running [go test] [runningId=%d]", uid, sid, runningId)
|
||||||
|
|
||||||
channelRet := map[string]interface{}{}
|
channelRet := map[string]interface{}{}
|
||||||
channelRet["cmd"] = "go test"
|
channelRet["cmd"] = "go test"
|
||||||
|
@ -126,11 +126,11 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd.Wait()
|
cmd.Wait()
|
||||||
|
|
||||||
if !cmd.ProcessState.Success() {
|
if !cmd.ProcessState.Success() {
|
||||||
logger.Debugf("User [%s, %s] 's running [go test] [runningId=%d] has done (with error)", username, sid, runningId)
|
logger.Debugf("User [%s, %s] 's running [go test] [runningId=%d] has done (with error)", uid, sid, runningId)
|
||||||
|
|
||||||
channelRet["output"] = "<span class='test-error'>" + i18n.Get(locale, "test-error").(string) + "</span>\n" + string(buf)
|
channelRet["output"] = "<span class='test-error'>" + i18n.Get(locale, "test-error").(string) + "</span>\n" + string(buf)
|
||||||
} else {
|
} else {
|
||||||
logger.Debugf("User [%s, %s] 's running [go test] [runningId=%d] has done", username, sid, runningId)
|
logger.Debugf("User [%s, %s] 's running [go test] [runningId=%d] has done", uid, sid, runningId)
|
||||||
|
|
||||||
channelRet["output"] = "<span class='test-succ'>" + i18n.Get(locale, "test-succ").(string) + "</span>\n" + string(buf)
|
channelRet["output"] = "<span class='test-succ'>" + i18n.Get(locale, "test-succ").(string) + "</span>\n" + string(buf)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
locale := conf.GetUser(username).Locale
|
locale := conf.GetUser(uid).Locale
|
||||||
|
|
||||||
var args map[string]interface{}
|
var args map[string]interface{}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := exec.Command("go", "vet", ".")
|
cmd := exec.Command("go", "vet", ".")
|
||||||
cmd.Dir = curDir
|
cmd.Dir = curDir
|
||||||
|
|
||||||
setCmdEnv(cmd, username)
|
setCmdEnv(cmd, uid)
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -114,7 +114,7 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
go func(runningId int) {
|
go func(runningId int) {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
|
|
||||||
logger.Debugf("User [%s, %s] is running [go vet] [runningId=%d]", username, sid, runningId)
|
logger.Debugf("User [%s, %s] is running [go vet] [runningId=%d]", uid, sid, runningId)
|
||||||
|
|
||||||
channelRet := map[string]interface{}{}
|
channelRet := map[string]interface{}{}
|
||||||
channelRet["cmd"] = "go vet"
|
channelRet["cmd"] = "go vet"
|
||||||
|
@ -126,11 +126,11 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd.Wait()
|
cmd.Wait()
|
||||||
|
|
||||||
if !cmd.ProcessState.Success() {
|
if !cmd.ProcessState.Success() {
|
||||||
logger.Debugf("User [%s, %s] 's running [go vet] [runningId=%d] has done (with error)", username, sid, runningId)
|
logger.Debugf("User [%s, %s] 's running [go vet] [runningId=%d] has done (with error)", uid, sid, runningId)
|
||||||
|
|
||||||
channelRet["output"] = "<span class='vet-error'>" + i18n.Get(locale, "vet-error").(string) + "</span>\n" + string(buf)
|
channelRet["output"] = "<span class='vet-error'>" + i18n.Get(locale, "vet-error").(string) + "</span>\n" + string(buf)
|
||||||
} else {
|
} else {
|
||||||
logger.Debugf("User [%s, %s] 's running [go vet] [runningId=%d] has done", username, sid, runningId)
|
logger.Debugf("User [%s, %s] 's running [go vet] [runningId=%d] has done", uid, sid, runningId)
|
||||||
|
|
||||||
channelRet["output"] = "<span class='vet-succ'>" + i18n.Get(locale, "vet-succ").(string) + "</span>\n" + string(buf)
|
channelRet["output"] = "<span class='vet-succ'>" + i18n.Get(locale, "vet-succ").(string) + "</span>\n" + string(buf)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
httpSession.Save(r, w)
|
httpSession.Save(r, w)
|
||||||
|
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
|
|
||||||
locale := conf.Wide.Locale
|
locale := conf.Wide.Locale
|
||||||
|
|
||||||
|
@ -92,9 +92,9 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
"code": template.HTML(code), "ver": conf.WideVersion, "year": time.Now().Year(),
|
"code": template.HTML(code), "ver": conf.WideVersion, "year": time.Now().Year(),
|
||||||
"embed": embed, "disqus": disqus, "fileName": fileName}
|
"embed": embed, "disqus": disqus, "fileName": fileName}
|
||||||
|
|
||||||
wideSessions := session.WideSessions.GetByUsername(username)
|
wideSessions := session.WideSessions.GetByUserId(uid)
|
||||||
|
|
||||||
logger.Debugf("User [%s] has [%d] sessions", username, len(wideSessions))
|
logger.Debugf("User [%s] has [%d] sessions", uid, len(wideSessions))
|
||||||
|
|
||||||
t, err := template.ParseFiles("views/playground/index.html")
|
t, err := template.ParseFiles("views/playground/index.html")
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ func RunHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
go func(runningId int) {
|
go func(runningId int) {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
|
|
||||||
logger.Debugf("User [%s, %s] is running [id=%d, file=%s]", wSession.Username, sid, runningId, filePath)
|
logger.Debugf("User [%s, %s] is running [id=%d, file=%s]", wSession.UserId, sid, runningId, filePath)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
// Copyright (c) 2014-2019, b3log.org & hacpai.com
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"github.com/b3log/wide/conf"
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/b3log/wide/util"
|
||||||
|
"github.com/parnurzeal/gorequest"
|
||||||
|
)
|
||||||
|
|
||||||
|
var states = map[string]string{}
|
||||||
|
|
||||||
|
// RedirectGitHubHandler redirects to GitHub auth page.
|
||||||
|
func RedirectGitHubHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
requestResult := util.NewResult()
|
||||||
|
_, _, errs := gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
|
||||||
|
Get("https://hacpai.com/oauth/wide/client").
|
||||||
|
Set("user-agent", conf.UserAgent).Timeout(10 * time.Second).EndStruct(requestResult)
|
||||||
|
if nil != errs {
|
||||||
|
logger.Errorf("Get oauth client id failed: %+v", errs)
|
||||||
|
http.Error(w, "Get oauth info failed", http.StatusInternalServerError)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if 0 != requestResult.Code {
|
||||||
|
logger.Errorf("get oauth client id failed [code=%d, msg=%s]", requestResult.Code, requestResult.Msg)
|
||||||
|
http.Error(w, "Get oauth info failed", http.StatusNotFound)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := requestResult.Data.(map[string]interface{})
|
||||||
|
clientId := data["clientId"].(string)
|
||||||
|
loginAuthURL := data["loginAuthURL"].(string)
|
||||||
|
|
||||||
|
referer := r.URL.Query().Get("referer")
|
||||||
|
if "" == referer || !strings.Contains(referer, "://") {
|
||||||
|
referer = conf.Wide.Server + referer
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(referer, "/") {
|
||||||
|
referer = referer[:len(referer)-1]
|
||||||
|
}
|
||||||
|
state := util.Rand.String(16) + referer
|
||||||
|
states[state] = state
|
||||||
|
path := loginAuthURL + "?client_id=" + clientId + "&state=" + state + "&scope=public_repo,read:user,user:follow"
|
||||||
|
|
||||||
|
logger.Infof("redirect to github [" + path + "]")
|
||||||
|
|
||||||
|
http.Redirect(w, r, path, http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GithubCallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
logger.Infof("Github callback [" + r.URL.String() + "]")
|
||||||
|
|
||||||
|
state := r.URL.Query().Get("state")
|
||||||
|
if _, exist := states[state]; !exist {
|
||||||
|
http.Error(w, "Get state param failed", http.StatusBadRequest)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(states, state)
|
||||||
|
|
||||||
|
referer := state[16:]
|
||||||
|
if strings.Contains(referer, "__0") || strings.Contains(referer, "__1") {
|
||||||
|
referer = referer[:len(referer)-len("__0")]
|
||||||
|
}
|
||||||
|
accessToken := r.URL.Query().Get("ak")
|
||||||
|
githubUser := GitHubUserInfo(accessToken)
|
||||||
|
if nil == githubUser {
|
||||||
|
logger.Warnf("Can not get user info with token [" + accessToken + "]")
|
||||||
|
http.Error(w, "Get user info failed", http.StatusUnauthorized)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
githubId := githubUser["userId"].(string)
|
||||||
|
userName := githubUser["userName"].(string)
|
||||||
|
avatar := githubUser["userAvatar"].(string)
|
||||||
|
|
||||||
|
result := util.NewResult()
|
||||||
|
defer util.RetResult(w, r, result)
|
||||||
|
|
||||||
|
user := conf.GetUser(githubId)
|
||||||
|
if nil == user {
|
||||||
|
msg := addUser(githubId, userName, avatar)
|
||||||
|
if userCreated != msg {
|
||||||
|
result.Succ = false
|
||||||
|
result.Msg = msg
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a HTTP session
|
||||||
|
httpSession, _ := HTTPSession.Get(r, "wide-session")
|
||||||
|
httpSession.Values["username"] = userName
|
||||||
|
|
||||||
|
httpSession.Values["id"] = strconv.Itoa(rand.Int())
|
||||||
|
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
|
||||||
|
if "" != conf.Wide.Context {
|
||||||
|
httpSession.Options.Path = conf.Wide.Context
|
||||||
|
}
|
||||||
|
httpSession.Save(r, w)
|
||||||
|
|
||||||
|
logger.Debugf("Created a HTTP session [%s] for user [%s]", httpSession.Values["id"].(string), userName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitHubUserInfo returns GitHub user info specified by the given access token.
|
||||||
|
func GitHubUserInfo(accessToken string) (ret map[string]interface{}) {
|
||||||
|
result := map[string]interface{}{}
|
||||||
|
response, data, errors := gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
|
||||||
|
Get("https://hacpai.com/github/user?ak="+accessToken).Timeout(7*time.Second).
|
||||||
|
Set("User-Agent", conf.UserAgent).EndStruct(&result)
|
||||||
|
if nil != errors || http.StatusOK != response.StatusCode {
|
||||||
|
logger.Errorf("Get github user info failed: %+v, %s", errors, data)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if 0 != result["sc"].(float64) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return result["data"].(map[string]interface{})
|
||||||
|
}
|
|
@ -75,7 +75,7 @@ var HTTPSession = sessions.NewCookieStore([]byte("BEYOND"))
|
||||||
// WideSession represents a session associated with a browser tab.
|
// WideSession represents a session associated with a browser tab.
|
||||||
type WideSession struct {
|
type WideSession struct {
|
||||||
ID string // id
|
ID string // id
|
||||||
Username string // username
|
UserId string // user id
|
||||||
HTTPSession *sessions.Session // HTTP session related
|
HTTPSession *sessions.Session // HTTP session related
|
||||||
Processes []*os.Process // process set
|
Processes []*os.Process // process set
|
||||||
EventQueue *event.UserEventQueue // event queue
|
EventQueue *event.UserEventQueue // event queue
|
||||||
|
@ -111,7 +111,7 @@ func FixedTimeRelease() {
|
||||||
|
|
||||||
for _, s := range WideSessions {
|
for _, s := range WideSessions {
|
||||||
if s.Updated.Before(threshold) {
|
if s.Updated.Before(threshold) {
|
||||||
logger.Debugf("Removes a invalid session [%s], user [%s]", s.ID, s.Username)
|
logger.Debugf("Removes a invalid session [%s], user [%s]", s.ID, s.UserId)
|
||||||
|
|
||||||
WideSessions.Remove(s.ID)
|
WideSessions.Remove(s.ID)
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ func FixedTimeReport() {
|
||||||
go func() {
|
go func() {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
|
|
||||||
for _ = range time.Tick(10 * time.Minute) {
|
for _ = range time.Tick(10*time.Minute) {
|
||||||
users := userReports{}
|
users := userReports{}
|
||||||
processSum := 0
|
processSum := 0
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ func FixedTimeReport() {
|
||||||
processCnt := len(s.Processes)
|
processCnt := len(s.Processes)
|
||||||
processSum += processCnt
|
processSum += processCnt
|
||||||
|
|
||||||
if report, exists := contains(users, s.Username); exists {
|
if report, exists := contains(users, s.UserId); exists {
|
||||||
if s.Updated.After(report.updated) {
|
if s.Updated.After(report.updated) {
|
||||||
report.updated = s.Updated
|
report.updated = s.Updated
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ func FixedTimeReport() {
|
||||||
report.sessionCnt++
|
report.sessionCnt++
|
||||||
report.processCnt += processCnt
|
report.processCnt += processCnt
|
||||||
} else {
|
} else {
|
||||||
users = append(users, &userReport{username: s.Username, sessionCnt: 1, processCnt: processCnt, updated: s.Updated})
|
users = append(users, &userReport{username: s.UserId, sessionCnt: 1, processCnt: processCnt, updated: s.Updated})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
wSession = WideSessions.new(httpSession, sid)
|
wSession = WideSessions.new(httpSession, sid)
|
||||||
|
|
||||||
logger.Tracef("Created a wide session [%s] for websocket reconnecting, user [%s]", sid, wSession.Username)
|
logger.Tracef("Created a wide session [%s] for websocket reconnecting, user [%s]", sid, wSession.UserId)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Tracef("Open a new [Session Channel] with session [%s], %d", sid, len(SessionWS))
|
logger.Tracef("Open a new [Session Channel] with session [%s], %d", sid, len(SessionWS))
|
||||||
|
@ -263,7 +263,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if err := wsChan.ReadJSON(&input); err != nil {
|
if err := wsChan.ReadJSON(&input); err != nil {
|
||||||
logger.Tracef("[Session Channel] of session [%s] disconnected, releases all resources with it, user [%s]", sid, wSession.Username)
|
logger.Tracef("[Session Channel] of session [%s] disconnected, releases all resources with it, user [%s]", sid, wSession.UserId)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ func SaveContentHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
wSession.Content = args.LatestSessionContent
|
wSession.Content = args.LatestSessionContent
|
||||||
|
|
||||||
for _, user := range conf.Users {
|
for _, user := range conf.Users {
|
||||||
if user.Name == wSession.Username {
|
if user.Id == wSession.UserId {
|
||||||
// update the variable in-memory, session.FixedTimeSave() function will persist it periodically
|
// update the variable in-memory, session.FixedTimeSave() function will persist it periodically
|
||||||
user.LatestSessionContent = wSession.Content
|
user.LatestSessionContent = wSession.Content
|
||||||
|
|
||||||
|
@ -376,9 +376,9 @@ func (sessions *wSessions) Remove(sid string) {
|
||||||
// kill processes
|
// kill processes
|
||||||
for _, p := range s.Processes {
|
for _, p := range s.Processes {
|
||||||
if err := p.Kill(); nil != err {
|
if err := p.Kill(); nil != err {
|
||||||
logger.Errorf("Can't kill process [%d] of session [%s], user [%s]", p.Pid, sid, s.Username)
|
logger.Errorf("Can't kill process [%d] of session [%s], user [%s]", p.Pid, sid, s.UserId)
|
||||||
} else {
|
} else {
|
||||||
logger.Debugf("Killed a process [%d] of session [%s], user [%s]", p.Pid, sid, s.Username)
|
logger.Debugf("Killed a process [%d] of session [%s], user [%s]", p.Pid, sid, s.UserId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,12 +410,12 @@ func (sessions *wSessions) Remove(sid string) {
|
||||||
|
|
||||||
cnt := 0 // count wide sessions associated with HTTP session
|
cnt := 0 // count wide sessions associated with HTTP session
|
||||||
for _, ses := range *sessions {
|
for _, ses := range *sessions {
|
||||||
if ses.Username == s.Username {
|
if ses.UserId == s.UserId {
|
||||||
cnt++
|
cnt++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debugf("Removed a session [%s] of user [%s], it has [%d] sessions currently", sid, s.Username, cnt)
|
logger.Debugf("Removed a session [%s] of user [%s], it has [%d] sessions currently", sid, s.UserId, cnt)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -423,14 +423,14 @@ func (sessions *wSessions) Remove(sid string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByUsername gets wide sessions.
|
// GetByUsername gets wide sessions.
|
||||||
func (sessions *wSessions) GetByUsername(username string) []*WideSession {
|
func (sessions *wSessions) GetByUserId(userId string) []*WideSession {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
|
|
||||||
ret := []*WideSession{}
|
ret := []*WideSession{}
|
||||||
|
|
||||||
for _, s := range *sessions {
|
for _, s := range *sessions {
|
||||||
if s.Username == username {
|
if s.UserId == userId {
|
||||||
ret = append(ret, s)
|
ret = append(ret, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,12 +443,12 @@ func (sessions *wSessions) new(httpSession *sessions.Session, sid string) *WideS
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
|
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
ret := &WideSession{
|
ret := &WideSession{
|
||||||
ID: sid,
|
ID: sid,
|
||||||
Username: username,
|
UserId: uid,
|
||||||
HTTPSession: httpSession,
|
HTTPSession: httpSession,
|
||||||
EventQueue: nil,
|
EventQueue: nil,
|
||||||
State: sessionStateActive,
|
State: sessionStateActive,
|
||||||
|
@ -459,7 +459,7 @@ func (sessions *wSessions) new(httpSession *sessions.Session, sid string) *WideS
|
||||||
|
|
||||||
*sessions = append(*sessions, ret)
|
*sessions = append(*sessions, ret)
|
||||||
|
|
||||||
if "playground" == username {
|
if "playground" == uid {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,7 +526,7 @@ func (sessions *wSessions) new(httpSession *sessions.Session, sid string) *WideS
|
||||||
go func() {
|
go func() {
|
||||||
defer util.Recover()
|
defer util.Recover()
|
||||||
|
|
||||||
workspaces := filepath.SplitList(conf.GetUserWorkspace(username))
|
workspaces := filepath.SplitList(conf.GetUserWorkspace(uid))
|
||||||
for _, workspace := range workspaces {
|
for _, workspace := range workspaces {
|
||||||
filepath.Walk(filepath.Join(workspace, "src"), func(dirPath string, f os.FileInfo, err error) error {
|
filepath.Walk(filepath.Join(workspace, "src"), func(dirPath string, f os.FileInfo, err error) error {
|
||||||
if strings.HasPrefix(f.Name(), ".") || "node_modules" == f.Name() || "vendor" == f.Name() {
|
if strings.HasPrefix(f.Name(), ".") || "node_modules" == f.Name() || "vendor" == f.Name() {
|
||||||
|
|
185
session/users.go
185
session/users.go
|
@ -15,15 +15,11 @@
|
||||||
package session
|
package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
@ -38,7 +34,6 @@ const (
|
||||||
// TODO: i18n
|
// TODO: i18n
|
||||||
|
|
||||||
userExists = "user exists"
|
userExists = "user exists"
|
||||||
emailExists = "email exists"
|
|
||||||
userCreated = "user created"
|
userCreated = "user created"
|
||||||
userCreateError = "user create error"
|
userCreateError = "user create error"
|
||||||
notAllowRegister = "not allow register"
|
notAllowRegister = "not allow register"
|
||||||
|
@ -63,8 +58,8 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
httpSession.Save(r, w)
|
httpSession.Save(r, w)
|
||||||
|
|
||||||
username := httpSession.Values["username"].(string)
|
uid := httpSession.Values["uid"].(string)
|
||||||
user := conf.GetUser(username)
|
user := conf.GetUser(uid)
|
||||||
|
|
||||||
if "GET" == r.Method {
|
if "GET" == r.Method {
|
||||||
tmpLinux := user.GoBuildArgsForLinux
|
tmpLinux := user.GoBuildArgsForLinux
|
||||||
|
@ -116,8 +111,6 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
Keymap string
|
Keymap string
|
||||||
Workspace string
|
Workspace string
|
||||||
Username string
|
Username string
|
||||||
Password string
|
|
||||||
Email string
|
|
||||||
Locale string
|
Locale string
|
||||||
Theme string
|
Theme string
|
||||||
EditorFontFamily string
|
EditorFontFamily string
|
||||||
|
@ -143,14 +136,6 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
user.Keymap = args.Keymap
|
user.Keymap = args.Keymap
|
||||||
// XXX: disallow change workspace at present
|
// XXX: disallow change workspace at present
|
||||||
// user.Workspace = args.Workspace
|
// user.Workspace = args.Workspace
|
||||||
if user.Password != args.Password {
|
|
||||||
user.Password = conf.Salt(args.Password, user.Salt)
|
|
||||||
}
|
|
||||||
user.Email = args.Email
|
|
||||||
|
|
||||||
hash := md5.New()
|
|
||||||
hash.Write([]byte(user.Email))
|
|
||||||
user.Gravatar = hex.EncodeToString(hash.Sum(nil))
|
|
||||||
|
|
||||||
user.Locale = args.Locale
|
user.Locale = args.Locale
|
||||||
user.Theme = args.Theme
|
user.Theme = args.Theme
|
||||||
|
@ -160,7 +145,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
user.Editor.Theme = args.EditorTheme
|
user.Editor.Theme = args.EditorTheme
|
||||||
user.Editor.TabSize = args.EditorTabSize
|
user.Editor.TabSize = args.EditorTabSize
|
||||||
|
|
||||||
conf.UpdateCustomizedConf(username)
|
conf.UpdateCustomizedConf(uid)
|
||||||
|
|
||||||
now := time.Now().UnixNano()
|
now := time.Now().UnixNano()
|
||||||
user.Lived = now
|
user.Lived = now
|
||||||
|
@ -169,66 +154,6 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
result.Succ = user.Save()
|
result.Succ = user.Save()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoginHandler handles request of user login.
|
|
||||||
func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if "GET" == r.Method {
|
|
||||||
// show the login page
|
|
||||||
|
|
||||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(conf.Wide.Locale),
|
|
||||||
"locale": conf.Wide.Locale, "ver": conf.WideVersion, "year": time.Now().Year()}
|
|
||||||
|
|
||||||
t, err := template.ParseFiles("views/login.html")
|
|
||||||
|
|
||||||
if nil != err {
|
|
||||||
logger.Error(err)
|
|
||||||
http.Error(w, err.Error(), 500)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Execute(w, model)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// non-GET request as login request
|
|
||||||
result := util.NewResult()
|
|
||||||
defer util.RetResult(w, r, result)
|
|
||||||
|
|
||||||
args := struct {
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
}{}
|
|
||||||
|
|
||||||
args.Username = r.FormValue("username")
|
|
||||||
args.Password = r.FormValue("password")
|
|
||||||
|
|
||||||
result.Succ = false
|
|
||||||
for _, user := range conf.Users {
|
|
||||||
if user.Name == args.Username && user.Password == conf.Salt(args.Password, user.Salt) {
|
|
||||||
result.Succ = true
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !result.Succ {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a HTTP session
|
|
||||||
httpSession, _ := HTTPSession.Get(r, "wide-session")
|
|
||||||
httpSession.Values["username"] = args.Username
|
|
||||||
httpSession.Values["id"] = strconv.Itoa(rand.Int())
|
|
||||||
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
|
|
||||||
if "" != conf.Wide.Context {
|
|
||||||
httpSession.Options.Path = conf.Wide.Context
|
|
||||||
}
|
|
||||||
httpSession.Save(r, w)
|
|
||||||
|
|
||||||
logger.Debugf("Created a HTTP session [%s] for user [%s]", httpSession.Values["id"].(string), args.Username)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogoutHandler handles request of user logout (exit).
|
// LogoutHandler handles request of user logout (exit).
|
||||||
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
result := util.NewResult()
|
result := util.NewResult()
|
||||||
|
@ -240,66 +165,6 @@ func LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
httpSession.Save(r, w)
|
httpSession.Save(r, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignUpUserHandler handles request of registering user.
|
|
||||||
func SignUpUserHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if "GET" == r.Method {
|
|
||||||
// show the user sign up page
|
|
||||||
|
|
||||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(conf.Wide.Locale),
|
|
||||||
"locale": conf.Wide.Locale, "ver": conf.WideVersion, "dir": conf.Wide.UsersWorkspaces,
|
|
||||||
"pathSeparator": conf.PathSeparator, "year": time.Now().Year()}
|
|
||||||
|
|
||||||
t, err := template.ParseFiles("views/sign_up.html")
|
|
||||||
|
|
||||||
if nil != err {
|
|
||||||
logger.Error(err)
|
|
||||||
http.Error(w, err.Error(), 500)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Execute(w, model)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// non-GET request as add user request
|
|
||||||
|
|
||||||
result := util.NewResult()
|
|
||||||
defer util.RetResult(w, r, result)
|
|
||||||
|
|
||||||
var args map[string]interface{}
|
|
||||||
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
|
||||||
logger.Error(err)
|
|
||||||
result.Succ = false
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
username := args["username"].(string)
|
|
||||||
password := args["password"].(string)
|
|
||||||
email := args["email"].(string)
|
|
||||||
|
|
||||||
msg := addUser(username, password, email)
|
|
||||||
if userCreated != msg {
|
|
||||||
result.Succ = false
|
|
||||||
result.Msg = msg
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a HTTP session
|
|
||||||
httpSession, _ := HTTPSession.Get(r, "wide-session")
|
|
||||||
httpSession.Values["username"] = username
|
|
||||||
httpSession.Values["id"] = strconv.Itoa(rand.Int())
|
|
||||||
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
|
|
||||||
if "" != conf.Wide.Context {
|
|
||||||
httpSession.Options.Path = conf.Wide.Context
|
|
||||||
}
|
|
||||||
httpSession.Save(r, w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FixedTimeSave saves online users' configurations periodically (1 minute).
|
// FixedTimeSave saves online users' configurations periodically (1 minute).
|
||||||
//
|
//
|
||||||
// Main goal of this function is to save user session content, for restoring session content while user open Wide next time.
|
// Main goal of this function is to save user session content, for restoring session content while user open Wide next time.
|
||||||
|
@ -313,11 +178,11 @@ func FixedTimeSave() {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanAccess determines whether the user specified by the given username can access the specified path.
|
// CanAccess determines whether the user specified by the given user id can access the specified path.
|
||||||
func CanAccess(username, path string) bool {
|
func CanAccess(userId, path string) bool {
|
||||||
path = filepath.FromSlash(path)
|
path = filepath.FromSlash(path)
|
||||||
|
|
||||||
userWorkspace := conf.GetUserWorkspace(username)
|
userWorkspace := conf.GetUserWorkspace(userId)
|
||||||
workspaces := filepath.SplitList(userWorkspace)
|
workspaces := filepath.SplitList(userWorkspace)
|
||||||
|
|
||||||
for _, workspace := range workspaces {
|
for _, workspace := range workspaces {
|
||||||
|
@ -342,20 +207,20 @@ func SaveOnlineUsers() {
|
||||||
func getOnlineUsers() []*conf.User {
|
func getOnlineUsers() []*conf.User {
|
||||||
ret := []*conf.User{}
|
ret := []*conf.User{}
|
||||||
|
|
||||||
usernames := map[string]string{} // distinct username
|
uids := map[string]string{} // distinct uid
|
||||||
for _, s := range WideSessions {
|
for _, s := range WideSessions {
|
||||||
usernames[s.Username] = s.Username
|
uids[s.UserId] = s.UserId
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, username := range usernames {
|
for _, uid := range uids {
|
||||||
u := conf.GetUser(username)
|
u := conf.GetUser(uid)
|
||||||
|
|
||||||
if "playground" == username { // user [playground] is a reserved mock user
|
if "playground" == uid { // user [playground] is a reserved mock user
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if nil == u {
|
if nil == u {
|
||||||
logger.Warnf("Not found user [%s]", username)
|
logger.Warnf("Not found user [%s]", uid)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -366,7 +231,7 @@ func getOnlineUsers() []*conf.User {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// addUser add a user with the specified username, password and email.
|
// addUser add a user with the specified user id, username and avatar.
|
||||||
//
|
//
|
||||||
// 1. create the user's workspace
|
// 1. create the user's workspace
|
||||||
// 2. generate 'Hello, 世界' demo code in the workspace (a console version and a HTTP version)
|
// 2. generate 'Hello, 世界' demo code in the workspace (a console version and a HTTP version)
|
||||||
|
@ -374,12 +239,12 @@ func getOnlineUsers() []*conf.User {
|
||||||
// 4. serve files of the user's workspace via HTTP
|
// 4. serve files of the user's workspace via HTTP
|
||||||
//
|
//
|
||||||
// Note: user [playground] is a reserved mock user
|
// Note: user [playground] is a reserved mock user
|
||||||
func addUser(username, password, email string) string {
|
func addUser(userId, userName, userAvatar string) string {
|
||||||
if !conf.Wide.AllowRegister {
|
if !conf.Wide.AllowRegister {
|
||||||
return notAllowRegister
|
return notAllowRegister
|
||||||
}
|
}
|
||||||
|
|
||||||
if "playground" == username {
|
if "playground" == userId {
|
||||||
return userExists
|
return userExists
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,32 +252,26 @@ func addUser(username, password, email string) string {
|
||||||
defer addUserMutex.Unlock()
|
defer addUserMutex.Unlock()
|
||||||
|
|
||||||
for _, user := range conf.Users {
|
for _, user := range conf.Users {
|
||||||
if strings.ToLower(user.Name) == strings.ToLower(username) {
|
if strings.ToLower(user.Id) == strings.ToLower(userId) {
|
||||||
return userExists
|
return userExists
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.ToLower(user.Email) == strings.ToLower(email) {
|
|
||||||
return emailExists
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
workspace := filepath.Join(conf.Wide.UsersWorkspaces, username)
|
workspace := filepath.Join(conf.Wide.UsersWorkspaces, userId)
|
||||||
|
newUser := conf.NewUser(userId, userName, userAvatar, workspace)
|
||||||
newUser := conf.NewUser(username, password, email, workspace)
|
|
||||||
conf.Users = append(conf.Users, newUser)
|
conf.Users = append(conf.Users, newUser)
|
||||||
|
|
||||||
if !newUser.Save() {
|
if !newUser.Save() {
|
||||||
return userCreateError
|
return userCreateError
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.CreateWorkspaceDir(workspace)
|
conf.CreateWorkspaceDir(workspace)
|
||||||
helloWorld(workspace)
|
helloWorld(workspace)
|
||||||
conf.UpdateCustomizedConf(username)
|
conf.UpdateCustomizedConf(userId)
|
||||||
|
|
||||||
http.Handle("/workspace/"+username+"/",
|
http.Handle("/workspace/"+userId+"/",
|
||||||
http.StripPrefix("/workspace/"+username+"/", http.FileServer(http.Dir(newUser.WorkspacePath()))))
|
http.StripPrefix("/workspace/"+userId+"/", http.FileServer(http.Dir(newUser.WorkspacePath()))))
|
||||||
|
|
||||||
logger.Infof("Created a user [%s]", username)
|
logger.Infof("Created a user [%s]", userId)
|
||||||
|
|
||||||
return userCreated
|
return userCreated
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
This directory is used to hold user _admin_ customized style file `style.css`, it will be generated when wide startup automatically.
|
|
|
@ -29,16 +29,16 @@ var retLogger = log.NewLogger(os.Stdout)
|
||||||
// Result.
|
// Result.
|
||||||
type Result struct {
|
type Result struct {
|
||||||
Succ bool `json:"succ"` // successful or not
|
Succ bool `json:"succ"` // successful or not
|
||||||
Code string `json:"code"` // return code
|
Code int `json:"code"` // return code
|
||||||
Msg string `json:"msg"` // message
|
Msg string `json:"msg"` // message
|
||||||
Data interface{} `json:"data"` // data object
|
Data interface{} `json:"data"` // data object
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewResult creates a result with Succ=true, Code="0", Msg="", Data=nil.
|
// NewResult creates a result with Succ=true, Code=0, Msg="", Data=nil.
|
||||||
func NewResult() *Result {
|
func NewResult() *Result {
|
||||||
return &Result{
|
return &Result{
|
||||||
Succ: true,
|
Succ: true,
|
||||||
Code: "0",
|
Code: 0,
|
||||||
Msg: "",
|
Msg: "",
|
||||||
Data: nil,
|
Data: nil,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue