Incorporated issues

This commit is contained in:
Jason Streifling 2024-03-28 07:00:37 +01:00
parent 304d3aa2e0
commit 78addbd8e3
11 changed files with 365 additions and 61 deletions

View File

@ -50,6 +50,7 @@ func main() {
mux.HandleFunc("GET /edit-user/", view.EditUser(db, store)) mux.HandleFunc("GET /edit-user/", view.EditUser(db, store))
mux.HandleFunc("GET /hub/", view.ShowHub(db, store)) mux.HandleFunc("GET /hub/", view.ShowHub(db, store))
mux.HandleFunc("GET /logout/", view.Logout(store)) mux.HandleFunc("GET /logout/", view.Logout(store))
mux.HandleFunc("GET /publish-issue/", view.PublishLatestIssue(db))
mux.HandleFunc("GET /rejected-articles/", view.ShowRejectedArticles(db, store)) mux.HandleFunc("GET /rejected-articles/", view.ShowRejectedArticles(db, store))
mux.HandleFunc("GET /rss/", view.ShowRSS( mux.HandleFunc("GET /rss/", view.ShowRSS(
db, db,
@ -57,6 +58,7 @@ func main() {
"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",
)) ))
mux.HandleFunc("GET /this-issue/", view.ShowCurrentArticles(db))
mux.HandleFunc("GET /unpublished-articles/", view.ShowUnpublishedArticles(db)) mux.HandleFunc("GET /unpublished-articles/", view.ShowUnpublishedArticles(db))
mux.HandleFunc("GET /write-article/", view.WriteArticle(db)) mux.HandleFunc("GET /write-article/", view.WriteArticle(db))

View File

@ -1,7 +1,10 @@
package model package model
import ( import (
"context"
"database/sql"
"fmt" "fmt"
"log"
"time" "time"
) )
@ -14,26 +17,64 @@ type Article struct {
Rejected bool Rejected bool
ID int64 ID int64
AuthorID int64 AuthorID int64
IssueID int64
} }
func (db *DB) AddArticle(a *Article) (int64, error) { func (db *DB) AddArticle(a *Article) (int64, error) {
query := ` var id int64
txOptions := &sql.TxOptions{Isolation: sql.LevelSerializable}
selectQuery := "SELECT id FROM issues WHERE published = false"
insertQuery := `
INSERT INTO articles INSERT INTO articles
(title, description, content, published, rejected, author_id) (title, description, content, published, rejected, author_id, issue_id)
VALUES (?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?)
` `
result, err := db.Exec(query, a.Title, a.Description, a.Content, for i := 0; i < TxMaxRetries; i++ {
a.Published, a.Rejected, a.AuthorID) id, err := func() (int64, error) {
tx, err := db.BeginTx(context.Background(), txOptions)
if err != nil { if err != nil {
return 0, fmt.Errorf("error inserting article into DB: %v", err) return 0, fmt.Errorf("error starting transaction: %v", err)
}
id, err := result.LastInsertId()
if err != nil {
return 0, fmt.Errorf("error retrieving last ID: %v", err)
} }
if err = tx.QueryRow(selectQuery).Scan(&id); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return 0, fmt.Errorf("error getting issue ID when adding article to DB: %v", err)
}
result, err := tx.Exec(insertQuery, a.Title, a.Description,
a.Content, a.Published, a.Rejected, a.AuthorID, id)
if err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return 0, fmt.Errorf("error inserting article into DB: %v", err)
}
id, err := result.LastInsertId()
if err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return 0, fmt.Errorf("error retrieving ID of added article: %v", err)
}
if err = tx.Commit(); err != nil {
return 0, fmt.Errorf("error committing transaction when adding article to DB: %v", err)
}
return id, nil return id, nil
}()
if err == nil {
return id, nil
}
log.Println(err)
wait(i)
}
return 0, fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
} }
func (db *DB) GetArticle(id int64) (*Article, error) { func (db *DB) GetArticle(id int64) (*Article, error) {
@ -79,8 +120,8 @@ func (db *DB) GetCertainArticles(published, rejected bool) ([]*Article, error) {
article := new(Article) article := new(Article)
var created []byte var created []byte
if err = rows.Scan(&article.ID, &article.Title, &created, &article.Description, if err = rows.Scan(&article.ID, &article.Title, &created,
&article.Content, &article.AuthorID); err != nil { &article.Description, &article.Content, &article.AuthorID); err != nil {
return nil, fmt.Errorf("error scanning article row: %v", err) return nil, fmt.Errorf("error scanning article row: %v", err)
} }
@ -95,3 +136,122 @@ func (db *DB) GetCertainArticles(published, rejected bool) ([]*Article, error) {
return articleList, nil return articleList, nil
} }
func (db *DB) GetCurrentIssueArticles() ([]*Article, error) {
var issueID int64
txOptions := &sql.TxOptions{Isolation: sql.LevelSerializable}
issueQuery := "SELECT id FROM issues WHERE published = false"
articlesQuery := `
SELECT id, title, created, description, content, author_id
FROM articles
WHERE issue_id = ? AND published = true
`
for i := 0; i < TxMaxRetries; i++ {
id, err := func() ([]*Article, error) {
tx, err := db.BeginTx(context.Background(), txOptions)
if err != nil {
return nil, fmt.Errorf("error starting transaction: %v", err)
}
row := tx.QueryRow(issueQuery)
if err := row.Scan(&issueID); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return nil, fmt.Errorf("error querying DB for unpublished issue: %v", err)
}
rows, err := tx.Query(articlesQuery, issueID)
if err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return nil, fmt.Errorf("error querying DB for articles of issue %v: %v", issueID, err)
}
articleList := make([]*Article, 0)
for rows.Next() {
article := new(Article)
var created []byte
if err = rows.Scan(&article.ID, &article.Title, &created,
&article.Description, &article.Content, &article.AuthorID); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return nil, fmt.Errorf("error scanning article from issue %v: %v", issueID, err)
}
article.Created, err = time.Parse("2006-01-02 15:04:05", string(created))
if err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return nil, fmt.Errorf("error parsing created: %v", err)
}
articleList = append(articleList, article)
}
if err = tx.Commit(); err != nil {
return nil, fmt.Errorf("error committing transaction when getting articles of issue %v: %v", issueID, err)
}
return articleList, nil
}()
if err == nil {
return id, nil
}
log.Println(err)
wait(i)
}
return nil, fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
}
func (db *DB) AddArticleToCurrentIssue(id int64) error {
var issueID int64
txOptions := &sql.TxOptions{Isolation: sql.LevelSerializable}
selectQuery := "SELECT id FROM issues WHERE published = false"
updateQuery := "UPDATE articles SET issue_id = ? WHERE id = ?"
for i := 0; i < TxMaxRetries; i++ {
err := func() error {
tx, err := db.BeginTx(context.Background(), txOptions)
if err != nil {
return fmt.Errorf("error starting transaction: %v", err)
}
if err = tx.QueryRow(selectQuery).Scan(&issueID); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return fmt.Errorf("error scanning row: %v", err)
}
_, err = db.Exec(updateQuery, issueID, id)
if err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return fmt.Errorf("error updating issueID for article: %v", err)
}
if err = tx.Commit(); err != nil {
return fmt.Errorf("error committing transaction when getting articles of issue %v: %v", issueID, err)
}
return nil
}()
if err == nil {
return nil
}
log.Println(err)
wait(i)
}
return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
}

