Compare commits

..

2 Commits

Author SHA1 Message Date
2247f316a3 Added ability to add user 2024-02-24 10:28:12 +01:00
9beedf9b2b Added ability to login 2024-02-24 09:54:25 +01:00
11 changed files with 178 additions and 77 deletions

View File

@ -35,16 +35,6 @@ func OpenDB(dbName string) (*DB, error) {
} }
func (db *DB) AddUser(user, pass, first, last string, writer, editor, admin bool) error { func (db *DB) AddUser(user, pass, first, last string, writer, editor, admin bool) error {
userString, stringLen, ok := checkUserStrings(user, first, last)
if !ok {
return fmt.Errorf("error: %v is longer than %v characters", userString, stringLen)
}
if !permissionsOK(writer, editor, admin) {
return fmt.Errorf("error: permissions must be mutually exclusive: writer = %v, editor = %v, admin = %v",
writer, editor, admin)
}
hashedPass, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) hashedPass, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost)
if err != nil { if err != nil {
return fmt.Errorf("error creating password hash: %v", err) return fmt.Errorf("error creating password hash: %v", err)
@ -64,21 +54,46 @@ func (db *DB) AddUser(user, pass, first, last string, writer, editor, admin bool
return nil return nil
} }
func (db *DB) ChangePassword(id int64, oldPass, newPass string) error { func (db *DB) GetID(user string) (int64, error) {
var oldHashedPass string var id int64
selectQuery := ` query := `
SELECT id FROM
users
WHERE
username = ?
`
row := db.QueryRow(query, user)
if err := row.Scan(&id); err != nil {
return 0, fmt.Errorf("user not in DB: %v", err)
}
return id, nil
}
func (db *DB) CheckPassword(id int64, pass string) error {
var queriedPass string
query := `
SELECT password FROM SELECT password FROM
users users
WHERE WHERE
id = ? id = ?
` `
row := db.QueryRow(selectQuery, id) row := db.QueryRow(query, id)
if err := row.Scan(&oldHashedPass); err != nil { if err := row.Scan(&queriedPass); err != nil {
return fmt.Errorf("error reading password from DB: %v", err) return fmt.Errorf("error reading password from DB: %v", err)
} }
if err := bcrypt.CompareHashAndPassword([]byte(oldHashedPass), []byte(oldPass)); err != nil { if err := bcrypt.CompareHashAndPassword([]byte(queriedPass), []byte(pass)); err != nil {
return fmt.Errorf("incorrect password: %v", err)
}
return nil
}
func (db *DB) ChangePassword(id int64, oldPass, newPass string) error {
if err := db.CheckPassword(id, oldPass); err != nil {
return fmt.Errorf("error checking password: %v", err) return fmt.Errorf("error checking password: %v", err)
} }
@ -88,9 +103,10 @@ func (db *DB) ChangePassword(id int64, oldPass, newPass string) error {
} }
updateQuery := ` updateQuery := `
UPDATE users UPDATE users SET
SET password = ? password = ?
WHERE id = ? WHERE
id = ?
` `
_, err = db.Exec(updateQuery, string(newHashedPass), id) _, err = db.Exec(updateQuery, string(newHashedPass), id)
if err != nil { if err != nil {

View File

@ -50,24 +50,3 @@ func getCredentials() (string, string, error) {
return user, pass, nil return user, pass, nil
} }
func checkUserStrings(user, first, last string) (string, int, bool) {
userLen := 15
nameLen := 50
if len(user) > userLen {
return user, userLen, false
} else if len(first) > nameLen {
return first, nameLen, false
} else if len(last) > nameLen {
return last, nameLen, false
} else {
return "", 0, true
}
}
func permissionsOK(writer, editor, admin bool) bool {
return writer && !editor && !admin ||
!writer && editor && !admin ||
!writer && !editor && admin
}

View File

@ -1,4 +1,4 @@
package articles package data
import ( import (
"bytes" "bytes"

View File

@ -1,27 +0,0 @@
package handlers
import (
"log"
"net/http"
"streifling.com/jason/cpolis/cmd/articles"
"streifling.com/jason/cpolis/cmd/feed"
)
func HandleFinishedEdit(f *feed.Feed) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
title := r.PostFormValue("editor-title")
desc := r.PostFormValue("editor-desc")
mdContent := r.PostFormValue("editor-text")
content, err := articles.ConvertToHTML(mdContent)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
log.Panicln(err)
}
feed.AddToFeed(f, title, desc, content)
feed.SaveFeed(f, "tmp/rss.gob")
// template.Must(template.ParseFiles("web/templates/editor.html")).ExecuteTemplate(w, "html-result", rssItem)
}
}

16
cmd/ui/helpers.go Normal file
View File

@ -0,0 +1,16 @@
package ui
func checkUserStrings(user, first, last string) (string, int, bool) {
userLen := 15
nameLen := 50
if len(user) > userLen {
return user, userLen, false
} else if len(first) > nameLen {
return first, nameLen, false
} else if len(last) > nameLen {
return last, nameLen, false
} else {
return "", 0, true
}
}

1
cmd/ui/htmlStructs.go Normal file
View File

@ -0,0 +1 @@
package ui

87
cmd/ui/ui.go Normal file
View File

@ -0,0 +1,87 @@
package ui
import (
"html/template"
"log"
"net/http"
"streifling.com/jason/cpolis/cmd/data"
"streifling.com/jason/cpolis/cmd/feed"
)
func HandleLogin(db *data.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user := r.PostFormValue("username")
pass := r.PostFormValue("password")
id, err := db.GetID(user)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
// TODO: und nun?
}
if err := db.CheckPassword(id, pass); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else {
template.Must(template.ParseFiles("web/templates/editor.html")).ExecuteTemplate(w, "page-content", nil)
}
}
}
func HandleFinishedEdit(f *feed.Feed) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
title := r.PostFormValue("editor-title")
desc := r.PostFormValue("editor-desc")
mdContent := r.PostFormValue("editor-text")
content, err := data.ConvertToHTML(mdContent)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
log.Panicln(err)
}
feed.AddToFeed(f, title, desc, content)
feed.SaveFeed(f, "tmp/rss.gob")
// template.Must(template.ParseFiles("web/templates/editor.html")).ExecuteTemplate(w, "html-result", rssItem)
}
}
func HandleAddUser(db *data.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var writer, editor, admin bool
user := r.PostFormValue("username")
pass := r.PostFormValue("password")
pass2 := r.PostFormValue("password2")
first := r.PostFormValue("first-name")
last := r.PostFormValue("last-name")
role := r.PostFormValue("role")
_, _, ok := checkUserStrings(user, first, last)
if !ok {
template.Must(template.ParseFiles("web/templates/add-user.html")).Execute(w, nil)
}
if pass != pass2 {
template.Must(template.ParseFiles("web/templates/add-user.html")).Execute(w, nil)
}
switch role {
case "writer":
writer = true
editor = false
admin = false
case "editor":
writer = false
editor = true
admin = false
case "admin":
writer = false
editor = false
admin = true
default:
template.Must(template.ParseFiles("web/templates/add-user.html")).Execute(w, nil)
}
db.AddUser(user, pass, first, last, writer, editor, admin)
template.Must(template.ParseFiles("web/templates/editor.html")).Execute(w, nil)
}
}

