separate users' configurations from wide.json
This commit is contained in:
parent
24c29e176e
commit
3b359d92d8
|
@ -0,0 +1,112 @@
|
|||
// Copyright (c) 2014, B3log
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 conf
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// LatestSessionContent represents the latest session content.
|
||||
type LatestSessionContent struct {
|
||||
FileTree []string // paths of expanding nodes of file tree
|
||||
Files []string // paths of files of opening editor tabs
|
||||
CurrentFile string // path of file of the current focused editor tab
|
||||
}
|
||||
|
||||
// User configuration.
|
||||
type User struct {
|
||||
Name string
|
||||
Password string
|
||||
Email string
|
||||
Gravatar string // see http://gravatar.com
|
||||
Workspace string // the GOPATH of this user
|
||||
Locale string
|
||||
GoFormat string
|
||||
FontFamily string
|
||||
FontSize string
|
||||
Theme string
|
||||
Editor *editor
|
||||
LatestSessionContent *LatestSessionContent
|
||||
}
|
||||
|
||||
// Editor configuration of a user.
|
||||
type editor struct {
|
||||
FontFamily string
|
||||
FontSize string
|
||||
LineHeight string
|
||||
Theme string
|
||||
TabSize string
|
||||
}
|
||||
|
||||
// NewUser creates a user with the specified username, password, email and workspace.
|
||||
func NewUser(username, password, email, workspace string) *User {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(email))
|
||||
gravatar := hex.EncodeToString(hash.Sum(nil))
|
||||
|
||||
return &User{Name: username, Password: password, Email: email, Gravatar: gravatar, Workspace: workspace,
|
||||
Locale: Wide.Locale, GoFormat: "gofmt", FontFamily: "Helvetica", FontSize: "13px", Theme: "default",
|
||||
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, "", " ")
|
||||
|
||||
if nil != err {
|
||||
logger.Error(err)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile("conf/users/"+u.Name+".json", bytes, 0644); nil != err {
|
||||
logger.Error(err)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// GetWorkspace gets workspace path of the user.
|
||||
//
|
||||
// Compared to the use of Wide.Workspace, this function will be processed as follows:
|
||||
// 1. Replace {WD} variable with the actual directory path
|
||||
// 2. Replace ${GOPATH} with enviorment variable GOPATH
|
||||
// 3. Replace "/" with "\\" (Windows)
|
||||
func (u *User) GetWorkspace() string {
|
||||
w := strings.Replace(u.Workspace, "{WD}", Wide.WD, 1)
|
||||
w = strings.Replace(w, "${GOPATH}", os.Getenv("GOPATH"), 1)
|
||||
|
||||
return filepath.FromSlash(w)
|
||||
}
|
||||
|
||||
// GetOwner gets the user the specified path belongs to. Returns "" if not found.
|
||||
func GetOwner(path string) string {
|
||||
for _, user := range Users {
|
||||
if strings.HasPrefix(path, user.GetWorkspace()) {
|
||||
return user.Name
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"Name": "admin",
|
||||
"Password": "admin",
|
||||
"Email": "",
|
||||
"Gravatar": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"Workspace": "${GOPATH}",
|
||||
"Locale": "en_US",
|
||||
"GoFormat": "gofmt",
|
||||
"FontFamily": "Helvetica",
|
||||
"FontSize": "13px",
|
||||
"Theme": "black",
|
||||
"Editor": {
|
||||
"FontFamily": "Consolas, 'Courier New', monospace",
|
||||
"FontSize": "13px",
|
||||
"LineHeight": "17px",
|
||||
"Theme": "wide",
|
||||
"TabSize": "4"
|
||||
},
|
||||
"LatestSessionContent": {
|
||||
"FileTree": [
|
||||
"D:\\GoGoGo\\src"
|
||||
],
|
||||
"Files": [],
|
||||
"CurrentFile": ""
|
||||
}
|
||||
}
|
235
conf/wide.go
235
conf/wide.go
|
@ -12,13 +12,10 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package conf includes configurations related manipulations, all configurations (including user configurations) are
|
||||
// stored in wide.json.
|
||||
// Package conf includes configurations related manipulations.
|
||||
package conf
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -40,108 +37,102 @@ const (
|
|||
PathSeparator = string(os.PathSeparator)
|
||||
// PathListSeparator holds the OS-specific path list separator.
|
||||
PathListSeparator = string(os.PathListSeparator)
|
||||
)
|
||||
|
||||
const (
|
||||
// WideVersion holds the current wide version.
|
||||
WideVersion = "1.1.0"
|
||||
// CodeMirrorVer holds the current editor version.
|
||||
CodeMirrorVer = "4.8"
|
||||
)
|
||||
|
||||
// LatestSessionContent represents the latest session content.
|
||||
type LatestSessionContent struct {
|
||||
FileTree []string // paths of expanding nodes of file tree
|
||||
Files []string // paths of files of opening editor tabs
|
||||
CurrentFile string // path of file of the current focused editor tab
|
||||
}
|
||||
|
||||
// User configuration.
|
||||
type User struct {
|
||||
Name string
|
||||
Password string
|
||||
Email string
|
||||
Gravatar string // see http://gravatar.com
|
||||
Workspace string // the GOPATH of this user
|
||||
Locale string
|
||||
GoFormat string
|
||||
FontFamily string
|
||||
FontSize string
|
||||
Theme string
|
||||
Editor *Editor
|
||||
LatestSessionContent *LatestSessionContent
|
||||
}
|
||||
|
||||
// Editor configuration of a user.
|
||||
type Editor struct {
|
||||
FontFamily string
|
||||
FontSize string
|
||||
LineHeight string
|
||||
Theme string
|
||||
TabSize string
|
||||
}
|
||||
|
||||
// Configuration.
|
||||
type conf struct {
|
||||
IP string // server ip, ${ip}
|
||||
Port string // server port
|
||||
Context string // server context
|
||||
Server string // server host and port ({IP}:{Port})
|
||||
StaticServer string // static resources server scheme, host and port (http://{IP}:{Port})
|
||||
LogLevel string // logging level
|
||||
Channel string // channel (ws://{IP}:{Port})
|
||||
HTTPSessionMaxAge int // HTTP session max age (in seciond)
|
||||
StaticResourceVersion string // version of static resources
|
||||
MaxProcs int // Go max procs
|
||||
RuntimeMode string // runtime mode (dev/prod)
|
||||
WD string // current working direcitory, ${pwd}
|
||||
Locale string // default locale
|
||||
Users []*User // configurations of users
|
||||
IP string // server ip, ${ip}
|
||||
Port string // server port
|
||||
Context string // server context
|
||||
Server string // server host and port ({IP}:{Port})
|
||||
StaticServer string // static resources server scheme, host and port (http://{IP}:{Port})
|
||||
LogLevel string // logging level: trace/debug/info/warn/error
|
||||
Channel string // channel (ws://{IP}:{Port})
|
||||
HTTPSessionMaxAge int // HTTP session max age (in seciond)
|
||||
StaticResourceVersion string // version of static resources
|
||||
MaxProcs int // Go max procs
|
||||
RuntimeMode string // runtime mode (dev/prod)
|
||||
WD string // current working direcitory, ${pwd}
|
||||
Locale string // default locale
|
||||
}
|
||||
|
||||
// Configuration variable.
|
||||
var Wide conf
|
||||
|
||||
// A raw copy of configuration variable.
|
||||
//
|
||||
// Save function will use this variable to persist.
|
||||
var rawWide conf
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
|
||||
// Wide configurations.
|
||||
var Wide *conf
|
||||
|
||||
// configurations of users.
|
||||
var Users []*User
|
||||
|
||||
// Indicates whether runs via Docker.
|
||||
var Docker bool
|
||||
|
||||
// NewUser creates a user with the specified username, password, email and workspace.
|
||||
func NewUser(username, password, email, workspace string) *User {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(email))
|
||||
gravatar := hex.EncodeToString(hash.Sum(nil))
|
||||
|
||||
return &User{Name: username, Password: password, Email: email, Gravatar: gravatar, Workspace: workspace,
|
||||
Locale: Wide.Locale, GoFormat: "gofmt", FontFamily: "Helvetica", FontSize: "13px", Theme: "default",
|
||||
Editor: &Editor{FontFamily: "Consolas, 'Courier New', monospace", FontSize: "inherit", LineHeight: "17px",
|
||||
Theme: "wide", TabSize: "4"}}
|
||||
// Load loads the Wide configurations from wide.json and users' configurations from users/{username}.json.
|
||||
func Load(confPath, confIP, confPort, confServer, confLogLevel, confStaticServer, confContext, confChannel string, confDocker bool) {
|
||||
initWide(confPath, confIP, confPort, confServer, confLogLevel, confStaticServer, confContext, confChannel, confDocker)
|
||||
initUsers()
|
||||
}
|
||||
|
||||
// Load loads the configurations from wide.json.
|
||||
func Load(confPath, confIP, confPort, confServer, confLogLevel, confStaticServer, confContext, confChannel string,
|
||||
confDocker bool) {
|
||||
bytes, _ := ioutil.ReadFile(confPath)
|
||||
func initUsers() {
|
||||
f, err := os.Open("conf/users")
|
||||
if nil != err {
|
||||
logger.Error(err)
|
||||
|
||||
err := json.Unmarshal(bytes, &Wide)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
names, err := f.Readdirnames(-1)
|
||||
if nil != err {
|
||||
logger.Error(err)
|
||||
|
||||
os.Exit(-1)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
for _, name := range names {
|
||||
user := &User{}
|
||||
|
||||
bytes, _ := ioutil.ReadFile("conf/users/" + name)
|
||||
|
||||
err := json.Unmarshal(bytes, user)
|
||||
if err != nil {
|
||||
logger.Errorf("Parses [%s] error: %v", name, err)
|
||||
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
Users = append(Users, user)
|
||||
}
|
||||
|
||||
initWorkspaceDirs()
|
||||
initCustomizedConfs()
|
||||
}
|
||||
|
||||
func initWide(confPath, confIP, confPort, confServer, confLogLevel, confStaticServer, confContext, confChannel string, confDocker bool) {
|
||||
bytes, err := ioutil.ReadFile(confPath)
|
||||
if nil != err {
|
||||
logger.Error(err)
|
||||
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
Wide = &conf{}
|
||||
|
||||
err = json.Unmarshal(bytes, Wide)
|
||||
if err != nil {
|
||||
logger.Error("Parses wide.json error: ", err)
|
||||
logger.Error("Parses [wide.json] error: ", err)
|
||||
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
log.SetLevel(Wide.LogLevel)
|
||||
|
||||
// keep the raw content
|
||||
json.Unmarshal(bytes, &rawWide)
|
||||
|
||||
logger.Debug("Conf: \n" + string(bytes))
|
||||
|
||||
// Working Driectory
|
||||
|
@ -204,12 +195,6 @@ func Load(confPath, confIP, confPort, confServer, confLogLevel, confStaticServer
|
|||
|
||||
Wide.Server = strings.Replace(Wide.Server, "{Port}", Wide.Port, 1)
|
||||
Wide.StaticServer = strings.Replace(Wide.StaticServer, "{Port}", Wide.Port, 1)
|
||||
|
||||
// upgrade if need
|
||||
upgrade()
|
||||
|
||||
initWorkspaceDirs()
|
||||
initCustomizedConfs()
|
||||
}
|
||||
|
||||
// FixedTimeCheckEnv checks Wide runtime enviorment periodically (7 minutes).
|
||||
|
@ -261,20 +246,9 @@ func checkEnv() {
|
|||
}
|
||||
}
|
||||
|
||||
// FixedTimeSave saves configurations (wide.json) periodically (1 minute).
|
||||
//
|
||||
// Main goal of this function is to save user session content, for restoring session content while user open Wide next time.
|
||||
func FixedTimeSave() {
|
||||
go func() {
|
||||
for _ = range time.Tick(time.Minute) {
|
||||
Save()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// GetUserWorkspace gets workspace path with the specified username, returns "" if not found.
|
||||
func (c *conf) GetUserWorkspace(username string) string {
|
||||
for _, user := range c.Users {
|
||||
func GetUserWorkspace(username string) string {
|
||||
for _, user := range Users {
|
||||
if user.Name == username {
|
||||
return user.GetWorkspace()
|
||||
}
|
||||
|
@ -284,8 +258,8 @@ func (c *conf) GetUserWorkspace(username string) string {
|
|||
}
|
||||
|
||||
// GetGoFmt gets the path of Go format tool, returns "gofmt" if not found "goimports".
|
||||
func (c *conf) GetGoFmt(username string) string {
|
||||
for _, user := range c.Users {
|
||||
func GetGoFmt(username string) string {
|
||||
for _, user := range Users {
|
||||
if user.Name == username {
|
||||
switch user.GoFormat {
|
||||
case "gofmt":
|
||||
|
@ -302,22 +276,9 @@ func (c *conf) GetGoFmt(username string) string {
|
|||
return "gofmt"
|
||||
}
|
||||
|
||||
// GetWorkspace gets workspace path of the user.
|
||||
//
|
||||
// Compared to the use of Wide.Workspace, this function will be processed as follows:
|
||||
// 1. Replace {WD} variable with the actual directory path
|
||||
// 2. Replace ${GOPATH} with enviorment variable GOPATH
|
||||
// 3. Replace "/" with "\\" (Windows)
|
||||
func (u *User) GetWorkspace() string {
|
||||
w := strings.Replace(u.Workspace, "{WD}", Wide.WD, 1)
|
||||
w = strings.Replace(w, "${GOPATH}", os.Getenv("GOPATH"), 1)
|
||||
|
||||
return filepath.FromSlash(w)
|
||||
}
|
||||
|
||||
// GetUser gets configuration of the user specified by the given username, returns nil if not found.
|
||||
func (*conf) GetUser(username string) *User {
|
||||
for _, user := range Wide.Users {
|
||||
func GetUser(username string) *User {
|
||||
for _, user := range Users {
|
||||
if user.Name == username {
|
||||
return user
|
||||
}
|
||||
|
@ -326,13 +287,10 @@ func (*conf) GetUser(username string) *User {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Save saves Wide configurations.
|
||||
// Save saves Wide and all users' configurations.
|
||||
func Save() bool {
|
||||
// just the Users field are volatile
|
||||
rawWide.Users = Wide.Users
|
||||
|
||||
// format
|
||||
bytes, err := json.MarshalIndent(rawWide, "", " ")
|
||||
// Wide, XXX: does we need to save wide.json?
|
||||
bytes, err := json.MarshalIndent(Wide, "", " ")
|
||||
|
||||
if nil != err {
|
||||
logger.Error(err)
|
||||
|
@ -346,40 +304,17 @@ func Save() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// upgrade upgrades the wide.json.
|
||||
func upgrade() {
|
||||
// Users
|
||||
for _, user := range Wide.Users {
|
||||
if "" == user.Theme {
|
||||
user.Theme = "default" // since 1.1.0
|
||||
}
|
||||
|
||||
if "" == user.Editor.Theme {
|
||||
user.Editor.Theme = "wide" // since 1.1.0
|
||||
}
|
||||
|
||||
if "" == user.Editor.TabSize {
|
||||
user.Editor.TabSize = "4" // since 1.1.0
|
||||
}
|
||||
|
||||
if "" != user.Email && "" == user.Gravatar {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(user.Email))
|
||||
gravatar := hex.EncodeToString(hash.Sum(nil))
|
||||
|
||||
user.Gravatar = gravatar
|
||||
}
|
||||
for _, user := range Users {
|
||||
user.Save()
|
||||
}
|
||||
|
||||
Save()
|
||||
return true
|
||||
}
|
||||
|
||||
// initCustomizedConfs initializes the user customized configurations.
|
||||
func initCustomizedConfs() {
|
||||
for _, user := range Wide.Users {
|
||||
for _, user := range Users {
|
||||
UpdateCustomizedConf(user.Name)
|
||||
}
|
||||
}
|
||||
|
@ -389,7 +324,7 @@ func initCustomizedConfs() {
|
|||
// 1. /static/user/{username}/style.css
|
||||
func UpdateCustomizedConf(username string) {
|
||||
var u *User
|
||||
for _, user := range Wide.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 {
|
||||
u = user
|
||||
}
|
||||
|
@ -438,7 +373,7 @@ func UpdateCustomizedConf(username string) {
|
|||
func initWorkspaceDirs() {
|
||||
paths := []string{}
|
||||
|
||||
for _, user := range Wide.Users {
|
||||
for _, user := range Users {
|
||||
paths = append(paths, filepath.SplitList(user.GetWorkspace())...)
|
||||
}
|
||||
|
||||
|
|
|
@ -11,35 +11,5 @@
|
|||
"MaxProcs": 4,
|
||||
"RuntimeMode": "dev",
|
||||
"WD": "${pwd}",
|
||||
"Locale": "en_US",
|
||||
"Users": [
|
||||
{
|
||||
"Name": "admin",
|
||||
"Password": "admin",
|
||||
"Email": "",
|
||||
"Gravatar": "",
|
||||
"Workspace": "${GOPATH}",
|
||||
"Locale": "en_US",
|
||||
"GoFormat": "gofmt",
|
||||
"FontFamily": "Helvetica",
|
||||
"FontSize": "13px",
|
||||
"Theme": "default",
|
||||
"Editor": {
|
||||
"FontFamily": "Consolas, 'Courier New', monospace",
|
||||
"FontSize": "13px",
|
||||
"LineHeight": "17px",
|
||||
"Theme": "wide",
|
||||
"TabSize": "4"
|
||||
},
|
||||
"LatestSessionContent": {
|
||||
"FileTree": [
|
||||
"D:\\GoGoGo\\src",
|
||||
"D:\\GoGoGo\\src\\demo",
|
||||
"D:\\GoGoGo\\src\\hello"
|
||||
],
|
||||
"Files": [],
|
||||
"CurrentFile": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
"Locale": "en_US"
|
||||
}
|
|
@ -147,7 +147,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// logger.Infof("offset: %d", offset)
|
||||
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(username)
|
||||
userWorkspace := conf.GetUserWorkspace(username)
|
||||
workspaces := filepath.SplitList(userWorkspace)
|
||||
libPath := ""
|
||||
for _, workspace := range workspaces {
|
||||
|
@ -455,7 +455,7 @@ func getCursorOffset(code string, line, ch int) (offset int) {
|
|||
}
|
||||
|
||||
func setCmdEnv(cmd *exec.Cmd, username string) {
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(username)
|
||||
userWorkspace := conf.GetUserWorkspace(username)
|
||||
|
||||
cmd.Env = append(cmd.Env,
|
||||
"GOPATH="+userWorkspace,
|
||||
|
|
|
@ -77,7 +77,7 @@ func GoFmtHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
fmt := conf.Wide.GetGoFmt(username)
|
||||
fmt := conf.GetGoFmt(username)
|
||||
|
||||
argv := []string{filePath}
|
||||
cmd := exec.Command(fmt, argv...)
|
||||
|
|
|
@ -82,7 +82,7 @@ func GetFiles(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
username := session.Values["username"].(string)
|
||||
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(username)
|
||||
userWorkspace := conf.GetUserWorkspace(username)
|
||||
workspaces := filepath.SplitList(userWorkspace)
|
||||
|
||||
root := Node{Name: "root", Path: "", IconSkin: "ico-ztree-dir ", Type: "d", Children: []*Node{}}
|
||||
|
@ -163,14 +163,16 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
data["mode"] = "img"
|
||||
|
||||
user := GetUsre(path)
|
||||
if nil == user {
|
||||
username := conf.GetOwner(path)
|
||||
if "" == username {
|
||||
logger.Warnf("The path [%s] has no owner")
|
||||
data["path"] = ""
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
user := conf.GetUser(username)
|
||||
|
||||
data["path"] = "/workspace/" + user.Name + "/" + strings.Replace(path, user.GetWorkspace(), "", 1)
|
||||
|
||||
return
|
||||
|
@ -356,7 +358,7 @@ func Find(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
username := session.Values["username"].(string)
|
||||
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(username)
|
||||
userWorkspace := conf.GetUserWorkspace(username)
|
||||
workspaces := filepath.SplitList(userWorkspace)
|
||||
|
||||
if "" != path && !util.File.IsDir(path) {
|
||||
|
@ -406,7 +408,7 @@ func SearchText(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
dir := args["dir"].(string)
|
||||
if "" == dir {
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(wSession.Username)
|
||||
userWorkspace := conf.GetUserWorkspace(wSession.Username)
|
||||
workspaces := filepath.SplitList(userWorkspace)
|
||||
dir = workspaces[0]
|
||||
}
|
||||
|
@ -736,14 +738,3 @@ func searchInFile(path string, text string) []*Snippet {
|
|||
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetUsre gets the user the specified path belongs to. Returns nil if not found.
|
||||
func GetUsre(path string) *conf.User {
|
||||
for _, user := range conf.Wide.Users {
|
||||
if strings.HasPrefix(path, user.GetWorkspace()) {
|
||||
return user
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
22
main.go
22
main.go
|
@ -47,13 +47,13 @@ var logger *log.Logger
|
|||
// The only one init function in Wide.
|
||||
func init() {
|
||||
confPath := flag.String("conf", "conf/wide.json", "path of wide.json")
|
||||
confIP := flag.String("ip", "", "ip to visit")
|
||||
confPort := flag.String("port", "", "port to visit")
|
||||
confIP := flag.String("ip", "", "this will overwrite Wide.IP if specified")
|
||||
confPort := flag.String("port", "", "this will overwrite Wide.Port if specified")
|
||||
confServer := flag.String("server", "", "this will overwrite Wide.Server if specified")
|
||||
confLogLevel := flag.String("log_level", "info", "logging level: trace/debug/info/warn/error")
|
||||
confLogLevel := flag.String("log_level", "info", "this will overwrite Wide.LogLevel if specified")
|
||||
confStaticServer := flag.String("static_server", "", "this will overwrite Wide.StaticServer if specified")
|
||||
confContext := flag.String("context", "", "this will overwrite Wide.Context if specified")
|
||||
confChannel := flag.String("channel", "", "this will overwrite Wide.XXXChannel if specified")
|
||||
confChannel := flag.String("channel", "", "this will overwrite Wide.Channel if specified")
|
||||
confStat := flag.Bool("stat", false, "whether report statistics periodically")
|
||||
confDocker := flag.Bool("docker", false, "whether run in a docker container")
|
||||
|
||||
|
@ -77,8 +77,8 @@ func init() {
|
|||
*confDocker)
|
||||
|
||||
conf.FixedTimeCheckEnv()
|
||||
conf.FixedTimeSave()
|
||||
|
||||
session.FixedTimeSave()
|
||||
session.FixedTimeRelease()
|
||||
|
||||
if *confStat {
|
||||
|
@ -103,7 +103,7 @@ func main() {
|
|||
serveSingle("/favicon.ico", "./static/favicon.ico")
|
||||
|
||||
// workspaces
|
||||
for _, user := range conf.Wide.Users {
|
||||
for _, user := range conf.Users {
|
||||
http.Handle(conf.Wide.Context+"/workspace/"+user.Name+"/",
|
||||
http.StripPrefix(conf.Wide.Context+"/workspace/"+user.Name+"/", http.FileServer(http.Dir(user.GetWorkspace()))))
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
wideSession := session.WideSessions.New(httpSession, sid)
|
||||
|
||||
username := httpSession.Values["username"].(string)
|
||||
user := conf.Wide.GetUser(username)
|
||||
user := conf.GetUser(username)
|
||||
if nil == user {
|
||||
logger.Warnf("Not found user [%s]", username)
|
||||
|
||||
|
@ -248,8 +248,8 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
|
|||
httpSession.Save(r, w)
|
||||
|
||||
username := httpSession.Values["username"].(string)
|
||||
locale := conf.Wide.GetUser(username).Locale
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(username)
|
||||
locale := conf.GetUser(username).Locale
|
||||
userWorkspace := conf.GetUserWorkspace(username)
|
||||
|
||||
sid := r.URL.Query()["sid"][0]
|
||||
wSession := session.WideSessions.Get(sid)
|
||||
|
@ -288,7 +288,7 @@ func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) {
|
|||
httpSession.Save(r, w)
|
||||
|
||||
username := httpSession.Values["username"].(string)
|
||||
locale := conf.Wide.GetUser(username).Locale
|
||||
locale := conf.GetUser(username).Locale
|
||||
|
||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale}
|
||||
|
||||
|
@ -320,7 +320,7 @@ func aboutHandler(w http.ResponseWriter, r *http.Request) {
|
|||
httpSession.Save(r, w)
|
||||
|
||||
username := httpSession.Values["username"].(string)
|
||||
locale := conf.Wide.GetUser(username).Locale
|
||||
locale := conf.GetUser(username).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()}
|
||||
|
|
|
@ -64,7 +64,7 @@ func event2Notification(e *event.Event) {
|
|||
|
||||
httpSession, _ := session.HTTPSession.Get(wsChannel.Request, "wide-session")
|
||||
username := httpSession.Values["username"].(string)
|
||||
locale := conf.Wide.GetUser(username).Locale
|
||||
locale := conf.GetUser(username).Locale
|
||||
|
||||
var notification *Notification
|
||||
|
||||
|
|
|
@ -263,7 +263,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
username := httpSession.Values["username"].(string)
|
||||
locale := conf.Wide.GetUser(username).Locale
|
||||
locale := conf.GetUser(username).Locale
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -522,7 +522,7 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
username := httpSession.Values["username"].(string)
|
||||
locale := conf.Wide.GetUser(username).Locale
|
||||
locale := conf.GetUser(username).Locale
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -640,7 +640,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
username := httpSession.Values["username"].(string)
|
||||
locale := conf.Wide.GetUser(username).Locale
|
||||
locale := conf.GetUser(username).Locale
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -805,7 +805,7 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
username := httpSession.Values["username"].(string)
|
||||
locale := conf.Wide.GetUser(username).Locale
|
||||
locale := conf.GetUser(username).Locale
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -937,7 +937,7 @@ func StopHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func setCmdEnv(cmd *exec.Cmd, username string) {
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(username)
|
||||
userWorkspace := conf.GetUserWorkspace(username)
|
||||
|
||||
cmd.Env = append(cmd.Env,
|
||||
"GOPATH="+userWorkspace,
|
||||
|
|
|
@ -242,7 +242,7 @@ func SaveContent(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
wSession.Content = args.LatestSessionContent
|
||||
|
||||
for _, user := range conf.Wide.Users {
|
||||
for _, user := range conf.Users {
|
||||
if user.Name == wSession.Username {
|
||||
// update the variable in-memory, conf.FixedTimeSave() function will persist it periodically
|
||||
user.LatestSessionContent = wSession.Content
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"strconv"
|
||||
"sync"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/i18n"
|
||||
|
@ -61,7 +62,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
httpSession.Save(r, w)
|
||||
|
||||
username := httpSession.Values["username"].(string)
|
||||
user := conf.Wide.GetUser(username)
|
||||
user := conf.GetUser(username)
|
||||
|
||||
if "GET" == r.Method {
|
||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(user.Locale), "user": user,
|
||||
|
@ -134,7 +135,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
conf.UpdateCustomizedConf(username)
|
||||
|
||||
succ = conf.Save()
|
||||
succ = user.Save()
|
||||
}
|
||||
|
||||
// LoginHandler handles request of user login.
|
||||
|
@ -178,7 +179,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
succ = false
|
||||
for _, user := range conf.Wide.Users {
|
||||
for _, user := range conf.Users {
|
||||
if user.Name == args.Username && user.Password == args.Password {
|
||||
succ = true
|
||||
|
||||
|
@ -219,7 +220,7 @@ func SignUpUser(w http.ResponseWriter, r *http.Request) {
|
|||
if "GET" == r.Method {
|
||||
// show the user sign up page
|
||||
|
||||
firstUserWorkspace := conf.Wide.GetUserWorkspace(conf.Wide.Users[0].Name)
|
||||
firstUserWorkspace := conf.GetUserWorkspace(conf.Users[0].Name)
|
||||
dir := filepath.Dir(firstUserWorkspace)
|
||||
|
||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(conf.Wide.Locale),
|
||||
|
@ -266,6 +267,46 @@ func SignUpUser(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
func FixedTimeSave() {
|
||||
go func() {
|
||||
for _ = range time.Tick(time.Minute) {
|
||||
users := getOnlineUsers()
|
||||
|
||||
for _, u := range users {
|
||||
if u.Save() {
|
||||
logger.Tracef("Saved online user [%s]'s configurations")
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func getOnlineUsers() []*conf.User {
|
||||
ret := []*conf.User{}
|
||||
|
||||
usernames := map[string]string{} // distinct username
|
||||
for _, s := range WideSessions {
|
||||
usernames[s.Username] = ""
|
||||
}
|
||||
|
||||
for _, username := range usernames {
|
||||
u := conf.GetUser(username)
|
||||
|
||||
if nil == u {
|
||||
logger.Warnf("Not found user [%s]", username)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
ret = append(ret, u)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// addUser add a user with the specified username, password and email.
|
||||
//
|
||||
// 1. create the user's workspace
|
||||
|
@ -276,7 +317,7 @@ func addUser(username, password, email string) string {
|
|||
addUserMutex.Lock()
|
||||
defer addUserMutex.Unlock()
|
||||
|
||||
for _, user := range conf.Wide.Users {
|
||||
for _, user := range conf.Users {
|
||||
if user.Name == username {
|
||||
return userExists
|
||||
}
|
||||
|
@ -286,12 +327,12 @@ func addUser(username, password, email string) string {
|
|||
}
|
||||
}
|
||||
|
||||
firstUserWorkspace := conf.Wide.GetUserWorkspace(conf.Wide.Users[0].Name)
|
||||
firstUserWorkspace := conf.GetUserWorkspace(conf.Users[0].Name)
|
||||
dir := filepath.Dir(firstUserWorkspace)
|
||||
workspace := filepath.Join(dir, username)
|
||||
|
||||
newUser := conf.NewUser(username, password, email, workspace)
|
||||
conf.Wide.Users = append(conf.Wide.Users, newUser)
|
||||
conf.Users = append(conf.Users, newUser)
|
||||
|
||||
if !conf.Save() {
|
||||
return userCreateError
|
||||
|
|
|
@ -63,7 +63,7 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
wideSession := session.WideSessions.New(httpSession, sid)
|
||||
|
||||
username := httpSession.Values["username"].(string)
|
||||
locale := conf.Wide.GetUser(username).Locale
|
||||
locale := conf.GetUser(username).Locale
|
||||
|
||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale,
|
||||
"session": wideSession}
|
||||
|
@ -182,7 +182,7 @@ func pipeCommands(username string, commands ...*exec.Cmd) string {
|
|||
}
|
||||
|
||||
func setCmdEnv(cmd *exec.Cmd, username string) {
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(username)
|
||||
userWorkspace := conf.GetUserWorkspace(username)
|
||||
|
||||
cmd.Env = append(cmd.Env,
|
||||
"TERM="+os.Getenv("TERM"),
|
||||
|
|
Loading…
Reference in New Issue