e045e00fbf
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>
550 lines
16 KiB
Go
550 lines
16 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
// source: prompt_rule.sql
|
|
|
|
package generated
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
const countPromptRules = `-- name: CountPromptRules :one
|
|
SELECT COUNT(*)
|
|
FROM prompt_rules
|
|
WHERE tenant_id = $1
|
|
AND brand_id = $2
|
|
AND deleted_at IS NULL
|
|
AND ($3::bigint IS NULL OR group_id = $3)
|
|
AND ($4::text IS NULL OR status = $4)
|
|
AND ($5::text IS NULL OR name ILIKE '%' || $5 || '%')
|
|
`
|
|
|
|
type CountPromptRulesParams struct {
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
GroupID pgtype.Int8 `json:"group_id"`
|
|
Status pgtype.Text `json:"status"`
|
|
Keyword pgtype.Text `json:"keyword"`
|
|
}
|
|
|
|
func (q *Queries) CountPromptRules(ctx context.Context, arg CountPromptRulesParams) (int64, error) {
|
|
row := q.db.QueryRow(ctx, countPromptRules,
|
|
arg.TenantID,
|
|
arg.BrandID,
|
|
arg.GroupID,
|
|
arg.Status,
|
|
arg.Keyword,
|
|
)
|
|
var count int64
|
|
err := row.Scan(&count)
|
|
return count, err
|
|
}
|
|
|
|
const countPromptRulesUngrouped = `-- name: CountPromptRulesUngrouped :one
|
|
SELECT COUNT(*)
|
|
FROM prompt_rules
|
|
WHERE tenant_id = $1
|
|
AND brand_id = $2
|
|
AND deleted_at IS NULL
|
|
AND group_id IS NULL
|
|
`
|
|
|
|
type CountPromptRulesUngroupedParams struct {
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
}
|
|
|
|
func (q *Queries) CountPromptRulesUngrouped(ctx context.Context, arg CountPromptRulesUngroupedParams) (int64, error) {
|
|
row := q.db.QueryRow(ctx, countPromptRulesUngrouped, arg.TenantID, arg.BrandID)
|
|
var count int64
|
|
err := row.Scan(&count)
|
|
return count, err
|
|
}
|
|
|
|
const createPromptRule = `-- name: CreatePromptRule :one
|
|
INSERT INTO prompt_rules (tenant_id, brand_id, group_id, name, prompt_content, scene, default_tone, default_word_count)
|
|
VALUES ($1, $2, $3, $4, $5,
|
|
$6, $7, $8)
|
|
RETURNING id, created_at
|
|
`
|
|
|
|
type CreatePromptRuleParams struct {
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
GroupID pgtype.Int8 `json:"group_id"`
|
|
Name string `json:"name"`
|
|
PromptContent string `json:"prompt_content"`
|
|
Scene pgtype.Text `json:"scene"`
|
|
DefaultTone pgtype.Text `json:"default_tone"`
|
|
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
|
|
}
|
|
|
|
type CreatePromptRuleRow struct {
|
|
ID int64 `json:"id"`
|
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
|
}
|
|
|
|
func (q *Queries) CreatePromptRule(ctx context.Context, arg CreatePromptRuleParams) (CreatePromptRuleRow, error) {
|
|
row := q.db.QueryRow(ctx, createPromptRule,
|
|
arg.TenantID,
|
|
arg.BrandID,
|
|
arg.GroupID,
|
|
arg.Name,
|
|
arg.PromptContent,
|
|
arg.Scene,
|
|
arg.DefaultTone,
|
|
arg.DefaultWordCount,
|
|
)
|
|
var i CreatePromptRuleRow
|
|
err := row.Scan(&i.ID, &i.CreatedAt)
|
|
return i, err
|
|
}
|
|
|
|
const createPromptRuleGroup = `-- name: CreatePromptRuleGroup :one
|
|
INSERT INTO prompt_rule_groups (tenant_id, brand_id, name, sort_order)
|
|
VALUES ($1, $2, $3, $4)
|
|
RETURNING id, created_at
|
|
`
|
|
|
|
type CreatePromptRuleGroupParams struct {
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
Name string `json:"name"`
|
|
SortOrder int32 `json:"sort_order"`
|
|
}
|
|
|
|
type CreatePromptRuleGroupRow struct {
|
|
ID int64 `json:"id"`
|
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
|
}
|
|
|
|
func (q *Queries) CreatePromptRuleGroup(ctx context.Context, arg CreatePromptRuleGroupParams) (CreatePromptRuleGroupRow, error) {
|
|
row := q.db.QueryRow(ctx, createPromptRuleGroup,
|
|
arg.TenantID,
|
|
arg.BrandID,
|
|
arg.Name,
|
|
arg.SortOrder,
|
|
)
|
|
var i CreatePromptRuleGroupRow
|
|
err := row.Scan(&i.ID, &i.CreatedAt)
|
|
return i, err
|
|
}
|
|
|
|
const getPromptRuleByID = `-- name: GetPromptRuleByID :one
|
|
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 = $1 AND tenant_id = $2 AND brand_id = $3 AND deleted_at IS NULL
|
|
`
|
|
|
|
type GetPromptRuleByIDParams struct {
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
}
|
|
|
|
type GetPromptRuleByIDRow struct {
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
GroupID pgtype.Int8 `json:"group_id"`
|
|
Name string `json:"name"`
|
|
PromptContent string `json:"prompt_content"`
|
|
Scene pgtype.Text `json:"scene"`
|
|
DefaultTone pgtype.Text `json:"default_tone"`
|
|
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
|
|
Status string `json:"status"`
|
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
|
}
|
|
|
|
func (q *Queries) GetPromptRuleByID(ctx context.Context, arg GetPromptRuleByIDParams) (GetPromptRuleByIDRow, error) {
|
|
row := q.db.QueryRow(ctx, getPromptRuleByID, arg.ID, arg.TenantID, arg.BrandID)
|
|
var i GetPromptRuleByIDRow
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.TenantID,
|
|
&i.GroupID,
|
|
&i.Name,
|
|
&i.PromptContent,
|
|
&i.Scene,
|
|
&i.DefaultTone,
|
|
&i.DefaultWordCount,
|
|
&i.Status,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const listAllPromptRulesSimple = `-- name: ListAllPromptRulesSimple :many
|
|
SELECT id, name, status
|
|
FROM prompt_rules
|
|
WHERE tenant_id = $1 AND brand_id = $2 AND deleted_at IS NULL AND status = 'enabled'
|
|
ORDER BY name
|
|
`
|
|
|
|
type ListAllPromptRulesSimpleParams struct {
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
}
|
|
|
|
type ListAllPromptRulesSimpleRow struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
func (q *Queries) ListAllPromptRulesSimple(ctx context.Context, arg ListAllPromptRulesSimpleParams) ([]ListAllPromptRulesSimpleRow, error) {
|
|
rows, err := q.db.Query(ctx, listAllPromptRulesSimple, arg.TenantID, arg.BrandID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []ListAllPromptRulesSimpleRow
|
|
for rows.Next() {
|
|
var i ListAllPromptRulesSimpleRow
|
|
if err := rows.Scan(&i.ID, &i.Name, &i.Status); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listPromptRuleGroups = `-- name: ListPromptRuleGroups :many
|
|
|
|
SELECT id, tenant_id, name, sort_order, created_at, updated_at
|
|
FROM prompt_rule_groups
|
|
WHERE tenant_id = $1 AND brand_id = $2 AND deleted_at IS NULL
|
|
ORDER BY sort_order, created_at
|
|
`
|
|
|
|
type ListPromptRuleGroupsParams struct {
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
}
|
|
|
|
type ListPromptRuleGroupsRow struct {
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
Name string `json:"name"`
|
|
SortOrder int32 `json:"sort_order"`
|
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
|
}
|
|
|
|
// ============================================================
|
|
// Prompt Rule Groups
|
|
// ============================================================
|
|
func (q *Queries) ListPromptRuleGroups(ctx context.Context, arg ListPromptRuleGroupsParams) ([]ListPromptRuleGroupsRow, error) {
|
|
rows, err := q.db.Query(ctx, listPromptRuleGroups, arg.TenantID, arg.BrandID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []ListPromptRuleGroupsRow
|
|
for rows.Next() {
|
|
var i ListPromptRuleGroupsRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.TenantID,
|
|
&i.Name,
|
|
&i.SortOrder,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listPromptRules = `-- name: ListPromptRules :many
|
|
|
|
SELECT pr.id, pr.tenant_id, pr.group_id, pr.name, pr.prompt_content,
|
|
pr.scene, pr.default_tone, pr.default_word_count, pr.status,
|
|
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.brand_id = pr.brand_id AND a.deleted_at IS NULL
|
|
WHERE pr.tenant_id = $1
|
|
AND pr.brand_id = $2
|
|
AND pr.deleted_at IS NULL
|
|
AND ($3::bigint IS NULL OR pr.group_id = $3)
|
|
AND ($4::text IS NULL OR pr.status = $4)
|
|
AND ($5::text IS NULL OR pr.name ILIKE '%' || $5 || '%')
|
|
GROUP BY pr.id
|
|
ORDER BY pr.created_at DESC
|
|
LIMIT $7 OFFSET $6
|
|
`
|
|
|
|
type ListPromptRulesParams struct {
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
GroupID pgtype.Int8 `json:"group_id"`
|
|
Status pgtype.Text `json:"status"`
|
|
Keyword pgtype.Text `json:"keyword"`
|
|
PageOffset int32 `json:"page_offset"`
|
|
PageSize int32 `json:"page_size"`
|
|
}
|
|
|
|
type ListPromptRulesRow struct {
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
GroupID pgtype.Int8 `json:"group_id"`
|
|
Name string `json:"name"`
|
|
PromptContent string `json:"prompt_content"`
|
|
Scene pgtype.Text `json:"scene"`
|
|
DefaultTone pgtype.Text `json:"default_tone"`
|
|
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
|
|
Status string `json:"status"`
|
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
|
ArticleCount int32 `json:"article_count"`
|
|
}
|
|
|
|
// ============================================================
|
|
// Prompt Rules
|
|
// ============================================================
|
|
func (q *Queries) ListPromptRules(ctx context.Context, arg ListPromptRulesParams) ([]ListPromptRulesRow, error) {
|
|
rows, err := q.db.Query(ctx, listPromptRules,
|
|
arg.TenantID,
|
|
arg.BrandID,
|
|
arg.GroupID,
|
|
arg.Status,
|
|
arg.Keyword,
|
|
arg.PageOffset,
|
|
arg.PageSize,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []ListPromptRulesRow
|
|
for rows.Next() {
|
|
var i ListPromptRulesRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.TenantID,
|
|
&i.GroupID,
|
|
&i.Name,
|
|
&i.PromptContent,
|
|
&i.Scene,
|
|
&i.DefaultTone,
|
|
&i.DefaultWordCount,
|
|
&i.Status,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.ArticleCount,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listPromptRulesUngrouped = `-- name: ListPromptRulesUngrouped :many
|
|
SELECT pr.id, pr.tenant_id, pr.group_id, pr.name, pr.prompt_content,
|
|
pr.scene, pr.default_tone, pr.default_word_count, pr.status,
|
|
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.brand_id = pr.brand_id AND a.deleted_at IS NULL
|
|
WHERE pr.tenant_id = $1
|
|
AND pr.brand_id = $2
|
|
AND pr.deleted_at IS NULL
|
|
AND pr.group_id IS NULL
|
|
GROUP BY pr.id
|
|
ORDER BY pr.created_at DESC
|
|
LIMIT $4 OFFSET $3
|
|
`
|
|
|
|
type ListPromptRulesUngroupedParams struct {
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
PageOffset int32 `json:"page_offset"`
|
|
PageSize int32 `json:"page_size"`
|
|
}
|
|
|
|
type ListPromptRulesUngroupedRow struct {
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
GroupID pgtype.Int8 `json:"group_id"`
|
|
Name string `json:"name"`
|
|
PromptContent string `json:"prompt_content"`
|
|
Scene pgtype.Text `json:"scene"`
|
|
DefaultTone pgtype.Text `json:"default_tone"`
|
|
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
|
|
Status string `json:"status"`
|
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
|
ArticleCount int32 `json:"article_count"`
|
|
}
|
|
|
|
func (q *Queries) ListPromptRulesUngrouped(ctx context.Context, arg ListPromptRulesUngroupedParams) ([]ListPromptRulesUngroupedRow, error) {
|
|
rows, err := q.db.Query(ctx, listPromptRulesUngrouped,
|
|
arg.TenantID,
|
|
arg.BrandID,
|
|
arg.PageOffset,
|
|
arg.PageSize,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []ListPromptRulesUngroupedRow
|
|
for rows.Next() {
|
|
var i ListPromptRulesUngroupedRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.TenantID,
|
|
&i.GroupID,
|
|
&i.Name,
|
|
&i.PromptContent,
|
|
&i.Scene,
|
|
&i.DefaultTone,
|
|
&i.DefaultWordCount,
|
|
&i.Status,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.ArticleCount,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const softDeletePromptRule = `-- name: SoftDeletePromptRule :exec
|
|
UPDATE prompt_rules SET deleted_at = NOW(), updated_at = NOW()
|
|
WHERE id = $1 AND tenant_id = $2 AND brand_id = $3 AND deleted_at IS NULL
|
|
`
|
|
|
|
type SoftDeletePromptRuleParams struct {
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
}
|
|
|
|
func (q *Queries) SoftDeletePromptRule(ctx context.Context, arg SoftDeletePromptRuleParams) error {
|
|
_, err := q.db.Exec(ctx, softDeletePromptRule, arg.ID, arg.TenantID, arg.BrandID)
|
|
return err
|
|
}
|
|
|
|
const softDeletePromptRuleGroup = `-- name: SoftDeletePromptRuleGroup :exec
|
|
UPDATE prompt_rule_groups SET deleted_at = NOW(), updated_at = NOW()
|
|
WHERE id = $1 AND tenant_id = $2 AND brand_id = $3 AND deleted_at IS NULL
|
|
`
|
|
|
|
type SoftDeletePromptRuleGroupParams struct {
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
}
|
|
|
|
func (q *Queries) SoftDeletePromptRuleGroup(ctx context.Context, arg SoftDeletePromptRuleGroupParams) error {
|
|
_, err := q.db.Exec(ctx, softDeletePromptRuleGroup, arg.ID, arg.TenantID, arg.BrandID)
|
|
return err
|
|
}
|
|
|
|
const updatePromptRule = `-- name: UpdatePromptRule :exec
|
|
UPDATE prompt_rules
|
|
SET name = $1, group_id = $2,
|
|
prompt_content = $3,
|
|
scene = $4, default_tone = $5,
|
|
default_word_count = $6, updated_at = NOW()
|
|
WHERE id = $7 AND tenant_id = $8 AND brand_id = $9 AND deleted_at IS NULL
|
|
`
|
|
|
|
type UpdatePromptRuleParams struct {
|
|
Name string `json:"name"`
|
|
GroupID pgtype.Int8 `json:"group_id"`
|
|
PromptContent string `json:"prompt_content"`
|
|
Scene pgtype.Text `json:"scene"`
|
|
DefaultTone pgtype.Text `json:"default_tone"`
|
|
DefaultWordCount pgtype.Int4 `json:"default_word_count"`
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
}
|
|
|
|
func (q *Queries) UpdatePromptRule(ctx context.Context, arg UpdatePromptRuleParams) error {
|
|
_, err := q.db.Exec(ctx, updatePromptRule,
|
|
arg.Name,
|
|
arg.GroupID,
|
|
arg.PromptContent,
|
|
arg.Scene,
|
|
arg.DefaultTone,
|
|
arg.DefaultWordCount,
|
|
arg.ID,
|
|
arg.TenantID,
|
|
arg.BrandID,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const updatePromptRuleGroup = `-- name: UpdatePromptRuleGroup :exec
|
|
UPDATE prompt_rule_groups SET name = $1, sort_order = $2, updated_at = NOW()
|
|
WHERE id = $3 AND tenant_id = $4 AND brand_id = $5 AND deleted_at IS NULL
|
|
`
|
|
|
|
type UpdatePromptRuleGroupParams struct {
|
|
Name string `json:"name"`
|
|
SortOrder int32 `json:"sort_order"`
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
}
|
|
|
|
func (q *Queries) UpdatePromptRuleGroup(ctx context.Context, arg UpdatePromptRuleGroupParams) error {
|
|
_, err := q.db.Exec(ctx, updatePromptRuleGroup,
|
|
arg.Name,
|
|
arg.SortOrder,
|
|
arg.ID,
|
|
arg.TenantID,
|
|
arg.BrandID,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const updatePromptRuleStatus = `-- name: UpdatePromptRuleStatus :exec
|
|
UPDATE prompt_rules SET status = $1, updated_at = NOW()
|
|
WHERE id = $2 AND tenant_id = $3 AND brand_id = $4 AND deleted_at IS NULL
|
|
`
|
|
|
|
type UpdatePromptRuleStatusParams struct {
|
|
Status string `json:"status"`
|
|
ID int64 `json:"id"`
|
|
TenantID int64 `json:"tenant_id"`
|
|
BrandID int64 `json:"brand_id"`
|
|
}
|
|
|
|
func (q *Queries) UpdatePromptRuleStatus(ctx context.Context, arg UpdatePromptRuleStatusParams) error {
|
|
_, err := q.db.Exec(ctx, updatePromptRuleStatus,
|
|
arg.Status,
|
|
arg.ID,
|
|
arg.TenantID,
|
|
arg.BrandID,
|
|
)
|
|
return err
|
|
}
|