diff --git a/.gitignore b/.gitignore
index 3e433b3a..7681c884 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,6 @@
/wide.exe
/wide
-/static/user/admin/style.css
-
/header
/header.exe
diff --git a/conf/user.go b/conf/user.go
index f54d478c..cdcf89eb 100644
--- a/conf/user.go
+++ b/conf/user.go
@@ -15,9 +15,6 @@
package conf
import (
- "crypto/md5"
- "crypto/sha1"
- "encoding/hex"
"encoding/json"
"io/ioutil"
"os"
@@ -25,8 +22,6 @@ import (
"regexp"
"strings"
"time"
-
- "github.com/b3log/wide/util"
)
// Panel represents a UI panel.
@@ -52,11 +47,9 @@ type LatestSessionContent struct {
// User configuration.
type User struct {
+ Id string
Name string
- Password string
- Salt string
- Email string
- Gravatar string // see http://gravatar.com
+ Avatar string
Workspace string // the GOPATH of this user (maybe contain several paths splitted by os.PathListSeparator)
Locale string
GoFormat string
@@ -83,27 +76,6 @@ type editor struct {
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.
func (u *User) Save() bool {
bytes, err := json.MarshalIndent(u, "", " ")
@@ -115,12 +87,12 @@ func (u *User) Save() bool {
}
if "" == string(bytes) {
- logger.Error("Truncated user [" + u.Name + "]")
+ logger.Error("Truncated user [" + u.Id + "]")
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)
return false
@@ -129,6 +101,20 @@ func (u *User) Save() bool {
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.
//
// 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 {
for _, user := range Users {
if strings.HasPrefix(path, user.WorkspacePath()) {
- return user.Name
+ return user.Id
}
}
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))
-}
diff --git a/conf/users/admin.json b/conf/users/admin.json
deleted file mode 100644
index 99e0f79e..00000000
--- a/conf/users/admin.json
+++ /dev/null
@@ -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
- }
- }
- }
-}
\ No newline at end of file
diff --git a/conf/wide.go b/conf/wide.go
index 6b89d7ee..88d33cdf 100644
--- a/conf/wide.go
+++ b/conf/wide.go
@@ -42,6 +42,8 @@ const (
WideVersion = "1.5.3"
// CodeMirrorVer holds the current editor version.
CodeMirrorVer = "5.1"
+ // UserAgent represents HTTP client user agent.
+ UserAgent = "Wide/" + WideVersion + "; +https://github.com/b3log/wide"
HelloWorld = `package main
@@ -70,7 +72,7 @@ type conf struct {
Locale string // default locale
Playground string // playground 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
Autocomplete bool // default autocomplete
}
@@ -335,10 +337,10 @@ func checkEnv() {
}
}
-// GetUserWorkspace gets workspace path with the specified username, returns "" if not found.
-func GetUserWorkspace(username string) string {
+// GetUserWorkspace gets workspace path with the specified user id, returns "" if not found.
+func GetUserWorkspace(userId string) string {
for _, user := range Users {
- if user.Name == username {
+ if user.Id == userId {
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".
-func GetGoFmt(username string) string {
+func GetGoFmt(userId string) string {
for _, user := range Users {
- if user.Name == username {
+ if user.Id == userId {
switch user.GoFormat {
case "gofmt":
return "gofmt"
@@ -365,15 +367,14 @@ func GetGoFmt(username string) string {
return "gofmt"
}
-// GetUser gets configuration of the user specified by the given username, returns nil if not found.
-func GetUser(username string) *User {
- if "playground" == username { // reserved user for Playground
- // mock it
- return NewUser("playground", "", "", "")
+// GetUser gets configuration of the user specified by the given user id, returns nil if not found.
+func GetUser(id string) *User {
+ if "playground" == id { // reserved user for Playground
+ return NewUser("playground", "playground", "", "")
}
for _, user := range Users {
- if user.Name == username {
+ if user.Id == id {
return user
}
}
@@ -384,17 +385,17 @@ func GetUser(username string) *User {
// initCustomizedConfs initializes the user customized configurations.
func initCustomizedConfs() {
for _, user := range Users {
- UpdateCustomizedConf(user.Name)
+ UpdateCustomizedConf(user.Id)
}
}
// UpdateCustomizedConf creates (if not exists) or updates user customized configuration files.
//
// 1. /static/user/{username}/style.css
-func UpdateCustomizedConf(username string) {
+func UpdateCustomizedConf(userId string) {
var u *User
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
}
}
@@ -413,7 +414,7 @@ func UpdateCustomizedConf(username string) {
}
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 {
logger.Error(err)
diff --git a/editor/editors.go b/editor/editors.go
index 74ebd5aa..0a0dcd89 100644
--- a/editor/editors.go
+++ b/editor/editors.go
@@ -117,7 +117,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := session.Values["username"].(string)
+ uid := session.Values["uid"].(string)
path := args["path"].(string)
@@ -147,7 +147,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
logger.Tracef("offset: %d", offset)
- userWorkspace := conf.GetUserWorkspace(username)
+ userWorkspace := conf.GetUserWorkspace(uid)
workspaces := filepath.SplitList(userWorkspace)
libPath := ""
for _, workspace := range workspaces {
@@ -183,7 +183,7 @@ func GetExprInfoHandler(w http.ResponseWriter, r *http.Request) {
defer util.RetResult(w, r, result)
session, _ := session.HTTPSession.Get(r, "wide-session")
- username := session.Values["username"].(string)
+ uid := session.Values["uid"].(string)
var args map[string]interface{}
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.Dir = curDir
- setCmdEnv(cmd, username)
+ setCmdEnv(cmd, uid)
output, err := cmd.CombinedOutput()
if nil != err {
@@ -259,7 +259,7 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := session.Values["username"].(string)
+ uid := session.Values["uid"].(string)
var args map[string]interface{}
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.Dir = curDir
- setCmdEnv(cmd, username)
+ setCmdEnv(cmd, uid)
output, err := cmd.CombinedOutput()
if nil != err {
@@ -347,7 +347,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := session.Values["username"].(string)
+ uid := session.Values["uid"].(string)
var args map[string]interface{}
@@ -392,7 +392,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) {
cmd := exec.Command(ideStub, argv...)
cmd.Dir = curDir
- setCmdEnv(cmd, username)
+ setCmdEnv(cmd, uid)
output, err := cmd.CombinedOutput()
if nil != err {
@@ -453,8 +453,8 @@ func getCursorOffset(code string, line, ch int) (offset int) {
return offset
}
-func setCmdEnv(cmd *exec.Cmd, username string) {
- userWorkspace := conf.GetUserWorkspace(username)
+func setCmdEnv(cmd *exec.Cmd, userId string) {
+ userWorkspace := conf.GetUserWorkspace(userId)
cmd.Env = append(cmd.Env,
"GOPATH="+userWorkspace,
diff --git a/file/files.go b/file/files.go
index 64a0738b..06b5c5cc 100644
--- a/file/files.go
+++ b/file/files.go
@@ -80,12 +80,12 @@ func GetFilesHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
result := util.NewResult()
defer util.RetGzResult(w, r, result)
- userWorkspace := conf.GetUserWorkspace(username)
+ userWorkspace := conf.GetUserWorkspace(uid)
workspaces := filepath.SplitList(userWorkspace)
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
}
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
r.ParseForm()
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)
return
@@ -162,7 +162,7 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
result := util.NewResult()
defer util.RetResult(w, r, result)
@@ -178,7 +178,7 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
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)
return
@@ -212,7 +212,7 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
return
}
- user := conf.GetUser(username)
+ user := conf.GetUser(uid)
data["path"] = "/workspace/" + user.Name + "/" + strings.Replace(path, user.WorkspacePath(), "", 1)
@@ -238,7 +238,7 @@ func SaveFileHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
result := util.NewResult()
defer util.RetResult(w, r, result)
@@ -255,7 +255,7 @@ func SaveFileHandler(w http.ResponseWriter, r *http.Request) {
filePath := args["file"].(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)
return
@@ -294,7 +294,7 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
result := util.NewResult()
defer util.RetResult(w, r, result)
@@ -310,7 +310,7 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
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)
return
@@ -331,9 +331,9 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
}
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 {
- 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
}
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
result := util.NewResult()
defer util.RetResult(w, r, result)
@@ -362,7 +362,7 @@ func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
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)
return
@@ -381,7 +381,7 @@ func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
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.
@@ -392,7 +392,7 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
result := util.NewResult()
defer util.RetResult(w, r, result)
@@ -408,14 +408,14 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
oldPath := args["oldPath"].(string)
if util.Go.IsAPI(oldPath) ||
- !session.CanAccess(username, oldPath) {
+ !session.CanAccess(uid, oldPath) {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
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)
return
@@ -434,7 +434,7 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
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.
@@ -457,7 +457,7 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
result := util.NewResult()
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
- if !util.Go.IsAPI(path) && !session.CanAccess(username, path) {
+ if !util.Go.IsAPI(path) && !session.CanAccess(uid, path) {
http.Error(w, "Forbidden", http.StatusForbidden)
return
@@ -479,7 +479,7 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
name := args["name"].(string)
- userWorkspace := conf.GetUserWorkspace(username)
+ userWorkspace := conf.GetUserWorkspace(uid)
workspaces := filepath.SplitList(userWorkspace)
if "" != path && !util.File.IsDir(path) {
@@ -536,7 +536,7 @@ func SearchTextHandler(w http.ResponseWriter, r *http.Request) {
dir := args["dir"].(string)
if "" == dir {
- userWorkspace := conf.GetUserWorkspace(wSession.Username)
+ userWorkspace := conf.GetUserWorkspace(wSession.UserId)
workspaces := filepath.SplitList(userWorkspace)
dir = workspaces[0]
}
diff --git a/go.mod b/go.mod
index ebe4db59..7fb6aa70 100644
--- a/go.mod
+++ b/go.mod
@@ -3,12 +3,19 @@ module github.com/b3log/wide
go 1.12
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/gorilla/context v0.0.0-20141217160251-215affda49ad // indirect
github.com/gorilla/securecookie v0.0.0-20150327155805-8e98dd730fc4 // indirect
github.com/gorilla/sessions v0.0.0-20150417174705-f61c3ec2cf65
github.com/gorilla/websocket v0.0.0-20150530030352-a3ec486e6a7a
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/text v0.3.2
)
diff --git a/go.sum b/go.sum
index 65084268..d104a272 100644
--- a/go.sum
+++ b/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/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/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
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/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/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/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/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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
diff --git a/main.go b/main.go
index 8f0332ff..f0bb7aa2 100644
--- a/main.go
+++ b/main.go
@@ -158,9 +158,7 @@ func main() {
http.HandleFunc(conf.Wide.Context+"/notification/ws", handlerWrapper(notification.WSHandler))
// user
- http.HandleFunc(conf.Wide.Context+"/login", handlerWrapper(session.LoginHandler))
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))
// playground
@@ -197,8 +195,8 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
- if "playground" == username { // reserved user for Playground
+ uid := httpSession.Values["uid"].(string)
+ if "playground" == uid { // reserved user for Playground
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound)
return
@@ -210,9 +208,9 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
}
httpSession.Save(r, w)
- user := conf.GetUser(username)
+ user := conf.GetUser(uid)
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)
@@ -221,14 +219,14 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
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,
- "username": username, "sid": session.WideSessions.GenId(), "latestSessionContent": user.LatestSessionContent,
+ "uid": uid, "sid": session.WideSessions.GenId(), "latestSessionContent": user.LatestSessionContent,
"pathSeparator": conf.PathSeparator, "codeMirrorVer": conf.CodeMirrorVer,
"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")
if nil != err {
@@ -279,9 +277,9 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
}
httpSession.Save(r, w)
- username := httpSession.Values["username"].(string)
- locale := conf.GetUser(username).Locale
- userWorkspace := conf.GetUserWorkspace(username)
+ uid := httpSession.Values["uid"].(string)
+ locale := conf.GetUser(uid).Locale
+ userWorkspace := conf.GetUserWorkspace(uid)
sid := r.URL.Query()["sid"][0]
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,
- "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")
@@ -319,8 +317,8 @@ func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) {
}
httpSession.Save(r, w)
- username := httpSession.Values["username"].(string)
- locale := conf.GetUser(username).Locale
+ uid := httpSession.Values["uid"].(string)
+ locale := conf.GetUser(uid).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)
- username := httpSession.Values["username"].(string)
- locale := conf.GetUser(username).Locale
+ uid := httpSession.Values["uid"].(string)
+ locale := conf.GetUser(uid).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()}
diff --git a/notification/notifications.go b/notification/notifications.go
index 527509ee..d350cb1d 100644
--- a/notification/notifications.go
+++ b/notification/notifications.go
@@ -63,8 +63,8 @@ func event2Notification(e *event.Event) {
}
httpSession, _ := session.HTTPSession.Get(wsChannel.Request, "wide-session")
- username := httpSession.Values["username"].(string)
- locale := conf.GetUser(username).Locale
+ uid := httpSession.Values["uid"].(string)
+ locale := conf.GetUser(uid).Locale
var notification *Notification
diff --git a/output/build.go b/output/build.go
index 4475f588..442f20fa 100644
--- a/output/build.go
+++ b/output/build.go
@@ -44,8 +44,8 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
- user := conf.GetUser(username)
+ uid := httpSession.Values["uid"].(string)
+ user := conf.GetUser(uid)
locale := user.Locale
var args map[string]interface{}
@@ -61,7 +61,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
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)
return
@@ -101,7 +101,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
cmd := exec.Command("go", goBuildArgs...)
cmd.Dir = curDir
- setCmdEnv(cmd, username)
+ setCmdEnv(cmd, uid)
executable := filepath.Base(curDir) + suffix
executable = filepath.Join(curDir, executable)
diff --git a/output/cross.go b/output/cross.go
index 07cf7cda..1db55b9b 100644
--- a/output/cross.go
+++ b/output/cross.go
@@ -43,8 +43,8 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
- locale := conf.GetUser(username).Locale
+ uid := httpSession.Values["uid"].(string)
+ locale := conf.GetUser(uid).Locale
var args map[string]interface{}
@@ -58,7 +58,7 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
sid := args["sid"].(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)
return
@@ -75,7 +75,7 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
suffix = ".exe"
}
- user := conf.GetUser(username)
+ user := conf.GetUser(uid)
goBuildArgs := []string{}
goBuildArgs = append(goBuildArgs, "build")
goBuildArgs = append(goBuildArgs, user.BuildArgs(goos)...)
@@ -83,7 +83,7 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
cmd := exec.Command("go", goBuildArgs...)
cmd.Dir = curDir
- setCmdEnv(cmd, username)
+ setCmdEnv(cmd, uid)
for i, env := range cmd.Env {
if strings.HasPrefix(env, "GOOS=") {
diff --git a/output/get.go b/output/get.go
index 0aadea3a..5585e2f7 100644
--- a/output/get.go
+++ b/output/get.go
@@ -41,8 +41,8 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
- locale := conf.GetUser(username).Locale
+ uid := httpSession.Values["uid"].(string)
+ locale := conf.GetUser(uid).Locale
var args map[string]interface{}
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.Dir = curDir
- setCmdEnv(cmd, username)
+ setCmdEnv(cmd, uid)
stdout, err := cmd.StdoutPipe()
if nil != err {
@@ -114,7 +114,7 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) {
defer util.Recover()
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["cmd"] = "go get"
@@ -123,11 +123,11 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) {
buf, _ := ioutil.ReadAll(reader)
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"] = "" + i18n.Get(locale, "get-error").(string) + "\n" + string(buf)
} 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"] = "" + i18n.Get(locale, "get-succ").(string) + "\n"
}
diff --git a/output/install.go b/output/install.go
index 0a2db712..c7894272 100644
--- a/output/install.go
+++ b/output/install.go
@@ -43,8 +43,8 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
- locale := conf.GetUser(username).Locale
+ uid := httpSession.Values["uid"].(string)
+ locale := conf.GetUser(uid).Locale
var args map[string]interface{}
@@ -63,7 +63,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
cmd := exec.Command("go", "install")
cmd.Dir = curDir
- setCmdEnv(cmd, username)
+ setCmdEnv(cmd, uid)
logger.Debugf("go install %s", curDir)
@@ -119,7 +119,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
defer util.Recover()
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
buf, _ := ioutil.ReadAll(reader)
@@ -183,7 +183,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
}
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]
err := wsChannel.WriteJSON(&channelRet)
diff --git a/output/outputs.go b/output/outputs.go
index 6fcb5933..e5c9a1d3 100644
--- a/output/outputs.go
+++ b/output/outputs.go
@@ -104,8 +104,8 @@ func parsePath(curDir, outputLine string) string {
return tagStart + text + tagEnd + msgPart
}
-func setCmdEnv(cmd *exec.Cmd, username string) {
- userWorkspace := conf.GetUserWorkspace(username)
+func setCmdEnv(cmd *exec.Cmd, uid string) {
+ userWorkspace := conf.GetUserWorkspace(uid)
cache, err := os.UserCacheDir()
if nil != err {
logger.Warnf("Get user cache dir failed [" + err.Error() + "]")
diff --git a/output/processes.go b/output/processes.go
index 552eff85..6926c902 100644
--- a/output/processes.go
+++ b/output/processes.go
@@ -86,7 +86,7 @@ func (procs *procs) Kill(wSession *session.WideSession, pid int) {
for i, p := range userProcesses {
if p.Pid == pid {
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 {
var newProcesses []*os.Process
@@ -96,7 +96,7 @@ func (procs *procs) Kill(wSession *session.WideSession, pid int) {
// bind process with wide session
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
diff --git a/output/run.go b/output/run.go
index 036a8442..ca4194e9 100644
--- a/output/run.go
+++ b/output/run.go
@@ -106,7 +106,7 @@ func RunHandler(w http.ResponseWriter, r *http.Request) {
go func(runningId int) {
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() {
defer util.Recover()
diff --git a/output/test.go b/output/test.go
index e57aab13..3b30de62 100644
--- a/output/test.go
+++ b/output/test.go
@@ -41,8 +41,8 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
- locale := conf.GetUser(username).Locale
+ uid := httpSession.Values["uid"].(string)
+ locale := conf.GetUser(uid).Locale
var args map[string]interface{}
@@ -61,7 +61,7 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
cmd := exec.Command("go", "test", "-v")
cmd.Dir = curDir
- setCmdEnv(cmd, username)
+ setCmdEnv(cmd, uid)
stdout, err := cmd.StdoutPipe()
if nil != err {
@@ -114,7 +114,7 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
go func(runningId int) {
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["cmd"] = "go test"
@@ -126,11 +126,11 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
cmd.Wait()
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"] = "" + i18n.Get(locale, "test-error").(string) + "\n" + string(buf)
} 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"] = "" + i18n.Get(locale, "test-succ").(string) + "\n" + string(buf)
}
diff --git a/output/vet.go b/output/vet.go
index 750eaac3..e199cac8 100644
--- a/output/vet.go
+++ b/output/vet.go
@@ -41,8 +41,8 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
return
}
- username := httpSession.Values["username"].(string)
- locale := conf.GetUser(username).Locale
+ uid := httpSession.Values["uid"].(string)
+ locale := conf.GetUser(uid).Locale
var args map[string]interface{}
@@ -61,7 +61,7 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
cmd := exec.Command("go", "vet", ".")
cmd.Dir = curDir
- setCmdEnv(cmd, username)
+ setCmdEnv(cmd, uid)
stdout, err := cmd.StdoutPipe()
if nil != err {
@@ -114,7 +114,7 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
go func(runningId int) {
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["cmd"] = "go vet"
@@ -126,11 +126,11 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
cmd.Wait()
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"] = "" + i18n.Get(locale, "vet-error").(string) + "\n" + string(buf)
} 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"] = "" + i18n.Get(locale, "vet-succ").(string) + "\n" + string(buf)
}
diff --git a/playground/playgrounds.go b/playground/playgrounds.go
index ef63a202..515ae4f3 100644
--- a/playground/playgrounds.go
+++ b/playground/playgrounds.go
@@ -52,7 +52,7 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
}
httpSession.Save(r, w)
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
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(),
"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")
diff --git a/playground/run.go b/playground/run.go
index ab5ae544..d9b630e6 100644
--- a/playground/run.go
+++ b/playground/run.go
@@ -108,7 +108,7 @@ func RunHandler(w http.ResponseWriter, r *http.Request) {
go func(runningId int) {
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() {
defer util.Recover()
diff --git a/session/oauthctl.go b/session/oauthctl.go
new file mode 100644
index 00000000..9c43500d
--- /dev/null
+++ b/session/oauthctl.go
@@ -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{})
+}
diff --git a/session/sessions.go b/session/sessions.go
index a83f5f53..1813d052 100644
--- a/session/sessions.go
+++ b/session/sessions.go
@@ -46,7 +46,7 @@ import (
const (
sessionStateActive = iota
- sessionStateClosed // (not used so far)
+ sessionStateClosed // (not used so far)
)
// Logger.
@@ -75,7 +75,7 @@ var HTTPSession = sessions.NewCookieStore([]byte("BEYOND"))
// WideSession represents a session associated with a browser tab.
type WideSession struct {
ID string // id
- Username string // username
+ UserId string // user id
HTTPSession *sessions.Session // HTTP session related
Processes []*os.Process // process set
EventQueue *event.UserEventQueue // event queue
@@ -111,7 +111,7 @@ func FixedTimeRelease() {
for _, s := range WideSessions {
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)
}
@@ -139,7 +139,7 @@ func FixedTimeReport() {
go func() {
defer util.Recover()
- for _ = range time.Tick(10 * time.Minute) {
+ for _ = range time.Tick(10*time.Minute) {
users := userReports{}
processSum := 0
@@ -147,7 +147,7 @@ func FixedTimeReport() {
processCnt := len(s.Processes)
processSum += processCnt
- if report, exists := contains(users, s.Username); exists {
+ if report, exists := contains(users, s.UserId); exists {
if s.Updated.After(report.updated) {
report.updated = s.Updated
}
@@ -155,7 +155,7 @@ func FixedTimeReport() {
report.sessionCnt++
report.processCnt += processCnt
} 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)
- 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))
@@ -263,7 +263,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) {
for {
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
}
@@ -307,7 +307,7 @@ func SaveContentHandler(w http.ResponseWriter, r *http.Request) {
wSession.Content = args.LatestSessionContent
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
user.LatestSessionContent = wSession.Content
@@ -376,9 +376,9 @@ func (sessions *wSessions) Remove(sid string) {
// kill processes
for _, p := range s.Processes {
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 {
- 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
for _, ses := range *sessions {
- if ses.Username == s.Username {
+ if ses.UserId == s.UserId {
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
}
@@ -423,14 +423,14 @@ func (sessions *wSessions) Remove(sid string) {
}
// GetByUsername gets wide sessions.
-func (sessions *wSessions) GetByUsername(username string) []*WideSession {
+func (sessions *wSessions) GetByUserId(userId string) []*WideSession {
mutex.Lock()
defer mutex.Unlock()
ret := []*WideSession{}
for _, s := range *sessions {
- if s.Username == username {
+ if s.UserId == userId {
ret = append(ret, s)
}
}
@@ -443,12 +443,12 @@ func (sessions *wSessions) new(httpSession *sessions.Session, sid string) *WideS
mutex.Lock()
defer mutex.Unlock()
- username := httpSession.Values["username"].(string)
+ uid := httpSession.Values["uid"].(string)
now := time.Now()
ret := &WideSession{
ID: sid,
- Username: username,
+ UserId: uid,
HTTPSession: httpSession,
EventQueue: nil,
State: sessionStateActive,
@@ -459,7 +459,7 @@ func (sessions *wSessions) new(httpSession *sessions.Session, sid string) *WideS
*sessions = append(*sessions, ret)
- if "playground" == username {
+ if "playground" == uid {
return ret
}
@@ -526,7 +526,7 @@ func (sessions *wSessions) new(httpSession *sessions.Session, sid string) *WideS
go func() {
defer util.Recover()
- workspaces := filepath.SplitList(conf.GetUserWorkspace(username))
+ workspaces := filepath.SplitList(conf.GetUserWorkspace(uid))
for _, workspace := range workspaces {
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() {
diff --git a/session/users.go b/session/users.go
index ac6c572a..6f602556 100644
--- a/session/users.go
+++ b/session/users.go
@@ -15,15 +15,11 @@
package session
import (
- "crypto/md5"
- "encoding/hex"
"encoding/json"
- "math/rand"
"net/http"
"os"
"path/filepath"
"runtime"
- "strconv"
"strings"
"sync"
"text/template"
@@ -38,7 +34,6 @@ const (
// TODO: i18n
userExists = "user exists"
- emailExists = "email exists"
userCreated = "user created"
userCreateError = "user create error"
notAllowRegister = "not allow register"
@@ -63,8 +58,8 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
}
httpSession.Save(r, w)
- username := httpSession.Values["username"].(string)
- user := conf.GetUser(username)
+ uid := httpSession.Values["uid"].(string)
+ user := conf.GetUser(uid)
if "GET" == r.Method {
tmpLinux := user.GoBuildArgsForLinux
@@ -116,8 +111,6 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
Keymap string
Workspace string
Username string
- Password string
- Email string
Locale string
Theme string
EditorFontFamily string
@@ -143,14 +136,6 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
user.Keymap = args.Keymap
// XXX: disallow change workspace at present
// 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.Theme = args.Theme
@@ -160,7 +145,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
user.Editor.Theme = args.EditorTheme
user.Editor.TabSize = args.EditorTabSize
- conf.UpdateCustomizedConf(username)
+ conf.UpdateCustomizedConf(uid)
now := time.Now().UnixNano()
user.Lived = now
@@ -169,66 +154,6 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
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).
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult()
@@ -240,66 +165,6 @@ func LogoutHandler(w http.ResponseWriter, r *http.Request) {
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).
//
// 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.
-func CanAccess(username, path string) bool {
+// CanAccess determines whether the user specified by the given user id can access the specified path.
+func CanAccess(userId, path string) bool {
path = filepath.FromSlash(path)
- userWorkspace := conf.GetUserWorkspace(username)
+ userWorkspace := conf.GetUserWorkspace(userId)
workspaces := filepath.SplitList(userWorkspace)
for _, workspace := range workspaces {
@@ -342,20 +207,20 @@ func SaveOnlineUsers() {
func getOnlineUsers() []*conf.User {
ret := []*conf.User{}
- usernames := map[string]string{} // distinct username
+ uids := map[string]string{} // distinct uid
for _, s := range WideSessions {
- usernames[s.Username] = s.Username
+ uids[s.UserId] = s.UserId
}
- for _, username := range usernames {
- u := conf.GetUser(username)
+ for _, uid := range uids {
+ 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
}
if nil == u {
- logger.Warnf("Not found user [%s]", username)
+ logger.Warnf("Not found user [%s]", uid)
continue
}
@@ -366,7 +231,7 @@ func getOnlineUsers() []*conf.User {
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
// 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
//
// 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 {
return notAllowRegister
}
- if "playground" == username {
+ if "playground" == userId {
return userExists
}
@@ -387,32 +252,26 @@ func addUser(username, password, email string) string {
defer addUserMutex.Unlock()
for _, user := range conf.Users {
- if strings.ToLower(user.Name) == strings.ToLower(username) {
+ if strings.ToLower(user.Id) == strings.ToLower(userId) {
return userExists
}
-
- if strings.ToLower(user.Email) == strings.ToLower(email) {
- return emailExists
- }
}
- workspace := filepath.Join(conf.Wide.UsersWorkspaces, username)
-
- newUser := conf.NewUser(username, password, email, workspace)
+ workspace := filepath.Join(conf.Wide.UsersWorkspaces, userId)
+ newUser := conf.NewUser(userId, userName, userAvatar, workspace)
conf.Users = append(conf.Users, newUser)
-
if !newUser.Save() {
return userCreateError
}
conf.CreateWorkspaceDir(workspace)
helloWorld(workspace)
- conf.UpdateCustomizedConf(username)
+ conf.UpdateCustomizedConf(userId)
- http.Handle("/workspace/"+username+"/",
- http.StripPrefix("/workspace/"+username+"/", http.FileServer(http.Dir(newUser.WorkspacePath()))))
+ http.Handle("/workspace/"+userId+"/",
+ 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
}
diff --git a/static/user/admin/README.md b/static/user/admin/README.md
deleted file mode 100644
index 592dcdb9..00000000
--- a/static/user/admin/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This directory is used to hold user _admin_ customized style file `style.css`, it will be generated when wide startup automatically.
diff --git a/util/ret.go b/util/ret.go
index f9102aff..735582f1 100644
--- a/util/ret.go
+++ b/util/ret.go
@@ -29,16 +29,16 @@ var retLogger = log.NewLogger(os.Stdout)
// Result.
type Result struct {
Succ bool `json:"succ"` // successful or not
- Code string `json:"code"` // return code
+ Code int `json:"code"` // return code
Msg string `json:"msg"` // message
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 {
return &Result{
Succ: true,
- Code: "0",
+ Code: 0,
Msg: "",
Data: nil,
}