Commit Graph

24 Commits

Author SHA1 Message Date
9a2a5ccbf5 fix(nginx): 关闭绝对重定向,修 /admin 跳到 :8080
容器内监听 8080,对外经门户反代走 443。nginx 默认把重定向拼成
$scheme://$host:$server_port,于是 GET /admin(无尾斜杠)被 301 到
http://<域名>:8080/admin/:既泄漏内部端口,又把 https 降级成 http。

- absolute_redirect off + port_in_redirect off,改用相对 Location
- 为 /admin /item-icons /wallpapers /extension 显式处理无尾斜杠请求
2026-09-11 16:25:26 +08:00
c4b0b8abdf build: 用 patch-index.py 幂等注入 navi.css/navi.js
Dashy 的 index.html 不保证有 </body>,原来 sed 替换 </body> 会静默丢掉注入的
<script>(旧镜像里 script 与 </body> 同行,被整行删除后就没有锚点了),
结果新访客加载不到 navi.js。改为 Python 脚本:先清理旧标签,再在
</head>/</body> 前插入,缺 </body> 时在 </html> 前补回来,可重复执行。

同时 .gitignore 忽略 __pycache__。
2026-09-11 16:25:26 +08:00
6fd62d4949 docs: note that the install page shows the sync token
安装引导页已展示服务地址与同步令牌;README 补充说明令牌来源
(/admin/api/sync-info,位于门户登录墙内,不能挂在被放行的 /api/ 下)。
2026-09-11 11:52:17 +08:00
de795de0fb feat(install): show the sync token on the install page
插件必须填 NAVI_SYNC_TOKEN,但页面上没有任何地方能看到它 —— 用户只能去翻
.env,实际就是配不起来。

- admin-server 新增 GET /admin/api/sync-info,返回 syncToken / hasToken。
  放在 /admin/ 下而不是 /api/ 下是必须的:插件上报用的 /api/history/sync
  被门户 auth_request 放行,若令牌挂在同一前缀下就等于公开。
  实测 /api/history/sync-info 返回 401,只有 /admin/api/sync-info 能取到。
- 安装引导页把「第一步」改为填写两项(服务地址 + 同步令牌),各自可复制;
  服务端未设令牌时提示留空即可;未登录时提示需先登录门户。
- README 补充对应说明。
2026-09-11 11:49:31 +08:00
e409f967a9 feat(admin): custom wallpaper for the nav background
- admin-server 新增 GET/POST /api/wallpaper:
  multipart 上传(png/jpg/webp/gif/svg,上限 8MB)或 JSON 直接给 URL,
  服务端把一段带标记的 CSS 写入 appConfig.customCss(标记块可反复替换,
  不碰主题其余部分),并记录 appConfig.wallpaper / wallpaperDim。
- 上传的图片落在 data 卷 wallpapers/,nginx 以 /wallpapers/ 提供
  (长缓存,文件名带时间戳)。
- 遮罩:壁纸上面铺一层可调强度的白色 linear-gradient,默认 0.45,
  否则玻璃卡片上的文字在照片上会读不清。
- 安全:URL 校验只允许 / 或 http(s):// 开头且不含引号/括号/换行,
  避免注入到 CSS;类型判定走正文特征而非文件名。
- admin UI 增加「外观」区块:上传/填 URL/遮罩滑块/应用/移除 + 预览。

实测:上传 → /wallpapers/wall-*.png,web 200 image/png,
body background-image 为遮罩+图片,移除后恢复默认渐变。
2026-09-11 11:46:53 +08:00
f8c4771828 fix(admin,theme): make admin actually work; glass theme targets real DOM
后台之前有两处让它完全不可用的问题(都属于「看着有、实际不工作」):
1. 写操作 401 —— admin UI 从未带 Authorization 头,而 admin-server 强制校验
   NAVI_ADMIN_TOKEN。于是添加/删除一直静默失败。
2. JSON 键名不匹配 —— Section/NavItem 只有 yaml tag,没有 json tag,
   接口返回 {"Name":..,"Items":[{"Title":..}]},而前端读 s.name / it.title,
   渲染直接抛异常(菜单区永远停在「加载中…」)。

