fix: read privileged membership and the admin actions through a clean statement (T-12.1-38, T-12.1-39)

classes.fresh chained WithContext onto a lazy NewDB session, which clones the
caller's statement with its conditions. A handle that carried a condition
made IsPrivilegedMember answer false for a member of a privileged group, so
the takeover guard would have let the request through. No caller passes such
a handle today: the admin hooks hand over the write's transaction handle.

- fresh builds the empty statement before anything is chained onto it
- IsPrivilegedMember and PrivilegedGroupIDs read through fresh
This commit is contained in:
Jakub Zych
2026-10-05 14:53:41 +02:00
parent ba43ad9c03
commit f4969591e2
2 changed files with 10 additions and 5 deletions

View File

@@ -83,7 +83,7 @@ func PrivilegedGroupIDs(ctx context.Context, db *gorm.DB, codes []string) ([]uin
if len(codes) == 0 {
return ids, nil
}
err := db.Session(&gorm.Session{NewDB: true}).WithContext(ctx).
err := fresh(ctx, db).
Table("user_groups").
Where("code IN ?", codes).
Order("id").
@@ -97,7 +97,8 @@ func PrivilegedGroupIDs(ctx context.Context, db *gorm.DB, codes []string) ([]uin
// IsPrivilegedMember reports whether the user belongs to at least one group
// whose code is in codes. A user in no group, and a group without a code,
// give false. A deactivated user's membership counts: it survives the soft
// delete.
// delete. The membership is read through an empty statement on db's
// connection, so conditions the caller's handle carries never narrow it.
func IsPrivilegedMember(ctx context.Context, db *gorm.DB, codes []string, userID uint) (bool, error) {
if db == nil {
return false, fmt.Errorf("golem15.user: gorm handle is missing")
@@ -105,7 +106,7 @@ func IsPrivilegedMember(ctx context.Context, db *gorm.DB, codes []string, userID
if len(codes) == 0 || userID == 0 {
return false, nil
}
held, err := UserGroupCodes(ctx, db.Session(&gorm.Session{NewDB: true}), userID)
held, err := UserGroupCodes(ctx, fresh(ctx, db), userID)
if err != nil {
return false, err
}