feat: user deletion and get user as json

This commit is contained in:
Teajey 2024-11-22 10:38:53 +09:00
parent 20761920d3
commit dcba801dde
Signed by: Teajey
GPG Key ID: 970E790FE834A713
13 changed files with 173 additions and 64 deletions

View File

@ -66,7 +66,7 @@ func queryForGroups(query string, args ...any) ([]Group, error) {
} }
func queryForGroupMembers(groupId string) ([]User, error) { func queryForGroupMembers(groupId string) ([]User, error) {
query := "SELECT user.id, user.name, user.reference, user.is_admin FROM user JOIN group_member ON group_member.user_id = user.id JOIN [group] ON [group].id = group_member.group_id WHERE [group].id = ? ORDER BY group_member.user_id" query := "SELECT user.id, user.name, user.reference, user.is_admin, user.is_live FROM v_user AS user JOIN group_member ON group_member.user_id = user.id JOIN [group] ON [group].id = group_member.group_id WHERE [group].id = ? ORDER BY group_member.user_id"
members, err := queryForUsers(query, groupId) members, err := queryForUsers(query, groupId)
if err != nil { if err != nil {
return members, fmt.Errorf("Failed to get members: %w", err) return members, fmt.Errorf("Failed to get members: %w", err)

View File

@ -3,9 +3,10 @@ CREATE TABLE IF NOT EXISTS "user" (
"id" INTEGER NOT NULL UNIQUE, "id" INTEGER NOT NULL UNIQUE,
"name" TEXT NOT NULL UNIQUE, "name" TEXT NOT NULL UNIQUE,
"reference" TEXT NOT NULL UNIQUE, "reference" TEXT NOT NULL UNIQUE,
"motto" TEXT NOT NULL, "motto" TEXT NOT NULL DEFAULT "",
"password_hash" TEXT NOT NULL, "password_hash" TEXT NOT NULL,
"is_admin" INTEGER NOT NULL DEFAULT 0, "is_admin" INTEGER NOT NULL DEFAULT 0,
"is_live" INTEGER NOT NULL DEFAULT 1,
PRIMARY KEY("id" AUTOINCREMENT) PRIMARY KEY("id" AUTOINCREMENT)
); );
CREATE TABLE IF NOT EXISTS "gift" ( CREATE TABLE IF NOT EXISTS "gift" (
@ -38,4 +39,15 @@ CREATE TABLE IF NOT EXISTS "session" (
"value" TEXT NOT NULL, "value" TEXT NOT NULL,
PRIMARY KEY("id" AUTOINCREMENT) PRIMARY KEY("id" AUTOINCREMENT)
); );
DROP VIEW IF EXISTS "v_user";
CREATE VIEW "v_user"
AS
SELECT * FROM user WHERE user.is_live = 1;
-- DROP VIEW IF EXISTS "v_wish";
-- CREATE VIEW "v_wish"
-- AS
-- SELECT gift.id, gift.name, gift.sent FROM gift JOIN user AS recipient;
COMMIT; COMMIT;

22
server/db/migration/1.sql Normal file
View File

@ -0,0 +1,22 @@
BEGIN TRANSACTION;
ALTER TABLE user ADD COLUMN "is_live" INTEGER NOT NULL DEFAULT 1;
ALTER TABLE user RENAME TO old_user;
CREATE TABLE "user" (
"id" INTEGER NOT NULL UNIQUE,
"name" TEXT NOT NULL UNIQUE,
"reference" TEXT NOT NULL UNIQUE,
"motto" TEXT NOT NULL DEFAULT "",
"password_hash" TEXT NOT NULL,
"is_admin" INTEGER NOT NULL DEFAULT 0,
"is_live" INTEGER NOT NULL DEFAULT 1,
PRIMARY KEY("id" AUTOINCREMENT)
);
INSERT INTO user SELECT * FROM old_user;
DROP TABLE "old_user";
COMMIT;

View File

@ -12,6 +12,7 @@ type User struct {
Name string Name string
Reference string Reference string
IsAdmin bool IsAdmin bool
IsLive bool
} }
type Gift struct { type Gift struct {
@ -29,7 +30,7 @@ type Gift struct {
func queryForUser(query string, args ...any) (*User, error) { func queryForUser(query string, args ...any) (*User, error) {
var u User var u User
err := database.QueryRow(query, args...).Scan(&u.Id, &u.Name, &u.Reference, &u.IsAdmin) err := database.QueryRow(query, args...).Scan(&u.Id, &u.Name, &u.Reference, &u.IsAdmin, &u.IsLive)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return nil, nil return nil, nil
} else if err != nil { } else if err != nil {
@ -47,7 +48,7 @@ func queryForUsers(query string, args ...any) ([]User, error) {
users := []User{} users := []User{}
for rows.Next() { for rows.Next() {
var u User var u User
err = rows.Scan(&u.Id, &u.Name, &u.Reference, &u.IsAdmin) err = rows.Scan(&u.Id, &u.Name, &u.Reference, &u.IsAdmin, &u.IsLive)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -61,27 +62,42 @@ func queryForUsers(query string, args ...any) ([]User, error) {
} }
func GetAllUsers() ([]User, error) { func GetAllUsers() ([]User, error) {
stmt := "SELECT user.id, user.name, user.reference, user.is_admin FROM user" stmt := "SELECT id, name, reference, is_admin, is_live FROM user"
return queryForUsers(stmt) return queryForUsers(stmt)
} }
func GetUser(id string) (*User, error) { func GetUser(id string) (*User, error) {
stmt := "SELECT user.id, user.name, user.reference, user.is_admin FROM user WHERE user.id = ?" stmt := "SELECT id, name, reference, is_admin, is_live FROM v_user WHERE id = ?"
return queryForUser(stmt, id) return queryForUser(stmt, id)
} }
func GetUserByName(username string) (*User, error) { func GetUserByName(username string) (*User, error) {
stmt := "SELECT user.id, user.name, user.reference, user.is_admin FROM user WHERE user.name = ?" stmt := "SELECT id, name, reference, is_admin, is_live FROM v_user WHERE name = ?"
return queryForUser(stmt, username) return queryForUser(stmt, username)
} }
func GetUserByReference(reference string) (*User, error) { func GetUserByReference(reference string) (*User, error) {
stmt := "SELECT user.id, user.name, user.reference, user.is_admin FROM user WHERE user.reference = ?" stmt := "SELECT id, name, reference, is_admin, is_live FROM v_user WHERE reference = ?"
return queryForUser(stmt, reference) return queryForUser(stmt, reference)
} }
func GetAnyUserByReference(reference string) (*User, error) {
stmt := "SELECT id, name, reference, is_admin, is_live FROM user WHERE reference = ?"
return queryForUser(stmt, reference)
}
func (u *User) SetLive(setting bool) error {
query := "UPDATE user SET is_live = ? WHERE reference = ?"
_, err := database.Exec(query, setting, u.Reference)
if err != nil {
return err
}
u.IsLive = setting
return err
}
func CreateUser(username string, passHash []byte) (*User, error) { func CreateUser(username string, passHash []byte) (*User, error) {
stmt := "INSERT INTO user (name, motto, reference, password_hash) VALUES (?, '', ?, ?)" stmt := "INSERT INTO user (name, reference, password_hash) VALUES (?, ?, ?)"
reference, err := uuid.NewRandom() reference, err := uuid.NewRandom()
if err != nil { if err != nil {
return nil, err return nil, err
@ -102,7 +118,7 @@ func CreateUser(username string, passHash []byte) (*User, error) {
} }
func (u *User) GetPassHash() ([]byte, error) { func (u *User) GetPassHash() ([]byte, error) {
stmt := "SELECT user.password_hash FROM user WHERE user.id = ?" stmt := "SELECT password_hash FROM v_user WHERE id = ?"
var passHash string var passHash string
err := database.QueryRow(stmt, u.Id).Scan(&passHash) err := database.QueryRow(stmt, u.Id).Scan(&passHash)
if err != nil { if err != nil {
@ -112,7 +128,7 @@ func (u *User) GetPassHash() ([]byte, error) {
} }
func (u *User) CountGifts() (int, error) { func (u *User) CountGifts() (int, error) {
stmt := "SELECT COUNT(gift.id) AS gift_count FROM gift JOIN user ON gift.recipient_id = user.id LEFT JOIN user AS claimant ON gift.claimant_id = claimant.id WHERE gift.creator_id = user.id AND user.id = ?" stmt := "SELECT COUNT(gift.id) AS gift_count FROM gift WHERE gift.creator_id = ?1 AND gift.recipient_id = ?1"
var giftCount int var giftCount int
err := database.QueryRow(stmt, u.Id).Scan(&giftCount) err := database.QueryRow(stmt, u.Id).Scan(&giftCount)
if err != nil { if err != nil {
@ -122,7 +138,7 @@ func (u *User) CountGifts() (int, error) {
} }
func (u *User) GetGifts() ([]Gift, error) { func (u *User) GetGifts() ([]Gift, error) {
stmt := "SELECT gift.id, gift.name, claimant.id, claimant.name, gift.sent FROM gift JOIN user ON gift.recipient_id = user.id LEFT JOIN user AS claimant ON gift.claimant_id = claimant.id WHERE gift.creator_id = user.id AND user.id = ?" stmt := "SELECT gift.id, gift.name, gift.sent FROM gift WHERE gift.creator_id = ?1 AND gift.recipient_id = ?1"
rows, err := database.Query(stmt, u.Id) rows, err := database.Query(stmt, u.Id)
if err != nil { if err != nil {
return nil, err return nil, err
@ -132,19 +148,15 @@ func (u *User) GetGifts() ([]Gift, error) {
for rows.Next() { for rows.Next() {
var id string var id string
var name string var name string
var claimantId sql.NullString
var claimantName sql.NullString
var sent bool var sent bool
err = rows.Scan(&id, &name, &claimantId, &claimantName, &sent) err = rows.Scan(&id, &name, &sent)
if err != nil { if err != nil {
return nil, err return nil, err
} }
gift := Gift{ gift := Gift{
Id: id, Id: id,
Name: name, Name: name,
ClaimantId: claimantId.String, Sent: sent,
ClaimantName: claimantName.String,
Sent: sent,
} }
gifts = append(gifts, gift) gifts = append(gifts, gift)
} }
@ -158,15 +170,15 @@ func (u *User) GetGifts() ([]Gift, error) {
func (u *User) GetOtherUserGifts(otherUserReference string) ([]Gift, error) { func (u *User) GetOtherUserGifts(otherUserReference string) ([]Gift, error) {
otherUser, err := GetUserByReference(otherUserReference) otherUser, err := GetUserByReference(otherUserReference)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("Failed to get other user: %w", err)
} }
if otherUser.Id == u.Id { if otherUser.Id == u.Id {
return nil, fmt.Errorf("Not allowed to view own foreign wishlist") return nil, fmt.Errorf("Not allowed to view own foreign wishlist")
} }
stmt := "SELECT gift.id, gift.name, claimant.id, claimant.name, gift.sent, gift.creator_id, creator.name, gift.recipient_id FROM gift JOIN user ON gift.recipient_id = user.id LEFT JOIN user AS claimant ON gift.claimant_id = claimant.id LEFT JOIN user AS creator ON gift.creator_id = creator.id WHERE user.id = ?" stmt := "SELECT gift.id, gift.name, claimant.id, claimant.name, gift.sent, gift.creator_id, creator.name, gift.recipient_id FROM gift JOIN v_user AS user ON gift.recipient_id = user.id LEFT JOIN v_user AS claimant ON gift.claimant_id = claimant.id LEFT JOIN v_user AS creator ON gift.creator_id = creator.id WHERE user.id = ?"
rows, err := database.Query(stmt, otherUser.Id) rows, err := database.Query(stmt, otherUser.Id)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("Failed to execute query: %w", err)
} }
defer rows.Close() defer rows.Close()
gifts := []Gift{} gifts := []Gift{}
@ -181,7 +193,7 @@ func (u *User) GetOtherUserGifts(otherUserReference string) ([]Gift, error) {
var recipientId string var recipientId string
err = rows.Scan(&id, &name, &claimantId, &claimantName, &sent, &creatorId, &creatorName, &recipientId) err = rows.Scan(&id, &name, &claimantId, &claimantName, &sent, &creatorId, &creatorName, &recipientId)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("Failed to scan row: %w", err)
} }
gift := Gift{ gift := Gift{
Id: id, Id: id,
@ -197,13 +209,13 @@ func (u *User) GetOtherUserGifts(otherUserReference string) ([]Gift, error) {
} }
err = rows.Err() err = rows.Err()
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("Rows returned an error: %w", err)
} }
return gifts, nil return gifts, nil
} }
func (u *User) GetTodo() ([]Gift, error) { func (u *User) GetTodo() ([]Gift, error) {
stmt := "SELECT gift.id, gift.name, gift.sent, recipient.name, recipient.reference FROM gift JOIN user ON gift.claimant_id = user.id JOIN user AS recipient ON gift.recipient_id = recipient.id WHERE user.id = ? ORDER BY gift.sent ASC, gift.name" stmt := "SELECT gift.id, gift.name, gift.sent, recipient.name, recipient.reference FROM gift JOIN v_user AS user ON gift.claimant_id = user.id JOIN v_user AS recipient ON gift.recipient_id = recipient.id WHERE user.id = ? ORDER BY gift.sent ASC, gift.name"
rows, err := database.Query(stmt, u.Id) rows, err := database.Query(stmt, u.Id)
if err != nil { if err != nil {
return nil, err return nil, err
@ -393,7 +405,7 @@ func (u *User) AddGiftToUser(otherUserReference string, giftName string) error {
} }
func (u *User) GetGroups() ([]Group, error) { func (u *User) GetGroups() ([]Group, error) {
stmt := "SELECT [group].id, [group].name, [group].reference FROM [group] JOIN group_member ON group_member.group_id = [group].id JOIN user ON user.id = group_member.user_id WHERE user.id = ?" stmt := "SELECT [group].id, [group].name, [group].reference FROM [group] JOIN group_member ON group_member.group_id = [group].id JOIN v_user AS user ON user.id = group_member.user_id WHERE user.id = ?"
rows, err := database.Query(stmt, u.Id) rows, err := database.Query(stmt, u.Id)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -55,6 +55,8 @@ func main() {
r.Json.Public.HandleFunc("GET /", routing.NotFoundJson) r.Json.Public.HandleFunc("GET /", routing.NotFoundJson)
r.Json.Private.Handle("GET /users", route.ExpectUser(route.UsersJson)) r.Json.Private.Handle("GET /users", route.ExpectUser(route.UsersJson))
r.Json.Private.Handle("GET /users/{userReference}", route.ExpectUser(route.User))
r.Json.Private.Handle("POST /users/{userReference}", route.ExpectUser(route.UserPost))
r.Json.Private.Handle("GET /groups", route.ExpectUser(route.GroupsJson)) r.Json.Private.Handle("GET /groups", route.ExpectUser(route.GroupsJson))
r.Json.Private.Handle("POST /groups/{groupReference}", route.ExpectUser(route.GroupPost)) r.Json.Private.Handle("POST /groups/{groupReference}", route.ExpectUser(route.GroupPost))
r.Json.Private.Handle("GET /groups/{groupReference}", route.ExpectUser(route.Group)) r.Json.Private.Handle("GET /groups/{groupReference}", route.ExpectUser(route.Group))

View File

@ -10,8 +10,8 @@ import (
func writeGeneralErrorJson(w http.ResponseWriter, status int, format string, a ...any) { func writeGeneralErrorJson(w http.ResponseWriter, status int, format string, a ...any) {
msg := fmt.Sprintf(format, a...) msg := fmt.Sprintf(format, a...)
log.Printf("General error: %s\n", msg) log.Printf("General error: %s\n", msg)
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(status) w.WriteHeader(status)
escapedMsg := strings.ReplaceAll(msg, `"`, `\"`) escapedMsg := strings.ReplaceAll(msg, `"`, `\"`)
_, _ = w.Write([]byte(fmt.Sprintf(`{"GeneralError":"%s"}`, escapedMsg))) _, _ = w.Write([]byte(fmt.Sprintf(`{"GeneralError":"%s"}`, escapedMsg)))
w.Header().Add("Content-Type", "application/json")
} }

View File

@ -14,9 +14,9 @@ type foreignWishlistProps struct {
Gifts []db.Gift Gifts []db.Gift
} }
func (ctx *Context) ForeignWishlist(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) ForeignWishlist(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
userReference := r.PathValue("userReference") userReference := r.PathValue("userReference")
if user.Reference == userReference { if currentUser.Reference == userReference {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
@ -29,12 +29,12 @@ func (ctx *Context) ForeignWishlist(user *db.User, w http.ResponseWriter, r *htt
error.Page(w, "User not found", http.StatusNotFound, err) error.Page(w, "User not found", http.StatusNotFound, err)
return return
} }
gifts, err := user.GetOtherUserGifts(userReference) gifts, err := currentUser.GetOtherUserGifts(userReference)
if err != nil { if err != nil {
error.Page(w, "An error occurred while fetching this user's wishlist :(", http.StatusInternalServerError, err) error.Page(w, "An error occurred while fetching this user's wishlist :(", http.StatusInternalServerError, err)
return return
} }
p := foreignWishlistProps{CurrentUserId: user.Id, CurrentUserName: user.Name, Username: otherUser.Name, Gifts: gifts} p := foreignWishlistProps{CurrentUserId: currentUser.Id, CurrentUserName: currentUser.Name, Username: otherUser.Name, Gifts: gifts}
templates.Execute(w, "foreign_wishlist.gotmpl", p) templates.Execute(w, "foreign_wishlist.gotmpl", p)
} }

View File

@ -15,9 +15,9 @@ type GroupProps struct {
CurrentUsername string CurrentUsername string
} }
func (ctx *Context) GroupPage(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) GroupPage(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
groupReference := r.PathValue("groupReference") groupReference := r.PathValue("groupReference")
group, err := user.GetGroupByReference(groupReference) group, err := currentUser.GetGroupByReference(groupReference)
if err != nil { if err != nil {
error.Page(w, "An error occurred while fetching this group :(", http.StatusInternalServerError, err) error.Page(w, "An error occurred while fetching this group :(", http.StatusInternalServerError, err)
return return
@ -26,11 +26,11 @@ func (ctx *Context) GroupPage(user *db.User, w http.ResponseWriter, r *http.Requ
error.Page(w, "Group not found. (It might be because you're not a member)", http.StatusNotFound, nil) error.Page(w, "Group not found. (It might be because you're not a member)", http.StatusNotFound, nil)
return return
} }
index := group.MemberIndex(user.Id) index := group.MemberIndex(currentUser.Id)
group.Members = slices.Delete(group.Members, index, index+1) group.Members = slices.Delete(group.Members, index, index+1)
p := GroupProps{ p := GroupProps{
Group: group, Group: group,
CurrentUsername: user.Name, CurrentUsername: currentUser.Name,
} }
templates.Execute(w, "group_page.gotmpl", p) templates.Execute(w, "group_page.gotmpl", p)
} }
@ -120,8 +120,8 @@ func (ctx *Context) GroupPost(currentUser *db.User, w http.ResponseWriter, r *ht
_ = json.NewEncoder(w).Encode(group) _ = json.NewEncoder(w).Encode(group)
} }
func (ctx *Context) GroupsJson(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) GroupsJson(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if !user.IsAdmin { if !currentUser.IsAdmin {
NotFoundJson(w, r) NotFoundJson(w, r)
return return
} }
@ -135,8 +135,8 @@ func (ctx *Context) GroupsJson(user *db.User, w http.ResponseWriter, r *http.Req
_ = json.NewEncoder(w).Encode(groups) _ = json.NewEncoder(w).Encode(groups)
} }
func (ctx *Context) Group(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) Group(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if !user.IsAdmin { if !currentUser.IsAdmin {
NotFoundJson(w, r) NotFoundJson(w, r)
return return
} }

View File

@ -18,40 +18,40 @@ type HomeProps struct {
Groups []db.Group Groups []db.Group
} }
func (ctx *Context) Home(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) Home(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
gifts, err := user.GetGifts() gifts, err := currentUser.GetGifts()
if err != nil { if err != nil {
error.Page(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError, err) error.Page(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError, err)
return return
} }
todo, err := user.GetTodo() todo, err := currentUser.GetTodo()
if err != nil { if err != nil {
error.Page(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError, err) error.Page(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError, err)
return return
} }
groups, err := user.GetGroups() groups, err := currentUser.GetGroups()
if err != nil { if err != nil {
error.Page(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError, err) error.Page(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError, err)
return return
} }
p := HomeProps{Username: user.Name, Gifts: gifts, Todo: todo, Reference: user.Reference, HostUrl: env.HostUrl.String(), Groups: groups} p := HomeProps{Username: currentUser.Name, Gifts: gifts, Todo: todo, Reference: currentUser.Reference, HostUrl: env.HostUrl.String(), Groups: groups}
templates.Execute(w, "home.gotmpl", p) templates.Execute(w, "home.gotmpl", p)
} }
func (ctx *Context) HomePost(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) HomePost(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
http.Error(w, "Couldn't parse form", http.StatusBadRequest) http.Error(w, "Couldn't parse form", http.StatusBadRequest)
return return
} }
switch r.Form.Get("intent") { switch r.Form.Get("intent") {
case "add_idea": case "add_idea":
ctx.WishlistAdd(user, w, r) ctx.WishlistAdd(currentUser, w, r)
return return
case "delete_idea": case "delete_idea":
ctx.WishlistDelete(user, w, r) ctx.WishlistDelete(currentUser, w, r)
return return
default: default:
ctx.TodoUpdate(user, w, r) ctx.TodoUpdate(currentUser, w, r)
return return
} }
} }

View File

@ -6,7 +6,7 @@ import (
"net/http" "net/http"
) )
func (ctx *Context) TodoUpdate(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) TodoUpdate(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
return return
@ -14,14 +14,14 @@ func (ctx *Context) TodoUpdate(user *db.User, w http.ResponseWriter, r *http.Req
switch r.Form.Get("intent") { switch r.Form.Get("intent") {
case "unclaim_todo": case "unclaim_todo":
unclaims := r.Form["gift"] unclaims := r.Form["gift"]
err := user.ClaimGifts([]string{}, unclaims) err := currentUser.ClaimGifts([]string{}, unclaims)
if err != nil { if err != nil {
http.Error(w, "Failed to update claim...", http.StatusInternalServerError) http.Error(w, "Failed to update claim...", http.StatusInternalServerError)
return return
} }
case "complete_todo": case "complete_todo":
claims := r.Form["gift"] claims := r.Form["gift"]
err := user.CompleteGifts(claims) err := currentUser.CompleteGifts(claims)
if err != nil { if err != nil {
log.Printf("Failed to complete gifts: %s\n", err) log.Printf("Failed to complete gifts: %s\n", err)
http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError) http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError)
@ -29,6 +29,7 @@ func (ctx *Context) TodoUpdate(user *db.User, w http.ResponseWriter, r *http.Req
} }
default: default:
http.Error(w, "Invalid intent", http.StatusBadRequest) http.Error(w, "Invalid intent", http.StatusBadRequest)
return
} }
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
} }

View File

@ -6,8 +6,8 @@ import (
"net/http" "net/http"
) )
func (ctx *Context) UsersJson(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) UsersJson(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if !user.IsAdmin { if !currentUser.IsAdmin {
NotFoundJson(w, r) NotFoundJson(w, r)
return return
} }
@ -20,3 +20,63 @@ func (ctx *Context) UsersJson(user *db.User, w http.ResponseWriter, r *http.Requ
_ = json.NewEncoder(w).Encode(users) _ = json.NewEncoder(w).Encode(users)
} }
func (ctx *Context) User(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if !currentUser.IsAdmin {
NotFoundJson(w, r)
return
}
reference := r.PathValue("userReference")
user, err := db.GetUserByReference(reference)
if err != nil {
writeGeneralErrorJson(w, http.StatusInternalServerError, "Failed to get user: %s", err)
return
}
if user == nil {
writeGeneralErrorJson(w, http.StatusNotFound, "User not found")
return
}
_ = json.NewEncoder(w).Encode(user)
}
func (ctx *Context) UserPost(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if !currentUser.IsAdmin {
NotFoundJson(w, r)
return
}
if err := r.ParseForm(); err != nil {
writeGeneralErrorJson(w, http.StatusInternalServerError, "Failed to parse form: %s", err)
return
}
reference := r.PathValue("userReference")
if reference == currentUser.Reference {
writeGeneralErrorJson(w, http.StatusForbidden, "You cannot delete yourself.")
return
}
user, err := db.GetAnyUserByReference(reference)
if err != nil {
writeGeneralErrorJson(w, http.StatusInternalServerError, "Failed to get user: %s", err)
return
}
if user == nil {
writeGeneralErrorJson(w, http.StatusNotFound, "User not found")
return
}
intent := r.Form.Get("intent")
if intent != "" {
err = user.SetLive(intent != "delete")
if err != nil {
writeGeneralErrorJson(w, http.StatusInternalServerError, "Failed to delete user: "+err.Error())
return
}
}
_ = json.NewEncoder(w).Encode(user)
}

View File

@ -6,13 +6,13 @@ import (
"net/http" "net/http"
) )
func (ctx *Context) WishlistAdd(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) WishlistAdd(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
newGiftName := r.Form.Get("gift_name") newGiftName := r.Form.Get("gift_name")
err := user.AddGift(newGiftName) err := currentUser.AddGift(newGiftName)
if err != nil { if err != nil {
error.Page(w, "Failed to add gift.", http.StatusInternalServerError, err) error.Page(w, "Failed to add gift.", http.StatusInternalServerError, err)
return return
@ -20,13 +20,13 @@ func (ctx *Context) WishlistAdd(user *db.User, w http.ResponseWriter, r *http.Re
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
} }
func (ctx *Context) WishlistDelete(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) WishlistDelete(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
targets := r.Form["gift"] targets := r.Form["gift"]
err := user.RemoveGifts(targets...) err := currentUser.RemoveGifts(targets...)
if err != nil { if err != nil {
error.Page(w, "Failed to remove gifts.", http.StatusInternalServerError, err) error.Page(w, "Failed to remove gifts.", http.StatusInternalServerError, err)
return return
@ -34,7 +34,7 @@ func (ctx *Context) WishlistDelete(user *db.User, w http.ResponseWriter, r *http
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
} }
func (ctx *Context) ForeignWishlistPost(user *db.User, w http.ResponseWriter, r *http.Request) { func (ctx *Context) ForeignWishlistPost(currentUser *db.User, w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
error.Page(w, "Failed to parse form...", http.StatusBadRequest, err) error.Page(w, "Failed to parse form...", http.StatusBadRequest, err)
return return
@ -44,14 +44,14 @@ func (ctx *Context) ForeignWishlistPost(user *db.User, w http.ResponseWriter, r
case "claim": case "claim":
claims := r.Form["unclaimed"] claims := r.Form["unclaimed"]
unclaims := r.Form["claimed"] unclaims := r.Form["claimed"]
err := user.ClaimGifts(claims, unclaims) err := currentUser.ClaimGifts(claims, unclaims)
if err != nil { if err != nil {
error.Page(w, "Failed to update claim...", http.StatusInternalServerError, err) error.Page(w, "Failed to update claim...", http.StatusInternalServerError, err)
return return
} }
case "complete": case "complete":
claims := r.Form["claimed"] claims := r.Form["claimed"]
err := user.CompleteGifts(claims) err := currentUser.CompleteGifts(claims)
if err != nil { if err != nil {
error.Page(w, "Failed to complete gifts...", http.StatusInternalServerError, nil) error.Page(w, "Failed to complete gifts...", http.StatusInternalServerError, nil)
return return
@ -62,7 +62,7 @@ func (ctx *Context) ForeignWishlistPost(user *db.User, w http.ResponseWriter, r
error.Page(w, "Gift name not provided", http.StatusBadRequest, nil) error.Page(w, "Gift name not provided", http.StatusBadRequest, nil)
return return
} }
err := user.AddGiftToUser(userReference, giftName) err := currentUser.AddGiftToUser(userReference, giftName)
if err != nil { if err != nil {
error.Page(w, "Failed to add gift idea to other user...", http.StatusInternalServerError, err) error.Page(w, "Failed to add gift idea to other user...", http.StatusInternalServerError, err)
return return
@ -71,7 +71,7 @@ func (ctx *Context) ForeignWishlistPost(user *db.User, w http.ResponseWriter, r
claims := r.Form["unclaimed"] claims := r.Form["unclaimed"]
unclaims := r.Form["claimed"] unclaims := r.Form["claimed"]
gifts := append(claims, unclaims...) gifts := append(claims, unclaims...)
err := user.RemoveGifts(gifts...) err := currentUser.RemoveGifts(gifts...)
if err != nil { if err != nil {
error.Page(w, "Failed to remove gift idea for other user...", http.StatusInternalServerError, err) error.Page(w, "Failed to remove gift idea for other user...", http.StatusInternalServerError, err)
return return

View File

@ -83,7 +83,7 @@
</ul> </ul>
<button id="unclaimSubmit" class="btn btn-warning" type="submit" name="intent" value="unclaim_todo" <button id="unclaimSubmit" class="btn btn-warning" type="submit" name="intent" value="unclaim_todo"
disabled>Unclaim</button> disabled>Unclaim</button>
<button id="completeSubmit" class="btn btn-success" type="submit" name="mode" value="complete_todo" <button id="completeSubmit" class="btn btn-success" type="submit" name="intent" value="complete_todo"
disabled>Complete</button> disabled>Complete</button>
</form> </form>
{{else}} {{else}}