diff --git a/Dockerfile b/Dockerfile index 715f498b6..198ef0c4c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ ENV PUPPETEER_SKIP_DOWNLOAD=true ### Install toolchain ### RUN npm add --location=global pnpm@^8.0.0 # https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#node-gyp-alpine -RUN apk add --no-cache python3 make g++ +RUN apk add --no-cache python3 make g++ rsync COPY . . diff --git a/packages/core/package.json b/packages/core/package.json index 8b599e998..225c2ac3e 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -12,12 +12,12 @@ }, "scripts": { "precommit": "lint-staged", - "copyfiles": "copyfiles -u 1 src/routes/**/*.openapi.json build/", - "build": "rm -rf build/ && tsc -p tsconfig.build.json && pnpm run copyfiles", - "build:test": "rm -rf build/ && tsc -p tsconfig.test.json --sourcemap && pnpm run copyfiles", + "copy:apidocs": "rsync -a -m --include '*/' --include '*.openapi.json' --exclude '*' src/routes/ build/routes/", + "build": "rm -rf build/ && tsc -p tsconfig.build.json && pnpm run copy:apidocs", + "build:test": "rm -rf build/ && tsc -p tsconfig.test.json --sourcemap && pnpm run copy:apidocs", "lint": "eslint --ext .ts src", "lint:report": "pnpm lint --format json --output-file report.json", - "dev": "rm -rf build/ && pnpm run copyfiles && nodemon", + "dev": "rm -rf build/ && pnpm run copy:apidocs && nodemon", "start": "NODE_ENV=production node .", "test:only": "NODE_OPTIONS=\"--experimental-vm-modules --max_old_space_size=4096\" jest --logHeapUsage", "test": "pnpm build:test && pnpm test:only", @@ -80,8 +80,8 @@ "qrcode": "^1.5.3", "redis": "^4.6.5", "roarr": "^7.11.0", - "semver": "^7.3.8", "samlify": "2.8.10", + "semver": "^7.3.8", "slonik": "^30.0.0", "slonik-interceptor-preset": "^1.2.10", "slonik-sql-tag-raw": "^1.1.4", @@ -109,7 +109,6 @@ "@types/semver": "^7.3.12", "@types/sinon": "^10.0.13", "@types/supertest": "^2.0.11", - "copyfiles": "^2.4.1", "eslint": "^8.44.0", "jest": "^29.5.0", "jest-matcher-specific-error": "^1.0.0", diff --git a/packages/core/src/routes/organization/index.openapi.json b/packages/core/src/routes/organization/index.openapi.json index 07bb039b3..4e4786159 100644 --- a/packages/core/src/routes/organization/index.openapi.json +++ b/packages/core/src/routes/organization/index.openapi.json @@ -1,7 +1,7 @@ { "tags": [{ "name": "Organizations", - "description": "Organization is a concept that brings together multiple identities (mostly users). Logto supports multiple organizations, and each organization can have multiple users.\n\nEvery organization shares the same set (organization template) of roles and permissions. Each user can have different roles in different organizations.\n\nSee [this guide](https://docs.logto.io/docs/recipes/organizations) to learn more about organizations." + "description": "Organization is a concept that brings together multiple identities (mostly users). Logto supports multiple organizations, and each organization can have multiple users.\n\nEvery organization shares the same set (organization template) of roles and permissions. Each user can have different roles in different organizations." }], "paths": { "/api/organizations": { @@ -38,6 +38,11 @@ "name": "q", "in": "query", "description": "The query to filter organizations. It can be a partial ID or name.\n\nIf not provided, all organizations will be returned." + }, + { + "name": "showFeatured", + "in": "query", + "description": "Whether to show featured users in the organization. Featured users are randomly selected from the organization members.\n\nIf not provided, `featuredUsers` will not be included in the response." } ], "responses": { diff --git a/packages/core/src/routes/organization/roles.openapi.json b/packages/core/src/routes/organization/roles.openapi.json index 57b610af9..8dfcec86d 100644 --- a/packages/core/src/routes/organization/roles.openapi.json +++ b/packages/core/src/routes/organization/roles.openapi.json @@ -1,7 +1,7 @@ { "tags": [{ "name": "Organization roles", - "description": "Organization roles are used to define a set of organization scopes that can be assigned to users. Every organization role is a part of the organization template.\n\nOrganization roles will only be meaningful within an organization context. For example, a user may have an `admin` role for organization A, but not for organization B. To learn more about organization template and access control in organizations, see [this guide](/docs/rbac/organizations)." + "description": "Organization roles are used to define a set of organization scopes that can be assigned to users. Every organization role is a part of the organization template.\n\nOrganization roles will only be meaningful within an organization context. For example, a user may have an `admin` role for organization A, but not for organization B." }], "paths": { "/api/organization-roles": { diff --git a/packages/core/src/routes/organization/scopes.openapi.json b/packages/core/src/routes/organization/scopes.openapi.json index 087687654..93daf52b1 100644 --- a/packages/core/src/routes/organization/scopes.openapi.json +++ b/packages/core/src/routes/organization/scopes.openapi.json @@ -1,7 +1,7 @@ { "tags": [{ "name": "Organization scopes", - "description": "Organization scopes (permissions) are used to define actions that can be performed on a organization. Every organization scope is a part of the organization template.\n\nOrganization scopes will only be meaningful within an organization context. For example, a user may have a `read` scope for organization A, but not for organization B. To learn more about organization template and access control in organizations, see [this guide](/docs/rbac/organizations)." + "description": "Organization scopes (permissions) are used to define actions that can be performed on a organization. Every organization scope is a part of the organization template.\n\nOrganization scopes will only be meaningful within an organization context. For example, a user may have a `read` scope for organization A, but not for organization B." }], "paths": { "/api/organization-scopes": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4f4fce8d3..c856f1b1a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3368,15 +3368,12 @@ importers: '@types/supertest': specifier: ^2.0.11 version: 2.0.11 - copyfiles: - specifier: ^2.4.1 - version: 2.4.1 eslint: specifier: ^8.44.0 version: 8.44.0 jest: specifier: ^29.5.0 - version: 29.5.0(@types/node@18.11.18)(ts-node@10.9.1) + version: 29.5.0(@types/node@18.11.18) jest-matcher-specific-error: specifier: ^1.0.0 version: 1.0.0 @@ -7034,6 +7031,48 @@ packages: slash: 3.0.0 dev: true + /@jest/core@29.5.0: + resolution: {integrity: sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/console': 29.5.0 + '@jest/reporters': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.11.18 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.8.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.5.0 + jest-config: 29.5.0(@types/node@18.11.18) + jest-haste-map: 29.5.0 + jest-message-util: 29.5.0 + jest-regex-util: 29.4.3 + jest-resolve: 29.5.0 + jest-resolve-dependencies: 29.5.0 + jest-runner: 29.5.0 + jest-runtime: 29.5.0 + jest-snapshot: 29.5.0 + jest-util: 29.5.0 + jest-validate: 29.5.0 + jest-watcher: 29.5.0 + micromatch: 4.0.5 + pretty-format: 29.5.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color + - ts-node + dev: true + /@jest/core@29.5.0(ts-node@10.9.1): resolution: {integrity: sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -11244,14 +11283,6 @@ packages: strip-ansi: 6.0.1 wrap-ansi: 6.2.0 - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -11485,28 +11516,11 @@ packages: depd: 2.0.0 keygrip: 1.1.0 - /copyfiles@2.4.1: - resolution: {integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==} - hasBin: true - dependencies: - glob: 7.2.0 - minimatch: 3.1.2 - mkdirp: 1.0.4 - noms: 0.0.0 - through2: 2.0.5 - untildify: 4.0.0 - yargs: 16.2.0 - dev: true - /core-js@3.21.1: resolution: {integrity: sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==} requiresBuild: true dev: false - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - /cosmiconfig-typescript-loader@4.3.0(@types/node@18.11.18)(cosmiconfig@8.2.0)(ts-node@10.9.1)(typescript@5.0.2): resolution: {integrity: sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==} engines: {node: '>=12', npm: '>=6'} @@ -13488,17 +13502,6 @@ packages: is-glob: 4.0.3 dev: true - /glob@7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: @@ -14586,10 +14589,6 @@ packages: /isarray@0.0.1: resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true - /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true @@ -14679,6 +14678,34 @@ packages: - supports-color dev: true + /jest-cli@29.5.0(@types/node@18.11.18): + resolution: {integrity: sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/types': 29.5.0 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + import-local: 3.1.0 + jest-config: 29.5.0(@types/node@18.11.18) + jest-util: 29.5.0 + jest-validate: 29.5.0 + prompts: 2.4.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + /jest-cli@29.5.0(@types/node@18.11.18)(ts-node@10.9.1): resolution: {integrity: sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -14707,6 +14734,45 @@ packages: - ts-node dev: true + /jest-config@29.5.0(@types/node@18.11.18): + resolution: {integrity: sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.20.2 + '@jest/test-sequencer': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.11.18 + babel-jest: 29.5.0(@babel/core@7.20.2) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.5.0 + jest-environment-node: 29.5.0 + jest-get-type: 29.4.3 + jest-regex-util: 29.4.3 + jest-resolve: 29.5.0 + jest-runner: 29.5.0 + jest-util: 29.5.0 + jest-validate: 29.5.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.5.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /jest-config@29.5.0(@types/node@18.11.18)(ts-node@10.9.1): resolution: {integrity: sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -15118,6 +15184,26 @@ packages: supports-color: 8.1.1 dev: true + /jest@29.5.0(@types/node@18.11.18): + resolution: {integrity: sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.5.0 + '@jest/types': 29.5.0 + import-local: 3.1.0 + jest-cli: 29.5.0(@types/node@18.11.18) + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + /jest@29.5.0(@types/node@18.11.18)(ts-node@10.9.1): resolution: {integrity: sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -16619,6 +16705,7 @@ packages: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} hasBin: true + dev: false /module-details-from-path@1.0.3: resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} @@ -16855,13 +16942,6 @@ packages: undefsafe: 2.0.5 dev: true - /noms@0.0.0: - resolution: {integrity: sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=} - dependencies: - inherits: 2.0.4 - readable-stream: 1.0.34 - dev: true - /nopt@1.0.10: resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} hasBin: true @@ -17854,10 +17934,6 @@ packages: engines: {node: '>=6'} dev: true - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true - /process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} @@ -18479,27 +18555,6 @@ packages: strip-bom: 3.0.0 dev: true - /readable-stream@1.0.34: - resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 0.0.1 - string_decoder: 0.10.31 - dev: true - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -18921,10 +18976,6 @@ packages: dependencies: tslib: 2.5.0 - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -19571,16 +19622,6 @@ packages: es-abstract: 1.20.4 dev: true - /string_decoder@0.10.31: - resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} - dev: true - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: true - /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: @@ -20118,13 +20159,6 @@ packages: engines: {node: '>=0.2.6'} dev: false - /through2@2.0.5: - resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} - dependencies: - readable-stream: 2.3.8 - xtend: 4.0.2 - dev: true - /through2@3.0.2: resolution: {integrity: sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==} dependencies: @@ -20582,11 +20616,6 @@ packages: engines: {node: '>= 0.8'} dev: false - /untildify@4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} - dev: true - /update-browserslist-db@1.0.10(browserslist@4.21.4): resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} hasBin: true @@ -21027,19 +21056,6 @@ packages: y18n: 4.0.3 yargs-parser: 18.1.3 - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - dependencies: - cliui: 7.0.4 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - dev: true - /yargs@17.6.0: resolution: {integrity: sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==} engines: {node: '>=12'}