mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 15:51:26 +00:00
refactor(db): port operations, settings, audit, and misc metadata to sqlc (#84)
* refactor(db): port operations, settings, audit, activity, and misc service metadata to sqlc Covers the cross-cutting surface: operations board reads, app settings, notification producers, activity/audit inserts, builds upsert/cancel, git clone credential resolution, invites, environments, registry auth, project/service variables, HA resolver, boot sweeps, and admin user ops. Dynamic filtered lists and Better Auth table probes stay raw by design. Authored By: TDvorak <[email protected]> * refactor(db): port apwhy gateway handlers and proxy data plane to sqlc Final tranche — every static call site now uses generated queries. Raw SQL remains only where the statement is assembled at runtime (filtered lists, sparse updates, admin count closure) or probes Better Auth's auth_users table, which lives outside the local schema. Authored By: TDvorak <[email protected]>
This commit is contained in:
1 parent
66301bb68a
commit
0dc5857b5f
45 files changed
+3272
-689
No files matched your search
@@ -0,0 +1,125 @@
|
||||
-- name: GetAPServiceForValidate :one
|
||||
SELECT upstream_url, health_path, upstream_auth_header, upstream_auth_value, request_timeout_ms
|
||||
FROM api_services WHERE id = $1;
|
||||
|
||||
-- name: SetAPServiceValidation :exec
|
||||
UPDATE api_services
|
||||
SET last_validation_at = NOW(), last_validation_status = $1, last_validation_message = $2, updated_at = NOW()
|
||||
WHERE id = $3;
|
||||
|
||||
-- name: InsertServiceIncident :exec
|
||||
INSERT INTO incident_events (service_id, code, message, severity, http_status, occurred_at)
|
||||
VALUES ($1, 'SERVICE_VALIDATION_FAILED', $2, 'medium', $3, NOW());
|
||||
|
||||
-- name: InsertGatewayIncident :exec
|
||||
INSERT INTO incident_events (service_id, api_key_id, code, message, severity, http_status, occurred_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, NOW());
|
||||
|
||||
-- name: ListAPServices :many
|
||||
SELECT id, name, slug, upstream_url, route_prefix, enabled,
|
||||
to_char(created_at, 'YYYY-MM-DD"T"HH24:MI:SS"Z"') AS created_at,
|
||||
to_char(updated_at, 'YYYY-MM-DD"T"HH24:MI:SS"Z"') AS updated_at
|
||||
FROM api_services
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: InsertAPService :one
|
||||
INSERT INTO api_services (
|
||||
name, slug, upstream_url, route_prefix, health_path,
|
||||
rpm_limit, monthly_quota, created_at, updated_at
|
||||
) VALUES ($1, $2, $3, $4, '/health', $5, $6, NOW(), NOW())
|
||||
RETURNING id;
|
||||
|
||||
-- name: SetAPServiceEnabled :exec
|
||||
UPDATE api_services SET enabled = $1, updated_at = NOW() WHERE id = $2;
|
||||
|
||||
-- name: ListAPKeys :many
|
||||
SELECT id, name, key_prefix, plan, enabled, rpm_limit, monthly_quota,
|
||||
to_char(created_at, 'YYYY-MM-DD"T"HH24:MI:SS"Z"') AS created_at,
|
||||
to_char(updated_at, 'YYYY-MM-DD"T"HH24:MI:SS"Z"') AS updated_at
|
||||
FROM api_keys
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: InsertAPKey :one
|
||||
INSERT INTO api_keys (
|
||||
name, key_hash, key_prefix, plan, allowed_service_ids,
|
||||
rpm_limit, monthly_quota, created_at, updated_at
|
||||
) VALUES ($1, $2, $3, $4, '[]', $5, $6, NOW(), NOW())
|
||||
RETURNING id;
|
||||
|
||||
-- name: SetAPKeyEnabled :exec
|
||||
UPDATE api_keys SET enabled = $1, updated_at = NOW() WHERE id = $2;
|
||||
|
||||
-- name: CountAPServices :one
|
||||
SELECT COUNT(*) FROM api_services;
|
||||
|
||||
-- name: CountAPKeys :one
|
||||
SELECT COUNT(*) FROM api_keys;
|
||||
|
||||
-- name: SumUsageCounters :one
|
||||
SELECT COALESCE(SUM(request_count), 0) FROM usage_counters;
|
||||
|
||||
-- name: SumRequestMetricSince :one
|
||||
SELECT COALESCE(SUM(value), 0)::int
|
||||
FROM metrics_timeseries
|
||||
WHERE metric = 'request_total' AND occurred_at >= DATE_TRUNC($1::text, NOW());
|
||||
|
||||
-- name: ListTopAPServices :many
|
||||
SELECT s.id, s.name, COALESCE(SUM(u.request_count), 0) AS total_requests
|
||||
FROM api_services s
|
||||
LEFT JOIN usage_counters u ON u.service_id = s.id
|
||||
GROUP BY s.id, s.name
|
||||
ORDER BY total_requests DESC, s.name ASC
|
||||
LIMIT 10;
|
||||
|
||||
-- name: ListRequestsByDay :many
|
||||
SELECT TO_CHAR(DATE_TRUNC('day', occurred_at), 'YYYY-MM-DD') AS day_bucket, COUNT(*) AS total
|
||||
FROM metrics_timeseries
|
||||
WHERE metric = 'request_total' AND occurred_at >= NOW() - INTERVAL '7 days'
|
||||
GROUP BY DATE_TRUNC('day', occurred_at)
|
||||
ORDER BY DATE_TRUNC('day', occurred_at) ASC;
|
||||
|
||||
-- name: ListIncidentStatusCodes :many
|
||||
SELECT COALESCE(http_status, 0) AS status_code, COALESCE(SUM(count), 0) AS total
|
||||
FROM incident_events
|
||||
WHERE occurred_at >= NOW() - INTERVAL '7 days'
|
||||
GROUP BY COALESCE(http_status, 0)
|
||||
ORDER BY total DESC, status_code ASC;
|
||||
|
||||
-- name: ListClientEventPaths :many
|
||||
SELECT COALESCE((labels_json::jsonb ->> 'path'), 'unknown') AS path, COUNT(*) AS total
|
||||
FROM metrics_timeseries
|
||||
WHERE metric = 'client_event' AND occurred_at >= NOW() - INTERVAL '7 days'
|
||||
GROUP BY COALESCE((labels_json::jsonb ->> 'path'), 'unknown')
|
||||
ORDER BY total DESC, path ASC
|
||||
LIMIT 20;
|
||||
|
||||
-- name: GetAPServiceBySlug :one
|
||||
SELECT id, upstream_url, route_prefix, upstream_auth_header,
|
||||
upstream_auth_value, enabled, rpm_limit, monthly_quota,
|
||||
request_timeout_ms
|
||||
FROM api_services WHERE slug = $1;
|
||||
|
||||
-- name: ListAPKeysByPrefix :many
|
||||
SELECT id, key_hash, enabled, rpm_limit, monthly_quota, allowed_service_ids
|
||||
FROM api_keys WHERE key_prefix = $1;
|
||||
|
||||
-- name: SumUsageByKey :one
|
||||
SELECT COALESCE(SUM(request_count), 0)::bigint FROM usage_counters
|
||||
WHERE api_key_id = $1 AND period_month = $2;
|
||||
|
||||
-- name: SumUsageByService :one
|
||||
SELECT COALESCE(SUM(request_count), 0)::bigint FROM usage_counters
|
||||
WHERE service_id = $1 AND period_month = $2;
|
||||
|
||||
-- name: UpsertUsageCounter :exec
|
||||
INSERT INTO usage_counters (api_key_id, service_id, period_month, request_count, updated_at)
|
||||
VALUES ($1, $2, $3, 1, NOW())
|
||||
ON CONFLICT (api_key_id, service_id, period_month)
|
||||
DO UPDATE SET request_count = usage_counters.request_count + 1, updated_at = NOW();
|
||||
|
||||
-- name: TouchAPKeyLastUsed :exec
|
||||
UPDATE api_keys SET last_used_at = NOW() WHERE id = $1;
|
||||
|
||||
-- name: InsertMetricPoint :exec
|
||||
INSERT INTO metrics_timeseries (metric, value, labels_json, occurred_at)
|
||||
VALUES ('gateway_request', 1, $1, NOW());
|
||||
@@ -0,0 +1,28 @@
|
||||
-- name: InsertAuditLog :exec
|
||||
INSERT INTO audit_logs (id, user_id, resource, resource_id, action, details, severity, category, label, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
|
||||
|
||||
-- name: InsertAuditLogWithRequest :exec
|
||||
INSERT INTO audit_logs (id, user_id, resource, resource_id, action, details, ip_address, user_agent, severity, category, label, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6::jsonb, $7::inet, $8, $9, $10, $11, $12);
|
||||
|
||||
-- name: PruneAuditLogs :execrows
|
||||
DELETE FROM audit_logs WHERE created_at < NOW() - ($1::int * INTERVAL '1 day');
|
||||
|
||||
-- name: ListAuditBackfillBatch :many
|
||||
SELECT id::text, resource, action FROM audit_logs
|
||||
WHERE label = '' AND id > $1::uuid ORDER BY id LIMIT 500;
|
||||
|
||||
-- name: SetAuditLogMetadata :exec
|
||||
UPDATE audit_logs SET severity = $1, category = $2, label = $3 WHERE id = $4::uuid;
|
||||
|
||||
-- name: ListResourceAuditLogs :many
|
||||
SELECT id, COALESCE(user_id::text, '')::text AS user_id, resource,
|
||||
COALESCE(resource_id::text, '')::text AS resource_id, action,
|
||||
COALESCE(details::text, '{}')::text AS details,
|
||||
COALESCE(ip_address::text, '')::text AS ip_address,
|
||||
COALESCE(user_agent, '') AS user_agent, created_at
|
||||
FROM audit_logs
|
||||
WHERE user_id::text = $1 AND resource = $2 AND resource_id::text = $3
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 100;
|
||||
@@ -35,3 +35,23 @@ FROM users WHERE id = $1;
|
||||
UPDATE users
|
||||
SET name = COALESCE($1::varchar, name), avatar_url = COALESCE($2::varchar, avatar_url)
|
||||
WHERE id = $3;
|
||||
|
||||
-- name: UpsertAdminUser :one
|
||||
INSERT INTO users (email, password_hash, name, is_admin)
|
||||
VALUES ($1, $2, $3, true)
|
||||
ON CONFLICT (email) DO UPDATE
|
||||
SET is_admin = true, updated_at = NOW()
|
||||
RETURNING id;
|
||||
|
||||
-- name: ListAdminUsers :many
|
||||
SELECT id, email, name, COALESCE(avatar_url, '') AS avatar_url, is_admin,
|
||||
COALESCE(to_char(created_at, 'YYYY-MM-DD"T"HH24:MI:SS"Z"'), '')::text AS created_at
|
||||
FROM users
|
||||
ORDER BY created_at ASC;
|
||||
|
||||
-- name: SetUserAdmin :execrows
|
||||
UPDATE users SET is_admin = $1, updated_at = NOW() WHERE id = $2;
|
||||
|
||||
-- name: GetAdminUserInfo :one
|
||||
SELECT email, COALESCE(name, '') AS name, is_admin
|
||||
FROM users WHERE id = $1;
|
||||
@@ -0,0 +1,33 @@
|
||||
-- name: UpsertBuild :exec
|
||||
INSERT INTO builds
|
||||
(id, project_id, service_id, status, progress, started_at, completed_at, image_name, image_tag, size, error, log, metadata, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13::jsonb, $14, $14)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
project_id = EXCLUDED.project_id,
|
||||
service_id = EXCLUDED.service_id,
|
||||
status = EXCLUDED.status,
|
||||
progress = EXCLUDED.progress,
|
||||
started_at = EXCLUDED.started_at,
|
||||
completed_at = EXCLUDED.completed_at,
|
||||
image_name = EXCLUDED.image_name,
|
||||
image_tag = EXCLUDED.image_tag,
|
||||
size = EXCLUDED.size,
|
||||
error = EXCLUDED.error,
|
||||
log = EXCLUDED.log,
|
||||
metadata = EXCLUDED.metadata,
|
||||
updated_at = EXCLUDED.updated_at;
|
||||
|
||||
-- name: GetBuild :one
|
||||
SELECT id, project_id, service_id, status, progress, started_at, completed_at, image_name, image_tag, size, error, log, metadata
|
||||
FROM builds
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: CancelBuild :execrows
|
||||
UPDATE builds
|
||||
SET status = 'cancelled',
|
||||
progress = 100,
|
||||
completed_at = $1,
|
||||
log = COALESCE(log, '') || $2,
|
||||
updated_at = $1
|
||||
WHERE id = $3
|
||||
AND status NOT IN ('success', 'failed', 'cancelled');
|
||||
@@ -127,3 +127,11 @@ SELECT s.id, s.project_id, s.name,
|
||||
s.created_at, s.updated_at
|
||||
FROM services s
|
||||
WHERE (s.git_branch = $1 OR $1 = '') AND (s.git_repo = $2 OR s.git_repo = $3);
|
||||
|
||||
-- name: GetGitRepoCloneByFullName :one
|
||||
SELECT clone_url, provider_id FROM git_repositories
|
||||
WHERE full_name = $1 AND user_id = $2 LIMIT 1;
|
||||
|
||||
-- name: GetGitRepoProviderByCloneURL :one
|
||||
SELECT provider_id FROM git_repositories
|
||||
WHERE clone_url = $1 AND user_id = $2 LIMIT 1;
|
||||
@@ -0,0 +1,29 @@
|
||||
-- name: CountProjects :one
|
||||
SELECT COUNT(*) FROM projects;
|
||||
|
||||
-- name: GetRegistryAuth :one
|
||||
SELECT username, password FROM registries
|
||||
WHERE owner_id::text = $1 AND host = $2;
|
||||
|
||||
-- name: UpdateServiceRuntimeMeta :exec
|
||||
UPDATE services SET port = $1, healthcheck_path = $2 WHERE id = $3;
|
||||
|
||||
-- name: UpdateServiceDeployMeta :exec
|
||||
UPDATE services SET port = $1, healthcheck_path = $2,
|
||||
volumes = COALESCE($3::jsonb, '[]'::jsonb),
|
||||
git_repo = NULLIF($4::text, ''), git_branch = NULLIF($5::text, ''), builder = $6
|
||||
WHERE id = $7;
|
||||
|
||||
-- name: InsertEnvVar :exec
|
||||
INSERT INTO environment_variables (id, service_id, key, value, is_secret, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7);
|
||||
|
||||
-- name: DeleteProjectVariables :exec
|
||||
DELETE FROM project_variables WHERE project_id = $1;
|
||||
|
||||
-- name: InsertProjectVariable :exec
|
||||
INSERT INTO project_variables (id, project_id, key, value, is_secret, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7);
|
||||
|
||||
-- name: GetProjectVariableValue :one
|
||||
SELECT value FROM project_variables WHERE project_id = $1 AND key = $2;
|
||||
@@ -0,0 +1,43 @@
|
||||
-- name: ListActiveOperationDeployments :many
|
||||
SELECT d.id, d.service_id, s.name AS service_name, p.name AS project_name, d.status,
|
||||
COALESCE(d.image_name, '') AS image, d.error, d.started_at, d.completed_at, d.created_at
|
||||
FROM deployments d
|
||||
JOIN services s ON s.id = d.service_id
|
||||
JOIN projects p ON p.id = s.project_id
|
||||
WHERE d.status IN ('queued','pending','building','deploying','rolling_back')
|
||||
AND (p.is_approved OR p.owner_id = $1 OR $2::bool
|
||||
OR EXISTS (SELECT 1 FROM project_members pm WHERE pm.project_id = p.id AND pm.user_id = $1))
|
||||
ORDER BY d.created_at ASC;
|
||||
|
||||
-- name: ListRecentFailedDeployments :many
|
||||
SELECT d.id, d.service_id, s.name AS service_name, p.name AS project_name, d.status,
|
||||
COALESCE(d.image_name, '') AS image, d.error, d.started_at, d.completed_at, d.created_at
|
||||
FROM deployments d
|
||||
JOIN services s ON s.id = d.service_id
|
||||
JOIN projects p ON p.id = s.project_id
|
||||
WHERE d.status IN ('failed','cancelled','rolled_back')
|
||||
AND d.updated_at > NOW() - INTERVAL '24 hours'
|
||||
AND (p.is_approved OR p.owner_id = $1 OR $2::bool
|
||||
OR EXISTS (SELECT 1 FROM project_members pm WHERE pm.project_id = p.id AND pm.user_id = $1))
|
||||
ORDER BY d.updated_at DESC
|
||||
LIMIT 20;
|
||||
|
||||
-- name: ListRecentCronRuns :many
|
||||
SELECT e.id, j.name AS job_name, j.schedule, e.status, e.started_at, e.finished_at, e.error
|
||||
FROM cron_executions e
|
||||
JOIN cron_jobs j ON j.id = e.cron_job_id
|
||||
JOIN projects p ON p.id = j.project_id
|
||||
WHERE e.started_at > NOW() - INTERVAL '24 hours'
|
||||
AND (p.is_approved OR p.owner_id = $1 OR $2::bool
|
||||
OR EXISTS (SELECT 1 FROM project_members pm WHERE pm.project_id = p.id AND pm.user_id = $1))
|
||||
ORDER BY e.started_at DESC
|
||||
LIMIT 30;
|
||||
|
||||
-- name: ListRecentOperationBackups :many
|
||||
SELECT b.id, b.database_id, ds.name AS db_name, b.status, b.size, b.created_at, b.completed_at
|
||||
FROM database_backups b
|
||||
JOIN database_services ds ON ds.id = b.database_id
|
||||
WHERE b.created_at > NOW() - INTERVAL '24 hours'
|
||||
AND (ds.user_id = $1 OR $2::bool)
|
||||
ORDER BY b.created_at DESC
|
||||
LIMIT 20;
|
||||
@@ -0,0 +1,62 @@
|
||||
-- name: GetServiceSleep :one
|
||||
SELECT COALESCE(sleep_enabled, false) AS sleep_enabled, COALESCE(sleep_idle_minutes, 15) AS sleep_idle_minutes
|
||||
FROM services WHERE id = $1;
|
||||
|
||||
-- name: GetServiceNodeID :one
|
||||
SELECT node_id FROM services WHERE id = $1;
|
||||
|
||||
-- name: GetServiceSpread :one
|
||||
SELECT COALESCE(spread, false) FROM services WHERE id = $1;
|
||||
|
||||
-- name: GetServicePlacementTags :one
|
||||
SELECT placement_tags FROM services WHERE id = $1;
|
||||
|
||||
-- name: GetServiceTraefikLabels :one
|
||||
SELECT traefik_labels FROM services WHERE id = $1;
|
||||
|
||||
-- name: GetServiceVolumes :one
|
||||
SELECT volumes FROM services WHERE id = $1;
|
||||
|
||||
-- name: GetNodeAgentName :one
|
||||
SELECT name FROM node_agents WHERE id = $1;
|
||||
|
||||
-- name: GetServiceProjectID :one
|
||||
SELECT project_id FROM services WHERE id = $1;
|
||||
|
||||
-- name: GetServiceProjectAndStatus :one
|
||||
SELECT s.project_id, COALESCE(s.status, '') AS status
|
||||
FROM services s WHERE s.id = $1;
|
||||
|
||||
-- name: GetEnvironmentProjectID :one
|
||||
SELECT project_id FROM environments WHERE id = $1;
|
||||
|
||||
-- name: GetProjectReadAccess :one
|
||||
SELECT is_approved, owner_id::text FROM projects WHERE id = $1;
|
||||
|
||||
-- name: ProjectMemberExists :one
|
||||
SELECT EXISTS(SELECT 1 FROM project_members WHERE project_id = $1 AND user_id = $2);
|
||||
|
||||
-- name: DeleteEnvVarsForService :exec
|
||||
DELETE FROM environment_variables WHERE service_id = $1;
|
||||
|
||||
-- name: FailInterruptedDeployments :exec
|
||||
UPDATE deployments SET status = 'failed', error = 'Interrupted by server restart', completed_at = NOW(), updated_at = NOW()
|
||||
WHERE status IN ('queued', 'pending', 'building', 'deploying', 'rolling_back');
|
||||
|
||||
-- name: ListSecretEnvVars :many
|
||||
SELECT id, value FROM environment_variables WHERE is_secret = TRUE;
|
||||
|
||||
-- name: UpdateEnvVarValue :exec
|
||||
UPDATE environment_variables SET value = $1, updated_at = NOW() WHERE id = $2;
|
||||
|
||||
-- name: ListAgentHealthRows :many
|
||||
SELECT id, COALESCE(name, hostname, id::text) AS name, COALESCE(status, '') AS status,
|
||||
COALESCE(last_heartbeat < $1, TRUE)::bool AS stale, auto_prune
|
||||
FROM node_agents;
|
||||
|
||||
-- name: SetAgentStatus :exec
|
||||
UPDATE node_agents SET status = $1, updated_at = NOW() WHERE id = $2;
|
||||
|
||||
-- name: GetServiceNameProjectPort :one
|
||||
SELECT name, project_id::text, COALESCE(port, 0)::int AS port
|
||||
FROM services WHERE id::text = $1;
|
||||
@@ -0,0 +1,21 @@
|
||||
-- name: GetAppSetting :one
|
||||
SELECT value FROM app_settings WHERE key = $1;
|
||||
|
||||
-- name: UpsertAppSetting :exec
|
||||
INSERT INTO app_settings (key, value, is_secret, updated_at)
|
||||
VALUES ($1, $2, $3, NOW())
|
||||
ON CONFLICT (key) DO UPDATE
|
||||
SET value = EXCLUDED.value, is_secret = EXCLUDED.is_secret, updated_at = NOW();
|
||||
|
||||
-- name: UpsertAppSettingValue :exec
|
||||
INSERT INTO app_settings (key, value, updated_at) VALUES ($1, $2, NOW())
|
||||
ON CONFLICT (key) DO UPDATE SET value = $2, updated_at = NOW();
|
||||
|
||||
-- name: DeleteAppSetting :exec
|
||||
DELETE FROM app_settings WHERE key = $1;
|
||||
|
||||
-- name: GetUserIsAdmin :one
|
||||
SELECT is_admin FROM users WHERE id = $1;
|
||||
|
||||
-- name: ListAdminUserIDs :many
|
||||
SELECT id FROM users WHERE is_admin;
|
||||
Reference in new issue
Block a user