修法:
- admin-server:token 改为**默认不校验**(/admin/ 已在外层门户登录墙内,
  用户确认无需叠加),仅当显式设 NAVI_ADMIN_REQUIRE_TOKEN=1 时才校验;
  历史 DELETE 不受影响(那条路径被门户放行,仍必须自带 token)。
- 补 json tag;Config/Section/NavItem 加 yaml ",inline" 保留未知键,
  避免保存 conf.yml 时把不认识的配置(layout/pages/item 的 target 等)丢掉。
- 新增 /api/pageinfo(标题/副标题/页脚/顶部导航可在后台编辑)与
  /api/icon(图标上传,限 png/svg/jpg,512KB)。
- 重写 admin UI:站点信息 + 顶部导航编辑、图标上传(.ico 用 canvas 转 PNG,
  因为 Dashy 的 isImage() 只认 svg/png/jpg)、可选令牌。

主题:旧 customCss 大部分是死代码 —— .tile / .item-group / .item-group-outer
在页面里根本不存在(querySelectorAll 计数为 0),卡片灰底其实来自 a.item,
而 .home 的不透明背景盖住了 body 渐变,所以玻璃效果一直看不出来。
现按真实类名(a.item / .item-wrapper / .collapsable / .collapsible-content /
.home / header)重写,并加入工作空间侧边栏的溢出修复。

安装页:.btn 自带 display 会盖掉浏览器默认的 [hidden]{display:none},
未配置商店时「一键安装」按钮仍然可见且 href 为空(点了没反应)。
现显式兜住 [hidden],并把浏览器识别补全(iOS/Android 单独提示为不可安装、
Edge/Brave/Vivaldi/Opera 给出各自的 extensions 地址、优先用 userAgentData)。
2026-09-11 11:43:44 +08:00
aa237868c1 feat(deploy): let data volume override SearXNG settings
SearXNG 的配置原本只能靠镜像内置的 /etc/searxng/settings.yml,
于是代理(outgoing.proxies)这类部署相关配置每次重建容器都会丢,
改配置也必须重建镜像。

改为:容器启动时若存在 /app/data/searxng-settings.yml 就用它,
否则回退到镜像内置配置。用 sh -c 包一层是因为 supervisord 的
environment= 不支持条件判断。

注意必须带 [ -f ] 判断:实测 SEARXNG_SETTINGS_PATH 指向不存在的
文件时 SearXNG 会直接报错退出(PermissionError: ... not exists!)。

已验证:SEARXNG_SETTINGS_PATH 指向自造配置能正确覆盖端口与实例名。
README 补充配置优先级与数据卷备份清单。
2026-09-11 11:09:33 +08:00
73396cd5d4 docs: document NAVI_FAVICON_PROXY and pass it through compose
新增的 favicon 抓取代理变量此前只存在于代码里:
- .env.example 补充说明与示例(默认留空,自动复用 SearXNG 的 outgoing.proxies)
- docker-compose.yml 透传该变量
- README 环境变量表补一行
2026-09-11 11:00:40 +08:00
0283985094 fix(docker): retry apt-get to tolerate transient proxy 502s
构建时遇到 'E: Failed to fetch ... 502 Bad Gateway [IP: 127.0.0.1 7890]':
经代理拉 Debian 包偶发上游抖动。给三处 apt-get 统一加
Acquire::Retries=5 与 http 超时,避免一次网络抖动就让整个
(含耗时较久的 SearXNG 构建阶段)前功尽弃。
2026-09-11 10:59:33 +08:00
3f1d896db8 fix(docker): create /out before zipping extension packages
Go 的 -o 会自动创建父目录,zip 不会,导致 extpack 阶段
'/out/navi-chrome.zip: No such file or directory' 构建失败。
(上一次构建也是失败的:后台通知里的 exit 0 来自命令末尾的 tail,
不是 docker build 的退出码,已改为显式记录 BUILD_EXIT。)
2026-09-11 10:58:20 +08:00
0a6199b240 test(history): cover favicon/ICO logic; base format detection on body, not Content-Type
新增 history-server/favicon_test.go(仓库此前没有任何测试),覆盖:
- Dashy 渲染白名单(只认 svg/png/jpg,jpeg 归一为 jpg)
- sniffExt 必须拒绝 SPA 的 HTML 兜底页
- ICO 内嵌 PNG 提取(取最大条目)
- DIB(BMP) 解码:尺寸、像素顺序(自下而上)、全 0 alpha 视为不透明、
  不支持的位深/过短数据要报错
