package store import ( "database/sql" "errors" "strconv" "strings" ) // Settings 键白名单(§7.1 SettingsDTO 同源;admin_password_hash 永不进入 API 响应)。 const ( KeyAdminPasswordHash = "admin_password_hash" KeySiteTitle = "site_title" KeySiteDesc = "site_desc" KeyPageSize = "page_size" ) // GetSetting 读取单个设置。 func (s *Store) GetSetting(key string) (string, bool, error) { var v string err := s.db.QueryRow(`SELECT value FROM settings WHERE key=?`, key).Scan(&v) if errors.Is(err, sql.ErrNoRows) { return "", false, nil } return v, err == nil, err } // SetSetting 写入单个设置(INSERT OR REPLACE)。 func (s *Store) SetSetting(key, value string) error { _, err := s.db.Exec(`INSERT INTO settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`, key, value) return err } // SiteSettings 对外的站点设置白名单视图。 type SiteSettings struct { SiteTitle string `json:"site_title"` SiteDesc string `json:"site_desc"` PageSize int `json:"page_size"` } // Defaults,未初始化时兜底。 const ( DefaultSiteTitle = "Pure Note" DefaultSiteDesc = "" DefaultPageSize = 10 ) // GetSiteSettings 读取站点设置(白名单三键,带默认值)。 func (s *Store) GetSiteSettings() (*SiteSettings, error) { ss := &SiteSettings{SiteTitle: DefaultSiteTitle, SiteDesc: DefaultSiteDesc, PageSize: DefaultPageSize} if v, ok, err := s.GetSetting(KeySiteTitle); err != nil { return nil, err } else if ok && v != "" { ss.SiteTitle = v } if v, ok, err := s.GetSetting(KeySiteDesc); err != nil { return nil, err } else if ok { ss.SiteDesc = v } if v, ok, err := s.GetSetting(KeyPageSize); err != nil { return nil, err } else if ok { // strconv.Atoi 全文解析:拒绝 "10abc" 类部分解析的脏值(评审 round2 P2-13) if n, err := strconv.Atoi(strings.TrimSpace(v)); err == nil && n >= 1 && n <= 100 { ss.PageSize = n } } return ss, nil }