View File

@ -3,12 +3,14 @@ package model
import ( import (
"fmt" "fmt"
"log" "log"
"math"
"math/rand/v2"
"time"
) )
func (db *DB) WriteArticleTags(articleID int64, tagIDs []int64) error { func (db *DB) WriteArticleTags(articleID int64, tagIDs []int64) error {
query := `
INSERT INTO articles_tags (article_id, tag_id)
VALUES (?, ?)
`
for i := 0; i < TxMaxRetries; i++ { for i := 0; i < TxMaxRetries; i++ {
err := func() error { err := func() error {
tx, err := db.Begin() tx, err := db.Begin()
@ -17,13 +19,9 @@ func (db *DB) WriteArticleTags(articleID int64, tagIDs []int64) error {
} }
for _, tagID := range tagIDs { for _, tagID := range tagIDs {
query := `
INSERT INTO articles_tags (article_id, tag_id)
VALUES (?, ?)
`
if _, err := tx.Exec(query, articleID, tagID); err != nil { if _, err := tx.Exec(query, articleID, tagID); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("error: transaction error: %v, rollback error: %v", err, rollbackErr) log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
} }
return fmt.Errorf("error inserting into articles_tags: %v", err) return fmt.Errorf("error inserting into articles_tags: %v", err)
} }
@ -39,9 +37,7 @@ func (db *DB) WriteArticleTags(articleID int64, tagIDs []int64) error {
} }
log.Println(err) log.Println(err)
waitTime := time.Duration(math.Pow(2, float64(i))) * time.Second wait(i)
jitter := time.Duration(rand.IntN(1000)) * time.Millisecond
time.Sleep(waitTime + jitter)
} }
return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries) return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
} }
@ -70,3 +66,29 @@ func (db *DB) GetArticleTags(articleID int64) ([]*Tag, error) {
return tags, nil return tags, nil
} }
func (db *DB) UpdateArticleTags(articleID int64, tagIDs []int64) error {
query := `
`
for i := 0; i < TxMaxRetries; i++ {
err := func() error {
tx, err := db.Begin()
if err != nil {
return fmt.Errorf("error starting transaction: %v", err)
}
if err = tx.Commit(); err != nil {
return fmt.Errorf("error committing transaction: %v", err)
}
return nil
}()
if err == nil {
return nil
}
log.Println(err)
wait(i)
}
return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
}

