feat(auth,prompt-rule): add password change with session revocation and scope prompt rules by brand
Add self-service password change that re-hashes the credential and bumps a per-user session version so all existing access/refresh tokens are rejected. Session version is tracked in Redis with an in-memory fallback and enforced in middleware and refresh. Scope prompt rules and rule groups to a brand: new brand_id column (migrated to a "未归属" fallback brand for existing rows), brand-filtered queries/indexes, and brand-aware admin-web tabs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,12 @@ SELECT id, email, phone, password_hash, name, avatar_url, status, created_at, up
|
||||
FROM users
|
||||
WHERE id = sqlc.arg(id) AND deleted_at IS NULL;
|
||||
|
||||
-- name: UpdateUserPassword :exec
|
||||
UPDATE users
|
||||
SET password_hash = sqlc.arg(password_hash),
|
||||
updated_at = NOW()
|
||||
WHERE id = sqlc.arg(id) AND deleted_at IS NULL;
|
||||
|
||||
-- name: GetTenantMembership :one
|
||||
SELECT tm.id,
|
||||
tm.tenant_id,
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
-- name: ListPromptRuleGroups :many
|
||||
SELECT id, tenant_id, name, sort_order, created_at, updated_at
|
||||
FROM prompt_rule_groups
|
||||
WHERE tenant_id = sqlc.arg(tenant_id) AND deleted_at IS NULL
|
||||
WHERE tenant_id = sqlc.arg(tenant_id) AND brand_id = sqlc.arg(brand_id) AND deleted_at IS NULL
|
||||
ORDER BY sort_order, created_at;
|
||||
|
||||
-- name: CreatePromptRuleGroup :one
|
||||
INSERT INTO prompt_rule_groups (tenant_id, name, sort_order)
|
||||
VALUES (sqlc.arg(tenant_id), sqlc.arg(name), sqlc.arg(sort_order))
|
||||
INSERT INTO prompt_rule_groups (tenant_id, brand_id, name, sort_order)
|
||||
VALUES (sqlc.arg(tenant_id), sqlc.arg(brand_id), sqlc.arg(name), sqlc.arg(sort_order))
|
||||
RETURNING id, created_at;
|
||||
|
||||
-- name: UpdatePromptRuleGroup :exec
|
||||
UPDATE prompt_rule_groups SET name = sqlc.arg(name), sort_order = sqlc.arg(sort_order), updated_at = NOW()
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND deleted_at IS NULL;
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND brand_id = sqlc.arg(brand_id) AND deleted_at IS NULL;
|
||||
|
||||
-- name: SoftDeletePromptRuleGroup :exec
|
||||
UPDATE prompt_rule_groups SET deleted_at = NOW(), updated_at = NOW()
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND deleted_at IS NULL;
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND brand_id = sqlc.arg(brand_id) AND deleted_at IS NULL;
|
||||
|
||||
-- ============================================================
|
||||
-- Prompt Rules
|
||||
@@ -31,8 +31,9 @@ SELECT pr.id, pr.tenant_id, pr.group_id, pr.name, pr.prompt_content,
|
||||
pr.created_at, pr.updated_at,
|
||||
COUNT(a.id)::INT AS article_count
|
||||
FROM prompt_rules pr
|
||||
LEFT JOIN articles a ON a.prompt_rule_id = pr.id AND a.deleted_at IS NULL
|
||||
LEFT JOIN articles a ON a.prompt_rule_id = pr.id AND a.brand_id = pr.brand_id AND a.deleted_at IS NULL
|
||||
WHERE pr.tenant_id = sqlc.arg(tenant_id)
|
||||
AND pr.brand_id = sqlc.arg(brand_id)
|
||||
AND pr.deleted_at IS NULL
|
||||
AND (sqlc.narg(group_id)::bigint IS NULL OR pr.group_id = sqlc.narg(group_id))
|
||||
AND (sqlc.narg(status)::text IS NULL OR pr.status = sqlc.narg(status))
|
||||
@@ -45,6 +46,7 @@ LIMIT sqlc.arg(page_size) OFFSET sqlc.arg(page_offset);
|
||||
SELECT COUNT(*)
|
||||
FROM prompt_rules
|
||||
WHERE tenant_id = sqlc.arg(tenant_id)
|
||||
AND brand_id = sqlc.arg(brand_id)
|
||||
AND deleted_at IS NULL
|
||||
AND (sqlc.narg(group_id)::bigint IS NULL OR group_id = sqlc.narg(group_id))
|
||||
AND (sqlc.narg(status)::text IS NULL OR status = sqlc.narg(status))
|
||||
@@ -56,8 +58,9 @@ SELECT pr.id, pr.tenant_id, pr.group_id, pr.name, pr.prompt_content,
|
||||
pr.created_at, pr.updated_at,
|
||||
COUNT(a.id)::INT AS article_count
|
||||
FROM prompt_rules pr
|
||||
LEFT JOIN articles a ON a.prompt_rule_id = pr.id AND a.deleted_at IS NULL
|
||||
LEFT JOIN articles a ON a.prompt_rule_id = pr.id AND a.brand_id = pr.brand_id AND a.deleted_at IS NULL
|
||||
WHERE pr.tenant_id = sqlc.arg(tenant_id)
|
||||
AND pr.brand_id = sqlc.arg(brand_id)
|
||||
AND pr.deleted_at IS NULL
|
||||
AND pr.group_id IS NULL
|
||||
GROUP BY pr.id
|
||||
@@ -68,6 +71,7 @@ LIMIT sqlc.arg(page_size) OFFSET sqlc.arg(page_offset);
|
||||
SELECT COUNT(*)
|
||||
FROM prompt_rules
|
||||
WHERE tenant_id = sqlc.arg(tenant_id)
|
||||
AND brand_id = sqlc.arg(brand_id)
|
||||
AND deleted_at IS NULL
|
||||
AND group_id IS NULL;
|
||||
|
||||
@@ -76,11 +80,11 @@ SELECT id, tenant_id, group_id, name, prompt_content,
|
||||
scene, default_tone, default_word_count, status,
|
||||
created_at, updated_at
|
||||
FROM prompt_rules
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND deleted_at IS NULL;
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND brand_id = sqlc.arg(brand_id) AND deleted_at IS NULL;
|
||||
|
||||
-- name: CreatePromptRule :one
|
||||
INSERT INTO prompt_rules (tenant_id, group_id, name, prompt_content, scene, default_tone, default_word_count)
|
||||
VALUES (sqlc.arg(tenant_id), sqlc.narg(group_id), sqlc.arg(name), sqlc.arg(prompt_content),
|
||||
INSERT INTO prompt_rules (tenant_id, brand_id, group_id, name, prompt_content, scene, default_tone, default_word_count)
|
||||
VALUES (sqlc.arg(tenant_id), sqlc.arg(brand_id), sqlc.narg(group_id), sqlc.arg(name), sqlc.arg(prompt_content),
|
||||
sqlc.narg(scene), sqlc.narg(default_tone), sqlc.narg(default_word_count))
|
||||
RETURNING id, created_at;
|
||||
|
||||
@@ -90,18 +94,18 @@ SET name = sqlc.arg(name), group_id = sqlc.narg(group_id),
|
||||
prompt_content = sqlc.arg(prompt_content),
|
||||
scene = sqlc.narg(scene), default_tone = sqlc.narg(default_tone),
|
||||
default_word_count = sqlc.narg(default_word_count), updated_at = NOW()
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND deleted_at IS NULL;
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND brand_id = sqlc.arg(brand_id) AND deleted_at IS NULL;
|
||||
|
||||
-- name: UpdatePromptRuleStatus :exec
|
||||
UPDATE prompt_rules SET status = sqlc.arg(status), updated_at = NOW()
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND deleted_at IS NULL;
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND brand_id = sqlc.arg(brand_id) AND deleted_at IS NULL;
|
||||
|
||||
-- name: SoftDeletePromptRule :exec
|
||||
UPDATE prompt_rules SET deleted_at = NOW(), updated_at = NOW()
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND deleted_at IS NULL;
|
||||
WHERE id = sqlc.arg(id) AND tenant_id = sqlc.arg(tenant_id) AND brand_id = sqlc.arg(brand_id) AND deleted_at IS NULL;
|
||||
|
||||
-- name: ListAllPromptRulesSimple :many
|
||||
SELECT id, name, status
|
||||
FROM prompt_rules
|
||||
WHERE tenant_id = sqlc.arg(tenant_id) AND deleted_at IS NULL AND status = 'enabled'
|
||||
WHERE tenant_id = sqlc.arg(tenant_id) AND brand_id = sqlc.arg(brand_id) AND deleted_at IS NULL AND status = 'enabled'
|
||||
ORDER BY name;
|
||||
|
||||
Reference in New Issue
Block a user