feat: complete browser extensions + token auth for history/admin APIs

- Extensions: rewrite both Chrome MV3 & Firefox MV2 with reliable
  chrome.history.search incremental pull (not onVisited), local search-engine
  filtering, URL dedup, 30s alarm, retry queue, Bearer token header
- Add icons (16/48/96/128) for both browsers
- Manifest fixes: chrome action popup, firefox options_ui + browser shim
- history-server: require NAVI_SYNC_TOKEN for POST /sync & GET history,
  NAVI_ADMIN_TOKEN for DELETE; fix RWMutex deadlock (unlock before
  sortDashyFavorites) that stalled syncs with valid token
- admin-server: require NAVI_ADMIN_TOKEN for item add/delete writes
This commit is contained in:
JianFeeeee
2026-09-08 22:35:54 +08:00
parent 76a4265222
commit f0b318be45
16 changed files with 417 additions and 234 deletions

View File

@ -13,10 +13,23 @@ import (
)
var (
confFile = envOr("DASHY_CONF", "/app/data/conf.yml")
mu sync.Mutex
confFile = envOr("DASHY_CONF", "/app/data/conf.yml")
adminToken = os.Getenv("NAVI_ADMIN_TOKEN")
mu sync.Mutex
)
func requireToken(w http.ResponseWriter, r *http.Request, expected string) bool {
if expected == "" {
return true // 未配置 token 则不校验
}
auth := r.Header.Get("Authorization")
if strings.HasPrefix(auth, "Bearer ") && strings.TrimPrefix(auth, "Bearer ") == expected {
return true
}
jsonErr(w, http.StatusUnauthorized, "invalid or missing token")
return false
}
type Config struct {
AppConfig map[string]any `yaml:"appConfig"`
PageInfo map[string]any `yaml:"pageInfo"`
@ -110,6 +123,9 @@ func handleAddItem(w http.ResponseWriter, r *http.Request) {
jsonErr(w, 405, "method not allowed")
return
}
if !requireToken(w, r, adminToken) {
return
}
mu.Lock()
defer mu.Unlock()
@ -153,6 +169,9 @@ func handleDeleteItem(w http.ResponseWriter, r *http.Request) {
jsonErr(w, 405, "method not allowed")
return
}
if !requireToken(w, r, adminToken) {
return
}
mu.Lock()
defer mu.Unlock()