66
cmd/model/issues.go Normal file
View File

@ -0,0 +1,66 @@
package model
import (
"context"
"database/sql"
"fmt"
"log"
)
func (db *DB) AddIssue() (int64, error) {
query := "INSERT INTO issues (published) VALUES (?)"
result, err := db.Exec(query, false)
if err != nil {
return 0, fmt.Errorf("error inserting issue into DB: %v", err)
}
id, err := result.LastInsertId()
if err != nil {
return 0, fmt.Errorf("error getting ID of added issue: %v", err)
}
return id, nil
}
func (db *DB) PublishLatestIssue() error {
var id int64
txOptions := &sql.TxOptions{Isolation: sql.LevelSerializable}
updateQuery := "UPDATE issues SET published = true WHERE published = false"
insertQuery := "INSERT INTO issues (published) VALUES (?)"
for i := 0; i < TxMaxRetries; i++ {
err := func() error {
tx, err := db.BeginTx(context.Background(), txOptions)
if err != nil {
return fmt.Errorf("error starting transaction: %v", err)
}
if _, err := tx.Exec(updateQuery, id); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return fmt.Errorf("error publishing issue: %v", err)
}
if _, err := tx.Exec(insertQuery, false); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
}
return fmt.Errorf("error inserting new issue into DB: %v", err)
}
if err = tx.Commit(); err != nil {
return fmt.Errorf("error committing transaction when publishing issue: %v", err)
}
return nil
}()
if err == nil {
return nil
}
log.Println(err)
wait(i)
}
return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
}

View File

