Make session user inaccessible

This commit is contained in:
Teajey 2025-08-25 21:40:47 +09:00
parent a826417745
commit 57e18ae0ce
Signed by: Teajey
GPG Key ID: 970E790FE834A713
11 changed files with 38 additions and 26 deletions

View File

@ -5,7 +5,7 @@ type Admin struct {
} }
func (s *Session) Admin() *Admin { func (s *Session) Admin() *Admin {
if s.User.IsAdmin { if s.User().IsAdmin {
return &Admin{s} return &Admin{s}
} else { } else {
return nil return nil

View File

@ -45,7 +45,7 @@ func GetGroupByReference(reference string) (*Group, error)
func (g *Group) MemberIndex(userId string) int func (g *Group) MemberIndex(userId string) int
type Session struct { type Session struct {
User // Has unexported fields.
} }
func Login(username, password string) (*Session, error) func Login(username, password string) (*Session, error)
@ -74,6 +74,8 @@ func (s *Session) RevokeWishes(ids ...string) error
func (u *Session) SuggestWishForUser(otherUserReference string, wishName string) error func (u *Session) SuggestWishForUser(otherUserReference string, wishName string) error
func (s *Session) User() User
type User struct { type User struct {
Id string Id string
NormalName string NormalName string

View File

@ -72,7 +72,7 @@ func queryManyGroupMembers(groupId string) ([]User, error) {
func (s *Session) GetGroupByReference(reference string) (*Group, error) { func (s *Session) GetGroupByReference(reference string) (*Group, error) {
stmt := "SELECT [group].id, [group].name, [group].reference FROM [group] JOIN group_member ON [group].id == group_member.group_id WHERE [group].reference = ? AND group_member.user_id = ?;" stmt := "SELECT [group].id, [group].name, [group].reference FROM [group] JOIN group_member ON [group].id == group_member.group_id WHERE [group].reference = ? AND group_member.user_id = ?;"
return queryOneGroup(stmt, reference, s.User.Id) return queryOneGroup(stmt, reference, s.User().Id)
} }
func GetGroupByReference(reference string) (*Group, error) { func GetGroupByReference(reference string) (*Group, error) {
@ -126,5 +126,5 @@ func (a *Admin) RemoveUserFromGroup(userId, groupId string) error {
// Get the groups the session user belongs to // Get the groups the session user belongs to
func (u *Session) GetGroups() ([]Group, error) { func (u *Session) GetGroups() ([]Group, error) {
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 = ?" 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 = ?"
return queryManyGroups(stmt, u.Id) return queryManyGroups(stmt, u.User().Id)
} }

View File

@ -26,7 +26,7 @@ func TestCantSeeSelfInGroup(t *testing.T) {
group, err := s.Admin().CreateGroup(" My Friends ", " my-friends ") group, err := s.Admin().CreateGroup(" My Friends ", " my-friends ")
fixtures.FailIfErr(t, err, "Failed to create group") fixtures.FailIfErr(t, err, "Failed to create group")
err = s.Admin().AddUserToGroup(s.User.Id, group.Id) err = s.Admin().AddUserToGroup(s.User().Id, group.Id)
fixtures.FailIfErr(t, err, "Failed to add self to group") fixtures.FailIfErr(t, err, "Failed to add self to group")
err = s.Admin().AddUserToGroup(caleb.Id, group.Id) err = s.Admin().AddUserToGroup(caleb.Id, group.Id)

View File

@ -3,7 +3,12 @@ package lishwist
import "fmt" import "fmt"
type Session struct { type Session struct {
User user User
}
// Returns a copy of the user associated with this session
func (s *Session) User() User {
return s.user
} }
func SessionFromUsername(username string) (*Session, error) { func SessionFromUsername(username string) (*Session, error) {

View File

@ -24,7 +24,7 @@ type Wish struct {
func (s *Session) GetWishes() ([]Wish, error) { func (s *Session) GetWishes() ([]Wish, error) {
stmt := "SELECT wish.id, wish.name, wish.sent FROM wish WHERE wish.creator_id = ?1 AND wish.recipient_id = ?1" stmt := "SELECT wish.id, wish.name, wish.sent FROM wish WHERE wish.creator_id = ?1 AND wish.recipient_id = ?1"
rows, err := db.Connection.Query(stmt, s.User.Id) rows, err := db.Connection.Query(stmt, s.User().Id)
if err != nil { if err != nil {
return nil, fmt.Errorf("Query execution failed: %w", err) return nil, fmt.Errorf("Query execution failed: %w", err)
} }
@ -54,17 +54,17 @@ func (s *Session) GetWishes() ([]Wish, error) {
func (s *Session) MakeWish(name string) error { func (s *Session) MakeWish(name string) error {
stmt := "INSERT INTO wish (name, recipient_id, creator_id) VALUES (?, ?, ?)" stmt := "INSERT INTO wish (name, recipient_id, creator_id) VALUES (?, ?, ?)"
_, err := db.Connection.Exec(stmt, strings.TrimSpace(name), s.User.Id, s.User.Id) _, err := db.Connection.Exec(stmt, strings.TrimSpace(name), s.User().Id, s.User().Id)
if err != nil { if err != nil {
return fmt.Errorf("Query execution failed: %w", err) return fmt.Errorf("Query execution failed: %w", err)
} }
return nil return nil
} }
func (u *Session) deleteWishes(tx *sql.Tx, ids []string) error { func (s *Session) deleteWishes(tx *sql.Tx, ids []string) error {
stmt := "DELETE FROM wish WHERE wish.creator_id = ? AND wish.id = ?" stmt := "DELETE FROM wish WHERE wish.creator_id = ? AND wish.id = ?"
for _, id := range ids { for _, id := range ids {
r, err := tx.Exec(stmt, u.Id, id) r, err := tx.Exec(stmt, s.User().Id, id)
if err != nil { if err != nil {
return err return err
} }
@ -107,7 +107,7 @@ func (s *Session) GetOthersWishes(userReference string) ([]Wish, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to get other user: %w", err) return nil, fmt.Errorf("Failed to get other user: %w", err)
} }
if otherUser.Id == s.User.Id { if otherUser.Id == s.User().Id {
return nil, errors.New("Use (s *Session) GetWishes() to view your own wishes") return nil, errors.New("Use (s *Session) GetWishes() to view your own wishes")
} }
stmt := "SELECT wish.id, wish.name, claimant.id, claimant.name, wish.sent, wish.creator_id, creator.name, wish.recipient_id FROM wish JOIN v_user AS user ON wish.recipient_id = user.id LEFT JOIN v_user AS claimant ON wish.claimant_id = claimant.id LEFT JOIN v_user AS creator ON wish.creator_id = creator.id WHERE user.id = ?" stmt := "SELECT wish.id, wish.name, claimant.id, claimant.name, wish.sent, wish.creator_id, creator.name, wish.recipient_id FROM wish JOIN v_user AS user ON wish.recipient_id = user.id LEFT JOIN v_user AS claimant ON wish.claimant_id = claimant.id LEFT JOIN v_user AS creator ON wish.creator_id = creator.id WHERE user.id = ?"
@ -164,7 +164,7 @@ func (s *Session) executeClaims(tx *sql.Tx, claims, unclaims []string) error {
claimStmt := "UPDATE wish SET claimant_id = ? WHERE id = ?" claimStmt := "UPDATE wish SET claimant_id = ? WHERE id = ?"
unclaimStmt := "UPDATE wish SET claimant_id = NULL WHERE id = ?" unclaimStmt := "UPDATE wish SET claimant_id = NULL WHERE id = ?"
for _, id := range claims { for _, id := range claims {
r, err := tx.Exec(claimStmt, s.Id, id) r, err := tx.Exec(claimStmt, s.User().Id, id)
if err != nil { if err != nil {
return err return err
} }
@ -264,7 +264,7 @@ func (u *Session) SuggestWishForUser(otherUserReference string, wishName string)
return err return err
} }
stmt := "INSERT INTO wish (name, recipient_id, creator_id) VALUES (?, ?, ?)" stmt := "INSERT INTO wish (name, recipient_id, creator_id) VALUES (?, ?, ?)"
_, err = db.Connection.Exec(stmt, wishName, otherUser.Id, u.Id) _, err = db.Connection.Exec(stmt, wishName, otherUser.Id, u.User().Id)
if err != nil { if err != nil {
return err return err
} }

View File

@ -18,7 +18,8 @@ type foreignWishlistProps struct {
func ForeignWishlist(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response { func ForeignWishlist(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response {
userReference := r.PathValue("userReference") userReference := r.PathValue("userReference")
if app.User.Reference == userReference { user := app.User()
if user.Reference == userReference {
return rsvp.Found("/", "You're not allowed to view your own wishlist!") return rsvp.Found("/", "You're not allowed to view your own wishlist!")
} }
otherUser, err := lishwist.GetUserByReference(userReference) otherUser, err := lishwist.GetUserByReference(userReference)
@ -31,10 +32,10 @@ func ForeignWishlist(app *lishwist.Session, h http.Header, r *http.Request) rsvp
} }
wishes, err := app.GetOthersWishes(userReference) wishes, err := app.GetOthersWishes(userReference)
if err != nil { if err != nil {
log.Printf("%q couldn't get wishes of other user %q: %s\n", app.User.Name, otherUser.Name, err) log.Printf("%q couldn't get wishes of other user %q: %s\n", user.Name, otherUser.Name, err)
return response.Error(http.StatusInternalServerError, "An error occurred while fetching this user :(") return response.Error(http.StatusInternalServerError, "An error occurred while fetching this user :(")
} }
p := foreignWishlistProps{CurrentUserId: app.User.Id, CurrentUserName: app.User.Name, Username: otherUser.Name, Gifts: wishes} p := foreignWishlistProps{CurrentUserId: user.Id, CurrentUserName: user.Name, Username: otherUser.Name, Gifts: wishes}
return response.Data("foreign_wishlist.gotmpl", p) return response.Data("foreign_wishlist.gotmpl", p)
} }

View File

@ -25,19 +25,21 @@ func AdminGroup(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Resp
if group == nil { if group == nil {
return response.Error(http.StatusNotFound, "Group not found") return response.Error(http.StatusNotFound, "Group not found")
} }
if !app.User.IsAdmin { user := app.User()
index := group.MemberIndex(app.User.Id) if !user.IsAdmin {
index := group.MemberIndex(user.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: app.User.Name, CurrentUsername: user.Name,
} }
return response.Data("group_page.gotmpl", p) return response.Data("group_page.gotmpl", p)
} }
func Group(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response { func Group(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response {
if app.User.IsAdmin { user := app.User()
if user.IsAdmin {
return AdminGroup(app, h, r) return AdminGroup(app, h, r)
} }
groupReference := r.PathValue("groupReference") groupReference := r.PathValue("groupReference")
@ -49,11 +51,11 @@ func Group(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response
if group == nil { if group == nil {
return response.Error(http.StatusNotFound, "Group not found. (It might be because you're not a member)") return response.Error(http.StatusNotFound, "Group not found. (It might be because you're not a member)")
} }
index := group.MemberIndex(app.User.Id) index := group.MemberIndex(user.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: app.User.Name, CurrentUsername: user.Name,
} }
return response.Data("group_page.gotmpl", p) return response.Data("group_page.gotmpl", p)
} }

View File

@ -26,7 +26,8 @@ func Home(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response {
log.Printf("Failed to get gifts: %s\n", err) log.Printf("Failed to get gifts: %s\n", err)
return response.Error(http.StatusInternalServerError, "An error occurred while fetching your wishlist :(") return response.Error(http.StatusInternalServerError, "An error occurred while fetching your wishlist :(")
} }
todo, err := app.GetTodo() user := app.User()
todo, err := user.GetTodo()
if err != nil { if err != nil {
log.Printf("Failed to get todo: %s\n", err) log.Printf("Failed to get todo: %s\n", err)
return response.Error(http.StatusInternalServerError, "An error occurred while fetching your wishlist :(") return response.Error(http.StatusInternalServerError, "An error occurred while fetching your wishlist :(")
@ -36,7 +37,7 @@ func Home(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response {
log.Printf("Failed to get groups: %s\n", err) log.Printf("Failed to get groups: %s\n", err)
return response.Error(http.StatusInternalServerError, "An error occurred while fetching your wishlist :(") return response.Error(http.StatusInternalServerError, "An error occurred while fetching your wishlist :(")
} }
p := HomeProps{Username: app.User.Name, Gifts: gifts, Todo: todo, Reference: app.User.Reference, HostUrl: env.HostUrl.String(), Groups: groups} p := HomeProps{Username: user.Name, Gifts: gifts, Todo: todo, Reference: user.Reference, HostUrl: env.HostUrl.String(), Groups: groups}
return response.Data("home.gotmpl", p) return response.Data("home.gotmpl", p)
} }

View File

@ -70,9 +70,10 @@ func LoginPost(session *response.Session, h http.Header, r *http.Request) rsvp.R
} }
} }
user := app.User()
session.SetID("") session.SetID("")
session.SetValue("authorized", true) session.SetValue("authorized", true)
session.SetValue("username", app.User.Name) session.SetValue("username", user.Name)
return rsvp.SeeOther(r.URL.Path, "Login successful!") return rsvp.SeeOther(r.URL.Path, "Login successful!")
} }

View File

@ -53,7 +53,7 @@ func UserPost(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Respon
} }
reference := r.PathValue("userReference") reference := r.PathValue("userReference")
if reference == app.User.Reference { if reference == app.User().Reference {
return response.Error(http.StatusForbidden, "You cannot delete yourself.") return response.Error(http.StatusForbidden, "You cannot delete yourself.")
} }