Files
Commilitia-Drop/internal/db/web_sessions.sql.go
T
admin e51666c52e 浏览器免重登:HttpOnly cookie + 服务端 session 表 + 设备名持久化
- 新增 web_sessions 表(sqlc):refresh_token 以 AES-256-GCM 落盘,密钥取自
  CDROP_SESSION_SECRET(env、不在库内);cookie 仅存不透明随机串,表 id 存其
  SHA-256,故 DB 单独泄露既换不出可用 cookie、也解不出 token
- /auth/exchange 建 session 并下发 HttpOnly; Secure; SameSite=Lax; Path=/api/auth
  cookie,响应体不再回传 refresh_token
- /auth/refresh 改为 cookie 驱动(7 天滑动失活),同时即开机静默免重登;
  新增 /auth/logout(删 session + 清 cookie)、/auth/device(写设备名入 session)
- device_name 随 session 存,开机 refresh 带回前端,抗 iOS PWA 存储清除;
  setup / 改名时 syncWebDeviceName 推送服务端
- striped per-session 锁串行化同会话并发 refresh,防一次性 refresh_token 被
  花两次而把用户从所有 tab 登出
- 前端 store 移除 refreshToken 字段(长寿命凭据彻底不进 JS);main.tsx 首屏前
  bootstrapAuth 用 cookie 静默续期,命中直接进已登录态、避免登录页闪现
- config:prod 强制 CDROP_SESSION_SECRET,缺失拒启动
- 桌面端不受影响(自有 loopback flow + Go keyring,不碰这两个端点)
2026-06-16 00:54:40 +08:00

131 lines
3.4 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: web_sessions.sql
package db
import (
"context"
)
const createWebSession = `-- name: CreateWebSession :exec
INSERT INTO web_sessions (id, user_id, refresh_token, device_name, user_agent, created_at, last_used_at, expires_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`
type CreateWebSessionParams struct {
ID string `json:"id"`
UserID string `json:"user_id"`
RefreshToken string `json:"refresh_token"`
DeviceName string `json:"device_name"`
UserAgent string `json:"user_agent"`
CreatedAt int64 `json:"created_at"`
LastUsedAt int64 `json:"last_used_at"`
ExpiresAt int64 `json:"expires_at"`
}
// web_sessions: browser "passwordless re-login". The opaque cookie token is
// never stored; id holds its SHA-256, so a DB leak yields no usable cookie.
// refresh_token is AES-256-GCM ciphertext (key lives in the container env, not
// the DB). 7-day sliding window: every refresh rotates the token and pushes
// expires_at forward; idle sessions are reaped by DeleteExpiredWebSessions.
func (q *Queries) CreateWebSession(ctx context.Context, arg CreateWebSessionParams) error {
_, err := q.db.ExecContext(ctx, createWebSession,
arg.ID,
arg.UserID,
arg.RefreshToken,
arg.DeviceName,
arg.UserAgent,
arg.CreatedAt,
arg.LastUsedAt,
arg.ExpiresAt,
)
return err
}
const deleteExpiredWebSessions = `-- name: DeleteExpiredWebSessions :execrows
DELETE FROM web_sessions
WHERE expires_at < ?
`
func (q *Queries) DeleteExpiredWebSessions(ctx context.Context, expiresAt int64) (int64, error) {
result, err := q.db.ExecContext(ctx, deleteExpiredWebSessions, expiresAt)
if err != nil {
return 0, err
}
return result.RowsAffected()
}
const deleteWebSession = `-- name: DeleteWebSession :exec
DELETE FROM web_sessions
WHERE id = ?
`
func (q *Queries) DeleteWebSession(ctx context.Context, id string) error {
_, err := q.db.ExecContext(ctx, deleteWebSession, id)
return err
}
const getWebSession = `-- name: GetWebSession :one
SELECT id, user_id, refresh_token, device_name, user_agent, created_at, last_used_at, expires_at
FROM web_sessions
WHERE id = ?
`
func (q *Queries) GetWebSession(ctx context.Context, id string) (WebSession, error) {
row := q.db.QueryRowContext(ctx, getWebSession, id)
var i WebSession
err := row.Scan(
&i.ID,
&i.UserID,
&i.RefreshToken,
&i.DeviceName,
&i.UserAgent,
&i.CreatedAt,
&i.LastUsedAt,
&i.ExpiresAt,
)
return i, err
}
const rotateWebSession = `-- name: RotateWebSession :exec
UPDATE web_sessions
SET refresh_token = ?, last_used_at = ?, expires_at = ?
WHERE id = ?
`
type RotateWebSessionParams struct {
RefreshToken string `json:"refresh_token"`
LastUsedAt int64 `json:"last_used_at"`
ExpiresAt int64 `json:"expires_at"`
ID string `json:"id"`
}
func (q *Queries) RotateWebSession(ctx context.Context, arg RotateWebSessionParams) error {
_, err := q.db.ExecContext(ctx, rotateWebSession,
arg.RefreshToken,
arg.LastUsedAt,
arg.ExpiresAt,
arg.ID,
)
return err
}
const setWebSessionDevice = `-- name: SetWebSessionDevice :exec
UPDATE web_sessions
SET device_name = ?
WHERE id = ?
`
type SetWebSessionDeviceParams struct {
DeviceName string `json:"device_name"`
ID string `json:"id"`
}
func (q *Queries) SetWebSessionDevice(ctx context.Context, arg SetWebSessionDeviceParams) error {
_, err := q.db.ExecContext(ctx, setWebSessionDevice, arg.DeviceName, arg.ID)
return err
}