- 从多条目 ICO 中挑最大者
- host:port 文件名净化、中英文段落名匹配

写测试时当场抓到实现里的一个真漏洞:判定完全信任 Content-Type,
于是服务端谎报 image/svg+xml 而正文是 HTML 时会被存成 .svg。
现改为以**正文特征**为准(PNG/JPEG/ICO 魔数 + SVG 根元素校验),
Content-Type 只用于排除明显不是图片的类型,避免误存。

实测回归:google/github/docker/HN/wikipedia 及内网服务 6/6 拿到真实图标。
2026-09-11 10:57:30 +08:00
e7ea091e19 fix(history): give history entries real site favicons
历史条目的图标原先写死 fas fa-globe,整栏都是地球图标。

- 新增 history-server/favicon.go:后台抓取每个 host 的 favicon 并缓存到
  data/item-icons/,命中后 conf.yml 写本地文件名,与手工图标同一套解析。
  抓取顺序 <host>/favicon.ico → 首页 <link rel=icon>;3 个 worker,
  失败 6 小时后再试;完成后合并触发一次 conf.yml 重建。
- 只缓存 Dashy 能渲染的格式:其 isImage() 白名单是 [svg,png,jpg],
  写 .ico 进去完全渲染不出来。因此 .ico 先抽内嵌 PNG,若是传统 BMP/DIB
  编码则解码后转 PNG(Google 这类站点只给老式 .ico)。
- 内网地址用 host:port 区分(不同端口的服务不再共用一个图标),且只直连;
  外网站点直连失败时自动复用 SearXNG outgoing.proxies 的代理,
  也可用 NAVI_FAVICON_PROXY 覆盖。
- 修掉一个真实缺陷:导航项都没有访问数据时,原来会提前 return 并把
  「历史访问」清成只剩安装入口 —— 只浏览站外站点时真实历史会整个消失。
  现在只冻结「常用服务」,历史照常生成。
- Dockerfile 去掉 # syntax=docker/dockerfile:1:该指令会让 BuildKit 去 pull
  docker/dockerfile 前端镜像,无外网环境直接构建失败;本文件未用 BuildKit 语法。

实测:6/6 站点(含 google.com 的 DIB 型 ico、github.com、docker.com、
news.ycombinator.com 与两个内网服务)均得到真实图标,页面 naturalWidth>0。
2026-09-11 10:55:00 +08:00
ff0e6418f8 feat(nav): auto-detect browser extension and offer one-click install
导航页现在会自动检测浏览历史插件是否已安装:

- 扩展在用户配置的服务地址上动态注册 content script
  (Chrome: chrome.scripting.registerContentScripts,
   Firefox: browser.contentScripts.register),
  于 document_start 给 <html> 打上 data-navi-ext 标记,
  不在其他站点运行。
- history-server 始终把「安装浏览历史插件」放在「历史访问」第一条
  (入口 url=/extension/install.html),启动时也会重建一次,
  不再需要等下一次同步。
- web/navi.js 读到标记后隐藏该入口(连 .item-wrapper 一起隐藏,
  避免留下空网格位)。
- 新增 /extension/install.html:自动识别浏览器,给出对应安装包与步骤;
  支持在 data 卷放 extension-store.json 配置商店链接,
  有商店链接时显示真正的「一键安装」。
- 段落名匹配同时兼容中英文(常用服务/Favorites、历史访问/History),
  修掉了公开示例 conf.yml 用英文名时重建逻辑完全失效的问题。
- 扩展升到 1.1.0(新增 scripting 权限与 detect.js)。

