Address production-readiness review: clearer errors, safer votes, and ops hardening.
Distinguish auth/lookup failures, make votes idempotent on visible questions, bound shutdown, page admin users, LRU throttle, trusted-proxy CIDRs, avatar cleanup, versioned migrations, and session cleanup logging.
This commit is contained in:
+21
-6
@@ -82,14 +82,14 @@ func (u *User) Create(ctx context.Context) error {
|
||||
if u.CreatedAt == "" {
|
||||
u.CreatedAt = time.Now().UTC().Format(time.RFC3339)
|
||||
}
|
||||
return sqlc.New(u.db).CreateUser(ctx, sqlc.CreateUserParams{
|
||||
return mapUniqueViolation(sqlc.New(u.db).CreateUser(ctx, sqlc.CreateUserParams{
|
||||
ID: u.ID,
|
||||
Username: u.Username,
|
||||
Name: u.Name,
|
||||
PasswordHash: u.PasswordHash,
|
||||
Role: string(u.Role),
|
||||
CreatedAt: u.CreatedAt,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
// adminRoleLockKey serializes SetRole so concurrent demotions cannot bypass the
|
||||
@@ -171,17 +171,32 @@ func CountAdmins(ctx context.Context, db *sql.DB) (int, error) {
|
||||
return int(n), err
|
||||
}
|
||||
|
||||
func ListUsers(ctx context.Context, db *sql.DB) ([]User, error) {
|
||||
rows, err := sqlc.New(db).ListUsers(ctx, AdminUsersLimit)
|
||||
func ListUsers(ctx context.Context, db *sql.DB, q ListUsersQuery) ([]User, string, string, error) {
|
||||
limit := q.Limit
|
||||
if limit <= 0 {
|
||||
limit = AdminUsersLimit
|
||||
}
|
||||
rows, err := sqlc.New(db).ListUsers(ctx, sqlc.ListUsersParams{
|
||||
Search: q.Search,
|
||||
CursorCreated: q.CursorCreated,
|
||||
CursorID: q.CursorID,
|
||||
RowLimit: int32(limit + 1),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
out := make([]User, 0, len(rows))
|
||||
for _, r := range rows {
|
||||
u := toUser(db, r.ID, r.Username, r.Name, r.Role, r.AvatarUrl, r.State, r.CreatedAt, "")
|
||||
out = append(out, *u)
|
||||
}
|
||||
return out, nil
|
||||
var nextCreated, nextID string
|
||||
if len(out) > limit {
|
||||
last := out[limit-1]
|
||||
nextCreated, nextID = last.CreatedAt, last.ID
|
||||
out = out[:limit]
|
||||
}
|
||||
return out, nextCreated, nextID, nil
|
||||
}
|
||||
|
||||
func UserByID(ctx context.Context, db *sql.DB, id string) (*User, error) {
|
||||
|
||||
Reference in New Issue
Block a user