@ -3,17 +3,15 @@ package model
import ( import (
"fmt" "fmt"
"log" "log"
"math"
"math/rand/v2"
"time"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
const ( const (
Admin = iota Admin = iota
Publisher
Editor Editor
Writer Author
) )
type User struct { type User struct {
@ -24,21 +22,26 @@ type User struct {
Role int Role int
} }
func (db *DB) AddUser(user *User, pass string) error { func (db *DB) AddUser(u *User, pass string) (int64, error) {
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 0, fmt.Errorf("error creating password hash: %v", err)
} }
query := ` query := `
INSERT INTO users (username, password, first_name, last_name, role) INSERT INTO users (username, password, first_name, last_name, role)
VALUES (?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?)
` `
if _, err = db.Exec(query, user.UserName, string(hashedPass), user.FirstName, user.LastName, user.Role); err != nil { result, err := db.Exec(query, u.UserName, string(hashedPass), u.FirstName, u.LastName, u.Role)
return fmt.Errorf("error inserting user into DB: %v", err) if err != nil {
return 0, fmt.Errorf("error inserting new user %v into DB: %v", u.UserName, err)
}
id, err := result.LastInsertId()
if err != nil {
return 0, fmt.Errorf("error inserting user into DB: %v", err)
} }
return nil return id, nil
} }
func (db *DB) GetID(userName string) (int64, bool) { func (db *DB) GetID(userName string) (int64, bool) {
@ -87,14 +90,14 @@ func (tx *Tx) ChangePassword(id int64, oldPass, newPass string) error {
row := tx.QueryRow(getQuery, id) row := tx.QueryRow(getQuery, id)
if err := row.Scan(&queriedPass); err != nil { if err := row.Scan(&queriedPass); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("error: transaction error: %v, rollback error: %v", err, rollbackErr) log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
} }
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(queriedPass), []byte(oldPass)); err != nil { if err := bcrypt.CompareHashAndPassword([]byte(queriedPass), []byte(oldPass)); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("error: transaction error: %v, rollback error: %v", err, rollbackErr) log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
} }
return fmt.Errorf("incorrect password: %v", err) return fmt.Errorf("incorrect password: %v", err)
} }
@ -102,7 +105,7 @@ func (tx *Tx) ChangePassword(id int64, oldPass, newPass string) error {
newHashedPass, err := bcrypt.GenerateFromPassword([]byte(newPass), bcrypt.DefaultCost) newHashedPass, err := bcrypt.GenerateFromPassword([]byte(newPass), bcrypt.DefaultCost)
if err != nil { if err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("error: transaction error: %v, rollback error: %v", err, rollbackErr) log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
} }
return fmt.Errorf("error creating password hash: %v", err) return fmt.Errorf("error creating password hash: %v", err)
} }
@ -114,7 +117,7 @@ func (tx *Tx) ChangePassword(id int64, oldPass, newPass string) error {
` `
if _, err = tx.Exec(setQuery, string(newHashedPass), id); err != nil { if _, err = tx.Exec(setQuery, string(newHashedPass), id); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("error: transaction error: %v, rollback error: %v", err, rollbackErr) log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
} }
return fmt.Errorf("error updating password in DB: %v", err) return fmt.Errorf("error updating password in DB: %v", err)
} }
@ -132,7 +135,8 @@ func (db *DB) GetUser(id int64) (*User, error) {
` `
row := db.QueryRow(query, id) row := db.QueryRow(query, id)
if err := row.Scan(&user.ID, &user.UserName, &user.FirstName, &user.LastName, &user.Role); err != nil { if err := row.Scan(&user.ID, &user.UserName, &user.FirstName,
&user.LastName, &user.Role); err != nil {
return nil, fmt.Errorf("error reading user information: %v", err) return nil, fmt.Errorf("error reading user information: %v", err)
} }
@ -161,7 +165,7 @@ func (db *DB) UpdateUserAttributes(id int64, user, first, last, oldPass, newPass
if !passwordEmpty { if !passwordEmpty {
if err = tx.ChangePassword(id, oldPass, newPass); err != nil { if err = tx.ChangePassword(id, oldPass, newPass); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("error: transaction error: %v, rollback error: %v", err, rollbackErr) log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
} }
return fmt.Errorf("error changing password: %v", err) return fmt.Errorf("error changing password: %v", err)
} }
@ -173,7 +177,7 @@ func (db *DB) UpdateUserAttributes(id int64, user, first, last, oldPass, newPass
&Attribute{Table: "users", ID: id, AttName: "last_name", Value: last}, &Attribute{Table: "users", ID: id, AttName: "last_name", Value: last},
); err != nil { ); err != nil {
if rollbackErr := tx.Rollback(); rollbackErr != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil {
log.Fatalf("error: transaction error: %v, rollback error: %v", err, rollbackErr) log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
} }
return fmt.Errorf("error updating attributes in DB: %v", err) return fmt.Errorf("error updating attributes in DB: %v", err)
} }
@ -189,9 +193,7 @@ func (db *DB) UpdateUserAttributes(id int64, user, first, last, oldPass, newPass
} }
log.Println(err) log.Println(err)
waitTime := time.Duration(math.Pow(2, float64(i))) * time.Second wait(i)
jitter := time.Duration(rand.IntN(1000)) * time.Millisecond
time.Sleep(waitTime + jitter)
} }
return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries) return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)

