Go · 17054 bytes Raw Blame History
1 // Code generated by sqlc. DO NOT EDIT.
2 // versions:
3 // sqlc v1.31.1
4 // source: admin.sql
5
6 package admindb
7
8 import (
9 "context"
10
11 "github.com/jackc/pgx/v5/pgtype"
12 )
13
14 const adminDiscardJob = `-- name: AdminDiscardJob :exec
15 UPDATE jobs
16 SET failed_at = now(),
17 last_error = 'discarded by site admin'
18 WHERE id = $1
19 `
20
21 // Mark a job dead without running it. Caller has already confirmed.
22 func (q *Queries) AdminDiscardJob(ctx context.Context, db DBTX, id int64) error {
23 _, err := db.Exec(ctx, adminDiscardJob, id)
24 return err
25 }
26
27 const adminRetryJob = `-- name: AdminRetryJob :exec
28 UPDATE jobs
29 SET run_at = now(),
30 attempts = 0,
31 last_error = NULL,
32 failed_at = NULL,
33 completed_at = NULL,
34 locked_by = NULL,
35 locked_at = NULL
36 WHERE id = $1
37 `
38
39 // Re-arm a failed/dead job for immediate retry: clear failure state,
40 // reset attempts, and set run_at to now() so the pool picks it up
41 // on the next tick.
42 func (q *Queries) AdminRetryJob(ctx context.Context, db DBTX, id int64) error {
43 _, err := db.Exec(ctx, adminRetryJob, id)
44 return err
45 }
46
47 const countActiveOrgs = `-- name: CountActiveOrgs :one
48 SELECT COUNT(*) FROM orgs WHERE deleted_at IS NULL
49 `
50
51 func (q *Queries) CountActiveOrgs(ctx context.Context, db DBTX) (int64, error) {
52 row := db.QueryRow(ctx, countActiveOrgs)
53 var count int64
54 err := row.Scan(&count)
55 return count, err
56 }
57
58 const countActiveRepos = `-- name: CountActiveRepos :one
59 SELECT COUNT(*) FROM repos WHERE deleted_at IS NULL
60 `
61
62 func (q *Queries) CountActiveRepos(ctx context.Context, db DBTX) (int64, error) {
63 row := db.QueryRow(ctx, countActiveRepos)
64 var count int64
65 err := row.Scan(&count)
66 return count, err
67 }
68
69 const countActiveUsers = `-- name: CountActiveUsers :one
70
71
72 SELECT COUNT(*) FROM users WHERE deleted_at IS NULL
73 `
74
75 // SPDX-License-Identifier: AGPL-3.0-or-later
76 //
77 // Admin-only query surface for /admin/*. Non-admin handlers should
78 // use the per-domain packages (usersdb, reposdb, …) directly. This
79 // file collects the cross-cutting reads + writes the admin UI needs:
80 // - dashboard counts
81 // - user/repo listings with admin-only filters (suspended, deleted)
82 // - site-admin flag toggle
83 // - transactional_email_log read/write
84 //
85 // Queries that already exist in their domain package (e.g.
86 // users.SuspendUser) are reused directly — no duplication here.
87 // ─── dashboard counts ────────────────────────────────────────────
88 func (q *Queries) CountActiveUsers(ctx context.Context, db DBTX) (int64, error) {
89 row := db.QueryRow(ctx, countActiveUsers)
90 var count int64
91 err := row.Scan(&count)
92 return count, err
93 }
94
95 const countJobsByStatus = `-- name: CountJobsByStatus :many
96 SELECT
97 CASE
98 WHEN completed_at IS NOT NULL THEN 'completed'
99 WHEN failed_at IS NOT NULL THEN 'failed'
100 WHEN locked_at IS NOT NULL THEN 'running'
101 ELSE 'queued'
102 END AS status,
103 COUNT(*)::bigint AS n
104 FROM jobs
105 GROUP BY 1
106 `
107
108 type CountJobsByStatusRow struct {
109 Status string
110 N int64
111 }
112
113 // Status is derived from the timestamp columns since the jobs table
114 // doesn't carry an enum: completed > failed > running > queued.
115 func (q *Queries) CountJobsByStatus(ctx context.Context, db DBTX) ([]CountJobsByStatusRow, error) {
116 rows, err := db.Query(ctx, countJobsByStatus)
117 if err != nil {
118 return nil, err
119 }
120 defer rows.Close()
121 items := []CountJobsByStatusRow{}
122 for rows.Next() {
123 var i CountJobsByStatusRow
124 if err := rows.Scan(&i.Status, &i.N); err != nil {
125 return nil, err
126 }
127 items = append(items, i)
128 }
129 if err := rows.Err(); err != nil {
130 return nil, err
131 }
132 return items, nil
133 }
134
135 const countSiteAdmins = `-- name: CountSiteAdmins :one
136 SELECT COUNT(*) FROM users WHERE is_site_admin = true AND deleted_at IS NULL
137 `
138
139 func (q *Queries) CountSiteAdmins(ctx context.Context, db DBTX) (int64, error) {
140 row := db.QueryRow(ctx, countSiteAdmins)
141 var count int64
142 err := row.Scan(&count)
143 return count, err
144 }
145
146 const countSuspendedUsers = `-- name: CountSuspendedUsers :one
147 SELECT COUNT(*) FROM users WHERE suspended_at IS NOT NULL AND deleted_at IS NULL
148 `
149
150 func (q *Queries) CountSuspendedUsers(ctx context.Context, db DBTX) (int64, error) {
151 row := db.QueryRow(ctx, countSuspendedUsers)
152 var count int64
153 err := row.Scan(&count)
154 return count, err
155 }
156
157 const getJobForAdmin = `-- name: GetJobForAdmin :one
158 SELECT id, kind, payload, run_at, attempts, max_attempts,
159 last_error, locked_by, locked_at, completed_at, failed_at, created_at
160 FROM jobs
161 WHERE id = $1
162 `
163
164 func (q *Queries) GetJobForAdmin(ctx context.Context, db DBTX, id int64) (Job, error) {
165 row := db.QueryRow(ctx, getJobForAdmin, id)
166 var i Job
167 err := row.Scan(
168 &i.ID,
169 &i.Kind,
170 &i.Payload,
171 &i.RunAt,
172 &i.Attempts,
173 &i.MaxAttempts,
174 &i.LastError,
175 &i.LockedBy,
176 &i.LockedAt,
177 &i.CompletedAt,
178 &i.FailedAt,
179 &i.CreatedAt,
180 )
181 return i, err
182 }
183
184 const insertTransactionalEmail = `-- name: InsertTransactionalEmail :one
185
186 INSERT INTO transactional_email_log (
187 recipient_user_id, recipient_email, kind, subject, provider_id,
188 status, error_summary
189 ) VALUES (
190 $1::bigint,
191 $2,
192 $3,
193 $4,
194 $5,
195 $6,
196 $7::text
197 )
198 RETURNING id
199 `
200
201 type InsertTransactionalEmailParams struct {
202 RecipientUserID pgtype.Int8
203 RecipientEmail string
204 Kind string
205 Subject string
206 ProviderID string
207 Status TransactionalEmailStatus
208 ErrorSummary pgtype.Text
209 }
210
211 // ─── transactional email log ─────────────────────────────────────
212 func (q *Queries) InsertTransactionalEmail(ctx context.Context, db DBTX, arg InsertTransactionalEmailParams) (int64, error) {
213 row := db.QueryRow(ctx, insertTransactionalEmail,
214 arg.RecipientUserID,
215 arg.RecipientEmail,
216 arg.Kind,
217 arg.Subject,
218 arg.ProviderID,
219 arg.Status,
220 arg.ErrorSummary,
221 )
222 var id int64
223 err := row.Scan(&id)
224 return id, err
225 }
226
227 const listAuditForAdmin = `-- name: ListAuditForAdmin :many
228
229 SELECT id, actor_id, action, target_type, target_id, meta, created_at
230 FROM auth_audit_log
231 WHERE
232 ($3::bigint IS NULL OR actor_id = $3::bigint)
233 AND ($4::text IS NULL OR action ILIKE $4::text || '%')
234 AND ($5::text IS NULL OR target_type = $5::text)
235 AND ($6::bigint IS NULL OR target_id = $6::bigint)
236 AND ($7::timestamptz IS NULL OR created_at >= $7::timestamptz)
237 AND ($8::timestamptz IS NULL OR created_at < $8::timestamptz)
238 ORDER BY created_at DESC, id DESC
239 LIMIT $1 OFFSET $2
240 `
241
242 type ListAuditForAdminParams struct {
243 Limit int32
244 Offset int32
245 ActorID pgtype.Int8
246 ActionPrefix pgtype.Text
247 TargetType pgtype.Text
248 TargetID pgtype.Int8
249 Since pgtype.Timestamptz
250 Until pgtype.Timestamptz
251 }
252
253 // ─── audit log viewer ────────────────────────────────────────────
254 // Filters: actor, action prefix, target type+id, time range. Keyset
255 // pagination on (created_at, id) keeps deep pages cheap.
256 func (q *Queries) ListAuditForAdmin(ctx context.Context, db DBTX, arg ListAuditForAdminParams) ([]AuthAuditLog, error) {
257 rows, err := db.Query(ctx, listAuditForAdmin,
258 arg.Limit,
259 arg.Offset,
260 arg.ActorID,
261 arg.ActionPrefix,
262 arg.TargetType,
263 arg.TargetID,
264 arg.Since,
265 arg.Until,
266 )
267 if err != nil {
268 return nil, err
269 }
270 defer rows.Close()
271 items := []AuthAuditLog{}
272 for rows.Next() {
273 var i AuthAuditLog
274 if err := rows.Scan(
275 &i.ID,
276 &i.ActorID,
277 &i.Action,
278 &i.TargetType,
279 &i.TargetID,
280 &i.Meta,
281 &i.CreatedAt,
282 ); err != nil {
283 return nil, err
284 }
285 items = append(items, i)
286 }
287 if err := rows.Err(); err != nil {
288 return nil, err
289 }
290 return items, nil
291 }
292
293 const listJobsForAdmin = `-- name: ListJobsForAdmin :many
294
295 SELECT id, kind, payload, run_at, attempts, max_attempts,
296 last_error, locked_by, locked_at, completed_at, failed_at, created_at,
297 CASE
298 WHEN completed_at IS NOT NULL THEN 'completed'
299 WHEN failed_at IS NOT NULL THEN 'failed'
300 WHEN locked_at IS NOT NULL THEN 'running'
301 ELSE 'queued'
302 END AS status
303 FROM jobs
304 WHERE
305 ($3::text IS NULL OR kind = $3::text)
306 AND (
307 $4::text IS NULL
308 OR ($4::text = 'queued' AND completed_at IS NULL AND failed_at IS NULL AND locked_at IS NULL)
309 OR ($4::text = 'running' AND completed_at IS NULL AND failed_at IS NULL AND locked_at IS NOT NULL)
310 OR ($4::text = 'failed' AND failed_at IS NOT NULL)
311 OR ($4::text = 'completed' AND completed_at IS NOT NULL)
312 )
313 ORDER BY id DESC
314 LIMIT $1 OFFSET $2
315 `
316
317 type ListJobsForAdminParams struct {
318 Limit int32
319 Offset int32
320 Kind pgtype.Text
321 StatusFilter pgtype.Text
322 }
323
324 type ListJobsForAdminRow struct {
325 ID int64
326 Kind string
327 Payload []byte
328 RunAt pgtype.Timestamptz
329 Attempts int32
330 MaxAttempts int32
331 LastError pgtype.Text
332 LockedBy pgtype.Text
333 LockedAt pgtype.Timestamptz
334 CompletedAt pgtype.Timestamptz
335 FailedAt pgtype.Timestamptz
336 CreatedAt pgtype.Timestamptz
337 Status string
338 }
339
340 // ─── jobs queue inspector ────────────────────────────────────────
341 // The admin can filter by kind + status (computed from the timestamp
342 // columns). Status filter values: queued | running | failed | completed.
343 func (q *Queries) ListJobsForAdmin(ctx context.Context, db DBTX, arg ListJobsForAdminParams) ([]ListJobsForAdminRow, error) {
344 rows, err := db.Query(ctx, listJobsForAdmin,
345 arg.Limit,
346 arg.Offset,
347 arg.Kind,
348 arg.StatusFilter,
349 )
350 if err != nil {
351 return nil, err
352 }
353 defer rows.Close()
354 items := []ListJobsForAdminRow{}
355 for rows.Next() {
356 var i ListJobsForAdminRow
357 if err := rows.Scan(
358 &i.ID,
359 &i.Kind,
360 &i.Payload,
361 &i.RunAt,
362 &i.Attempts,
363 &i.MaxAttempts,
364 &i.LastError,
365 &i.LockedBy,
366 &i.LockedAt,
367 &i.CompletedAt,
368 &i.FailedAt,
369 &i.CreatedAt,
370 &i.Status,
371 ); err != nil {
372 return nil, err
373 }
374 items = append(items, i)
375 }
376 if err := rows.Err(); err != nil {
377 return nil, err
378 }
379 return items, nil
380 }
381
382 const listRecentTransactionalEmails = `-- name: ListRecentTransactionalEmails :many
383 SELECT id, recipient_user_id, recipient_email, kind, subject,
384 provider_id, status, error_summary, sent_at, delivered_at
385 FROM transactional_email_log
386 WHERE ($2::transactional_email_status IS NULL
387 OR status = $2::transactional_email_status)
388 ORDER BY sent_at DESC
389 LIMIT $1
390 `
391
392 type ListRecentTransactionalEmailsParams struct {
393 Limit int32
394 Status NullTransactionalEmailStatus
395 }
396
397 // Admin email-queue surface. Most recent first; status filter optional.
398 func (q *Queries) ListRecentTransactionalEmails(ctx context.Context, db DBTX, arg ListRecentTransactionalEmailsParams) ([]TransactionalEmailLog, error) {
399 rows, err := db.Query(ctx, listRecentTransactionalEmails, arg.Limit, arg.Status)
400 if err != nil {
401 return nil, err
402 }
403 defer rows.Close()
404 items := []TransactionalEmailLog{}
405 for rows.Next() {
406 var i TransactionalEmailLog
407 if err := rows.Scan(
408 &i.ID,
409 &i.RecipientUserID,
410 &i.RecipientEmail,
411 &i.Kind,
412 &i.Subject,
413 &i.ProviderID,
414 &i.Status,
415 &i.ErrorSummary,
416 &i.SentAt,
417 &i.DeliveredAt,
418 ); err != nil {
419 return nil, err
420 }
421 items = append(items, i)
422 }
423 if err := rows.Err(); err != nil {
424 return nil, err
425 }
426 return items, nil
427 }
428
429 const listReposForAdmin = `-- name: ListReposForAdmin :many
430
431 SELECT r.id, r.owner_user_id, r.owner_org_id, r.name, r.visibility,
432 r.is_archived, r.deleted_at, r.disk_used_bytes, r.created_at,
433 u.username AS owner_user_username,
434 o.slug AS owner_org_slug
435 FROM repos r
436 LEFT JOIN users u ON u.id = r.owner_user_id
437 LEFT JOIN orgs o ON o.id = r.owner_org_id
438 WHERE
439 ($3::text IS NULL OR r.name ILIKE $3::text || '%')
440 AND ($4::bool IS NOT TRUE OR r.deleted_at IS NOT NULL)
441 AND ($5::bool IS NOT TRUE OR r.is_archived = true)
442 AND ($6::repo_visibility IS NULL OR r.visibility = $6::repo_visibility)
443 ORDER BY r.id DESC
444 LIMIT $1 OFFSET $2
445 `
446
447 type ListReposForAdminParams struct {
448 Limit int32
449 Offset int32
450 NamePrefix pgtype.Text
451 DeletedOnly pgtype.Bool
452 ArchivedOnly pgtype.Bool
453 VisibilityFilter NullRepoVisibility
454 }
455
456 type ListReposForAdminRow struct {
457 ID int64
458 OwnerUserID pgtype.Int8
459 OwnerOrgID pgtype.Int8
460 Name string
461 Visibility RepoVisibility
462 IsArchived bool
463 DeletedAt pgtype.Timestamptz
464 DiskUsedBytes int64
465 CreatedAt pgtype.Timestamptz
466 OwnerUserUsername pgtype.Text
467 OwnerOrgSlug pgtype.Text
468 }
469
470 // ─── repos list ──────────────────────────────────────────────────
471 func (q *Queries) ListReposForAdmin(ctx context.Context, db DBTX, arg ListReposForAdminParams) ([]ListReposForAdminRow, error) {
472 rows, err := db.Query(ctx, listReposForAdmin,
473 arg.Limit,
474 arg.Offset,
475 arg.NamePrefix,
476 arg.DeletedOnly,
477 arg.ArchivedOnly,
478 arg.VisibilityFilter,
479 )
480 if err != nil {
481 return nil, err
482 }
483 defer rows.Close()
484 items := []ListReposForAdminRow{}
485 for rows.Next() {
486 var i ListReposForAdminRow
487 if err := rows.Scan(
488 &i.ID,
489 &i.OwnerUserID,
490 &i.OwnerOrgID,
491 &i.Name,
492 &i.Visibility,
493 &i.IsArchived,
494 &i.DeletedAt,
495 &i.DiskUsedBytes,
496 &i.CreatedAt,
497 &i.OwnerUserUsername,
498 &i.OwnerOrgSlug,
499 ); err != nil {
500 return nil, err
501 }
502 items = append(items, i)
503 }
504 if err := rows.Err(); err != nil {
505 return nil, err
506 }
507 return items, nil
508 }
509
510 const listUsersForAdmin = `-- name: ListUsersForAdmin :many
511
512 SELECT id, username, display_name, primary_email_id,
513 suspended_at, deleted_at, last_login_at, is_site_admin,
514 created_at
515 FROM users
516 WHERE
517 ($3::text IS NULL OR username::text ILIKE $3::text || '%')
518 AND ($4::bool IS NOT TRUE OR suspended_at IS NOT NULL)
519 AND ($5::bool IS NOT TRUE OR deleted_at IS NOT NULL)
520 ORDER BY id DESC
521 LIMIT $1 OFFSET $2
522 `
523
524 type ListUsersForAdminParams struct {
525 Limit int32
526 Offset int32
527 UsernamePrefix pgtype.Text
528 SuspendedOnly pgtype.Bool
529 DeletedOnly pgtype.Bool
530 }
531
532 type ListUsersForAdminRow struct {
533 ID int64
534 Username string
535 DisplayName string
536 PrimaryEmailID pgtype.Int8
537 SuspendedAt pgtype.Timestamptz
538 DeletedAt pgtype.Timestamptz
539 LastLoginAt pgtype.Timestamptz
540 IsSiteAdmin bool
541 CreatedAt pgtype.Timestamptz
542 }
543
544 // ─── users list ──────────────────────────────────────────────────
545 // Filters: optional username prefix, optional suspended/deleted-only.
546 // All filters use sqlc.narg so the empty case is "no filter".
547 func (q *Queries) ListUsersForAdmin(ctx context.Context, db DBTX, arg ListUsersForAdminParams) ([]ListUsersForAdminRow, error) {
548 rows, err := db.Query(ctx, listUsersForAdmin,
549 arg.Limit,
550 arg.Offset,
551 arg.UsernamePrefix,
552 arg.SuspendedOnly,
553 arg.DeletedOnly,
554 )
555 if err != nil {
556 return nil, err
557 }
558 defer rows.Close()
559 items := []ListUsersForAdminRow{}
560 for rows.Next() {
561 var i ListUsersForAdminRow
562 if err := rows.Scan(
563 &i.ID,
564 &i.Username,
565 &i.DisplayName,
566 &i.PrimaryEmailID,
567 &i.SuspendedAt,
568 &i.DeletedAt,
569 &i.LastLoginAt,
570 &i.IsSiteAdmin,
571 &i.CreatedAt,
572 ); err != nil {
573 return nil, err
574 }
575 items = append(items, i)
576 }
577 if err := rows.Err(); err != nil {
578 return nil, err
579 }
580 return items, nil
581 }
582
583 const markTransactionalEmailDelivered = `-- name: MarkTransactionalEmailDelivered :exec
584 UPDATE transactional_email_log
585 SET status = 'sent',
586 delivered_at = now(),
587 error_summary = NULL
588 WHERE id = $1
589 `
590
591 func (q *Queries) MarkTransactionalEmailDelivered(ctx context.Context, db DBTX, id int64) error {
592 _, err := db.Exec(ctx, markTransactionalEmailDelivered, id)
593 return err
594 }
595
596 const markTransactionalEmailFailed = `-- name: MarkTransactionalEmailFailed :exec
597 UPDATE transactional_email_log
598 SET status = $2,
599 error_summary = $3
600 WHERE id = $1
601 `
602
603 type MarkTransactionalEmailFailedParams struct {
604 ID int64
605 Status TransactionalEmailStatus
606 ErrorSummary pgtype.Text
607 }
608
609 func (q *Queries) MarkTransactionalEmailFailed(ctx context.Context, db DBTX, arg MarkTransactionalEmailFailedParams) error {
610 _, err := db.Exec(ctx, markTransactionalEmailFailed, arg.ID, arg.Status, arg.ErrorSummary)
611 return err
612 }
613
614 const setUserSiteAdmin = `-- name: SetUserSiteAdmin :exec
615 UPDATE users
616 SET is_site_admin = $2,
617 updated_at = now()
618 WHERE id = $1
619 `
620
621 type SetUserSiteAdminParams struct {
622 ID int64
623 IsSiteAdmin bool
624 }
625
626 func (q *Queries) SetUserSiteAdmin(ctx context.Context, db DBTX, arg SetUserSiteAdminParams) error {
627 _, err := db.Exec(ctx, setUserSiteAdmin, arg.ID, arg.IsSiteAdmin)
628 return err
629 }
630