11
main.go
View File

@ -7,7 +7,7 @@ import (
"streifling.com/jason/cpolis/cmd/data" "streifling.com/jason/cpolis/cmd/data"
"streifling.com/jason/cpolis/cmd/feed" "streifling.com/jason/cpolis/cmd/feed"
"streifling.com/jason/cpolis/cmd/handlers" "streifling.com/jason/cpolis/cmd/ui"
) )
func main() { func main() {
@ -17,10 +17,10 @@ func main() {
} }
defer db.Close() defer db.Close()
f, err := feed.OpenFeed("tmp/rss.gob") rss, err := feed.OpenFeed("tmp/rss.gob")
if err != nil { if err != nil {
log.Println(err) log.Println(err)
f = feed.NewFeed("Freimaurer Distrikt Niedersachsen und Sachsen-Anhalt", rss = feed.NewFeed("Freimaurer Distrikt Niedersachsen und Sachsen-Anhalt",
"https://distrikt-ni-st.de", "https://distrikt-ni-st.de",
"Freiheit, Gleichheit, Brüderlichkeit, Toleranz und Humanität") "Freiheit, Gleichheit, Brüderlichkeit, Toleranz und Humanität")
} }
@ -28,9 +28,10 @@ func main() {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.Handle("/web/static/", http.StripPrefix("/web/static/", http.FileServer(http.Dir("web/static/")))) mux.Handle("/web/static/", http.StripPrefix("/web/static/", http.FileServer(http.Dir("web/static/"))))
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
template.Must(template.ParseFiles("web/templates/index.html", "web/templates/editor.html")).Execute(w, nil) template.Must(template.ParseFiles("web/templates/index.html", "web/templates/login.html")).Execute(w, nil)
}) })
mux.HandleFunc("POST /finished-edit/", handlers.HandleFinishedEdit(f)) mux.HandleFunc("POST /login/", ui.HandleLogin(db))
mux.HandleFunc("POST /finished-edit/", ui.HandleFinishedEdit(rss))
log.Fatalln(http.ListenAndServe(":8080", mux)) log.Fatalln(http.ListenAndServe(":8080", mux))
} }

View File

@ -0,0 +1,19 @@
{{define "page-content"}}
<form>
<input name="username" placeholder="Benutzername" type="text" />
<input name="password" placeholder="Passwort" type="password" />
<input name="password2" placeholder="Passwort wiederholen" type="password" />
<input name="first-name" placeholder="Vorname" type="text" />
<input name="last-name" placeholder="Nachname" type="text" />
<label for="writer">Schreiber</label>
<input id="writer" name="role" type="radio" value="writer" />
<label for="editor">Redakteur</label>
<input id="editor" name="role" type="radio" value="editor" />
<label for="admin">Admin</label>
<input id="admin" name="role" type="radio" value="admin" />
<input type="submit" value="Anlegen" hx-post="/add-user/" hx-target="#page-content" />
</form>
{{end}}

View File

@ -1,9 +1,10 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Editor</h2>
<form> <form>
<input type="text" name="editor-title" value="Titel"> <input name="editor-title" placeholder="Titel" type="text" />
<textarea name="editor-desc"></textarea> <textarea name="editor-desc" placeholder="Beschreibung"></textarea>
<textarea name="editor-text"></textarea> <textarea name="editor-text" placeholder="Artikel"></textarea>
<input type="submit" value="Senden" hx-post="/finished-edit/" hx-target="#page-content"> <input type="submit" value="Senden" hx-post="/finished-edit/" hx-target="#page-content" />
</form> </form>
{{end}} {{end}}

8
web/templates/login.html Normal file
View File

@ -0,0 +1,8 @@
{{define "page-content"}}
<h2>Anmeldung</h2>
<form>
<input name="username" placeholder="Benutzername" type="text" />
<input name="password" placeholder="Passwort" type="password" />
<input type="submit" value="Anmelden" hx-post="/login/" hx-target="#page-content" />
</form>
{{end}}