Note: Chrome/Edge 不允许从网站直接安装非商店扩展,
因此自托管场景下只能下载后手动加载;发布到商店后才会出现一键安装。
2026-09-11 10:41:10 +08:00
88e23861fe fix(search): repair SearXNG engine failures
- bing: www.bing.com 302-redirects to cn.bing.com and SearXNG engine
  requests do not follow redirects, so it parsed the 178-byte redirect
  page and returned 0 results without any error report. Point bing at
  https://cn.bing.com to bypass the redirect.
- Raise outgoing request_timeout 3.0 -> 8.0 and max_request_timeout
  4.0 -> 15.0. max_request_timeout overrides each engine's own timeout,
  so 360search (timeout 20s) was still cut off at 4s.
- Enable duckduckgo (verified working) and disable baidu/sogou which
  return 302 verification pages (baidu also hits a 1h CAPTCHA ban, and
  sogou raises AttributeError on SXNG_Response.next_request).
- Document the diagnosis in the README FAQ.
2026-09-11 10:26:32 +08:00
e48fcc53cd fix: make browser history sync reliable 2026-09-10 22:24:43 +08:00
5d4cd64b30 fix: restore working Dockerfile (SearXNG pip install + msgspec + --no-build-isolation) 2026-09-09 10:22:10 +08:00
0fe13fc90b feat: unified nav portal - Dashy + SearXNG + history sync + admin UI + browser extensions
- Single Docker container with nginx reverse proxy
- SearXNG search proxy with configurable proxy support
- Browser extensions (Chrome MV3 + Firefox MV2) with SSE-style history sync
- Admin WebUI for managing navigation items
- Full deployment tutorial including auth reverse proxy and webui4frpc tunnel
- Sanitized conf.yml for public distribution
- Fixed SearXNG search trailing-slash issue via nginx rewrite
- Fixed SearXNG proxy configuration for China network access
- Fixed SearXNG engine loading (removed broken keep_only, use default_settings)
2026-09-09 09:52:33 +08:00
4f1c65a616 fix: keep manual favorites when no nav visit data; external-only visits don't trigger reorder
- Favorites section only rebuilds from Top-4 by visit frequency once real
  navigation hosts have visit data; otherwise manual Gitea/HomeAgent/AgentMail
  items are preserved untouched
- Pure external-site history (wikipedia etc.) no longer causes favorites to
  borrow tiles from other sections
2026-09-08 22:53:22 +08:00
c8aa6946c1 feat: favorites section shows top-4 Dashy nav items by real visit frequency
- Rebuild favorites from ALL Dashy navigation items (across every section),
  ranked by aggregated host visit counts from browser history
- Code-hosting (Gitea/GitLab/git.*) always pinned first regardless of visits
- Host-level dedup prevents duplicate tiles from previous rebuild cycles
- Fix code-host detection false positives (git. substring in domains like
  example.com); precise gitea/github/gitlab/codeberg matching + unit test
- History section now only lists non-navigation external sites
2026-09-08 22:50:08 +08:00
33564fb8f5 docs: complete deployment tutorial + frp/webui4frpc guide, expand .env/docker-compose for tokens & base_url
- Rewrite quick-start for source clone & build (A: compose, B: docker run)
- Expand frp section: full frps.toml, webui4frpc WebUI workflow, native frpc.toml, tunnel planning table
- docker-compose: NAVI_PORT / SEARXNG_BASE_URL env passthrough, better docs
- .env.example: document all vars incl token generation & base_url
- Fix firefox debugging URL typo, extension token note
2026-09-08 22:39:52 +08:00
f0b318be45 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
2026-09-08 22:35:54 +08:00
76a4265222 docs: fully sanitize README (remove host identifiers .60/.106) 2026-09-08 22:25:57 +08:00
72c947d146 chore: remove codegraph index from repo 2026-09-08 22:25:45 +08:00
7e49d2b51c feat: HomeDash - unified self-hosted navigation portal
Single-container navigation service combining:
- Dashy dashboard + SearXNG metasearch + history sync API + admin WebUI
- Go services for history/admin APIs, nginx as unified entry
- Browser extensions (Chrome MV3 / Firefox MV2) with 30s batched sync
- Production guide: portal-nginx unified auth reverse proxy + webui4frpc/frp tunnel
- Fully sanitized (no internal IPs/domains/credentials)
2026-09-08 22:25:00 +08:00