Fix email

This commit is contained in:
Arthur Belleville 2025-10-05 10:45:39 +02:00
parent 8147f61c5c
commit 4476a76180
No known key found for this signature in database
12 changed files with 471 additions and 65 deletions

View file

@ -4,8 +4,6 @@ SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhY
STREAM_CHAT_API_KEY=t5vvvddteapa
STREAM_CHAT_API_SECRET=zrr32sqenw3atpv9rnz2nhhyyncf7bunr7fmfqy9r7e69fcw978dhzevmhpxa2jj
EMAIL_USER="baptiste@xtablo.com"
EMAIL_KEY="jayf pzpj nrsv vtim"
XTABLO_URL="https://app-staging.xtablo.com"
CORS_ORIGIN="http://localhost:5173"
@ -14,4 +12,9 @@ R2_ACCOUNT_ID="9715fa14c5e5d1612301572cf1c6bbee"
R2_ACCESS_KEY_ID="caeb987bbcd601708a93c6aa562064ef"
R2_SECRET_ACCESS_KEY="42e455b25804687f7cff3d15be23c1f0f47ca742d7a41b6fa1a05a91041e0215"
SYNC_CALS_SECRET="hello"
SYNC_CALS_SECRET="hello"
EMAIL_USER="baptiste@xtablo.com"
EMAIL_CLIENT_ID="904332563417-e2n7pchtgnkrkp360baaebfeig55maig.apps.googleusercontent.com"
EMAIL_CLIENT_SECRET="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"
EMAIL_REFRESH_TOKEN="1//04dRsWFVjr0mqCgYIARAAGAQSNwF-L9IrN3JicCv2ib4F6AQlactB4CE6Q4ST_tEVVdmmECly_-05INeTeqidxmpRHHDJDM8UFBk"

View file

@ -4,9 +4,6 @@ SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhY
STREAM_CHAT_API_KEY=v4yf8rs94aa8
STREAM_CHAT_API_SECRET=jq2szvv73ua7sz9tvr9y24dxg37sw8ue8t576fu7ggr4h6wvcmunby4gvte8tm8f
EMAIL_USER="baptiste@xtablo.com"
EMAIL_KEY="jayf pzpj nrsv vtim"
XTABLO_URL=https://app.xtablo.com
CORS_ORIGIN="https://app.xtablo.com"
@ -14,4 +11,9 @@ R2_ACCOUNT_ID="9715fa14c5e5d1612301572cf1c6bbee"
R2_ACCESS_KEY_ID="caeb987bbcd601708a93c6aa562064ef"
R2_SECRET_ACCESS_KEY="42e455b25804687f7cff3d15be23c1f0f47ca742d7a41b6fa1a05a91041e0215"
SYNC_CALS_SECRET="gT3BAytmNwhe1wKmvgREBlWcqK0="
SYNC_CALS_SECRET="gT3BAytmNwhe1wKmvgREBlWcqK0="
EMAIL_USER="baptiste@xtablo.com"
EMAIL_CLIENT_ID="904332563417-e2n7pchtgnkrkp360baaebfeig55maig.apps.googleusercontent.com"
EMAIL_CLIENT_SECRET="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"
EMAIL_REFRESH_TOKEN="1//04dRsWFVjr0mqCgYIARAAGAQSNwF-L9IrN3JicCv2ib4F6AQlactB4CE6Q4ST_tEVVdmmECly_-05INeTeqidxmpRHHDJDM8UFBk"

View file

@ -4,12 +4,14 @@ SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhY
STREAM_CHAT_API_KEY=t5vvvddteapa
STREAM_CHAT_API_SECRET=zrr32sqenw3atpv9rnz2nhhyyncf7bunr7fmfqy9r7e69fcw978dhzevmhpxa2jj
EMAIL_USER="baptiste@xtablo.com"
EMAIL_KEY="jayf pzpj nrsv vtim"
XTABLO_URL="https://app-staging.xtablo.com"
CORS_ORIGIN="https://app-staging.xtablo.com"
R2_ACCOUNT_ID="9715fa14c5e5d1612301572cf1c6bbee"
R2_ACCESS_KEY_ID="caeb987bbcd601708a93c6aa562064ef"
R2_SECRET_ACCESS_KEY="42e455b25804687f7cff3d15be23c1f0f47ca742d7a41b6fa1a05a91041e0215"
R2_SECRET_ACCESS_KEY="42e455b25804687f7cff3d15be23c1f0f47ca742d7a41b6fa1a05a91041e0215"
EMAIL_USER="baptiste@xtablo.com"
EMAIL_CLIENT_ID="904332563417-e2n7pchtgnkrkp360baaebfeig55maig.apps.googleusercontent.com"
EMAIL_CLIENT_SECRET="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"
EMAIL_REFRESH_TOKEN="1//04dRsWFVjr0mqCgYIARAAGAQSNwF-L9IrN3JicCv2ib4F6AQlactB4CE6Q4ST_tEVVdmmECly_-05INeTeqidxmpRHHDJDM8UFBk"

