桌面应用图标替换为 B-brackets 设计(深藏青 + 白/蓝花括号)
- icon.svg 取自 opsx-icon-options/api/B-brackets.svg,全套光栅重生成: icon.icns(iconutil)、icon.ico(PNG-in-ICO 6 尺寸)、16-1024 PNG、Windows Square*/StoreLogo - 替换 Tauri 脚手架默认五角星图标;GUI 重启实测 Dock 图标已生效 - 服务全量重启:server 8787(官网/文档 200)+ web 5173 + 桌面 GUI
This commit is contained in:
1 parent
71a6d986a4
commit
39f4d5addc
161 files changed
+3289
-515
No files matched your search
@@ -108,6 +108,7 @@ CREATE INDEX IF NOT EXISTS idx_workspaces_owner ON workspaces(owner_id);
|
||||
if _, err := s.db.Exec(`ALTER TABLE workspaces ADD COLUMN mock_token TEXT`); err == nil {
|
||||
_, _ = s.db.Exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_workspaces_mock_token ON workspaces(mock_token)`)
|
||||
}
|
||||
_, _ = s.db.Exec(`ALTER TABLE workspaces ADD COLUMN mock_expires_at INTEGER NOT NULL DEFAULT 0`)
|
||||
// 老库补擅长列(幂等)
|
||||
_, _ = s.db.Exec(`ALTER TABLE team_members ADD COLUMN specialty TEXT NOT NULL DEFAULT ''`)
|
||||
rows, err := s.db.Query(`SELECT id FROM workspaces WHERE mock_token IS NULL OR mock_token = ''`)
|
||||
@@ -511,19 +512,114 @@ func (s *Store) FindMockEndpoint(workspaceID int64, method, path string) (*mocks
|
||||
return e, true, nil
|
||||
}
|
||||
|
||||
// ResolveMockToken:mock token → workspace id(不存在返回 false,不暴露信息)
|
||||
// ResolveMockToken:mock token → workspace id(不存在 / 已过期 / 已作废 均返回 false)
|
||||
func (s *Store) ResolveMockToken(token string) (int64, bool, error) {
|
||||
var id int64
|
||||
err := s.db.QueryRow(`SELECT id FROM workspaces WHERE mock_token = ?`, token).Scan(&id)
|
||||
var expiresAt int64
|
||||
err := s.db.QueryRow(
|
||||
`SELECT id, IFNULL(mock_expires_at, 0) FROM workspaces WHERE mock_token = ? AND mock_token != ''`,
|
||||
token,
|
||||
).Scan(&id, &expiresAt)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return 0, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
if expiresAt > 0 && time.Now().Unix() >= expiresAt {
|
||||
return 0, false, nil
|
||||
}
|
||||
return id, true, nil
|
||||
}
|
||||
|
||||
// SetMockExpiry 设置可选 TTL(expiresAtUnix=0 表示不过期)。
|
||||
func (s *Store) SetMockExpiry(workspaceID int64, expiresAtUnix int64) error {
|
||||
_, err := s.db.Exec(`UPDATE workspaces SET mock_expires_at = ? WHERE id = ?`, expiresAtUnix, workspaceID)
|
||||
return err
|
||||
}
|
||||
|
||||
// RevokeMock 作废当前 mock token:轮换新 token、清零过期、清空 endpoints;旧链接立刻失效。
|
||||
func (s *Store) RevokeMock(workspaceID int64) (newToken string, err error) {
|
||||
newToken = newMockToken()
|
||||
tx, err := s.db.Begin()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
if _, err := tx.Exec(
|
||||
`UPDATE workspaces SET mock_token = ?, mock_expires_at = 0 WHERE id = ?`,
|
||||
newToken, workspaceID,
|
||||
); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err := tx.Exec(`DELETE FROM mock_endpoints WHERE workspace_id = ?`, workspaceID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return newToken, nil
|
||||
}
|
||||
|
||||
const localMockWorkspaceName = "__opsxapi_local_mock__"
|
||||
const localMockUserEmail = "__local_mock__@opsxapi.internal"
|
||||
|
||||
// ensureLocalMockOwner 系统账号,仅作 FK 锚点,不出现在登录流程。
|
||||
func (s *Store) ensureLocalMockOwner() (int64, error) {
|
||||
var id int64
|
||||
err := s.db.QueryRow(`SELECT id FROM users WHERE email = ?`, localMockUserEmail).Scan(&id)
|
||||
if err == nil {
|
||||
return id, nil
|
||||
}
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
return 0, err
|
||||
}
|
||||
res, err := s.db.Exec(
|
||||
`INSERT INTO users(name, email, pass_hash, created_at) VALUES(?,?,?,?)`,
|
||||
"本机联调", localMockUserEmail, hashPassword(newMockToken()), time.Now().Unix(),
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return res.LastInsertId()
|
||||
}
|
||||
|
||||
// EnsureLocalMockWorkspace 为本机联调预留的系统空间(不绑真实用户账号)。
|
||||
func (s *Store) EnsureLocalMockWorkspace() (id int64, token string, err error) {
|
||||
err = s.db.QueryRow(
|
||||
`SELECT id, IFNULL(mock_token,'') FROM workspaces WHERE name = ? AND team_id IS NULL LIMIT 1`,
|
||||
localMockWorkspaceName,
|
||||
).Scan(&id, &token)
|
||||
if err == nil {
|
||||
if token == "" {
|
||||
token = newMockToken()
|
||||
if _, e := s.db.Exec(`UPDATE workspaces SET mock_token = ? WHERE id = ?`, token, id); e != nil {
|
||||
return 0, "", e
|
||||
}
|
||||
}
|
||||
return id, token, nil
|
||||
}
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
return 0, "", err
|
||||
}
|
||||
ownerID, err := s.ensureLocalMockOwner()
|
||||
if err != nil {
|
||||
return 0, "", err
|
||||
}
|
||||
token = newMockToken()
|
||||
now := time.Now().Unix()
|
||||
res, err := s.db.Exec(
|
||||
`INSERT INTO workspaces(name, team_id, owner_id, data, updated_at, mock_token) VALUES(?,NULL,?,'',?,?)`,
|
||||
localMockWorkspaceName, ownerID, now, token,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, "", err
|
||||
}
|
||||
id, err = res.LastInsertId()
|
||||
return id, token, err
|
||||
}
|
||||
|
||||
|
||||
func (s *Store) SaveWorkspace(wsID int64, data string) (int64, error) {
|
||||
now := time.Now().Unix()
|
||||
_, err := s.db.Exec(`UPDATE workspaces SET data = ?, updated_at = ? WHERE id = ?`, data, now, wsID)
|
||||
|
||||
Reference in new issue
Block a user