feat(config,workspace,user): jobs/notify config + workspace fetch repo + user ListAdmins

This commit is contained in:
2026-05-06 09:10:43 +08:00
parent 895799a6c9
commit 7b3892c42e
13 changed files with 338 additions and 6 deletions
+20 -6
View File
@@ -1,6 +1,6 @@
// Package user 内的 repository.go 是 sqlc 生成的查询包(usersqlc)之上的薄
// 包装层。它的唯一职责是把 驱动层类型(pgtype.UUID / pgtype.Timestamptz /
// int32 等)和 领域类型(uuid.UUID / time.Time / int / *time.Time)做双向
// 包装层。它的唯一职责是把 "驱动层类型"(pgtype.UUID / pgtype.Timestamptz /
// int32 等)和 "领域类型"(uuid.UUID / time.Time / int / *time.Time)做双向
// 转换,并把底层的 pgx.ErrNoRows 翻译为 errs.AppError,使 service 层可以面
// 向干净的领域接口编程,无需直接依赖驱动细节。
//
@@ -35,6 +35,7 @@ type Repository interface {
GetUserByEmail(ctx context.Context, email string) (*User, error)
GetUserByID(ctx context.Context, id uuid.UUID) (*User, error)
CountUsers(ctx context.Context) (int, error)
ListAdmins(ctx context.Context) ([]*User, error)
CreateSession(ctx context.Context, s *Session) error
GetSessionByTokenHash(ctx context.Context, hash []byte) (*Session, error)
@@ -61,7 +62,7 @@ func toPgUUID(u uuid.UUID) pgtype.UUID {
}
// fromPgUUID 把 pgtype.UUID 转回领域 uuid.UUID。Valid=false 时返回 uuid.Nil,
// 让上层用零值判定 无值,无需关心驱动层的可空封装。
// 让上层用零值判定 "无值",无需关心驱动层的可空封装。
func fromPgUUID(p pgtype.UUID) uuid.UUID {
if !p.Valid {
return uuid.Nil
@@ -168,8 +169,8 @@ func (r *pgRepo) CreateSession(ctx context.Context, s *Session) error {
}
// GetSessionByTokenHash 按 sha256 摘要反查会话。该方法主要给鉴权中间件
// 使用,因此 ErrNoRows 翻译为 Unauthorized 而非 NotFound:从语义看 找不到
// 会话 等价于 未认证,不应该把内部存在性细节透给客户端。
// 使用,因此 ErrNoRows 翻译为 Unauthorized 而非 NotFound:从语义看 "找不到
// 会话" 等价于 "未认证",不应该把内部存在性细节透给客户端。
func (r *pgRepo) GetSessionByTokenHash(ctx context.Context, hash []byte) (*Session, error) {
row, err := r.q.GetSessionByTokenHash(ctx, hash)
if err != nil {
@@ -191,10 +192,23 @@ func (r *pgRepo) TouchSession(ctx context.Context, hash []byte) error {
}
// DeleteSessionByTokenHash 删除指定哈希的会话。删除不存在的行不算错误,
// 调用方可以放心当作 登出幂等 使用。
// 调用方可以放心当作 "登出幂等" 使用。
func (r *pgRepo) DeleteSessionByTokenHash(ctx context.Context, hash []byte) error {
if err := r.q.DeleteSessionByTokenHash(ctx, hash); err != nil {
return errs.Wrap(err, errs.CodeInternal, "delete session by token hash")
}
return nil
}
// ListAdmins 返回所有 is_admin=true 的用户,供 jobs runner 等内部模块使用。
func (r *pgRepo) ListAdmins(ctx context.Context) ([]*User, error) {
rows, err := r.q.ListAdmins(ctx)
if err != nil {
return nil, errs.Wrap(err, errs.CodeInternal, "list admins")
}
out := make([]*User, 0, len(rows))
for _, row := range rows {
out = append(out, rowToUser(row))
}
return out, nil
}