368
api/package-lock.json generated
View file

@ -11,6 +11,7 @@
"@supabase/supabase-js": "^2.49.4",
"cors": "^2.8.5",
"dotenv": "^16.5.0",
"googleapis": "^161.0.0",
"graphile-worker": "^0.16.6",
"hono": "^4.7.7",
"hono-sessions": "^0.7.2",
@ -2279,6 +2280,14 @@
"node": ">=0.4.0"
}
},
"node_modules/agent-base": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
"engines": {
"node": ">= 14"
}
},
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
@ -2389,6 +2398,14 @@
],
"license": "MIT"
},
"node_modules/bignumber.js": {
"version": "9.3.1",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
"integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
"engines": {
"node": "*"
}
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@ -2468,6 +2485,21 @@
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@ -2654,6 +2686,14 @@
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
},
"node_modules/data-uri-to-buffer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
"engines": {
"node": ">= 12"
}
},
"node_modules/debug": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
@ -2865,6 +2905,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"node_modules/fast-xml-parser": {
"version": "5.2.5",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz",
@ -2882,6 +2927,28 @@
"fxparser": "src/cli/cli.js"
}
},
"node_modules/fetch-blob": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "paypal",
"url": "https://paypal.me/jimmywarting"
}
],
"dependencies": {
"node-domexception": "^1.0.0",
"web-streams-polyfill": "^3.0.3"
},
"engines": {
"node": "^12.20 || >= 14.13"
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@ -2954,6 +3021,17 @@
"node": ">= 6"
}
},
"node_modules/formdata-polyfill": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
"dependencies": {
"fetch-blob": "^3.1.2"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -2984,6 +3062,32 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gaxios": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.2.tgz",
"integrity": "sha512-/Szrn8nr+2TsQT1Gp8iIe/BEytJmbyfrbFh419DfGQSkEgNEhbPi7JRJuughjkTzPWgU9gBQf5AVu3DbHt0OXA==",
"dependencies": {
"extend": "^3.0.2",
"https-proxy-agent": "^7.0.1",
"node-fetch": "^3.3.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/gcp-metadata": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-7.0.1.tgz",
"integrity": "sha512-UcO3kefx6dCcZkgcTGgVOTFb7b1LlQ02hY1omMjjrrBzkajRMCFgYOjs7J71WqnuG1k2b+9ppGL7FsOfhZMQKQ==",
"dependencies": {
"gaxios": "^7.0.0",
"google-logging-utils": "^1.0.0",
"json-bigint": "^1.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@ -3083,6 +3187,77 @@
"node": ">= 6"
}
},
"node_modules/google-auth-library": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.4.0.tgz",
"integrity": "sha512-CmIrSy1bqMQUsPmA9+hcSbAXL80cFhu40cGMUjCaLpNKVzzvi+0uAHq8GNZxkoGYIsTX4ZQ7e4aInAqWxgn4fg==",
"dependencies": {
"base64-js": "^1.3.0",
"ecdsa-sig-formatter": "^1.0.11",
"gaxios": "^7.0.0",
"gcp-metadata": "^7.0.0",
"google-logging-utils": "^1.0.0",
"gtoken": "^8.0.0",
"jws": "^4.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/google-auth-library/node_modules/jwa": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/google-auth-library/node_modules/jws": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
"dependencies": {
"jwa": "^2.0.0",
"safe-buffer": "^5.0.1"
}
},
"node_modules/google-logging-utils": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.1.tgz",
"integrity": "sha512-rcX58I7nqpu4mbKztFeOAObbomBbHU2oIb/d3tJfF3dizGSApqtSwYJigGCooHdnMyQBIw8BrWyK96w3YXgr6A==",
"engines": {
"node": ">=14"
}
},
"node_modules/googleapis": {
"version": "161.0.0",
"resolved": "https://registry.npmjs.org/googleapis/-/googleapis-161.0.0.tgz",
"integrity": "sha512-JZy2cWMxgUF8E09KHzplI+z+FVG8NWDB/bsf4xevt9Um4bInb0X1qaG9qpDn49DHT5HsU0mOp3EOBGb8+AdE3Q==",
"dependencies": {
"google-auth-library": "^10.2.0",
"googleapis-common": "^8.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/googleapis-common": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-8.0.0.tgz",
"integrity": "sha512-66if47It7y+Sab3HMkwEXx1kCq9qUC9px8ZXoj1CMrmLmUw81GpbnsNlXnlyZyGbGPGcj+tDD9XsZ23m7GLaJQ==",
"dependencies": {
"extend": "^3.0.2",
"gaxios": "^7.0.0-rc.4",
"google-auth-library": "^10.1.0",
"qs": "^6.7.0",
"url-template": "^2.0.8"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@ -3144,6 +3319,37 @@
"node": ">=14.0.0"
}
},
"node_modules/gtoken": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz",
"integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==",
"dependencies": {
"gaxios": "^7.0.0",
"jws": "^4.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/gtoken/node_modules/jwa": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/gtoken/node_modules/jws": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
"dependencies": {
"jwa": "^2.0.0",
"safe-buffer": "^5.0.1"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -3218,6 +3424,18 @@
"iron-webcrypto": "^1.2.1"
}
},
"node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@ -3367,6 +3585,14 @@
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/json-bigint": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
"dependencies": {
"bignumber.js": "^9.0.0"
}
},
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
@ -3731,6 +3957,42 @@
"path-to-regexp": "^6.2.1"
}
},
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
"deprecated": "Use your platform's native DOMException instead",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "github",
"url": "https://paypal.me/jimmywarting"
}
],
"engines": {
"node": ">=10.5.0"
}
},
"node_modules/node-fetch": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
"dependencies": {
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/node-fetch"
}
},
"node_modules/nodemailer": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.4.tgz",
@ -3756,6 +4018,17 @@
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@ -3994,6 +4267,20 @@
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@ -4095,6 +4382,74 @@
"randombytes": "^2.1.0"
}
},
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
"side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-list": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-weakmap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3",
"side-channel-map": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/sinon": {
"version": "17.0.1",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz",
@ -4354,6 +4709,11 @@
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"license": "MIT"
},
"node_modules/url-template": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
"integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw=="
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -4384,6 +4744,14 @@
"node": ">= 0.8"
}
},
"node_modules/web-streams-polyfill": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
"engines": {
"node": ">= 8"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",

View file

@ -14,6 +14,7 @@
"@supabase/supabase-js": "^2.49.4",
"cors": "^2.8.5",
"dotenv": "^16.5.0",
"googleapis": "^161.0.0",
"graphile-worker": "^0.16.6",
"hono": "^4.7.7",
"hono-sessions": "^0.7.2",

View file

@ -9,7 +9,9 @@ export interface AppConfig {
STREAM_CHAT_API_KEY: string;
STREAM_CHAT_API_SECRET: string;
EMAIL_USER: string;
EMAIL_KEY: string;
EMAIL_CLIENT_ID: string;
EMAIL_CLIENT_SECRET: string;
EMAIL_REFRESH_TOKEN: string;
XTABLO_URL: string;
R2_ACCOUNT_ID: string;
R2_ACCESS_KEY_ID: string;
@ -54,7 +56,18 @@ function createConfig(): AppConfig {
process.env.STREAM_CHAT_API_SECRET
),
EMAIL_USER: validateEnvVar("EMAIL_USER", process.env.EMAIL_USER),
EMAIL_KEY: validateEnvVar("EMAIL_KEY", process.env.EMAIL_KEY),
EMAIL_CLIENT_ID: validateEnvVar(
"EMAIL_CLIENT_ID",
process.env.EMAIL_CLIENT_ID
),
EMAIL_CLIENT_SECRET: validateEnvVar(
"EMAIL_CLIENT_SECRET",
process.env.EMAIL_CLIENT_SECRET
),
EMAIL_REFRESH_TOKEN: validateEnvVar(
"EMAIL_REFRESH_TOKEN",
process.env.EMAIL_REFRESH_TOKEN
),
CORS_ORIGIN: [process.env.CORS_ORIGIN || "https://app.xtablo.com"],
XTABLO_URL: process.env.XTABLO_URL || "https://app.xtablo.com",
R2_ACCOUNT_ID: validateEnvVar("R2_ACCOUNT_ID", process.env.R2_ACCOUNT_ID),

View file

@ -1,7 +1,6 @@
import { S3Client } from "@aws-sdk/client-s3";
import { createClient, type User } from "@supabase/supabase-js";
import type { Context, Next } from "hono";
import nodemailer from "nodemailer";
import { StreamChat } from "stream-chat";
import { config } from "./config.js";
@ -40,20 +39,6 @@ export const supabaseMiddleware = async (c: Context, next: Next) => {
await next();
};
export const emailMiddleware = async (c: Context, next: Next) => {
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 465,
secure: true,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_KEY,
},
});
c.set("transporter", transporter);
await next();
};
export const streamChatMiddleware = async (c: Context, next: Next) => {
const serverClient = StreamChat.getInstance(
process.env.STREAM_CHAT_API_KEY as string,

View file

@ -1,7 +1,6 @@
import { Hono } from "hono";
import {
authMiddleware,
emailMiddleware,
r2Middleware,
streamChatMiddleware,
} from "./middleware.js";
@ -22,6 +21,7 @@ import type {
} from "./types.ts";
import { PutObjectCommand, type S3Client } from "@aws-sdk/client-s3";
import { generateICSFromEvents, writeCalendarFileToR2 } from "./helpers.js";
import { transporter } from "./transporter.js";
export const tabloRouter = new Hono<{
Variables: {
@ -44,7 +44,6 @@ export const tabloRouter = new Hono<{
// webcalRouter.use(r2Middleware);
tabloRouter.use(authMiddleware);
tabloRouter.use(emailMiddleware);
tabloRouter.use(streamChatMiddleware);
tabloRouter.use(r2Middleware);
@ -172,8 +171,6 @@ tabloRouter.post("/create-and-invite", async (c) => {
return c.json({ error: existingTabloError.message }, 500);
}
console.log("existingTablo", existingTablo);
let tabloData: { id: string; name: string } | null = null;
if (!existingTablo.length) {
@ -203,15 +200,20 @@ tabloRouter.post("/create-and-invite", async (c) => {
// Grant access to the current user (invited user) as a non-admin member
const { error: tabloAccessError } = await supabase
.from("tablo_access")
.insert({
tablo_id: tabloData.id,
user_id: user.id,
// ** IMPORTANT **
is_admin: false,
// -------------
is_active: true,
granted_by: ownerId,
});
.insert(
{
tablo_id: tabloData.id,
user_id: user.id,
// ** IMPORTANT **
is_admin: false,
// -------------
is_active: true,
granted_by: ownerId,
}
// {
// onConflict: "tablo_id, user_id",
// }
);
if (tabloAccessError) {
console.error("tabloAccessError", tabloAccessError);
@ -240,14 +242,11 @@ tabloRouter.post("/create-and-invite", async (c) => {
});
// Send email notifications to both owner and invited user
const transporter = c.get("transporter");
if (transporter) {
// Send email to the owner
await transporter.sendMail({
to: ownerDataTyped.email,
subject: "Nouveau tablo créé - Réservation confirmée",
html: `
// Send email to the owner
await transporter.sendMail({
to: ownerDataTyped.email,
subject: "Nouveau tablo créé - Réservation confirmée",
html: `
<h2>Votre tablo a é créé avec succès !</h2>
<p>Bonjour ${ownerDataTyped.name},</p>
<p>Un nouveau tablo "${tabloData.name}" a é créé suite à une réservation.</p>
@ -261,13 +260,13 @@ tabloRouter.post("/create-and-invite", async (c) => {
<p>Participant : ${invitedUserDataTyped.name} (${invitedUserDataTyped.email})</p>
<p>Vous pouvez gérer ce tablo depuis votre tableau de bord.</p>
`,
});
});
// Send email to the invited user
await transporter.sendMail({
to: invitedUserDataTyped.email,
subject: "Réservation confirmée - Nouveau tablo créé",
html: `
// Send email to the invited user
await transporter.sendMail({
to: invitedUserDataTyped.email,
subject: "Réservation confirmée - Nouveau tablo créé",
html: `
<h2>Votre réservation est confirmée !</h2>
<p>Bonjour ${invitedUserDataTyped.name},</p>
<p>Votre réservation a é confirmée et un tablo "${tabloData.name}" a é créé.</p>
@ -281,8 +280,7 @@ tabloRouter.post("/create-and-invite", async (c) => {
<p>Avec : ${ownerDataTyped.name}</p>
<p>Vous recevrez bientôt plus d'informations pour accéder à votre espace de collaboration.</p>
`,
});
}
});
return c.json({ id: tabloData.id });
});

33
api/src/transporter.ts Normal file
View file

@ -0,0 +1,33 @@
import nodemailer from "nodemailer";
import { google } from "googleapis";
import { config } from "./config.js";
const OAuth2 = google.auth.OAuth2;
export const createTransporter = async () => {
const oauth2Client = new OAuth2(
config.EMAIL_CLIENT_ID,
config.EMAIL_CLIENT_SECRET,
"https://developers.google.com/oauthplayground"
);
oauth2Client.setCredentials({
refresh_token: config.EMAIL_REFRESH_TOKEN,
});
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 465,
secure: true,
auth: {
type: "OAuth2",
user: config.EMAIL_USER,
clientId: config.EMAIL_CLIENT_ID,
clientSecret: config.EMAIL_CLIENT_SECRET,
refreshToken: config.EMAIL_REFRESH_TOKEN,
},
});
return transporter;
};
export const transporter = await createTransporter();

View file

@ -1,13 +1,10 @@
import { Hono } from "hono";
import {
authMiddleware,
emailMiddleware,
streamChatMiddleware,
} from "./middleware.js";
import { authMiddleware, streamChatMiddleware } from "./middleware.js";
import type { SupabaseClient, User } from "@supabase/supabase-js";
import { StreamChat } from "stream-chat";
import type { Transporter } from "nodemailer";
import type { Tables } from "./database.types.ts";
import { transporter } from "./transporter.js";
export const userRouter = new Hono<{
Variables: {
@ -20,7 +17,6 @@ export const userRouter = new Hono<{
userRouter.use(authMiddleware);
userRouter.use(streamChatMiddleware);
userRouter.use(emailMiddleware);
userRouter.post("/sign-up-to-stream", async (c) => {
const { id } = c.get("user");
@ -79,7 +75,6 @@ userRouter.get("/me", async (c) => {
userRouter.post("/mark-temporary", async (c) => {
const user = c.get("user");
const supabase = c.get("supabase");
const transporter = c.get("transporter");
const body = await c.req.json();
const { temporary_password } = body;

View file

@ -1,5 +1,5 @@
import { useQuery } from "@tanstack/react-query";
import { api } from "@ui/lib/api";
import { api, queryClient } from "@ui/lib/api";
import { EventTypeConfig } from "./event-types";
export type TimeSlot = {
@ -28,3 +28,7 @@ export function usePublicSlots(shortUserId: string, standardName: string) {
enabled: !!shortUserId && !!standardName,
});
}
export const invalidatePublicSlots = () => {
queryClient.invalidateQueries({ queryKey: ["public-slots"] });
};

View file

@ -9,6 +9,7 @@ import { useUser } from "@ui/providers/UserStoreProvider";
import { CreateTablo } from "@ui/types/tablos.types";
import { EventInsertInTablo } from "@ui/types/events.types";
import { useNavigate } from "react-router-dom";
import { invalidatePublicSlots } from "@ui/hooks/public";
type Tablo = Database["public"]["Tables"]["tablos"];
@ -141,6 +142,7 @@ export const useCreateTabloWithOwner = () => {
},
onSuccess: (data) => {
queryClient.invalidateQueries({ queryKey: ["tablos"] });
invalidatePublicSlots();
navigate(`/chat/${data.id}`, { replace: true });
navigate(0);
},