View File

@ -272,6 +272,12 @@ func PublishArticle(db *model.DB, s *control.CookieStore) http.HandlerFunc {
template.Must(tmpl, err).ExecuteTemplate(w, "page-content", msg) template.Must(tmpl, err).ExecuteTemplate(w, "page-content", msg)
} }
if err = db.AddArticleToCurrentIssue(id); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err = db.UpdateAttributes( if err = db.UpdateAttributes(
&model.Attribute{Table: "articles", ID: id, AttName: "published", Value: true}, &model.Attribute{Table: "articles", ID: id, AttName: "published", Value: true},
&model.Attribute{Table: "articles", ID: id, AttName: "rejected", Value: false}, &model.Attribute{Table: "articles", ID: id, AttName: "rejected", Value: false},
@ -317,3 +323,30 @@ func RejectArticle(db *model.DB, s *control.CookieStore) http.HandlerFunc {
tmpl.ExecuteTemplate(w, "page-content", session.Values["role"]) tmpl.ExecuteTemplate(w, "page-content", session.Values["role"])
} }
} }
func ShowCurrentArticles(db *model.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
articles, err := db.GetCurrentIssueArticles()
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tmpl, err := template.ParseFiles("web/templates/current-articles.html")
template.Must(tmpl, err).ExecuteTemplate(w, "page-content", articles)
}
}
func PublishLatestIssue(db *model.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := db.PublishLatestIssue(); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tmpl, err := template.ParseFiles("web/templates/hub.html")
template.Must(tmpl, err).ExecuteTemplate(w, "page-content", nil)
}
}

View File

