diff --git a/README.md b/README.md new file mode 100644 index 0000000..c5fc306 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +Create a configuration file `$HOME/.config/notes.yaml` with the following content: + +```yaml +websocket: + domains: + - notes.com + +database: + host: 127.0.0.1 + port: 5432 + name: notes.com + username: notes + password: SomePassword + +application: + directories: + static: /usr/local/share/notes + upload: /usr/local/lib/notes/upload + +session: + daysvalid: 31 +``` + +Create an empty database. diff --git a/db.go b/db.go index f8df736..65e189f 100644 --- a/db.go +++ b/db.go @@ -6,7 +6,6 @@ import ( _ "github.com/lib/pq" // Standard - "embed" "errors" "fmt" "log" @@ -16,9 +15,6 @@ import ( var ( dbConn string db *sqlx.DB - - //go:embed sql/* - embedded embed.FS ) func dbInit() (err error) {// {{{ diff --git a/main.go b/main.go index 8ea96d4..d1d14dd 100644 --- a/main.go +++ b/main.go @@ -3,8 +3,8 @@ package main import ( // Standard "crypto/md5" + "embed" "encoding/hex" - "path/filepath" "flag" "fmt" "html/template" @@ -13,41 +13,45 @@ import ( "net/http" "os" "path" + "path/filepath" "regexp" - "strings" "strconv" + "strings" "time" - _ "embed" ) -const VERSION = "v13"; -const LISTEN_HOST = "0.0.0.0"; +const LISTEN_HOST = "0.0.0.0" const DB_SCHEMA = 13 var ( - flagPort int + flagPort int flagVersion bool + flagConfig string + connectionManager ConnectionManager - static http.Handler - config Config + static http.Handler + config Config + VERSION string + + //go:embed version sql/* + embedded embed.FS ) -func init() {// {{{ - flag.IntVar( - &flagPort, - "port", - 1371, - "TCP port to listen on", - ) - flag.BoolVar(&flagVersion, "version", false, "Shows Notes version and exists") +func init() { // {{{ + version, _ := embedded.ReadFile("version") + VERSION = strings.TrimSpace(string(version)) + configFilename := os.Getenv("HOME") + "/.config/notes.yaml" + flag.IntVar(&flagPort, "port", 1371, "TCP port to listen on") + flag.BoolVar(&flagVersion, "version", false, "Shows Notes version and exists") + flag.StringVar(&flagConfig, "config", configFilename, "Filename of configuration file") flag.Parse() if false { - time.Sleep(time.Second*1) + time.Sleep(time.Second * 1) } -}// }}} -func main() {// {{{ +} // }}} +func main() { // {{{ var err error if flagVersion { @@ -57,7 +61,7 @@ func main() {// {{{ log.Printf("\x1b[32mNotes\x1b[0m %s\n", VERSION) - config, err = ConfigRead(os.Getenv("HOME")+"/.config/notes.yaml") + config, err = ConfigRead(flagConfig) if err != nil { fmt.Printf("%s\n", err) os.Exit(1) @@ -72,23 +76,23 @@ func main() {// {{{ go connectionManager.BroadcastLoop() static = http.FileServer(http.Dir(config.Application.Directories.Static)) - http.HandleFunc("/css_updated", cssUpdateHandler) - http.HandleFunc("/session/create", sessionCreate) - http.HandleFunc("/session/retrieve", sessionRetrieve) + http.HandleFunc("/css_updated", cssUpdateHandler) + http.HandleFunc("/session/create", sessionCreate) + http.HandleFunc("/session/retrieve", sessionRetrieve) http.HandleFunc("/session/authenticate", sessionAuthenticate) - http.HandleFunc("/user/password", userPassword) - http.HandleFunc("/node/tree", nodeTree) - http.HandleFunc("/node/retrieve", nodeRetrieve) - http.HandleFunc("/node/create", nodeCreate) - http.HandleFunc("/node/update", nodeUpdate) - http.HandleFunc("/node/rename", nodeRename) - http.HandleFunc("/node/delete", nodeDelete) - http.HandleFunc("/node/upload", nodeUpload) - http.HandleFunc("/node/download", nodeDownload) - http.HandleFunc("/node/search", nodeSearch) - http.HandleFunc("/key/retrieve", keyRetrieve) - http.HandleFunc("/key/create", keyCreate) - http.HandleFunc("/key/counter", keyCounter) + http.HandleFunc("/user/password", userPassword) + http.HandleFunc("/node/tree", nodeTree) + http.HandleFunc("/node/retrieve", nodeRetrieve) + http.HandleFunc("/node/create", nodeCreate) + http.HandleFunc("/node/update", nodeUpdate) + http.HandleFunc("/node/rename", nodeRename) + http.HandleFunc("/node/delete", nodeDelete) + http.HandleFunc("/node/upload", nodeUpload) + http.HandleFunc("/node/download", nodeDownload) + http.HandleFunc("/node/search", nodeSearch) + http.HandleFunc("/key/retrieve", keyRetrieve) + http.HandleFunc("/key/create", keyCreate) + http.HandleFunc("/key/counter", keyCounter) http.HandleFunc("/ws", websocketHandler) http.HandleFunc("/", staticHandler) @@ -96,13 +100,17 @@ func main() {// {{{ log.Printf("\x1b[32mNotes\x1b[0m Listening on %s\n", listen) log.Printf("\x1b[32mNotes\x1b[0m Answer for domains %s\n", strings.Join(config.Websocket.Domains, ", ")) http.ListenAndServe(listen, nil) -}// }}} +} // }}} -func cssUpdateHandler(w http.ResponseWriter, r *http.Request) {// {{{ +func cssUpdateHandler(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("[BROADCAST] CSS updated") - connectionManager.Broadcast(struct{ Ok bool; ID string; Op string }{ Ok: true, Op: "css_reload" }) -}// }}} -func websocketHandler(w http.ResponseWriter, r *http.Request) {// {{{ + connectionManager.Broadcast(struct { + Ok bool + ID string + Op string + }{Ok: true, Op: "css_reload"}) +} // }}} +func websocketHandler(w http.ResponseWriter, r *http.Request) { // {{{ var err error _, err = connectionManager.NewConnection(w, r) @@ -110,9 +118,9 @@ func websocketHandler(w http.ResponseWriter, r *http.Request) {// {{{ log.Printf("[Connection] %s\n", err) return } -}// }}} -func staticHandler(w http.ResponseWriter, r *http.Request) {// {{{ - data := struct{ +} // }}} +func staticHandler(w http.ResponseWriter, r *http.Request) { // {{{ + data := struct { VERSION string }{ VERSION: VERSION, @@ -149,9 +157,9 @@ func staticHandler(w http.ResponseWriter, r *http.Request) {// {{{ if err = tmpl.Execute(w, data); err != nil { w.Write([]byte(err.Error())) } -}// }}} +} // }}} -func sessionCreate(w http.ResponseWriter, r *http.Request) {// {{{ +func sessionCreate(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/session/create") session, err := CreateSession() if err != nil { @@ -159,11 +167,11 @@ func sessionCreate(w http.ResponseWriter, r *http.Request) {// {{{ return } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "Session": session, }) -}// }}} -func sessionRetrieve(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func sessionRetrieve(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/session/retrieve") var err error var found bool @@ -175,12 +183,12 @@ func sessionRetrieve(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, - "Valid": found, + "OK": true, + "Valid": found, "Session": session, }) -}// }}} -func sessionAuthenticate(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func sessionAuthenticate(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/session/authenticate") var err error var session Session @@ -192,7 +200,10 @@ func sessionAuthenticate(w http.ResponseWriter, r *http.Request) {// {{{ return } - req := struct{ Username string; Password string }{} + req := struct { + Username string + Password string + }{} if err = parseRequest(r, &req); err != nil { responseError(w, err) return @@ -204,13 +215,13 @@ func sessionAuthenticate(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "Authenticated": authenticated, - "Session": session, + "Session": session, }) -}// }}} +} // }}} -func userPassword(w http.ResponseWriter, r *http.Request) {// {{{ +func userPassword(w http.ResponseWriter, r *http.Request) { // {{{ var err error var ok bool var session Session @@ -222,7 +233,7 @@ func userPassword(w http.ResponseWriter, r *http.Request) {// {{{ req := struct { CurrentPassword string - NewPassword string + NewPassword string }{} if err = parseRequest(r, &req); err != nil { responseError(w, err) @@ -236,12 +247,12 @@ func userPassword(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "CurrentPasswordOK": ok, }) -}// }}} +} // }}} -func nodeTree(w http.ResponseWriter, r *http.Request) {// {{{ +func nodeTree(w http.ResponseWriter, r *http.Request) { // {{{ var err error var session Session @@ -250,7 +261,7 @@ func nodeTree(w http.ResponseWriter, r *http.Request) {// {{{ return } - req := struct { StartNodeID int }{} + req := struct{ StartNodeID int }{} if err = parseRequest(r, &req); err != nil { responseError(w, err) return @@ -263,11 +274,11 @@ func nodeTree(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "Nodes": nodes, }) -}// }}} -func nodeRetrieve(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func nodeRetrieve(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/node/retrieve") var err error var session Session @@ -277,7 +288,7 @@ func nodeRetrieve(w http.ResponseWriter, r *http.Request) {// {{{ return } - req := struct { ID int }{} + req := struct{ ID int }{} if err = parseRequest(r, &req); err != nil { responseError(w, err) return @@ -290,11 +301,11 @@ func nodeRetrieve(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "Node": node, }) -}// }}} -func nodeCreate(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func nodeCreate(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/node/create") var err error var session Session @@ -305,7 +316,7 @@ func nodeCreate(w http.ResponseWriter, r *http.Request) {// {{{ } req := struct { - Name string + Name string ParentID int }{} if err = parseRequest(r, &req); err != nil { @@ -320,11 +331,11 @@ func nodeCreate(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "Node": node, }) -}// }}} -func nodeUpdate(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func nodeUpdate(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/node/update") var err error var session Session @@ -335,8 +346,8 @@ func nodeUpdate(w http.ResponseWriter, r *http.Request) {// {{{ } req := struct { - NodeID int - Content string + NodeID int + Content string CryptoKeyID int }{} if err = parseRequest(r, &req); err != nil { @@ -353,8 +364,8 @@ func nodeUpdate(w http.ResponseWriter, r *http.Request) {// {{{ responseData(w, map[string]interface{}{ "OK": true, }) -}// }}} -func nodeRename(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func nodeRename(w http.ResponseWriter, r *http.Request) { // {{{ var err error var session Session @@ -365,7 +376,7 @@ func nodeRename(w http.ResponseWriter, r *http.Request) {// {{{ req := struct { NodeID int - Name string + Name string }{} if err = parseRequest(r, &req); err != nil { responseError(w, err) @@ -381,8 +392,8 @@ func nodeRename(w http.ResponseWriter, r *http.Request) {// {{{ responseData(w, map[string]interface{}{ "OK": true, }) -}// }}} -func nodeDelete(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func nodeDelete(w http.ResponseWriter, r *http.Request) { // {{{ var err error var session Session @@ -408,8 +419,8 @@ func nodeDelete(w http.ResponseWriter, r *http.Request) {// {{{ responseData(w, map[string]interface{}{ "OK": true, }) -}// }}} -func nodeUpload(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func nodeUpload(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/node/upload") var err error var session Session @@ -444,18 +455,17 @@ func nodeUpload(w http.ResponseWriter, r *http.Request) {// {{{ md5sumBytes := md5.Sum(fileBytes) md5sum := hex.EncodeToString(md5sumBytes[:]) - var nodeID int if nodeID, err = strconv.Atoi(r.PostFormValue("NodeID")); err != nil { responseError(w, err) return } nodeFile := File{ - NodeID: nodeID, + NodeID: nodeID, Filename: handler.Filename, - Size: handler.Size, - MIME: handler.Header.Get("Content-Type"), - MD5: md5sum, + Size: handler.Size, + MIME: handler.Header.Get("Content-Type"), + MD5: md5sum, } if err = session.AddFile(&nodeFile); err != nil { responseError(w, err) @@ -490,11 +500,11 @@ func nodeUpload(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "File": nodeFile, }) -}// }}} -func nodeDownload(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func nodeDownload(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/node/download") var err error var session Session @@ -524,7 +534,7 @@ func nodeDownload(w http.ResponseWriter, r *http.Request) {// {{{ responseError(w, fmt.Errorf("File not found")) return } - + var file *os.File fname := filepath.Join( config.Application.Directories.Upload, @@ -560,8 +570,8 @@ func nodeDownload(w http.ResponseWriter, r *http.Request) {// {{{ } } -}// }}} -func nodeFiles(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func nodeFiles(w http.ResponseWriter, r *http.Request) { // {{{ var err error var session Session var files []File @@ -586,11 +596,11 @@ func nodeFiles(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "Files": files, }) -}// }}} -func nodeSearch(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func nodeSearch(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/node/search") var err error var session Session @@ -616,12 +626,12 @@ func nodeSearch(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "Nodes": nodes, }) -}// }}} +} // }}} -func keyRetrieve(w http.ResponseWriter, r *http.Request) {// {{{ +func keyRetrieve(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/key/retrieve") var err error var session Session @@ -638,11 +648,11 @@ func keyRetrieve(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "Keys": keys, }) -}// }}} -func keyCreate(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func keyCreate(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/key/create") var err error var session Session @@ -654,7 +664,7 @@ func keyCreate(w http.ResponseWriter, r *http.Request) {// {{{ req := struct { Description string - Key string + Key string }{} if err = parseRequest(r, &req); err != nil { responseError(w, err) @@ -668,11 +678,11 @@ func keyCreate(w http.ResponseWriter, r *http.Request) {// {{{ } responseData(w, map[string]interface{}{ - "OK": true, + "OK": true, "Key": key, }) -}// }}} -func keyCounter(w http.ResponseWriter, r *http.Request) {// {{{ +} // }}} +func keyCounter(w http.ResponseWriter, r *http.Request) { // {{{ log.Println("/key/counter") var err error var session Session @@ -693,9 +703,9 @@ func keyCounter(w http.ResponseWriter, r *http.Request) {// {{{ // Javascript uses int32, thus getting a string counter for Javascript BigInt to parse. "Counter": strconv.FormatInt(counter, 10), }) -}// }}} +} // }}} -func newTemplate(requestPath string) (tmpl *template.Template, err error) {// {{{ +func newTemplate(requestPath string) (tmpl *template.Template, err error) { // {{{ // Append index.html if needed for further reading of the file p := requestPath if p[len(p)-1] == '/' { @@ -704,9 +714,11 @@ func newTemplate(requestPath string) (tmpl *template.Template, err error) {// {{ p = config.Application.Directories.Static + p base := path.Base(p) - if tmpl, err = template.New(base).ParseFiles(p); err != nil { return } + if tmpl, err = template.New(base).ParseFiles(p); err != nil { + return + } return -}// }}} +} // }}} // vim: foldmethod=marker diff --git a/version b/version new file mode 100644 index 0000000..958b5a3 --- /dev/null +++ b/version @@ -0,0 +1 @@ +v14