wiki-viewer 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +7 -0
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +32 -3
- package/.next/standalone/.next/routes-manifest.json +46 -0
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/agent/activity/route.js +6 -6
- package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/agents/[agentId]/revoke/route.js +6 -6
- package/.next/standalone/.next/server/app/api/agent/admin/agents/[agentId]/revoke/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/agents/route.js +6 -6
- package/.next/standalone/.next/server/app/api/agent/admin/agents/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/approve/route.js +7 -7
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/approve/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/deny/route.js +5 -5
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/deny/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/route.js +5 -5
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js +8 -7
- package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js +9 -8
- package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js +8 -7
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js +7 -7
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js +6 -5
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js +7 -6
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/internal/span/route.js +6 -5
- package/.next/standalone/.next/server/app/api/agent/internal/span/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/settings/route.js +7 -7
- package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js +8 -7
- package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/assets/[...path]/route.js +8 -2
- package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/[...all]/route.js +5 -5
- package/.next/standalone/.next/server/app/api/auth/[...all]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/admins/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/admins/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/admins/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/admins/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/admins/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/admins/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/admins/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/system/auth-config/route.js +6 -6
- package/.next/standalone/.next/server/app/api/system/auth-config/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/auth-settings/route.js +4 -4
- package/.next/standalone/.next/server/app/api/system/auth-settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/browse/route.js +4 -4
- package/.next/standalone/.next/server/app/api/system/browse/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/clear-root/route.js +5 -5
- package/.next/standalone/.next/server/app/api/system/clear-root/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/config/route.js +6 -6
- package/.next/standalone/.next/server/app/api/system/config/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/pins/route.js +4 -4
- package/.next/standalone/.next/server/app/api/system/pins/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/reveal/route.js +6 -6
- package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/root-status/route.js +5 -5
- package/.next/standalone/.next/server/app/api/system/root-status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/set-root/route.js +6 -6
- package/.next/standalone/.next/server/app/api/system/set-root/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/users/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/users/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/users/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/users/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/users/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/users/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/users/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/upload/[...path]/route.js +8 -2
- package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/app/route.js +5 -5
- package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/content/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/download/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/download/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/file/route.js +8 -2
- package/.next/standalone/.next/server/app/api/wiki/file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/folder/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/move/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/new-file/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/page/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/search/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route.js +15 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/wiki/slugs/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/upload/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/watch/route.js +7 -9
- package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +5 -5
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/manifest.webmanifest/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/manifest.webmanifest/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/manifest.webmanifest/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/manifest.webmanifest/route.js +9 -0
- package/.next/standalone/.next/server/app/manifest.webmanifest/route.js.map +5 -0
- package/.next/standalone/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/manifest.webmanifest.body +1 -0
- package/.next/standalone/.next/server/app/manifest.webmanifest.meta +1 -0
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/signin/page.js +1 -1
- package/.next/standalone/.next/server/app/signin/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/signin/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +7 -0
- package/.next/standalone/.next/server/chunks/0p91_next_dist_1195ub1._.js +18 -0
- package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0d2jbo5.js +1 -1
- package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0ytral2.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-244bv._.js +16 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0xz-_0v._.js → [root-of-the-server]__0-inabx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-ao6a_._.js → [root-of-the-server]__0.-9jt0._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0~-r-8f._.js → [root-of-the-server]__00c1-dr._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__00lep-u._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__00mtevo._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__00qu86p._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__012753j._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__01hp8ax._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0jhr.ex._.js → [root-of-the-server]__02n6z97._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__036mhjp._.js +5 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__03p0ob1._.js +16 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05t~v6l._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__068ni_k._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06yp.08._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__082nhm6._.js → [root-of-the-server]__07vphbd._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0pg6dn-._.js → [root-of-the-server]__08lkuwa._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__09cqzem._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0p_ox-k._.js → [root-of-the-server]__09k4q9e._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0_601._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ae3dk6._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0s28.4-._.js → [root-of-the-server]__0af-x45._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cqu-wm._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d75a5q._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d7x3e1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d7zxm_._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e7vs98._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fxzg4v._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0gda_iu._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hu~q20._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jk1uf4._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-8clq._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0lhka0x._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0kdn1le._.js → [root-of-the-server]__0na11h0._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0nd.b_c._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0otb8ra._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0p0-p__._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0piofm3._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rrf-jr._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s6_lzw._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0sh13v5._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ta~flu._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0v4im4p._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0qn8e~s._.js → [root-of-the-server]__0v_kyp-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vatqe-._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vdb2nr._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wdh63w._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0z3wg9x._.js +12 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0mzo03s._.js → [root-of-the-server]__0~.-3yk._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__123._fe._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__12800b1._.js → [root-of-the-server]__12ee_s6._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12onytt._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__04udrya._.js → [root-of-the-server]__12q8ch8._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1377.79._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1378-ox._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13aid91._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13hp4tw._.js +12 -0
- package/.next/standalone/.next/server/chunks/_079xuln._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0dr1r1g._.js +452 -0
- package/.next/standalone/.next/server/chunks/_101exke._.js +452 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_admins_route_actions_0dsm7cx.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_users_route_actions_0whj5cy.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_[id]_open_route_actions_1087xu7.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_[id]_route_actions_0~h7-8s.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_route_actions_0mkalc3.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_wiki_search_route_actions_0inxu93.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_manifest_webmanifest_route_actions_04wfv0d.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules__pnpm_0aj5g-w._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_lib_search_0d-_j3u._.js +46 -0
- package/.next/standalone/.next/server/chunks/src_lib_search_0ymmp0c._.js +46 -0
- package/.next/standalone/.next/server/chunks/ssr/0p91_next_dist_esm_build_templates_app-page_042apsk.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/0p91_next_dist_esm_build_templates_app-page_08q3u1e.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/0p91_next_dist_esm_build_templates_app-page_0nflz3~.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/0p91_next_dist_esm_build_templates_app-page_0p5k29e.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{0~w0_katex_dist_katex_mjs_0b8ra51._.js → 0~w0_katex_dist_katex_mjs_04mhawr._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_erDiagram-TEJ5UH35_mjs_0v6rnqy._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_mermaid_core_mjs_0hj_n-~._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0btcd4o._.js → [root-of-the-server]__02twzph._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ytvlzs._.js → [root-of-the-server]__09~x2v~._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hvvps3._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0pqaawz._.js +18 -18
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0c71i8a._.js → node_modules__pnpm_0.96tmo._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0lm8e2c._.js → node_modules__pnpm_011vy_q._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ezm2us._.js → node_modules__pnpm_01o_5qt._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0j3mvgg._.js → node_modules__pnpm_04n0h6.._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0~ln0by._.js → node_modules__pnpm_093dp2q._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_11e~j49._.js → node_modules__pnpm_09ej62_._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0de8xt-._.js → node_modules__pnpm_09ljbdz._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-x6zex._.js → node_modules__pnpm_09~_ob2._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0yq5z.h._.js → node_modules__pnpm_0a01ng7._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0kwc-vs._.js → node_modules__pnpm_0b8qx0g._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0hrbz84._.js → node_modules__pnpm_0bbc---._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0hobcbs._.js → node_modules__pnpm_0c.309.._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0rw91-f._.js → node_modules__pnpm_0c8aunj._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0o.c1z8._.js → node_modules__pnpm_0hk6xys._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0dboa_e._.js → node_modules__pnpm_0hlzy8f._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0j53hti._.js → node_modules__pnpm_0nw5ou2._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0xrmzh1._.js → node_modules__pnpm_0o.dn8o._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0cxwhfd._.js → node_modules__pnpm_0s0ur~d._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_07rxv2x._.js → node_modules__pnpm_0shlang._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0i.pw_m._.js → node_modules__pnpm_0sq3c2r._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ajzar9._.js → node_modules__pnpm_0t9jb7d._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_012nt.s._.js → node_modules__pnpm_0wmx9kq._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0z~h2ow._.js → node_modules__pnpm_0xfx0sf._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0cbsnwf._.js → node_modules__pnpm_0yiz.-t._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0bum3-3._.js → node_modules__pnpm_11sut1u._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0mdo4i3._.js → node_modules__pnpm_124u4o2._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0il8j.j._.js → node_modules__pnpm_13tajgx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/src_app_signin_00yk0vm._.js +2 -2
- package/.next/standalone/.next/server/edge/chunks/{08yl_next_dist_esm_build_templates_edge-wrapper_0o9h3w_.js → 08yl_next_dist_esm_build_templates_edge-wrapper_0xbpts6.js} +2 -2
- package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0.pmgt2._.js +3 -0
- package/.next/standalone/.next/server/functions-config-manifest.json +6 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware-manifest.json +8 -8
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/0c_~zevf2n0r4.css +2 -0
- package/.next/standalone/.next/static/chunks/0l4842ez-0_66.js +129 -0
- package/.next/standalone/README.md +46 -2
- package/.next/standalone/docs/workspacing-plan.md +364 -0
- package/.next/standalone/package.json +2 -2
- package/.next/standalone/packages/wiki-viewer-mcp/package.json +1 -1
- package/.next/standalone/public/icon-192.png +0 -0
- package/.next/standalone/public/icon-512.png +0 -0
- package/.next/standalone/public/icon-maskable-512.png +0 -0
- package/.next/standalone/src/app/api/agent/activity/route.ts +9 -8
- package/.next/standalone/src/app/api/agent/events/[...path]/route.ts +20 -8
- package/.next/standalone/src/app/api/agent/files/[...path]/route.ts +16 -9
- package/.next/standalone/src/app/api/agent/fs/file/[...path]/route.ts +28 -18
- package/.next/standalone/src/app/api/agent/fs/ls/[[...path]]/route.ts +12 -7
- package/.next/standalone/src/app/api/agent/fs/move/route.ts +16 -11
- package/.next/standalone/src/app/api/agent/fs/search/route.ts +49 -13
- package/.next/standalone/src/app/api/agent/internal/span/route.ts +9 -5
- package/.next/standalone/src/app/api/agent/register/route.ts +9 -1
- package/.next/standalone/src/app/api/agent/settings/route.ts +7 -3
- package/.next/standalone/src/app/api/agent/sidecar/[...path]/route.ts +8 -4
- package/.next/standalone/src/app/api/assets/[...path]/route.ts +9 -4
- package/.next/standalone/src/app/api/system/admins/route.ts +103 -0
- package/.next/standalone/src/app/api/system/reveal/route.ts +7 -6
- package/.next/standalone/src/app/api/system/set-root/route.ts +24 -1
- package/.next/standalone/src/app/api/system/users/route.ts +120 -0
- package/.next/standalone/src/app/api/system/workspaces/[id]/open/route.ts +34 -0
- package/.next/standalone/src/app/api/system/workspaces/[id]/route.ts +74 -0
- package/.next/standalone/src/app/api/system/workspaces/route.ts +67 -0
- package/.next/standalone/src/app/api/upload/[...path]/route.ts +10 -5
- package/.next/standalone/src/app/api/wiki/app/route.ts +10 -9
- package/.next/standalone/src/app/api/wiki/content/route.ts +14 -14
- package/.next/standalone/src/app/api/wiki/download/route.ts +7 -6
- package/.next/standalone/src/app/api/wiki/file/route.ts +7 -2
- package/.next/standalone/src/app/api/wiki/folder/route.ts +6 -5
- package/.next/standalone/src/app/api/wiki/move/route.ts +7 -7
- package/.next/standalone/src/app/api/wiki/new-file/route.ts +7 -6
- package/.next/standalone/src/app/api/wiki/page/route.ts +6 -5
- package/.next/standalone/src/app/api/wiki/presence/route.ts +8 -7
- package/.next/standalone/src/app/api/wiki/route.ts +13 -11
- package/.next/standalone/src/app/api/wiki/search/route.ts +44 -0
- package/.next/standalone/src/app/api/wiki/slugs/route.ts +8 -8
- package/.next/standalone/src/app/api/wiki/upload/route.ts +6 -5
- package/.next/standalone/src/app/api/wiki/watch/route.ts +16 -40
- package/.next/standalone/src/app/globals.css +484 -484
- package/.next/standalone/src/app/layout.tsx +15 -1
- package/.next/standalone/src/app/manifest.ts +30 -0
- package/.next/standalone/src/app/page.tsx +163 -49
- package/.next/standalone/src/components/auth-settings-sheet.tsx +171 -2
- package/.next/standalone/src/components/dir-picker.tsx +8 -6
- package/.next/standalone/src/components/editor/comment-thread.tsx +2 -1
- package/.next/standalone/src/components/editor/csv-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/editor-toolbar.tsx +2 -2
- package/.next/standalone/src/components/editor/editor.tsx +6 -5
- package/.next/standalone/src/components/editor/file-fallback-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/folder-index.tsx +2 -1
- package/.next/standalone/src/components/editor/image-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/media-popover.tsx +2 -1
- package/.next/standalone/src/components/editor/media-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/mermaid-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/node-app-viewer.tsx +4 -3
- package/.next/standalone/src/components/editor/notebook-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/office/docx-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/office/office-chrome.tsx +3 -2
- package/.next/standalone/src/components/editor/office/pptx-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/office/xlsx-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/pdf-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/proof-span-popover.tsx +2 -1
- package/.next/standalone/src/components/editor/source-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/suggest-edit-popover.tsx +2 -1
- package/.next/standalone/src/components/editor/suggestion-card.tsx +2 -1
- package/.next/standalone/src/components/editor/website-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/wiki-link-create-dialog.tsx +2 -1
- package/.next/standalone/src/components/search/search-command-dialog.tsx +109 -0
- package/.next/standalone/src/components/search/sidebar-search-box.tsx +121 -0
- package/.next/standalone/src/components/search/snippet-text.tsx +48 -0
- package/.next/standalone/src/components/ui/command.tsx +3 -2
- package/.next/standalone/src/lib/auth/admin.ts +112 -0
- package/.next/standalone/src/lib/auth/server.ts +13 -2
- package/.next/standalone/src/lib/config.ts +56 -4
- package/.next/standalone/src/lib/proof/audit.ts +19 -10
- package/.next/standalone/src/lib/proof/auth.ts +11 -0
- package/.next/standalone/src/lib/proof/collab-state.ts +4 -2
- package/.next/standalone/src/lib/proof/file-lock.ts +5 -0
- package/.next/standalone/src/lib/proof/idempotency.ts +5 -0
- package/.next/standalone/src/lib/proof/lease.ts +40 -27
- package/.next/standalone/src/lib/proof/mutex.ts +4 -0
- package/.next/standalone/src/lib/proof/raw-fs.ts +2 -3
- package/.next/standalone/src/lib/proof/registry.ts +5 -0
- package/.next/standalone/src/lib/search/indexable-exts.ts +25 -0
- package/.next/standalone/src/lib/search/indexer.ts +567 -0
- package/.next/standalone/src/lib/search/sanitize.ts +35 -0
- package/.next/standalone/src/lib/search/search-db.ts +57 -0
- package/.next/standalone/src/lib/search/watcher-pool.ts +79 -0
- package/.next/standalone/src/lib/workspace-client.ts +82 -0
- package/.next/standalone/src/lib/workspace-context.ts +142 -0
- package/.next/standalone/src/lib/workspaces.ts +196 -0
- package/.next/standalone/src/stores/ai-panel-store.ts +3 -2
- package/.next/standalone/src/stores/editor-store.ts +4 -3
- package/.next/standalone/src/stores/proof-store.ts +4 -3
- package/.next/standalone/src/stores/search-store.ts +86 -0
- package/.next/standalone/src/stores/wiki-slugs-store.ts +2 -1
- package/.next/standalone/src/tests/proof/admin-create-user.test.ts +43 -0
- package/.next/standalone/src/tests/proof/agent-workspace-scope.test.ts +134 -0
- package/.next/standalone/src/tests/proof/collab-state.test.ts +43 -41
- package/.next/standalone/src/tests/proof/preload.ts +21 -0
- package/.next/standalone/src/tests/proof/search-index.test.ts +339 -0
- package/.next/standalone/src/tests/proof/workspace-isolation.test.ts +87 -0
- package/.next/standalone/src/tests/proof/workspaces-api.test.ts +227 -0
- package/.next/standalone/tsconfig.tsbuildinfo +1 -1
- package/README.md +46 -2
- package/package.json +2 -2
- package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0o~h4zq.js +0 -5
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0.hb9q2._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0.uux34._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0092hkp._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05f6x0i._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05idwm9._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06-dtd0._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06sek6_._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07fpqks._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__094q5bj._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0awzyon._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d_da6q._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hhhvm7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kk26wc._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0km8suj._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kur4ro._.js +0 -15
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0mkwoul._.js +0 -12
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qc2~6l._.js +0 -15
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qyd-o8._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rkve~v._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rzo40z._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0sjocwy._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ssj9~d._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s~i040._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t220d-._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t5mg.n._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0trsqf4._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xq124z._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__106uw_c._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__10w2q~o._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13w-0iy._.js +0 -3
- package/.next/standalone/.next/server/chunks/src_lib_auth_server_ts_00f4e0h._.js +0 -452
- package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0ug2rvl._.js +0 -3
- package/.next/standalone/.next/static/chunks/0vwkqw_rofm-c.js +0 -129
- package/.next/standalone/.next/static/chunks/0zay6349~v_wc.css +0 -2
- /package/.next/standalone/.next/static/{H0E5wVJm9tAuN5CrU6zG2 → t7B6nXaoD1jo9f61t3aeK}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{H0E5wVJm9tAuN5CrU6zG2 → t7B6nXaoD1jo9f61t3aeK}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{H0E5wVJm9tAuN5CrU6zG2 → t7B6nXaoD1jo9f61t3aeK}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin management API.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/system/admins — any signed-in user (returns isAdmin flag, admin list,
|
|
5
|
+
* and user roster if caller is admin).
|
|
6
|
+
* POST { userId } — admin-only: promote user to admin.
|
|
7
|
+
* DELETE { userId } — admin-only: demote user; refuses to remove last admin.
|
|
8
|
+
*
|
|
9
|
+
* Bootstrap: first authenticated request triggers ensureBootstrapAdmin so the
|
|
10
|
+
* first user to sign in becomes admin when no WIKI_ADMIN_EMAILS is set.
|
|
11
|
+
*/
|
|
12
|
+
import { NextResponse } from "next/server";
|
|
13
|
+
import Database from "better-sqlite3";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import os from "node:os";
|
|
16
|
+
import { mkdirSync } from "node:fs";
|
|
17
|
+
import { checkOrigin } from "@/lib/auth/csrf";
|
|
18
|
+
import { requireUser } from "@/lib/auth/server";
|
|
19
|
+
import {
|
|
20
|
+
isAdmin,
|
|
21
|
+
listAdmins,
|
|
22
|
+
addAdmin,
|
|
23
|
+
removeAdmin,
|
|
24
|
+
requireAdmin,
|
|
25
|
+
ensureBootstrapAdmin,
|
|
26
|
+
} from "@/lib/auth/admin";
|
|
27
|
+
|
|
28
|
+
export const runtime = "nodejs";
|
|
29
|
+
|
|
30
|
+
interface UserRow {
|
|
31
|
+
id: string;
|
|
32
|
+
email: string;
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function queryAllUsers(): UserRow[] {
|
|
37
|
+
try {
|
|
38
|
+
const dir = path.join(process.env.HOME ?? os.homedir(), ".wiki-viewer");
|
|
39
|
+
mkdirSync(dir, { recursive: true });
|
|
40
|
+
const db = new Database(path.join(dir, "auth.db"));
|
|
41
|
+
db.pragma("journal_mode = WAL");
|
|
42
|
+
return db.prepare("SELECT id, email, name FROM user").all() as UserRow[];
|
|
43
|
+
} catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function GET(request: Request) {
|
|
49
|
+
const auth = await requireUser(request);
|
|
50
|
+
if (!auth.ok) return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
51
|
+
|
|
52
|
+
// Bootstrap: first authenticated user becomes admin if no admin set yet.
|
|
53
|
+
await ensureBootstrapAdmin(auth.user.id);
|
|
54
|
+
|
|
55
|
+
const admin = await isAdmin(auth.user.id, auth.user.email);
|
|
56
|
+
const admins = await listAdmins();
|
|
57
|
+
const users = admin ? queryAllUsers() : [];
|
|
58
|
+
|
|
59
|
+
return NextResponse.json({ admins, isAdmin: admin, users });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function POST(request: Request) {
|
|
63
|
+
const csrf = checkOrigin(request);
|
|
64
|
+
if (csrf) return csrf;
|
|
65
|
+
|
|
66
|
+
const authResult = await requireAdmin(request);
|
|
67
|
+
if (!authResult.ok)
|
|
68
|
+
return NextResponse.json({ error: authResult.code }, { status: authResult.status });
|
|
69
|
+
|
|
70
|
+
const body: { userId?: string } = await request.json();
|
|
71
|
+
if (!body.userId?.trim())
|
|
72
|
+
return NextResponse.json({ error: "Missing userId" }, { status: 400 });
|
|
73
|
+
|
|
74
|
+
await addAdmin(body.userId.trim());
|
|
75
|
+
const admins = await listAdmins();
|
|
76
|
+
return NextResponse.json({ ok: true, admins });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function DELETE(request: Request) {
|
|
80
|
+
const csrf = checkOrigin(request);
|
|
81
|
+
if (csrf) return csrf;
|
|
82
|
+
|
|
83
|
+
const authResult = await requireAdmin(request);
|
|
84
|
+
if (!authResult.ok)
|
|
85
|
+
return NextResponse.json({ error: authResult.code }, { status: authResult.status });
|
|
86
|
+
|
|
87
|
+
const body: { userId?: string } = await request.json();
|
|
88
|
+
if (!body.userId?.trim())
|
|
89
|
+
return NextResponse.json({ error: "Missing userId" }, { status: 400 });
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
await removeAdmin(body.userId.trim());
|
|
93
|
+
} catch (e) {
|
|
94
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
95
|
+
if (msg.startsWith("LAST_ADMIN")) {
|
|
96
|
+
return NextResponse.json({ error: "LAST_ADMIN", message: msg }, { status: 409 });
|
|
97
|
+
}
|
|
98
|
+
throw e;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const admins = await listAdmins();
|
|
102
|
+
return NextResponse.json({ ok: true, admins });
|
|
103
|
+
}
|
|
@@ -2,14 +2,15 @@ import { exec } from "node:child_process";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { NextResponse } from "next/server";
|
|
4
4
|
import { checkOrigin } from "@/lib/auth/csrf";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { resolveWorkspaceForUser } from "@/lib/workspace-context";
|
|
6
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
7
7
|
|
|
8
8
|
export async function POST(request: Request) {
|
|
9
9
|
const csrf = checkOrigin(request);
|
|
10
10
|
if (csrf) return csrf;
|
|
11
|
-
const
|
|
12
|
-
if (!
|
|
11
|
+
const ctx = await resolveWorkspaceForUser(request);
|
|
12
|
+
if (!ctx.ok) return NextResponse.json({ error: ctx.code }, { status: ctx.status });
|
|
13
|
+
const { rootDir } = ctx;
|
|
13
14
|
|
|
14
15
|
const body: { path?: string } = await request.json();
|
|
15
16
|
const rel = body.path;
|
|
@@ -17,8 +18,8 @@ export async function POST(request: Request) {
|
|
|
17
18
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
18
19
|
|
|
19
20
|
// Path traversal guard
|
|
20
|
-
const resolved =
|
|
21
|
-
if (
|
|
21
|
+
const resolved = safeWorkspacePath(rootDir, rel);
|
|
22
|
+
if (!resolved)
|
|
22
23
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
23
24
|
|
|
24
25
|
// Open in system file manager
|
|
@@ -1,9 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy set-root endpoint — back-compat shim for D1.
|
|
3
|
+
*
|
|
4
|
+
* Behaviour:
|
|
5
|
+
* 1. Validate dir (same as before).
|
|
6
|
+
* 2. Create (or find) a workspace for rootDir in the registry.
|
|
7
|
+
* 3. Keep setting the process-global rootDir + writing lastOpenedPath to config
|
|
8
|
+
* so the legacy fallback path still works for the existing client.
|
|
9
|
+
* 4. Return { ok, path, workspaceId } — added workspaceId for D2 migration.
|
|
10
|
+
*
|
|
11
|
+
* NOTE: NOT admin-gated here so the current single-user flow is unaffected.
|
|
12
|
+
* The new POST /api/system/workspaces route is admin-gated; D2 will switch the
|
|
13
|
+
* UI to use that endpoint.
|
|
14
|
+
*/
|
|
1
15
|
import { stat } from "node:fs/promises";
|
|
2
16
|
import { NextResponse } from "next/server";
|
|
3
17
|
import { checkOrigin } from "@/lib/auth/csrf";
|
|
4
18
|
import { requireUser } from "@/lib/auth/server";
|
|
5
19
|
import { writeConfig } from "@/lib/config";
|
|
6
20
|
import { setRootDir } from "@/lib/root-dir";
|
|
21
|
+
import { listWorkspaces, createWorkspace } from "@/lib/workspaces";
|
|
22
|
+
import path from "node:path";
|
|
7
23
|
|
|
8
24
|
export async function POST(request: Request) {
|
|
9
25
|
const csrf = checkOrigin(request);
|
|
@@ -24,7 +40,14 @@ export async function POST(request: Request) {
|
|
|
24
40
|
return NextResponse.json({ error: "Directory not found" }, { status: 404 });
|
|
25
41
|
}
|
|
26
42
|
|
|
43
|
+
// Legacy: keep the global + config in sync for the fallback resolver.
|
|
27
44
|
setRootDir(dir);
|
|
28
45
|
await writeConfig({ lastOpenedPath: dir });
|
|
29
|
-
|
|
46
|
+
|
|
47
|
+
// Find or create a workspace for this rootDir so the registry is populated.
|
|
48
|
+
const resolved = path.resolve(dir);
|
|
49
|
+
const existing = (await listWorkspaces()).find((w) => w.rootDir === resolved);
|
|
50
|
+
const ws = existing ?? (await createWorkspace({ rootDir: dir, createdBy: auth.user.id }));
|
|
51
|
+
|
|
52
|
+
return NextResponse.json({ ok: true, path: dir, workspaceId: ws.id });
|
|
30
53
|
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/system/users (admin only)
|
|
3
|
+
*
|
|
4
|
+
* Admin creates a new account with a generated temporary password, returned
|
|
5
|
+
* once in the response. The new user signs in and changes it. The signup
|
|
6
|
+
* allowlist is bypassed for admin-initiated creation (the admin is the gate).
|
|
7
|
+
*
|
|
8
|
+
* This calls auth.api.signUpEmail server-side; the session it would mint for
|
|
9
|
+
* the new user is discarded (we never forward those Set-Cookie headers), so
|
|
10
|
+
* the admin's own session is untouched.
|
|
11
|
+
*/
|
|
12
|
+
export const runtime = "nodejs";
|
|
13
|
+
|
|
14
|
+
import { NextResponse } from "next/server";
|
|
15
|
+
import { randomBytes } from "node:crypto";
|
|
16
|
+
import { checkOrigin } from "@/lib/auth/csrf";
|
|
17
|
+
import { requireAdmin } from "@/lib/auth/admin";
|
|
18
|
+
import { auth, authReady, withAdminUserCreate, passwordAuthEnabled, db } from "@/lib/auth/server";
|
|
19
|
+
|
|
20
|
+
const EMAIL_RE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
21
|
+
|
|
22
|
+
/** Readable temp password: 4 groups, mixed case + digits, no ambiguous chars. */
|
|
23
|
+
function generateTempPassword(): string {
|
|
24
|
+
const alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789";
|
|
25
|
+
const bytes = randomBytes(16);
|
|
26
|
+
let out = "";
|
|
27
|
+
for (let i = 0; i < 16; i++) {
|
|
28
|
+
out += alphabet[bytes[i] % alphabet.length];
|
|
29
|
+
if (i % 4 === 3 && i < 15) out += "-";
|
|
30
|
+
}
|
|
31
|
+
return out; // e.g. "k7Pm-9QrT-x2Vn-bL4w"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function POST(req: Request): Promise<NextResponse> {
|
|
35
|
+
const csrf = checkOrigin(req);
|
|
36
|
+
if (csrf) return csrf;
|
|
37
|
+
|
|
38
|
+
const admin = await requireAdmin(req);
|
|
39
|
+
if (!admin.ok) {
|
|
40
|
+
return NextResponse.json({ error: admin.code }, { status: admin.status });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!passwordAuthEnabled) {
|
|
44
|
+
return NextResponse.json(
|
|
45
|
+
{ error: "PASSWORD_AUTH_DISABLED", message: "Email/password sign-in is disabled; cannot create password accounts." },
|
|
46
|
+
{ status: 400 },
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let body: { email?: unknown; name?: unknown };
|
|
51
|
+
try {
|
|
52
|
+
body = (await req.json()) as { email?: unknown; name?: unknown };
|
|
53
|
+
} catch {
|
|
54
|
+
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "Invalid JSON" }, { status: 400 });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const email = typeof body.email === "string" ? body.email.trim().toLowerCase() : "";
|
|
58
|
+
const name = typeof body.name === "string" && body.name.trim() ? body.name.trim() : email.split("@")[0];
|
|
59
|
+
|
|
60
|
+
if (!EMAIL_RE.test(email)) {
|
|
61
|
+
return NextResponse.json({ error: "INVALID_EMAIL", message: "A valid email is required" }, { status: 400 });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const tempPassword = generateTempPassword();
|
|
65
|
+
|
|
66
|
+
await authReady();
|
|
67
|
+
// Reject duplicates up front (signUpEmail may otherwise create a second
|
|
68
|
+
// credential row or silently succeed depending on Better Auth internals).
|
|
69
|
+
try {
|
|
70
|
+
const existing = db
|
|
71
|
+
.prepare("SELECT 1 FROM user WHERE lower(email) = ? LIMIT 1")
|
|
72
|
+
.get(email);
|
|
73
|
+
if (existing) {
|
|
74
|
+
return NextResponse.json(
|
|
75
|
+
{ error: "USER_EXISTS", message: "A user with that email already exists." },
|
|
76
|
+
{ status: 409 },
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
// If the lookup fails, fall through and let signUpEmail decide.
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
// Bypass the signup allowlist for this admin-initiated creation. The
|
|
85
|
+
// returned response (and any session cookie) is intentionally discarded.
|
|
86
|
+
const result = await withAdminUserCreate(() =>
|
|
87
|
+
auth.api.signUpEmail({
|
|
88
|
+
body: { email, password: tempPassword, name },
|
|
89
|
+
asResponse: true,
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
if (!result.ok) {
|
|
93
|
+
const text = await result.text().catch(() => "");
|
|
94
|
+
if (/exist|unique|already/i.test(text)) {
|
|
95
|
+
return NextResponse.json(
|
|
96
|
+
{ error: "USER_EXISTS", message: "A user with that email already exists." },
|
|
97
|
+
{ status: 409 },
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return NextResponse.json(
|
|
101
|
+
{ error: "CREATE_FAILED", message: text || "Failed to create user" },
|
|
102
|
+
{ status: 500 },
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
} catch (e) {
|
|
106
|
+
const msg = e instanceof Error ? e.message : "";
|
|
107
|
+
if (/exist|unique|already/i.test(msg)) {
|
|
108
|
+
return NextResponse.json(
|
|
109
|
+
{ error: "USER_EXISTS", message: "A user with that email already exists." },
|
|
110
|
+
{ status: 409 },
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return NextResponse.json(
|
|
114
|
+
{ error: "CREATE_FAILED", message: msg || "Failed to create user" },
|
|
115
|
+
{ status: 500 },
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return NextResponse.json({ ok: true, email, name, tempPassword });
|
|
120
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/system/workspaces/[id]/open
|
|
3
|
+
*
|
|
4
|
+
* Client calls this when switching to a workspace. Records lastOpenedAt so
|
|
5
|
+
* the most-recently-used workspace can be selected on next load.
|
|
6
|
+
*/
|
|
7
|
+
import { NextResponse } from "next/server";
|
|
8
|
+
import { checkOrigin } from "@/lib/auth/csrf";
|
|
9
|
+
import { requireUser } from "@/lib/auth/server";
|
|
10
|
+
import { isAdmin } from "@/lib/auth/admin";
|
|
11
|
+
import { getWorkspace, touchWorkspace, userCanAccess } from "@/lib/workspaces";
|
|
12
|
+
|
|
13
|
+
export const runtime = "nodejs";
|
|
14
|
+
|
|
15
|
+
type Params = { params: Promise<{ id: string }> };
|
|
16
|
+
|
|
17
|
+
export async function POST(request: Request, { params }: Params) {
|
|
18
|
+
const csrf = checkOrigin(request);
|
|
19
|
+
if (csrf) return csrf;
|
|
20
|
+
|
|
21
|
+
const auth = await requireUser(request);
|
|
22
|
+
if (!auth.ok) return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
23
|
+
|
|
24
|
+
const { id } = await params;
|
|
25
|
+
const ws = await getWorkspace(id);
|
|
26
|
+
if (!ws) return NextResponse.json({ error: "WORKSPACE_NOT_FOUND" }, { status: 404 });
|
|
27
|
+
|
|
28
|
+
const admin = await isAdmin(auth.user.id, auth.user.email);
|
|
29
|
+
if (!userCanAccess(ws, auth.user.id, admin))
|
|
30
|
+
return NextResponse.json({ error: "WORKSPACE_FORBIDDEN" }, { status: 403 });
|
|
31
|
+
|
|
32
|
+
await touchWorkspace(id);
|
|
33
|
+
return NextResponse.json({ ok: true });
|
|
34
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-workspace management API.
|
|
3
|
+
*
|
|
4
|
+
* PATCH /api/system/workspaces/[id] — update name, pinnedPaths (any user with
|
|
5
|
+
* access), or allowedUserIds (admin-only).
|
|
6
|
+
* DELETE /api/system/workspaces/[id] — admin-only: remove workspace from registry
|
|
7
|
+
* (never touches the filesystem directory).
|
|
8
|
+
*/
|
|
9
|
+
import { NextResponse } from "next/server";
|
|
10
|
+
import { checkOrigin } from "@/lib/auth/csrf";
|
|
11
|
+
import { requireUser } from "@/lib/auth/server";
|
|
12
|
+
import { isAdmin, requireAdmin } from "@/lib/auth/admin";
|
|
13
|
+
import {
|
|
14
|
+
getWorkspace,
|
|
15
|
+
renameWorkspace,
|
|
16
|
+
removeWorkspace,
|
|
17
|
+
setWorkspaceAccess,
|
|
18
|
+
setWorkspacePins,
|
|
19
|
+
userCanAccess,
|
|
20
|
+
} from "@/lib/workspaces";
|
|
21
|
+
|
|
22
|
+
export const runtime = "nodejs";
|
|
23
|
+
|
|
24
|
+
type Params = { params: Promise<{ id: string }> };
|
|
25
|
+
|
|
26
|
+
export async function PATCH(request: Request, { params }: Params) {
|
|
27
|
+
const csrf = checkOrigin(request);
|
|
28
|
+
if (csrf) return csrf;
|
|
29
|
+
|
|
30
|
+
const auth = await requireUser(request);
|
|
31
|
+
if (!auth.ok) return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
32
|
+
|
|
33
|
+
const { id } = await params;
|
|
34
|
+
const ws = await getWorkspace(id);
|
|
35
|
+
if (!ws) return NextResponse.json({ error: "WORKSPACE_NOT_FOUND" }, { status: 404 });
|
|
36
|
+
|
|
37
|
+
const admin = await isAdmin(auth.user.id, auth.user.email);
|
|
38
|
+
if (!userCanAccess(ws, auth.user.id, admin))
|
|
39
|
+
return NextResponse.json({ error: "WORKSPACE_FORBIDDEN" }, { status: 403 });
|
|
40
|
+
|
|
41
|
+
const body: {
|
|
42
|
+
name?: string;
|
|
43
|
+
pinnedPaths?: string[];
|
|
44
|
+
allowedUserIds?: string[];
|
|
45
|
+
} = await request.json();
|
|
46
|
+
|
|
47
|
+
// allowedUserIds is admin-only
|
|
48
|
+
if (body.allowedUserIds !== undefined && !admin)
|
|
49
|
+
return NextResponse.json({ error: "ADMIN_REQUIRED" }, { status: 403 });
|
|
50
|
+
|
|
51
|
+
// Apply each field
|
|
52
|
+
if (body.name !== undefined) await renameWorkspace(id, body.name.trim());
|
|
53
|
+
if (body.pinnedPaths !== undefined) await setWorkspacePins(id, body.pinnedPaths);
|
|
54
|
+
if (body.allowedUserIds !== undefined) await setWorkspaceAccess(id, body.allowedUserIds);
|
|
55
|
+
|
|
56
|
+
const updated = await getWorkspace(id);
|
|
57
|
+
return NextResponse.json({ ok: true, workspace: updated });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function DELETE(request: Request, { params }: Params) {
|
|
61
|
+
const csrf = checkOrigin(request);
|
|
62
|
+
if (csrf) return csrf;
|
|
63
|
+
|
|
64
|
+
const authResult = await requireAdmin(request);
|
|
65
|
+
if (!authResult.ok)
|
|
66
|
+
return NextResponse.json({ error: authResult.code }, { status: authResult.status });
|
|
67
|
+
|
|
68
|
+
const { id } = await params;
|
|
69
|
+
const ws = await getWorkspace(id);
|
|
70
|
+
if (!ws) return NextResponse.json({ error: "WORKSPACE_NOT_FOUND" }, { status: 404 });
|
|
71
|
+
|
|
72
|
+
await removeWorkspace(id);
|
|
73
|
+
return NextResponse.json({ ok: true });
|
|
74
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace management API — list and create.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/system/workspaces — any signed-in user; returns workspaces the
|
|
5
|
+
* caller can access + isAdmin flag.
|
|
6
|
+
* POST { rootDir, name? } — admin-only: create a new workspace.
|
|
7
|
+
*
|
|
8
|
+
* Bootstrap: first authenticated request triggers ensureBootstrapAdmin.
|
|
9
|
+
*/
|
|
10
|
+
import { stat } from "node:fs/promises";
|
|
11
|
+
import { NextResponse } from "next/server";
|
|
12
|
+
import { checkOrigin } from "@/lib/auth/csrf";
|
|
13
|
+
import { requireUser } from "@/lib/auth/server";
|
|
14
|
+
import { isAdmin, requireAdmin, ensureBootstrapAdmin } from "@/lib/auth/admin";
|
|
15
|
+
import {
|
|
16
|
+
listWorkspaces,
|
|
17
|
+
createWorkspace,
|
|
18
|
+
migrateConfigToWorkspaces,
|
|
19
|
+
userCanAccess,
|
|
20
|
+
} from "@/lib/workspaces";
|
|
21
|
+
|
|
22
|
+
export const runtime = "nodejs";
|
|
23
|
+
|
|
24
|
+
export async function GET(request: Request) {
|
|
25
|
+
const auth = await requireUser(request);
|
|
26
|
+
if (!auth.ok) return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
27
|
+
|
|
28
|
+
// Bootstrap: first authenticated user becomes admin if no admin set yet.
|
|
29
|
+
await ensureBootstrapAdmin(auth.user.id);
|
|
30
|
+
await migrateConfigToWorkspaces();
|
|
31
|
+
|
|
32
|
+
const admin = await isAdmin(auth.user.id, auth.user.email);
|
|
33
|
+
const all = await listWorkspaces();
|
|
34
|
+
const workspaces = all.filter((ws) => userCanAccess(ws, auth.user.id, admin));
|
|
35
|
+
|
|
36
|
+
return NextResponse.json({ workspaces, isAdmin: admin });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function POST(request: Request) {
|
|
40
|
+
const csrf = checkOrigin(request);
|
|
41
|
+
if (csrf) return csrf;
|
|
42
|
+
|
|
43
|
+
const authResult = await requireAdmin(request);
|
|
44
|
+
if (!authResult.ok)
|
|
45
|
+
return NextResponse.json({ error: authResult.code }, { status: authResult.status });
|
|
46
|
+
|
|
47
|
+
const body: { rootDir?: string; name?: string } = await request.json();
|
|
48
|
+
const rootDir = body.rootDir?.trim();
|
|
49
|
+
if (!rootDir) return NextResponse.json({ error: "Missing rootDir" }, { status: 400 });
|
|
50
|
+
|
|
51
|
+
// Validate directory
|
|
52
|
+
try {
|
|
53
|
+
const info = await stat(rootDir);
|
|
54
|
+
if (!info.isDirectory())
|
|
55
|
+
return NextResponse.json({ error: "Not a directory" }, { status: 400 });
|
|
56
|
+
} catch {
|
|
57
|
+
return NextResponse.json({ error: "Directory not found" }, { status: 404 });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const workspace = await createWorkspace({
|
|
61
|
+
rootDir,
|
|
62
|
+
name: body.name?.trim() || undefined,
|
|
63
|
+
createdBy: authResult.user.id,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return NextResponse.json({ ok: true, workspace });
|
|
67
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { mkdir, stat, writeFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { NextResponse } from "next/server";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
5
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
5
6
|
|
|
6
7
|
const MAX_UPLOAD_BYTES = 50 * 1024 * 1024;
|
|
7
8
|
|
|
@@ -32,13 +33,17 @@ export async function POST(
|
|
|
32
33
|
request: Request,
|
|
33
34
|
{ params }: { params: Promise<{ path: string[] }> },
|
|
34
35
|
) {
|
|
36
|
+
const wsx = await resolveWorkspaceForAgent(request);
|
|
37
|
+
if (!wsx.ok) return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
38
|
+
const { rootDir } = wsx;
|
|
39
|
+
|
|
35
40
|
const { path: segments } = await params;
|
|
36
41
|
const subPath = (segments ?? []).join("/");
|
|
37
42
|
|
|
38
|
-
// Save images in _uploads/ within
|
|
39
|
-
const uploadsDir = path.join(
|
|
40
|
-
const resolved = path.
|
|
41
|
-
if (!resolved
|
|
43
|
+
// Save images in _uploads/ within rootDir, mirroring the page path
|
|
44
|
+
const uploadsDir = path.join(rootDir, "_uploads", subPath);
|
|
45
|
+
const resolved = safeWorkspacePath(rootDir, path.join("_uploads", subPath));
|
|
46
|
+
if (!resolved)
|
|
42
47
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
43
48
|
|
|
44
49
|
let form: FormData;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { NextResponse } from "next/server";
|
|
3
3
|
import { checkOrigin } from "@/lib/auth/csrf";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveWorkspaceForUser } from "@/lib/workspace-context";
|
|
5
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
5
6
|
import { getStatus, startApp, stopApp } from "@/lib/app-runner";
|
|
6
|
-
import { getRootDir, safeRootPath } from "@/lib/root-dir";
|
|
7
7
|
|
|
8
8
|
// GET /api/wiki/app?path=relative/path
|
|
9
9
|
export async function GET(request: Request) {
|
|
10
|
-
const
|
|
11
|
-
if (!
|
|
10
|
+
const ctx = await resolveWorkspaceForUser(request);
|
|
11
|
+
if (!ctx.ok) return NextResponse.json({ error: ctx.code }, { status: ctx.status });
|
|
12
12
|
|
|
13
13
|
const { searchParams } = new URL(request.url);
|
|
14
14
|
const rel = searchParams.get("path") ?? "";
|
|
@@ -19,15 +19,16 @@ export async function GET(request: Request) {
|
|
|
19
19
|
export async function POST(request: Request) {
|
|
20
20
|
const csrf = checkOrigin(request);
|
|
21
21
|
if (csrf) return csrf;
|
|
22
|
-
const
|
|
23
|
-
if (!
|
|
22
|
+
const ctx = await resolveWorkspaceForUser(request);
|
|
23
|
+
if (!ctx.ok) return NextResponse.json({ error: ctx.code }, { status: ctx.status });
|
|
24
|
+
const { rootDir } = ctx;
|
|
24
25
|
|
|
25
26
|
const body: { path?: string } = await request.json();
|
|
26
27
|
const rel = body.path;
|
|
27
28
|
if (!rel || typeof rel !== "string")
|
|
28
29
|
return NextResponse.json({ error: "Missing path" }, { status: 400 });
|
|
29
30
|
|
|
30
|
-
const abs =
|
|
31
|
+
const abs = safeWorkspacePath(rootDir, rel);
|
|
31
32
|
if (!abs)
|
|
32
33
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
33
34
|
|
|
@@ -43,8 +44,8 @@ export async function POST(request: Request) {
|
|
|
43
44
|
export async function DELETE(request: Request) {
|
|
44
45
|
const csrf = checkOrigin(request);
|
|
45
46
|
if (csrf) return csrf;
|
|
46
|
-
const
|
|
47
|
-
if (!
|
|
47
|
+
const ctx = await resolveWorkspaceForUser(request);
|
|
48
|
+
if (!ctx.ok) return NextResponse.json({ error: ctx.code }, { status: ctx.status });
|
|
48
49
|
|
|
49
50
|
const body: { path?: string } = await request.json();
|
|
50
51
|
const rel = body.path;
|
|
@@ -3,12 +3,12 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { NextResponse } from "next/server";
|
|
5
5
|
import { checkOrigin } from "@/lib/auth/csrf";
|
|
6
|
-
import {
|
|
6
|
+
import { resolveWorkspaceForUser } from "@/lib/workspace-context";
|
|
7
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
7
8
|
import { emitEvents, trimEvents } from "@/lib/proof/event-bus";
|
|
8
9
|
import { withFileMutex } from "@/lib/proof/mutex";
|
|
9
10
|
import { emptySidecar, readSidecar, writeSidecar } from "@/lib/proof/sidecar";
|
|
10
11
|
import { SIDECAR_EVENT_TRIM_SIZE } from "@/lib/proof-config";
|
|
11
|
-
import { getRootDir, safeRootPath } from "@/lib/root-dir";
|
|
12
12
|
|
|
13
13
|
const TEXT_EXTS = new Set([
|
|
14
14
|
"txt", "md", "markdown", "json", "yaml", "yml", "toml", "csv", "tsv",
|
|
@@ -35,12 +35,13 @@ function sha256content(content: string): string {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export async function GET(request: Request) {
|
|
38
|
-
const
|
|
39
|
-
if (!
|
|
38
|
+
const ctx = await resolveWorkspaceForUser(request);
|
|
39
|
+
if (!ctx.ok) return NextResponse.json({ error: ctx.code }, { status: ctx.status });
|
|
40
|
+
const { rootDir } = ctx;
|
|
40
41
|
|
|
41
42
|
const { searchParams } = new URL(request.url);
|
|
42
43
|
const rel = searchParams.get("path") ?? "";
|
|
43
|
-
const filePath =
|
|
44
|
+
const filePath = safeWorkspacePath(rootDir, rel);
|
|
44
45
|
if (!filePath)
|
|
45
46
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
46
47
|
if (!isTextFile(path.basename(filePath)))
|
|
@@ -55,7 +56,6 @@ export async function GET(request: Request) {
|
|
|
55
56
|
const content = buffer.toString("utf-8");
|
|
56
57
|
const headers: Record<string, string> = {};
|
|
57
58
|
if (isMarkdownFile(path.basename(filePath))) {
|
|
58
|
-
const rootDir = getRootDir();
|
|
59
59
|
const sc = await readSidecar(rootDir, rel);
|
|
60
60
|
if (sc) {
|
|
61
61
|
headers["X-Wiki-Revision"] = String(sc.revision);
|
|
@@ -71,10 +71,9 @@ export async function GET(request: Request) {
|
|
|
71
71
|
export async function PUT(request: Request) {
|
|
72
72
|
const csrf = checkOrigin(request);
|
|
73
73
|
if (csrf) return csrf;
|
|
74
|
-
const
|
|
75
|
-
if (!
|
|
76
|
-
|
|
77
|
-
}
|
|
74
|
+
const ctx = await resolveWorkspaceForUser(request);
|
|
75
|
+
if (!ctx.ok) return NextResponse.json({ error: ctx.code }, { status: ctx.status });
|
|
76
|
+
const { rootDir } = ctx;
|
|
78
77
|
|
|
79
78
|
const body: { path?: string; content?: string; baseRevision?: number } =
|
|
80
79
|
await request.json();
|
|
@@ -84,7 +83,7 @@ export async function PUT(request: Request) {
|
|
|
84
83
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
85
84
|
if (typeof content !== "string")
|
|
86
85
|
return NextResponse.json({ error: "Missing content" }, { status: 400 });
|
|
87
|
-
const filePath =
|
|
86
|
+
const filePath = safeWorkspacePath(rootDir, rel);
|
|
88
87
|
if (!filePath)
|
|
89
88
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
90
89
|
if (!isTextFile(path.basename(filePath)))
|
|
@@ -102,8 +101,9 @@ export async function PUT(request: Request) {
|
|
|
102
101
|
}
|
|
103
102
|
|
|
104
103
|
// Markdown files: mutex + sidecar revision check + fingerprint update + event.
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
// Use the same key format as the agent routes (`${rootDir}\0${rel}`) so a doc
|
|
105
|
+
// edited via both the editor and the agent fs API shares one lock.
|
|
106
|
+
return withFileMutex(`${rootDir}\u0000${rel}`, async () => {
|
|
107
107
|
const sc = (await readSidecar(rootDir, rel)) ?? emptySidecar(rel);
|
|
108
108
|
|
|
109
109
|
// baseRevision is required for markdown to prevent lost writes.
|
|
@@ -146,7 +146,7 @@ export async function PUT(request: Request) {
|
|
|
146
146
|
{
|
|
147
147
|
type: "file.edited",
|
|
148
148
|
at: new Date().toISOString(),
|
|
149
|
-
by: `user:${
|
|
149
|
+
by: `user:${ctx.userId}`,
|
|
150
150
|
revision: newRevision,
|
|
151
151
|
},
|
|
152
152
|
]);
|
|
@@ -4,8 +4,8 @@ import path from "node:path";
|
|
|
4
4
|
import { Readable } from "node:stream";
|
|
5
5
|
import JSZip from "jszip";
|
|
6
6
|
import { NextResponse } from "next/server";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { resolveWorkspaceForUser } from "@/lib/workspace-context";
|
|
8
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
9
9
|
|
|
10
10
|
// Skip noise that should never end up in a downloaded archive.
|
|
11
11
|
const SKIP_DIRS = new Set([".git", "node_modules", ".next", ".proof"]);
|
|
@@ -37,13 +37,14 @@ async function addDirToZip(
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export async function GET(request: Request) {
|
|
40
|
-
const
|
|
41
|
-
if (!
|
|
42
|
-
return NextResponse.json({ error:
|
|
40
|
+
const ctx = await resolveWorkspaceForUser(request);
|
|
41
|
+
if (!ctx.ok)
|
|
42
|
+
return NextResponse.json({ error: ctx.code }, { status: ctx.status });
|
|
43
|
+
const { rootDir } = ctx;
|
|
43
44
|
|
|
44
45
|
const { searchParams } = new URL(request.url);
|
|
45
46
|
const rel = searchParams.get("path") ?? "";
|
|
46
|
-
const target =
|
|
47
|
+
const target = safeWorkspacePath(rootDir, rel);
|
|
47
48
|
if (!target)
|
|
48
49
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
49
50
|
|