@saluzi/saluzi-edu 0.2.9 → 0.2.11
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/dist/cli.js +336 -333
- package/dist/rcs-web/assets/Dashboard-BwotBWlJ.js +1 -0
- package/dist/rcs-web/assets/Join-4yrksbdX.js +1 -0
- package/dist/rcs-web/assets/Login-Cxm_yEeE.js +1 -0
- package/dist/rcs-web/assets/SessionDetail-DNdfPOYy.js +50 -0
- package/dist/rcs-web/assets/Setup-BiAAxugt.js +1 -0
- package/dist/rcs-web/assets/ShareLanding-CP3Z6ckr.js +1 -0
- package/dist/rcs-web/assets/TeamCreate-DgdCwRSb.js +1 -0
- package/dist/rcs-web/assets/TeamDetail-CkNTFoMB.js +11 -0
- package/dist/rcs-web/assets/TeamList-Bf0sQ5RQ.js +1 -0
- package/dist/rcs-web/assets/TeamSettings-BaNAfXU3.js +1 -0
- package/dist/rcs-web/assets/UserSettings-CsutQjxG.js +1 -0
- package/{packages/remote-control-server/web/dist/assets/arc-D90597o-.js → dist/rcs-web/assets/arc-BxxmNQO6.js} +1 -1
- package/dist/rcs-web/assets/architectureDiagram-3BPJPVTR-DBjkRdbd.js +36 -0
- package/dist/rcs-web/assets/{blockDiagram-GPEHLZMM-DHd8IbOs.js → blockDiagram-GPEHLZMM-BF6COWlM.js} +2 -2
- package/dist/rcs-web/assets/{c4Diagram-AAUBKEIU-CjFkQJ9h.js → c4Diagram-AAUBKEIU-DHOf390v.js} +2 -2
- package/dist/rcs-web/assets/channel-JsvbMQjW.js +1 -0
- package/dist/rcs-web/assets/{chunk-2J33WTMH-C21XWnGZ.js → chunk-2J33WTMH-CeJN8yjM.js} +1 -1
- package/dist/rcs-web/assets/{chunk-4BX2VUAB-B3SXiJlt.js → chunk-4BX2VUAB-jP76_P2A.js} +1 -1
- package/dist/rcs-web/assets/{chunk-55IACEB6-DjImv45F.js → chunk-55IACEB6-BsFA6emB.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/chunk-727SXJPM-DtnaqsyD.js → dist/rcs-web/assets/chunk-727SXJPM-BF4HrQjZ.js} +1 -1
- package/dist/rcs-web/assets/{chunk-AQP2D5EJ-BVFgH5mS.js → chunk-AQP2D5EJ-DToJ74Kc.js} +1 -1
- package/dist/rcs-web/assets/{chunk-FMBD7UC4-Bl8jgb57.js → chunk-FMBD7UC4-DVTARgsa.js} +1 -1
- package/dist/rcs-web/assets/{chunk-ND2GUHAM-BpK111zh.js → chunk-ND2GUHAM-C50Gqv9c.js} +1 -1
- package/dist/rcs-web/assets/{chunk-QZHKN3VN-ruhIHBim.js → chunk-QZHKN3VN-EsIIh6zV.js} +1 -1
- package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-BXn8Uc4c.js +1 -0
- package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-BXn8Uc4c.js +1 -0
- package/dist/rcs-web/assets/code-block-IT6T5CEO-BnufHNTT.js +2 -0
- package/dist/rcs-web/assets/cose-bilkent-S5V4N54A-M6tNt14I.js +1 -0
- package/dist/rcs-web/assets/dagre-BM42HDAG-DaTm29qG.js +4 -0
- package/dist/rcs-web/assets/diagram-2AECGRRQ-fqoeOvq2.js +43 -0
- package/dist/rcs-web/assets/diagram-5GNKFQAL-6s2CiaGG.js +10 -0
- package/dist/rcs-web/assets/{diagram-KO2AKTUF-Uy3PDP5S.js → diagram-KO2AKTUF-C0aw_N95.js} +2 -2
- package/dist/rcs-web/assets/diagram-LMA3HP47-C8_Rv3rB.js +24 -0
- package/dist/rcs-web/assets/diagram-OG6HWLK6-Dae4u8Uc.js +24 -0
- package/{packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-sre_MTeK.js → dist/rcs-web/assets/erDiagram-TEJ5UH35-CosS5VWr.js} +13 -13
- package/dist/rcs-web/assets/{flowDiagram-I6XJVG4X-DwrWaLoe.js → flowDiagram-I6XJVG4X-D_Mxs46-.js} +2 -2
- package/dist/rcs-web/assets/ganttDiagram-6RSMTGT7-B0jy8Am_.js +292 -0
- package/dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-CSdu2HVI.js +106 -0
- package/dist/rcs-web/assets/i18n-Dbt-vEQ3.js +1 -0
- package/dist/rcs-web/assets/infoDiagram-5YYISTIA-Dcbc9L1S.js +2 -0
- package/{packages/remote-control-server/web/dist/assets/ishikawaDiagram-YF4QCWOH-SO0nn3--.js → dist/rcs-web/assets/ishikawaDiagram-YF4QCWOH-BLMjFE4t.js} +2 -2
- package/dist/rcs-web/assets/{journeyDiagram-JHISSGLW-D4igFUd4.js → journeyDiagram-JHISSGLW-Dw4nh1xI.js} +2 -2
- package/dist/rcs-web/assets/{kanban-definition-UN3LZRKU-Cm_yKsZC.js → kanban-definition-UN3LZRKU-DkU3j_ly.js} +2 -2
- package/dist/rcs-web/assets/{linear-4IMGll_E.js → linear-N5Cify7M.js} +1 -1
- package/dist/rcs-web/assets/main-30YqUvTd.js +238 -0
- package/dist/rcs-web/assets/main-EP6Lac2m.css +1 -0
- package/{packages/remote-control-server/web/dist/assets/mermaid-VLURNSYL-D_yQ7nAd.js → dist/rcs-web/assets/mermaid-VLURNSYL-gfiJUpl_.js} +5 -5
- package/dist/rcs-web/assets/{mermaid.core-B1qOUdiU.js → mermaid.core-B_Xc65Bf.js} +5 -5
- package/dist/rcs-web/assets/{mindmap-definition-RKZ34NQL-yETom5qt.js → mindmap-definition-RKZ34NQL-DUavHfNu.js} +2 -2
- package/{packages/remote-control-server/web/dist/assets/pieDiagram-4H26LBE5-KIhqXGT6.js → dist/rcs-web/assets/pieDiagram-4H26LBE5-DSJaToTU.js} +2 -2
- package/{packages/remote-control-server/web/dist/assets/quadrantDiagram-W4KKPZXB-DISqmoA6.js → dist/rcs-web/assets/quadrantDiagram-W4KKPZXB-BFp6TnHj.js} +2 -2
- package/dist/rcs-web/assets/{requirementDiagram-4Y6WPE33-DsgT4ptk.js → requirementDiagram-4Y6WPE33-eil6F3-O.js} +2 -2
- package/{packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-Dn67kbn0.js → dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-DbGhoepK.js} +2 -2
- package/{packages/remote-control-server/web/dist/assets/sequenceDiagram-3UESZ5HK-CtWaXZHl.js → dist/rcs-web/assets/sequenceDiagram-3UESZ5HK-B0YrN1ud.js} +14 -14
- package/dist/rcs-web/assets/stateDiagram-AJRCARHV-CofFPj3N.js +1 -0
- package/dist/rcs-web/assets/stateDiagram-v2-BHNVJYJU-DPlcvPn1.js +1 -0
- package/{packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-Dk5WUenC.js → dist/rcs-web/assets/timeline-definition-PNZ67QCA-Bx4dusy8.js} +2 -2
- package/dist/rcs-web/assets/useTeams-MDI4djXg.js +1 -0
- package/{packages/remote-control-server/web/dist/assets/vennDiagram-CIIHVFJN-TY8EiRrC.js → dist/rcs-web/assets/vennDiagram-CIIHVFJN-B_-3l-MF.js} +2 -2
- package/dist/rcs-web/assets/{wardleyDiagram-YWT4CUSO-BK3oi47X.js → wardleyDiagram-YWT4CUSO-DNSn-pGp.js} +2 -2
- package/dist/rcs-web/assets/workerType-OM09y7Lk.js +1 -0
- package/{packages/remote-control-server/web/dist/assets/xychartDiagram-2RQKCTM6-DhsxqX67.js → dist/rcs-web/assets/xychartDiagram-2RQKCTM6-TqUbNp0j.js} +2 -2
- package/dist/rcs-web/index.html +2 -3
- package/package.json +2 -1
- package/packages/remote-control-server/src/__tests__/acp-ws-handler.test.ts +7 -19
- package/packages/remote-control-server/src/__tests__/auth-login.test.ts +561 -0
- package/packages/remote-control-server/src/__tests__/auth-security.test.ts +547 -0
- package/packages/remote-control-server/src/__tests__/auth.test.ts +7 -18
- package/packages/remote-control-server/src/__tests__/bind-replacement.test.ts +251 -0
- package/packages/remote-control-server/src/__tests__/cookie.test.ts +155 -0
- package/packages/remote-control-server/src/__tests__/data-layer-fixes.test.ts +147 -0
- package/packages/remote-control-server/src/__tests__/db.test.ts +582 -0
- package/packages/remote-control-server/src/__tests__/design-gaps.test.ts +440 -0
- package/packages/remote-control-server/src/__tests__/disconnect-monitor.test.ts +2 -18
- package/packages/remote-control-server/src/__tests__/helpers/db.ts +43 -0
- package/packages/remote-control-server/src/__tests__/helpers/fixtures.ts +94 -0
- package/packages/remote-control-server/src/__tests__/helpers/mock-config.ts +31 -0
- package/packages/remote-control-server/src/__tests__/middleware.test.ts +4 -112
- package/packages/remote-control-server/src/__tests__/password.test.ts +76 -0
- package/packages/remote-control-server/src/__tests__/phase4-cleanup.test.ts +290 -0
- package/packages/remote-control-server/src/__tests__/phase4-integration.test.ts +224 -0
- package/packages/remote-control-server/src/__tests__/routes.test.ts +292 -207
- package/packages/remote-control-server/src/__tests__/services.test.ts +2 -18
- package/packages/remote-control-server/src/__tests__/session-visibility.test.ts +452 -0
- package/packages/remote-control-server/src/__tests__/session.test.ts +216 -0
- package/packages/remote-control-server/src/__tests__/shares.test.ts +1419 -0
- package/packages/remote-control-server/src/__tests__/sse-writer.test.ts +2 -18
- package/packages/remote-control-server/src/__tests__/teams.test.ts +2089 -0
- package/packages/remote-control-server/src/__tests__/work-dispatch.test.ts +2 -18
- package/packages/remote-control-server/src/__tests__/worker-token-removal.test.ts +487 -0
- package/packages/remote-control-server/src/__tests__/ws-handler.test.ts +2 -18
- package/packages/remote-control-server/src/auth/constants.ts +13 -0
- package/packages/remote-control-server/src/auth/cookie.ts +75 -0
- package/packages/remote-control-server/src/auth/middleware.ts +75 -165
- package/packages/remote-control-server/src/auth/password.ts +116 -0
- package/packages/remote-control-server/src/auth/session.ts +130 -0
- package/packages/remote-control-server/src/db/schema.sql +116 -0
- package/packages/remote-control-server/src/db/sqlite.ts +99 -0
- package/packages/remote-control-server/src/routes/acp/index.ts +6 -11
- package/packages/remote-control-server/src/routes/v1/environments.ts +111 -8
- package/packages/remote-control-server/src/routes/web/auth-routes.ts +634 -0
- package/packages/remote-control-server/src/routes/web/control.ts +5 -5
- package/packages/remote-control-server/src/routes/web/environments.ts +5 -27
- package/packages/remote-control-server/src/routes/web/sessions.ts +19 -41
- package/packages/remote-control-server/src/routes/web/shares.ts +371 -0
- package/packages/remote-control-server/src/routes/web/teams.ts +850 -0
- package/packages/remote-control-server/src/services/environment.ts +1 -4
- package/packages/remote-control-server/src/services/session-visibility.ts +79 -0
- package/packages/remote-control-server/src/services/session.ts +0 -13
- package/packages/remote-control-server/src/store.ts +150 -56
- package/packages/remote-control-server/src/types/api.ts +2 -8
- package/packages/remote-control-server/web/dist/assets/Dashboard-BwotBWlJ.js +1 -0
- package/packages/remote-control-server/web/dist/assets/Join-4yrksbdX.js +1 -0
- package/packages/remote-control-server/web/dist/assets/Login-Cxm_yEeE.js +1 -0
- package/packages/remote-control-server/web/dist/assets/SessionDetail-DNdfPOYy.js +50 -0
- package/packages/remote-control-server/web/dist/assets/Setup-BiAAxugt.js +1 -0
- package/packages/remote-control-server/web/dist/assets/ShareLanding-CP3Z6ckr.js +1 -0
- package/packages/remote-control-server/web/dist/assets/TeamCreate-DgdCwRSb.js +1 -0
- package/packages/remote-control-server/web/dist/assets/TeamDetail-CkNTFoMB.js +11 -0
- package/packages/remote-control-server/web/dist/assets/TeamList-Bf0sQ5RQ.js +1 -0
- package/packages/remote-control-server/web/dist/assets/TeamSettings-BaNAfXU3.js +1 -0
- package/packages/remote-control-server/web/dist/assets/UserSettings-CsutQjxG.js +1 -0
- package/{dist/rcs-web/assets/arc-D90597o-.js → packages/remote-control-server/web/dist/assets/arc-BxxmNQO6.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/architectureDiagram-3BPJPVTR-DBjkRdbd.js +36 -0
- package/packages/remote-control-server/web/dist/assets/{blockDiagram-GPEHLZMM-DHd8IbOs.js → blockDiagram-GPEHLZMM-BF6COWlM.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/{c4Diagram-AAUBKEIU-CjFkQJ9h.js → c4Diagram-AAUBKEIU-DHOf390v.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/channel-JsvbMQjW.js +1 -0
- package/packages/remote-control-server/web/dist/assets/{chunk-2J33WTMH-C21XWnGZ.js → chunk-2J33WTMH-CeJN8yjM.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-4BX2VUAB-B3SXiJlt.js → chunk-4BX2VUAB-jP76_P2A.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-55IACEB6-DjImv45F.js → chunk-55IACEB6-BsFA6emB.js} +1 -1
- package/{dist/rcs-web/assets/chunk-727SXJPM-DtnaqsyD.js → packages/remote-control-server/web/dist/assets/chunk-727SXJPM-BF4HrQjZ.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-AQP2D5EJ-BVFgH5mS.js → chunk-AQP2D5EJ-DToJ74Kc.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-FMBD7UC4-Bl8jgb57.js → chunk-FMBD7UC4-DVTARgsa.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-ND2GUHAM-BpK111zh.js → chunk-ND2GUHAM-C50Gqv9c.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-QZHKN3VN-ruhIHBim.js → chunk-QZHKN3VN-EsIIh6zV.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-BXn8Uc4c.js +1 -0
- package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-BXn8Uc4c.js +1 -0
- package/packages/remote-control-server/web/dist/assets/code-block-IT6T5CEO-BnufHNTT.js +2 -0
- package/packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A-M6tNt14I.js +1 -0
- package/packages/remote-control-server/web/dist/assets/dagre-BM42HDAG-DaTm29qG.js +4 -0
- package/packages/remote-control-server/web/dist/assets/diagram-2AECGRRQ-fqoeOvq2.js +43 -0
- package/packages/remote-control-server/web/dist/assets/diagram-5GNKFQAL-6s2CiaGG.js +10 -0
- package/packages/remote-control-server/web/dist/assets/{diagram-KO2AKTUF-Uy3PDP5S.js → diagram-KO2AKTUF-C0aw_N95.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/diagram-LMA3HP47-C8_Rv3rB.js +24 -0
- package/packages/remote-control-server/web/dist/assets/diagram-OG6HWLK6-Dae4u8Uc.js +24 -0
- package/{dist/rcs-web/assets/erDiagram-TEJ5UH35-sre_MTeK.js → packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-CosS5VWr.js} +13 -13
- package/packages/remote-control-server/web/dist/assets/{flowDiagram-I6XJVG4X-DwrWaLoe.js → flowDiagram-I6XJVG4X-D_Mxs46-.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-B0jy8Am_.js +292 -0
- package/packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-CSdu2HVI.js +106 -0
- package/packages/remote-control-server/web/dist/assets/i18n-Dbt-vEQ3.js +1 -0
- package/packages/remote-control-server/web/dist/assets/infoDiagram-5YYISTIA-Dcbc9L1S.js +2 -0
- package/{dist/rcs-web/assets/ishikawaDiagram-YF4QCWOH-SO0nn3--.js → packages/remote-control-server/web/dist/assets/ishikawaDiagram-YF4QCWOH-BLMjFE4t.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/{journeyDiagram-JHISSGLW-D4igFUd4.js → journeyDiagram-JHISSGLW-Dw4nh1xI.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/{kanban-definition-UN3LZRKU-Cm_yKsZC.js → kanban-definition-UN3LZRKU-DkU3j_ly.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/{linear-4IMGll_E.js → linear-N5Cify7M.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/main-30YqUvTd.js +238 -0
- package/packages/remote-control-server/web/dist/assets/main-EP6Lac2m.css +1 -0
- package/{dist/rcs-web/assets/mermaid-VLURNSYL-D_yQ7nAd.js → packages/remote-control-server/web/dist/assets/mermaid-VLURNSYL-gfiJUpl_.js} +5 -5
- package/packages/remote-control-server/web/dist/assets/{mermaid.core-B1qOUdiU.js → mermaid.core-B_Xc65Bf.js} +5 -5
- package/packages/remote-control-server/web/dist/assets/{mindmap-definition-RKZ34NQL-yETom5qt.js → mindmap-definition-RKZ34NQL-DUavHfNu.js} +2 -2
- package/{dist/rcs-web/assets/pieDiagram-4H26LBE5-KIhqXGT6.js → packages/remote-control-server/web/dist/assets/pieDiagram-4H26LBE5-DSJaToTU.js} +2 -2
- package/{dist/rcs-web/assets/quadrantDiagram-W4KKPZXB-DISqmoA6.js → packages/remote-control-server/web/dist/assets/quadrantDiagram-W4KKPZXB-BFp6TnHj.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/{requirementDiagram-4Y6WPE33-DsgT4ptk.js → requirementDiagram-4Y6WPE33-eil6F3-O.js} +2 -2
- package/{dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-Dn67kbn0.js → packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-DbGhoepK.js} +2 -2
- package/{dist/rcs-web/assets/sequenceDiagram-3UESZ5HK-CtWaXZHl.js → packages/remote-control-server/web/dist/assets/sequenceDiagram-3UESZ5HK-B0YrN1ud.js} +14 -14
- package/packages/remote-control-server/web/dist/assets/stateDiagram-AJRCARHV-CofFPj3N.js +1 -0
- package/packages/remote-control-server/web/dist/assets/stateDiagram-v2-BHNVJYJU-DPlcvPn1.js +1 -0
- package/{dist/rcs-web/assets/timeline-definition-PNZ67QCA-Dk5WUenC.js → packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-Bx4dusy8.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/useTeams-MDI4djXg.js +1 -0
- package/{dist/rcs-web/assets/vennDiagram-CIIHVFJN-TY8EiRrC.js → packages/remote-control-server/web/dist/assets/vennDiagram-CIIHVFJN-B_-3l-MF.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/{wardleyDiagram-YWT4CUSO-BK3oi47X.js → wardleyDiagram-YWT4CUSO-DNSn-pGp.js} +2 -2
- package/packages/remote-control-server/web/dist/assets/workerType-OM09y7Lk.js +1 -0
- package/{dist/rcs-web/assets/xychartDiagram-2RQKCTM6-DhsxqX67.js → packages/remote-control-server/web/dist/assets/xychartDiagram-2RQKCTM6-TqUbNp0j.js} +2 -2
- package/packages/remote-control-server/web/dist/index.html +2 -3
- package/dist/rcs-web/assets/Dashboard-Cyj-Bb86.js +0 -2
- package/dist/rcs-web/assets/SessionDetail-SA9QBkyj.js +0 -51
- package/dist/rcs-web/assets/architectureDiagram-3BPJPVTR-CG9q9_bk.js +0 -36
- package/dist/rcs-web/assets/channel-CQFGglg-.js +0 -1
- package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-C5rBdShD.js +0 -1
- package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-C5rBdShD.js +0 -1
- package/dist/rcs-web/assets/code-block-IT6T5CEO-BLGFrBw3.js +0 -2
- package/dist/rcs-web/assets/cose-bilkent-S5V4N54A-DBKEXjqM.js +0 -1
- package/dist/rcs-web/assets/dagre-BM42HDAG-DB_SWlAe.js +0 -4
- package/dist/rcs-web/assets/diagram-2AECGRRQ-Gbm8G3Xz.js +0 -43
- package/dist/rcs-web/assets/diagram-5GNKFQAL-BBuWqfDc.js +0 -10
- package/dist/rcs-web/assets/diagram-LMA3HP47-DyUwNrlg.js +0 -24
- package/dist/rcs-web/assets/diagram-OG6HWLK6-BXpvRwkJ.js +0 -24
- package/dist/rcs-web/assets/ganttDiagram-6RSMTGT7-ByDYviDl.js +0 -292
- package/dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-BUnOPw74.js +0 -106
- package/dist/rcs-web/assets/infoDiagram-5YYISTIA-B1RpwJHG.js +0 -2
- package/dist/rcs-web/assets/main-0A4a3FDU.css +0 -1
- package/dist/rcs-web/assets/main-Dom16YJk.js +0 -283
- package/dist/rcs-web/assets/qr-C0jP9HcD.js +0 -8
- package/dist/rcs-web/assets/qr-scanner-worker.min-D85Z9gVD.js +0 -98
- package/dist/rcs-web/assets/stateDiagram-AJRCARHV-D6xp64f3.js +0 -1
- package/dist/rcs-web/assets/stateDiagram-v2-BHNVJYJU-D76vZCyQ.js +0 -1
- package/packages/remote-control-server/web/dist/assets/Dashboard-Cyj-Bb86.js +0 -2
- package/packages/remote-control-server/web/dist/assets/SessionDetail-SA9QBkyj.js +0 -51
- package/packages/remote-control-server/web/dist/assets/architectureDiagram-3BPJPVTR-CG9q9_bk.js +0 -36
- package/packages/remote-control-server/web/dist/assets/channel-CQFGglg-.js +0 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-C5rBdShD.js +0 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-C5rBdShD.js +0 -1
- package/packages/remote-control-server/web/dist/assets/code-block-IT6T5CEO-BLGFrBw3.js +0 -2
- package/packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A-DBKEXjqM.js +0 -1
- package/packages/remote-control-server/web/dist/assets/dagre-BM42HDAG-DB_SWlAe.js +0 -4
- package/packages/remote-control-server/web/dist/assets/diagram-2AECGRRQ-Gbm8G3Xz.js +0 -43
- package/packages/remote-control-server/web/dist/assets/diagram-5GNKFQAL-BBuWqfDc.js +0 -10
- package/packages/remote-control-server/web/dist/assets/diagram-LMA3HP47-DyUwNrlg.js +0 -24
- package/packages/remote-control-server/web/dist/assets/diagram-OG6HWLK6-BXpvRwkJ.js +0 -24
- package/packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-ByDYviDl.js +0 -292
- package/packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-BUnOPw74.js +0 -106
- package/packages/remote-control-server/web/dist/assets/infoDiagram-5YYISTIA-B1RpwJHG.js +0 -2
- package/packages/remote-control-server/web/dist/assets/main-0A4a3FDU.css +0 -1
- package/packages/remote-control-server/web/dist/assets/main-Dom16YJk.js +0 -283
- package/packages/remote-control-server/web/dist/assets/qr-C0jP9HcD.js +0 -8
- package/packages/remote-control-server/web/dist/assets/qr-scanner-worker.min-D85Z9gVD.js +0 -98
- package/packages/remote-control-server/web/dist/assets/stateDiagram-AJRCARHV-D6xp64f3.js +0 -1
- package/packages/remote-control-server/web/dist/assets/stateDiagram-v2-BHNVJYJU-D76vZCyQ.js +0 -1
|
@@ -1,44 +1,22 @@
|
|
|
1
1
|
import { Hono } from 'hono'
|
|
2
|
-
import {
|
|
2
|
+
import { sessionAuth } from '../../auth/middleware'
|
|
3
3
|
import { config } from '../../config'
|
|
4
4
|
import { listActiveEnvironmentsResponse } from '../../services/environment'
|
|
5
5
|
import { listWebSessionsByOwnerUuid } from '../../services/session'
|
|
6
|
-
import {
|
|
6
|
+
import { storeListActiveEnvironments } from '../../store'
|
|
7
7
|
|
|
8
8
|
const app = new Hono()
|
|
9
9
|
|
|
10
10
|
/** GET /web/environments — List active environments (UUID-based, no user filtering) */
|
|
11
|
-
app.get('/environments',
|
|
11
|
+
app.get('/environments', sessionAuth, async c => {
|
|
12
12
|
// Environments are shared across all UUIDs for now
|
|
13
13
|
const envs = listActiveEnvironmentsResponse()
|
|
14
14
|
return c.json(envs, 200)
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
/** POST /web/environments/:id/test-worker-token — Verify a worker token for an environment */
|
|
18
|
-
app.post('/environments/:id/test-worker-token', uuidAuth, async c => {
|
|
19
|
-
const envId = c.req.param('id')
|
|
20
|
-
if (!envId) {
|
|
21
|
-
return c.json(
|
|
22
|
-
{ error: { type: 'bad_request', message: 'Missing environment id' } },
|
|
23
|
-
400,
|
|
24
|
-
)
|
|
25
|
-
}
|
|
26
|
-
const env = storeGetEnvironment(envId)
|
|
27
|
-
if (!env) {
|
|
28
|
-
return c.json(
|
|
29
|
-
{ error: { type: 'not_found', message: 'Environment not found' } },
|
|
30
|
-
404,
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
const body = await c.req.json().catch(() => ({}))
|
|
34
|
-
const token = typeof body?.token === 'string' ? body.token : undefined
|
|
35
|
-
const valid = verifyWorkerTokenForEnv(env, token)
|
|
36
|
-
return c.json({ valid, env_id: envId }, 200)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
17
|
/** GET /web/server-info — Aggregate server status for Web UI identity panel */
|
|
40
|
-
app.get('/server-info',
|
|
41
|
-
const uuid = c.get('
|
|
18
|
+
app.get('/server-info', sessionAuth, async c => {
|
|
19
|
+
const uuid = c.get('userId')!
|
|
42
20
|
const envs = storeListActiveEnvironments()
|
|
43
21
|
const sessions = listWebSessionsByOwnerUuid(uuid)
|
|
44
22
|
return c.json(
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { log, error as logError } from '../../logger'
|
|
2
2
|
import { Hono } from 'hono'
|
|
3
|
-
import {
|
|
4
|
-
uuidAuth,
|
|
5
|
-
requireWorkerToken,
|
|
6
|
-
verifyWorkerTokenForEnv,
|
|
7
|
-
} from '../../auth/middleware'
|
|
3
|
+
import { sessionAuth } from '../../auth/middleware'
|
|
8
4
|
import { getAutomationStateSnapshot } from '../../services/automationState'
|
|
9
5
|
import {
|
|
10
6
|
archiveSession,
|
|
@@ -30,29 +26,13 @@ import { getEventBus } from '../../transport/event-bus'
|
|
|
30
26
|
const app = new Hono()
|
|
31
27
|
|
|
32
28
|
/** POST /web/sessions — Create a session from web UI */
|
|
33
|
-
app.post('/sessions',
|
|
34
|
-
const uuid = c.get('
|
|
29
|
+
app.post('/sessions', sessionAuth, async c => {
|
|
30
|
+
const uuid = c.get('userId')!
|
|
35
31
|
const body = await c.req.json()
|
|
36
32
|
|
|
37
|
-
// Pre-validate
|
|
38
|
-
// environment has a workerTokenHash, the user must supply the matching
|
|
39
|
-
// plaintext token (body.worker_token or X-Worker-Token header). Returning
|
|
40
|
-
// 403 here avoids creating an orphaned empty session the user can't access.
|
|
33
|
+
// Pre-validate BEFORE creating the session record.
|
|
41
34
|
if (body.environment_id) {
|
|
42
35
|
const env = storeGetEnvironment(body.environment_id)
|
|
43
|
-
const workerToken =
|
|
44
|
-
body.worker_token || c.req.header('X-Worker-Token') || undefined
|
|
45
|
-
if (!verifyWorkerTokenForEnv(env, workerToken)) {
|
|
46
|
-
return c.json(
|
|
47
|
-
{
|
|
48
|
-
error: {
|
|
49
|
-
type: 'forbidden',
|
|
50
|
-
message: 'Worker token 不匹配,无法创建会话',
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
403,
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
36
|
|
|
57
37
|
// ACP environments: registerEnvironment already auto-created a
|
|
58
38
|
// source:'acp' session for this env. acp-link workers don't poll work
|
|
@@ -127,22 +107,22 @@ app.post('/sessions', uuidAuth, async c => {
|
|
|
127
107
|
})
|
|
128
108
|
|
|
129
109
|
/** GET /web/sessions — List sessions owned by the requesting UUID */
|
|
130
|
-
app.get('/sessions',
|
|
131
|
-
const uuid = c.get('
|
|
110
|
+
app.get('/sessions', sessionAuth, async c => {
|
|
111
|
+
const uuid = c.get('userId')!
|
|
132
112
|
const sessions = listWebSessionsByOwnerUuid(uuid)
|
|
133
113
|
return c.json(sessions, 200)
|
|
134
114
|
})
|
|
135
115
|
|
|
136
116
|
/** GET /web/sessions/all — List sessions owned by the requesting UUID (unowned sessions excluded) */
|
|
137
|
-
app.get('/sessions/all',
|
|
138
|
-
const uuid = c.get('
|
|
117
|
+
app.get('/sessions/all', sessionAuth, async c => {
|
|
118
|
+
const uuid = c.get('userId')!
|
|
139
119
|
const sessions = listWebSessionSummariesByOwnerUuid(uuid)
|
|
140
120
|
return c.json(sessions, 200)
|
|
141
121
|
})
|
|
142
122
|
|
|
143
123
|
/** GET /web/sessions/:id — Session detail */
|
|
144
|
-
app.get('/sessions/:id',
|
|
145
|
-
const uuid = c.get('
|
|
124
|
+
app.get('/sessions/:id', sessionAuth, async c => {
|
|
125
|
+
const uuid = c.get('userId')!
|
|
146
126
|
const sessionId = resolveOwnedWebSessionId(c.req.param('id')!, uuid)
|
|
147
127
|
if (!sessionId) {
|
|
148
128
|
return c.json(
|
|
@@ -189,7 +169,6 @@ app.get('/sessions/:id', uuidAuth, requireWorkerToken, async c => {
|
|
|
189
169
|
? {
|
|
190
170
|
id: env.id,
|
|
191
171
|
machine_name: env.machineName,
|
|
192
|
-
has_worker_token: env.workerTokenHash !== null,
|
|
193
172
|
worker_type: env.workerType,
|
|
194
173
|
}
|
|
195
174
|
: null,
|
|
@@ -199,8 +178,8 @@ app.get('/sessions/:id', uuidAuth, requireWorkerToken, async c => {
|
|
|
199
178
|
})
|
|
200
179
|
|
|
201
180
|
/** GET /web/sessions/:id/history — Historical events for session */
|
|
202
|
-
app.get('/sessions/:id/history',
|
|
203
|
-
const uuid = c.get('
|
|
181
|
+
app.get('/sessions/:id/history', sessionAuth, async c => {
|
|
182
|
+
const uuid = c.get('userId')!
|
|
204
183
|
const sessionId = resolveOwnedWebSessionId(c.req.param('id')!, uuid)
|
|
205
184
|
if (!sessionId) {
|
|
206
185
|
return c.json(
|
|
@@ -222,8 +201,8 @@ app.get('/sessions/:id/history', uuidAuth, requireWorkerToken, async c => {
|
|
|
222
201
|
})
|
|
223
202
|
|
|
224
203
|
/** SSE /web/sessions/:id/events — Real-time event stream */
|
|
225
|
-
app.get('/sessions/:id/events',
|
|
226
|
-
const uuid = c.get('
|
|
204
|
+
app.get('/sessions/:id/events', sessionAuth, async c => {
|
|
205
|
+
const uuid = c.get('userId')!
|
|
227
206
|
const sessionId = resolveOwnedWebSessionId(c.req.param('id')!, uuid)
|
|
228
207
|
if (!sessionId) {
|
|
229
208
|
return c.json(
|
|
@@ -256,12 +235,11 @@ app.get('/sessions/:id/events', uuidAuth, requireWorkerToken, async c => {
|
|
|
256
235
|
})
|
|
257
236
|
|
|
258
237
|
/** DELETE /web/sessions/:id — Archive (soft-delete) a session.
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const uuid = c.get('uuid')!
|
|
238
|
+
* Archived sessions disappear from the list but remain in storage for audit.
|
|
239
|
+
* Also stops the associated work item so the worker's heartbeat detects 410
|
|
240
|
+
* and kills the child process, releasing capacity. */
|
|
241
|
+
app.delete('/sessions/:id', sessionAuth, async c => {
|
|
242
|
+
const uuid = c.get('userId')!
|
|
265
243
|
const sessionId = resolveOwnedWebSessionId(c.req.param('id')!, uuid)
|
|
266
244
|
if (!sessionId) {
|
|
267
245
|
return c.json(
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { Hono } from 'hono'
|
|
2
|
+
import { randomUUID } from 'node:crypto'
|
|
3
|
+
import { getDb } from '../../db/sqlite'
|
|
4
|
+
import { sessionAuth } from '../../auth/middleware'
|
|
5
|
+
import { SYSTEM_USER_ID } from '../../auth/constants'
|
|
6
|
+
|
|
7
|
+
const app = new Hono()
|
|
8
|
+
|
|
9
|
+
interface SessionOwnerRow {
|
|
10
|
+
owner_type: string
|
|
11
|
+
owner_id: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface ShareRow {
|
|
15
|
+
id: string
|
|
16
|
+
session_id: string
|
|
17
|
+
granted_to_user: string | null
|
|
18
|
+
granted_to_team: string | null
|
|
19
|
+
permission: string
|
|
20
|
+
expires_at: string | null
|
|
21
|
+
granted_by: string
|
|
22
|
+
granted_at: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Helper: check if the current user is the session owner.
|
|
27
|
+
* Returns the userId on success, or a Response on failure.
|
|
28
|
+
*/
|
|
29
|
+
function checkSessionOwnership(
|
|
30
|
+
c: import('hono').Context,
|
|
31
|
+
sessionId: string,
|
|
32
|
+
): { userId: string } | Response {
|
|
33
|
+
const userId = c.get('userId') as string | undefined
|
|
34
|
+
const isAdmin = c.get('isAdmin') as boolean | undefined
|
|
35
|
+
|
|
36
|
+
if (!userId) {
|
|
37
|
+
return c.json(
|
|
38
|
+
{
|
|
39
|
+
error: { type: 'unauthorized', message: 'Not authenticated' },
|
|
40
|
+
},
|
|
41
|
+
401,
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const db = getDb()
|
|
46
|
+
|
|
47
|
+
// Check session exists
|
|
48
|
+
const session = db
|
|
49
|
+
.query('SELECT id FROM sessions WHERE id = $id')
|
|
50
|
+
.get({ $id: sessionId })
|
|
51
|
+
if (!session) {
|
|
52
|
+
return c.json(
|
|
53
|
+
{ error: { type: 'not_found', message: 'Session not found' } },
|
|
54
|
+
404,
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// System admin bypasses ownership check
|
|
59
|
+
if (isAdmin || userId === SYSTEM_USER_ID) {
|
|
60
|
+
return { userId }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Check ownership: user owns the session directly
|
|
64
|
+
const ownerRow = db
|
|
65
|
+
.query(
|
|
66
|
+
`SELECT owner_type, owner_id FROM session_owners
|
|
67
|
+
WHERE session_id = $sid
|
|
68
|
+
AND owner_type = 'user'
|
|
69
|
+
AND owner_id = $uid`,
|
|
70
|
+
)
|
|
71
|
+
.get({ $sid: sessionId, $uid: userId }) as SessionOwnerRow | null
|
|
72
|
+
|
|
73
|
+
if (ownerRow) {
|
|
74
|
+
return { userId }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Check ownership: user's team owns the session
|
|
78
|
+
const teamOwner = db
|
|
79
|
+
.query(
|
|
80
|
+
`SELECT so.owner_id FROM session_owners so
|
|
81
|
+
JOIN team_members tm ON tm.team_id = so.owner_id
|
|
82
|
+
WHERE so.session_id = $sid
|
|
83
|
+
AND so.owner_type = 'team'
|
|
84
|
+
AND tm.user_id = $uid`,
|
|
85
|
+
)
|
|
86
|
+
.get({ $sid: sessionId, $uid: userId })
|
|
87
|
+
|
|
88
|
+
if (teamOwner) {
|
|
89
|
+
return { userId }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return c.json(
|
|
93
|
+
{ error: { type: 'forbidden', message: 'Not session owner' } },
|
|
94
|
+
403,
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* POST /sessions/:id/share — Create a share for a session.
|
|
100
|
+
*/
|
|
101
|
+
app.post(
|
|
102
|
+
'/sessions/:id/share',
|
|
103
|
+
async (c, next) => {
|
|
104
|
+
const result = await sessionAuth(c, next)
|
|
105
|
+
if (result) return result
|
|
106
|
+
},
|
|
107
|
+
async c => {
|
|
108
|
+
const sessionId = c.req.param('id')
|
|
109
|
+
const ownership = checkSessionOwnership(c, sessionId)
|
|
110
|
+
if (ownership instanceof Response) return ownership
|
|
111
|
+
const { userId } = ownership
|
|
112
|
+
|
|
113
|
+
let body: Record<string, unknown>
|
|
114
|
+
try {
|
|
115
|
+
body = await c.req.json()
|
|
116
|
+
} catch {
|
|
117
|
+
return c.json(
|
|
118
|
+
{ error: { type: 'bad_request', message: 'Invalid JSON' } },
|
|
119
|
+
400,
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const grantedTo = body.grantedTo as
|
|
124
|
+
| { userId?: string; teamId?: string }
|
|
125
|
+
| undefined
|
|
126
|
+
const permission = body.permission as string | undefined
|
|
127
|
+
const expiresAt = (body.expiresAt || body.expires_at) as string | undefined
|
|
128
|
+
|
|
129
|
+
// Validate permission
|
|
130
|
+
if (!permission) {
|
|
131
|
+
return c.json(
|
|
132
|
+
{
|
|
133
|
+
error: {
|
|
134
|
+
type: 'bad_request',
|
|
135
|
+
message: 'permission is required',
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
400,
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
if (permission !== 'read' && permission !== 'write') {
|
|
142
|
+
return c.json(
|
|
143
|
+
{
|
|
144
|
+
error: {
|
|
145
|
+
type: 'bad_request',
|
|
146
|
+
message: 'permission must be "read" or "write"',
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
400,
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Validate grantedTo
|
|
154
|
+
if (!grantedTo) {
|
|
155
|
+
return c.json(
|
|
156
|
+
{
|
|
157
|
+
error: {
|
|
158
|
+
type: 'bad_request',
|
|
159
|
+
message: 'grantedTo is required',
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
400,
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const db = getDb()
|
|
167
|
+
|
|
168
|
+
// Validate target user/team exists
|
|
169
|
+
if (grantedTo.userId) {
|
|
170
|
+
const user = db
|
|
171
|
+
.query('SELECT id FROM users WHERE id = $id')
|
|
172
|
+
.get({ $id: grantedTo.userId })
|
|
173
|
+
if (!user) {
|
|
174
|
+
return c.json(
|
|
175
|
+
{
|
|
176
|
+
error: { type: 'not_found', message: 'User not found' },
|
|
177
|
+
},
|
|
178
|
+
404,
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
} else if (grantedTo.teamId) {
|
|
182
|
+
const team = db
|
|
183
|
+
.query('SELECT id FROM teams WHERE id = $id AND deleted_at IS NULL')
|
|
184
|
+
.get({ $id: grantedTo.teamId })
|
|
185
|
+
if (!team) {
|
|
186
|
+
return c.json(
|
|
187
|
+
{
|
|
188
|
+
error: { type: 'not_found', message: 'Team not found' },
|
|
189
|
+
},
|
|
190
|
+
404,
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Generate share token (same as id)
|
|
196
|
+
const shareId = `shr_${randomUUID().replace(/-/g, '')}`
|
|
197
|
+
const now = new Date().toISOString()
|
|
198
|
+
|
|
199
|
+
db.query(
|
|
200
|
+
`INSERT INTO session_shares
|
|
201
|
+
(id, session_id, granted_to_user, granted_to_team,
|
|
202
|
+
permission, expires_at, granted_by, granted_at)
|
|
203
|
+
VALUES ($id, $sid, $gtu, $gtt, $perm, $exp, $by, $now)`,
|
|
204
|
+
).run({
|
|
205
|
+
$id: shareId,
|
|
206
|
+
$sid: sessionId,
|
|
207
|
+
$gtu: grantedTo.userId || null,
|
|
208
|
+
$gtt: grantedTo.teamId || null,
|
|
209
|
+
$perm: permission,
|
|
210
|
+
$exp: expiresAt || null,
|
|
211
|
+
$by: userId,
|
|
212
|
+
$now: now,
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
return c.json(
|
|
216
|
+
{
|
|
217
|
+
id: shareId,
|
|
218
|
+
shareToken: shareId,
|
|
219
|
+
share_token: shareId,
|
|
220
|
+
permission,
|
|
221
|
+
expiresAt: expiresAt || null,
|
|
222
|
+
expires_at: expiresAt || null,
|
|
223
|
+
},
|
|
224
|
+
201,
|
|
225
|
+
)
|
|
226
|
+
},
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* GET /sessions/:id/shares — List all shares for a session.
|
|
231
|
+
*/
|
|
232
|
+
app.get(
|
|
233
|
+
'/sessions/:id/shares',
|
|
234
|
+
async (c, next) => {
|
|
235
|
+
const result = await sessionAuth(c, next)
|
|
236
|
+
if (result) return result
|
|
237
|
+
},
|
|
238
|
+
async c => {
|
|
239
|
+
const sessionId = c.req.param('id')
|
|
240
|
+
const ownership = checkSessionOwnership(c, sessionId)
|
|
241
|
+
if (ownership instanceof Response) return ownership
|
|
242
|
+
|
|
243
|
+
const db = getDb()
|
|
244
|
+
const shares = db
|
|
245
|
+
.query(
|
|
246
|
+
`SELECT id, session_id, granted_to_user, granted_to_team,
|
|
247
|
+
permission, expires_at, granted_by, granted_at
|
|
248
|
+
FROM session_shares
|
|
249
|
+
WHERE session_id = $sid`,
|
|
250
|
+
)
|
|
251
|
+
.all({ $sid: sessionId }) as ShareRow[]
|
|
252
|
+
|
|
253
|
+
return c.json(shares, 200)
|
|
254
|
+
},
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* DELETE /sessions/:id/shares/:shareId — Revoke a share.
|
|
259
|
+
*/
|
|
260
|
+
app.delete(
|
|
261
|
+
'/sessions/:id/shares/:shareId',
|
|
262
|
+
async (c, next) => {
|
|
263
|
+
const result = await sessionAuth(c, next)
|
|
264
|
+
if (result) return result
|
|
265
|
+
},
|
|
266
|
+
async c => {
|
|
267
|
+
const sessionId = c.req.param('id')
|
|
268
|
+
const shareId = c.req.param('shareId')
|
|
269
|
+
|
|
270
|
+
const ownership = checkSessionOwnership(c, sessionId)
|
|
271
|
+
if (ownership instanceof Response) return ownership
|
|
272
|
+
|
|
273
|
+
const db = getDb()
|
|
274
|
+
|
|
275
|
+
// Check share exists and belongs to this session
|
|
276
|
+
const share = db
|
|
277
|
+
.query(
|
|
278
|
+
`SELECT id FROM session_shares
|
|
279
|
+
WHERE id = $id AND session_id = $sid`,
|
|
280
|
+
)
|
|
281
|
+
.get({ $id: shareId, $sid: sessionId })
|
|
282
|
+
|
|
283
|
+
if (!share) {
|
|
284
|
+
return c.json(
|
|
285
|
+
{ error: { type: 'not_found', message: 'Share not found' } },
|
|
286
|
+
404,
|
|
287
|
+
)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Delete the share
|
|
291
|
+
db.query('DELETE FROM session_shares WHERE id = $id').run({
|
|
292
|
+
$id: shareId,
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
return c.json({ ok: true }, 200)
|
|
296
|
+
},
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* GET /sessions/s/:shareToken — Resolve a share token to session info.
|
|
301
|
+
*/
|
|
302
|
+
app.get(
|
|
303
|
+
'/sessions/s/:shareToken',
|
|
304
|
+
async (c, next) => {
|
|
305
|
+
const result = await sessionAuth(c, next)
|
|
306
|
+
if (result) return result
|
|
307
|
+
},
|
|
308
|
+
async c => {
|
|
309
|
+
const shareToken = c.req.param('shareToken')
|
|
310
|
+
|
|
311
|
+
// Validate format: must start with shr_
|
|
312
|
+
if (!shareToken || !shareToken.startsWith('shr_')) {
|
|
313
|
+
return c.json(
|
|
314
|
+
{
|
|
315
|
+
error: { type: 'not_found', message: 'Invalid share token' },
|
|
316
|
+
},
|
|
317
|
+
404,
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const db = getDb()
|
|
322
|
+
|
|
323
|
+
// Look up the share
|
|
324
|
+
const share = db
|
|
325
|
+
.query(
|
|
326
|
+
`SELECT id, session_id, expires_at
|
|
327
|
+
FROM session_shares WHERE id = $id`,
|
|
328
|
+
)
|
|
329
|
+
.get({ $id: shareToken }) as {
|
|
330
|
+
id: string
|
|
331
|
+
session_id: string
|
|
332
|
+
expires_at: string | null
|
|
333
|
+
} | null
|
|
334
|
+
|
|
335
|
+
if (!share) {
|
|
336
|
+
return c.json(
|
|
337
|
+
{ error: { type: 'not_found', message: 'Share not found' } },
|
|
338
|
+
404,
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Check expiry
|
|
343
|
+
if (share.expires_at && new Date(share.expires_at).getTime() < Date.now()) {
|
|
344
|
+
return c.json(
|
|
345
|
+
{ error: { type: 'unauthorized', message: 'Share expired' } },
|
|
346
|
+
401,
|
|
347
|
+
)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Check session still exists — return only public-safe fields
|
|
351
|
+
const session = db
|
|
352
|
+
.query(
|
|
353
|
+
`SELECT id, title, status, source, created_at, updated_at
|
|
354
|
+
FROM sessions WHERE id = $id`,
|
|
355
|
+
)
|
|
356
|
+
.get({ $id: share.session_id }) as Record<string, unknown> | null
|
|
357
|
+
|
|
358
|
+
if (!session) {
|
|
359
|
+
return c.json(
|
|
360
|
+
{
|
|
361
|
+
error: { type: 'not_found', message: 'Session not found' },
|
|
362
|
+
},
|
|
363
|
+
404,
|
|
364
|
+
)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return c.json(session, 200)
|
|
368
|
+
},
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
export default app
|