@ -1,6 +1,7 @@
package view package view
import ( import (
"fmt"
"html/template" "html/template"
"log" "log"
"net/http" "net/http"
@ -38,6 +39,7 @@ func ShowRSS(db *model.DB, title, link, desc string) http.HandlerFunc {
for _, tag := range tags { for _, tag := range tags {
tagNames = append(tagNames, tag.Name) tagNames = append(tagNames, tag.Name)
} }
tagNames = append(tagNames, fmt.Sprint("Orient Express ", article.IssueID))
user, err := db.GetUser(article.AuthorID) user, err := db.GetUser(article.AuthorID)
if err != nil { if err != nil {

View File

@ -86,19 +86,21 @@ func AddUser(db *model.DB, s *control.CookieStore) http.HandlerFunc {
return return
} }
num, err := db.CountEntries("users") htmlData.ID, err = db.AddUser(htmlData.User, pass)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
if num == 0 {
if htmlData.Role != model.Admin { if htmlData.ID == 1 {
htmlData.Msg = "Der erste Benutzer muss ein Administrator sein."
htmlData.Role = model.Admin htmlData.Role = model.Admin
tmpl, err := template.ParseFiles("web/templates/add-user.html")
tmpl = template.Must(tmpl, err) if err = db.UpdateAttributes(
tmpl.ExecuteTemplate(w, "page-content", htmlData) &model.Attribute{Table: "users", ID: id, AttName: "role", Value: htmlData.Role},
); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
@ -107,13 +109,13 @@ func AddUser(db *model.DB, s *control.CookieStore) http.HandlerFunc {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
}
if err := db.AddUser(htmlData.User, pass); err != nil { if _, err := db.AddIssue(); err != nil {
log.Println(err) log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
}
tmpl, err := template.ParseFiles("web/templates/hub.html") tmpl, err := template.ParseFiles("web/templates/hub.html")
template.Must(tmpl, err).ExecuteTemplate(w, "page-content", 0) template.Must(tmpl, err).ExecuteTemplate(w, "page-content", 0)

View File

@ -8,10 +8,12 @@
<input required name="first-name" placeholder="Vorname" type="text" value="{{.FirstName}}" /> <input required name="first-name" placeholder="Vorname" type="text" value="{{.FirstName}}" />
<input required name="last-name" placeholder="Nachname" type="text" value="{{.LastName}}" /> <input required name="last-name" placeholder="Nachname" type="text" value="{{.LastName}}" />
<input required id="writer" name="role" type="radio" value="2" {{if eq .Role 2 }}checked{{end}} /> <input required id="author" name="role" type="radio" value="3" {{if eq .Role 3 }}checked{{end}} />
<label for="writer">Schreiber</label> <label for="author">Autor</label>
<input required id="editor" name="role" type="radio" value="1" {{if eq .Role 1 }}checked{{end}} /> <input required id="editor" name="role" type="radio" value="2" {{if eq .Role 2 }}checked{{end}} />
<label for="editor">Redakteur</label> <label for="editor">Redakteur</label>
<input required id="publisher" name="role" type="radio" value="1" {{if eq .Role 1 }}checked{{end}} />
<label for="publisher">Herausgeber</label>
<input required id="admin" name="role" type="radio" value="0" {{if eq .Role 0 }}checked{{end}} /> <input required id="admin" name="role" type="radio" value="0" {{if eq .Role 0 }}checked{{end}} />
<label for="admin">Admin</label> <label for="admin">Admin</label>

View File

@ -0,0 +1,10 @@
{{define "page-content"}}
{{range .}}
<div>
<h1>{{.Title}}</h1>
<p>{{.Description}}</p>
</div>
{{end}}
<button hx-get="/publish-issue/" hx-target="#page-content">Ausgabe publizieren</button>
<button hx-get="/hub/" hx-target="#page-content">Abbrechen</button>
{{end}}

View File

@ -4,10 +4,13 @@
<button hx-get="/rejected-articles/" hx-target="#page-content">Abgelehnte Artikel</button> <button hx-get="/rejected-articles/" hx-target="#page-content">Abgelehnte Artikel</button>
<button hx-get="/rss/" hx-target="#page-content">RSS Feed</button> <button hx-get="/rss/" hx-target="#page-content">RSS Feed</button>
<button hx-get="/edit-user/" hx-target="#page-content">Benutzer bearbeiten</button> <button hx-get="/edit-user/" hx-target="#page-content">Benutzer bearbeiten</button>
{{if lt . 2}} {{if lt . 3}}
<button hx-get="/unpublished-articles/" hx-target="#page-content">Unveröffentlichte Artikel</button> <button hx-get="/unpublished-articles/" hx-target="#page-content">Unveröffentlichte Artikel</button>
<button hx-get="/create-tag/" hx-target="#page-content">Neuer Tag</button> <button hx-get="/create-tag/" hx-target="#page-content">Neuer Tag</button>
{{end}} {{end}}
{{if lt . 2}}
<button hx-get="/this-issue/" hx-target="#page-content">Diese Ausgabe</button>
{{end}}
{{if eq . 0}} {{if eq . 0}}
<button hx-get="/create-user/" hx-target="#page-content">Benutzer hinzufügen</button> <button hx-get="/create-user/" hx-target="#page-content">Benutzer hinzufügen</button>
{{end}} {{end}}