Compare commits

...

4 Commits

Author SHA1 Message Date
Magnus Åhall
6cb4833dbd Added structure to readme 2023-12-28 08:13:21 +01:00
Magnus Åhall
aef8f1a572 Create a user from command line 2023-12-28 08:08:59 +01:00
Magnus Åhall
392aff5956 Version handling from file 2023-12-28 07:47:23 +01:00
Magnus Åhall
ac58fa0fc8 Tree nodes aren't selectable 2023-07-22 10:50:24 +02:00
8 changed files with 213 additions and 120 deletions

36
README.md Normal file
View 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
View File

@ -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
View File

@ -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) {// {{{

57
main.go
View File

@ -3,8 +3,8 @@ package main
import (
// Standard
"crypto/md5"
"embed"
"encoding/hex"
"path/filepath"
"flag"
"fmt"
"html/template"
@ -13,34 +13,40 @@ 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
flagCreateUser bool
flagConfig string
connectionManager ConnectionManager
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")
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 {
@ -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,6 +74,15 @@ 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()
@ -100,7 +115,11 @@ func main() {// {{{
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" })
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
@ -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
@ -444,7 +466,6 @@ 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)
@ -704,7 +725,9 @@ 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
} // }}}

View File

@ -205,6 +205,7 @@ header .menu {
#tree .node .name {
white-space: nowrap;
cursor: pointer;
user-select: none;
}
#tree .node .name:hover {
color: #ecbf00;

View File

@ -232,6 +232,7 @@ header {
.name {
white-space: nowrap;
cursor: pointer;
user-select: none;
&:hover {
color: @accent_2;

36
user.go
View File

@ -3,6 +3,7 @@ package main
import (
// Standard
"database/sql"
"fmt"
)
func (session Session) UpdatePassword(currPass, newPass string) (ok bool, err error) {
@ -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
}

1
version Normal file
View File

@ -0,0 +1 @@
v14