diff --git a/.github/workflows/check-api-for-breaking-changes.yml b/.github/workflows/check-api-for-breaking-changes.yml index 7fba6c321..2086601a8 100644 --- a/.github/workflows/check-api-for-breaking-changes.yml +++ b/.github/workflows/check-api-for-breaking-changes.yml @@ -5,6 +5,7 @@ on: types: [opened, synchronize] paths: - "backend/src/server/routes/**" + - "backend/src/ee/routes/**" jobs: check-be-api-changes: diff --git a/backend/package-lock.json b/backend/package-lock.json index 97eaf4ff8..1ef6c19e2 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -47,10 +47,11 @@ "libsodium-wrappers": "^0.7.13", "lodash.isequal": "^4.5.0", "ms": "^2.1.3", - "mysql2": "^3.9.1", + "mysql2": "^3.9.4", "nanoid": "^5.0.4", "nodemailer": "^6.9.9", "ora": "^7.0.1", + "oracledb": "^6.4.0", "passport-github": "^1.1.0", "passport-gitlab2": "^5.0.0", "passport-google-oauth20": "^2.0.0", @@ -1708,6 +1709,22 @@ "node": ">=12" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", @@ -3162,9 +3179,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.8.0.tgz", - "integrity": "sha512-zdTObFRoNENrdPpnTNnhOljYIcOX7aI7+7wyrSpPFFIOf/nRdedE6IYsjaBE7tjukphh1tMTojgJ7p3lKY8x6Q==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.3.tgz", + "integrity": "sha512-X9alQ3XM6I9IlSlmC8ddAvMSyG1WuHk5oUnXGw+yUBs3BFoTizmG1La/Gr8fVJvDWAq+zlYTZ9DBgrlKRVY06g==", "cpu": [ "arm" ], @@ -3175,9 +3192,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.8.0.tgz", - "integrity": "sha512-aiItwP48BiGpMFS9Znjo/xCNQVwTQVcRKkFKsO81m8exrGjHkCBDvm9PHay2kpa8RPnZzzKcD1iQ9KaLY4fPQQ==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.3.tgz", + "integrity": "sha512-eQK5JIi+POhFpzk+LnjKIy4Ks+pwJ+NXmPxOCSvOKSNRPONzKuUvWE+P9JxGZVxrtzm6BAYMaL50FFuPe0oWMQ==", "cpu": [ "arm64" ], @@ -3188,9 +3205,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.8.0.tgz", - "integrity": "sha512-zhNIS+L4ZYkYQUjIQUR6Zl0RXhbbA0huvNIWjmPc2SL0cB1h5Djkcy+RZ3/Bwszfb6vgwUvcVJYD6e6Zkpsi8g==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.3.tgz", + "integrity": "sha512-Od4vE6f6CTT53yM1jgcLqNfItTsLt5zE46fdPaEmeFHvPs5SjZYlLpHrSiHEKR1+HdRfxuzXHjDOIxQyC3ptBA==", "cpu": [ "arm64" ], @@ -3201,9 +3218,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.8.0.tgz", - "integrity": "sha512-A/FAHFRNQYrELrb/JHncRWzTTXB2ticiRFztP4ggIUAfa9Up1qfW8aG2w/mN9jNiZ+HB0t0u0jpJgFXG6BfRTA==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.3.tgz", + "integrity": "sha512-0IMAO21axJeNIrvS9lSe/PGthc8ZUS+zC53O0VhF5gMxfmcKAP4ESkKOCwEi6u2asUrt4mQv2rjY8QseIEb1aw==", "cpu": [ "x64" ], @@ -3214,9 +3231,22 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.8.0.tgz", - "integrity": "sha512-JsidBnh3p2IJJA4/2xOF2puAYqbaczB3elZDT0qHxn362EIoIkq7hrR43Xa8RisgI6/WPfvb2umbGsuvf7E37A==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.3.tgz", + "integrity": "sha512-ge2DC7tHRHa3caVEoSbPRJpq7azhG+xYsd6u2MEnJ6XzPSzQsTKyXvh6iWjXRf7Rt9ykIUWHtl0Uz3T6yXPpKw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.14.3.tgz", + "integrity": "sha512-ljcuiDI4V3ySuc7eSk4lQ9wU8J8r8KrOUvB2U+TtK0TiW6OFDmJ+DdIjjwZHIw9CNxzbmXY39wwpzYuFDwNXuw==", "cpu": [ "arm" ], @@ -3227,9 +3257,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.8.0.tgz", - "integrity": "sha512-hBNCnqw3EVCkaPB0Oqd24bv8SklETptQWcJz06kb9OtiShn9jK1VuTgi7o4zPSt6rNGWQOTDEAccbk0OqJmS+g==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.3.tgz", + "integrity": "sha512-Eci2us9VTHm1eSyn5/eEpaC7eP/mp5n46gTRB3Aar3BgSvDQGJZuicyq6TsH4HngNBgVqC5sDYxOzTExSU+NjA==", "cpu": [ "arm64" ], @@ -3240,9 +3270,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.8.0.tgz", - "integrity": "sha512-Fw9ChYfJPdltvi9ALJ9wzdCdxGw4wtq4t1qY028b2O7GwB5qLNSGtqMsAel1lfWTZvf4b6/+4HKp0GlSYg0ahA==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.3.tgz", + "integrity": "sha512-UrBoMLCq4E92/LCqlh+blpqMz5h1tJttPIniwUgOFJyjWI1qrtrDhhpHPuFxULlUmjFHfloWdixtDhSxJt5iKw==", "cpu": [ "arm64" ], @@ -3252,10 +3282,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.3.tgz", + "integrity": "sha512-5aRjvsS8q1nWN8AoRfrq5+9IflC3P1leMoy4r2WjXyFqf3qcqsxRCfxtZIV58tCxd+Yv7WELPcO9mY9aeQyAmw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.8.0.tgz", - "integrity": "sha512-BH5xIh7tOzS9yBi8dFrCTG8Z6iNIGWGltd3IpTSKp6+pNWWO6qy8eKoRxOtwFbMrid5NZaidLYN6rHh9aB8bEw==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.3.tgz", + "integrity": "sha512-sk/Qh1j2/RJSX7FhEpJn8n0ndxy/uf0kI/9Zc4b1ELhqULVdTfN6HL31CDaTChiBAOgLcsJ1sgVZjWv8XNEsAQ==", "cpu": [ "riscv64" ], @@ -3265,10 +3308,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.3.tgz", + "integrity": "sha512-jOO/PEaDitOmY9TgkxF/TQIjXySQe5KVYB57H/8LRP/ux0ZoO8cSHCX17asMSv3ruwslXW/TLBcxyaUzGRHcqg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.8.0.tgz", - "integrity": "sha512-PmvAj8k6EuWiyLbkNpd6BLv5XeYFpqWuRvRNRl80xVfpGXK/z6KYXmAgbI4ogz7uFiJxCnYcqyvZVD0dgFog7Q==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.3.tgz", + "integrity": "sha512-8ybV4Xjy59xLMyWo3GCfEGqtKV5M5gCSrZlxkPGvEPCGDLNla7v48S662HSGwRd6/2cSneMQWiv+QzcttLrrOA==", "cpu": [ "x64" ], @@ -3279,9 +3335,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.8.0.tgz", - "integrity": "sha512-mdxnlW2QUzXwY+95TuxZ+CurrhgrPAMveDWI97EQlA9bfhR8tw3Pt7SUlc/eSlCNxlWktpmT//EAA8UfCHOyXg==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.3.tgz", + "integrity": "sha512-s+xf1I46trOY10OqAtZ5Rm6lzHre/UiLA1J2uOhCFXWkbZrJRkYBPO6FhvGfHmdtQ3Bx793MNa7LvoWFAm93bg==", "cpu": [ "x64" ], @@ -3292,9 +3348,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.8.0.tgz", - "integrity": "sha512-ge7saUz38aesM4MA7Cad8CHo0Fyd1+qTaqoIo+Jtk+ipBi4ATSrHWov9/S4u5pbEQmLjgUjB7BJt+MiKG2kzmA==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.3.tgz", + "integrity": "sha512-+4h2WrGOYsOumDQ5S2sYNyhVfrue+9tc9XcLWLh+Kw3UOxAvrfOrSMFon60KspcDdytkNDh7K2Vs6eMaYImAZg==", "cpu": [ "arm64" ], @@ -3305,9 +3361,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.8.0.tgz", - "integrity": "sha512-p9E3PZlzurhlsN5h9g7zIP1DnqKXJe8ZUkFwAazqSvHuWfihlIISPxG9hCHCoA+dOOspL/c7ty1eeEVFTE0UTw==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.3.tgz", + "integrity": "sha512-T1l7y/bCeL/kUwh9OD4PQT4aM7Bq43vX05htPJJ46RTI4r5KNt6qJRzAfNfM+OYMNEVBWQzR2Gyk+FXLZfogGw==", "cpu": [ "ia32" ], @@ -3318,9 +3374,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.8.0.tgz", - "integrity": "sha512-kb4/auKXkYKqlUYTE8s40FcJIj5soOyRLHKd4ugR0dCq0G2EfcF54eYcfQiGkHzjidZ40daB4ulsFdtqNKZtBg==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.3.tgz", + "integrity": "sha512-/BypzV0H1y1HzgYpxqRaXGBRqfodgoBBCcsrujT6QRcakDQdfU+Lq9PENPh5jB4I44YWq+0C2eHsHya+nZY1sA==", "cpu": [ "x64" ], @@ -5916,12 +5972,12 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -5929,7 +5985,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -7379,16 +7435,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -7419,6 +7475,14 @@ "node": ">= 0.10.0" } }, + "node_modules/express/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/express/node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -7749,9 +7813,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -9759,9 +9823,9 @@ } }, "node_modules/mysql2": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.1.tgz", - "integrity": "sha512-3njoWAAhGBYy0tWBabqUQcLtczZUxrmmtc2vszQUekg3kTJyZ5/IeLC3Fo04u6y6Iy5Sba7pIIa2P/gs8D3ZeQ==", + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.4.tgz", + "integrity": "sha512-OEESQuwxMza803knC1YSt7NMuc1BrK9j7gZhCSs2WAyxr1vfiI7QLaLOKTh5c9SWGz98qVyQUbK8/WckevNQhg==", "dependencies": { "denque": "^2.1.0", "generate-function": "^2.3.1", @@ -10231,6 +10295,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/oracledb": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/oracledb/-/oracledb-6.4.0.tgz", + "integrity": "sha512-TJI08qzQlf/l7T49VojP9BoQpjEr14NXZmpSzzcLrbNs7qSl0QA/Mc9gGiEdkg5WmwH0wqUjtMC7jlf1WamlYA==", + "hasInstallScript": true, + "engines": { + "node": ">=14.6" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -10818,9 +10891,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, "funding": [ { @@ -10839,7 +10912,7 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -11234,9 +11307,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -11511,10 +11584,13 @@ } }, "node_modules/rollup": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.8.0.tgz", - "integrity": "sha512-NpsklK2fach5CdI+PScmlE5R4Ao/FSWtF7LkoIrHDxPACY/xshNasPsbpG0VVHxUTbf74tJbVT4PrP8JsJ6ZDA==", + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.3.tgz", + "integrity": "sha512-ag5tTQKYsj1bhrFC9+OEWqb5O6VYgtQDO9hPDBMmIbePwhfSr+ExlcU741t8Dhw5DkPCQf6noz0jb36D6W9/hw==", "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, @@ -11523,19 +11599,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.8.0", - "@rollup/rollup-android-arm64": "4.8.0", - "@rollup/rollup-darwin-arm64": "4.8.0", - "@rollup/rollup-darwin-x64": "4.8.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.8.0", - "@rollup/rollup-linux-arm64-gnu": "4.8.0", - "@rollup/rollup-linux-arm64-musl": "4.8.0", - "@rollup/rollup-linux-riscv64-gnu": "4.8.0", - "@rollup/rollup-linux-x64-gnu": "4.8.0", - "@rollup/rollup-linux-x64-musl": "4.8.0", - "@rollup/rollup-win32-arm64-msvc": "4.8.0", - "@rollup/rollup-win32-ia32-msvc": "4.8.0", - "@rollup/rollup-win32-x64-msvc": "4.8.0", + "@rollup/rollup-android-arm-eabi": "4.14.3", + "@rollup/rollup-android-arm64": "4.14.3", + "@rollup/rollup-darwin-arm64": "4.14.3", + "@rollup/rollup-darwin-x64": "4.14.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.14.3", + "@rollup/rollup-linux-arm-musleabihf": "4.14.3", + "@rollup/rollup-linux-arm64-gnu": "4.14.3", + "@rollup/rollup-linux-arm64-musl": "4.14.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.14.3", + "@rollup/rollup-linux-riscv64-gnu": "4.14.3", + "@rollup/rollup-linux-s390x-gnu": "4.14.3", + "@rollup/rollup-linux-x64-gnu": "4.14.3", + "@rollup/rollup-linux-x64-musl": "4.14.3", + "@rollup/rollup-win32-arm64-msvc": "4.14.3", + "@rollup/rollup-win32-ia32-msvc": "4.14.3", + "@rollup/rollup-win32-x64-msvc": "4.14.3", "fsevents": "~2.3.2" } }, @@ -11887,9 +11966,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -12249,9 +12328,9 @@ } }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -13447,14 +13526,14 @@ } }, "node_modules/vite": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", - "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", + "version": "5.2.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.9.tgz", + "integrity": "sha512-uOQWfuZBlc6Y3W/DTuQ1Sr+oIXWvqljLvS881SVmAj00d5RdgShLcuXWxseWPd4HXwiYBFW/vXHfKFeqj9uQnw==", "dev": true, "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.32", - "rollup": "^4.2.0" + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" }, "bin": { "vite": "bin/vite.js" @@ -13589,9 +13668,9 @@ "dev": true }, "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.9.tgz", - "integrity": "sha512-jkYjjq7SdsWuNI6b5quymW0oC83NN5FdRPuCbs9HZ02mfVdAP8B8eeqLSYU3gb6OJEaY5CQabtTFbqBf26H3GA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -13605,9 +13684,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.9.tgz", - "integrity": "sha512-q4cR+6ZD0938R19MyEW3jEsMzbb/1rulLXiNAJQADD/XYp7pT+rOS5JGxvpRW8dFDEfjW4wLgC/3FXIw4zYglQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -13621,9 +13700,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.9.tgz", - "integrity": "sha512-KOqoPntWAH6ZxDwx1D6mRntIgZh9KodzgNOy5Ebt9ghzffOk9X2c1sPwtM9P+0eXbefnDhqYfkh5PLP5ULtWFA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -13637,9 +13716,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.9.tgz", - "integrity": "sha512-KBJ9S0AFyLVx2E5D8W0vExqRW01WqRtczUZ8NRu+Pi+87opZn5tL4Y0xT0mA4FtHctd0ZgwNoN639fUUGlNIWw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -13653,9 +13732,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.9.tgz", - "integrity": "sha512-vE0VotmNTQaTdX0Q9dOHmMTao6ObjyPm58CHZr1UK7qpNleQyxlFlNCaHsHx6Uqv86VgPmR4o2wdNq3dP1qyDQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -13669,9 +13748,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.9.tgz", - "integrity": "sha512-uFQyd/o1IjiEk3rUHSwUKkqZwqdvuD8GevWF065eqgYfexcVkxh+IJgwTaGZVu59XczZGcN/YMh9uF1fWD8j1g==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -13685,9 +13764,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.9.tgz", - "integrity": "sha512-WMLgWAtkdTbTu1AWacY7uoj/YtHthgqrqhf1OaEWnZb7PQgpt8eaA/F3LkV0E6K/Lc0cUr/uaVP/49iE4M4asA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -13701,9 +13780,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.9.tgz", - "integrity": "sha512-C/ChPohUYoyUaqn1h17m/6yt6OB14hbXvT8EgM1ZWaiiTYz7nWZR0SYmMnB5BzQA4GXl3BgBO1l8MYqL/He3qw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -13717,9 +13796,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.9.tgz", - "integrity": "sha512-PiPblfe1BjK7WDAKR1Cr9O7VVPqVNpwFcPWgfn4xu0eMemzRp442hXyzF/fSwgrufI66FpHOEJk0yYdPInsmyQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -13733,9 +13812,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.9.tgz", - "integrity": "sha512-f37i/0zE0MjDxijkPSQw1CO/7C27Eojqb+r3BbHVxMLkj8GCa78TrBZzvPyA/FNLUMzP3eyHCVkAopkKVja+6Q==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -13749,9 +13828,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.9.tgz", - "integrity": "sha512-t6mN147pUIf3t6wUt3FeumoOTPfmv9Cc6DQlsVBpB7eCpLOqQDyWBP1ymXn1lDw4fNUSb/gBcKAmvTP49oIkaA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -13765,9 +13844,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.9.tgz", - "integrity": "sha512-jg9fujJTNTQBuDXdmAg1eeJUL4Jds7BklOTkkH80ZgQIoCTdQrDaHYgbFZyeTq8zbY+axgptncko3v9p5hLZtw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -13781,9 +13860,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.9.tgz", - "integrity": "sha512-tkV0xUX0pUUgY4ha7z5BbDS85uI7ABw3V1d0RNTii7E9lbmV8Z37Pup2tsLV46SQWzjOeyDi1Q7Wx2+QM8WaCQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -13797,9 +13876,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.9.tgz", - "integrity": "sha512-DfLp8dj91cufgPZDXr9p3FoR++m3ZJ6uIXsXrIvJdOjXVREtXuQCjfMfvmc3LScAVmLjcfloyVtpn43D56JFHg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -13813,9 +13892,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.9.tgz", - "integrity": "sha512-zHbglfEdC88KMgCWpOl/zc6dDYJvWGLiUtmPRsr1OgCViu3z5GncvNVdf+6/56O2Ca8jUU+t1BW261V6kp8qdw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -13829,9 +13908,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.9.tgz", - "integrity": "sha512-JUjpystGFFmNrEHQnIVG8hKwvA2DN5o7RqiO1CVX8EN/F/gkCjkUMgVn6hzScpwnJtl2mPR6I9XV1oW8k9O+0A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -13845,9 +13924,9 @@ } }, "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.9.tgz", - "integrity": "sha512-GThgZPAwOBOsheA2RUlW5UeroRfESwMq/guy8uEe3wJlAOjpOXuSevLRd70NZ37ZrpO6RHGHgEHvPg1h3S1Jug==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -13861,9 +13940,9 @@ } }, "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.9.tgz", - "integrity": "sha512-Ki6PlzppaFVbLnD8PtlVQfsYw4S9n3eQl87cqgeIw+O3sRr9IghpfSKY62mggdt1yCSZ8QWvTZ9jo9fjDSg9uw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -13877,9 +13956,9 @@ } }, "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.9.tgz", - "integrity": "sha512-MLHj7k9hWh4y1ddkBpvRj2b9NCBhfgBt3VpWbHQnXRedVun/hC7sIyTGDGTfsGuXo4ebik2+3ShjcPbhtFwWDw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -13893,9 +13972,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.9.tgz", - "integrity": "sha512-GQoa6OrQ8G08guMFgeXPH7yE/8Dt0IfOGWJSfSH4uafwdC7rWwrfE6P9N8AtPGIjUzdo2+7bN8Xo3qC578olhg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -13909,9 +13988,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.9.tgz", - "integrity": "sha512-UOozV7Ntykvr5tSOlGCrqU3NBr3d8JqPes0QWN2WOXfvkWVGRajC+Ym0/Wj88fUgecUCLDdJPDF0Nna2UK3Qtg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -13925,9 +14004,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.9.tgz", - "integrity": "sha512-oxoQgglOP7RH6iasDrhY+R/3cHrfwIDvRlT4CGChflq6twk8iENeVvMJjmvBb94Ik1Z+93iGO27err7w6l54GQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -13941,9 +14020,9 @@ } }, "node_modules/vite/node_modules/esbuild": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.9.tgz", - "integrity": "sha512-U9CHtKSy+EpPsEBa+/A2gMs/h3ylBC0H0KSqIg7tpztHerLi6nrrcoUJAkNCEPumx8yJ+Byic4BVwHgRbN0TBg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "dev": true, "hasInstallScript": true, "bin": { @@ -13953,28 +14032,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.9", - "@esbuild/android-arm64": "0.19.9", - "@esbuild/android-x64": "0.19.9", - "@esbuild/darwin-arm64": "0.19.9", - "@esbuild/darwin-x64": "0.19.9", - "@esbuild/freebsd-arm64": "0.19.9", - "@esbuild/freebsd-x64": "0.19.9", - "@esbuild/linux-arm": "0.19.9", - "@esbuild/linux-arm64": "0.19.9", - "@esbuild/linux-ia32": "0.19.9", - "@esbuild/linux-loong64": "0.19.9", - "@esbuild/linux-mips64el": "0.19.9", - "@esbuild/linux-ppc64": "0.19.9", - "@esbuild/linux-riscv64": "0.19.9", - "@esbuild/linux-s390x": "0.19.9", - "@esbuild/linux-x64": "0.19.9", - "@esbuild/netbsd-x64": "0.19.9", - "@esbuild/openbsd-x64": "0.19.9", - "@esbuild/sunos-x64": "0.19.9", - "@esbuild/win32-arm64": "0.19.9", - "@esbuild/win32-ia32": "0.19.9", - "@esbuild/win32-x64": "0.19.9" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/vitest": { diff --git a/backend/package.json b/backend/package.json index 97fea1438..f53ec9329 100644 --- a/backend/package.json +++ b/backend/package.json @@ -112,6 +112,7 @@ "nanoid": "^5.0.4", "nodemailer": "^6.9.9", "ora": "^7.0.1", + "oracledb": "^6.4.0", "passport-github": "^1.1.0", "passport-gitlab2": "^5.0.0", "passport-google-oauth20": "^2.0.0", diff --git a/backend/src/ee/routes/v1/project-router.ts b/backend/src/ee/routes/v1/project-router.ts index fd5a7048d..9795aaf86 100644 --- a/backend/src/ee/routes/v1/project-router.ts +++ b/backend/src/ee/routes/v1/project-router.ts @@ -19,7 +19,6 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { description: "Return project secret snapshots ids", security: [ { - apiKeyAuth: [], bearerAuth: [] } ], @@ -97,8 +96,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { description: "Return audit logs", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ diff --git a/backend/src/ee/routes/v1/snapshot-router.ts b/backend/src/ee/routes/v1/snapshot-router.ts index 7eee44f7e..6767f8383 100644 --- a/backend/src/ee/routes/v1/snapshot-router.ts +++ b/backend/src/ee/routes/v1/snapshot-router.ts @@ -69,7 +69,6 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => { description: "Roll back project secrets to those captured in a secret snapshot version.", security: [ { - apiKeyAuth: [], bearerAuth: [] } ], diff --git a/backend/src/ee/services/dynamic-secret/providers/models.ts b/backend/src/ee/services/dynamic-secret/providers/models.ts index 9d45a7401..d3510d583 100644 --- a/backend/src/ee/services/dynamic-secret/providers/models.ts +++ b/backend/src/ee/services/dynamic-secret/providers/models.ts @@ -2,7 +2,8 @@ import { z } from "zod"; export enum SqlProviders { Postgres = "postgres", - MySQL = "mysql2" + MySQL = "mysql2", + Oracle = "oracledb" } export const DynamicSecretSqlDBSchema = z.object({ diff --git a/backend/src/ee/services/dynamic-secret/providers/sql-database.ts b/backend/src/ee/services/dynamic-secret/providers/sql-database.ts index ae61fa011..4c1d5438b 100644 --- a/backend/src/ee/services/dynamic-secret/providers/sql-database.ts +++ b/backend/src/ee/services/dynamic-secret/providers/sql-database.ts @@ -8,15 +8,25 @@ import { BadRequestError } from "@app/lib/errors"; import { getDbConnectionHost } from "@app/lib/knex"; import { alphaNumericNanoId } from "@app/lib/nanoid"; -import { DynamicSecretSqlDBSchema, TDynamicProviderFns } from "./models"; +import { DynamicSecretSqlDBSchema, SqlProviders, TDynamicProviderFns } from "./models"; const EXTERNAL_REQUEST_TIMEOUT = 10 * 1000; -const generatePassword = (size?: number) => { +const generatePassword = (provider: SqlProviders) => { + // oracle has limit of 48 password length + const size = provider === SqlProviders.Oracle ? 30 : 48; + const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*$#"; return customAlphabet(charset, 48)(size); }; +const generateUsername = (provider: SqlProviders) => { + // For oracle, the client assumes everything is upper case when not using quotes around the password + if (provider === SqlProviders.Oracle) return alphaNumericNanoId(32).toUpperCase(); + + return alphaNumericNanoId(32); +}; + export const SqlDatabaseProvider = (): TDynamicProviderFns => { const validateProviderInputs = async (inputs: unknown) => { const appCfg = getConfig(); @@ -59,10 +69,10 @@ export const SqlDatabaseProvider = (): TDynamicProviderFns => { const validateConnection = async (inputs: unknown) => { const providerInputs = await validateProviderInputs(inputs); const db = await getClient(providerInputs); - const isConnected = await db - .raw("SELECT NOW()") - .then(() => true) - .catch(() => false); + // oracle needs from keyword + const testStatement = providerInputs.client === SqlProviders.Oracle ? "SELECT 1 FROM DUAL" : "SELECT 1"; + + const isConnected = await db.raw(testStatement).then(() => true); await db.destroy(); return isConnected; }; @@ -71,8 +81,8 @@ export const SqlDatabaseProvider = (): TDynamicProviderFns => { const providerInputs = await validateProviderInputs(inputs); const db = await getClient(providerInputs); - const username = alphaNumericNanoId(32); - const password = generatePassword(); + const username = generateUsername(providerInputs.client); + const password = generatePassword(providerInputs.client); const { database } = providerInputs; const expiration = new Date(expireAt).toISOString(); diff --git a/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts b/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts index de2f6efcb..0e71ad126 100644 --- a/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts +++ b/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts @@ -1,4 +1,4 @@ -import { ForbiddenError } from "@casl/ability"; +import { ForbiddenError, subject } from "@casl/ability"; import { TableName, TSecretTagJunctionInsert } from "@app/db/schemas"; import { BadRequestError, InternalServerError } from "@app/lib/errors"; @@ -23,6 +23,7 @@ import { import { TSnapshotDALFactory } from "./snapshot-dal"; import { TSnapshotFolderDALFactory } from "./snapshot-folder-dal"; import { TSnapshotSecretDALFactory } from "./snapshot-secret-dal"; +import { getFullFolderPath } from "./snapshot-service-fns"; type TSecretSnapshotServiceFactoryDep = { snapshotDAL: TSnapshotDALFactory; @@ -33,7 +34,7 @@ type TSecretSnapshotServiceFactoryDep = { secretDAL: Pick; secretTagDAL: Pick; secretVersionTagDAL: Pick; - folderDAL: Pick; + folderDAL: Pick; permissionService: Pick; licenseService: Pick; }; @@ -71,6 +72,12 @@ export const secretSnapshotServiceFactory = ({ ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); + // We need to check if the user has access to the secrets in the folder. If we don't do this, a user could theoretically access snapshot secret values even if they don't have read access to the secrets in the folder. + ForbiddenError.from(permission).throwUnlessCan( + ProjectPermissionActions.Read, + subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) + ); + const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new BadRequestError({ message: "Folder not found" }); @@ -98,6 +105,12 @@ export const secretSnapshotServiceFactory = ({ ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); + // We need to check if the user has access to the secrets in the folder. If we don't do this, a user could theoretically access snapshot secret values even if they don't have read access to the secrets in the folder. + ForbiddenError.from(permission).throwUnlessCan( + ProjectPermissionActions.Read, + subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) + ); + const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new BadRequestError({ message: "Folder not found" }); @@ -116,6 +129,19 @@ export const secretSnapshotServiceFactory = ({ actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); + + const fullFolderPath = await getFullFolderPath({ + folderDAL, + folderId: snapshot.folderId, + envId: snapshot.environment.id + }); + + // We need to check if the user has access to the secrets in the folder. If we don't do this, a user could theoretically access snapshot secret values even if they don't have read access to the secrets in the folder. + ForbiddenError.from(permission).throwUnlessCan( + ProjectPermissionActions.Read, + subject(ProjectPermissionSub.Secrets, { environment: snapshot.environment.slug, secretPath: fullFolderPath }) + ); + return snapshot; }; diff --git a/backend/src/ee/services/secret-snapshot/snapshot-dal.ts b/backend/src/ee/services/secret-snapshot/snapshot-dal.ts index 41524c6eb..cdd5a999b 100644 --- a/backend/src/ee/services/secret-snapshot/snapshot-dal.ts +++ b/backend/src/ee/services/secret-snapshot/snapshot-dal.ts @@ -101,6 +101,7 @@ export const snapshotDALFactory = (db: TDbClient) => { key: "snapshotId", parentMapper: ({ snapshotId: id, + folderId, projectId, envId, envSlug, @@ -109,6 +110,7 @@ export const snapshotDALFactory = (db: TDbClient) => { snapshotUpdatedAt: updatedAt }) => ({ id, + folderId, projectId, createdAt, updatedAt, diff --git a/backend/src/ee/services/secret-snapshot/snapshot-service-fns.ts b/backend/src/ee/services/secret-snapshot/snapshot-service-fns.ts new file mode 100644 index 000000000..51cb9c056 --- /dev/null +++ b/backend/src/ee/services/secret-snapshot/snapshot-service-fns.ts @@ -0,0 +1,28 @@ +import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal"; + +type GetFullFolderPath = { + folderDAL: Pick; // Added findAllInEnv + folderId: string; + envId: string; +}; + +export const getFullFolderPath = async ({ folderDAL, folderId, envId }: GetFullFolderPath): Promise => { + // Helper function to remove duplicate slashes + const removeDuplicateSlashes = (path: string) => path.replace(/\/{2,}/g, "/"); + + // Fetch all folders at once based on environment ID to avoid multiple queries + const folders = await folderDAL.find({ envId }); + const folderMap = new Map(folders.map((folder) => [folder.id, folder])); + + const buildPath = (currFolderId: string): string => { + const folder = folderMap.get(currFolderId); + if (!folder) return ""; + const folderPathSegment = !folder.parentId && folder.name === "root" ? "/" : `/${folder.name}`; + if (folder.parentId) { + return removeDuplicateSlashes(`${buildPath(folder.parentId)}${folderPathSegment}`); + } + return removeDuplicateSlashes(folderPathSegment); + }; + + return buildPath(folderId); +}; diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 40772a207..c83234c1f 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -589,7 +589,8 @@ export const INTEGRATION = { secretSuffix: "The suffix for the saved secret. Used by GCP", initialSyncBehavoir: "Type of syncing behavoir with the integration", shouldAutoRedeploy: "Used by Render to trigger auto deploy", - secretGCPLabel: "The label for the GCP secrets" + secretGCPLabel: "The label for the GCP secrets", + secretAWSTag: "The tag for the AWS secrets" } }, UPDATE: { diff --git a/backend/src/server/plugins/swagger.ts b/backend/src/server/plugins/swagger.ts index 2d7e6706c..99032bb6f 100644 --- a/backend/src/server/plugins/swagger.ts +++ b/backend/src/server/plugins/swagger.ts @@ -30,12 +30,6 @@ export const fastifySwagger = fp(async (fastify) => { scheme: "bearer", bearerFormat: "JWT", description: "An access token in Infisical" - }, - apiKeyAuth: { - type: "apiKey", - in: "header", - name: "X-API-Key", - description: "An API Key in Infisical" } } } diff --git a/backend/src/server/routes/v1/integration-router.ts b/backend/src/server/routes/v1/integration-router.ts index cf8fbf41f..58a8917c5 100644 --- a/backend/src/server/routes/v1/integration-router.ts +++ b/backend/src/server/routes/v1/integration-router.ts @@ -56,7 +56,14 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { labelValue: z.string() }) .optional() - .describe(INTEGRATION.CREATE.metadata.secretGCPLabel) + .describe(INTEGRATION.CREATE.metadata.secretGCPLabel), + secretAWSTag: z + .object({ + key: z.string(), + value: z.string() + }) + .optional() + .describe(INTEGRATION.CREATE.metadata.secretAWSTag) }) .optional() }), diff --git a/backend/src/server/routes/v1/project-env-router.ts b/backend/src/server/routes/v1/project-env-router.ts index e1efa1637..ef51f865c 100644 --- a/backend/src/server/routes/v1/project-env-router.ts +++ b/backend/src/server/routes/v1/project-env-router.ts @@ -18,8 +18,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => { description: "Create environment", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -77,8 +76,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => { description: "Update environment", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -144,8 +142,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => { description: "Delete environment", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ diff --git a/backend/src/server/routes/v1/project-membership-router.ts b/backend/src/server/routes/v1/project-membership-router.ts index d99b4ec08..d2ed649db 100644 --- a/backend/src/server/routes/v1/project-membership-router.ts +++ b/backend/src/server/routes/v1/project-membership-router.ts @@ -26,8 +26,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider description: "Return project user memberships", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -139,8 +138,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider description: "Update project user membership", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -213,8 +211,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider description: "Delete project user membership", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ diff --git a/backend/src/server/routes/v1/project-router.ts b/backend/src/server/routes/v1/project-router.ts index 280e52680..1cf655a97 100644 --- a/backend/src/server/routes/v1/project-router.ts +++ b/backend/src/server/routes/v1/project-router.ts @@ -138,6 +138,12 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { rateLimit: readLimit }, schema: { + description: "Get project", + security: [ + { + bearerAuth: [] + } + ], params: z.object({ workspaceId: z.string().trim().describe(PROJECTS.GET.workspaceId) }), @@ -170,6 +176,12 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { rateLimit: writeLimit }, schema: { + description: "Delete project", + security: [ + { + bearerAuth: [] + } + ], params: z.object({ workspaceId: z.string().trim().describe(PROJECTS.DELETE.workspaceId) }), @@ -239,6 +251,12 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { rateLimit: writeLimit }, schema: { + description: "Update project", + security: [ + { + bearerAuth: [] + } + ], params: z.object({ workspaceId: z.string().trim().describe(PROJECTS.UPDATE.workspaceId) }), diff --git a/backend/src/server/routes/v1/secret-folder-router.ts b/backend/src/server/routes/v1/secret-folder-router.ts index 36544de1c..3b8d0988f 100644 --- a/backend/src/server/routes/v1/secret-folder-router.ts +++ b/backend/src/server/routes/v1/secret-folder-router.ts @@ -19,8 +19,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => description: "Create folders", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], body: z.object({ @@ -76,8 +75,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => description: "Update folder", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -140,8 +138,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => description: "Delete a folder", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -200,8 +197,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => description: "Get folders", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], querystring: z.object({ diff --git a/backend/src/server/routes/v1/secret-import-router.ts b/backend/src/server/routes/v1/secret-import-router.ts index 0d3f547b3..d036fdbdd 100644 --- a/backend/src/server/routes/v1/secret-import-router.ts +++ b/backend/src/server/routes/v1/secret-import-router.ts @@ -19,8 +19,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) => description: "Create secret imports", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], body: z.object({ @@ -84,8 +83,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) => description: "Update secret imports", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -159,8 +157,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) => description: "Delete secret imports", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -223,8 +220,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) => description: "Get secret imports", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], querystring: z.object({ diff --git a/backend/src/server/routes/v2/identity-org-router.ts b/backend/src/server/routes/v2/identity-org-router.ts index b53e43ed0..aab84ef8d 100644 --- a/backend/src/server/routes/v2/identity-org-router.ts +++ b/backend/src/server/routes/v2/identity-org-router.ts @@ -18,8 +18,7 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => { description: "Return organization identity memberships", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ diff --git a/backend/src/server/routes/v2/organization-router.ts b/backend/src/server/routes/v2/organization-router.ts index ae132316a..e8204222e 100644 --- a/backend/src/server/routes/v2/organization-router.ts +++ b/backend/src/server/routes/v2/organization-router.ts @@ -17,8 +17,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => { description: "Return organization user memberships", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -65,8 +64,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => { description: "Return projects in organization that user is part of", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -114,8 +112,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => { description: "Update organization user memberships", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -157,8 +154,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => { description: "Delete organization user memberships", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ diff --git a/backend/src/server/routes/v2/project-membership-router.ts b/backend/src/server/routes/v2/project-membership-router.ts index cb9aa73a9..96471dc2c 100644 --- a/backend/src/server/routes/v2/project-membership-router.ts +++ b/backend/src/server/routes/v2/project-membership-router.ts @@ -15,6 +15,12 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider rateLimit: writeLimit }, schema: { + description: "Invite members to project", + security: [ + { + bearerAuth: [] + } + ], params: z.object({ projectId: z.string().describe(PROJECTS.INVITE_MEMBER.projectId) }), @@ -64,10 +70,15 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider rateLimit: writeLimit }, schema: { + description: "Remove members from project", + security: [ + { + bearerAuth: [] + } + ], params: z.object({ projectId: z.string().describe(PROJECTS.REMOVE_MEMBER.projectId) }), - body: z.object({ emails: z.string().email().array().default([]).describe(PROJECTS.REMOVE_MEMBER.emails), usernames: z.string().array().default([]).describe(PROJECTS.REMOVE_MEMBER.usernames) diff --git a/backend/src/server/routes/v2/project-router.ts b/backend/src/server/routes/v2/project-router.ts index 26c7cf30c..a199cf0d4 100644 --- a/backend/src/server/routes/v2/project-router.ts +++ b/backend/src/server/routes/v2/project-router.ts @@ -36,11 +36,6 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { }, schema: { description: "Return encrypted project key", - security: [ - { - apiKeyAuth: [] - } - ], params: z.object({ workspaceId: z.string().trim().describe(PROJECTS.GET_KEY.workspaceId) }), @@ -149,6 +144,12 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { rateLimit: creationLimit }, schema: { + description: "Create a new project", + security: [ + { + bearerAuth: [] + } + ], body: z.object({ projectName: z.string().trim().describe(PROJECTS.CREATE.projectName), slug: z @@ -200,6 +201,12 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { rateLimit: writeLimit }, schema: { + description: "Delete project", + security: [ + { + bearerAuth: [] + } + ], params: z.object({ slug: slugSchema.describe("The slug of the project to delete.") }), diff --git a/backend/src/server/routes/v2/user-router.ts b/backend/src/server/routes/v2/user-router.ts index 217e32ddf..d1e80702f 100644 --- a/backend/src/server/routes/v2/user-router.ts +++ b/backend/src/server/routes/v2/user-router.ts @@ -85,11 +85,6 @@ export const registerUserRouter = async (server: FastifyZodProvider) => { }, schema: { description: "Return organizations that current user is part of", - security: [ - { - apiKeyAuth: [] - } - ], response: { 200: z.object({ organizations: OrganizationsSchema.array() @@ -217,11 +212,6 @@ export const registerUserRouter = async (server: FastifyZodProvider) => { }, schema: { description: "Retrieve the current user on the request", - security: [ - { - apiKeyAuth: [] - } - ], response: { 200: z.object({ user: UsersSchema.merge(UserEncryptionKeysSchema.omit({ verifier: true })) diff --git a/backend/src/server/routes/v3/secret-router.ts b/backend/src/server/routes/v3/secret-router.ts index 8f4b2b728..b1d852a88 100644 --- a/backend/src/server/routes/v3/secret-router.ts +++ b/backend/src/server/routes/v3/secret-router.ts @@ -158,8 +158,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { description: "List secrets", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], querystring: z.object({ @@ -280,8 +279,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { description: "Get a secret by name", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -375,8 +373,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { description: "Create secret", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -464,8 +461,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { description: "Update secret", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ @@ -550,8 +546,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { description: "Delete secret", security: [ { - bearerAuth: [], - apiKeyAuth: [] + bearerAuth: [] } ], params: z.object({ diff --git a/backend/src/services/integration-auth/integration-app-list.ts b/backend/src/services/integration-auth/integration-app-list.ts index 17c0051c8..9cb0d822c 100644 --- a/backend/src/services/integration-auth/integration-app-list.ts +++ b/backend/src/services/integration-auth/integration-app-list.ts @@ -129,26 +129,55 @@ const getAppsHeroku = async ({ accessToken }: { accessToken: string }) => { * Return list of names of apps for Vercel integration */ const getAppsVercel = async ({ accessToken, teamId }: { teamId?: string | null; accessToken: string }) => { - const res = ( - await request.get<{ projects: { name: string; id: string }[] }>(`${IntegrationUrls.VERCEL_API_URL}/v9/projects`, { + const apps: Array<{ name: string; appId: string }> = []; + + const limit = "20"; + let hasMorePages = true; + let next: number | null = null; + + interface Response { + projects: { name: string; id: string }[]; + pagination: { + count: number; + next: number | null; + prev: number; + }; + } + + while (hasMorePages) { + const params: { [key: string]: string } = { + limit + }; + + if (teamId) { + params.teamId = teamId; + } + + if (next) { + params.until = String(next); + } + + const { data } = await request.get(`${IntegrationUrls.VERCEL_API_URL}/v9/projects`, { + params: new URLSearchParams(params), headers: { Authorization: `Bearer ${accessToken}`, "Accept-Encoding": "application/json" - }, - ...(teamId - ? { - params: { - teamId - } - } - : {}) - }) - ).data; + } + }); - const apps = res.projects.map((a) => ({ - name: a.name, - appId: a.id - })); + data.projects.forEach((a) => { + apps.push({ + name: a.name, + appId: a.id + }); + }); + + next = data.pagination.next; + + if (data.pagination.next === null) { + hasMorePages = false; + } + } return apps; }; diff --git a/backend/src/services/integration-auth/integration-sync-secret.ts b/backend/src/services/integration-auth/integration-sync-secret.ts index 3273b4b2d..48226bb59 100644 --- a/backend/src/services/integration-auth/integration-sync-secret.ts +++ b/backend/src/services/integration-auth/integration-sync-secret.ts @@ -457,6 +457,8 @@ const syncSecretsAWSParameterStore = async ({ }); ssm.config.update(config); + const metadata = z.record(z.any()).parse(integration.metadata); + const params = { Path: integration.path as string, Recursive: false, @@ -486,7 +488,8 @@ const syncSecretsAWSParameterStore = async ({ Name: `${integration.path}${key}`, Type: "SecureString", Value: secrets[key].value, - Overwrite: true + // Overwrite: true, + Tags: metadata.secretAWSTag ? [{ Key: metadata.secretAWSTag.key, Value: metadata.secretAWSTag.value }] : [] }) .promise(); // case: secret exists in AWS parameter store @@ -499,6 +502,7 @@ const syncSecretsAWSParameterStore = async ({ Type: "SecureString", Value: secrets[key].value, Overwrite: true + // Tags: metadata.secretAWSTag ? [{ Key: metadata.secretAWSTag.key, Value: metadata.secretAWSTag.value }] : [] }) .promise(); } @@ -537,6 +541,7 @@ const syncSecretsAWSSecretManager = async ({ }) => { let secretsManager; const secKeyVal = getSecretKeyValuePair(secrets); + const metadata = z.record(z.any()).parse(integration.metadata); try { if (!accessId) return; @@ -573,7 +578,8 @@ const syncSecretsAWSSecretManager = async ({ await secretsManager.send( new CreateSecretCommand({ Name: integration.app as string, - SecretString: JSON.stringify(secKeyVal) + SecretString: JSON.stringify(secKeyVal), + Tags: metadata.secretAWSTag ? [{ Key: metadata.secretAWSTag.key, Value: metadata.secretAWSTag.value }] : [] }) ); } diff --git a/backend/src/services/integration/integration-types.ts b/backend/src/services/integration/integration-types.ts index 8f54c4fdb..93c36cd8e 100644 --- a/backend/src/services/integration/integration-types.ts +++ b/backend/src/services/integration/integration-types.ts @@ -22,6 +22,10 @@ export type TCreateIntegrationDTO = { labelName: string; labelValue: string; }; + secretAWSTag?: { + key: string; + value: string; + }; }; } & Omit; diff --git a/backend/src/services/project-membership/project-membership-service.ts b/backend/src/services/project-membership/project-membership-service.ts index becde2b72..6d148d03b 100644 --- a/backend/src/services/project-membership/project-membership-service.ts +++ b/backend/src/services/project-membership/project-membership-service.ts @@ -134,8 +134,7 @@ export const projectMembershipServiceFactory = ({ const projectMemberships = await projectMembershipDAL.insertMany( orgMembers.map(({ userId }) => ({ projectId, - userId: userId as string, - role: ProjectMembershipRole.Member + userId: userId as string })), tx ); @@ -267,8 +266,7 @@ export const projectMembershipServiceFactory = ({ const projectMemberships = await projectMembershipDAL.insertMany( orgMembers.map(({ user }) => ({ projectId, - userId: user.id, - role: ProjectMembershipRole.Member + userId: user.id })), tx ); diff --git a/cli/packages/cmd/agent.go b/cli/packages/cmd/agent.go index 7e8babb85..03bf9af4d 100644 --- a/cli/packages/cmd/agent.go +++ b/cli/packages/cmd/agent.go @@ -381,6 +381,12 @@ func ProcessTemplate(templateId int, templatePath string, data interface{}, acce funcs := template.FuncMap{ "secret": secretFunction, "dynamic_secret": dynamicSecretFunction, + "minus": func(a, b int) int { + return a - b + }, + "add": func(a, b int) int { + return a + b + }, } templateName := path.Base(templatePath) diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index 4e08e5fa8..84015cc02 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -7,6 +7,7 @@ import ( "encoding/csv" "encoding/json" "fmt" + "os" "strings" "github.com/Infisical/infisical-merge/packages/models" @@ -59,6 +60,11 @@ var exportCmd = &cobra.Command{ util.HandleError(err) } + templatePath, err := cmd.Flags().GetString("template") + if err != nil { + util.HandleError(err) + } + secretOverriding, err := cmd.Flags().GetBool("secret-overriding") if err != nil { util.HandleError(err, "Unable to parse flag") @@ -93,6 +99,31 @@ var exportCmd = &cobra.Command{ request.UniversalAuthAccessToken = token.Token } + if templatePath != "" { + sigChan := make(chan os.Signal, 1) + dynamicSecretLeases := NewDynamicSecretLeaseManager(sigChan) + newEtag := "" + + accessToken := "" + if token != nil { + accessToken = token.Token + } else { + log.Debug().Msg("GetAllEnvironmentVariables: Trying to fetch secrets using logged in details") + loggedInUserDetails, err := util.GetCurrentLoggedInUserDetails() + if err != nil { + util.HandleError(err) + } + accessToken = loggedInUserDetails.UserCredentials.JTWToken + } + + processedTemplate, err := ProcessTemplate(1, templatePath, nil, accessToken, "", &newEtag, dynamicSecretLeases) + if err != nil { + util.HandleError(err) + } + fmt.Print(processedTemplate.String()) + return + } + secrets, err := util.GetAllEnvironmentVariables(request, "") if err != nil { util.HandleError(err, "Unable to fetch secrets") @@ -140,6 +171,7 @@ func init() { exportCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs") exportCmd.Flags().String("projectId", "", "manually set the projectId to fetch secrets from") exportCmd.Flags().String("path", "/", "get secrets within a folder path") + exportCmd.Flags().String("template", "", "The path to the template file used to render secrets") } // Format according to the format flag diff --git a/docs/cli/commands/export.mdx b/docs/cli/commands/export.mdx index 49446e734..91ed215ef 100644 --- a/docs/cli/commands/export.mdx +++ b/docs/cli/commands/export.mdx @@ -33,6 +33,9 @@ Export environment variables from the platform into a file format. # Export variables to a YAML file infisical export --format=yaml > secrets.yaml + + # Render secrets using a custom template file + infisical export --template= ``` ### Environment variables @@ -57,6 +60,26 @@ Export environment variables from the platform into a file format. ### flags + + The `--template` flag specifies the path to the template file used for rendering secrets. When using templates, you can omit the other format flags. + + ```text my-template-file + {{$secrets := secret "" "" ""}} + {{$length := len $secrets}} + {{- "{"}} + {{- with $secrets }} + {{- range $index, $secret := . }} + "{{ $secret.Key }}": "{{ $secret.Value }}"{{if lt $index (minus $length 1)}},{{end}} + {{- end }} + {{- end }} + {{ "}" -}} + ``` + + ```bash + # Example + infisical export --template="/path/to/template/file" + ``` + Used to set the environment that secrets are pulled from. diff --git a/docs/documentation/platform/dynamic-secrets/mysql.mdx b/docs/documentation/platform/dynamic-secrets/mysql.mdx new file mode 100644 index 000000000..c64edab63 --- /dev/null +++ b/docs/documentation/platform/dynamic-secrets/mysql.mdx @@ -0,0 +1,115 @@ +--- +title: "MySQL" +description: "Learn how to dynamically generate MySQL Database user passwords." +--- + +The Infisical MySQL dynamic secret allows you to generate MySQL Database credentials on demand based on configured role. + +## Prerequisite +Create a user with the required permission in your SQL instance. This user will be used to create new accounts on-demand. + + +## Set up Dynamic Secrets with MySQL + + + + Open the Secret Overview dashboard and select the environment in which you would like to add a dynamic secret. + + + ![Add Dynamic Secret Button](../../../images/platform/dynamic-secrets/add-dynamic-secret-button.png) + + + ![Dynamic Secret Modal](../../../images/platform/dynamic-secrets/dynamic-secret-modal.png) + + + + Name by which you want the secret to be referenced + + + + Default time-to-live for a generated secret (it is possible to modify this value when a secret is generate) + + + + Maximum time-to-live for a generated secret + + + + Choose the service you want to generate dynamic secrets for. This must be selected as **MySQL**. + + + + Database host + + + + Database port + + + + Username that will be used to create dynamic secrets + + + + Password that will be used to create dynamic secrets + + + + Name of the database for which you want to create dynamic secrets + + + + A CA may be required if your DB requires it for incoming connections. AWS RDS instances with default settings will requires a CA which can be downloaded [here](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html#UsingWithRDS.SSL.CertificatesAllRegions). + + + + + If you want to provide specific privileges for the generated dynamic credentials, you can modify the SQL statement to your needs. This is useful if you want to only give access to a specific table(s). + + ![Modify SQL Statements Modal](/images/platform/dynamic-secrets/modify-sql-statement-mysql.png) + + + After submitting the form, you will see a dynamic secret created in the dashboard. + + + If this step fails, you may have to add the CA certificate. + + + ![Dynamic Secret](/images/platform/dynamic-secrets/dynamic-secret.png) + + + Once you've successfully configured the dynamic secret, you're ready to generate on-demand credentials. + To do this, simply click on the 'Generate' button which appears when hovering over the dynamic secret item. + Alternatively, you can initiate the creation of a new lease by selecting 'New Lease' from the dynamic secret lease list section. + + ![Dynamic Secret](/images/platform/dynamic-secrets/dynamic-secret-generate.png) + ![Dynamic Secret](/images/platform/dynamic-secrets/dynamic-secret-lease-empty.png) + + When generating these secrets, it's important to specify a Time-to-Live (TTL) duration. This will dictate how long the credentials are valid for. + + ![Provision Lease](/images/platform/dynamic-secrets/provision-lease.png) + + + Ensure that the TTL for the lease fall within the maximum TTL defined when configuring the dynamic secret. + + + + Once you click the `Submit` button, a new secret lease will be generated and the credentials from it will be shown to you. + + ![Provision Lease](/images/platform/dynamic-secrets/lease-values.png) + + + +## Audit or Revoke Leases +Once you have created one or more leases, you will be able to access them by clicking on the respective dynamic secret item on the dashboard. +This will allow you see the expiration time of the lease or delete a lease before it's set time to live. + +![Provision Lease](/images/platform/dynamic-secrets/lease-data.png) + +## Renew Leases +To extend the life of the generated dynamic secret leases past its initial time to live, simply click on the **Renew** as illustrated below. +![Provision Lease](/images/platform/dynamic-secrets/dynamic-secret-lease-renew.png) + + + Lease renewals cannot exceed the maximum TTL set when configuring the dynamic secret + \ No newline at end of file diff --git a/docs/documentation/platform/dynamic-secrets/oracle.mdx b/docs/documentation/platform/dynamic-secrets/oracle.mdx new file mode 100644 index 000000000..05b832c4f --- /dev/null +++ b/docs/documentation/platform/dynamic-secrets/oracle.mdx @@ -0,0 +1,115 @@ +--- +title: "Oracle" +description: "Learn how to dynamically generate Oracle Database user passwords." +--- + +The Infisical Oracle dynamic secret allows you to generate Oracle Database credentials on demand based on configured role. + +## Prerequisite +Create a user with the required permission in your SQL instance. This user will be used to create new accounts on-demand. + + +## Set up Dynamic Secrets with Oracle + + + + Open the Secret Overview dashboard and select the environment in which you would like to add a dynamic secret. + + + ![Add Dynamic Secret Button](../../../images/platform/dynamic-secrets/add-dynamic-secret-button.png) + + + ![Dynamic Secret Modal](../../../images/platform/dynamic-secrets/dynamic-secret-modal.png) + + + + Name by which you want the secret to be referenced + + + + Default time-to-live for a generated secret (it is possible to modify this value when a secret is generate) + + + + Maximum time-to-live for a generated secret + + + + Choose the service you want to generate dynamic secrets for. This must be selected as **Oracle**. + + + + Database host + + + + Database port + + + + Username that will be used to create dynamic secrets + + + + Password that will be used to create dynamic secrets + + + + Name of the database for which you want to create dynamic secrets + + + + A CA may be required if your DB requires it for incoming connections. AWS RDS instances with default settings will requires a CA which can be downloaded [here](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html#UsingWithRDS.SSL.CertificatesAllRegions). + + + ![Dynamic Secret Setup Modal](../../../images/platform/dynamic-secrets/dynamic-secret-modal-oracle.png) + + + + If you want to provide specific privileges for the generated dynamic credentials, you can modify the SQL statement to your needs. This is useful if you want to only give access to a specific table(s). + + + After submitting the form, you will see a dynamic secret created in the dashboard. + + + If this step fails, you may have to add the CA certficate. + + + ![Dynamic Secret](../../../images/platform/dynamic-secrets/dynamic-secret.png) + + + Once you've successfully configured the dynamic secret, you're ready to generate on-demand credentials. + To do this, simply click on the 'Generate' button which appears when hovering over the dynamic secret item. + Alternatively, you can initiate the creation of a new lease by selecting 'New Lease' from the dynamic secret lease list section. + + ![Dynamic Secret](/images/platform/dynamic-secrets/dynamic-secret-generate.png) + ![Dynamic Secret](/images/platform/dynamic-secrets/dynamic-secret-lease-empty.png) + + When generating these secrets, it's important to specify a Time-to-Live (TTL) duration. This will dictate how long the credentials are valid for. + + ![Provision Lease](/images/platform/dynamic-secrets/provision-lease.png) + + + Ensure that the TTL for the lease fall within the maximum TTL defined when configuring the dynamic secret. + + + + Once you click the `Submit` button, a new secret lease will be generated and the credentials for it will be shown to you. + + ![Provision Lease](/images/platform/dynamic-secrets/lease-values.png) + + + +## Audit or Revoke Leases +Once you have created one or more leases, you will be able to access them by clicking on the respective dynamic secret item on the dashboard. +This will allow you see the expiration time of the lease or delete a lease before it's set time to live. + +![Provision Lease](/images/platform/dynamic-secrets/lease-data.png) + +## Renew Leases +To extend the life of the generated dynamic secret leases past its initial time to live, simply click on the **Renew** as illustrated below. +![Provision Lease](/images/platform/dynamic-secrets/dynamic-secret-lease-renew.png) + + + Lease renewals cannot exceed the maximum TTL set when configuring the dynamic secret + \ No newline at end of file diff --git a/docs/documentation/platform/dynamic-secrets/postgresql.mdx b/docs/documentation/platform/dynamic-secrets/postgresql.mdx index b7728b484..78ba87ee5 100644 --- a/docs/documentation/platform/dynamic-secrets/postgresql.mdx +++ b/docs/documentation/platform/dynamic-secrets/postgresql.mdx @@ -1,14 +1,13 @@ --- title: "PostgreSQL" -description: "Learn how to dynamically generate PostgreSQL Database user passwords." +description: "How to dynamically generate PostgreSQL database users" --- -The Infisical PostgreSQL secret rotation allows you to automatically rotate your PostgreSQL database user's password at a predefined interval. - +The Infisical PostgreSQL dynamic secret allows you to generate PostgreSQL database credentials on demand based on configured role. ## Prerequisite -1. Create a user with the required permission in your SQL instance. +Create a user with the required permission in your SQL instance. This user will be used to create new accounts on-demand. ## Set up Dynamic Secrets with PostgreSQL @@ -17,7 +16,7 @@ The Infisical PostgreSQL secret rotation allows you to automatically rotate your Open the Secret Overview dashboard and select the environment in which you would like to add a dynamic secret. - + ![Add Dynamic Secret Button](../../../images/platform/dynamic-secrets/add-dynamic-secret-button.png) @@ -37,7 +36,7 @@ The Infisical PostgreSQL secret rotation allows you to automatically rotate your - Choose the service you want to generate dynamic secrets for + Choose the service you want to generate dynamic secrets for. This must be selected as **PostgreSQL**. @@ -68,31 +67,52 @@ The Infisical PostgreSQL secret rotation allows you to automatically rotate your - If you want to provide specific privileges for the future generated dynamic secrets, you are able to specify them as SQL statements. + If you want to provide specific privileges for the generated dynamic credentials, you can modify the SQL statement to your needs. This is useful if you want to only give access to a specific table(s). ![Modify SQL Statements Modal](../../../images/platform/dynamic-secrets/modify-sql-statements.png) - - After submitting the form, you will see a dynamic secret creates in the dashboard. + + After submitting the form, you will see a dynamic secret created in the dashboard. - If this step fails, you might have to add the CA certficate. + If this step fails, you may have to add the CA certficate. ![Dynamic Secret](../../../images/platform/dynamic-secrets/dynamic-secret.png) - Now that the dynamic secret is created, you can start generating unique secret values by specifying the Time-to-live within the predefined range. + Once you've successfully configured the dynamic secret, you're ready to generate on-demand credentials. + To do this, simply click on the 'Generate' button which appears when hovering over the dynamic secret item. + Alternatively, you can initiate the creation of a new lease by selecting 'New Lease' from the dynamic secret lease list section. - ![Provision Lease](../../../images/platform/dynamic-secrets/provision-lease.png) + ![Dynamic Secret](/images/platform/dynamic-secrets/dynamic-secret-generate.png) + ![Dynamic Secret](/images/platform/dynamic-secrets/dynamic-secret-lease-empty.png) - After you click the `Submit` button, a new secret lease will be generated and the Database User and Database Password will be shown. + When generating these secrets, it's important to specify a Time-to-Live (TTL) duration. This will dictate how long the credentials are valid for. - ![Provision Lease](../../../images/platform/dynamic-secrets/lease-values.png) - - - As soon as you have generated a few secret leases, you will be able to access them by clicking `Generate` on the dynamic secret row. In this modal, you are able to see the expiration time or delete a secret preemptively. + ![Provision Lease](/images/platform/dynamic-secrets/provision-lease.png) - ![Provision Lease](../../../images/platform/dynamic-secrets/lease-data.png) + + Ensure that the TTL for the lease fall within the maximum TTL defined when configuring the dynamic secret. + + + + Once you click the `Submit` button, a new secret lease will be generated and the credentials for it will be shown to you. + + ![Provision Lease](/images/platform/dynamic-secrets/lease-values.png) + +## Audit or Revoke Leases +Once you have created one or more leases, you will be able to access them by clicking on the respective dynamic secret item on the dashboard. +This will allow you see the expiration time of the lease or delete the lease before it's set time to live. + +![Provision Lease](/images/platform/dynamic-secrets/lease-data.png) + +## Renew Leases +To extend the life of the generated dynamic secret leases past its initial time to live, simply click on the **Renew** as illustrated below. +![Provision Lease](/images/platform/dynamic-secrets/dynamic-secret-lease-renew.png) + + + Lease renewals cannot exceed the maximum TTL set when configuring the dynamic secret + \ No newline at end of file diff --git a/docs/images/platform/dynamic-secrets/dynamic-secret-generate.png b/docs/images/platform/dynamic-secrets/dynamic-secret-generate.png new file mode 100644 index 000000000..4a816614a Binary files /dev/null and b/docs/images/platform/dynamic-secrets/dynamic-secret-generate.png differ diff --git a/docs/images/platform/dynamic-secrets/dynamic-secret-lease-empty.png b/docs/images/platform/dynamic-secrets/dynamic-secret-lease-empty.png new file mode 100644 index 000000000..e6da94dcd Binary files /dev/null and b/docs/images/platform/dynamic-secrets/dynamic-secret-lease-empty.png differ diff --git a/docs/images/platform/dynamic-secrets/dynamic-secret-lease-renew.png b/docs/images/platform/dynamic-secrets/dynamic-secret-lease-renew.png new file mode 100644 index 000000000..e97554415 Binary files /dev/null and b/docs/images/platform/dynamic-secrets/dynamic-secret-lease-renew.png differ diff --git a/docs/images/platform/dynamic-secrets/dynamic-secret-modal-mysql.png b/docs/images/platform/dynamic-secrets/dynamic-secret-modal-mysql.png new file mode 100644 index 000000000..de4911d0d Binary files /dev/null and b/docs/images/platform/dynamic-secrets/dynamic-secret-modal-mysql.png differ diff --git a/docs/images/platform/dynamic-secrets/dynamic-secret-modal-oracle.png b/docs/images/platform/dynamic-secrets/dynamic-secret-modal-oracle.png new file mode 100644 index 000000000..053873a9c Binary files /dev/null and b/docs/images/platform/dynamic-secrets/dynamic-secret-modal-oracle.png differ diff --git a/docs/images/platform/dynamic-secrets/dynamic-secret.png b/docs/images/platform/dynamic-secrets/dynamic-secret.png index f08fc4c55..e1ec71fcd 100644 Binary files a/docs/images/platform/dynamic-secrets/dynamic-secret.png and b/docs/images/platform/dynamic-secrets/dynamic-secret.png differ diff --git a/docs/images/platform/dynamic-secrets/modify-sql-statement-mysql.png b/docs/images/platform/dynamic-secrets/modify-sql-statement-mysql.png new file mode 100644 index 000000000..8ad9fc0e3 Binary files /dev/null and b/docs/images/platform/dynamic-secrets/modify-sql-statement-mysql.png differ diff --git a/docs/images/platform/dynamic-secrets/modify-sql-statement-oracle.png b/docs/images/platform/dynamic-secrets/modify-sql-statement-oracle.png new file mode 100644 index 000000000..0874aa23d Binary files /dev/null and b/docs/images/platform/dynamic-secrets/modify-sql-statement-oracle.png differ diff --git a/docs/integrations/cloud/aws-parameter-store.mdx b/docs/integrations/cloud/aws-parameter-store.mdx index d54458db9..547387996 100644 --- a/docs/integrations/cloud/aws-parameter-store.mdx +++ b/docs/integrations/cloud/aws-parameter-store.mdx @@ -29,7 +29,8 @@ Prerequisites: "ssm:PutParameter", "ssm:DeleteParameter", "ssm:GetParametersByPath", - "ssm:DeleteParameters" + "ssm:DeleteParameters", + "ssm:AddTagsToResource" ], "Resource": "*" } diff --git a/docs/integrations/cloud/aws-secret-manager.mdx b/docs/integrations/cloud/aws-secret-manager.mdx index 0eab1a561..a0187644d 100644 --- a/docs/integrations/cloud/aws-secret-manager.mdx +++ b/docs/integrations/cloud/aws-secret-manager.mdx @@ -28,7 +28,8 @@ Prerequisites: "Action": [ "secretsmanager:GetSecretValue", "secretsmanager:CreateSecret", - "secretsmanager:UpdateSecret" + "secretsmanager:UpdateSecret", + "secretsmanager:TagResource" ], "Resource": "*" } diff --git a/docs/mint.json b/docs/mint.json index 114af99c3..97a262920 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -32,10 +32,7 @@ "thumbsRating": true }, "api": { - "baseUrl": [ - "https://app.infisical.com", - "http://localhost:8080" - ] + "baseUrl": ["https://app.infisical.com", "http://localhost:8080"] }, "topbarLinks": [ { @@ -142,7 +139,9 @@ "group": "Dynamic Secrets", "pages": [ "documentation/platform/dynamic-secrets/overview", - "documentation/platform/dynamic-secrets/postgresql" + "documentation/platform/dynamic-secrets/postgresql", + "documentation/platform/dynamic-secrets/mysql", + "documentation/platform/dynamic-secrets/oracle" ] }, "documentation/platform/groups" @@ -370,15 +369,11 @@ }, { "group": "Build Tool Integrations", - "pages": [ - "integrations/build-tools/gradle" - ] + "pages": ["integrations/build-tools/gradle"] }, { "group": "", - "pages": [ - "sdks/overview" - ] + "pages": ["sdks/overview"] }, { "group": "SDK's", @@ -396,22 +391,13 @@ "api-reference/overview/authentication", { "group": "Examples", - "pages": [ - "api-reference/overview/examples/integration" - ] + "pages": ["api-reference/overview/examples/integration"] } ] }, { "group": "Endpoints", "pages": [ - { - "group": "Users", - "pages": [ - "api-reference/endpoints/users/me", - "api-reference/endpoints/users/my-organizations" - ] - }, { "group": "Identities", "pages": [ @@ -457,7 +443,6 @@ "api-reference/endpoints/workspaces/list-identity-memberships", "api-reference/endpoints/workspaces/update-identity-membership", "api-reference/endpoints/workspaces/delete-identity-membership", - "api-reference/endpoints/workspaces/workspace-key", "api-reference/endpoints/workspaces/secret-snapshots", "api-reference/endpoints/workspaces/rollback-snapshot" ] @@ -535,15 +520,11 @@ }, { "group": "Service Tokens", - "pages": [ - "api-reference/endpoints/service-tokens/get" - ] + "pages": ["api-reference/endpoints/service-tokens/get"] }, { "group": "Audit Logs", - "pages": [ - "api-reference/endpoints/audit-logs/export-audit-log" - ] + "pages": ["api-reference/endpoints/audit-logs/export-audit-log"] } ] }, @@ -559,9 +540,7 @@ }, { "group": "", - "pages": [ - "changelog/overview" - ] + "pages": ["changelog/overview"] }, { "group": "Contributing", @@ -585,9 +564,7 @@ }, { "group": "Contributing to SDK", - "pages": [ - "contributing/sdk/developing" - ] + "pages": ["contributing/sdk/developing"] } ] } diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index 125f69421..4c1456d3b 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -143,8 +143,8 @@ Without email configuration, Infisical's core functions like sign-up/login and s SMTP_HOST=email-smtp.ap-northeast-1.amazonaws.com # SMTP endpoint obtained from SMTP settings SMTP_USERNAME=xxx # your SMTP username SMTP_PASSWORD=xxx # your SMTP password - SMTP_PORT=587 - SMTP_SECURE=false + SMTP_PORT=465 + SMTP_SECURE=true SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails SMTP_FROM_NAME=Infisical ``` diff --git a/frontend/src/hooks/api/dynamicSecret/types.ts b/frontend/src/hooks/api/dynamicSecret/types.ts index cab17bda1..4b2a736d3 100644 --- a/frontend/src/hooks/api/dynamicSecret/types.ts +++ b/frontend/src/hooks/api/dynamicSecret/types.ts @@ -21,7 +21,8 @@ export enum DynamicSecretProviders { export enum SqlProviders { Postgres = "postgres", - MySql = "mysql2" + MySql = "mysql2", + Oracle = "oracledb" } export type TDynamicSecretProvider = { diff --git a/frontend/src/hooks/api/integrations/queries.tsx b/frontend/src/hooks/api/integrations/queries.tsx index 80a2df6fa..7804f0951 100644 --- a/frontend/src/hooks/api/integrations/queries.tsx +++ b/frontend/src/hooks/api/integrations/queries.tsx @@ -63,6 +63,10 @@ export const useCreateIntegration = () => { secretSuffix?: string; initialSyncBehavior?: string; shouldAutoRedeploy?: boolean; + secretAWSTag?: { + key: string; + value: string; + }; }; }) => { const { diff --git a/frontend/src/pages/integrations/aws-parameter-store/create.tsx b/frontend/src/pages/integrations/aws-parameter-store/create.tsx index 23fb210a0..dd643023c 100644 --- a/frontend/src/pages/integrations/aws-parameter-store/create.tsx +++ b/frontend/src/pages/integrations/aws-parameter-store/create.tsx @@ -10,6 +10,7 @@ import { faCircleInfo } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { motion } from "framer-motion"; import queryString from "query-string"; import { useCreateIntegration } from "@app/hooks/api"; @@ -21,11 +22,21 @@ import { FormControl, Input, Select, - SelectItem + SelectItem, + Switch, + Tab, + TabList, + TabPanel, + Tabs } from "../../../components/v2"; import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth"; import { useGetWorkspaceById } from "../../../hooks/api/workspace"; +enum TabSections { + Connection = "connection", + Options = "options" +} + const awsRegions = [ { name: "US East (Ohio)", slug: "us-east-2" }, { name: "US East (N. Virginia)", slug: "us-east-1" }, @@ -76,6 +87,9 @@ export default function AWSParameterStoreCreateIntegrationPage() { const [pathErrorText, setPathErrorText] = useState(""); const [isLoading, setIsLoading] = useState(false); + const [shouldTag, setShouldTag] = useState(false); + const [tagKey, setTagKey] = useState(""); + const [tagValue, setTagValue] = useState(""); useEffect(() => { if (workspace) { @@ -110,7 +124,17 @@ export default function AWSParameterStoreCreateIntegrationPage() { sourceEnvironment: selectedSourceEnvironment, path, region: selectedAWSRegion, - secretPath + secretPath, + metadata: { + ...(shouldTag + ? { + secretAWSTag: { + key: tagKey, + value: tagValue + } + } + : {}) + } }); setIsLoading(false); @@ -157,56 +181,114 @@ export default function AWSParameterStoreCreateIntegrationPage() { - - setSelectedSourceEnvironment(val)} + className="w-full border border-mineshaft-500" + > + {workspace?.environments.map((sourceEnvironment) => ( + + {sourceEnvironment.name} + + ))} + + + + setSecretPath(evt.target.value)} + placeholder="Provide a path, default is /" + /> + + + + + - {sourceEnvironment.name} - - ))} - - - - setSecretPath(evt.target.value)} - placeholder="Provide a path, default is /" - /> - - - - - - setPath(e.target.value)} - /> - + setPath(e.target.value)} + /> + + + + + +
+ setShouldTag(!shouldTag)} + isChecked={shouldTag} + > + Tag in AWS Parameter Store + +
+ {shouldTag && ( +
+ + setTagKey(e.target.value)} + /> + + + setTagValue(e.target.value)} + /> + +
+ )} +
+
+