Added ability to delete other users
This commit is contained in:
		@@ -53,6 +53,7 @@ func main() {
 | 
				
			|||||||
	mux.HandleFunc("GET /create-user", view.CreateUser(config))
 | 
						mux.HandleFunc("GET /create-user", view.CreateUser(config))
 | 
				
			||||||
	mux.HandleFunc("GET /edit-self", view.EditSelf(config, db, store))
 | 
						mux.HandleFunc("GET /edit-self", view.EditSelf(config, db, store))
 | 
				
			||||||
	mux.HandleFunc("GET /edit-user/{id}", view.EditUser(config, db))
 | 
						mux.HandleFunc("GET /edit-user/{id}", view.EditUser(config, db))
 | 
				
			||||||
 | 
						mux.HandleFunc("GET /delete-user/{id}", view.DeleteUser(config, db, store))
 | 
				
			||||||
	mux.HandleFunc("GET /hub", view.ShowHub(config, db, store))
 | 
						mux.HandleFunc("GET /hub", view.ShowHub(config, db, store))
 | 
				
			||||||
	mux.HandleFunc("GET /logout", view.Logout(config, store))
 | 
						mux.HandleFunc("GET /logout", view.Logout(config, store))
 | 
				
			||||||
	mux.HandleFunc("GET /pics/{pic}", view.ServeImage(config, store))
 | 
						mux.HandleFunc("GET /pics/{pic}", view.ServeImage(config, store))
 | 
				
			||||||
@@ -65,7 +66,8 @@ func main() {
 | 
				
			|||||||
	mux.HandleFunc("GET /rss", func(w http.ResponseWriter, r *http.Request) {
 | 
						mux.HandleFunc("GET /rss", func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
		http.ServeFile(w, r, config.RSSFile)
 | 
							http.ServeFile(w, r, config.RSSFile)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	mux.HandleFunc("GET /show-all-users", view.ShowAllUsers(config, db))
 | 
						mux.HandleFunc("GET /show-all-users-edit", view.ShowAllUsers(config, db, store, "edit-user"))
 | 
				
			||||||
 | 
						mux.HandleFunc("GET /show-all-users-delete", view.ShowAllUsers(config, db, store, "delete-user"))
 | 
				
			||||||
	mux.HandleFunc("GET /this-issue", view.ShowCurrentArticles(config, db))
 | 
						mux.HandleFunc("GET /this-issue", view.ShowCurrentArticles(config, db))
 | 
				
			||||||
	mux.HandleFunc("GET /unpublished-articles", view.ShowUnpublishedArticles(config, db))
 | 
						mux.HandleFunc("GET /unpublished-articles", view.ShowUnpublishedArticles(config, db))
 | 
				
			||||||
	mux.HandleFunc("GET /write-article", view.WriteArticle(config, db))
 | 
						mux.HandleFunc("GET /write-article", view.WriteArticle(config, db))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,7 @@ const (
 | 
				
			|||||||
	Publisher
 | 
						Publisher
 | 
				
			||||||
	Editor
 | 
						Editor
 | 
				
			||||||
	Author
 | 
						Author
 | 
				
			||||||
 | 
						NonExistent
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type User struct {
 | 
					type User struct {
 | 
				
			||||||
@@ -269,7 +270,7 @@ func (db *DB) AddFirstUser(u *User, pass string) (int64, error) {
 | 
				
			|||||||
	return 0, fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
 | 
						return 0, fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (db *DB) GetAllUsers() ([]*User, error) {
 | 
					func (db *DB) GetAllUsers() (map[int64]*User, error) {
 | 
				
			||||||
	query := "SELECT id, username, first_name, last_name, role FROM users"
 | 
						query := "SELECT id, username, first_name, last_name, role FROM users"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rows, err := db.Query(query)
 | 
						rows, err := db.Query(query)
 | 
				
			||||||
@@ -277,14 +278,14 @@ func (db *DB) GetAllUsers() ([]*User, error) {
 | 
				
			|||||||
		return nil, fmt.Errorf("error getting all users from DB: %v", err)
 | 
							return nil, fmt.Errorf("error getting all users from DB: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	users := make([]*User, 0)
 | 
						users := make(map[int64]*User, 0)
 | 
				
			||||||
	for rows.Next() {
 | 
						for rows.Next() {
 | 
				
			||||||
		user := new(User)
 | 
							user := new(User)
 | 
				
			||||||
		if err = rows.Scan(&user.ID, &user.UserName, &user.FirstName,
 | 
							if err = rows.Scan(&user.ID, &user.UserName, &user.FirstName,
 | 
				
			||||||
			&user.LastName, &user.Role); err != nil {
 | 
								&user.LastName, &user.Role); err != nil {
 | 
				
			||||||
			return nil, fmt.Errorf("error getting user info: %v", err)
 | 
								return nil, fmt.Errorf("error getting user info: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		users = append(users, user)
 | 
							users[user.ID] = user
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return users, nil
 | 
						return users, nil
 | 
				
			||||||
@@ -299,11 +300,7 @@ func (tx *Tx) SetPassword(id int64, newPass string) error {
 | 
				
			|||||||
		return fmt.Errorf("error creating password hash: %v", err)
 | 
							return fmt.Errorf("error creating password hash: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setQuery := `
 | 
						setQuery := "UPDATE users SET password = ? WHERE id = ?"
 | 
				
			||||||
    UPDATE users
 | 
					 | 
				
			||||||
    SET password = ?
 | 
					 | 
				
			||||||
    WHERE id = ?
 | 
					 | 
				
			||||||
    `
 | 
					 | 
				
			||||||
	if _, err = tx.Exec(setQuery, string(hashedPass), id); err != nil {
 | 
						if _, err = tx.Exec(setQuery, string(hashedPass), id); err != nil {
 | 
				
			||||||
		if rollbackErr := tx.Rollback(); rollbackErr != nil {
 | 
							if rollbackErr := tx.Rollback(); rollbackErr != nil {
 | 
				
			||||||
			log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
 | 
								log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
 | 
				
			||||||
@@ -370,3 +367,14 @@ func (db *DB) UpdateUserAttributes(id int64, user, first, last, newPass, newPass
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
 | 
						return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (db *DB) DeleteUser(id int64) error {
 | 
				
			||||||
 | 
						query := "DELETE FROM users WHERE id = ?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := db.Exec(query, id)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("error deleting user %v from DB: %v", id, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -95,8 +95,16 @@ func AddUser(c *control.Config, db *model.DB, s *control.CookieStore) http.Handl
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							session, err := s.Get(r, "cookie")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								tmpl, err := template.ParseFiles(c.WebDir + "/templates/login.html")
 | 
				
			||||||
 | 
								msg := "Session nicht mehr gültig. Bitte erneut anmelden."
 | 
				
			||||||
 | 
								template.Must(tmpl, err).ExecuteTemplate(w, "page-content", msg)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html")
 | 
							tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html")
 | 
				
			||||||
		template.Must(tmpl, err).ExecuteTemplate(w, "page-content", 0)
 | 
							tmpl = template.Must(tmpl, err)
 | 
				
			||||||
 | 
							tmpl.ExecuteTemplate(w, "page-content", session.Values["role"].(int))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -266,17 +274,32 @@ func AddFirstUser(c *control.Config, db *model.DB, s *control.CookieStore) http.
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ShowAllUsers(c *control.Config, db *model.DB) http.HandlerFunc {
 | 
					func ShowAllUsers(c *control.Config, db *model.DB, s *control.CookieStore, action string) http.HandlerFunc {
 | 
				
			||||||
	return func(w http.ResponseWriter, r *http.Request) {
 | 
						return func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
		users, err := db.GetAllUsers()
 | 
							var err error
 | 
				
			||||||
 | 
							type htmlData struct {
 | 
				
			||||||
 | 
								Users  map[int64]*model.User
 | 
				
			||||||
 | 
								Action string
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							data := &htmlData{Action: action}
 | 
				
			||||||
 | 
							data.Users, err = db.GetAllUsers()
 | 
				
			||||||
		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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							session, err := s.Get(r, "cookie")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								tmpl, err := template.ParseFiles(c.WebDir + "/templates/login.html")
 | 
				
			||||||
 | 
								msg := "Session nicht mehr gültig. Bitte erneut anmelden."
 | 
				
			||||||
 | 
								template.Must(tmpl, err).ExecuteTemplate(w, "page-content", msg)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							delete(data.Users, session.Values["id"].(int64))
 | 
				
			||||||
		tmpl, err := template.ParseFiles(c.WebDir + "/templates/show-all-users.html")
 | 
							tmpl, err := template.ParseFiles(c.WebDir + "/templates/show-all-users.html")
 | 
				
			||||||
		template.Must(tmpl, err).ExecuteTemplate(w, "page-content", users)
 | 
							template.Must(tmpl, err).ExecuteTemplate(w, "page-content", data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -372,8 +395,43 @@ func UpdateUser(c *control.Config, db *model.DB, s *control.CookieStore) http.Ha
 | 
				
			|||||||
			template.Must(tmpl, err).ExecuteTemplate(w, "page-content", userData)
 | 
								template.Must(tmpl, err).ExecuteTemplate(w, "page-content", userData)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							session, err := s.Get(r, "cookie")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								tmpl, err := template.ParseFiles(c.WebDir + "/templates/login.html")
 | 
				
			||||||
 | 
								msg := "Session nicht mehr gültig. Bitte erneut anmelden."
 | 
				
			||||||
 | 
								template.Must(tmpl, err).ExecuteTemplate(w, "page-content", msg)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html")
 | 
							tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html")
 | 
				
			||||||
		tmpl = template.Must(tmpl, err)
 | 
							tmpl = template.Must(tmpl, err)
 | 
				
			||||||
		tmpl.ExecuteTemplate(w, "page-content", 0)
 | 
							tmpl.ExecuteTemplate(w, "page-content", session.Values["role"].(int))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DeleteUser(c *control.Config, db *model.DB, s *control.CookieStore) http.HandlerFunc {
 | 
				
			||||||
 | 
						return func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
							id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Println(err)
 | 
				
			||||||
 | 
								http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err = db.DeleteUser(id); err != nil {
 | 
				
			||||||
 | 
								log.Println(err)
 | 
				
			||||||
 | 
								http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							session, err := s.Get(r, "cookie")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								tmpl, err := template.ParseFiles(c.WebDir + "/templates/login.html")
 | 
				
			||||||
 | 
								msg := "Session nicht mehr gültig. Bitte erneut anmelden."
 | 
				
			||||||
 | 
								template.Must(tmpl, err).ExecuteTemplate(w, "page-content", msg)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html")
 | 
				
			||||||
 | 
							tmpl = template.Must(tmpl, err)
 | 
				
			||||||
 | 
							tmpl.ExecuteTemplate(w, "page-content", session.Values["role"].(int))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,7 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div>
 | 
					        <div>
 | 
				
			||||||
            <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">Administrator</label>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,7 +44,7 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div>
 | 
					        <div>
 | 
				
			||||||
            <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">Administrator</label>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
<div class="flex flex-col gap-4">
 | 
					<div class="flex flex-col gap-4">
 | 
				
			||||||
    <button class="btn" hx-get="/logout" hx-target="#page-content">Abmelden</button>
 | 
					    <button class="btn" hx-get="/logout" hx-target="#page-content">Abmelden</button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {{if lt . 4}}
 | 
				
			||||||
    <div class="mb-3">
 | 
					    <div class="mb-3">
 | 
				
			||||||
        <h2>Autor</h2>
 | 
					        <h2>Autor</h2>
 | 
				
			||||||
        <div class="grid grid-cols-2 gap-x-4 gap-y-2">
 | 
					        <div class="grid grid-cols-2 gap-x-4 gap-y-2">
 | 
				
			||||||
@@ -11,6 +12,7 @@
 | 
				
			|||||||
            <button class="btn" hx-get="/edit-self" hx-target="#page-content">Profil bearbeiten</button>
 | 
					            <button class="btn" hx-get="/edit-self" hx-target="#page-content">Profil bearbeiten</button>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					    {{end}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {{if lt . 3}}
 | 
					    {{if lt . 3}}
 | 
				
			||||||
    <div class="mb-3">
 | 
					    <div class="mb-3">
 | 
				
			||||||
@@ -36,9 +38,10 @@
 | 
				
			|||||||
    {{if eq . 0}}
 | 
					    {{if eq . 0}}
 | 
				
			||||||
    <div class="mb-3">
 | 
					    <div class="mb-3">
 | 
				
			||||||
        <h2>Administrator</h2>
 | 
					        <h2>Administrator</h2>
 | 
				
			||||||
        <div class="grid grid-cols-2 gap-4">
 | 
					        <div class="grid grid-cols-3 gap-4">
 | 
				
			||||||
            <button class="btn" hx-get="/create-user" hx-target="#page-content">Benutzer hinzufügen</button>
 | 
					            <button class="btn" hx-get="/create-user" hx-target="#page-content">Benutzer hinzufügen</button>
 | 
				
			||||||
            <button class="btn" hx-get="/show-all-users" hx-target="#page-content">Benutzer bearbeiten</button>
 | 
					            <button class="btn" hx-get="/show-all-users-edit" hx-target="#page-content">Benutzer bearbeiten</button>
 | 
				
			||||||
 | 
					            <button class="btn" hx-get="/show-all-users-delete" hx-target="#page-content">Benutzer löschen</button>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    {{end}}
 | 
					    {{end}}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,12 +2,12 @@
 | 
				
			|||||||
<h2>Alle Benutzer</h2>
 | 
					<h2>Alle Benutzer</h2>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="flex flex-col gap-4">
 | 
					<div class="flex flex-col gap-4">
 | 
				
			||||||
    {{range .}}
 | 
					    {{range .Users}}
 | 
				
			||||||
    <button class="btn" hx-get="/edit-user/{{.ID}}" hx-target="#page-content">
 | 
					    <button class="btn" hx-get="/{{$.Action}}/{{.ID}}" hx-target="#page-content">
 | 
				
			||||||
        <h1 class="font-bold text-2xl">
 | 
					        <h1 class="font-bold text-2xl">
 | 
				
			||||||
            {{.UserName}}
 | 
					            {{.UserName}}
 | 
				
			||||||
            ({{if eq .Role 0}}
 | 
					            ({{if eq .Role 0}}
 | 
				
			||||||
            Admin
 | 
					            Administrator
 | 
				
			||||||
            {{else if eq .Role 1}}
 | 
					            {{else if eq .Role 1}}
 | 
				
			||||||
            Herausgeber
 | 
					            Herausgeber
 | 
				
			||||||
            {{else if eq .Role 2}}
 | 
					            {{else if eq .Role 2}}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user