diff --git a/scripts/build.bat b/scripts/build.bat old mode 100644 new mode 100755 diff --git a/scripts/run.bat b/scripts/run.bat old mode 100644 new mode 100755 diff --git a/server/cmd/version.go b/server/cmd/version.go index c5dfaf37..545e8fb9 100644 --- a/server/cmd/version.go +++ b/server/cmd/version.go @@ -22,6 +22,6 @@ var versionCmd = &cobra.Command{ Short: "Print the version number of ShadowEditor", Long: `All software has versions. This is ShadowEditor's`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("ShadowEditor version: v0.4.6") + fmt.Println("ShadowEditor version: v0.5.0") }, } diff --git a/server/config-server.toml b/server/config-server.toml new file mode 100644 index 00000000..bae827e5 --- /dev/null +++ b/server/config-server.toml @@ -0,0 +1,23 @@ +# Shadow Editor Server Configuration + +[server] +port = ":2020" # server address + +[database] +type = "mongo" # only support mongo +connection = "mongodb://127.0.0.1:27017" # mongo connection string +database = "ShadowEditor" # mongo database name + +[authority] +enabled = true # enable authority +expires = 120 # login time, minutes, only support integer + +[upload] +max_size = 1000000000 # max upload file size + +[remote] +enabled = false # enable remote edit +web_socket_port = 5000 # web socket server port + +[log] +file = "../logs/ShadowServer.txt" \ No newline at end of file diff --git a/server/config.toml b/server/config.toml index bae827e5..ac5ae14a 100644 --- a/server/config.toml +++ b/server/config.toml @@ -5,11 +5,12 @@ port = ":2020" # server address [database] type = "mongo" # only support mongo -connection = "mongodb://127.0.0.1:27017" # mongo connection string -database = "ShadowEditor" # mongo database name +host = "127.0.0.1" # mongoDB host +port = 27017 # mongoDB port +database = "ShadowEditor" # mongoDB database name [authority] -enabled = true # enable authority +enabled = true # enable authority expires = 120 # login time, minutes, only support integer [upload] @@ -19,5 +20,10 @@ max_size = 1000000000 # max upload file size enabled = false # enable remote edit web_socket_port = 5000 # web socket server port +[path] +public_dir = "./public" # The directory that contains index.html. + # Path `./public/Upload` need write authority. +log_dir = "./logs" # The directory that contains log files. Need write authority. + [log] -file = "../logs/ShadowServer.txt" \ No newline at end of file +file = "./logs/ShadowServer.txt" \ No newline at end of file diff --git a/server/helper/config.go b/server/helper/config.go index 4409579c..363b542b 100644 --- a/server/helper/config.go +++ b/server/helper/config.go @@ -8,12 +8,15 @@ package helper import ( + "fmt" "os" + "runtime" + "strings" "github.com/BurntSushi/toml" ) -// GetConfig get config from config.toml +// GetConfig get server config from `config.toml` func GetConfig(path string) (config *ConfigModel, err error) { file, err := os.Open(path) if err != nil { @@ -27,49 +30,68 @@ func GetConfig(path string) (config *ConfigModel, err error) { return nil, err } + // parse mongoDB connection string. + config.Database.Connection = fmt.Sprintf("mongodb://%v:%v", config.Database.Host, config.Database.Port) + + // In windows system, path separator "/" should be replace with "\\". + if strings.HasPrefix(runtime.GOOS, "windows") { + config.Path.PublicDir = strings.ReplaceAll(config.Path.PublicDir, "/", "\\") + config.Path.LogDir = strings.ReplaceAll(config.Path.LogDir, "/", "\\") + } + return } -// ConfigModel shadoweditor config +// ConfigModel is the structure of file `config.toml`. type ConfigModel struct { Server ServerConfigModel `toml:"server"` Database DatabaseConfigModel `toml:"database"` Authority AuthorityConfigModel `toml:"authority"` Upload UploadConfigModel `toml:"upload"` Remote RemoteConfigModel `toml:"remote"` + Path PathConfigModel `toml:"path"` Log LogConfigModel `toml:"log"` } -// ServerConfigModel server config +// ServerConfigModel is the server config section in `config.toml`; type ServerConfigModel struct { Port string `toml:"port"` } -// DatabaseConfigModel database config +// DatabaseConfigModel is the database config section in `config.toml`; type DatabaseConfigModel struct { - Type string `toml:"type"` - Connection string `toml:"connection"` + Type string `toml:"type"` + Host string `toml:"host"` + Port int `toml:"port"` + // Connection should not read from config.toml. + Connection string Database string `toml:"database"` } -// AuthorityConfigModel authority config +// AuthorityConfigModel is the authority config section in `config.toml`; type AuthorityConfigModel struct { Enabled bool `toml:"enabled"` Expires int `toml:"expires"` } -// UploadConfigModel upload config +// UploadConfigModel is the upload config section in `config.toml`; type UploadConfigModel struct { MaxSize int64 `toml:"max_size"` } -// RemoteConfigModel remote config +// RemoteConfigModel is the remote config section in `config.toml`; type RemoteConfigModel struct { Enabled bool `toml:"enabled"` WebSocketPort int `toml:"web_socket_port"` } -// LogConfigModel log config +// PathConfigModel is the authority path section in `config.toml`; +type PathConfigModel struct { + PublicDir string `toml:"public_dir"` + LogDir string `toml:"log_dir"` +} + +// LogConfigModel is the log config section in `config.toml`; type LogConfigModel struct { File string `toml:"file"` } diff --git a/server/helper/config_test.go b/server/helper/config_test.go index 66fcd2df..5381db75 100644 --- a/server/helper/config_test.go +++ b/server/helper/config_test.go @@ -29,5 +29,8 @@ func TestConfig(t *testing.T) { t.Logf("remote.enabled: %v", config.Remote.Enabled) t.Logf("remote.web_socket_port: %v", config.Remote.WebSocketPort) + t.Logf("path.public_dir: %v", config.Path.PublicDir) + t.Logf("path.log_dir: %v", config.Path.LogDir) + t.Logf("log.file: %v", config.Log.File) } diff --git a/server/helper/json.go b/server/helper/json.go index 38f2d44d..23aad4bd 100644 --- a/server/helper/json.go +++ b/server/helper/json.go @@ -8,19 +8,24 @@ package helper import ( + "reflect" + "time" + + "go.mongodb.org/mongo-driver/bson/primitive" + jsoniter "github.com/json-iterator/go" "github.com/tengge1/shadoweditor/helper/encoder" ) func init() { - jsoniter.RegisterTypeEncoder("time.Time", encoder.TimeEncoder{}) + jsoniter.RegisterTypeEncoder(reflect.TypeOf(time.Now()).String(), encoder.TimeEncoder{}) jsoniter.RegisterTypeEncoder( - "go.mongodb.org/mongo-driver/bson/primitive.ObjectID", + reflect.TypeOf(primitive.NewObjectID()).String(), encoder.PrimitiveObjectIDEncoder{}, ) jsoniter.RegisterTypeEncoder( - "go.mongodb.org/mongo-driver/bson/primitive.D", + reflect.TypeOf(primitive.D{}).String(), encoder.PrimitiveDEncoder{}, ) } diff --git a/server/server/animation/handle_animation.go b/server/server/animation/handle_animation.go index 88b84b83..c84fff34 100644 --- a/server/server/animation/handle_animation.go +++ b/server/server/animation/handle_animation.go @@ -166,7 +166,7 @@ func (Animation) Add(w http.ResponseWriter, r *http.Request) { now := time.Now() savePath := fmt.Sprintf("/Upload/Animation/%v", helper.TimeToString(now, "yyyyMMddHHmmss")) - physicalPath := helper.MapPath(savePath) + physicalPath := server.MapPath(savePath) tempPath := filepath.Join(physicalPath, "temp") @@ -375,7 +375,7 @@ func (Animation) Delete(w http.ResponseWriter, r *http.Request) { } path := doc["SavePath"].(string) - physicalPath := helper.MapPath(path) + physicalPath := server.MapPath(path) os.RemoveAll(physicalPath) db.DeleteOne(server.AnimationCollectionName, filter) diff --git a/server/server/audio/handle_audio.go b/server/server/audio/handle_audio.go index fb891f48..2e0f4405 100644 --- a/server/server/audio/handle_audio.go +++ b/server/server/audio/handle_audio.go @@ -166,7 +166,7 @@ func (Audio) Add(w http.ResponseWriter, r *http.Request) { now := time.Now() savePath := fmt.Sprintf("/Upload/Audio/%v", helper.TimeToString(now, "yyyyMMddHHmmss")) - physicalPath := helper.MapPath(savePath) + physicalPath := server.MapPath(savePath) if _, err := os.Stat(physicalPath); os.IsNotExist(err) { os.MkdirAll(physicalPath, 0755) @@ -343,7 +343,7 @@ func (Audio) Delete(w http.ResponseWriter, r *http.Request) { } path := doc["SavePath"].(string) - physicalPath := helper.MapPath(path) + physicalPath := server.MapPath(path) os.RemoveAll(physicalPath) db.DeleteOne(server.AudioCollectionName, filter) diff --git a/server/server/export/editor/copy_assets.go b/server/server/export/editor/copy_assets.go index 13feb985..45fa4fc8 100644 --- a/server/server/export/editor/copy_assets.go +++ b/server/server/export/editor/copy_assets.go @@ -19,7 +19,7 @@ import ( // CopyAssets copy the assets needed to the exported scene. func CopyAssets(path string) error { // copy html files - sourceName := helper.MapPath("/index.html") + sourceName := server.MapPath("/index.html") destName := filepath.Join(path, "editor.html") if err := helper.CopyFile(sourceName, destName); err != nil { return err @@ -41,28 +41,28 @@ func CopyAssets(path string) error { os.MkdirAll(dirName, 0755) } - sourceName = helper.MapPath("/build/ShadowEditor.js") + sourceName = server.MapPath("/build/ShadowEditor.js") destName = filepath.Join(path, "build", "ShadowEditor.js") if err := helper.CopyFile(sourceName, destName); err != nil { return err } // copy assets folder - sourceName = helper.MapPath("/assets") + sourceName = server.MapPath("/assets") destName = filepath.Join(path, "assets") if err := helper.CopyDirectory(sourceName, destName); err != nil { return err } // copy language pack - sourceName = helper.MapPath("/lang") + sourceName = server.MapPath("/lang") destName = filepath.Join(path, "lang") if err := helper.CopyDirectory(sourceName, destName); err != nil { return err } // copy website icon - sourceName = helper.MapPath("/favicon.ico") + sourceName = server.MapPath("/favicon.ico") destName = filepath.Join(path, "favicon.ico") return helper.CopyDirectory(sourceName, destName) } diff --git a/server/server/export/editor/run.go b/server/server/export/editor/run.go index 7e86eb1c..5d9e3ba2 100644 --- a/server/server/export/editor/run.go +++ b/server/server/export/editor/run.go @@ -26,7 +26,7 @@ func init() { func Run(w http.ResponseWriter, r *http.Request) { now := time.Now() - path := helper.MapPath(fmt.Sprintf("/temp/%v", helper.TimeToString(now, "yyyyMMddHHmmss"))) + path := server.MapPath(fmt.Sprintf("/temp/%v", helper.TimeToString(now, "yyyyMMddHHmmss"))) if _, err := os.Stat(path); os.IsNotExist(err) { os.MkdirAll(path, 0755) diff --git a/server/helper/map_path.go b/server/server/map_path.go similarity index 79% rename from server/helper/map_path.go rename to server/server/map_path.go index bb52f9bb..be07a4bd 100644 --- a/server/helper/map_path.go +++ b/server/server/map_path.go @@ -5,7 +5,7 @@ // For more information, please visit: https://github.com/tengge1/ShadowEditor // You can also visit: https://gitee.com/tengge1/ShadowEditor -package helper +package server import ( "fmt" @@ -18,6 +18,6 @@ func MapPath(path string) string { if !strings.HasPrefix(path, "/") { path = "/" + path } - path = strings.ReplaceAll(path, "/", string(filepath.Separator)) - return fmt.Sprintf("./%v", path) + path = fmt.Sprintf("%v%v", Config.Path.PublicDir, path) + return strings.ReplaceAll(path, "/", string(filepath.Separator)) } diff --git a/server/helper/map_path_test.go b/server/server/map_path_test.go similarity index 96% rename from server/helper/map_path_test.go rename to server/server/map_path_test.go index 72d813d3..c560cf2a 100644 --- a/server/helper/map_path_test.go +++ b/server/server/map_path_test.go @@ -5,7 +5,7 @@ // For more information, please visit: https://github.com/tengge1/ShadowEditor // You can also visit: https://gitee.com/tengge1/ShadowEditor -package helper +package server import "testing" diff --git a/server/server/mesh/handle_mesh.go b/server/server/mesh/handle_mesh.go index 4532177c..c9fa57cb 100644 --- a/server/server/mesh/handle_mesh.go +++ b/server/server/mesh/handle_mesh.go @@ -169,7 +169,7 @@ func (Mesh) Add(w http.ResponseWriter, r *http.Request) { now := time.Now() savePath := fmt.Sprintf("/Upload/Model/%v", helper.TimeToString(now, "yyyyMMddHHmmss")) - physicalPath := helper.MapPath(savePath) + physicalPath := server.MapPath(savePath) tempPath := filepath.Join(physicalPath, "temp") @@ -540,7 +540,7 @@ func (Mesh) Delete(w http.ResponseWriter, r *http.Request) { } path := doc["SavePath"].(string) - physicalPath := helper.MapPath(path) + physicalPath := server.MapPath(path) os.RemoveAll(physicalPath) db.DeleteOne(server.MeshCollectionName, filter) @@ -588,11 +588,11 @@ func (Mesh) Download(w http.ResponseWriter, r *http.Request) { } // create zip file - savePath := helper.MapPath(doc["SavePath"].(string)) + savePath := server.MapPath(doc["SavePath"].(string)) now := helper.TimeToString(time.Now(), "yyyyMMddHHmmssfff") destFile := fmt.Sprintf("/temp/%v.zip", now) - descPhysicalFile := helper.MapPath(destFile) + descPhysicalFile := server.MapPath(destFile) helper.Zip(savePath, descPhysicalFile) diff --git a/server/server/middleware/crossorigin.go b/server/server/middleware_crossorigin.go similarity index 96% rename from server/server/middleware/crossorigin.go rename to server/server/middleware_crossorigin.go index 33ab37fc..d6e4635d 100644 --- a/server/server/middleware/crossorigin.go +++ b/server/server/middleware_crossorigin.go @@ -5,7 +5,7 @@ // For more information, please visit: https://github.com/tengge1/ShadowEditor // You can also visit: https://gitee.com/tengge1/ShadowEditor -package middleware +package server import ( "net/http" diff --git a/server/server/middleware/gzip.go b/server/server/middleware_gzip.go similarity index 98% rename from server/server/middleware/gzip.go rename to server/server/middleware_gzip.go index 07e56982..ac891c1c 100644 --- a/server/server/middleware/gzip.go +++ b/server/server/middleware_gzip.go @@ -5,7 +5,7 @@ // For more information, please visit: https://github.com/tengge1/ShadowEditor // You can also visit: https://gitee.com/tengge1/ShadowEditor -package middleware +package server import ( "compress/gzip" diff --git a/server/server/middleware/static.go b/server/server/middleware_static.go similarity index 91% rename from server/server/middleware/static.go rename to server/server/middleware_static.go index 8d41dbb9..96eb9cf9 100644 --- a/server/server/middleware/static.go +++ b/server/server/middleware_static.go @@ -5,7 +5,7 @@ // For more information, please visit: https://github.com/tengge1/ShadowEditor // You can also visit: https://gitee.com/tengge1/ShadowEditor -package middleware +package server import ( "fmt" @@ -15,8 +15,6 @@ import ( "os" "path/filepath" "strings" - - "github.com/tengge1/shadoweditor/helper" ) // StaticHandler is responsible for serve static contents. @@ -29,7 +27,7 @@ func StaticHandler(w http.ResponseWriter, r *http.Request, next http.HandlerFunc // TODO: May have security risk. // static contents - path := helper.MapPath("/public/") + r.URL.Path + path := MapPath("/public/") + r.URL.Path if strings.HasSuffix(path, "/") { path += "index.html" diff --git a/server/server/screenshot/handle_screenshot.go b/server/server/screenshot/handle_screenshot.go index abb15772..add91418 100644 --- a/server/server/screenshot/handle_screenshot.go +++ b/server/server/screenshot/handle_screenshot.go @@ -169,7 +169,7 @@ func (Screenshot) Add(w http.ResponseWriter, r *http.Request) { now := time.Now() savePath := fmt.Sprintf("/Upload/Screenshot/%v", helper.TimeToString(now, "yyyyMMddHHmmss")) - physicalPath := helper.MapPath(savePath) + physicalPath := server.MapPath(savePath) if _, err := os.Stat(physicalPath); os.IsNotExist(err) { os.MkdirAll(physicalPath, 0755) @@ -345,7 +345,7 @@ func (Screenshot) Delete(w http.ResponseWriter, r *http.Request) { } path := doc["SavePath"].(string) - physicalPath := helper.MapPath(path) + physicalPath := server.MapPath(path) os.RemoveAll(physicalPath) db.DeleteOne(server.ScreenshotCollectionName, filter) diff --git a/server/server/server.go b/server/server/server.go index 76698fc3..e81dc9f4 100644 --- a/server/server/server.go +++ b/server/server/server.go @@ -12,8 +12,6 @@ import ( "net/http" "github.com/urfave/negroni" - - "github.com/tengge1/shadoweditor/server/middleware" ) // Start start the server @@ -21,9 +19,9 @@ func Start() { log.Printf("starting shadoweditor server on port %v", Config.Server.Port) handler := negroni.Classic() - handler.Use(negroni.HandlerFunc(middleware.CrossOriginHandler)) - handler.Use(negroni.HandlerFunc(middleware.GZipHandler)) - // handler.Use(negroni.HandlerFunc(middleware.StaticHandler)) + handler.Use(negroni.HandlerFunc(CrossOriginHandler)) + handler.Use(negroni.HandlerFunc(GZipHandler)) + handler.Use(negroni.HandlerFunc(StaticHandler)) handler.UseHandler(Mux) err := http.ListenAndServe(Config.Server.Port, handler) diff --git a/server/server/texture/handle_texture.go b/server/server/texture/handle_texture.go index 1b6b0f0d..3b9ceb6e 100644 --- a/server/server/texture/handle_texture.go +++ b/server/server/texture/handle_texture.go @@ -183,7 +183,7 @@ func (Texture) Add(w http.ResponseWriter, r *http.Request) { now := time.Now() savePath := fmt.Sprintf("/Upload/Texture/%v", helper.TimeToString(now, "yyyyMMddHHmmss")) - physicalPath := helper.MapPath(savePath) + physicalPath := server.MapPath(savePath) if _, err := os.Stat(physicalPath); os.IsNotExist(err) { os.MkdirAll(physicalPath, 0755) @@ -406,7 +406,7 @@ func (Texture) Delete(w http.ResponseWriter, r *http.Request) { // 删除纹理所在目录 path := doc["SavePath"].(string) - physicalPath := helper.MapPath(path) + physicalPath := server.MapPath(path) err = os.RemoveAll(physicalPath) if err != nil { diff --git a/server/server/upload/handle_upload.go b/server/server/upload/handle_upload.go index 4327aba6..e42ae3a0 100644 --- a/server/server/upload/handle_upload.go +++ b/server/server/upload/handle_upload.go @@ -67,7 +67,7 @@ func (Upload) Upload(w http.ResponseWriter, r *http.Request) { now := time.Now() savePath := fmt.Sprintf("/Upload/File/%v", helper.TimeToString(now, "yyyyMMddHHmmss")) - physicalPath := helper.MapPath(savePath) + physicalPath := server.MapPath(savePath) if _, err := os.Stat(physicalPath); os.IsNotExist(err) { os.MkdirAll(physicalPath, 0755) diff --git a/server/server/video/handle_video.go b/server/server/video/handle_video.go index fd3ff5a8..a3df67c2 100644 --- a/server/server/video/handle_video.go +++ b/server/server/video/handle_video.go @@ -167,7 +167,7 @@ func (Video) Add(w http.ResponseWriter, r *http.Request) { now := time.Now() savePath := fmt.Sprintf("/Upload/Video/%v", helper.TimeToString(now, "yyyyMMddHHmmss")) - physicalPath := helper.MapPath(savePath) + physicalPath := server.MapPath(savePath) if _, err := os.Stat(physicalPath); os.IsNotExist(err) { os.MkdirAll(physicalPath, 0755) @@ -343,7 +343,7 @@ func (Video) Delete(w http.ResponseWriter, r *http.Request) { } path := doc["SavePath"].(string) - physicalPath := helper.MapPath(path) + physicalPath := server.MapPath(path) os.RemoveAll(physicalPath) db.DeleteOne(server.VideoCollectionName, filter) diff --git a/server/test/json/primitive_d/primitive_d.go b/server/test/json/primitive_d/primitive_d.go index 010b2783..fd5cb467 100644 --- a/server/test/json/primitive_d/primitive_d.go +++ b/server/test/json/primitive_d/primitive_d.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "reflect" "unsafe" "go.mongodb.org/mongo-driver/bson/primitive" @@ -15,7 +16,7 @@ func main() { {Key: "hello", Value: "world"}, } - jsoniter.RegisterTypeEncoder("go.mongodb.org/mongo-driver/bson/primitive.D", PrimitiveDEncoder{}) + jsoniter.RegisterTypeEncoder(reflect.TypeOf(primitive.D{}).String(), PrimitiveDEncoder{}) bytes, err := jsoniter.Marshal(data) if err != nil { diff --git a/server/test/system/check_type.go b/server/test/system/check_type.go new file mode 100644 index 00000000..eeb13b1c --- /dev/null +++ b/server/test/system/check_type.go @@ -0,0 +1,10 @@ +package main + +import ( + "fmt" + "runtime" +) + +func main() { + fmt.Println(runtime.GOOS) +}