diff --git a/.github/workflows/tagging.yaml b/.github/workflows/tagging.yaml index f985489..24e7c7d 100644 --- a/.github/workflows/tagging.yaml +++ b/.github/workflows/tagging.yaml @@ -11,18 +11,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Setup node 18.x - uses: actions/setup-node@v3 + + - uses: TriPSs/conventional-changelog-action@v3 + name: Changelog + id: changelog with: - node-version: 18.x - cache: "npm" - - name: Git Identity - run: | - git checkout dev - git fetch --all --tags - git config --global user.email "antoniojosedonishung@gmail.com" - git config --global user.name "Antonio Donis" - - name: Changelog - run: 'npx standard-version --message "[ci skip] chore(release): %s"' - - name: Push changes - run: git push --follow-tags --force origin dev \ No newline at end of file + git-user-name: "Antonio Donis" + git-user-email: "antoniojosedonishung@gmail.com" + git-message: "[ci skip] chore(release): {version}" + version-file: "version.json" \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8706aa5..a80a4f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,60 +1,45 @@ -# Changelog +## [0.8.1](https://github.com/hawks-atlanta/proxy-python/compare/v0.8.0...v0.8.1) (2023-10-14) -All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. -### 0.0.11 (2023-10-11) - -### 0.0.10 (2023-10-11) +### Bug Fixes +* **files:** Keep files extension ([#56](https://github.com/hawks-atlanta/proxy-python/issues/56)) ([624cc06](https://github.com/hawks-atlanta/proxy-python/commit/624cc06af6443602bc9b946c8fc7ee5376dbea2c)) -### Bug Fixes -* Enable all CORS origins ([#44](https://github.com/hawks-atlanta/proxy-python/issues/44)) ([9f8ad6a](https://github.com/hawks-atlanta/proxy-python/commit/9f8ad6ae4dee09b18bd7e1f44d36f0c0ee7f4ced)) -### 0.0.9 (2023-10-09) +# [0.8.0](https://github.com/hawks-atlanta/proxy-python/compare/v0.7.0...v0.8.0) (2023-10-14) ### Features -* Register endpoint ([#39](https://github.com/hawks-atlanta/proxy-python/issues/39)) ([38392d4](https://github.com/hawks-atlanta/proxy-python/commit/38392d476c718eacc7e70e0bed98de08f2f1d186)) +* file upload ([#53](https://github.com/hawks-atlanta/proxy-python/issues/53)) ([097d026](https://github.com/hawks-atlanta/proxy-python/commit/097d0267b4596ee8cea5f24e4b4ceaf019ff801d)) -### 0.0.8 (2023-10-09) -### 0.0.7 (2023-10-09) -### 0.0.6 (2023-10-08) +# [0.7.0](https://github.com/hawks-atlanta/proxy-python/compare/v0.6.0...v0.7.0) (2023-10-14) ### Features -* endpoint challenge ([#33](https://github.com/hawks-atlanta/proxy-python/issues/33)) ([ee78fb6](https://github.com/hawks-atlanta/proxy-python/commit/ee78fb6864d0f6616464439c5c177884e514cf29)) +* create a folder ([#52](https://github.com/hawks-atlanta/proxy-python/issues/52)) ([7aca7f2](https://github.com/hawks-atlanta/proxy-python/commit/7aca7f204ce10c37154bcf1ed716cd13ca02c142)) -### 0.0.5 (2023-10-04) -### Features - -* endpoint login ([#15](https://github.com/hawks-atlanta/proxy-python/issues/15)) ([4921ca1](https://github.com/hawks-atlanta/proxy-python/commit/4921ca11b886d950d7811f67ac573b7a9adc6831)) +# [0.6.0](https://github.com/hawks-atlanta/proxy-python/compare/v0.5.0...v0.6.0) (2023-10-13) -### 0.0.4 (2023-08-24) - -### 0.0.3 (2023-08-24) +### Features -### Bug Fixes +* Update password ([#51](https://github.com/hawks-atlanta/proxy-python/issues/51)) ([395b44b](https://github.com/hawks-atlanta/proxy-python/commit/395b44bf9223cf1126521f80ac0ae1796d2207de)) -* coverage pipeline correct xml format ([#7](https://github.com/hawks-atlanta/proxy-python/issues/7)) ([1002efa](https://github.com/hawks-atlanta/proxy-python/commit/1002efa3c86bcdc2e7954f8f9394780ac5f41198)) -### 0.0.2 (2023-08-23) -### 0.0.1 (2023-08-23) +# [0.5.0](https://github.com/hawks-atlanta/proxy-python/compare/v0.4.0...v0.5.0) (2023-10-13) ### Features -* docker-compose ([6e44d01](https://github.com/hawks-atlanta/frontend-python/commit/6e44d01abede6ace6b488c6131bc96bd3b884c6d)) +* Endpoint to rename a file ([#50](https://github.com/hawks-atlanta/proxy-python/issues/50)) ([b1e93fc](https://github.com/hawks-atlanta/proxy-python/commit/b1e93fc468187e15341161c3db1084559b64e93c)) -### Bug Fixes -* base flask repository ([3f8ea73](https://github.com/hawks-atlanta/frontend-python/commit/3f8ea739fc267bc3bf6dc15c4cf540c511fe9419)) diff --git a/docker-compose.yaml b/docker-compose.yaml index d48e5d2..38108fa 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -9,7 +9,7 @@ services: ports: - "127.0.0.1:8080:8080" environment: - METADATA_BASEURL: http://metadata:8080 + METADATA_BASEURL: http://metadata:8080/api/v1 AUTHENTICATION_BASEURL: http://authentication:8080 WORKER_HOST: worker WORKER_PORT: 1099 diff --git a/docs/spec.openapi.yaml b/docs/spec.openapi.yaml index b777cbe..388f036 100644 --- a/docs/spec.openapi.yaml +++ b/docs/spec.openapi.yaml @@ -10,7 +10,6 @@ info: tags: - name: Authentication - name: Account - - name: Authorization - name: Files paths: @@ -25,8 +24,8 @@ paths: schema: $ref: "#/components/schemas/credentials" responses: - "200": - description: Login succeed + "201": + description: Login succeeded content: application/json: schema: @@ -43,64 +42,36 @@ paths: application/json: schema: $ref: "#/components/schemas/statusResponse" - /account/register: - post: - tags: - - Authentication - description: Register the new user in the service - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/credentials" - responses: - "201": - description: Registration succeed - content: - application/json: - schema: - $ref: "#/components/schemas/authorization" - "409": - description: Username already registered - content: - application/json: - schema: - $ref: "#/components/schemas/statusResponse" - "500": - description: Internal error - content: - application/json: - schema: - $ref: "#/components/schemas/statusResponse" + /auth/refresh: post: tags: - - Authorization - security: - - bearer: [] + - Authentication + security: + - bearer: [] description: Verifies the received token is still valid responses: "200": - description: The current token is valid and a new token was obtained successfully. + description: The current token is valid, and a new token was obtained successfully. content: application/json: schema: type: object properties: - msg: + msg: type: string - example: "Login successfull" - token: + example: "Token refreshed successfully" + token: type: string - example: "{jwt}" + example: "{new_jwt}" "400": - description: JSON body wasn't given or was not valid. + description: JSON body wasn't given or was not valid. content: application/json: schema: $ref: "#/components/schemas/statusResponse" "401": - description: No authorization header was given. + description: No authorization header was given or the token is invalid. content: application/json: schema: @@ -111,32 +82,26 @@ paths: application/json: schema: $ref: "#/components/schemas/statusResponse" - /account/password: - patch: + + /account/register: + post: tags: - Account - description: Updates the username password + description: Register a new user in the service requestBody: content: application/json: schema: - allOf: - - $ref: "#/components/schemas/authorization" - - type: object - properties: - currentPassword: - type: string - newPassword: - type: string + $ref: "#/components/schemas/credentials" responses: - "200": - description: Password updated successfully + "201": + description: Registration successful content: application/json: schema: - $ref: "#/components/schemas/statusResponse" - "401": - description: Unauthorized + $ref: "#/components/schemas/authorization" + "409": + description: Username is already registered content: application/json: schema: @@ -148,71 +113,79 @@ paths: schema: $ref: "#/components/schemas/statusResponse" - /files: + /file/upload: post: tags: - Files - description: Create a new file + security: + - bearer: [] + description: Upload a file requestBody: content: multipart/form-data: schema: type: object properties: + file: + type: string + format: binary fileName: type: string + example: "picture" location: type: string - file: - type: string + example: "5295d524-aafc-407c-96ed-adae2cd5047a" responses: "201": - description: File created successfully - content: - application/json: - schema: - $ref: "#/components/schemas/statusResponse" - "401": - description: Not authorized + description: File upload successful content: application/json: schema: - $ref: "#/components/schemas/statusResponse" + type: object + properties: + fileUUID: + type: string "500": - description: Internal error + description: Internal Server Error content: application/json: schema: $ref: "#/components/schemas/statusResponse" - /folders: - post: + /file/download/{fileUUID}: + get: tags: - Files - description: Create a new folder - requestBody: - content: - application/json: - schema: - type: object - properties: - folderName: - type: string - location: - type: string #UUID + security: + - bearer: [] + description: Download a file by UUID + parameters: + - in: path + name: fileUUID + required: true + schema: + type: string + description: The UUID of the file to download responses: - "201": - description: Folder created successfully + "200": + description: File downloaded successfully content: - application/json: + application/file: schema: - $ref: "#/components/schemas/statusResponse" + type: string + format: binary "401": description: Not authorized content: application/json: schema: $ref: "#/components/schemas/statusResponse" + "404": + description: File not found + content: + application/json: + schema: + $ref: "#/components/schemas/statusResponse" "500": description: Internal error content: @@ -220,20 +193,32 @@ paths: schema: $ref: "#/components/schemas/statusResponse" - /files/shared: + /file/check/{fileUUID}: get: tags: - Files - description: Gets the list of shared files + security: + - bearer: [] + description: Check if the given file is ready + parameters: + - in: path + name: fileUUID + required: true + schema: + type: string responses: "200": - description: List of shared files obtained + description: The state of the file was retreived successfully content: application/json: schema: - type: array - items: - $ref: "#/components/schemas/fileDetailsShared" + allOf: + - $ref: "#/components/schemas/statusResponse" + type: object + properties: + ready: + type: boolean + example: true "401": description: Not authorized content: @@ -246,25 +231,33 @@ paths: application/json: schema: $ref: "#/components/schemas/statusResponse" - /files/{fileId}/edit: - put: + + /file/{fileUUID}/move: + patch: tags: - Files - description: Edit an existing file + security: + - bearer: [] + description: Move an existing file to a different location parameters: - in: path - name: fileId - required: true - schema: - type: string - - in: query - name: newContent + name: fileUUID required: true schema: type: string + description: The ID of the file to move + requestBody: + content: + application/json: + schema: + type: object + properties: + targetDirectoryUUID: + type: string + example: "fbef8fdb-d16e-436b-8835-b96091b0b9ce" responses: "200": - description: File successfully edited + description: File moved successfully content: application/json: schema: @@ -281,20 +274,33 @@ paths: application/json: schema: $ref: "#/components/schemas/statusResponse" - /files/{fileId}: - delete: + + /file/{fileUUID}/rename: + patch: tags: - Files - description: Deletes an existing file + security: + - bearer: [] + description: Rename an existing file parameters: - in: path - name: fileId + name: fileUUID required: true schema: type: string + description: The ID of the file to rename + requestBody: + content: + application/json: + schema: + type: object + properties: + newName: + type: string + example: "new_file_name" responses: "200": - description: File successfully deleted + description: File renamed successfully content: application/json: schema: @@ -311,25 +317,24 @@ paths: application/json: schema: $ref: "#/components/schemas/statusResponse" - /files/{fileId}/move: - patch: + + /file/{fileUUID}: + delete: tags: - Files - description: Move an existing file to a different location + security: + - bearer: [] + description: Deletes an existing file by fileUUID parameters: - in: path - name: fileId - required: true - schema: - type: string - - in: query - name: newLocation + name: fileUUID required: true schema: type: string + description: The ID of the file to delete responses: "200": - description: File moved successfully + description: File successfully deleted content: application/json: schema: @@ -347,10 +352,12 @@ paths: schema: $ref: "#/components/schemas/statusResponse" - /files/list: + /file/list: get: tags: - Files + security: + - bearer: [] description: List files in a given location parameters: - in: query @@ -381,38 +388,28 @@ paths: schema: $ref: "#/components/schemas/statusResponse" - /files/download/{fileUUID}: + /file/shared: get: tags: - Files - description: Download a file by UUID - parameters: - - in: path - name: fileUUID - required: true - schema: - type: string - description: The UUID of the file to download + security: + - bearer: [] + description: Gets the list of shared files responses: "200": - description: File downloaded successfully + description: List of shared files obtained content: - application/octet-stream: + application/json: schema: - type: string - format: binary + type: array + items: + $ref: "#/components/schemas/fileDetailsShared" "401": description: Not authorized content: application/json: schema: $ref: "#/components/schemas/statusResponse" - "404": - description: File not found - content: - application/json: - schema: - $ref: "#/components/schemas/statusResponse" "500": description: Internal error content: @@ -420,10 +417,12 @@ paths: schema: $ref: "#/components/schemas/statusResponse" - /files/share: + /file/share: post: tags: - Files + security: + - bearer: [] description: Share a file with a user requestBody: content: @@ -462,10 +461,57 @@ paths: schema: $ref: "#/components/schemas/statusResponse" - /files/unshare: + /file/shared-with-who: + get: + tags: + - Files + security: + - bearer: [] + description: Get the list of users the file is shared with + parameters: + - in: query + name: fileUUID + required: true + schema: + type: string + responses: + "200": + description: List of users the file is shared with + content: + application/json: + schema: + type: object + properties: + users: + type: array + items: + type: string + example: sulcud + "401": + description: Not authorized + content: + application/json: + schema: + $ref: "#/components/schemas/statusResponse" + "404": + description: File not found + content: + application/json: + schema: + $ref: "#/components/schemas/statusResponse" + "500": + description: Internal error + content: + application/json: + schema: + $ref: "#/components/schemas/statusResponse" + + /file/unshare: post: tags: - Files + security: + - bearer: [] description: Unshare a file with a user requestBody: content: @@ -504,39 +550,69 @@ paths: schema: $ref: "#/components/schemas/statusResponse" - /files/sharedwithwho: - get: + /account/password: + patch: tags: - - Files - description: Get the list of users the file is shared with - parameters: - - in: query - name: fileUUID - required: true - schema: - type: string + - Account + security: + - bearer: [] + description: Updates the password + requestBody: + content: + application/json: + schema: + type: object + properties: + oldPassword: + type: string + newPassword: + type: string responses: "200": - description: List of users the file is shared with + description: Password updated successfully content: application/json: schema: - type: object - properties: - users: - type: array - items: - type: string - example: sulcud - + $ref: "#/components/schemas/statusResponse" "401": - description: Not authorized + description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/statusResponse" - "404": - description: File not found + "500": + description: Internal error + content: + application/json: + schema: + $ref: "#/components/schemas/statusResponse" + + /folders: + post: + tags: + - Files + security: + - bearer: [] + description: Create a new folder + requestBody: + content: + application/json: + schema: + type: object + properties: + folderName: + type: string + location: + type: string #UUID + responses: + "201": + description: Folder created successfully + content: + application/json: + schema: + $ref: "#/components/schemas/statusResponse" + "401": + description: Not authorized content: application/json: schema: @@ -550,16 +626,11 @@ paths: components: securitySchemes: - bearer: - type: http - scheme: bearer - bearerFormat: JWT + bearer: + type: http + scheme: bearer + bearerFormat: JWT schemas: - account: - type: object - properties: - uuid: - type: string statusResponse: type: object properties: @@ -579,30 +650,38 @@ components: properties: token: type: string + example: "{jwt}" fileDetails: type: object properties: - fileName: + name: type: string - fileSize: + example: "pixture.png" + size: type: integer + example: 4687 isFile: type: boolean - fileUUID: + uuid: type: string + example: "5295d524-aafc-407c-96ed-adae2cd5047a" fileDetailsShared: type: object properties: - fileName: + name: type: string - fileSize: + example: "pixture.png" + size: type: integer + example: 4687 isFile: type: boolean - fileUUID: + uuid: type: string + example: "5295d524-aafc-407c-96ed-adae2cd5047a" ownerusername: type: string + example: "CocoTheCat" shareWithReq: type: object properties: diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 9149c7d..0000000 --- a/package-lock.json +++ /dev/null @@ -1,2095 +0,0 @@ -{ - "name": "frontend-python", - "version": "0.0.11", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "version": "0.0.11", - "devDependencies": { - "git-semver-tags": "^4.1.1", - "standard-version": "^9.5.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", - "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.22.10", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", - "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", - "dev": true - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "engines": [ - "node >= 6.0" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/conventional-changelog": { - "version": "3.1.25", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.25.tgz", - "integrity": "sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ==", - "dev": true, - "dependencies": { - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-atom": "^2.0.8", - "conventional-changelog-codemirror": "^2.0.8", - "conventional-changelog-conventionalcommits": "^4.5.0", - "conventional-changelog-core": "^4.2.1", - "conventional-changelog-ember": "^2.0.9", - "conventional-changelog-eslint": "^3.0.9", - "conventional-changelog-express": "^2.0.6", - "conventional-changelog-jquery": "^3.0.11", - "conventional-changelog-jshint": "^2.0.9", - "conventional-changelog-preset-loader": "^2.3.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-atom": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", - "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-codemirror": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", - "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-config-spec": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", - "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", - "dev": true - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", - "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", - "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", - "dev": true, - "dependencies": { - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-parser": "^3.2.0", - "dateformat": "^3.0.0", - "get-pkg-repo": "^4.0.0", - "git-raw-commits": "^2.0.8", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.1", - "lodash": "^4.17.15", - "normalize-package-data": "^3.0.0", - "q": "^1.5.1", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-core/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/conventional-changelog-core/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/conventional-changelog-core/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/conventional-changelog-core/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/conventional-changelog-core/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/conventional-changelog-core/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/conventional-changelog-core/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/conventional-changelog-core/node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", - "dev": true, - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/conventional-changelog-core/node_modules/read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", - "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/conventional-changelog-core/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/conventional-changelog-core/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/conventional-changelog-ember": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", - "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-eslint": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", - "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-express": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", - "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-jquery": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", - "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-jshint": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", - "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-preset-loader": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", - "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-writer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", - "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", - "dev": true, - "dependencies": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-changelog-writer": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-filter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", - "dev": true, - "dependencies": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", - "dev": true, - "dependencies": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-recommended-bump": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", - "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", - "dev": true, - "dependencies": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.7", - "conventional-commits-parser": "^3.2.0", - "git-raw-commits": "^2.0.8", - "git-semver-tags": "^4.1.1", - "meow": "^8.0.0", - "q": "^1.5.1" - }, - "bin": { - "conventional-recommended-bump": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotgitignore": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", - "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", - "dev": true, - "dependencies": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - }, - "bin": { - "get-pkg-repo": "src/cli.js" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-pkg-repo/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/get-pkg-repo/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/get-pkg-repo/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/get-pkg-repo/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", - "dev": true, - "dependencies": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", - "dev": true, - "dependencies": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/git-semver-tags": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", - "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", - "dev": true, - "dependencies": { - "meow": "^8.0.0", - "semver": "^6.0.0" - }, - "bin": { - "git-semver-tags": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", - "dev": true, - "dependencies": { - "ini": "^1.3.2" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", - "dev": true, - "dependencies": { - "text-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "dev": true, - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/standard-version": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.5.0.tgz", - "integrity": "sha512-3zWJ/mmZQsOaO+fOlsa0+QK90pwhNd042qEcw6hKFNoLFs7peGyvPffpEBbK/DSGPbyOvli0mUIFv5A4qTjh2Q==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "conventional-changelog": "3.1.25", - "conventional-changelog-config-spec": "2.1.0", - "conventional-changelog-conventionalcommits": "4.6.3", - "conventional-recommended-bump": "6.1.0", - "detect-indent": "^6.0.0", - "detect-newline": "^3.1.0", - "dotgitignore": "^2.1.0", - "figures": "^3.1.0", - "find-up": "^5.0.0", - "git-semver-tags": "^4.0.0", - "semver": "^7.1.1", - "stringify-package": "^1.0.1", - "yargs": "^16.0.0" - }, - "bin": { - "standard-version": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/standard-version/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/standard-version/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/standard-version/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/standard-version/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/standard-version/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/stringify-package": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", - "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", - "deprecated": "This module is not used anymore, and has been replaced by @npmcli/package-json", - "dev": true - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true - }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 90587f1..0000000 --- a/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "devDependencies": { - "git-semver-tags": "^4.1.1", - "standard-version": "^9.5.0" - }, - "version": "0.0.11" -} diff --git a/src/controllers/_authentication_controllers.py b/src/controllers/_authentication_controllers.py deleted file mode 100644 index d0cb32a..0000000 --- a/src/controllers/_authentication_controllers.py +++ /dev/null @@ -1,42 +0,0 @@ -from flask import request -from src.config.soap_client import soap_client - - -def login_handler(): - try: - data = request.json - username = data.get("username") - password = data.get("password") - if not username or not password: - return {"msg": "Required fields are missing in JSON data"}, 400 - - result = soap_client.service.auth_login( - {"username": username, "password": password} - ) - - if result.auth is not None: - jwt = result.auth.token - return {"msg": "Login successful", "token": jwt}, 200 - - return {"msg": "Invalid credentials"}, 401 - - except Exception as e: - print("[Exception] login_handler ->", str(e)) - return {"msg": "Internal error", "error": str(e)}, 500 - - -def challenge_handler(token): - try: - response = soap_client.service.auth_refresh({"token": token}) - if hasattr(response.auth, "token"): - refreshed_token = response.auth.token - return { - "msg": "JWT refreshed successfully", - "token": refreshed_token, - }, 200 - else: - return {"msg": response.msg}, response.code - - except Exception as e: - print("[Exception] challenge ->", str(e)) - return {"msg": "Internal error: " + str(e)}, 500 diff --git a/src/controllers/account/__init__.py b/src/controllers/account/__init__.py new file mode 100644 index 0000000..7cf62d6 --- /dev/null +++ b/src/controllers/account/__init__.py @@ -0,0 +1,7 @@ +from .register_user._handler import register_handler +from .update_password._handler import update_password_handler + +ACCOUNT_HANDLERS = { + "REGISTER": register_handler, + "UPDATE_PASSWORD": update_password_handler, +} diff --git a/src/controllers/_account_controllers.py b/src/controllers/account/register_user/_handler.py similarity index 64% rename from src/controllers/_account_controllers.py rename to src/controllers/account/register_user/_handler.py index fc82a38..fce158d 100644 --- a/src/controllers/_account_controllers.py +++ b/src/controllers/account/register_user/_handler.py @@ -1,3 +1,4 @@ +import json from flask import request from src.config.soap_client import soap_client @@ -5,15 +6,13 @@ def register_handler(): try: # Get JSON data from the request - data = request.json - - if not data: - return {"msg": "No JSON data provided in the request"}, 400 - + data = json.loads(request.data) username = data.get("username") password = data.get("password") - if not username or not password: + not_valid_username = not username or len(username) == 0 + not_valid_password = not password or len(password) == 0 + if not_valid_username or not_valid_password: return {"msg": "Required fields are missing in JSON data"}, 400 result = soap_client.service.account_register( @@ -26,6 +25,9 @@ def register_handler(): return {"msg": "Username already registered"}, 409 + except ValueError: + return {"msg": "Invalid JSON data provided in the request"}, 400 + except Exception as e: print("[Exception] register_handler ->", str(e)) - return {"msg": "Internal error", "error": str(e)}, 500 + return {"msg": "There was an error registering the user"}, 500 diff --git a/src/views/_account_views_test.py b/src/controllers/account/register_user/_register_user_test.py similarity index 89% rename from src/views/_account_views_test.py rename to src/controllers/account/register_user/_register_user_test.py index 2d37c36..da3be2f 100644 --- a/src/views/_account_views_test.py +++ b/src/controllers/account/register_user/_register_user_test.py @@ -2,6 +2,7 @@ from main import app from src.lib.faker import fake_username, fake_password + register_test_data = {"username": fake_username(), "password": fake_password()} @@ -20,11 +21,11 @@ def test_account_register_successful() -> None: def test_account_register_missing_fields() -> None: # Empty json - data = {} - response = app.test_client().post("/account/register", json=data) - + response = app.test_client().post("/account/register") assert response.status_code == 400 - assert json.loads(response.data)["msg"] == "No JSON data provided in the request" + assert ( + json.loads(response.data)["msg"] == "Invalid JSON data provided in the request" + ) # Missing password data = {"username": register_test_data["username"]} diff --git a/src/controllers/account/update_password/_handler.py b/src/controllers/account/update_password/_handler.py new file mode 100644 index 0000000..0a0d365 --- /dev/null +++ b/src/controllers/account/update_password/_handler.py @@ -0,0 +1,29 @@ +import json +from flask import request +from src.config.soap_client import soap_client + + +def update_password_handler(token): + try: + data = json.loads(request.data) + oldPassword = data.get("oldPassword") + newPassword = data.get("newPassword") + + if not oldPassword or not newPassword or not token: + return {"msg": "Required fields are missing in JSON data"}, 400 + + result = soap_client.service.account_password( + {"oldpassword": oldPassword, "newpassword": newPassword, "token": token} + ) + + if result["error"] is True: + return {"msg": result["msg"]}, result["code"] + else: + return {"msg": "Password updated successfully"}, 200 + + except ValueError: + return {"msg": "Invalid JSON data provided in the request"}, 400 + + except Exception as e: + print("[Exception] password_handler ->", str(e)) + return {"msg": "Internal error", "error": str(e)}, 500 diff --git a/src/controllers/account/update_password/_update_password_test.py b/src/controllers/account/update_password/_update_password_test.py new file mode 100644 index 0000000..c5e4900 --- /dev/null +++ b/src/controllers/account/update_password/_update_password_test.py @@ -0,0 +1,97 @@ +import json +from main import app + +from src.config.soap_client import soap_client +from src.lib.faker import fake_username, fake_password + + +update_password_test_data = {"username": fake_username(), "password": fake_password()} + + +def test_update_password_success() -> None: + # Register test user + register_response = soap_client.service.account_register( + { + "username": update_password_test_data["username"], + "password": update_password_test_data["password"], + } + ) + assert register_response.error is False + + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": update_password_test_data["username"], + "password": update_password_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Update the password + change_data = { + "oldPassword": update_password_test_data["password"], + "newPassword": "Andrea2", + } + response = app.test_client().patch( + "/account/password", + json=change_data, + headers={ + "Authorization": f"Bearer {token}", + }, + ) + + assert response.status_code == 200 + assert json.loads(response.data)["msg"] == "Password updated successfully" + update_password_test_data["password"] = change_data["newPassword"] + + +def test_update_password_missing_fields() -> None: + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": update_password_test_data["username"], + "password": update_password_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # No JSON + response = app.test_client().patch( + "/account/password", headers={"Authorization": f"Bearer {token}"} + ) + + assert response.status_code == 400 + assert ( + json.loads(response.data)["msg"] == "Invalid JSON data provided in the request" + ) + + # Missing fields + data = {} + response = app.test_client().patch( + "/account/password", + json=data, + headers={ + "Authorization": f"Bearer {token}", + }, + ) + + assert response.status_code == 400 + assert ( + json.loads(response.data)["msg"] == "Required fields are missing in JSON data" + ) + + +def test_update_password_not_valid_token() -> None: + change_data = {"oldPassword": "Andrea1", "newPassword": "Andrea2"} + response = app.test_client().patch( + "/account/password", + json=change_data, + headers={ + "Authorization": "Bearer 123", + }, + ) + + assert response.status_code == 401 + assert json.loads(response.data)["msg"] == "unauthorized" diff --git a/src/controllers/authentication/__init__.py b/src/controllers/authentication/__init__.py new file mode 100644 index 0000000..93b3416 --- /dev/null +++ b/src/controllers/authentication/__init__.py @@ -0,0 +1,4 @@ +from .login._handler import login_handler +from .refresh._handler import challenge_handler + +AUTHENTICATION_HANDLERS = {"LOGIN": login_handler, "REFRESH": challenge_handler} diff --git a/src/controllers/authentication/login/_handler.py b/src/controllers/authentication/login/_handler.py new file mode 100644 index 0000000..3644f07 --- /dev/null +++ b/src/controllers/authentication/login/_handler.py @@ -0,0 +1,32 @@ +import json +from flask import request +from src.config.soap_client import soap_client + + +def login_handler(): + try: + data = json.loads(request.data) + username = data.get("username") + password = data.get("password") + + not_valid_username = not username or len(username) == 0 + not_valid_password = not password or len(password) == 0 + if not_valid_username or not_valid_password: + return {"msg": "Required fields are missing in JSON data"}, 400 + + result = soap_client.service.auth_login( + {"username": username, "password": password} + ) + + if result.auth is not None: + jwt = result.auth.token + return {"msg": "Login successful", "token": jwt}, 200 + + return {"msg": "Invalid credentials"}, 401 + + except ValueError: + return {"msg": "Invalid JSON data provided in the request"}, 400 + + except Exception as e: + print("[Exception] login_handler ->", str(e)) + return {"msg": "There was an error logging in"}, 500 diff --git a/src/controllers/authentication/login/_login_test.py b/src/controllers/authentication/login/_login_test.py new file mode 100644 index 0000000..082fc9e --- /dev/null +++ b/src/controllers/authentication/login/_login_test.py @@ -0,0 +1,44 @@ +import json +from main import app + +from src.config.soap_client import soap_client +from src.lib.faker import fake_username, fake_password + + +def test_auth_login_successful() -> None: + test_data = {"username": fake_username(), "password": fake_password()} + + registration_data = { + "username": test_data["username"], + "password": test_data["password"], + } + registration_result = soap_client.service.account_register(registration_data) + assert registration_result.error is False + + login_data = {"username": test_data["username"], "password": test_data["password"]} + response = app.test_client().post("/auth/login", json=login_data) + assert response.status_code == 200 + + json_response = json.loads(response.data) + assert json_response["msg"] != "" + assert json_response["token"] != "" + + +def test_auth_login_invalid_credentials() -> None: + data = {"username": "unexistent", "password": "password"} + response = app.test_client().post("/auth/login", json=data) + json_response = json.loads(response.data) + + assert response.status_code == 401 + assert json_response["msg"] == "Invalid credentials" + + +def test_auth_login_missing_fields() -> None: + # No JSON + response = app.test_client().post("/auth/login") + assert response.status_code == 400 + + # Missing field + data = {"username": "miguel"} + response = app.test_client().post("/auth/login", json=data) + assert response.status_code == 400 diff --git a/src/controllers/authentication/refresh/_handler.py b/src/controllers/authentication/refresh/_handler.py new file mode 100644 index 0000000..9c962ec --- /dev/null +++ b/src/controllers/authentication/refresh/_handler.py @@ -0,0 +1,18 @@ +from src.config.soap_client import soap_client + + +def challenge_handler(token): + try: + response = soap_client.service.auth_refresh({"token": token}) + if hasattr(response.auth, "token"): + refreshed_token = response.auth.token + return { + "msg": "JWT refreshed successfully", + "token": refreshed_token, + }, 200 + else: + return {"msg": response.msg}, response.code + + except Exception as e: + print("[Exception] challenge ->", str(e)) + return {"msg": "There was an error validating or refreshing the session"}, 500 diff --git a/src/views/_authentication_views_test.py b/src/controllers/authentication/refresh/_refresh_test.py similarity index 61% rename from src/views/_authentication_views_test.py rename to src/controllers/authentication/refresh/_refresh_test.py index 5b836a8..ed175b1 100644 --- a/src/views/_authentication_views_test.py +++ b/src/controllers/authentication/refresh/_refresh_test.py @@ -1,45 +1,8 @@ import json from main import app -from config.soap_client import soap_client -from src.lib.faker import fake_username, fake_password - - -def test_auth_login_successful() -> None: - test_data = {"username": fake_username(), "password": fake_password()} - - registration_data = { - "username": test_data["username"], - "password": test_data["password"], - } - registration_result = soap_client.service.account_register(registration_data) - assert registration_result.error is False - login_data = {"username": test_data["username"], "password": test_data["password"]} - response = app.test_client().post("/auth/login", json=login_data) - assert response.status_code == 200 - - json_response = json.loads(response.data) - assert json_response["msg"] != "" - assert json_response["token"] != "" - - -def test_auth_login_invalid_credentials() -> None: - data = {"username": "unexistent", "password": "password"} - response = app.test_client().post("/auth/login", json=data) - json_response = json.loads(response.data) - - assert response.status_code == 401 - assert json_response["msg"] == "Invalid credentials" - - -def test_auth_login_missing_fields() -> None: - data = {"username": "miguel"} - response = app.test_client().post("/auth/login", json=data) - assert response.status_code == 400 - - data = {"password": "miguel"} - response = app.test_client().post("/auth/login", json=data) - assert response.status_code == 400 +from src.config.soap_client import soap_client +from src.lib.faker import fake_username, fake_password def test_auth_refresh_missing_token() -> None: diff --git a/src/controllers/files/__init__.py b/src/controllers/files/__init__.py new file mode 100644 index 0000000..8eb4833 --- /dev/null +++ b/src/controllers/files/__init__.py @@ -0,0 +1,11 @@ +from .check_file_status._handler import check_state_handler +from .rename_file._handler import rename_handler +from .create_directory._handler import create_new_dir_handler +from .upload_file._handler import upload_file_handler + +FILES_HANDLERS = { + "CHECK_STATE": check_state_handler, + "RENAME": rename_handler, + "CREATE_DIRECTORY": create_new_dir_handler, + "UPLOAD": upload_file_handler, +} diff --git a/src/controllers/files/check_file_status/_check_file_status_test.py b/src/controllers/files/check_file_status/_check_file_status_test.py new file mode 100644 index 0000000..744fa56 --- /dev/null +++ b/src/controllers/files/check_file_status/_check_file_status_test.py @@ -0,0 +1,90 @@ +import json +from uuid import uuid4 +from random import randbytes +from main import app + +from src.config.soap_client import soap_client +from src.lib.faker import fake_username, fake_password + + +# GET STATUS TESTS +get_status_test_data = { + "username": fake_username(), + "password": fake_password(), + "file": { + "name": "test_file.txt", + "content": randbytes(1024), + }, +} + + +def test_get_status_not_success_code(): + # Register an user + register_response = soap_client.service.account_register( + { + "username": get_status_test_data["username"], + "password": get_status_test_data["password"], + } + ) + assert register_response.error is False + + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": get_status_test_data["username"], + "password": get_status_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Try to get status of the file + random_file_uuid = uuid4() + response = soap_client.service.file_check( + {"token": token, "fileUUID": random_file_uuid} + ) + + assert response.code == 404 + assert response.msg == f"There is no file with the {random_file_uuid} UUID" + + +def test_get_status_success_code(): + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": get_status_test_data["username"], + "password": get_status_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Upload a file + upload_response = soap_client.service.file_upload( + { + "token": token, + "fileName": get_status_test_data["file"]["name"], + "fileContent": get_status_test_data["file"]["content"], + "location": None, + } + ) + assert upload_response.error is False + + # Get status of the file + response = app.test_client().get( + f"/file/{upload_response.fileUUID}/status", + headers={"Authorization": f"Bearer {token}"}, + ) + + has_expected_success_code = ( + response.status_code == 200 or response.status_code == 202 + ) + assert has_expected_success_code + + json_response = json.loads(response.data) + has_boolean_ready = ( + json_response["ready"] is True or json_response["ready"] is False + ) + assert has_boolean_ready + + assert json_response["msg"] == "File status has been obtained successfully" diff --git a/src/controllers/files/check_file_status/_handler.py b/src/controllers/files/check_file_status/_handler.py new file mode 100644 index 0000000..49696f6 --- /dev/null +++ b/src/controllers/files/check_file_status/_handler.py @@ -0,0 +1,20 @@ +from src.config.soap_client import soap_client + + +def check_state_handler(token, file_uuid): + try: + response = soap_client.service.file_check( + {"token": token, "fileUUID": file_uuid} + ) + + has_success_code = str(response.code).startswith("20") + if not has_success_code: + return {"msg": response.msg}, response.code + + return { + "msg": "File status has been obtained successfully", + "ready": response.ready, + }, response.code + except Exception as e: + print("[Exception] check_state_handler ->", str(e)) + return {"msg": "There was an error checking the file state"}, 500 diff --git a/src/controllers/files/create_directory/_create_directory_test.py b/src/controllers/files/create_directory/_create_directory_test.py new file mode 100644 index 0000000..7937f0e --- /dev/null +++ b/src/controllers/files/create_directory/_create_directory_test.py @@ -0,0 +1,103 @@ +import json +from main import app + +from src.config.soap_client import soap_client +from src.lib.faker import fake_username, fake_password + + +# CREATE FOLDER TEST +test_folders = { + "username": fake_username(), + "password": fake_password(), + "folder": { + "directoryName": "test-directory232", + "location": "test-location232", + "token": "test-token232", + }, +} + + +def test_createfolder_bad_request(): + # Register an user + register_response = soap_client.service.account_register( + { + "username": test_folders["username"], + "password": test_folders["password"], + } + ) + assert register_response.error is False + + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": test_folders["username"], + "password": test_folders["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # No JSON (400 Bad Request) + response = app.test_client().post( + "/folders", + headers={"Authorization": f"Bearer {token}"}, + ) + assert response.status_code == 400 + + # Empty directory name (400 Bad Request) + response = app.test_client().post( + "/folders", + json={"directoryName": ""}, + headers={"Authorization": f"Bearer {token}"}, + ) + assert response.status_code == 400 + + +def test_createfolder_success(): + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": test_folders["username"], + "password": test_folders["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Create a folder + create_folder_response = app.test_client().post( + "/folders", + json={ + "directoryName": test_folders["folder"]["directoryName"], + "location": test_folders["folder"]["location"], + }, + headers={"Authorization": f"Bearer {token}"}, + ) + + assert create_folder_response.status_code == 201 + + +def test_createfolder_duplicate(): + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": test_folders["username"], + "password": test_folders["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Create a folder with a duplicate name + create_folder_response = app.test_client().post( + "/folders", + json={ + "directoryName": test_folders["folder"]["directoryName"], + "location": test_folders["folder"]["location"], + }, + headers={"Authorization": f"Bearer {token}"}, + ) + + # already exists + assert create_folder_response.status_code == 409 + json.loads(create_folder_response.data) diff --git a/src/controllers/files/create_directory/_handler.py b/src/controllers/files/create_directory/_handler.py new file mode 100644 index 0000000..c4e5626 --- /dev/null +++ b/src/controllers/files/create_directory/_handler.py @@ -0,0 +1,37 @@ +import json +from flask import request +from src.config.soap_client import soap_client + + +def create_new_dir_handler(token): + try: + data = json.loads(request.data) + + directoryName = data.get("directoryName") + location = data.get("location") + + if not directoryName or not location: + return {"msg": "Required fields are missing in JSON data"}, 400 + + response = soap_client.service.file_new_dir( + { + "directoryName": directoryName, + "location": location, + "token": token, + } + ) + + if response["error"] is True: + return {"msg": response["msg"]}, response["code"] + else: + return { + "msg": "New directory created successfully", + "directoryUUID": response["fileUUID"], + }, response["code"] + + except ValueError: + return {"msg": "Invalid JSON data provided in the request"}, 400 + + except Exception as e: + print("[Exception] create_new_directory ->", str(e)) + return {"msg": "There was an error creating the new directory"}, 500 diff --git a/src/controllers/files/rename_file/_handler.py b/src/controllers/files/rename_file/_handler.py new file mode 100644 index 0000000..0ef312a --- /dev/null +++ b/src/controllers/files/rename_file/_handler.py @@ -0,0 +1,25 @@ +import json +from flask import request +from src.config.soap_client import soap_client + + +def rename_handler(token, file_uuid): + try: + data = json.loads(request.data) + new_name = data["newName"] + if not new_name or len(new_name) == 0: + return {"msg": "New name is required"}, 400 + + request_data = {"token": token, "fileUUID": file_uuid, "newName": new_name} + response = soap_client.service.file_rename(request_data) + + if response["error"] is True: + return {"msg": response["msg"]}, response["code"] + else: + return {"msg": "The file has been renamed successfully"}, 200 + + except ValueError: + return {"msg": "Invalid JSON data provided in the request"}, 400 + + except Exception: + return {"msg": "There was an error renaming the file"}, 500 diff --git a/src/controllers/files/rename_file/_rename_file_test.py b/src/controllers/files/rename_file/_rename_file_test.py new file mode 100644 index 0000000..69c4686 --- /dev/null +++ b/src/controllers/files/rename_file/_rename_file_test.py @@ -0,0 +1,112 @@ +import json +from random import randbytes +from main import app + +from src.config.soap_client import soap_client +from src.lib.faker import fake_username, fake_password + +# RENAME FILE TESTS +rename_test_data = { + "username": fake_username(), + "password": fake_password(), + "file": { + "uuid": None, + "name": "test.txt", + "content": randbytes(1024), + }, +} + + +def test_rename_bad_request(): + # Register an user + register_response = soap_client.service.account_register( + { + "username": rename_test_data["username"], + "password": rename_test_data["password"], + } + ) + assert register_response.error is False + + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": rename_test_data["username"], + "password": rename_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # No JSON + response = app.test_client().patch( + f"/file/{rename_test_data['file']['uuid']}/rename", + headers={"Authorization": f"Bearer {token}"}, + ) + assert response.status_code == 400 + + # Empty file name + response = app.test_client().patch( + f"/file/{rename_test_data['file']['uuid']}/rename", + json={"newName": ""}, + headers={"Authorization": f"Bearer {token}"}, + ) + assert response.status_code == 400 + + +def test_rename_success(): + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": rename_test_data["username"], + "password": rename_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Upload a file + create_file_response = soap_client.service.file_upload( + { + "token": token, + "fileName": rename_test_data["file"]["name"], + "fileContent": rename_test_data["file"]["content"], + "location": None, + } + ) + assert create_file_response.error is False + + # Rename the file + new_name = "renamed.txt" + response = app.test_client().patch( + f"/file/{create_file_response.fileUUID}/rename", + json={"newName": new_name}, + headers={"Authorization": f"Bearer {token}"}, + ) + + json_response = json.loads(response.data) + assert response.status_code == 200 + assert json_response["msg"] == "The file has been renamed successfully" + + # Update the test data + rename_test_data["file"]["uuid"] = create_file_response.fileUUID + rename_test_data["file"]["name"] = new_name + + +def test_rename_conflict(): + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": rename_test_data["username"], + "password": rename_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Try to rename the file with the same name + response = app.test_client().patch( + f"/file/{rename_test_data['file']['uuid']}/rename", + json={"newName": rename_test_data["file"]["name"]}, + headers={"Authorization": f"Bearer {token}"}, + ) + assert response.status_code == 409 diff --git a/src/controllers/files/upload_file/_handler.py b/src/controllers/files/upload_file/_handler.py new file mode 100644 index 0000000..2ac618e --- /dev/null +++ b/src/controllers/files/upload_file/_handler.py @@ -0,0 +1,45 @@ +from flask import request +from werkzeug.utils import secure_filename +from src.config.soap_client import soap_client +from src.lib.helpers import is_valid_uuid + + +def upload_file_handler(token): + try: + if "file" not in request.files or "location" not in request.form: + return {"msg": "Required fields are missing in form data"}, 400 + + # Get file from request + file = request.files["file"] + + # Set null if file location is am empty string + fileLocation = request.form["location"] + fileLocation = None if fileLocation == "" else fileLocation + + # Check if fileLocation is a valid UUID + not_valid_location = fileLocation is not None and not is_valid_uuid( + fileLocation + ) + if not_valid_location: + return {"msg": "Not valid file location provided"}, 400 + + # Separate file name from extension + fileName = secure_filename(file.filename) + result = soap_client.service.file_upload( + { + "fileName": fileName, + "fileContent": file.read(), + "location": fileLocation, + "token": token, + } + ) + + if result.fileUUID is None: + return {"msg": result["msg"]}, result["code"] + + fileId = result.fileUUID + return {"msg": "The file is being uploaded", "fileUUID": fileId}, 201 + + except Exception as e: + print("[Exception] file_download_handler ->", str(e)) + return {"msg": "Internal error", "error": str(e)}, 500 diff --git a/src/controllers/files/upload_file/_upload_file_test.py b/src/controllers/files/upload_file/_upload_file_test.py new file mode 100644 index 0000000..7c03460 --- /dev/null +++ b/src/controllers/files/upload_file/_upload_file_test.py @@ -0,0 +1,119 @@ +import json +import os +from random import randbytes +from main import app + +from src.config.soap_client import soap_client +from src.lib.faker import fake_username, fake_password + +upload_file_test_data = { + "username": fake_username(), + "password": fake_password(), + "file": { + "name": "picture.jpeg", + "content": randbytes(1024), + }, +} + + +def test_file_upload_bad_request() -> None: + # Register an user + register_response = soap_client.service.account_register( + { + "username": upload_file_test_data["username"], + "password": upload_file_test_data["password"], + } + ) + assert register_response.error is False + + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": upload_file_test_data["username"], + "password": upload_file_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Write random file to disk + with open(f"./{upload_file_test_data['file']['name']}", "wb") as rf: + rf.write(upload_file_test_data["file"]["content"]) + + # Upload file with empty form data + response = app.test_client().post( + "/file/upload", + headers={"Authorization": f"Bearer {token}"}, + data={}, + ) + json_response = json.loads(response.data) + + assert response.status_code == 400 + assert json_response["msg"] == "Required fields are missing in form data" + + # Upload file with not valid location UUID + response = app.test_client().post( + "/file/upload", + headers={"Authorization": f"Bearer {token}"}, + data={ + "file": (open(f"./{upload_file_test_data['file']['name']}.jpeg", "rb")), + "location": "not-valid-uuid", + }, + ) + json_response = json.loads(response.data) + + assert response.status_code == 400 + assert json_response["msg"] == "Not valid file location provided" + + +def test_file_upload_successful() -> None: + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": upload_file_test_data["username"], + "password": upload_file_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Upload file + response = app.test_client().post( + "/file/upload", + headers={"Authorization": f"Bearer {token}"}, + data={ + "file": (open(f"./{upload_file_test_data['file']['name']}", "rb")), + "location": "", + }, + ) + json_response = json.loads(response.data) + + assert response.status_code == 201 + assert json_response["msg"] == "The file is being uploaded" + assert json_response["fileUUID"] is not None + + +def test_file_upload_conflict() -> None: + # Login with the user + login_response = soap_client.service.auth_login( + { + "username": upload_file_test_data["username"], + "password": upload_file_test_data["password"], + } + ) + assert login_response.error is False + token = login_response.auth.token + + # Upload file + response = app.test_client().post( + "/file/upload", + headers={"Authorization": f"Bearer {token}"}, + data={ + "file": (open(f"./{upload_file_test_data['file']['name']}.jpeg", "rb")), + "location": "", + }, + ) + assert response.status_code == 409 + + # Delete file from disk + os.remove(f"./{upload_file_test_data['file']['name']}") diff --git a/src/lib/helpers.py b/src/lib/helpers.py new file mode 100644 index 0000000..60d2f1d --- /dev/null +++ b/src/lib/helpers.py @@ -0,0 +1,10 @@ +from uuid import UUID + + +def is_valid_uuid(uuid_to_test): + try: + uuid_obj = UUID(uuid_to_test, version=4) + except ValueError: + return False + + return str(uuid_obj) == uuid_to_test diff --git a/src/views/__init__.py b/src/views/__init__.py index 4b1c006..cc68bc6 100644 --- a/src/views/__init__.py +++ b/src/views/__init__.py @@ -1,6 +1,7 @@ import flask from ._authentication_views import views as authentication_views from ._account_views import views as account_views +from ._file_views import views as file_views # NOTE: Register all views / routes using the following blueprint @@ -9,3 +10,4 @@ views.register_blueprint(authentication_views) views.register_blueprint(account_views) +views.register_blueprint(file_views) diff --git a/src/views/_account_views.py b/src/views/_account_views.py index 60f98e6..7c50f60 100644 --- a/src/views/_account_views.py +++ b/src/views/_account_views.py @@ -1,9 +1,16 @@ import flask -from src.controllers import _account_controllers +from src.middlewares import auth_middlewares +from src.controllers.account import ACCOUNT_HANDLERS views = flask.Blueprint("account", __name__) @views.route("/account/register", methods=["POST"]) def account_register(): - return _account_controllers.register_handler() + return ACCOUNT_HANDLERS["REGISTER"]() + + +@views.route("/account/password", methods=["PATCH"]) +@auth_middlewares.token_required +def account_password(token): + return ACCOUNT_HANDLERS["UPDATE_PASSWORD"](token) diff --git a/src/views/_authentication_views.py b/src/views/_authentication_views.py index eb278bc..9f2fd43 100644 --- a/src/views/_authentication_views.py +++ b/src/views/_authentication_views.py @@ -1,16 +1,16 @@ import flask -from src.controllers import _authentication_controllers from src.middlewares import auth_middlewares +from src.controllers.authentication import AUTHENTICATION_HANDLERS views = flask.Blueprint("authentication", __name__) @views.route("/auth/login", methods=["POST"]) def auth_login(): - return _authentication_controllers.login_handler() + return AUTHENTICATION_HANDLERS["LOGIN"]() @views.route("/auth/refresh", methods=["POST"]) @auth_middlewares.token_required def auth_refresh(token): - return _authentication_controllers.challenge_handler(token) + return AUTHENTICATION_HANDLERS["REFRESH"](token) diff --git a/src/views/_file_views.py b/src/views/_file_views.py new file mode 100644 index 0000000..37eec16 --- /dev/null +++ b/src/views/_file_views.py @@ -0,0 +1,30 @@ +import flask +from src.middlewares import auth_middlewares +from src.controllers.files import FILES_HANDLERS + + +views = flask.Blueprint("file", __name__) + + +@views.route("/file//status", methods=["GET"]) +@auth_middlewares.token_required +def file_check(token, file_uuid): + return FILES_HANDLERS["CHECK_STATE"](token, file_uuid) + + +@views.route("/file//rename", methods=["PATCH"]) +@auth_middlewares.token_required +def file_rename(token, file_uuid): + return FILES_HANDLERS["RENAME"](token, file_uuid) + + +@views.route("/folders", methods=["POST"]) +@auth_middlewares.token_required +def dir_create(token): + return FILES_HANDLERS["CREATE_DIRECTORY"](token) + + +@views.route("/file/upload", methods=["POST"]) +@auth_middlewares.token_required +def file_upload(token): + return FILES_HANDLERS["UPLOAD"](token) diff --git a/version.json b/version.json new file mode 100644 index 0000000..4069080 --- /dev/null +++ b/version.json @@ -0,0 +1,3 @@ +{ + "version": "0.8.1" +} \ No newline at end of file diff --git a/version.py b/version.py index 6ee98f8..08b00ca 100644 --- a/version.py +++ b/version.py @@ -1,5 +1,5 @@ import json -with open("package.json", "rb") as pkg_file: +with open("version.json", "rb") as pkg_file: pkg = json.load(pkg_file) print(f"version={pkg['version']}")