From e83abb84c6d8dedb71295a2c73a83bc208b07c96 Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Tue, 17 Jun 2025 15:04:27 +0500 Subject: [PATCH] Fix calendar sync (#9271) Signed-off-by: Denis Bykhov --- common/config/rush/pnpm-lock.yaml | 190 ++---------------- services/calendar/pod-calendar/package.json | 6 +- services/calendar/pod-calendar/src/auth.ts | 8 +- .../calendar/pod-calendar/src/calendar.ts | 21 +- services/calendar/pod-calendar/src/config.ts | 7 - .../calendar/pod-calendar/src/kvsUtils.ts | 4 + .../calendar/pod-calendar/src/pushHandler.ts | 20 +- services/calendar/pod-calendar/src/sync.ts | 5 +- services/calendar/pod-calendar/src/utils.ts | 34 +++- .../pod-calendar/src/workspaceClient.ts | 9 +- 10 files changed, 93 insertions(+), 211 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index ca58da1f8c..1f2652fec5 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -34,27 +34,6 @@ importers: '@faker-js/faker': specifier: ^8.4.1 version: 8.4.1 - '@hcengineering/account-client': - specifier: ^0.7.88 - version: 0.7.88 - '@hcengineering/card': - specifier: ^0.7.88 - version: 0.7.88 - '@hcengineering/core': - specifier: ^0.7.88 - version: 0.7.88 - '@hcengineering/platform-rig': - specifier: ^0.6.490 - version: 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) - '@hcengineering/server-token': - specifier: ^0.7.88 - version: 0.7.88 - '@hcengineering/text-core': - specifier: ^0.7.88 - version: 0.7.88 - '@hcengineering/text-markdown': - specifier: ^0.7.88 - version: 0.7.88 '@hocuspocus/provider': specifier: ^2.15.2 version: 2.15.2(bufferutil@4.0.8)(utf-8-validate@6.0.4)(y-protocols@1.0.6(yjs@13.6.23))(yjs@13.6.23) @@ -804,7 +783,7 @@ importers: version: file:projects/pod-backup.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9)) '@rush-temp/pod-calendar': specifier: file:./projects/pod-calendar.tgz - version: file:projects/pod-calendar.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(bufferutil@4.0.8)(encoding@0.1.13)(gcp-metadata@5.3.0(encoding@0.1.13))(snappy@7.2.2)(socks@2.8.3)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))(utf-8-validate@6.0.4) + version: file:projects/pod-calendar.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.4) '@rush-temp/pod-calendar-mailer': specifier: file:./projects/pod-calendar-mailer.tgz version: file:projects/pod-calendar-mailer.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9)) @@ -3018,46 +2997,6 @@ packages: '@gar/promisify@1.1.3': resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - '@hcengineering/account-client@0.7.88': - resolution: {integrity: sha512-CZWOJT/JZAUy+FuYuX0QcJQYDnVDNAB0QHU4RxKc7gSlYAYleibL7qJC0vRGL4rNkvDVZfJMKDPUQW4AauGqtA==, tarball: https://npm.pkg.github.com/download/@hcengineering/account-client/0.7.88/57caa95e62fecc4ca22a32c76bcdc900b0384f04} - - '@hcengineering/analytics@0.7.88': - resolution: {integrity: sha512-3jT3h2Y85awrgG0JWZSrpWOXaX1J3dpq8zouo3QMw8OVO1RgHCwPEqrBPOALnB+gc9cZL02p6Aq4J+fnTZ2fww==, tarball: https://npm.pkg.github.com/download/@hcengineering/analytics/0.7.88/385c2ae512bbcae39189d63e53ea527aa21a662f} - - '@hcengineering/card@0.7.88': - resolution: {integrity: sha512-3JDgocHFSGmQuKsrtQ5CTTm4rpd/PHahIx6oNX8sshDGpS2hnvNtrHNkJf39seIKiq0NNKmJ//Etl4I21h4c6w==, tarball: https://npm.pkg.github.com/download/@hcengineering/card/0.7.88/e39b9e182325945494f162f2dd6f16ef9bea0f3e} - - '@hcengineering/core@0.7.88': - resolution: {integrity: sha512-c3GRTGAZYARu1kMt4TqkugmnuprYesZ4XZUeakReRtZdYei9tAF+i9xPpDKb4J3hvMC3u82LlEiV8iK26iXpTA==, tarball: https://npm.pkg.github.com/download/@hcengineering/core/0.7.88/ca01c3ccd43c85ea44b189d995b0693c5465956c} - - '@hcengineering/platform-rig@0.6.490': - resolution: {integrity: sha512-zBcZ/OXbgZ4U3IYWLHk0WcUsHb2IstdwthUDY9n2cWIsJR6h3TeksK9FZ/rsEftiVubvJT1YspsbzVMARj0Ygw==, tarball: https://npm.pkg.github.com/download/@hcengineering/platform-rig/0.6.490/d90aa2aa64b0f90ec124295eb7e97421c388d5d0} - hasBin: true - peerDependencies: - '@typescript-eslint/parser': ^6.11.0 - eslint: ^8.54.0 - - '@hcengineering/platform@0.7.88': - resolution: {integrity: sha512-iFAwYQZjGox1NqEgUh8hiT1mRHdSJqYmYux0lkeIFyt8Nn/BAZOVXe0br0Dx7wXiueFPWhSZSeWVhxvBb78zoA==, tarball: https://npm.pkg.github.com/download/@hcengineering/platform/0.7.88/b3fbe09d6b849f7eb3641792682bf133103037f0} - - '@hcengineering/server-token@0.7.88': - resolution: {integrity: sha512-UQfW0E+v+PTwR7ICR+kSTQqAokpiV008ukqsxRSQJkCM4vmNYciUgd/7Y/ifDMFhKDvNyODb+wgAQs3QxkSbkA==, tarball: https://npm.pkg.github.com/download/@hcengineering/server-token/0.7.88/11b3a8247869a50037fcbb13572e16545116ff93} - - '@hcengineering/text-core@0.7.88': - resolution: {integrity: sha512-mFri9SMzD99uR3/H0gZ4KEekYf3lEmJ2bqEQrjIVmi9z7+CzDTxmKnXeHKzcFpvQaLt5kmbPIoXM4MyxpK7ZXA==, tarball: https://npm.pkg.github.com/download/@hcengineering/text-core/0.7.88/7e53b0da9622709b2d1071049ead3843e0c45764} - - '@hcengineering/text-html@0.7.88': - resolution: {integrity: sha512-Wj0gYv0JEUIKpuaDFmRn7/60/SXGg0CZVmzbux0XlUzayly+C4Pkfj5U3G/ZEUyDBtAtyeBdWtnkzgQgN6qOuQ==, tarball: https://npm.pkg.github.com/download/@hcengineering/text-html/0.7.88/e48beced20921d9e1e9c84548c3caf5c9770bac1} - - '@hcengineering/text-markdown@0.7.88': - resolution: {integrity: sha512-066WeD/6EI5VmFQZ/Cv6eEOFXBd+fA+YPxX5fb0ytlZr5bLpQs6/AifpyqJoZ5gqQzfAf/HmtDVxDl5QU95FGw==, tarball: https://npm.pkg.github.com/download/@hcengineering/text-markdown/0.7.88/86938b13b0bdd81941a22378e3b2e92998f71d80} - - '@hcengineering/theme@0.7.88': - resolution: {integrity: sha512-PCt9bFuGPYOf1kQgjzxPSZgGXU4G14Z1XZJfgGu71u/zHxG6fu6nls35aSrEjy2Ks6oR+OCqqvpDh6RTf6utrg==, tarball: https://npm.pkg.github.com/download/@hcengineering/theme/0.7.88/d939d1e2a9047def2795dc5124653e49ca522cfc} - - '@hcengineering/ui@0.7.88': - resolution: {integrity: sha512-mzHXcX3aBC/OXUaV9F2hnB6+irwMfEYM5J1CnfqiHqgv3Hza20BZR6BrYe/nQCLb44DuHkXojbwL94AKK3QW6w==, tarball: https://npm.pkg.github.com/download/@hcengineering/ui/0.7.88/fce3392a59f706c248ba4b17714163e5725d5f01} - '@hocuspocus/common@2.15.2': resolution: {integrity: sha512-wU1wxXNnQQMXyeL3mdSDYiQsm/r/QyJVjjQhF7sUBrLnjdsN7bA1cvfcSvJBr1ymrMSeYRmUL3UlQmEHEOaP7w==} @@ -4080,15 +4019,15 @@ packages: version: 0.0.0 '@rush-temp/communication-client-query@file:projects/communication-client-query.tgz': - resolution: {integrity: sha512-4pqwjw8vCSnBMYiLQaakZppeYHjIGUmxxyTxC+VuDMUrCzm9HxKQAPGHNhpgzY086A1qW5bDFLmDYXC+WM4pAw==, tarball: file:projects/communication-client-query.tgz} + resolution: {integrity: sha512-JP02UI9BNphEKkBC9UD+sL/PZVZ6Qt3Hoyi34/1kHmZR473zNj64iJnUWLnNN2zCsICXn+FCeK/h5CAqc1JzUQ==, tarball: file:projects/communication-client-query.tgz} version: 0.0.0 '@rush-temp/communication-cockroach@file:projects/communication-cockroach.tgz': - resolution: {integrity: sha512-E31i06YbMBCQPM4CMX46eKOrlNjEAjjES8vi0xn+qKgo1YyGkYFj2nvp6d/D4s7eim2lezkpE3xQrAAGrSDYVg==, tarball: file:projects/communication-cockroach.tgz} + resolution: {integrity: sha512-WldK8XFrmOw7CrwOkF33GG+mKzGpn0OlPbeqZn8hKFRmamZqE/+IORfSd7O3GEXvei830wpXFtB9vD5KDRPNTg==, tarball: file:projects/communication-cockroach.tgz} version: 0.0.0 '@rush-temp/communication-query@file:projects/communication-query.tgz': - resolution: {integrity: sha512-WscFsTvRKI9bvVBZU+QKwrZfWGQPJwMHUNL94q/vdq0DEigs5d4rZw8RTLfy2vHXPP7ZwpOztEFfYBTcdfKKgQ==, tarball: file:projects/communication-query.tgz} + resolution: {integrity: sha512-kDeFUmrcUthxCM/WS7CRyZpOsjAPmBbIJ7O8nRJ+++2LzbaTzmCiAlVUzpaV3rOH0xOBbKIYrX9jDKqOxI2CQA==, tarball: file:projects/communication-query.tgz} version: 0.0.0 '@rush-temp/communication-resources@file:projects/communication-resources.tgz': @@ -4096,27 +4035,27 @@ packages: version: 0.0.0 '@rush-temp/communication-rest-client@file:projects/communication-rest-client.tgz': - resolution: {integrity: sha512-1qay6ifhfDK+Fe0f/gojdpue2/VefkgxvBI9AXBDh94pfhsGG7nR42WlCqlH16kXzyOfJdT9rQO8twCocAc8pw==, tarball: file:projects/communication-rest-client.tgz} + resolution: {integrity: sha512-zoI9BXo2K1Q0MR+oV4kQX/G7nk9U48QU2t5DqLLTDrVIvnwcpfBJjJXsVZnoFCMCLTfFpoLyfW7S7UOAB+7PNg==, tarball: file:projects/communication-rest-client.tgz} version: 0.0.0 '@rush-temp/communication-sdk-types@file:projects/communication-sdk-types.tgz': - resolution: {integrity: sha512-6hZYMRhj5QuyLx1m81y1fDykH36PpRsES0pSx41UyFDVCmlqhFanA1ECb/PHrQdkplQdkL8eTWxac4ZDycpylA==, tarball: file:projects/communication-sdk-types.tgz} + resolution: {integrity: sha512-MfVuAH3fClVRrgiBMbB89IHg2gg/lqb+opQgKhBabgg+BwlEH4Y/lsCvkLnLrOvYfOgIqZlFTPCyMjqQl26QpA==, tarball: file:projects/communication-sdk-types.tgz} version: 0.0.0 '@rush-temp/communication-server@file:projects/communication-server.tgz': - resolution: {integrity: sha512-Q65yyRV1re6jrXywZo4NU4IqzaYhnJklFFITLiEf6grjNYzQqkjrAj8pCVnZMt/F0Wo9wgiZe2blK63YcfCLdQ==, tarball: file:projects/communication-server.tgz} + resolution: {integrity: sha512-VKBMp1FdRlipM9nce/+utdZ/Apl0nIMzrBqQbp+5eKqSAqBVKOthMVBU3v88LMeFJJFAvk8LOzJ/wrZIXZB6BQ==, tarball: file:projects/communication-server.tgz} version: 0.0.0 '@rush-temp/communication-shared@file:projects/communication-shared.tgz': - resolution: {integrity: sha512-nXFiBbVILxCmVw01Kpx/cJQB2daeQ3GOa4PzZm3wgzy6E4548qT9ZbwpPuj8p92usOTe3svfWSlAh+9PaZyT1g==, tarball: file:projects/communication-shared.tgz} + resolution: {integrity: sha512-hucGiPhKdBLpEczWSQORfT3kQg0zz7zPxyYdXELIWu7YNSWCfjaELwwTl5mpbTXpRc97MqWInDtIMIkUU/Pp2w==, tarball: file:projects/communication-shared.tgz} version: 0.0.0 '@rush-temp/communication-types@file:projects/communication-types.tgz': - resolution: {integrity: sha512-kMbaKd24NYzYURoQG1p5CJT7vfS+27gI6bb4h7ziw1OnKVEaUJ0tZ26TFPqqf4A8XFqlkS7avEBXEvF9bu0kmw==, tarball: file:projects/communication-types.tgz} + resolution: {integrity: sha512-aEnTx//MRryreOfPxh/DuuzzH2edEBl1DliWJ7znv749baZlQsgcqKgF+Zctcv2KkdxOVLV67WZUW/EW2qeZug==, tarball: file:projects/communication-types.tgz} version: 0.0.0 '@rush-temp/communication-yaml@file:projects/communication-yaml.tgz': - resolution: {integrity: sha512-+5aqoZwp7g2Pn0ctnJ/Kofg7g9YaIW5pl6AOhzmkb2i1/wXMSxTc64bja4zlc1BoLM2SvSgzpbTZCqWeE60lTw==, tarball: file:projects/communication-yaml.tgz} + resolution: {integrity: sha512-4tzLbDx3LLFOPir5KHUkw2t9UJz1OTtMdg8jqhf1OmnUXzNsJMatXahxfz7aPcS7VkGzdqjjmx7l4Ndn6w+DGg==, tarball: file:projects/communication-yaml.tgz} version: 0.0.0 '@rush-temp/communication@file:projects/communication.tgz': @@ -4852,7 +4791,7 @@ packages: version: 0.0.0 '@rush-temp/pod-calendar@file:projects/pod-calendar.tgz': - resolution: {integrity: sha512-cvodjIOioz1hYCAAUDEv8Qf8GmiU1jcprLTM0eHlLFvmsGy2GhH4G4U2GHQKO3tKOb4IAbCzut4Xs2fJAjSrWw==, tarball: file:projects/pod-calendar.tgz} + resolution: {integrity: sha512-S3ygrMi6bQUc9U7sfujx5iv8t7gHC+Kl/u/NjRtcmEPDdF47zdmr8mr0THnZNfpgpabFcnBaPcTm9mvXXe/Ftg==, tarball: file:projects/pod-calendar.tgz} version: 0.0.0 '@rush-temp/pod-collaborator@file:projects/pod-collaborator.tgz': @@ -14924,82 +14863,6 @@ snapshots: '@gar/promisify@1.1.3': {} - '@hcengineering/account-client@0.7.88': - dependencies: - '@hcengineering/core': 0.7.88 - '@hcengineering/platform': 0.7.88 - - '@hcengineering/analytics@0.7.88': - dependencies: - '@hcengineering/platform': 0.7.88 - - '@hcengineering/card@0.7.88': - dependencies: - '@hcengineering/core': 0.7.88 - '@hcengineering/platform': 0.7.88 - '@hcengineering/ui': 0.7.88 - - '@hcengineering/core@0.7.88': - dependencies: - '@hcengineering/analytics': 0.7.88 - '@hcengineering/platform': 0.7.88 - fast-equals: 5.2.2 - - '@hcengineering/platform-rig@0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)': - dependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) - eslint: 8.56.0 - typescript: 5.8.3 - - '@hcengineering/platform@0.7.88': - dependencies: - intl-messageformat: 10.7.14 - - '@hcengineering/server-token@0.7.88': - dependencies: - '@hcengineering/core': 0.7.88 - '@hcengineering/platform': 0.7.88 - jwt-simple: 0.5.6 - - '@hcengineering/text-core@0.7.88': - dependencies: - '@hcengineering/core': 0.7.88 - fast-equals: 5.2.2 - - '@hcengineering/text-html@0.7.88': - dependencies: - '@hcengineering/text-core': 0.7.88 - htmlparser2: 9.1.0 - - '@hcengineering/text-markdown@0.7.88': - dependencies: - '@hcengineering/text-core': 0.7.88 - '@hcengineering/text-html': 0.7.88 - fast-equals: 5.2.2 - markdown-it: 14.0.0 - - '@hcengineering/theme@0.7.88': - dependencies: - '@hcengineering/analytics': 0.7.88 - '@hcengineering/platform': 0.7.88 - svelte: 4.2.19 - - '@hcengineering/ui@0.7.88': - dependencies: - '@hcengineering/analytics': 0.7.88 - '@hcengineering/core': 0.7.88 - '@hcengineering/platform': 0.7.88 - '@hcengineering/theme': 0.7.88 - autolinker: 4.0.0 - date-fns: 2.30.0 - date-fns-tz: 2.0.0(date-fns@2.30.0) - dompurify: 3.2.3 - emojibase: 16.0.0 - fast-equals: 5.2.2 - hls.js: 1.5.20 - plyr: 3.7.8 - svelte: 4.2.19 - '@hocuspocus/common@2.15.2': dependencies: lib0: 0.2.99 @@ -17597,7 +17460,6 @@ snapshots: '@rush-temp/communication-client-query@file:projects/communication-client-query.tgz(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))': dependencies: - '@hcengineering/platform-rig': 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) esbuild: 0.24.2 @@ -17620,7 +17482,6 @@ snapshots: '@rush-temp/communication-cockroach@file:projects/communication-cockroach.tgz(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))': dependencies: - '@hcengineering/platform-rig': 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) '@types/uuid': 8.3.4 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) @@ -17645,7 +17506,6 @@ snapshots: '@rush-temp/communication-query@file:projects/communication-query.tgz(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))': dependencies: - '@hcengineering/platform-rig': 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) '@types/uuid': 8.3.4 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) @@ -17714,8 +17574,6 @@ snapshots: '@rush-temp/communication-rest-client@file:projects/communication-rest-client.tgz(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))': dependencies: - '@hcengineering/core': 0.7.88 - '@hcengineering/platform-rig': 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) '@types/snappyjs': 0.7.1 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) @@ -17739,8 +17597,6 @@ snapshots: '@rush-temp/communication-sdk-types@file:projects/communication-sdk-types.tgz(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))': dependencies: - '@hcengineering/core': 0.7.88 - '@hcengineering/platform-rig': 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) esbuild: 0.24.2 @@ -17762,12 +17618,6 @@ snapshots: '@rush-temp/communication-server@file:projects/communication-server.tgz(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))': dependencies: - '@hcengineering/account-client': 0.7.88 - '@hcengineering/core': 0.7.88 - '@hcengineering/platform-rig': 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) - '@hcengineering/server-token': 0.7.88 - '@hcengineering/text-core': 0.7.88 - '@hcengineering/text-markdown': 0.7.88 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) esbuild: 0.24.2 @@ -17790,7 +17640,6 @@ snapshots: '@rush-temp/communication-shared@file:projects/communication-shared.tgz(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))': dependencies: - '@hcengineering/platform-rig': 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) esbuild: 0.24.2 @@ -17812,9 +17661,6 @@ snapshots: '@rush-temp/communication-types@file:projects/communication-types.tgz(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))': dependencies: - '@hcengineering/card': 0.7.88 - '@hcengineering/core': 0.7.88 - '@hcengineering/platform-rig': 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) esbuild: 0.24.2 @@ -17836,7 +17682,6 @@ snapshots: '@rush-temp/communication-yaml@file:projects/communication-yaml.tgz(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))': dependencies: - '@hcengineering/platform-rig': 0.6.490(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0) '@types/js-yaml': 4.0.9 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) @@ -22221,7 +22066,7 @@ snapshots: - node-notifier - supports-color - '@rush-temp/pod-calendar@file:projects/pod-calendar.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(bufferutil@4.0.8)(encoding@0.1.13)(gcp-metadata@5.3.0(encoding@0.1.13))(snappy@7.2.2)(socks@2.8.3)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))(utf-8-validate@6.0.4)': + '@rush-temp/pod-calendar@file:projects/pod-calendar.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.4)': dependencies: '@tsconfig/node16': 1.0.4 '@types/cors': 2.8.17 @@ -22247,31 +22092,22 @@ snapshots: googleapis: 122.0.0(encoding@0.1.13) jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3)) jwt-simple: 0.5.6 - mongodb: 6.16.0(gcp-metadata@5.3.0(encoding@0.1.13))(snappy@7.2.2)(socks@2.8.3) prettier: 3.2.5 ts-jest: 29.1.2(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3)))(typescript@5.8.3) - ts-node-dev: 2.0.0(@types/node@22.15.29)(typescript@5.8.3) + ts-node: 10.9.2(@types/node@22.15.29)(typescript@5.8.3) typescript: 5.8.3 ws: 8.18.2(bufferutil@4.0.8)(utf-8-validate@6.0.4) transitivePeerDependencies: - - '@aws-sdk/credential-providers' - '@babel/core' - '@jest/types' - - '@mongodb-js/zstd' - '@swc/core' - '@swc/wasm' - babel-jest - babel-plugin-macros - bufferutil - encoding - - gcp-metadata - - kerberos - - mongodb-client-encryption - node-notifier - - snappy - - socks - supports-color - - ts-node - utf-8-validate '@rush-temp/pod-collaborator@file:projects/pod-collaborator.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))': diff --git a/services/calendar/pod-calendar/package.json b/services/calendar/pod-calendar/package.json index 3d20c29939..20521658aa 100644 --- a/services/calendar/pod-calendar/package.json +++ b/services/calendar/pod-calendar/package.json @@ -22,7 +22,7 @@ "docker:tbuild": "docker build -t hardcoreeng/calendar . --platform=linux/amd64 && ../../../common/scripts/docker_tag_push.sh hardcoreeng/calendar", "docker:staging": "../../../common/scripts/docker_tag.sh hardcoreeng/calendar staging", "docker:push": "../../../common/scripts/docker_tag.sh hardcoreeng/calendar", - "run-local": "cross-env ts-node src/index.ts", + "run-local": "ts-node src/index.ts", "format": "format src", "_phase:build": "compile transpile src", "_phase:test": "jest --passWithNoTests --silent", @@ -49,7 +49,7 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.1.1", "prettier": "^3.1.0", - "ts-node-dev": "^2.0.0", + "ts-node": "^10.8.0", "typescript": "^5.8.3" }, "dependencies": { @@ -61,7 +61,6 @@ "@hcengineering/contact": "^0.6.24", "@hcengineering/core": "^0.6.32", "@hcengineering/platform": "^0.6.11", - "@hcengineering/mongo": "^0.6.1", "@hcengineering/setting": "^0.6.17", "@hcengineering/text": "^0.6.5", "@hcengineering/server-client": "^0.6.0", @@ -77,7 +76,6 @@ "googleapis": "^122.0.0", "google-auth-library": "^8.0.2", "jwt-simple": "^0.5.6", - "mongodb": "^6.16.0", "ws": "^8.18.2" } } diff --git a/services/calendar/pod-calendar/src/auth.ts b/services/calendar/pod-calendar/src/auth.ts index 05d621a4ea..f1ead553af 100644 --- a/services/calendar/pod-calendar/src/auth.ts +++ b/services/calendar/pod-calendar/src/auth.ts @@ -25,7 +25,7 @@ import { getClient } from './client' import { addUserByEmail, removeUserByEmail } from './kvsUtils' import { IncomingSyncManager, lock } from './sync' import { CALENDAR_INTEGRATION, GoogleEmail, SCOPES, State, Token, User } from './types' -import { getGoogleClient, getWorkspaceToken } from './utils' +import { getGoogleClient, getWorkspaceToken, removeIntegrationSecret } from './utils' import { WatchController } from './watch' interface AuthResult { @@ -124,11 +124,7 @@ export class AuthController { const token = JSON.parse(secret.secret) const watchController = WatchController.get(this.accountClient) await watchController.unsubscribe(token) - await this.accountClient.deleteIntegrationSecret(data) - const left = await this.accountClient.listIntegrationsSecrets(data) - if (left.length === 0) { - await this.accountClient.deleteIntegration(data) - } + await removeIntegrationSecret(this.ctx, this.accountClient, data) } private async process (code: string): Promise { diff --git a/services/calendar/pod-calendar/src/calendar.ts b/services/calendar/pod-calendar/src/calendar.ts index a5e659a171..4dcdc56a9d 100644 --- a/services/calendar/pod-calendar/src/calendar.ts +++ b/services/calendar/pod-calendar/src/calendar.ts @@ -22,9 +22,10 @@ import { OAuth2Client } from 'google-auth-library' import { calendar_v3 } from 'googleapis' import { getRateLimitter, RateLimiter } from './rateLimiter' import { IncomingSyncManager } from './sync' -import type { Token } from './types' -import { encodeReccuring, getGoogleClient } from './utils' +import { CALENDAR_INTEGRATION, type Token } from './types' +import { encodeReccuring, getGoogleClient, removeIntegrationSecret, setCredentials } from './utils' import type { WorkspaceClient } from './workspaceClient' +import { removeUserByEmail } from './kvsUtils' export class CalendarClient { private readonly calendar: calendar_v3.Calendar @@ -52,9 +53,19 @@ export class CalendarClient { user: Token, client: Client, workspace: WorkspaceClient - ): Promise { + ): Promise { const calendarClient = new CalendarClient(ctx, accountClient, user, client, workspace) - calendarClient.oAuth2Client.setCredentials(user) + const authSucces = await setCredentials(calendarClient.oAuth2Client, user) + if (!authSucces) { + await removeUserByEmail(user, user.email) + await removeIntegrationSecret(ctx, calendarClient.accountClient, { + socialId: user.userId, + kind: CALENDAR_INTEGRATION, + workspaceUuid: user.workspace, + key: user.email + }) + return + } return calendarClient } @@ -215,7 +226,7 @@ export class CalendarClient { try { await this.rateLimiter.take(1) const current = await this.calendar.events.get({ calendarId, eventId: event.eventId }) - if (current !== undefined) { + if (current !== undefined && current.data.status !== 'cancelled') { const ev = this.applyUpdate(current.data, event) await this.rateLimiter.take(1) await this.calendar.events.update({ diff --git a/services/calendar/pod-calendar/src/config.ts b/services/calendar/pod-calendar/src/config.ts index 6335023a7f..8b0134c10e 100644 --- a/services/calendar/pod-calendar/src/config.ts +++ b/services/calendar/pod-calendar/src/config.ts @@ -16,8 +16,6 @@ interface Config { Port: number - MongoURI: string - MongoDB: string AccountsURL: string ServiceID: string Secret: string @@ -30,9 +28,6 @@ interface Config { const envMap: { [key in keyof Config]: string } = { Port: 'PORT', - MongoURI: 'MONGO_URI', - MongoDB: 'MONGO_DB', - AccountsURL: 'ACCOUNTS_URL', ServiceID: 'SERVICE_ID', Secret: 'SECRET', @@ -47,8 +42,6 @@ const parseNumber = (str: string | undefined): number | undefined => (str !== un const config: Config = (() => { const params: Partial = { Port: parseNumber(process.env[envMap.Port]) ?? 8095, - MongoDB: process.env[envMap.MongoDB] ?? 'calendar-service', - MongoURI: process.env[envMap.MongoURI], AccountsURL: process.env[envMap.AccountsURL], ServiceID: process.env[envMap.ServiceID] ?? 'calendar-service', Secret: process.env[envMap.Secret], diff --git a/services/calendar/pod-calendar/src/kvsUtils.ts b/services/calendar/pod-calendar/src/kvsUtils.ts index b0b34157ba..1cd0e476b8 100644 --- a/services/calendar/pod-calendar/src/kvsUtils.ts +++ b/services/calendar/pod-calendar/src/kvsUtils.ts @@ -68,6 +68,10 @@ export async function addUserByEmail (user: Token, email: GoogleEmail): Promise< const client = getKvsClient() const key = `${CALENDAR_INTEGRATION}:users:${email}` const curr = (await client.getValue(key)) ?? [] + const exists = curr.find((p) => p.userId === user.userId && p.workspace === user.workspace) + if (exists !== undefined) { + return + } curr.push(user) await client.setValue(key, curr) } diff --git a/services/calendar/pod-calendar/src/pushHandler.ts b/services/calendar/pod-calendar/src/pushHandler.ts index 2b28c4bd99..2299f26e4c 100644 --- a/services/calendar/pod-calendar/src/pushHandler.ts +++ b/services/calendar/pod-calendar/src/pushHandler.ts @@ -16,10 +16,10 @@ import { AccountClient } from '@hcengineering/account-client' import core, { isActiveMode, MeasureContext, TxOperations } from '@hcengineering/core' import { getClient } from './client' -import { getUserByEmail } from './kvsUtils' +import { getUserByEmail, removeUserByEmail } from './kvsUtils' import { IncomingSyncManager } from './sync' -import { GoogleEmail, Token } from './types' -import { getGoogleClient, getWorkspaceToken } from './utils' +import { CALENDAR_INTEGRATION, GoogleEmail, Token } from './types' +import { getGoogleClient, getWorkspaceToken, removeIntegrationSecret, setCredentials } from './utils' export class PushHandler { constructor ( @@ -35,8 +35,18 @@ export class PushHandler { const client = await getClient(getWorkspaceToken(token.workspace)) const txOp = new TxOperations(client, core.account.System) const res = getGoogleClient() - res.auth.setCredentials(token) - await IncomingSyncManager.push(this.ctx, this.accountClient, txOp, token, res.google, calendarId) + const authSuccess = await setCredentials(res.auth, token) + if (!authSuccess) { + await removeUserByEmail(token, token.email) + await removeIntegrationSecret(this.ctx, this.accountClient, { + kind: CALENDAR_INTEGRATION, + workspaceUuid: token.workspace, + socialId: token.userId, + key: token.email + }) + } else { + await IncomingSyncManager.push(this.ctx, this.accountClient, txOp, token, res.google, calendarId) + } await txOp.close() }, { workspace: token.workspace, user: token.userId } diff --git a/services/calendar/pod-calendar/src/sync.ts b/services/calendar/pod-calendar/src/sync.ts index 60d6f4f15f..b3f176fea5 100644 --- a/services/calendar/pod-calendar/src/sync.ts +++ b/services/calendar/pod-calendar/src/sync.ts @@ -236,8 +236,7 @@ export class IncomingSyncManager { private getEventCalendar (calendarId: string, event: calendar_v3.Schema$Event): ExternalCalendar | undefined { const _calendar = this.calendars.find((p) => p.externalId === event.organizer?.email) ?? - this.calendars.find((p) => p.externalId === calendarId) ?? - this.calendars[0] + this.calendars.find((p) => p.externalId === calendarId) return _calendar } @@ -602,6 +601,8 @@ export class IncomingSyncManager { if (err?.response?.status === 410) { syncToken = undefined pageToken = undefined + } else { + throw err } } } diff --git a/services/calendar/pod-calendar/src/utils.ts b/services/calendar/pod-calendar/src/utils.ts index 80bd624cf0..1836733ae4 100644 --- a/services/calendar/pod-calendar/src/utils.ts +++ b/services/calendar/pod-calendar/src/utils.ts @@ -14,12 +14,13 @@ // import { RecurringRule } from '@hcengineering/calendar' -import { systemAccountUuid, Timestamp, WorkspaceUuid } from '@hcengineering/core' +import { MeasureContext, systemAccountUuid, Timestamp, WorkspaceUuid } from '@hcengineering/core' import { generateToken } from '@hcengineering/server-token' -import { OAuth2Client } from 'google-auth-library' +import { Credentials, OAuth2Client } from 'google-auth-library' import { calendar_v3, google } from 'googleapis' import config from './config' import { CALENDAR_INTEGRATION, ReccuringData, State, type Token, type User } from './types' +import { AccountClient, IntegrationSecretKey } from '@hcengineering/account-client' export class DeferredPromise { public readonly promise: Promise @@ -283,3 +284,32 @@ export function getGoogleClient (): { google: googleClient } } + +export async function setCredentials (oAuth2Client: OAuth2Client, credentials: Credentials): Promise { + try { + oAuth2Client.setCredentials(credentials) + await google.oauth2({ version: 'v2', auth: oAuth2Client }).userinfo.get() + return true + } catch (err: any) { + if (err?.response?.data?.error === 'invalid_grant') { + return false + } + throw err + } +} + +export async function removeIntegrationSecret ( + ctx: MeasureContext, + accountClient: AccountClient, + data: IntegrationSecretKey +): Promise { + try { + await accountClient.deleteIntegrationSecret(data) + const left = await accountClient.listIntegrationsSecrets(data) + if (left.length === 0) { + await accountClient.deleteIntegration(data) + } + } catch (err: any) { + ctx.error('Failed to remove integration secret', { message: err.message, ...data }) + } +} diff --git a/services/calendar/pod-calendar/src/workspaceClient.ts b/services/calendar/pod-calendar/src/workspaceClient.ts index cf611b4bcb..0a44547c45 100644 --- a/services/calendar/pod-calendar/src/workspaceClient.ts +++ b/services/calendar/pod-calendar/src/workspaceClient.ts @@ -117,12 +117,15 @@ export class WorkspaceClient { await limiter.waitProcessing() } - private async createCalendarClient (user: Token): Promise { + private async createCalendarClient (user: Token): Promise { const current = this.clients.get(user.email) if (current !== undefined) { return current } const newClient = await CalendarClient.create(this.ctx, this.accountClient, user, this.client, this) + if (newClient === undefined) { + return + } this.clients.set(user.email, newClient) return newClient } @@ -190,11 +193,11 @@ export class WorkspaceClient { await client.syncMyEvent(newEvent) await this.updateSyncTime() } - this.ctx.info('all outcoming messages synced', this.workspace) + this.ctx.info('all outcoming messages synced', { workspace: this.workspace }) } private async getCalendarClientByCalendar (id: Ref): Promise { - const calendar = this.calendarsByExternal.get(id) + const calendar = this.calendarsById.get(id) if (calendar === undefined) { console.warn("couldn't find calendar by id", id) return