Compare commits
4 Commits
48e07c15d4
...
6cb4833dbd
Author | SHA1 | Date | |
---|---|---|---|
|
6cb4833dbd | ||
|
aef8f1a572 | ||
|
392aff5956 | ||
|
ac58fa0fc8 |
36
README.md
Normal file
36
README.md
Normal file
@ -0,0 +1,36 @@
|
||||
# Run from scratch
|
||||
|
||||
## Database
|
||||
|
||||
Create an empty database. The configured user needs to be able to create and alter stuff.
|
||||
|
||||
## Configuration
|
||||
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
|
||||
```
|
||||
|
||||
## User
|
||||
|
||||
Create a user by running
|
||||
```
|
||||
notes --createuser
|
||||
```
|
1
TODO
1
TODO
@ -4,7 +4,6 @@
|
||||
- per file
|
||||
- when deleting node and child nodes
|
||||
* Move node
|
||||
* Tree titles should be user-select none
|
||||
|
||||
|
||||
Long term
|
||||
|
4
db.go
4
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) {// {{{
|
||||
|
247
main.go
247
main.go
@ -3,8 +3,8 @@ package main
|
||||
import (
|
||||
// Standard
|
||||
"crypto/md5"
|
||||
"embed"
|
||||
"encoding/hex"
|
||||
"path/filepath"
|
||||
"flag"
|
||||
"fmt"
|
||||
"html/template"
|
||||
@ -13,41 +13,47 @@ 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
|
||||
flagVersion bool
|
||||
flagPort int
|
||||
flagVersion bool
|
||||
flagCreateUser 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.BoolVar(&flagCreateUser, "createuser", false, "Create a user and exit")
|
||||
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 +63,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)
|
||||
@ -68,27 +74,36 @@ func main() {// {{{
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if flagCreateUser {
|
||||
err = createUser()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
connectionManager = NewConnectionManager()
|
||||
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 +111,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 +129,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 +168,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 +178,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 +194,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 +211,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 +226,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 +244,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 +258,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 +272,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 +285,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 +299,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 +312,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 +327,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 +342,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 +357,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 +375,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 +387,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 +403,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 +430,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 +466,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 +511,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 +545,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 +581,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 +607,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 +637,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 +659,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 +675,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 +689,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 +714,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 +725,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
|
||||
|
@ -205,6 +205,7 @@ header .menu {
|
||||
#tree .node .name {
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
#tree .node .name:hover {
|
||||
color: #ecbf00;
|
||||
|
@ -232,6 +232,7 @@ header {
|
||||
.name {
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
color: @accent_2;
|
||||
|
42
user.go
42
user.go
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
// Standard
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (session Session) UpdatePassword(currPass, newPass string) (ok bool, err error) {
|
||||
@ -24,9 +25,9 @@ func (session Session) UpdatePassword(currPass, newPass string) (ok bool, err er
|
||||
password=password_hash(SUBSTRING(password FROM 1 FOR 32), $3::bytea)
|
||||
RETURNING id
|
||||
`,
|
||||
newPass,
|
||||
session.UserID,
|
||||
currPass,
|
||||
newPass,
|
||||
session.UserID,
|
||||
currPass,
|
||||
)
|
||||
|
||||
if rowsAffected, err = result.RowsAffected(); err != nil {
|
||||
@ -35,3 +36,38 @@ func (session Session) UpdatePassword(currPass, newPass string) (ok bool, err er
|
||||
|
||||
return rowsAffected > 0, nil
|
||||
}
|
||||
|
||||
func createUser() (err error) {
|
||||
var username, password string
|
||||
fmt.Printf("Username: ")
|
||||
fmt.Scanln(&username)
|
||||
fmt.Printf("Password: ")
|
||||
fmt.Scanln(&password)
|
||||
|
||||
err = CreateDbUser(username, password)
|
||||
return
|
||||
}
|
||||
|
||||
func CreateDbUser(username string, password string) (err error) {
|
||||
var result sql.Result
|
||||
|
||||
result, err = db.Exec(`
|
||||
INSERT INTO public.user(username, password)
|
||||
VALUES(
|
||||
$1,
|
||||
password_hash(
|
||||
/* salt in hex */
|
||||
ENCODE(gen_random_bytes(16), 'hex'),
|
||||
|
||||
/* password */
|
||||
$2::bytea
|
||||
)
|
||||
)
|
||||
`,
|
||||
username,
|
||||
password,
|
||||
)
|
||||
|
||||
_, err = result.RowsAffected()
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user