commit 3cc6b026cc34654ce0954a0349acc2f7d63c2434 Author: kaysar Date: Wed Feb 21 11:45:10 2024 +0700 init diff --git a/.goreleaser.debug.yaml b/.goreleaser.debug.yaml new file mode 100644 index 0000000..5d80e56 --- /dev/null +++ b/.goreleaser.debug.yaml @@ -0,0 +1,148 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com +project_name: casaos-user-service +before: + hooks: + - go generate + - go run github.com/google/go-licenses@latest check . --disallowed_types=restricted + - go mod tidy + - go test -race -v ./... +builds: + - id: casaos-user-service-amd64 + binary: build/sysroot/usr/bin/casaos-user-service + env: + - CC=x86_64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - amd64 + - id: casaos-user-service-arm64 + binary: build/sysroot/usr/bin/casaos-user-service + env: + - CC=aarch64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - arm64 + - id: casaos-user-service-arm-7 + binary: build/sysroot/usr/bin/casaos-user-service + env: + - CC=arm-linux-gnueabihf-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - arm + goarm: + - "7" + - id: casaos-user-service-migration-tool-amd64 + binary: build/sysroot/usr/bin/casaos-user-service-migration-tool + main: ./cmd/migration-tool + env: + - CC=x86_64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - amd64 + - id: casaos-user-service-migration-tool-arm64 + binary: build/sysroot/usr/bin/casaos-user-service-migration-tool + main: ./cmd/migration-tool + env: + - CC=aarch64-linux-gnu-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - arm64 + - id: casaos-user-service-migration-tool-arm-7 + binary: build/sysroot/usr/bin/casaos-user-service-migration-tool + main: ./cmd/migration-tool + env: + - CC=arm-linux-gnueabihf-gcc + gcflags: + - all=-N -l + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - arm + goarm: + - "7" +archives: + - name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}" + id: casaos-user-service + builds: + - casaos-user-service-amd64 + - casaos-user-service-arm64 + - casaos-user-service-arm-7 + files: + - build/**/* + - name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}" + id: casaos-user-service-migration-tool + builds: + - casaos-user-service-migration-tool-amd64 + - casaos-user-service-migration-tool-arm64 + - casaos-user-service-migration-tool-arm-7 + files: + - build/sysroot/etc/**/* +checksum: + name_template: "checksums.txt" +snapshot: + name_template: "{{ incpatch .Version }}" +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" +release: + github: + owner: IceWhaleTech + name: CasaOS-UserService + draft: true + prerelease: auto + mode: replace + name_template: "v{{ .Version }}" diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..b74e4ef --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,179 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com +project_name: casaos-user-service +before: + hooks: + - go generate + - go run github.com/google/go-licenses@latest check . --disallowed_types=restricted + - go mod tidy + - go test -race -v ./... +builds: + - id: casaos-user-service-amd64 + binary: build/sysroot/usr/bin/casaos-user-service + hooks: + post: + - upx --best --lzma -v --no-progress "{{ .Path }}" + env: + - CC=x86_64-linux-gnu-gcc + ldflags: + - -X main.commit={{.Commit}} + - -X main.date={{.Date}} + - -s + - -w + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - amd64 + - id: casaos-user-service-arm64 + binary: build/sysroot/usr/bin/casaos-user-service + # hooks: + # post: + # - upx --best --lzma -v --no-progress "{{ .Path }}" + env: + - CC=aarch64-linux-gnu-gcc + ldflags: + - -X main.commit={{.Commit}} + - -X main.date={{.Date}} + - -s + - -w + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - arm64 + - id: casaos-user-service-arm-7 + binary: build/sysroot/usr/bin/casaos-user-service + hooks: + post: + - upx --best --lzma -v --no-progress "{{ .Path }}" + env: + - CC=arm-linux-gnueabihf-gcc + ldflags: + - -X main.commit={{.Commit}} + - -X main.date={{.Date}} + - -s + - -w + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - arm + goarm: + - "7" + - id: casaos-user-service-migration-tool-amd64 + binary: build/sysroot/usr/bin/casaos-user-service-migration-tool + hooks: + post: + - upx --best --lzma -v --no-progress "{{ .Path }}" + main: ./cmd/migration-tool + env: + - CC=x86_64-linux-gnu-gcc + ldflags: + - -X main.commit={{.Commit}} + - -X main.date={{.Date}} + - -s + - -w + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - amd64 + - id: casaos-user-service-migration-tool-arm64 + binary: build/sysroot/usr/bin/casaos-user-service-migration-tool + # hooks: + # post: + # - upx --best --lzma -v --no-progress "{{ .Path }}" + main: ./cmd/migration-tool + env: + - CC=aarch64-linux-gnu-gcc + ldflags: + - -X main.commit={{.Commit}} + - -X main.date={{.Date}} + - -s + - -w + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - arm64 + - id: casaos-user-service-migration-tool-arm-7 + binary: build/sysroot/usr/bin/casaos-user-service-migration-tool + hooks: + post: + - upx --best --lzma -v --no-progress "{{ .Path }}" + main: ./cmd/migration-tool + env: + - CC=arm-linux-gnueabihf-gcc + ldflags: + - -X main.commit={{.Commit}} + - -X main.date={{.Date}} + - -s + - -w + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + goos: + - linux + goarch: + - arm + goarm: + - "7" +archives: + - name_template: >- + {{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-v{{ .Version }} + builds: + - casaos-user-service-amd64 + - casaos-user-service-arm64 + - casaos-user-service-arm-7 + files: + - build/**/* + - name_template: >- + {{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-migration-tool-v{{ .Version }} + id: casaos-user-service-migration-tool + builds: + - casaos-user-service-migration-tool-amd64 + - casaos-user-service-migration-tool-arm64 + - casaos-user-service-migration-tool-arm-7 + files: + - build/sysroot/etc/**/* +checksum: + name_template: "checksums.txt" +snapshot: + name_template: "{{ incpatch .Version }}" +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" +release: + github: + owner: IceWhaleTech + name: CasaOS-UserService + draft: true + prerelease: auto + mode: replace + name_template: "v{{ .Version }}" diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c6b44ef --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "UserService (localhost)", + "type": "go", + "debugAdapter": "dlv-dap", + "request": "launch", + "port": 2345, + "host": "127.0.0.1", + "mode": "exec", + "program": "${workspaceFolder}/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service" + } + ] +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7379f01 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# CasaOS-UserService + +[![Go Reference](https://pkg.go.dev/badge/github.com/IceWhaleTech/CasaOS-UserService.svg)](https://pkg.go.dev/github.com/IceWhaleTech/CasaOS-UserService) [![Go Report Card](https://goreportcard.com/badge/github.com/IceWhaleTech/CasaOS-UserService)](https://goreportcard.com/report/github.com/IceWhaleTech/CasaOS-UserService) [![goreleaser](https://github.com/IceWhaleTech/CasaOS-UserService/actions/workflows/release.yml/badge.svg)](https://github.com/IceWhaleTech/CasaOS-UserService/actions/workflows/release.yml) [![codecov](https://codecov.io/gh/IceWhaleTech/CasaOS-UserService/branch/main/graph/badge.svg?token=4GWJIF6FDD)](https://codecov.io/gh/IceWhaleTech/CasaOS-UserService) + +User Service provides user management functionalities to CasaOS. + + + +## publish api to npm + +### edit version in package.json + +### run +```bash +yarn + +yarn start +``` + +### publish + +Manual publish +```bash +yarn publish +``` + +Auto publish +```bash +git push origin dev** +``` \ No newline at end of file diff --git a/api/index.html b/api/index.html new file mode 100644 index 0000000..b787fd3 --- /dev/null +++ b/api/index.html @@ -0,0 +1,24 @@ + + + + + CasaOS | Developers + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api/user-service/openapi.yaml b/api/user-service/openapi.yaml new file mode 100644 index 0000000..feb76ee --- /dev/null +++ b/api/user-service/openapi.yaml @@ -0,0 +1,211 @@ +openapi: 3.0.3 + +info: + title: Casaos User Service API + version: v2 + description: | + + + + CasaOS + + This is the API for the Casaos User Service. + It is used to manage users and their access to Casaos services. + +servers: + - url: /v2/users + description: Casaos User Service API + +tags: + - name: event + description: Event related operations +security: + - access_token: [] + +paths: + /event/{event_uuid}: + delete: + summary: Delete an event + description: Delete an event + operationId: deleteEvent + tags: + - event + parameters: + - $ref: "#/components/parameters/event_uuid" + + responses: + "200": + description: Event deleted + $ref: "#/components/responses/DeleteEventOK" + "401": + description: Event not found + + "404": + description: Event not found + $ref: "#/components/responses/ResponseNotFound" + "500": + $ref: "#/components/responses/BadResponse" + description: Internal server error + /events: + get: + summary: Get all events + description: Get all events + operationId: getEvents + tags: + - event + parameters: + - name: form + in: query + description: Form of the events to get + required: false + schema: + type: string + format: date-time + example: "2021-01-01T00:00:00Z" + responses: + "200": + description: Events found + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Event" + "500": + description: Internal server error + $ref: "#/components/responses/BadResponse" + /event/local_storage/{serial}: + delete: + summary: Delete an event + description: Delete an event + operationId: deleteEventBySerial + tags: + - event + parameters: + - $ref: "#/components/parameters/serial" + responses: + "200": + description: Event deleted + $ref: "#/components/responses/OKResponse" + "401": + description: Event not found + "404": + description: Event not found + $ref: "#/components/responses/ResponseNotFound" + "500": + $ref: "#/components/responses/BadResponse" + description: Internal server error +components: + securitySchemes: + access_token: + type: apiKey + in: header + name: Authorization + parameters: + serial: + name: serial + in: path + description: Serial of the local storage + required: true + schema: + type: string + example: "1234567890" + event_uuid: + name: event_uuid + in: path + description: UUID of the event to get + required: true + schema: + type: string + format: uuid + example: 123e4567-e89b-12d3-a456-426655440000 + responses: + OKResponse: + description: OK + content: + application/json: + schema: + type: object + $ref: "#/components/schemas/BaseResponse" + DeleteEventOK: + description: Event deleted + content: + application/json: + schema: + type: object + $ref: "#/components/schemas/Event" + BadResponse: + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/BaseResponse" + ResponseNotFound: + description: Not Found + content: + application/json: + schema: + $ref: "#/components/schemas/BaseResponse" + example: + message: "Not Found" + schemas: + BaseResponse: + type: object + properties: + message: + readOnly: true + type: string + example: "Bad request" + description: Error message + Property: + type: object + properties: + name: + type: string + description: Name of the property + value: + type: string + description: Value of the property + Event: + type: object + required: + - "sourceID" + - "name" + - "properties" + properties: + event_uuid: + type: string + format: uuid + description: UUID of the event + sourceID: + type: string + description: associated source id + example: "local-storage" + name: + type: string + description: event name + example: "local-storage:disk:added" + properties: + type: array + description: event properties + items: + $ref: "#/components/schemas/Property" + example: + - name: local-storage:vendor + value: SanDisk + - name: local-storage:model + value: Cruzer + - name: local-storage:uuid + value: 442e0e5b-9d3e-4fe8-b46f-9c4141fdecd7 + - name: casaos-ui:type + value: notification-style-2 + - name: casaos-ui:title + value: "New disk found" + - name: casaos-ui:icon-1 + value: casaos-icon-disk + - name: casaos-ui:message-1 + value: "A new disk, SanDisk Cruzer, is added." + timestamp: + type: string + description: timestamp this event took place + format: date-time diff --git a/build/scripts/migration/service.d/user-service/migration.list b/build/scripts/migration/service.d/user-service/migration.list new file mode 100644 index 0000000..9f66bcb --- /dev/null +++ b/build/scripts/migration/service.d/user-service/migration.list @@ -0,0 +1,3 @@ +LEGACY_WITHOUT_VERSION ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS-UserService/releases/download/v0.3.6/linux-${ARCH}-casaos-user-service-migration-tool-v0.3.6.tar.gz +v0.3.5 ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS-UserService/releases/download/v0.3.6/linux-${ARCH}-casaos-user-service-migration-tool-v0.3.6.tar.gz +v0.3.5.1 ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS-UserService/releases/download/v0.3.6/linux-${ARCH}-casaos-user-service-migration-tool-v0.3.6.tar.gz diff --git a/build/sysroot/etc/casaos/user-service.conf.sample b/build/sysroot/etc/casaos/user-service.conf.sample new file mode 100644 index 0000000..1d2d1ba --- /dev/null +++ b/build/sysroot/etc/casaos/user-service.conf.sample @@ -0,0 +1,9 @@ +[common] +RuntimePath=/var/run/casaos + +[app] +LogPath = /var/log/casaos +LogSaveName = user-service +LogFileExt = log +DBPath = /var/lib/casaos/db +UserDataPath = /var/lib/casaos diff --git a/build/sysroot/usr/lib/systemd/system/casaos-user-service.service b/build/sysroot/usr/lib/systemd/system/casaos-user-service.service new file mode 100644 index 0000000..7fcff9f --- /dev/null +++ b/build/sysroot/usr/lib/systemd/system/casaos-user-service.service @@ -0,0 +1,13 @@ +[Unit] +After=casaos-message-bus.service +Description=CasaOS User Service + +[Service] +ExecStartPre=/usr/bin/casaos-user-service -v +ExecStart=/usr/bin/casaos-user-service -c /etc/casaos/user-service.conf +PIDFile=/var/run/casaos/user-service.pid +Restart=always +Type=notify + +[Install] +WantedBy=multi-user.target diff --git a/cmd/migration-tool/log.go b/cmd/migration-tool/log.go new file mode 100644 index 0000000..ed69983 --- /dev/null +++ b/cmd/migration-tool/log.go @@ -0,0 +1,37 @@ +package main + +import ( + "log" + "os" +) + +type Logger struct { + DebugMode bool + + _debug *log.Logger + _info *log.Logger + _error *log.Logger +} + +func NewLogger() *Logger { + return &Logger{ + DebugMode: false, + _debug: log.New(os.Stdout, "DEBUG: ", 0), + _info: log.New(os.Stdout, "", 0), + _error: log.New(os.Stderr, "ERROR: ", 0), + } +} + +func (l *Logger) Debug(format string, v ...interface{}) { + if l.DebugMode { + l._debug.Printf(format, v...) + } +} + +func (l *Logger) Info(format string, v ...interface{}) { + l._info.Printf(format, v...) +} + +func (l *Logger) Error(format string, v ...interface{}) { + l._error.Printf(format, v...) +} diff --git a/cmd/migration-tool/main.go b/cmd/migration-tool/main.go new file mode 100644 index 0000000..cbf1322 --- /dev/null +++ b/cmd/migration-tool/main.go @@ -0,0 +1,106 @@ +package main + +import ( + _ "embed" + "flag" + "fmt" + "os" + + interfaces "github.com/IceWhaleTech/CasaOS-Common" + "github.com/IceWhaleTech/CasaOS-Common/utils/systemctl" + "github.com/IceWhaleTech/CasaOS-UserService/common" +) + +const ( + userServiceConfigDirPath = "/etc/casaos" + userServiceConfigFilePath = "/etc/casaos/user-service.conf" + userServiceName = "casaos-user-service.service" + userServiceNameShort = "user-service" +) + +//go:embedded ../../build/sysroot/etc/casaos/user-service.conf.sample +//var _userServiceConfigFileSample string + +var ( + commit = "private build" + date = "private build" + + _logger *Logger +) + +// var _status *version.GlobalMigrationStatus + +func main() { + versionFlag := flag.Bool("v", false, "version") + debugFlag := flag.Bool("d", true, "debug") + forceFlag := flag.Bool("f", false, "force") + flag.Parse() + + if *versionFlag { + fmt.Printf("v%s\n", common.Version) + os.Exit(0) + } + + println("git commit:", commit) + println("build date:", date) + + _logger = NewLogger() + + if os.Getuid() != 0 { + _logger.Info("Root privileges are required to run this program.") + os.Exit(1) + } + + if *debugFlag { + _logger.DebugMode = true + } + + if !*forceFlag { + isRunning, err := systemctl.IsServiceRunning(userServiceName) + if err != nil { + _logger.Error("Failed to check if %s is running", userServiceName) + panic(err) + } + + if isRunning { + _logger.Info("%s is running. If migration is still needed, try with -f.", userServiceName) + os.Exit(1) + } + } + + migrationTools := []interfaces.MigrationTool{ + NewMigrationDummy(), + } + + var selectedMigrationTool interfaces.MigrationTool + + // look for the right migration tool matching current version + for _, tool := range migrationTools { + migrationNeeded, err := tool.IsMigrationNeeded() + if err != nil { + panic(err) + } + + if migrationNeeded { + selectedMigrationTool = tool + break + } + } + + if selectedMigrationTool == nil { + _logger.Info("No migration to proceed.") + return + } + + if err := selectedMigrationTool.PreMigrate(); err != nil { + panic(err) + } + + if err := selectedMigrationTool.Migrate(); err != nil { + panic(err) + } + + if err := selectedMigrationTool.PostMigrate(); err != nil { + _logger.Error("Migration succeeded, but post-migration failed: %s", err) + } +} diff --git a/cmd/migration-tool/migration_dummy.go b/cmd/migration-tool/migration_dummy.go new file mode 100644 index 0000000..6d08df2 --- /dev/null +++ b/cmd/migration-tool/migration_dummy.go @@ -0,0 +1,27 @@ +package main + +import ( + interfaces "github.com/IceWhaleTech/CasaOS-Common" +) + +type migrationTool struct{} + +func (u *migrationTool) IsMigrationNeeded() (bool, error) { + return false, nil +} + +func (u *migrationTool) PreMigrate() error { + return nil +} + +func (u *migrationTool) Migrate() error { + return nil +} + +func (u *migrationTool) PostMigrate() error { + return nil +} + +func NewMigrationDummy() interfaces.MigrationTool { + return &migrationTool{} +} diff --git a/codegen/message_bus/api.go b/codegen/message_bus/api.go new file mode 100644 index 0000000..73b4e35 --- /dev/null +++ b/codegen/message_bus/api.go @@ -0,0 +1,2769 @@ +// Package message_bus provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT. +package message_bus + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" + "time" + + "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/getkin/kin-openapi/openapi3" + "github.com/labstack/echo/v4" +) + +const ( + Access_tokenScopes = "access_token.Scopes" +) + +// Action defines model for Action. +type Action struct { + // Name action name + Name string `json:"name"` + + // Properties event properties + Properties map[string]string `json:"properties"` + + // SourceID associated source id + SourceID string `json:"sourceID"` + + // Timestamp timestamp this action took place + Timestamp *time.Time `json:"timestamp,omitempty"` +} + +// ActionType defines model for ActionType. +type ActionType struct { + // Name action name + // + // (there is no naming convention for action names, but it is recommended to name each as structural and descriptive as possible) + Name string `json:"name"` + PropertyTypeList []PropertyType `json:"propertyTypeList"` + + // SourceID action source id to identify where the action will take + SourceID string `json:"sourceID"` +} + +// BaseResponse defines model for BaseResponse. +type BaseResponse struct { + // Message message returned by server side if there is any + Message *string `json:"message,omitempty"` +} + +// Event defines model for Event. +type Event struct { + // Name event name + Name string `json:"name"` + + // Properties event properties + Properties map[string]string `json:"properties"` + + // SourceID associated source id + SourceID string `json:"sourceID"` + + // Timestamp timestamp this event took place + Timestamp *time.Time `json:"timestamp,omitempty"` + + // Uuid event uuid + Uuid *string `json:"uuid,omitempty"` +} + +// EventType defines model for EventType. +type EventType struct { + // Name event name + // + // (there is no naming convention for event names, but it is recommended to name each as structural and descriptive as possible) + Name string `json:"name"` + PropertyTypeList []PropertyType `json:"propertyTypeList"` + + // SourceID event source id to identify where the event comes from + SourceID string `json:"sourceID"` +} + +// PropertyType defines model for PropertyType. +type PropertyType struct { + Description *string `json:"description,omitempty"` + Example *string `json:"example,omitempty"` + + // Name property name + // + // > It is recommended for a property name to be as descriptive as possible. One option is to prefix with a namespace. + // > - If the property is source specific, prefix with source ID. For example, `local-storage:vendor` + // > - Otherwise, prefix with `common:`. For example, `common:email` + // > + // > Some bad examples are `id`, `avail`, `blk`...which can be ambiguous and confusing. + Name string `json:"name"` +} + +// ActionName defines model for ActionName. +type ActionName = string + +// ActionNames defines model for ActionNames. +type ActionNames = []string + +// EventName defines model for EventName. +type EventName = string + +// EventNames defines model for EventNames. +type EventNames = []string + +// SourceID defines model for SourceID. +type SourceID = string + +// GetActionTypeOK defines model for GetActionTypeOK. +type GetActionTypeOK = ActionType + +// GetActionTypesOK defines model for GetActionTypesOK. +type GetActionTypesOK = []ActionType + +// GetEventTypeOK defines model for GetEventTypeOK. +type GetEventTypeOK = EventType + +// GetEventTypesOK defines model for GetEventTypesOK. +type GetEventTypesOK = []EventType + +// PublishEventOK defines model for PublishEventOK. +type PublishEventOK = Event + +// ResponseBadRequest defines model for ResponseBadRequest. +type ResponseBadRequest = BaseResponse + +// ResponseConflict defines model for ResponseConflict. +type ResponseConflict = BaseResponse + +// ResponseInternalServerError defines model for ResponseInternalServerError. +type ResponseInternalServerError = BaseResponse + +// ResponseNotFound defines model for ResponseNotFound. +type ResponseNotFound = BaseResponse + +// ResponseOK defines model for ResponseOK. +type ResponseOK = BaseResponse + +// TriggerActionOK defines model for TriggerActionOK. +type TriggerActionOK = Action + +// PublishEvent event properties +type PublishEvent map[string]string + +// RegisterActionTypes defines model for RegisterActionTypes. +type RegisterActionTypes = []ActionType + +// RegisterEventTypes defines model for RegisterEventTypes. +type RegisterEventTypes = []EventType + +// TriggerAction action properties +type TriggerAction map[string]string + +// SubscribeActionWSParams defines parameters for SubscribeActionWS. +type SubscribeActionWSParams struct { + Names *ActionNames `form:"names,omitempty" json:"names,omitempty"` +} + +// TriggerActionJSONBody defines parameters for TriggerAction. +type TriggerActionJSONBody map[string]string + +// RegisterActionTypesJSONBody defines parameters for RegisterActionTypes. +type RegisterActionTypesJSONBody = []ActionType + +// SubscribeEventWSParams defines parameters for SubscribeEventWS. +type SubscribeEventWSParams struct { + Names *EventNames `form:"names,omitempty" json:"names,omitempty"` +} + +// PublishEventJSONBody defines parameters for PublishEvent. +type PublishEventJSONBody map[string]string + +// RegisterEventTypesJSONBody defines parameters for RegisterEventTypes. +type RegisterEventTypesJSONBody = []EventType + +// TriggerActionJSONRequestBody defines body for TriggerAction for application/json ContentType. +type TriggerActionJSONRequestBody TriggerActionJSONBody + +// RegisterActionTypesJSONRequestBody defines body for RegisterActionTypes for application/json ContentType. +type RegisterActionTypesJSONRequestBody = RegisterActionTypesJSONBody + +// PublishEventJSONRequestBody defines body for PublishEvent for application/json ContentType. +type PublishEventJSONRequestBody PublishEventJSONBody + +// RegisterEventTypesJSONRequestBody defines body for RegisterEventTypes for application/json ContentType. +type RegisterEventTypesJSONRequestBody = RegisterEventTypesJSONBody + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(ctx context.Context, req *http.Request) error + +// Doer performs HTTP requests. +// +// The standard http.Client implements this interface. +type HttpRequestDoer interface { + Do(req *http.Request) (*http.Response, error) +} + +// Client which conforms to the OpenAPI3 specification for this service. +type Client struct { + // The endpoint of the server conforming to this interface, with scheme, + // https://api.deepmap.com for example. This can contain a path relative + // to the server, such as https://api.deepmap.com/dev-test, and all the + // paths in the swagger spec will be appended to the server. + Server string + + // Doer for performing requests, typically a *http.Client with any + // customized settings, such as certificate chains. + Client HttpRequestDoer + + // A list of callbacks for modifying requests which are generated before sending over + // the network. + RequestEditors []RequestEditorFn +} + +// ClientOption allows setting custom parameters during construction +type ClientOption func(*Client) error + +// Creates a new Client, with reasonable defaults +func NewClient(server string, opts ...ClientOption) (*Client, error) { + // create a client with sane default values + client := Client{ + Server: server, + } + // mutate client and add all optional params + for _, o := range opts { + if err := o(&client); err != nil { + return nil, err + } + } + // ensure the server URL always has a trailing slash + if !strings.HasSuffix(client.Server, "/") { + client.Server += "/" + } + // create httpClient, if not already present + if client.Client == nil { + client.Client = &http.Client{} + } + return &client, nil +} + +// WithHTTPClient allows overriding the default Doer, which is +// automatically created using http.Client. This is useful for tests. +func WithHTTPClient(doer HttpRequestDoer) ClientOption { + return func(c *Client) error { + c.Client = doer + return nil + } +} + +// WithRequestEditorFn allows setting up a callback function, which will be +// called right before sending the request. This can be used to mutate the request. +func WithRequestEditorFn(fn RequestEditorFn) ClientOption { + return func(c *Client) error { + c.RequestEditors = append(c.RequestEditors, fn) + return nil + } +} + +// The interface specification for the client above. +type ClientInterface interface { + // SubscribeActionWS request + SubscribeActionWS(ctx context.Context, sourceId SourceID, params *SubscribeActionWSParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // TriggerAction request with any body + TriggerActionWithBody(ctx context.Context, sourceId SourceID, name ActionName, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + TriggerAction(ctx context.Context, sourceId SourceID, name ActionName, body TriggerActionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetActionTypes request + GetActionTypes(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // RegisterActionTypes request with any body + RegisterActionTypesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + RegisterActionTypes(ctx context.Context, body RegisterActionTypesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetActionTypesBySourceID request + GetActionTypesBySourceID(ctx context.Context, sourceId SourceID, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetActionType request + GetActionType(ctx context.Context, sourceId SourceID, name ActionName, reqEditors ...RequestEditorFn) (*http.Response, error) + + // SubscribeEventWS request + SubscribeEventWS(ctx context.Context, sourceId SourceID, params *SubscribeEventWSParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // PublishEvent request with any body + PublishEventWithBody(ctx context.Context, sourceId SourceID, name EventName, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + PublishEvent(ctx context.Context, sourceId SourceID, name EventName, body PublishEventJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetEventTypes request + GetEventTypes(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // RegisterEventTypes request with any body + RegisterEventTypesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + RegisterEventTypes(ctx context.Context, body RegisterEventTypesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetEventTypesBySourceID request + GetEventTypesBySourceID(ctx context.Context, sourceId SourceID, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetEventType request + GetEventType(ctx context.Context, sourceId SourceID, name EventName, reqEditors ...RequestEditorFn) (*http.Response, error) + + // SubscribeSIO request + SubscribeSIO(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // PollSIO request + PollSIO(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // SubscribeSIO2 request + SubscribeSIO2(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // PollSIO2 request + PollSIO2(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) +} + +func (c *Client) SubscribeActionWS(ctx context.Context, sourceId SourceID, params *SubscribeActionWSParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewSubscribeActionWSRequest(c.Server, sourceId, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) TriggerActionWithBody(ctx context.Context, sourceId SourceID, name ActionName, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewTriggerActionRequestWithBody(c.Server, sourceId, name, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) TriggerAction(ctx context.Context, sourceId SourceID, name ActionName, body TriggerActionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewTriggerActionRequest(c.Server, sourceId, name, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) GetActionTypes(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetActionTypesRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RegisterActionTypesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRegisterActionTypesRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RegisterActionTypes(ctx context.Context, body RegisterActionTypesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRegisterActionTypesRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) GetActionTypesBySourceID(ctx context.Context, sourceId SourceID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetActionTypesBySourceIDRequest(c.Server, sourceId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) GetActionType(ctx context.Context, sourceId SourceID, name ActionName, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetActionTypeRequest(c.Server, sourceId, name) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) SubscribeEventWS(ctx context.Context, sourceId SourceID, params *SubscribeEventWSParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewSubscribeEventWSRequest(c.Server, sourceId, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) PublishEventWithBody(ctx context.Context, sourceId SourceID, name EventName, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPublishEventRequestWithBody(c.Server, sourceId, name, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) PublishEvent(ctx context.Context, sourceId SourceID, name EventName, body PublishEventJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPublishEventRequest(c.Server, sourceId, name, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) GetEventTypes(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetEventTypesRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RegisterEventTypesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRegisterEventTypesRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RegisterEventTypes(ctx context.Context, body RegisterEventTypesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRegisterEventTypesRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) GetEventTypesBySourceID(ctx context.Context, sourceId SourceID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetEventTypesBySourceIDRequest(c.Server, sourceId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) GetEventType(ctx context.Context, sourceId SourceID, name EventName, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetEventTypeRequest(c.Server, sourceId, name) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) SubscribeSIO(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewSubscribeSIORequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) PollSIO(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPollSIORequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) SubscribeSIO2(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewSubscribeSIO2Request(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) PollSIO2(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPollSIO2Request(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +// NewSubscribeActionWSRequest generates requests for SubscribeActionWS +func NewSubscribeActionWSRequest(server string, sourceId SourceID, params *SubscribeActionWSParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "source_id", runtime.ParamLocationPath, sourceId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/action/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + queryValues := queryURL.Query() + + if params.Names != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "names", runtime.ParamLocationQuery, *params.Names); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewTriggerActionRequest calls the generic TriggerAction builder with application/json body +func NewTriggerActionRequest(server string, sourceId SourceID, name ActionName, body TriggerActionJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewTriggerActionRequestWithBody(server, sourceId, name, "application/json", bodyReader) +} + +// NewTriggerActionRequestWithBody generates requests for TriggerAction with any type of body +func NewTriggerActionRequestWithBody(server string, sourceId SourceID, name ActionName, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "source_id", runtime.ParamLocationPath, sourceId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "name", runtime.ParamLocationPath, name) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/action/%s/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewGetActionTypesRequest generates requests for GetActionTypes +func NewGetActionTypesRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/action_type") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewRegisterActionTypesRequest calls the generic RegisterActionTypes builder with application/json body +func NewRegisterActionTypesRequest(server string, body RegisterActionTypesJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewRegisterActionTypesRequestWithBody(server, "application/json", bodyReader) +} + +// NewRegisterActionTypesRequestWithBody generates requests for RegisterActionTypes with any type of body +func NewRegisterActionTypesRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/action_type") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewGetActionTypesBySourceIDRequest generates requests for GetActionTypesBySourceID +func NewGetActionTypesBySourceIDRequest(server string, sourceId SourceID) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "source_id", runtime.ParamLocationPath, sourceId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/action_type/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewGetActionTypeRequest generates requests for GetActionType +func NewGetActionTypeRequest(server string, sourceId SourceID, name ActionName) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "source_id", runtime.ParamLocationPath, sourceId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "name", runtime.ParamLocationPath, name) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/action_type/%s/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewSubscribeEventWSRequest generates requests for SubscribeEventWS +func NewSubscribeEventWSRequest(server string, sourceId SourceID, params *SubscribeEventWSParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "source_id", runtime.ParamLocationPath, sourceId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/event/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + queryValues := queryURL.Query() + + if params.Names != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "names", runtime.ParamLocationQuery, *params.Names); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewPublishEventRequest calls the generic PublishEvent builder with application/json body +func NewPublishEventRequest(server string, sourceId SourceID, name EventName, body PublishEventJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewPublishEventRequestWithBody(server, sourceId, name, "application/json", bodyReader) +} + +// NewPublishEventRequestWithBody generates requests for PublishEvent with any type of body +func NewPublishEventRequestWithBody(server string, sourceId SourceID, name EventName, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "source_id", runtime.ParamLocationPath, sourceId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "name", runtime.ParamLocationPath, name) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/event/%s/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewGetEventTypesRequest generates requests for GetEventTypes +func NewGetEventTypesRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/event_type") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewRegisterEventTypesRequest calls the generic RegisterEventTypes builder with application/json body +func NewRegisterEventTypesRequest(server string, body RegisterEventTypesJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewRegisterEventTypesRequestWithBody(server, "application/json", bodyReader) +} + +// NewRegisterEventTypesRequestWithBody generates requests for RegisterEventTypes with any type of body +func NewRegisterEventTypesRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/event_type") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewGetEventTypesBySourceIDRequest generates requests for GetEventTypesBySourceID +func NewGetEventTypesBySourceIDRequest(server string, sourceId SourceID) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "source_id", runtime.ParamLocationPath, sourceId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/event_type/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewGetEventTypeRequest generates requests for GetEventType +func NewGetEventTypeRequest(server string, sourceId SourceID, name EventName) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "source_id", runtime.ParamLocationPath, sourceId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "name", runtime.ParamLocationPath, name) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/event_type/%s/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewSubscribeSIORequest generates requests for SubscribeSIO +func NewSubscribeSIORequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/socket.io") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewPollSIORequest generates requests for PollSIO +func NewPollSIORequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/socket.io") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewSubscribeSIO2Request generates requests for SubscribeSIO2 +func NewSubscribeSIO2Request(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/socket.io/") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewPollSIO2Request generates requests for PollSIO2 +func NewPollSIO2Request(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/socket.io/") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return nil +} + +// ClientWithResponses builds on ClientInterface to offer response payloads +type ClientWithResponses struct { + ClientInterface +} + +// NewClientWithResponses creates a new ClientWithResponses, which wraps +// Client with return type handling +func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { + client, err := NewClient(server, opts...) + if err != nil { + return nil, err + } + return &ClientWithResponses{client}, nil +} + +// WithBaseURL overrides the baseURL. +func WithBaseURL(baseURL string) ClientOption { + return func(c *Client) error { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { + // SubscribeActionWS request + SubscribeActionWSWithResponse(ctx context.Context, sourceId SourceID, params *SubscribeActionWSParams, reqEditors ...RequestEditorFn) (*SubscribeActionWSResponse, error) + + // TriggerAction request with any body + TriggerActionWithBodyWithResponse(ctx context.Context, sourceId SourceID, name ActionName, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*TriggerActionResponse, error) + + TriggerActionWithResponse(ctx context.Context, sourceId SourceID, name ActionName, body TriggerActionJSONRequestBody, reqEditors ...RequestEditorFn) (*TriggerActionResponse, error) + + // GetActionTypes request + GetActionTypesWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetActionTypesResponse, error) + + // RegisterActionTypes request with any body + RegisterActionTypesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterActionTypesResponse, error) + + RegisterActionTypesWithResponse(ctx context.Context, body RegisterActionTypesJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterActionTypesResponse, error) + + // GetActionTypesBySourceID request + GetActionTypesBySourceIDWithResponse(ctx context.Context, sourceId SourceID, reqEditors ...RequestEditorFn) (*GetActionTypesBySourceIDResponse, error) + + // GetActionType request + GetActionTypeWithResponse(ctx context.Context, sourceId SourceID, name ActionName, reqEditors ...RequestEditorFn) (*GetActionTypeResponse, error) + + // SubscribeEventWS request + SubscribeEventWSWithResponse(ctx context.Context, sourceId SourceID, params *SubscribeEventWSParams, reqEditors ...RequestEditorFn) (*SubscribeEventWSResponse, error) + + // PublishEvent request with any body + PublishEventWithBodyWithResponse(ctx context.Context, sourceId SourceID, name EventName, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PublishEventResponse, error) + + PublishEventWithResponse(ctx context.Context, sourceId SourceID, name EventName, body PublishEventJSONRequestBody, reqEditors ...RequestEditorFn) (*PublishEventResponse, error) + + // GetEventTypes request + GetEventTypesWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetEventTypesResponse, error) + + // RegisterEventTypes request with any body + RegisterEventTypesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterEventTypesResponse, error) + + RegisterEventTypesWithResponse(ctx context.Context, body RegisterEventTypesJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterEventTypesResponse, error) + + // GetEventTypesBySourceID request + GetEventTypesBySourceIDWithResponse(ctx context.Context, sourceId SourceID, reqEditors ...RequestEditorFn) (*GetEventTypesBySourceIDResponse, error) + + // GetEventType request + GetEventTypeWithResponse(ctx context.Context, sourceId SourceID, name EventName, reqEditors ...RequestEditorFn) (*GetEventTypeResponse, error) + + // SubscribeSIO request + SubscribeSIOWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*SubscribeSIOResponse, error) + + // PollSIO request + PollSIOWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PollSIOResponse, error) + + // SubscribeSIO2 request + SubscribeSIO2WithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*SubscribeSIO2Response, error) + + // PollSIO2 request + PollSIO2WithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PollSIO2Response, error) +} + +type SubscribeActionWSResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r SubscribeActionWSResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r SubscribeActionWSResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type TriggerActionResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Action + JSON400 *BaseResponse + JSON404 *BaseResponse +} + +// Status returns HTTPResponse.Status +func (r TriggerActionResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r TriggerActionResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetActionTypesResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]ActionType +} + +// Status returns HTTPResponse.Status +func (r GetActionTypesResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetActionTypesResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type RegisterActionTypesResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *BaseResponse + JSON400 *BaseResponse + JSON409 *BaseResponse +} + +// Status returns HTTPResponse.Status +func (r RegisterActionTypesResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RegisterActionTypesResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetActionTypesBySourceIDResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]ActionType + JSON404 *BaseResponse +} + +// Status returns HTTPResponse.Status +func (r GetActionTypesBySourceIDResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetActionTypesBySourceIDResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetActionTypeResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ActionType + JSON404 *BaseResponse +} + +// Status returns HTTPResponse.Status +func (r GetActionTypeResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetActionTypeResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type SubscribeEventWSResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r SubscribeEventWSResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r SubscribeEventWSResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type PublishEventResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Event + JSON400 *BaseResponse + JSON404 *BaseResponse +} + +// Status returns HTTPResponse.Status +func (r PublishEventResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PublishEventResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetEventTypesResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]EventType + JSON500 *BaseResponse +} + +// Status returns HTTPResponse.Status +func (r GetEventTypesResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetEventTypesResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type RegisterEventTypesResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *BaseResponse + JSON400 *BaseResponse + JSON409 *BaseResponse +} + +// Status returns HTTPResponse.Status +func (r RegisterEventTypesResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RegisterEventTypesResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetEventTypesBySourceIDResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]EventType + JSON404 *BaseResponse +} + +// Status returns HTTPResponse.Status +func (r GetEventTypesBySourceIDResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetEventTypesBySourceIDResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetEventTypeResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *EventType + JSON404 *BaseResponse +} + +// Status returns HTTPResponse.Status +func (r GetEventTypeResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetEventTypeResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type SubscribeSIOResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r SubscribeSIOResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r SubscribeSIOResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type PollSIOResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r PollSIOResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PollSIOResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type SubscribeSIO2Response struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r SubscribeSIO2Response) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r SubscribeSIO2Response) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type PollSIO2Response struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r PollSIO2Response) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PollSIO2Response) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// SubscribeActionWSWithResponse request returning *SubscribeActionWSResponse +func (c *ClientWithResponses) SubscribeActionWSWithResponse(ctx context.Context, sourceId SourceID, params *SubscribeActionWSParams, reqEditors ...RequestEditorFn) (*SubscribeActionWSResponse, error) { + rsp, err := c.SubscribeActionWS(ctx, sourceId, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseSubscribeActionWSResponse(rsp) +} + +// TriggerActionWithBodyWithResponse request with arbitrary body returning *TriggerActionResponse +func (c *ClientWithResponses) TriggerActionWithBodyWithResponse(ctx context.Context, sourceId SourceID, name ActionName, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*TriggerActionResponse, error) { + rsp, err := c.TriggerActionWithBody(ctx, sourceId, name, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseTriggerActionResponse(rsp) +} + +func (c *ClientWithResponses) TriggerActionWithResponse(ctx context.Context, sourceId SourceID, name ActionName, body TriggerActionJSONRequestBody, reqEditors ...RequestEditorFn) (*TriggerActionResponse, error) { + rsp, err := c.TriggerAction(ctx, sourceId, name, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseTriggerActionResponse(rsp) +} + +// GetActionTypesWithResponse request returning *GetActionTypesResponse +func (c *ClientWithResponses) GetActionTypesWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetActionTypesResponse, error) { + rsp, err := c.GetActionTypes(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetActionTypesResponse(rsp) +} + +// RegisterActionTypesWithBodyWithResponse request with arbitrary body returning *RegisterActionTypesResponse +func (c *ClientWithResponses) RegisterActionTypesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterActionTypesResponse, error) { + rsp, err := c.RegisterActionTypesWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRegisterActionTypesResponse(rsp) +} + +func (c *ClientWithResponses) RegisterActionTypesWithResponse(ctx context.Context, body RegisterActionTypesJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterActionTypesResponse, error) { + rsp, err := c.RegisterActionTypes(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRegisterActionTypesResponse(rsp) +} + +// GetActionTypesBySourceIDWithResponse request returning *GetActionTypesBySourceIDResponse +func (c *ClientWithResponses) GetActionTypesBySourceIDWithResponse(ctx context.Context, sourceId SourceID, reqEditors ...RequestEditorFn) (*GetActionTypesBySourceIDResponse, error) { + rsp, err := c.GetActionTypesBySourceID(ctx, sourceId, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetActionTypesBySourceIDResponse(rsp) +} + +// GetActionTypeWithResponse request returning *GetActionTypeResponse +func (c *ClientWithResponses) GetActionTypeWithResponse(ctx context.Context, sourceId SourceID, name ActionName, reqEditors ...RequestEditorFn) (*GetActionTypeResponse, error) { + rsp, err := c.GetActionType(ctx, sourceId, name, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetActionTypeResponse(rsp) +} + +// SubscribeEventWSWithResponse request returning *SubscribeEventWSResponse +func (c *ClientWithResponses) SubscribeEventWSWithResponse(ctx context.Context, sourceId SourceID, params *SubscribeEventWSParams, reqEditors ...RequestEditorFn) (*SubscribeEventWSResponse, error) { + rsp, err := c.SubscribeEventWS(ctx, sourceId, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseSubscribeEventWSResponse(rsp) +} + +// PublishEventWithBodyWithResponse request with arbitrary body returning *PublishEventResponse +func (c *ClientWithResponses) PublishEventWithBodyWithResponse(ctx context.Context, sourceId SourceID, name EventName, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PublishEventResponse, error) { + rsp, err := c.PublishEventWithBody(ctx, sourceId, name, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParsePublishEventResponse(rsp) +} + +func (c *ClientWithResponses) PublishEventWithResponse(ctx context.Context, sourceId SourceID, name EventName, body PublishEventJSONRequestBody, reqEditors ...RequestEditorFn) (*PublishEventResponse, error) { + rsp, err := c.PublishEvent(ctx, sourceId, name, body, reqEditors...) + if err != nil { + return nil, err + } + return ParsePublishEventResponse(rsp) +} + +// GetEventTypesWithResponse request returning *GetEventTypesResponse +func (c *ClientWithResponses) GetEventTypesWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetEventTypesResponse, error) { + rsp, err := c.GetEventTypes(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetEventTypesResponse(rsp) +} + +// RegisterEventTypesWithBodyWithResponse request with arbitrary body returning *RegisterEventTypesResponse +func (c *ClientWithResponses) RegisterEventTypesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterEventTypesResponse, error) { + rsp, err := c.RegisterEventTypesWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRegisterEventTypesResponse(rsp) +} + +func (c *ClientWithResponses) RegisterEventTypesWithResponse(ctx context.Context, body RegisterEventTypesJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterEventTypesResponse, error) { + rsp, err := c.RegisterEventTypes(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRegisterEventTypesResponse(rsp) +} + +// GetEventTypesBySourceIDWithResponse request returning *GetEventTypesBySourceIDResponse +func (c *ClientWithResponses) GetEventTypesBySourceIDWithResponse(ctx context.Context, sourceId SourceID, reqEditors ...RequestEditorFn) (*GetEventTypesBySourceIDResponse, error) { + rsp, err := c.GetEventTypesBySourceID(ctx, sourceId, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetEventTypesBySourceIDResponse(rsp) +} + +// GetEventTypeWithResponse request returning *GetEventTypeResponse +func (c *ClientWithResponses) GetEventTypeWithResponse(ctx context.Context, sourceId SourceID, name EventName, reqEditors ...RequestEditorFn) (*GetEventTypeResponse, error) { + rsp, err := c.GetEventType(ctx, sourceId, name, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetEventTypeResponse(rsp) +} + +// SubscribeSIOWithResponse request returning *SubscribeSIOResponse +func (c *ClientWithResponses) SubscribeSIOWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*SubscribeSIOResponse, error) { + rsp, err := c.SubscribeSIO(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseSubscribeSIOResponse(rsp) +} + +// PollSIOWithResponse request returning *PollSIOResponse +func (c *ClientWithResponses) PollSIOWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PollSIOResponse, error) { + rsp, err := c.PollSIO(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParsePollSIOResponse(rsp) +} + +// SubscribeSIO2WithResponse request returning *SubscribeSIO2Response +func (c *ClientWithResponses) SubscribeSIO2WithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*SubscribeSIO2Response, error) { + rsp, err := c.SubscribeSIO2(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseSubscribeSIO2Response(rsp) +} + +// PollSIO2WithResponse request returning *PollSIO2Response +func (c *ClientWithResponses) PollSIO2WithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PollSIO2Response, error) { + rsp, err := c.PollSIO2(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParsePollSIO2Response(rsp) +} + +// ParseSubscribeActionWSResponse parses an HTTP response from a SubscribeActionWSWithResponse call +func ParseSubscribeActionWSResponse(rsp *http.Response) (*SubscribeActionWSResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &SubscribeActionWSResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} + +// ParseTriggerActionResponse parses an HTTP response from a TriggerActionWithResponse call +func ParseTriggerActionResponse(rsp *http.Response) (*TriggerActionResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &TriggerActionResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Action + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + } + + return response, nil +} + +// ParseGetActionTypesResponse parses an HTTP response from a GetActionTypesWithResponse call +func ParseGetActionTypesResponse(rsp *http.Response) (*GetActionTypesResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetActionTypesResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest []ActionType + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseRegisterActionTypesResponse parses an HTTP response from a RegisterActionTypesWithResponse call +func ParseRegisterActionTypesResponse(rsp *http.Response) (*RegisterActionTypesResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RegisterActionTypesResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &dest + + } + + return response, nil +} + +// ParseGetActionTypesBySourceIDResponse parses an HTTP response from a GetActionTypesBySourceIDWithResponse call +func ParseGetActionTypesBySourceIDResponse(rsp *http.Response) (*GetActionTypesBySourceIDResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetActionTypesBySourceIDResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest []ActionType + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + } + + return response, nil +} + +// ParseGetActionTypeResponse parses an HTTP response from a GetActionTypeWithResponse call +func ParseGetActionTypeResponse(rsp *http.Response) (*GetActionTypeResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetActionTypeResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ActionType + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + } + + return response, nil +} + +// ParseSubscribeEventWSResponse parses an HTTP response from a SubscribeEventWSWithResponse call +func ParseSubscribeEventWSResponse(rsp *http.Response) (*SubscribeEventWSResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &SubscribeEventWSResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} + +// ParsePublishEventResponse parses an HTTP response from a PublishEventWithResponse call +func ParsePublishEventResponse(rsp *http.Response) (*PublishEventResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &PublishEventResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Event + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + } + + return response, nil +} + +// ParseGetEventTypesResponse parses an HTTP response from a GetEventTypesWithResponse call +func ParseGetEventTypesResponse(rsp *http.Response) (*GetEventTypesResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetEventTypesResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest []EventType + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + +// ParseRegisterEventTypesResponse parses an HTTP response from a RegisterEventTypesWithResponse call +func ParseRegisterEventTypesResponse(rsp *http.Response) (*RegisterEventTypesResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RegisterEventTypesResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &dest + + } + + return response, nil +} + +// ParseGetEventTypesBySourceIDResponse parses an HTTP response from a GetEventTypesBySourceIDWithResponse call +func ParseGetEventTypesBySourceIDResponse(rsp *http.Response) (*GetEventTypesBySourceIDResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetEventTypesBySourceIDResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest []EventType + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + } + + return response, nil +} + +// ParseGetEventTypeResponse parses an HTTP response from a GetEventTypeWithResponse call +func ParseGetEventTypeResponse(rsp *http.Response) (*GetEventTypeResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetEventTypeResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest EventType + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest BaseResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + } + + return response, nil +} + +// ParseSubscribeSIOResponse parses an HTTP response from a SubscribeSIOWithResponse call +func ParseSubscribeSIOResponse(rsp *http.Response) (*SubscribeSIOResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &SubscribeSIOResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} + +// ParsePollSIOResponse parses an HTTP response from a PollSIOWithResponse call +func ParsePollSIOResponse(rsp *http.Response) (*PollSIOResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &PollSIOResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} + +// ParseSubscribeSIO2Response parses an HTTP response from a SubscribeSIO2WithResponse call +func ParseSubscribeSIO2Response(rsp *http.Response) (*SubscribeSIO2Response, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &SubscribeSIO2Response{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} + +// ParsePollSIO2Response parses an HTTP response from a PollSIO2WithResponse call +func ParsePollSIO2Response(rsp *http.Response) (*PollSIO2Response, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &PollSIO2Response{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // Subscribe to actions by source ID (WebSocket) + // (GET /action/{source_id}) + SubscribeActionWS(ctx echo.Context, sourceId SourceID, params SubscribeActionWSParams) error + // Trigger an action + // (POST /action/{source_id}/{name}) + TriggerAction(ctx echo.Context, sourceId SourceID, name ActionName) error + // List action types + // (GET /action_type) + GetActionTypes(ctx echo.Context) error + // Register one or more action types + // (POST /action_type) + RegisterActionTypes(ctx echo.Context) error + // Get action types by source ID + // (GET /action_type/{source_id}) + GetActionTypesBySourceID(ctx echo.Context, sourceId SourceID) error + // Get an action type by source ID and name + // (GET /action_type/{source_id}/{name}) + GetActionType(ctx echo.Context, sourceId SourceID, name ActionName) error + // Subscribe to events by source ID (WebSocket) + // (GET /event/{source_id}) + SubscribeEventWS(ctx echo.Context, sourceId SourceID, params SubscribeEventWSParams) error + // Publish an event + // (POST /event/{source_id}/{name}) + PublishEvent(ctx echo.Context, sourceId SourceID, name EventName) error + // List event types + // (GET /event_type) + GetEventTypes(ctx echo.Context) error + // Register one or more event types + // (POST /event_type) + RegisterEventTypes(ctx echo.Context) error + // Get event types by source ID + // (GET /event_type/{source_id}) + GetEventTypesBySourceID(ctx echo.Context, sourceId SourceID) error + // Get an event type by source ID and name + // (GET /event_type/{source_id}/{name}) + GetEventType(ctx echo.Context, sourceId SourceID, name EventName) error + // Subscribe to events and actions (SocketIO) + // (GET /socket.io) + SubscribeSIO(ctx echo.Context) error + // Poll events and actions (SocketIO) + // (POST /socket.io) + PollSIO(ctx echo.Context) error + // Subscribe to events and actions (SocketIO) + // (GET /socket.io/) + SubscribeSIO2(ctx echo.Context) error + // Poll events and actions (SocketIO) + // (POST /socket.io/) + PollSIO2(ctx echo.Context) error +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +// SubscribeActionWS converts echo context to params. +func (w *ServerInterfaceWrapper) SubscribeActionWS(ctx echo.Context) error { + var err error + // ------------- Path parameter "source_id" ------------- + var sourceId SourceID + + err = runtime.BindStyledParameterWithLocation("simple", false, "source_id", runtime.ParamLocationPath, ctx.Param("source_id"), &sourceId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter source_id: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Parameter object where we will unmarshal all parameters from the context + var params SubscribeActionWSParams + // ------------- Optional query parameter "names" ------------- + + err = runtime.BindQueryParameter("form", true, false, "names", ctx.QueryParams(), ¶ms.Names) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter names: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.SubscribeActionWS(ctx, sourceId, params) + return err +} + +// TriggerAction converts echo context to params. +func (w *ServerInterfaceWrapper) TriggerAction(ctx echo.Context) error { + var err error + // ------------- Path parameter "source_id" ------------- + var sourceId SourceID + + err = runtime.BindStyledParameterWithLocation("simple", false, "source_id", runtime.ParamLocationPath, ctx.Param("source_id"), &sourceId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter source_id: %s", err)) + } + + // ------------- Path parameter "name" ------------- + var name ActionName + + err = runtime.BindStyledParameterWithLocation("simple", false, "name", runtime.ParamLocationPath, ctx.Param("name"), &name) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter name: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.TriggerAction(ctx, sourceId, name) + return err +} + +// GetActionTypes converts echo context to params. +func (w *ServerInterfaceWrapper) GetActionTypes(ctx echo.Context) error { + var err error + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetActionTypes(ctx) + return err +} + +// RegisterActionTypes converts echo context to params. +func (w *ServerInterfaceWrapper) RegisterActionTypes(ctx echo.Context) error { + var err error + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.RegisterActionTypes(ctx) + return err +} + +// GetActionTypesBySourceID converts echo context to params. +func (w *ServerInterfaceWrapper) GetActionTypesBySourceID(ctx echo.Context) error { + var err error + // ------------- Path parameter "source_id" ------------- + var sourceId SourceID + + err = runtime.BindStyledParameterWithLocation("simple", false, "source_id", runtime.ParamLocationPath, ctx.Param("source_id"), &sourceId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter source_id: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetActionTypesBySourceID(ctx, sourceId) + return err +} + +// GetActionType converts echo context to params. +func (w *ServerInterfaceWrapper) GetActionType(ctx echo.Context) error { + var err error + // ------------- Path parameter "source_id" ------------- + var sourceId SourceID + + err = runtime.BindStyledParameterWithLocation("simple", false, "source_id", runtime.ParamLocationPath, ctx.Param("source_id"), &sourceId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter source_id: %s", err)) + } + + // ------------- Path parameter "name" ------------- + var name ActionName + + err = runtime.BindStyledParameterWithLocation("simple", false, "name", runtime.ParamLocationPath, ctx.Param("name"), &name) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter name: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetActionType(ctx, sourceId, name) + return err +} + +// SubscribeEventWS converts echo context to params. +func (w *ServerInterfaceWrapper) SubscribeEventWS(ctx echo.Context) error { + var err error + // ------------- Path parameter "source_id" ------------- + var sourceId SourceID + + err = runtime.BindStyledParameterWithLocation("simple", false, "source_id", runtime.ParamLocationPath, ctx.Param("source_id"), &sourceId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter source_id: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Parameter object where we will unmarshal all parameters from the context + var params SubscribeEventWSParams + // ------------- Optional query parameter "names" ------------- + + err = runtime.BindQueryParameter("form", true, false, "names", ctx.QueryParams(), ¶ms.Names) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter names: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.SubscribeEventWS(ctx, sourceId, params) + return err +} + +// PublishEvent converts echo context to params. +func (w *ServerInterfaceWrapper) PublishEvent(ctx echo.Context) error { + var err error + // ------------- Path parameter "source_id" ------------- + var sourceId SourceID + + err = runtime.BindStyledParameterWithLocation("simple", false, "source_id", runtime.ParamLocationPath, ctx.Param("source_id"), &sourceId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter source_id: %s", err)) + } + + // ------------- Path parameter "name" ------------- + var name EventName + + err = runtime.BindStyledParameterWithLocation("simple", false, "name", runtime.ParamLocationPath, ctx.Param("name"), &name) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter name: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PublishEvent(ctx, sourceId, name) + return err +} + +// GetEventTypes converts echo context to params. +func (w *ServerInterfaceWrapper) GetEventTypes(ctx echo.Context) error { + var err error + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetEventTypes(ctx) + return err +} + +// RegisterEventTypes converts echo context to params. +func (w *ServerInterfaceWrapper) RegisterEventTypes(ctx echo.Context) error { + var err error + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.RegisterEventTypes(ctx) + return err +} + +// GetEventTypesBySourceID converts echo context to params. +func (w *ServerInterfaceWrapper) GetEventTypesBySourceID(ctx echo.Context) error { + var err error + // ------------- Path parameter "source_id" ------------- + var sourceId SourceID + + err = runtime.BindStyledParameterWithLocation("simple", false, "source_id", runtime.ParamLocationPath, ctx.Param("source_id"), &sourceId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter source_id: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetEventTypesBySourceID(ctx, sourceId) + return err +} + +// GetEventType converts echo context to params. +func (w *ServerInterfaceWrapper) GetEventType(ctx echo.Context) error { + var err error + // ------------- Path parameter "source_id" ------------- + var sourceId SourceID + + err = runtime.BindStyledParameterWithLocation("simple", false, "source_id", runtime.ParamLocationPath, ctx.Param("source_id"), &sourceId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter source_id: %s", err)) + } + + // ------------- Path parameter "name" ------------- + var name EventName + + err = runtime.BindStyledParameterWithLocation("simple", false, "name", runtime.ParamLocationPath, ctx.Param("name"), &name) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter name: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetEventType(ctx, sourceId, name) + return err +} + +// SubscribeSIO converts echo context to params. +func (w *ServerInterfaceWrapper) SubscribeSIO(ctx echo.Context) error { + var err error + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.SubscribeSIO(ctx) + return err +} + +// PollSIO converts echo context to params. +func (w *ServerInterfaceWrapper) PollSIO(ctx echo.Context) error { + var err error + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PollSIO(ctx) + return err +} + +// SubscribeSIO2 converts echo context to params. +func (w *ServerInterfaceWrapper) SubscribeSIO2(ctx echo.Context) error { + var err error + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.SubscribeSIO2(ctx) + return err +} + +// PollSIO2 converts echo context to params. +func (w *ServerInterfaceWrapper) PollSIO2(ctx echo.Context) error { + var err error + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PollSIO2(ctx) + return err +} + +// This is a simple interface which specifies echo.Route addition functions which +// are present on both echo.Echo and echo.Group, since we want to allow using +// either of them for path registration +type EchoRouter interface { + CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route +} + +// RegisterHandlers adds each server route to the EchoRouter. +func RegisterHandlers(router EchoRouter, si ServerInterface) { + RegisterHandlersWithBaseURL(router, si, "") +} + +// Registers handlers, and prepends BaseURL to the paths, so that the paths +// can be served under a prefix. +func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) { + + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + router.GET(baseURL+"/action/:source_id", wrapper.SubscribeActionWS) + router.POST(baseURL+"/action/:source_id/:name", wrapper.TriggerAction) + router.GET(baseURL+"/action_type", wrapper.GetActionTypes) + router.POST(baseURL+"/action_type", wrapper.RegisterActionTypes) + router.GET(baseURL+"/action_type/:source_id", wrapper.GetActionTypesBySourceID) + router.GET(baseURL+"/action_type/:source_id/:name", wrapper.GetActionType) + router.GET(baseURL+"/event/:source_id", wrapper.SubscribeEventWS) + router.POST(baseURL+"/event/:source_id/:name", wrapper.PublishEvent) + router.GET(baseURL+"/event_type", wrapper.GetEventTypes) + router.POST(baseURL+"/event_type", wrapper.RegisterEventTypes) + router.GET(baseURL+"/event_type/:source_id", wrapper.GetEventTypesBySourceID) + router.GET(baseURL+"/event_type/:source_id/:name", wrapper.GetEventType) + router.GET(baseURL+"/socket.io", wrapper.SubscribeSIO) + router.POST(baseURL+"/socket.io", wrapper.PollSIO) + router.GET(baseURL+"/socket.io/", wrapper.SubscribeSIO2) + router.POST(baseURL+"/socket.io/", wrapper.PollSIO2) + +} + +// Base64 encoded, gzipped, json marshaled Swagger object +var swaggerSpec = []string{ + + "H4sIAAAAAAAC/+xbXW8bt9L+KwTf98IBVpLjuOe0AnoR121q9LQOogA5QGxY3N2RlvEuuSG5spVA//2A", + "5H5wP2St5LUNFL1KJJEzw5lnZh5++DsOeJJyBkxJPP2OUyJIAgqE+fQ2UJSzv0gC+hNleIpToiLsYWa+", + "s/94WMDXjAoI8VSJDDwsgwgSoufAPUnSWA+NeUDikVRckCVMUyIU1cKnCy4SorCH1TrV46QSlC3xZuM5", + "6uU+srxtPyc8Y1qTWcjXDMS6vhKJXdOpgsTobRhWWkqEIGtj6K8rYOop3BRSeTslYQhhp4NKvbKfEK/j", + "BwEJXxn5g7tlxjMRwMX5Fq9I8/MNDQ9xTYc/NlYMSHXGQ2p98j7zYyoj4yj9OeBM5f8laRrTgGhkTL5I", + "zvR3lVoShgY0JH4veApC5QJbqw5BBoKmeiyeYtCKUFpN8aoFfG/EJeEhxHiKfxHZNxDYa/ycZTTEU3x6", + "egLH8IM/+il8A6PTBfw48k//tRj9FJy+Pn29CCEI/92auwIWcoGneEbYOZW3Tni4/wUCZd1Vt/3o4+X5", + "5atWMDYe/gBLKhUIm5Af16n1RW9nlpj5fwELPMX/N6mqzsQOk5NKeAeYDjDWxPyJbC1lP87Uj4Iul4Vb", + "nwOexGjqic99APgYfJm8lSln0q7hHagKC5d/7OWXvgBrW3f5h15ETbfcU/kTwLy0qkTcgA5xUNxH85O4", + "Y69Msja5NX1ob2zX+iGH6BkJP9gu00Ozk1sJSKn71hSfkRAVIjZeT+vOiITChC4jG0KLob9wtohpcLCt", + "5fzBDHUlFuMumALBSDwDsQLxqxC6dw0U1l325FXJseYvrn7jGQsP9dlfXCErYDCn1UQWAwfE/i79NgVq", + "7WrwwrxNb+lEZ0titiq1xsdy9t3Z73L+/SBB3rYP8RqK/vbE0MuJueXtDX9KyQNKFITIDkKGvffm6B5W", + "NAGpSJK2hZc/IRVRifLYKc5vURqTQIvLgzTFIVEw0hM690UVwfhcLcYrtmFOEK47Vu806P1RdsWu2JGK", + "QACiEjGuv6RsiQLONAD0sAUXyJkhPeRnClGlJwgIeJIACyFEykwGBCSIEJFIKpEFKhMkRoSFqDRhBfrX", + "lEtJ/RhePRrna730/1Db33r18PfOxHYbfxBP1g8llvSiaagdtVijO+NGFUHhrjsax0iRW9gHcn3hUC27", + "CxS1AtmCRVn7m+vLf0ACVCYYhMhfI2maHJI0BEQXqAQLYevaugxRJuEli9fFrrhjx1vubPsA1RahPtVw", + "y5nDP8XwhYqh9djetdDD1j/dQDC/uQb39OLABbfaAuwN457ltprw3NV2Vx49Z7G1XthVa+2ogCcg0ULw", + "5PlrbW2FLUjU1uQeD/5ORHhHBCCb1ogvbOo8kH9O0ankFMWgY3w3HItFlYi8yo6P3wC6aIHMtH5UG6+j", + "4BtMbYHYGF0yQNwo0/IUR6mABb1Hd1RFiFhYpySAcal5hC5MY6lUaT/YwMsUArqggVcTk/94cT5Gv+mE", + "sd7w0LyrYs4dRZc6++6ohLq8uV40Z9N5U17+PSSExqWcUt6MJ4B8EhYTJNIBndNw7qE5Wek5Hpr78e18", + "PB7fRTSIUECYcWDi02XGM2nSNeBskUnKluMHEjQv/7tQbILexqlONQgyQdV6plMzb4hBAFLeKH4LrDz2", + "joCEpnXlB99vMxVxQb+ZvVKln6T0D8jPPShb8DbSjJeClOrCBIXrEELI/pAHMYGQkp+v8JEOCAg5CnjM", + "xcgUEJiikIjbV1cYSRFIUD9f4UipVE4nE0HuxkuqoszPJIh8ZzcOeDK5COBTRGL4CEE0ifmSTxJC2SQg", + "knCZ/3PjE8ZA3GjxN4wuI3Xz4/Fxej9O2fIKH2psrAU9obXqjhoVN36cwcMG02SJSKxN+IVIcjmzRj2/", + "RdaaSQMFV8xahf7MKeeZToUggFTl7MFmhqXStrSjFRFUp4yNhcw7XUxXIKSuH4muNjLzNQZ9EFJXGKbz", + "mUqZFeOpDDIptVAPpTEQCWhFJVWmAH1+R9XvmY8EpFxSxcX6+qjwl/VV20F2Ia8QF+gLpwx95plA51QG", + "XITV7NB+MV4uJ7fs61vfP/Phv6/GVyahqDL53uGSt+8vsIf1Am1KrU50YecpMJJSPMVvxsfjN7pTERWZ", + "jJ5Yj02+l9dVG/31ElQ7P2eFq7TfCk/7azQv587RihL0CfwZD25BjZ12MTeFfF4UtLxOQ4goM640N3PI", + "FqlaXMyHvKqXu+Z1CtI6Q3cAU2kuQtdEu839NDNrrS59P3ezj2rIpLzV23g7x7o3uJvrxjn/6+PXbRd+", + "jEBXbwbOls8HlKVLQXKe5vjPHarBqP0UxFQzGDNTQACmn+axIAbWa9NVlD3NglC7yZTzLEmIWD8Qx7JL", + "oqPSBE0BFVlq1+HKrl9ZmHLKlMTXWnQHiCbfdbwNllIuO8CUn7YhwoqgcguEYlPpZ50Rrl8qPU908+AW", + "l6/rbSS2dj87qVvavAY6OT7eLiYfN2keSW48fNpnXsdpvpl62n9qeUxcx04rbA4+rJkoARXxsA6NG5Wz", + "3c7CorkyInFcS2+kIqIMlINMCGAqXiORX35CaHlYD7zUr7zwIVFo3ZrVXWKtdyxvuUTPc9zibUmJ4moX", + "cU2JBUq4AMTgru6WvgvvutU+AMVdYg7CsnOu/1gY/9R/anUfU4tZp6v3iWED2r365zt4COU7sJ3vrspO", + "WG1pdoL+bD2rtqqH1svrYTJnmCpkPOl60e1ejwid07W2R5C5qm38zEb4sPA5tNXsdXeG83l73qMiPnDA", + "646vERbtxPwQZmfszXZhf8JrT46el+7m56I72a45Y3xisuu8xntJrlts9hyqm9oXEzupbj71UUy3BZ6d", + "RDd/z6HhWxxz92nftad9zxLXw1huzc6DiEHjwcvLc9xmxBxgGCO76klPgusk9HD81nkKeGDJrj2C2nj4", + "h30C0PW8pYMhO0tvOvSx/Nj16r70uOG8A9mxI+VvSo77h6+eE3sx4870GJgYV6F6UV7cTLmhWJLrwi2s", + "eL+g9eTEld5hKHF1qbkrjs/aHR8T6cHpsOPzXWx4W8ylZa6U70GC60ftmgJbsnRxaRjwqPyI5oLzZI5k", + "xLM41OQPqIpAoLmRM9fFZW7lzB+it7OLSzwY4yyNG4pwegUSGryPx7Em95RRRUlMv+U3pIX+XlzVdfRR", + "MdNlquVqXKK6rYFqk7ok++tmFNt0lMdxRxgeXHnAmaIs0+sWPNm+8G1m9V9wDcmTrVAurmFJYu6g59Wc", + "OYL7AFLzdMI+Dsivn5Ug1CxGxkRGaD6ZoxEi6I6LWyJ0ZupgJeSeJvSbBl+SEkV9GlO13oHok38g7UZ4", + "K2hfPGg59E9eCvsb9zLe9Lf6Nfzna92a7Ls72/8yEeMpnqxOJnm7vfEzu2vPs6j9kM/0BBPMhDCy1Etw", + "mISnPX8HcWyeblio6CHa4uLkIj/IsGupXgPUd0y64/ZQ7Z7t7aE7d57zFKF+I9HWXhQRZC5EjRGd62l1", + "vPKEoFL2CXzZPDQYUGMBiEphRyls67P36eYNBzmHhUldzpB9b/UBFj9f7fjLlSuMJjYHG0HNn2gNqnCr", + "sgEVVQeDXdpqf8A0rMrt6gZU5T4v61JYf2B37eH7kSLLd4Jnqa0M+bg/85x5iEJ6jez2ug5dvfa9oFdq", + "qZD78OGbt4XolIJm+d9QdJhbmFkzr/yAGy/yrjfXm/8FAAD//yaxUhg3PgAA", +} + +// GetSwagger returns the content of the embedded swagger specification file +// or error if failed to decode +func decodeSpec() ([]byte, error) { + zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) + if err != nil { + return nil, fmt.Errorf("error base64 decoding spec: %s", err) + } + zr, err := gzip.NewReader(bytes.NewReader(zipped)) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %s", err) + } + var buf bytes.Buffer + _, err = buf.ReadFrom(zr) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %s", err) + } + + return buf.Bytes(), nil +} + +var rawSpec = decodeSpecCached() + +// a naive cached of a decoded swagger spec +func decodeSpecCached() func() ([]byte, error) { + data, err := decodeSpec() + return func() ([]byte, error) { + return data, err + } +} + +// Constructs a synthetic filesystem for resolving external references when loading openapi specifications. +func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { + var res = make(map[string]func() ([]byte, error)) + if len(pathToFile) > 0 { + res[pathToFile] = rawSpec + } + + return res +} + +// GetSwagger returns the Swagger specification corresponding to the generated code +// in this file. The external references of Swagger specification are resolved. +// The logic of resolving external references is tightly connected to "import-mapping" feature. +// Externally referenced files must be embedded in the corresponding golang packages. +// Urls can be supported but this task was out of the scope. +func GetSwagger() (swagger *openapi3.T, err error) { + var resolvePath = PathToRawSpec("") + + loader := openapi3.NewLoader() + loader.IsExternalRefsAllowed = true + loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { + var pathToFile = url.String() + pathToFile = path.Clean(pathToFile) + getSpec, ok := resolvePath[pathToFile] + if !ok { + err1 := fmt.Errorf("path not found: %s", pathToFile) + return nil, err1 + } + return getSpec() + } + var specData []byte + specData, err = rawSpec() + if err != nil { + return + } + swagger, err = loader.LoadFromData(specData) + if err != nil { + return + } + return +} diff --git a/codegen/user_service/user_service_api.go b/codegen/user_service/user_service_api.go new file mode 100644 index 0000000..fe824bb --- /dev/null +++ b/codegen/user_service/user_service_api.go @@ -0,0 +1,290 @@ +// Package codegen provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT. +package codegen + +import ( + "bytes" + "compress/gzip" + "encoding/base64" + "fmt" + "net/http" + "net/url" + "path" + "strings" + "time" + + "github.com/deepmap/oapi-codegen/pkg/runtime" + openapi_types "github.com/deepmap/oapi-codegen/pkg/types" + "github.com/getkin/kin-openapi/openapi3" + "github.com/labstack/echo/v4" +) + +const ( + Access_tokenScopes = "access_token.Scopes" +) + +// BaseResponse defines model for BaseResponse. +type BaseResponse struct { + // Message Error message + Message *string `json:"message,omitempty"` +} + +// Event defines model for Event. +type Event struct { + // EventUuid UUID of the event + EventUuid *openapi_types.UUID `json:"event_uuid,omitempty"` + + // Name event name + Name string `json:"name"` + + // Properties event properties + Properties []Property `json:"properties"` + + // SourceID associated source id + SourceID string `json:"sourceID"` + + // Timestamp timestamp this event took place + Timestamp *time.Time `json:"timestamp,omitempty"` +} + +// Property defines model for Property. +type Property struct { + // Name Name of the property + Name *string `json:"name,omitempty"` + + // Value Value of the property + Value *string `json:"value,omitempty"` +} + +// EventUuid defines model for event_uuid. +type EventUuid = openapi_types.UUID + +// Serial defines model for serial. +type Serial = string + +// BadResponse defines model for BadResponse. +type BadResponse = BaseResponse + +// DeleteEventOK defines model for DeleteEventOK. +type DeleteEventOK = Event + +// OKResponse defines model for OKResponse. +type OKResponse = BaseResponse + +// ResponseNotFound defines model for ResponseNotFound. +type ResponseNotFound = BaseResponse + +// GetEventsParams defines parameters for GetEvents. +type GetEventsParams struct { + // Form Form of the events to get + Form *time.Time `form:"form,omitempty" json:"form,omitempty"` +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // Delete an event + // (DELETE /event/local_storage/{serial}) + DeleteEventBySerial(ctx echo.Context, serial Serial) error + // Delete an event + // (DELETE /event/{event_uuid}) + DeleteEvent(ctx echo.Context, eventUuid EventUuid) error + // Get all events + // (GET /events) + GetEvents(ctx echo.Context, params GetEventsParams) error +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +// DeleteEventBySerial converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteEventBySerial(ctx echo.Context) error { + var err error + // ------------- Path parameter "serial" ------------- + var serial Serial + + err = runtime.BindStyledParameterWithLocation("simple", false, "serial", runtime.ParamLocationPath, ctx.Param("serial"), &serial) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter serial: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.DeleteEventBySerial(ctx, serial) + return err +} + +// DeleteEvent converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteEvent(ctx echo.Context) error { + var err error + // ------------- Path parameter "event_uuid" ------------- + var eventUuid EventUuid + + err = runtime.BindStyledParameterWithLocation("simple", false, "event_uuid", runtime.ParamLocationPath, ctx.Param("event_uuid"), &eventUuid) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter event_uuid: %s", err)) + } + + ctx.Set(Access_tokenScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.DeleteEvent(ctx, eventUuid) + return err +} + +// GetEvents converts echo context to params. +func (w *ServerInterfaceWrapper) GetEvents(ctx echo.Context) error { + var err error + + ctx.Set(Access_tokenScopes, []string{""}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetEventsParams + // ------------- Optional query parameter "form" ------------- + + err = runtime.BindQueryParameter("form", true, false, "form", ctx.QueryParams(), ¶ms.Form) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetEvents(ctx, params) + return err +} + +// This is a simple interface which specifies echo.Route addition functions which +// are present on both echo.Echo and echo.Group, since we want to allow using +// either of them for path registration +type EchoRouter interface { + CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route +} + +// RegisterHandlers adds each server route to the EchoRouter. +func RegisterHandlers(router EchoRouter, si ServerInterface) { + RegisterHandlersWithBaseURL(router, si, "") +} + +// Registers handlers, and prepends BaseURL to the paths, so that the paths +// can be served under a prefix. +func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) { + + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + router.DELETE(baseURL+"/event/local_storage/:serial", wrapper.DeleteEventBySerial) + router.DELETE(baseURL+"/event/:event_uuid", wrapper.DeleteEvent) + router.GET(baseURL+"/events", wrapper.GetEvents) + +} + +// Base64 encoded, gzipped, json marshaled Swagger object +var swaggerSpec = []string{ + + "H4sIAAAAAAAC/9xYbW/bNhD+KwS3DxsgWbKjpImAfmiatggCJMXSbsDiwDiLZ5uNRKokldY1/N8HUrQt", + "WzLidtkGrAjQULw33j13fJgFzWRRSoHCaJouaAkKCjSo3AofUZhRVXFmVwx1pnhpuBQ0pR8/Xl4QOSFm", + "hsTJESPJFA0NKLf7JZgZDaiAAmnatBRQhZ8rrpDR1KgKA6qzGRbgHH6FosytQn9whMnxyYsQT8/GYX/A", + "jkJIjk/CZHBycnycJHEcxzSgE6kKMDSl3rSZl1ZbG8XFlC6XAdWoOOTt+G/d99UJcplBTrSRCqbYfQRv", + "6ODwbfSnZ3FHUEtrQ5dSaHRpPgf2m1/bZSaFQWHsr1CWOc/Ahhx90jbuRcPdzwonNKU/RZsaRvWujs5B", + "49qoc7l9/HNgxB4EtaHLgF5gjgbf2CrdXD1bEM5el3e3QZhzyqz/m6t/PQM3V9bxSuJamreyEuwA9+sq", + "L2iBWlvApPRaGlIbWAbPFGDD5Nqmx0tD0TatkiUqw2s0rWPaRfwbpaQiq+2ggdYmGCw2gd2IfL7Cd7un", + "/Bc5/oSZg09d6FYo3zU/nu7mVSvumqrHj9trnsr1dOh7OmVcP6TAGHYa3o67y3xDouHkbrEaD9veHlEw", + "qWhAHyGv7PYtiAuuH+gy2KNRSIZ5Q+G1qr6h2i/vU7QST5IBxng8Ds/YEYbJBE/DcXIyCc+ypJ/0Jwwz", + "9qJpLAMNUocVT10uNoaENHziIR9qM88xHOxR5CZval7jF2KzTCa+Dzp0eCZF2G8o+S33ne0kaKPmQbul", + "+YoI7zAgPrukTlpAuCau1D26vA8oN1jop7rxfV3fOd3gG5QCt9ayUhleXrSxAVrLjINBRmoh4qqyB4Rd", + "yDO8QG2gKNvG11vEzLhe37LygZQ5ZNhsGAYGQyvfeQdubqy7zVl8N21h/76jt9eJabV3dzdeQ4Grxi5X", + "uh0H93XcVf/dfn5avz2F3F2fVYqb+a2taR0jZBlqPTLyAd3wdhf7DIGh2lztryozk4p/c6Df+IKSX+G8", + "Hs1cTGQ72GEVx0dZyTNTKXQLHApi/9U7HhMFMg4vh/SXUuEElQ4zmUsVOuhhShioh1+HlGiVaTQvh3Rm", + "TKnTKFLwpTflZlaNK43KX0u9TBbRZYZ/zCDHD5jNolxOZVQAF1HdMf6/0RiEQDWy5keCT2dmdBrH5dde", + "KaZD+sPR5tbSPxiu+cKdi9E4r/CJiHkxJZDbGF6DhpvbOqr/IKQ6nGgXCR9s33LtsPzq/SWZSOV+f+3M", + "k48aFblF9cgz7A0FuTRWuNLILJkuQMAU7VJpAoJZTa5IjWgr4K3o2oDuDR123VROaYcLG4IdoKh0Dd9H", + "O9mpLFFAyWlKj3px78hOBDAz1z2RmzmRG2IjP8SiRc2El3U7WArXboyaTxIQ67vdNrLrr0u23ne04Xx+", + "u2LWzdfHXfe43ohEnpDbCb9FpwdxvG/Yr+WiBuFcBjSJ+x18qaYV0qwvNJrEydOmW5RyGdDjQ2JqvgPc", + "OKuKAtS8M50GpjZJNTmh91bcF2uxYV3PVaLvLk2D+P1YebbfI/+vCrks2Jdy6zzv0BDIc+LFdivyDs2b", + "1c5OPbbtvJWq2OLWeudx/rlCNd/cf5ZG0O6H7CAe9MPY/nyI49T9/Hko8dhT+YNfdwfxNv/G3CVte96c", + "eoOUv1nwVq1a9W4QElejbSpyd2/zY2d3dw33z+9K5TSl0eMgcleD6zDvvLtBFOaOoa7RpHf+MEOX98u/", + "AgAA//8z3sRjChIAAA==", +} + +// GetSwagger returns the content of the embedded swagger specification file +// or error if failed to decode +func decodeSpec() ([]byte, error) { + zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) + if err != nil { + return nil, fmt.Errorf("error base64 decoding spec: %s", err) + } + zr, err := gzip.NewReader(bytes.NewReader(zipped)) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %s", err) + } + var buf bytes.Buffer + _, err = buf.ReadFrom(zr) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %s", err) + } + + return buf.Bytes(), nil +} + +var rawSpec = decodeSpecCached() + +// a naive cached of a decoded swagger spec +func decodeSpecCached() func() ([]byte, error) { + data, err := decodeSpec() + return func() ([]byte, error) { + return data, err + } +} + +// Constructs a synthetic filesystem for resolving external references when loading openapi specifications. +func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { + var res = make(map[string]func() ([]byte, error)) + if len(pathToFile) > 0 { + res[pathToFile] = rawSpec + } + + return res +} + +// GetSwagger returns the Swagger specification corresponding to the generated code +// in this file. The external references of Swagger specification are resolved. +// The logic of resolving external references is tightly connected to "import-mapping" feature. +// Externally referenced files must be embedded in the corresponding golang packages. +// Urls can be supported but this task was out of the scope. +func GetSwagger() (swagger *openapi3.T, err error) { + var resolvePath = PathToRawSpec("") + + loader := openapi3.NewLoader() + loader.IsExternalRefsAllowed = true + loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { + var pathToFile = url.String() + pathToFile = path.Clean(pathToFile) + getSpec, ok := resolvePath[pathToFile] + if !ok { + err1 := fmt.Errorf("path not found: %s", pathToFile) + return nil, err1 + } + return getSpec() + } + var specData []byte + specData, err = rawSpec() + if err != nil { + return + } + swagger, err = loader.LoadFromData(specData) + if err != nil { + return + } + return +} diff --git a/common/version.go b/common/version.go new file mode 100644 index 0000000..feb4161 --- /dev/null +++ b/common/version.go @@ -0,0 +1,3 @@ +package common + +const Version = "0.4.4" diff --git a/dist/artifacts.json b/dist/artifacts.json new file mode 100644 index 0000000..a166796 --- /dev/null +++ b/dist/artifacts.json @@ -0,0 +1 @@ +[{"name":"build/sysroot/usr/bin/casaos-user-service","path":"dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service","goos":"linux","goarch":"amd64","goamd64":"v1","internal_type":4,"type":"Binary","extra":{"Binary":"casaos-user-service","Ext":"","ID":"casaos-user-service-amd64"}}] \ No newline at end of file diff --git a/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service b/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service new file mode 100644 index 0000000..a7e5075 Binary files /dev/null and b/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service differ diff --git a/dist/config.yaml b/dist/config.yaml new file mode 100644 index 0000000..1cbf03b --- /dev/null +++ b/dist/config.yaml @@ -0,0 +1,131 @@ +project_name: casaos-user-service +release: + github: + owner: IceWhaleTech + name: CasaOS-UserService + draft: true + prerelease: auto + name_template: v{{ .Version }} + mode: replace +builds: + - id: casaos-user-service-amd64 + goos: + - linux + goarch: + - amd64 + goarm: + - "6" + gomips: + - hardfloat + goamd64: + - v1 + targets: + - linux_amd64_v1 + dir: . + main: . + binary: build/sysroot/usr/bin/casaos-user-service + builder: go + gobinary: go + command: build + ldflags: + - -extldflags "-static" + tags: + - musl + - netgo + - osusergo + gcflags: + - all=-N -l + env: + - CC=x86_64-linux-gnu-gcc +archives: + - id: casaos-user-service + builds: + - casaos-user-service-amd64 + - casaos-user-service-arm64 + - casaos-user-service-arm-7 + name_template: '{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}' + format: tar.gz + files: + - src: build/**/* + - id: casaos-user-service-migration-tool + builds: + - casaos-user-service-migration-tool-amd64 + - casaos-user-service-migration-tool-arm64 + - casaos-user-service-migration-tool-arm-7 + name_template: '{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}' + format: tar.gz + files: + - src: build/sysroot/etc/**/* +snapshot: + name_template: '{{ incpatch .Version }}' +checksum: + name_template: checksums.txt + algorithm: sha256 +changelog: + filters: + exclude: + - '^docs:' + - '^test:' + sort: asc +dist: dist +env_files: + github_token: ~/.config/goreleaser/github_token + gitlab_token: ~/.config/goreleaser/gitlab_token + gitea_token: ~/.config/goreleaser/gitea_token +before: + hooks: + - go generate + - go run github.com/google/go-licenses@latest check . --disallowed_types=restricted + - go mod tidy + - go test -race -v ./... +source: + name_template: '{{ .ProjectName }}-{{ .Version }}' + format: tar.gz +gomod: + gobinary: go +announce: + twitter: + message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}' + mastodon: + message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}' + server: "" + reddit: + title_template: '{{ .ProjectName }} {{ .Tag }} is out!' + url_template: '{{ .ReleaseURL }}' + slack: + message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}' + username: GoReleaser + discord: + message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}' + author: GoReleaser + color: "3888754" + icon_url: https://goreleaser.com/static/avatar.png + teams: + title_template: '{{ .ProjectName }} {{ .Tag }} is out!' + message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}' + color: '#2D313E' + icon_url: https://goreleaser.com/static/avatar.png + smtp: + subject_template: '{{ .ProjectName }} {{ .Tag }} is out!' + body_template: 'You can view details from: {{ .ReleaseURL }}' + mattermost: + message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}' + title_template: '{{ .ProjectName }} {{ .Tag }} is out!' + username: GoReleaser + linkedin: + message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}' + telegram: + message_template: '{{ .ProjectName }} {{ mdv2escape .Tag }} is out! Check it out at {{ mdv2escape .ReleaseURL }}' + parse_mode: MarkdownV2 + webhook: + message_template: '{ "message": "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"}' + content_type: application/json; charset=utf-8 + opencollective: + title_template: '{{ .Tag }}' + message_template: '{{ .ProjectName }} {{ .Tag }} is out!
Check it out at {{ .ReleaseURL }}' +git: + tag_sort: -version:refname +github_urls: + download: https://github.com +gitlab_urls: + download: https://gitlab.com diff --git a/dist/metadata.json b/dist/metadata.json new file mode 100644 index 0000000..c44fe19 --- /dev/null +++ b/dist/metadata.json @@ -0,0 +1 @@ +{"project_name":"casaos-user-service","tag":"v0.4.5","previous_tag":"v0.4.4-alpha7","version":"0.4.6","commit":"4d2b65e34c6d01800273009d60756205c08cb0c3","date":"2024-02-02T15:35:39.294862443+07:00","runtime":{"goos":"linux","goarch":"amd64"}} \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5ac57d0 --- /dev/null +++ b/go.mod @@ -0,0 +1,86 @@ +module github.com/KaySar12/NextZen-UserService + +go 1.20 + +require ( + github.com/KaySar12/NextZen-Common v1.0.1 + github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf + github.com/deepmap/oapi-codegen v1.12.4 + github.com/getkin/kin-openapi v0.117.0 + github.com/gin-contrib/gzip v0.0.6 + github.com/gin-gonic/gin v1.9.1 + github.com/glebarez/sqlite v1.8.0 + github.com/labstack/echo/v4 v4.10.2 + github.com/satori/go.uuid v1.2.0 + github.com/tidwall/gjson v1.14.4 + go.uber.org/zap v1.24.0 + golang.org/x/net v0.17.0 + gopkg.in/ini.v1 v1.67.0 + gorm.io/gorm v1.25.0 +) + +require ( + github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect + github.com/benbjohnson/clock v1.3.1 // indirect + github.com/bytedance/sonic v1.9.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/glebarez/go-sqlite v1.21.1 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/invopop/yaml v0.2.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/labstack/gommon v0.4.0 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/perimeterx/marshmallow v1.1.4 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/samber/lo v1.38.1 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/text v0.13.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + modernc.org/libc v1.22.4 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/sqlite v1.21.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..3849aaf --- /dev/null +++ b/go.sum @@ -0,0 +1,251 @@ +github.com/IceWhaleTech/CasaOS-Common v0.4.8-alpha3 h1:5E5LAqi2uXpOZqcPOgQ4m6d9MagYyfhKIFXnzd8s3W4= +github.com/IceWhaleTech/CasaOS-Common v0.4.8-alpha3/go.mod h1:2IuYyy5qW1BE6jqC6M+tOU+WtUec1K565rLATBJ9p/0= +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/benbjohnson/clock v1.3.1 h1:Heo0FGXzOxUHquZbraxt+tT7UXVDhesUQH5ISbsOkCQ= +github.com/benbjohnson/clock v1.3.1/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP7g5Q2s= +github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/getkin/kin-openapi v0.117.0 h1:QT2DyGujAL09F4NrKDHJGsUoIprlIcFVHWDVDcUFE8A= +github.com/getkin/kin-openapi v0.117.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc= +github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY= +github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E= +github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc= +github.com/glebarez/sqlite v1.8.0/go.mod h1:bpET16h1za2KOOMb8+jCp6UBP/iahDpfPQqSaYLTLx8= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= +github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= +github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= +github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= +github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw= +github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= +github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU= +gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +modernc.org/libc v1.22.4 h1:wymSbZb0AlrjdAVX3cjreCHTPCpPARbQXNz6BHPzdwQ= +modernc.org/libc v1.22.4/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/sqlite v1.21.2 h1:ixuUG0QS413Vfzyx6FWx6PYTmHaOegTY+hjzhn7L+a0= +modernc.org/sqlite v1.21.2/go.mod h1:cxbLkB5WS32DnQqeH4h4o1B0eMr8W/y8/RGuxQ3JsC0= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/main.go b/main.go new file mode 100644 index 0000000..67a9041 --- /dev/null +++ b/main.go @@ -0,0 +1,176 @@ +//go:generate bash -c "mkdir -p codegen/user_service && go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.12.4 -generate types,server,spec -package codegen api/user-service/openapi.yaml > codegen/user_service/user_service_api.go" +//go:generate bash -c "mkdir -p codegen/message_bus && go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.12.4 -package message_bus https://raw.githubusercontent.com/IceWhaleTech/CasaOS-MessageBus/main/api/message_bus/openapi.yaml > codegen/message_bus/api.go" +package main + +import ( + _ "embed" + "flag" + "fmt" + "net" + "net/http" + "os" + "path/filepath" + "strings" + "time" + + "github.com/IceWhaleTech/CasaOS-Common/external" + "github.com/IceWhaleTech/CasaOS-Common/model" + util_http "github.com/IceWhaleTech/CasaOS-Common/utils/http" + "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" + "github.com/IceWhaleTech/CasaOS-Common/utils/logger" + "github.com/IceWhaleTech/CasaOS-UserService/common" + "github.com/IceWhaleTech/CasaOS-UserService/pkg/config" + "github.com/IceWhaleTech/CasaOS-UserService/pkg/sqlite" + "github.com/IceWhaleTech/CasaOS-UserService/pkg/utils/encryption" + "github.com/IceWhaleTech/CasaOS-UserService/pkg/utils/random" + "github.com/IceWhaleTech/CasaOS-UserService/route" + "github.com/IceWhaleTech/CasaOS-UserService/service" + "github.com/coreos/go-systemd/daemon" + "go.uber.org/zap" +) + +const localhost = "127.0.0.1" + +var ( + commit = "private build" + date = "private build" + + //go:embed api/index.html + _docHTML string + + //go:embed api/user-service/openapi.yaml + _docYAML string + + //go:embed build/sysroot/etc/casaos/user-service.conf.sample + _confSample string +) + +func init() { + configFlag := flag.String("c", "", "config address") + dbFlag := flag.String("db", "", "db path") + resetUserFlag := flag.Bool("ru", false, "reset user") + userFlag := flag.String("user", "", "user name") + versionFlag := flag.Bool("v", false, "version") + + flag.Parse() + + if *versionFlag { + fmt.Printf("v%s\n", common.Version) + os.Exit(0) + } + + println("git commit:", commit) + println("build date:", date) + + config.InitSetup(*configFlag, _confSample) + + logger.LogInit(config.AppInfo.LogPath, config.AppInfo.LogSaveName, config.AppInfo.LogFileExt) + + if len(*dbFlag) == 0 { + *dbFlag = config.AppInfo.DBPath + } + + sqliteDB := sqlite.GetDb(*dbFlag) + service.MyService = service.NewService(sqliteDB, config.CommonInfo.RuntimePath) + + if *resetUserFlag { + if userFlag == nil || len(*userFlag) == 0 { + fmt.Println("user is empty") + return + } + + userData := service.MyService.User().GetUserAllInfoByName(*userFlag) + + if userData.Id == 0 { + fmt.Println("user not exist") + return + } + + password := random.RandomString(6, false) + userData.Password = encryption.GetMD5ByStr(password) + service.MyService.User().UpdateUserPassword(userData) + fmt.Println("User reset successful") + fmt.Println("UserName:" + userData.Username) + fmt.Println("Password:" + password) + } +} + +func main() { + v1Router := route.InitRouter() + v2Router := route.InitV2Router() + v2DocRouter := route.InitV2DocRouter(_docHTML, _docYAML) + + _, publicKey := service.MyService.User().GetKeyPair() + + jswkJSON, err := jwt.GenerateJwksJSON(publicKey) + if err != nil { + panic(err) + } + + mux := &util_http.HandlerMultiplexer{ + HandlerMap: map[string]http.Handler{ + "v1": v1Router, + "v2": v2Router, + "doc": v2DocRouter, + strings.SplitN(jwt.JWKSPath, "/", 2)[0]: jwt.JWKSHandler(jswkJSON), + }, + } + + listener, err := net.Listen("tcp", net.JoinHostPort(localhost, "0")) + if err != nil { + panic(err) + } + + apiPaths := []string{ + "/v1/users", + route.V2APIPath, + route.V2DocPath, + "/" + jwt.JWKSPath, + } + for _, v := range apiPaths { + err = service.MyService.Gateway().CreateRoute(&model.Route{ + Path: v, + Target: "http://" + listener.Addr().String(), + }) + + if err != nil { + panic(err) + } + } + + // write address file + addressFilePath, err := writeAddressFile(config.CommonInfo.RuntimePath, external.UserServiceAddressFilename, "http://"+listener.Addr().String()) + if err != nil { + panic(err) + } + + if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil { + logger.Error("Failed to notify systemd that user service is ready", zap.Any("error", err)) + } else if supported { + logger.Info("Notified systemd that user service is ready") + } else { + logger.Info("This process is not running as a systemd service.") + } + go route.EventListen() + logger.Info("User service is listening...", zap.Any("address", listener.Addr().String()), zap.String("filepath", addressFilePath)) + + s := &http.Server{ + Handler: mux, + ReadHeaderTimeout: 5 * time.Second, // fix G112: Potential slowloris attack (see https://github.com/securego/gosec) + } + + err = s.Serve(listener) // not using http.serve() to fix G114: Use of net/http serve function that has no support for setting timeouts (see https://github.com/securego/gosec) + if err != nil { + panic(err) + } +} + +func writeAddressFile(runtimePath string, filename string, address string) (string, error) { + err := os.MkdirAll(runtimePath, 0o755) + if err != nil { + return "", err + } + + filepath := filepath.Join(runtimePath, filename) + return filepath, os.WriteFile(filepath, []byte(address), 0o600) +} diff --git a/model/event.go b/model/event.go new file mode 100644 index 0000000..f5768ca --- /dev/null +++ b/model/event.go @@ -0,0 +1,13 @@ +package model + +type EventModel struct { + UUID string `gorm:"primaryKey" json:"uuid"` + SourceID string `gorm:"index" json:"source_id"` + Name string `json:"name"` + Properties string `gorm:"serializer:json" json:"properties"` + Timestamp int64 `gorm:"autoCreateTime:milli" json:"timestamp"` +} + +func (p *EventModel) TableName() string { + return "events" +} diff --git a/model/sys_common.go b/model/sys_common.go new file mode 100644 index 0000000..9d56b36 --- /dev/null +++ b/model/sys_common.go @@ -0,0 +1,19 @@ +package model + +type CommonModel struct { + RuntimePath string +} + +type APPModel struct { + LogPath string + LogSaveName string + LogFileExt string + UserDataPath string + DBPath string +} + +type Result struct { + Success int `json:"success" example:"200"` + Message string `json:"message" example:"ok"` + Data interface{} `json:"data" example:"返回结果"` +} diff --git a/model/system_model/verify_information.go b/model/system_model/verify_information.go new file mode 100644 index 0000000..7404202 --- /dev/null +++ b/model/system_model/verify_information.go @@ -0,0 +1,16 @@ +/* + * @Author: LinkLeong link@icewhale.com + * @Date: 2022-06-15 11:30:47 + * @LastEditors: LinkLeong + * @LastEditTime: 2022-06-23 18:40:40 + * @Description: + * @Website: https://www.casaos.io + * Copyright (c) 2022 by icewhale, All Rights Reserved. + */ +package system_model + +type VerifyInformation struct { + RefreshToken string `json:"refresh_token"` + AccessToken string `json:"access_token"` + ExpiresAt int64 `json:"expires_at"` +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8ce77a7 --- /dev/null +++ b/package.json @@ -0,0 +1,36 @@ +{ + "name": "casaos-userservice-openapi", + "version": "0.0.1", + "scripts": { + "build": "rm -rf dist && tsc && rm -rf generate", + "generate:local": "openapi-generator-cli generate -g typescript-axios -i ./api/user-service/openapi.yaml -o ./generate", + "generate:npx": "npx @openapitools/openapi-generator-cli generate -g typescript-axios -i ./api/user-service/openapi.yaml -o ./generate", + "generate:ts": "npx openapi-typescript-codegen --input ./api/user-service/openapi.yaml --output ./generate", + "publish": "npm publish --access public", + "start": "yarn generate:ts && yarn build" + }, + "homepage": "https://github.com/IceWhaleTech/CasaOS-UserService#readme", + "description": "Casaos-Localstorage Typescript+Axios SDK", + "keywords": [ + "CasaOS-UserService", + "SDK", + "CasaOS-UserService Axios" + ], + "main": "dist/index", + "files": [ + "LICENSE", + "README.md", + "dist" + ], + "dependencies": { + "axios": "^1.1.0" + }, + "devDependencies": { + "@openapitools/openapi-generator-cli": "2.5.2", + "@types/node": "^18.8.3", + "openapi-typescript-codegen": "^0.23.0", + "typescript": "^4.9.5" + }, + "author": "casaos", + "license": "Apache-2.0" +} diff --git a/pkg/config/config.go b/pkg/config/config.go new file mode 100644 index 0000000..70fbbe2 --- /dev/null +++ b/pkg/config/config.go @@ -0,0 +1,5 @@ +package config + +const ( + UserServiceConfigFilePath = "/etc/casaos/user-service.conf" +) diff --git a/pkg/config/init.go b/pkg/config/init.go new file mode 100644 index 0000000..ac9b341 --- /dev/null +++ b/pkg/config/init.go @@ -0,0 +1,94 @@ +package config + +import ( + "fmt" + "log" + "os" + + "github.com/IceWhaleTech/CasaOS-Common/utils/constants" + "github.com/IceWhaleTech/CasaOS-UserService/model" + "gopkg.in/ini.v1" +) + +// models with default values + +var ( + CommonInfo = &model.CommonModel{ + RuntimePath: constants.DefaultRuntimePath, + } + + AppInfo = &model.APPModel{ + DBPath: constants.DefaultDataPath, + UserDataPath: constants.DefaultDataPath, + LogPath: constants.DefaultLogPath, + LogSaveName: "user", + LogFileExt: "log", + } + + Cfg *ini.File + ConfigFilePath string +) + +func InitSetup(config string, sample string) { + ConfigFilePath = UserServiceConfigFilePath + if len(config) > 0 { + ConfigFilePath = config + } + + // create default config file if not exist + if _, err := os.Stat(ConfigFilePath); os.IsNotExist(err) { + fmt.Println("config file not exist, create it") + // create config file + file, err := os.Create(ConfigFilePath) + if err != nil { + panic(err) + } + defer file.Close() + + // write default config + _, err = file.WriteString(sample) + if err != nil { + panic(err) + } + } + + var err error + + Cfg, err = ini.Load(ConfigFilePath) + if err != nil { + fmt.Printf("Fail to read file: %v", err) + os.Exit(1) + } + + mapTo("common", CommonInfo) + mapTo("app", AppInfo) +} + +func SaveSetup(config string) { + reflectFrom("common", CommonInfo) + reflectFrom("app", AppInfo) + + configFilePath := UserServiceConfigFilePath + if len(config) > 0 { + configFilePath = config + } + + if err := Cfg.SaveTo(configFilePath); err != nil { + fmt.Printf("Fail to save file: %v", err) + os.Exit(1) + } +} + +func mapTo(section string, v interface{}) { + err := Cfg.Section(section).MapTo(v) + if err != nil { + log.Fatalf("Cfg.MapTo %s err: %v", section, err) + } +} + +func reflectFrom(section string, v interface{}) { + err := Cfg.Section(section).ReflectFrom(v) + if err != nil { + log.Fatalf("Cfg.ReflectFrom %s err: %v", section, err) + } +} diff --git a/pkg/sqlite/db.go b/pkg/sqlite/db.go new file mode 100644 index 0000000..331d64e --- /dev/null +++ b/pkg/sqlite/db.go @@ -0,0 +1,49 @@ +/* + * @Author: LinkLeong link@icewhale.com + * @Date: 2022-05-13 18:15:46 + * @LastEditors: LinkLeong + * @LastEditTime: 2022-07-11 18:10:53 + * @Description: + * @Website: https://www.casaos.io + * Copyright (c) 2022 by icewhale, All Rights Reserved. + */ +package sqlite + +import ( + "time" + + "github.com/IceWhaleTech/CasaOS-Common/utils/logger" + "github.com/IceWhaleTech/CasaOS-UserService/model" + "github.com/IceWhaleTech/CasaOS-UserService/pkg/utils/file" + model2 "github.com/IceWhaleTech/CasaOS-UserService/service/model" + "github.com/glebarez/sqlite" + "go.uber.org/zap" + "gorm.io/gorm" +) + +var gdb *gorm.DB + +func GetDb(dbPath string) *gorm.DB { + if gdb != nil { + return gdb + } + + file.IsNotExistMkDir(dbPath) + db, err := gorm.Open(sqlite.Open(dbPath+"/user.db"), &gorm.Config{}) + if err != nil { + panic(err) + } + + c, _ := db.DB() + c.SetMaxIdleConns(10) + c.SetMaxOpenConns(1) + c.SetConnMaxIdleTime(time.Second * 1000) + + gdb = db + + err = db.AutoMigrate(model2.UserDBModel{}, model.EventModel{}) + if err != nil { + logger.Error("check or create db error", zap.Any("error", err)) + } + return db +} diff --git a/pkg/utils/encryption/md5_helper.go b/pkg/utils/encryption/md5_helper.go new file mode 100644 index 0000000..1a142e6 --- /dev/null +++ b/pkg/utils/encryption/md5_helper.go @@ -0,0 +1,21 @@ +/* + * @Author: LinkLeong link@icewhale.com + * @Date: 2022-06-14 14:33:25 + * @LastEditors: LinkLeong + * @LastEditTime: 2022-06-14 14:33:49 + * @Description: + * @Website: https://www.casaos.io + * Copyright (c) 2022 by icewhale, All Rights Reserved. + */ +package encryption + +import ( + "crypto/md5" + "encoding/hex" +) + +func GetMD5ByStr(str string) string { + h := md5.New() + h.Write([]byte(str)) + return hex.EncodeToString(h.Sum(nil)) +} diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go new file mode 100644 index 0000000..93bf307 --- /dev/null +++ b/pkg/utils/file/file.go @@ -0,0 +1,145 @@ +package file + +import ( + "io" + "os" + "path" + "strings" +) + +// GetExt get the file ext +func GetExt(fileName string) string { + return path.Ext(fileName) +} + +func CheckNotExist(src string) bool { + _, err := os.Stat(src) + + return os.IsNotExist(err) +} + +// IsNotExistMkDir create a directory if it does not exist +func IsNotExistMkDir(src string) error { + if notExist := CheckNotExist(src); notExist { + if err := MkDir(src); err != nil { + return err + } + } + + return nil +} + +// MkDir create a directory +func MkDir(src string) error { + err := os.MkdirAll(src, os.ModePerm) + if err != nil { + return err + } + os.Chmod(src, 0o777) + + return nil +} + +// IsNotExistMkDir create a directory if it does not exist +func IsNotExistCreateFile(src string) error { + if notExist := CheckNotExist(src); notExist { + if err := CreateFile(src); err != nil { + return err + } + } + + return nil +} + +func Exists(path string) bool { + _, err := os.Stat(path) // os.Stat获取文件信息 + if err != nil { + return os.IsExist(err) + } + return true +} + +func CreateFile(path string) error { + file, err := os.Create(path) + if err != nil { + return err + } + defer file.Close() + return nil +} + +func ReadFullFile(path string) []byte { + file, err := os.Open(path) + if err != nil { + return []byte("") + } + defer file.Close() + content, err := io.ReadAll(file) + if err != nil { + return []byte("") + } + return content +} + +/** + * @description: + * @param {*} src + * @param {*} dst + * @param {string} style + * @return {*} + * @method: + * @router: + */ +func CopySingleFile(src, dst, style string) error { + var err error + var srcfd *os.File + var dstfd *os.File + var srcinfo os.FileInfo + + if Exists(dst) { + if style == "skip" { + return nil + } else { + os.Remove(dst) + } + } + + if srcfd, err = os.Open(src); err != nil { + return err + } + defer srcfd.Close() + + if dstfd, err = os.Create(dst); err != nil { + return err + } + defer dstfd.Close() + + if _, err = io.Copy(dstfd, srcfd); err != nil { + return err + } + if srcinfo, err = os.Stat(src); err != nil { + return err + } + return os.Chmod(dst, srcinfo.Mode()) +} + +func WriteToPath(data []byte, path, name string) error { + fullPath := path + if strings.HasSuffix(path, "/") { + fullPath += name + } else { + fullPath += "/" + name + } + IsNotExistCreateFile(fullPath) + file, err := os.OpenFile(fullPath, + os.O_WRONLY|os.O_TRUNC|os.O_CREATE, + 0o666, + ) + if err != nil { + return err + } + defer file.Close() + _, err = file.Write(data) + + return err +} diff --git a/pkg/utils/file/image.go b/pkg/utils/file/image.go new file mode 100644 index 0000000..105a59e --- /dev/null +++ b/pkg/utils/file/image.go @@ -0,0 +1,182 @@ +package file + +import ( + "errors" + "net/http" + "os" + "path/filepath" + "strings" +) + +func ImageExtArray() []string { + + ext := []string{ + "ase", + "art", + "bmp", + "blp", + "cd5", + "cit", + "cpt", + "cr2", + "cut", + "dds", + "dib", + "djvu", + "egt", + "exif", + "gif", + "gpl", + "grf", + "icns", + "ico", + "iff", + "jng", + "jpeg", + "jpg", + "jfif", + "jp2", + "jps", + "lbm", + "max", + "miff", + "mng", + "msp", + "nitf", + "ota", + "pbm", + "pc1", + "pc2", + "pc3", + "pcf", + "pcx", + "pdn", + "pgm", + "PI1", + "PI2", + "PI3", + "pict", + "pct", + "pnm", + "pns", + "ppm", + "psb", + "psd", + "pdd", + "psp", + "px", + "pxm", + "pxr", + "qfx", + "raw", + "rle", + "sct", + "sgi", + "rgb", + "int", + "bw", + "tga", + "tiff", + "tif", + "vtf", + "xbm", + "xcf", + "xpm", + "3dv", + "amf", + "ai", + "awg", + "cgm", + "cdr", + "cmx", + "dxf", + "e2d", + "egt", + "eps", + "fs", + "gbr", + "odg", + "svg", + "stl", + "vrml", + "x3d", + "sxd", + "v2d", + "vnd", + "wmf", + "emf", + "art", + "xar", + "png", + "webp", + "jxr", + "hdp", + "wdp", + "cur", + "ecw", + "iff", + "lbm", + "liff", + "nrrd", + "pam", + "pcx", + "pgf", + "sgi", + "rgb", + "rgba", + "bw", + "int", + "inta", + "sid", + "ras", + "sun", + "tga", + } + + return ext +} + +/** +* @description:get a image's ext +* @param {string} path "file path" +* @return {string} ext "file ext" +* @return {error} err "error info" + */ +func GetImageExt(p string) (string, error) { + file, err := os.Open(p) + if err != nil { + return "", err + } + + buff := make([]byte, 512) + + _, err = file.Read(buff) + + if err != nil { + return "", err + } + + filetype := http.DetectContentType(buff) + + ext := ImageExtArray() + + for i := 0; i < len(ext); i++ { + if strings.Contains(ext[i], filetype[6:]) { + return ext[i], nil + } + } + + return "", errors.New("invalid image type") +} + +func GetImageExtByName(p string) (string, error) { + + extArr := ImageExtArray() + ext := filepath.Ext(p) + for i := 0; i < len(extArr); i++ { + if strings.Contains(ext, extArr[i]) { + return extArr[i], nil + } + } + return "", errors.New("invalid image type") +} diff --git a/pkg/utils/random/random.go b/pkg/utils/random/random.go new file mode 100644 index 0000000..6909cad --- /dev/null +++ b/pkg/utils/random/random.go @@ -0,0 +1,24 @@ +package random + +import ( + "math/rand" + "time" +) + +func RandomString(n int, onlyLetter bool) string { + + var letters []rune + + if onlyLetter { + letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + } else { + letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") + } + + b := make([]rune, n) + rand.Seed(time.Now().UnixNano()) + for i := range b { + b[i] = letters[rand.Intn(len(letters))] + } + return string(b) +} diff --git a/route/event_listen.go b/route/event_listen.go new file mode 100644 index 0000000..a6e851b --- /dev/null +++ b/route/event_listen.go @@ -0,0 +1,76 @@ +package route + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" + "time" + + "github.com/IceWhaleTech/CasaOS-Common/external" + "github.com/IceWhaleTech/CasaOS-Common/utils/logger" + message_bus "github.com/IceWhaleTech/CasaOS-UserService/codegen/message_bus" + "github.com/IceWhaleTech/CasaOS-UserService/model" + "github.com/IceWhaleTech/CasaOS-UserService/pkg/config" + "github.com/IceWhaleTech/CasaOS-UserService/service" + "go.uber.org/zap" + "golang.org/x/net/websocket" +) + +func EventListen() { + for i := 0; i < 1000; i++ { + + messageBusUrl, err := external.GetMessageBusAddress(config.CommonInfo.RuntimePath) + if err != nil { + logger.Error("get message bus url error", zap.Any("err", err)) + return + } + + wsURL := fmt.Sprintf("ws://%s/event/%s", strings.ReplaceAll(messageBusUrl, "http://", ""), "local-storage") + ws, err := websocket.Dial(wsURL, "", "http://localhost") + if err != nil { + logger.Error("connect websocket err"+strconv.Itoa(i), zap.Any("error", err)) + time.Sleep(time.Second * 1) + continue + } + defer ws.Close() + + logger.Info("subscribed to", zap.Any("url", wsURL)) + for { + + msg := make([]byte, 1024) + n, err := ws.Read(msg) + if err != nil { + logger.Error("err", zap.Any("err", err.Error())) + } + + var event message_bus.Event + + if err := json.Unmarshal(msg[:n], &event); err != nil { + logger.Error("err", zap.Any("err", err.Error())) + } + propertiesStr, err := json.Marshal(event.Properties) + if err != nil { + logger.Error("marshal error", zap.Any("err", err.Error()), zap.Any("event", event)) + continue + } + model := model.EventModel{ + SourceID: event.SourceID, + Name: event.Name, + Properties: string(propertiesStr), + UUID: *event.Uuid, + } + if event.Name == "local-storage:raid_status" { + continue + } + service.MyService.Event().CreateEvemt(model) + // logger.Info("info", zap.Any("写入信息1", model)) + // output, err := json.MarshalIndent(event, "", " ") + // if err != nil { + // logger.Error("err", zap.Any("err", err.Error())) + // } + // logger.Info("info", zap.Any("写入信息", string(output))) + } + } + logger.Error("error when try to connect to message bus") +} diff --git a/route/v1.go b/route/v1.go new file mode 100644 index 0000000..70df0a6 --- /dev/null +++ b/route/v1.go @@ -0,0 +1,72 @@ +package route + +import ( + "crypto/ecdsa" + "os" + + "github.com/IceWhaleTech/CasaOS-Common/middleware" + "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" + v1 "github.com/IceWhaleTech/CasaOS-UserService/route/v1" + "github.com/IceWhaleTech/CasaOS-UserService/service" + "github.com/gin-contrib/gzip" + "github.com/gin-gonic/gin" +) + +func InitRouter() *gin.Engine { + r := gin.Default() + r.Use(middleware.Cors()) + // r.Use(middleware.WriteLog()) + r.Use(gzip.Gzip(gzip.DefaultCompression)) + + // check if environment variable is set + if ginMode, success := os.LookupEnv("GIN_MODE"); success { + gin.SetMode(ginMode) + } else { + gin.SetMode(gin.ReleaseMode) + } + + r.POST("/v1/users/register", v1.PostUserRegister) + r.POST("/v1/users/login", v1.PostUserLogin) + r.GET("/v1/users/name", v1.GetUserAllUsername) // all/name + r.POST("/v1/users/refresh", v1.PostUserRefreshToken) + // No short-term modifications + r.GET("/v1/users/image", v1.GetUserImage) + + r.GET("/v1/users/status", v1.GetUserStatus) // init/check + + v1Group := r.Group("/v1") + + v1Group.Use(jwt.JWT( + func() (*ecdsa.PublicKey, error) { + _, publicKey := service.MyService.User().GetKeyPair() + return publicKey, nil + }, + )) + { + v1UsersGroup := v1Group.Group("/users") + v1UsersGroup.Use() + { + v1UsersGroup.GET("/current", v1.GetUserInfo) + v1UsersGroup.PUT("/current", v1.PutUserInfo) + v1UsersGroup.PUT("/current/password", v1.PutUserPassword) + + v1UsersGroup.GET("/current/custom/:key", v1.GetUserCustomConf) + v1UsersGroup.POST("/current/custom/:key", v1.PostUserCustomConf) + v1UsersGroup.DELETE("/current/custom/:key", v1.DeleteUserCustomConf) + + v1UsersGroup.POST("/current/image/:key", v1.PostUserUploadImage) + v1UsersGroup.PUT("/current/image/:key", v1.PutUserImage) + // v1UserGroup.POST("/file/image/:key", v1.PostUserFileImage) + v1UsersGroup.DELETE("/current/image", v1.DeleteUserImage) + + v1UsersGroup.PUT("/avatar", v1.PutUserAvatar) + v1UsersGroup.GET("/avatar", v1.GetUserAvatar) + + v1UsersGroup.DELETE("/:id", v1.DeleteUser) + v1UsersGroup.GET("/:username", v1.GetUserInfoByUsername) + v1UsersGroup.DELETE("", v1.DeleteUserAll) + } + } + + return r +} diff --git a/route/v1/user.go b/route/v1/user.go new file mode 100644 index 0000000..bdc352e --- /dev/null +++ b/route/v1/user.go @@ -0,0 +1,785 @@ +package v1 + +import ( + "crypto/ecdsa" + "encoding/base64" + json2 "encoding/json" + "image" + "image/png" + "io" + "log" + "net/http" + url2 "net/url" + "os" + "path" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/IceWhaleTech/CasaOS-Common/utils/common_err" + "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" + "github.com/IceWhaleTech/CasaOS-Common/utils/logger" + "github.com/IceWhaleTech/CasaOS-UserService/model" + "github.com/IceWhaleTech/CasaOS-UserService/model/system_model" + "github.com/IceWhaleTech/CasaOS-UserService/pkg/config" + "github.com/IceWhaleTech/CasaOS-UserService/pkg/utils/encryption" + "github.com/IceWhaleTech/CasaOS-UserService/pkg/utils/file" + model2 "github.com/IceWhaleTech/CasaOS-UserService/service/model" + uuid "github.com/satori/go.uuid" + "github.com/tidwall/gjson" + "go.uber.org/zap" + + "github.com/IceWhaleTech/CasaOS-UserService/service" + "github.com/gin-gonic/gin" +) + +// @Summary register user +// @Router /user/register/ [post] +func PostUserRegister(c *gin.Context) { + json := make(map[string]string) + c.ShouldBind(&json) + + username := json["username"] + pwd := json["password"] + key := json["key"] + if _, ok := service.UserRegisterHash[key]; !ok { + c.JSON(common_err.CLIENT_ERROR, + model.Result{Success: common_err.KEY_NOT_EXIST, Message: common_err.GetMsg(common_err.KEY_NOT_EXIST)}) + return + } + + if len(username) == 0 || len(pwd) == 0 { + c.JSON(common_err.CLIENT_ERROR, + model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + if len(pwd) < 6 { + c.JSON(common_err.CLIENT_ERROR, + model.Result{Success: common_err.PWD_IS_TOO_SIMPLE, Message: common_err.GetMsg(common_err.PWD_IS_TOO_SIMPLE)}) + return + } + oldUser := service.MyService.User().GetUserInfoByUserName(username) + if oldUser.Id > 0 { + c.JSON(common_err.CLIENT_ERROR, + model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)}) + return + } + + user := model2.UserDBModel{} + user.Username = username + user.Password = encryption.GetMD5ByStr(pwd) + user.Role = "admin" + + user = service.MyService.User().CreateUser(user) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)}) + return + } + file.MkDir(config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id)) + delete(service.UserRegisterHash, key) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) +} + +// @Summary login +// @Produce application/json +// @Accept application/json +// @Tags user +// @Param user_name query string true "User name" +// @Param pwd query string true "password" +// @Success 200 {string} string "ok" +// @Router /user/login [post] +func PostUserLogin(c *gin.Context) { + json := make(map[string]string) + c.ShouldBind(&json) + + username := json["username"] + + password := json["password"] + // check params is empty + if len(username) == 0 || len(password) == 0 { + c.JSON(common_err.CLIENT_ERROR, + model.Result{ + Success: common_err.CLIENT_ERROR, + Message: common_err.GetMsg(common_err.INVALID_PARAMS), + }) + return + } + user := service.MyService.User().GetUserAllInfoByName(username) + if user.Id == 0 { + c.JSON(common_err.CLIENT_ERROR, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + if user.Password != encryption.GetMD5ByStr(password) { + c.JSON(common_err.CLIENT_ERROR, + model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)}) + return + } + + privateKey, _ := service.MyService.User().GetKeyPair() + + token := system_model.VerifyInformation{} + + accessToken, err := jwt.GetAccessToken(user.Username, privateKey, user.Id) + if err != nil { + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + } + token.AccessToken = accessToken + + refreshToken, err := jwt.GetRefreshToken(user.Username, privateKey, user.Id) + if err != nil { + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + } + token.RefreshToken = refreshToken + + token.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix() + data := make(map[string]interface{}, 2) + user.Password = "" + data["token"] = token + + // TODO:1 Database fields cannot be external + data["user"] = user + + c.JSON(common_err.SUCCESS, + model.Result{ + Success: common_err.SUCCESS, + Message: common_err.GetMsg(common_err.SUCCESS), + Data: data, + }) +} + +// @Summary edit user head +// @Produce application/json +// @Accept multipart/form-data +// @Tags user +// @Param file formData file true "用户头像" +// @Security ApiKeyAuth +// @Success 200 {string} string "ok" +// @Router /users/avatar [put] +func PutUserAvatar(c *gin.Context) { + id := c.GetHeader("user_id") + user := service.MyService.User().GetUserInfoById(id) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + json := make(map[string]string) + c.ShouldBind(&json) + + data := json["file"] + imgBase64 := strings.Replace(data, "data:image/png;base64,", "", 1) + decodeData, err := base64.StdEncoding.DecodeString(string(imgBase64)) + if err != nil { + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + // 将字节数组转为图片 + img, _, err := image.Decode(strings.NewReader(string(decodeData))) + if err != nil { + log.Fatal(err) + } + + ext := ".png" + avatarPath := config.AppInfo.UserDataPath + "/" + id + "/avatar" + ext + os.Remove(avatarPath) + outFile, err := os.Create(avatarPath) + if err != nil { + logger.Error("create file error", zap.Error(err)) + } + defer outFile.Close() + + err = png.Encode(outFile, img) + if err != nil { + logger.Error("encode error", zap.Error(err)) + } + user.Avatar = avatarPath + service.MyService.User().UpdateUser(user) + c.JSON(http.StatusOK, + model.Result{ + Success: common_err.SUCCESS, + Message: common_err.GetMsg(common_err.SUCCESS), + Data: user, + }) +} + +// @Summary get user head +// @Produce application/json +// @Tags user +// @Param file formData file true "用户头像" +// @Security ApiKeyAuth +// @Success 200 {string} string "ok" +// @Router /users/avatar [get] +func GetUserAvatar(c *gin.Context) { + id := c.GetHeader("user_id") + user := service.MyService.User().GetUserInfoById(id) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + + if file.Exists(user.Avatar) { + c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(path.Base(user.Avatar))) + c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value") + c.File(user.Avatar) + return + } + user.Avatar = "/usr/share/casaos/www/avatar.svg" + if file.Exists(user.Avatar) { + c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(path.Base(user.Avatar))) + c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value") + c.File(user.Avatar) + return + } + user.Avatar = "/var/lib/casaos/www/avatar.svg" + c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(path.Base(user.Avatar))) + c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value") + c.File(user.Avatar) +} + +// @Summary edit user name +// @Produce application/json +// @Accept application/json +// @Tags user +// @Param old_name query string true "Old user name" +// @Security ApiKeyAuth +// @Success 200 {string} string "ok" +// @Router /user/name/:id [put] +func PutUserInfo(c *gin.Context) { + id := c.GetHeader("user_id") + json := model2.UserDBModel{} + c.ShouldBind(&json) + user := service.MyService.User().GetUserInfoById(id) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + if len(json.Username) > 0 { + u := service.MyService.User().GetUserInfoByUserName(json.Username) + if u.Id > 0 { + c.JSON(common_err.CLIENT_ERROR, + model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)}) + return + } + } + + if len(json.Email) == 0 { + json.Email = user.Email + } + if len(json.Avatar) == 0 { + json.Avatar = user.Avatar + } + if len(json.Role) == 0 { + json.Role = user.Role + } + if len(json.Description) == 0 { + json.Description = user.Description + } + if len(json.Nickname) == 0 { + json.Nickname = user.Nickname + } + service.MyService.User().UpdateUser(json) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json}) +} + +// @Summary edit user password +// @Produce application/json +// @Accept application/json +// @Tags user +// @Security ApiKeyAuth +// @Success 200 {string} string "ok" +// @Router /user/password/:id [put] +func PutUserPassword(c *gin.Context) { + id := c.GetHeader("user_id") + json := make(map[string]string) + c.ShouldBind(&json) + oldPwd := json["old_password"] + pwd := json["password"] + if len(oldPwd) == 0 || len(pwd) == 0 { + c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + user := service.MyService.User().GetUserAllInfoById(id) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + if user.Password != encryption.GetMD5ByStr(oldPwd) { + c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID_OLD, Message: common_err.GetMsg(common_err.PWD_INVALID_OLD)}) + return + } + user.Password = encryption.GetMD5ByStr(pwd) + service.MyService.User().UpdateUserPassword(user) + user.Password = "" + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user}) +} + +// @Summary edit user nick +// @Produce application/json +// @Accept application/json +// @Tags user +// @Param nick_name query string false "nick name" +// @Security ApiKeyAuth +// @Success 200 {string} string "ok" +// @Router /user/nick [put] +func PutUserNick(c *gin.Context) { + id := c.GetHeader("user_id") + json := make(map[string]string) + c.ShouldBind(&json) + Nickname := json["nick_name"] + if len(Nickname) == 0 { + c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + user := service.MyService.User().GetUserInfoById(id) + if user.Id == 0 { + c.JSON(http.StatusOK, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + user.Nickname = Nickname + service.MyService.User().UpdateUser(user) + c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user}) +} + +// @Summary edit user description +// @Produce application/json +// @Accept multipart/form-data +// @Tags user +// @Param description formData string false "Description" +// @Security ApiKeyAuth +// @Success 200 {string} string "ok" +// @Router /user/desc [put] +func PutUserDesc(c *gin.Context) { + id := c.GetHeader("user_id") + json := make(map[string]string) + c.ShouldBind(&json) + desc := json["description"] + if len(desc) == 0 { + c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + user := service.MyService.User().GetUserInfoById(id) + if user.Id == 0 { + c.JSON(http.StatusOK, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + user.Description = desc + + service.MyService.User().UpdateUser(user) + + c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user}) +} + +// @Summary get user info +// @Produce application/json +// @Accept application/json +// @Tags user +// @Success 200 {string} string "ok" +// @Router /user/info/:id [get] +func GetUserInfo(c *gin.Context) { + id := c.GetHeader("user_id") + user := service.MyService.User().GetUserInfoById(id) + + c.JSON(common_err.SUCCESS, + model.Result{ + Success: common_err.SUCCESS, + Message: common_err.GetMsg(common_err.SUCCESS), + Data: user, + }) +} + +/** + * @description: + * @param {*gin.Context} c + * @param {string} Username + * @return {*} + * @method: + * @router: + */ +func GetUserInfoByUsername(c *gin.Context) { + username := c.Param("username") + if len(username) == 0 { + c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + user := service.MyService.User().GetUserInfoByUserName(username) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + + c.JSON(common_err.SUCCESS, + model.Result{ + Success: common_err.SUCCESS, + Message: common_err.GetMsg(common_err.SUCCESS), + Data: user, + }) +} + +/** + * @description: get all Usernames + * @method:GET + * @router:/user/all/name + */ +func GetUserAllUsername(c *gin.Context) { + users := service.MyService.User().GetAllUserName() + names := []string{} + for _, v := range users { + names = append(names, v.Username) + } + c.JSON(common_err.SUCCESS, + model.Result{ + Success: common_err.SUCCESS, + Message: common_err.GetMsg(common_err.SUCCESS), + Data: names, + }) +} + +/** + * @description:get custom file by user + * @param {path} name string "file name" + * @method: GET + * @router: /user/custom/:key + */ +func GetUserCustomConf(c *gin.Context) { + name := c.Param("key") + if len(name) == 0 { + c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + id := c.GetHeader("user_id") + + user := service.MyService.User().GetUserInfoById(id) + // user := service.MyService.User().GetUserInfoByUsername(Username) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + filePath := config.AppInfo.UserDataPath + "/" + id + "/" + name + ".json" + + data := file.ReadFullFile(filePath) + if !gjson.ValidBytes(data) { + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(data)}) + return + } + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))}) +} + +/** + * @description:create or update custom conf by user + * @param {path} name string "file name" + * @method:POST + * @router:/user/custom/:key + */ +func PostUserCustomConf(c *gin.Context) { + name := c.Param("key") + if len(name) == 0 { + c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + id := c.GetHeader("user_id") + user := service.MyService.User().GetUserInfoById(id) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + data, _ := io.ReadAll(c.Request.Body) + filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + + if err := file.IsNotExistMkDir(filePath); err != nil { + c.JSON(common_err.SERVICE_ERROR, + model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)}) + return + } + + if err := file.WriteToPath(data, filePath, name+".json"); err != nil { + c.JSON(common_err.SERVICE_ERROR, + model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)}) + return + } + + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))}) +} + +/** + * @description: delete user custom config + * @param {path} key string + * @method:delete + * @router:/user/custom/:key + */ +func DeleteUserCustomConf(c *gin.Context) { + name := c.Param("key") + if len(name) == 0 { + c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + id := c.GetHeader("user_id") + user := service.MyService.User().GetUserInfoById(id) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, + model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + name + ".json" + err := os.Remove(filePath) + if err != nil { + c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)}) + return + } + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) +} + +/** + * @description: + * @param {path} id string "user id" + * @method:DELETE + * @router:/user/delete/:id + */ +func DeleteUser(c *gin.Context) { + id := c.Param("id") + service.MyService.User().DeleteUserById(id) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id}) +} + +/** + * @description:update user image + * @method:POST + * @router:/user/current/image/:key + */ +func PutUserImage(c *gin.Context) { + id := c.GetHeader("user_id") + json := make(map[string]string) + c.ShouldBind(&json) + + path := json["path"] + key := c.Param("key") + if len(path) == 0 || len(key) == 0 { + c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + if !file.Exists(path) { + c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)}) + return + } + + _, err := file.GetImageExt(path) + if err != nil { + c.JSON(http.StatusOK, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)}) + return + } + + user := service.MyService.User().GetUserInfoById(id) + if user.Id == 0 { + c.JSON(http.StatusOK, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + fstat, _ := os.Stat(path) + if fstat.Size() > 10<<20 { + c.JSON(http.StatusOK, model.Result{Success: common_err.IMAGE_TOO_LARGE, Message: common_err.GetMsg(common_err.IMAGE_TOO_LARGE)}) + return + } + ext := file.GetExt(path) + filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + key + ext + file.CopySingleFile(path, filePath, "overwrite") + + data := make(map[string]string, 3) + data["path"] = filePath + data["file_name"] = key + ext + data["online_path"] = "/v1/users/image?path=" + filePath + c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) +} + +/** +* @description: +* @param {*gin.Context} c +* @param {file} file +* @param {string} key +* @param {string} type:avatar,background +* @return {*} +* @method: +* @router: + */ +func PostUserUploadImage(c *gin.Context) { + id := c.GetHeader("user_id") + f, err := c.FormFile("file") + key := c.Param("key") + t := c.PostForm("type") + if len(key) == 0 { + c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + if err != nil { + c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()}) + return + } + + _, err = file.GetImageExtByName(f.Filename) + if err != nil { + c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)}) + return + } + ext := filepath.Ext(f.Filename) + user := service.MyService.User().GetUserInfoById(id) + + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + if t == "avatar" { + key = "avatar" + } + path := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + key + ext + + c.SaveUploadedFile(f, path) + data := make(map[string]string, 3) + data["path"] = path + data["file_name"] = key + ext + data["online_path"] = "/v1/users/image?path=" + path + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) +} + +/** + * @description: get current user's image + * @method:GET + * @router:/user/image/:id + */ +func GetUserImage(c *gin.Context) { + filePath := c.Query("path") + if len(filePath) == 0 { + c.JSON(http.StatusNotFound, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + if !file.Exists(filePath) { + c.JSON(http.StatusNotFound, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)}) + return + } + if !strings.Contains(filePath, config.AppInfo.UserDataPath) { + c.JSON(http.StatusNotFound, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)}) + return + } + + fileTmp, _ := os.Open(filePath) + defer fileTmp.Close() + + fileName := path.Base(filePath) + + // @tiger - RESTful 规范下不应该返回文件本身内容,而是返回文件的静态URL,由前端去解析 + c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName)) + c.File(filePath) +} + +func DeleteUserImage(c *gin.Context) { + id := c.GetHeader("user_id") + path := c.Query("path") + if len(path) == 0 { + c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + return + } + user := service.MyService.User().GetUserInfoById(id) + if user.Id == 0 { + c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)}) + return + } + if !file.Exists(path) { + c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)}) + return + } + if !strings.Contains(path, config.AppInfo.UserDataPath+"/"+strconv.Itoa(user.Id)) { + c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)}) + return + } + os.Remove(path) + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) +} + +/** + * @description: + * @param {*gin.Context} c + * @param {string} refresh_token + * @return {*} + * @method: + * @router: + */ +func PostUserRefreshToken(c *gin.Context) { + js := make(map[string]string) + c.ShouldBind(&js) + refresh := js["refresh_token"] + + privateKey, _ := service.MyService.User().GetKeyPair() + + claims, err := jwt.ParseToken( + refresh, + func() (*ecdsa.PublicKey, error) { + _, publicKey := service.MyService.User().GetKeyPair() + return publicKey, nil + }) + if err != nil { + c.JSON(http.StatusUnauthorized, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE), Data: err.Error()}) + return + } + if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("refresh", true) { + c.JSON(http.StatusUnauthorized, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE)}) + return + } + + newAccessToken, err := jwt.GetAccessToken(claims.Username, privateKey, claims.ID) + if err != nil { + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + newRefreshToken, err := jwt.GetRefreshToken(claims.Username, privateKey, claims.ID) + if err != nil { + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + verifyInfo := system_model.VerifyInformation{ + AccessToken: newAccessToken, + RefreshToken: newRefreshToken, + ExpiresAt: time.Now().Add(3 * time.Hour).Unix(), + } + + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: verifyInfo}) +} + +func DeleteUserAll(c *gin.Context) { + service.MyService.User().DeleteAllUser() + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) +} + +// @Summary 检查是否进入引导状态 +// @Produce application/json +// @Accept application/json +// @Tags sys +// @Security ApiKeyAuth +// @Success 200 {string} string "ok" +// @Router /sys/init/check [get] +func GetUserStatus(c *gin.Context) { + data := make(map[string]interface{}, 2) + + if service.MyService.User().GetUserCount() > 0 { + data["initialized"] = true + data["key"] = "" + } else { + key := uuid.NewV4().String() + service.UserRegisterHash[key] = key + data["key"] = key + data["initialized"] = false + } + c.JSON(common_err.SUCCESS, + model.Result{ + Success: common_err.SUCCESS, + Message: common_err.GetMsg(common_err.SUCCESS), + Data: data, + }) +} diff --git a/route/v2.go b/route/v2.go new file mode 100644 index 0000000..93c2c7a --- /dev/null +++ b/route/v2.go @@ -0,0 +1,111 @@ +package route + +import ( + "crypto/ecdsa" + "net/http" + "net/url" + "strconv" + "strings" + + "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" + codegen "github.com/IceWhaleTech/CasaOS-UserService/codegen/user_service" + v2 "github.com/IceWhaleTech/CasaOS-UserService/route/v2" + "github.com/IceWhaleTech/CasaOS-UserService/service" + "github.com/deepmap/oapi-codegen/pkg/middleware" + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/openapi3filter" + "github.com/labstack/echo/v4" + echo_middleware "github.com/labstack/echo/v4/middleware" +) + +var ( + _swagger *openapi3.T + + V2APIPath string + V2DocPath string +) + +func init() { + swagger, err := codegen.GetSwagger() + if err != nil { + panic(err) + } + + _swagger = swagger + + u, err := url.Parse(_swagger.Servers[0].URL) + if err != nil { + panic(err) + } + + V2APIPath = strings.TrimRight(u.Path, "/") + V2DocPath = "/doc" + V2APIPath +} + +func InitV2Router() http.Handler { + UserService := v2.NewUserService() + + e := echo.New() + + e.Use((echo_middleware.CORSWithConfig(echo_middleware.CORSConfig{ + AllowOrigins: []string{"*"}, + AllowMethods: []string{echo.POST, echo.GET, echo.OPTIONS, echo.PUT, echo.DELETE}, + AllowHeaders: []string{echo.HeaderAuthorization, echo.HeaderContentLength, echo.HeaderXCSRFToken, echo.HeaderContentType, echo.HeaderAccessControlAllowOrigin, echo.HeaderAccessControlAllowHeaders, echo.HeaderAccessControlAllowMethods, echo.HeaderConnection, echo.HeaderOrigin, echo.HeaderXRequestedWith}, + ExposeHeaders: []string{echo.HeaderContentLength, echo.HeaderAccessControlAllowOrigin, echo.HeaderAccessControlAllowHeaders}, + MaxAge: 172800, + AllowCredentials: true, + }))) + + e.Use(echo_middleware.Gzip()) + + e.Use(echo_middleware.Logger()) + + e.Use(echo_middleware.JWTWithConfig(echo_middleware.JWTConfig{ + Skipper: func(c echo.Context) bool { + return c.RealIP() == "::1" || c.RealIP() == "127.0.0.1" + }, + ParseTokenFunc: func(token string, c echo.Context) (interface{}, error) { + valid, claims, err := jwt.Validate( + token, + func() (*ecdsa.PublicKey, error) { + _, publicKey := service.MyService.User().GetKeyPair() + return publicKey, nil + }) + if err != nil || !valid { + return nil, echo.ErrUnauthorized + } + + c.Request().Header.Set("user_id", strconv.Itoa(claims.ID)) + + return claims, nil + }, + TokenLookupFuncs: []echo_middleware.ValuesExtractor{ + func(c echo.Context) ([]string, error) { + return []string{c.Request().Header.Get(echo.HeaderAuthorization)}, nil + }, + }, + })) + + e.Use(middleware.OapiRequestValidatorWithOptions(_swagger, &middleware.Options{Options: openapi3filter.Options{AuthenticationFunc: openapi3filter.NoopAuthenticationFunc}})) + + codegen.RegisterHandlersWithBaseURL(e, UserService, V2APIPath) + + return e +} + +func InitV2DocRouter(docHTML string, docYAML string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == V2DocPath { + if _, err := w.Write([]byte(docHTML)); err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + return + } + + if r.URL.Path == V2DocPath+"/openapi.yaml" { + if _, err := w.Write([]byte(docYAML)); err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + } + }) +} diff --git a/route/v2/api_route_event.go b/route/v2/api_route_event.go new file mode 100644 index 0000000..180df2e --- /dev/null +++ b/route/v2/api_route_event.go @@ -0,0 +1,25 @@ +package v2 + +import ( + "net/http" + + codegen "github.com/IceWhaleTech/CasaOS-UserService/codegen/user_service" + "github.com/IceWhaleTech/CasaOS-UserService/service" + "github.com/labstack/echo/v4" +) + +func (s *UserService) DeleteEvent(ctx echo.Context, params codegen.EventUuid) error { + m := service.MyService.Event().GetEventByUUID(params.String()) + service.MyService.Event().DeleteEvent(params.String()) + return ctx.JSON(http.StatusOK, m) +} + +func (s *UserService) GetEvents(ctx echo.Context, params codegen.GetEventsParams) error { + list := service.MyService.Event().GetEvents() + return ctx.JSON(http.StatusOK, list) +} + +func (s *UserService) DeleteEventBySerial(ctx echo.Context, serial codegen.Serial) error { + service.MyService.Event().DeleteEventBySerial(serial) + return ctx.JSON(http.StatusOK, serial) +} diff --git a/route/v2/route.go b/route/v2/route.go new file mode 100644 index 0000000..eda56fb --- /dev/null +++ b/route/v2/route.go @@ -0,0 +1,9 @@ +package v2 + +import codegen "github.com/IceWhaleTech/CasaOS-UserService/codegen/user_service" + +type UserService struct{} + +func NewUserService() codegen.ServerInterface { + return &UserService{} +} diff --git a/service/event.go b/service/event.go new file mode 100644 index 0000000..8b45ba7 --- /dev/null +++ b/service/event.go @@ -0,0 +1,56 @@ +package service + +import ( + "encoding/json" + + "github.com/IceWhaleTech/CasaOS-UserService/model" + "gorm.io/gorm" +) + +type EventService interface { + CreateEvemt(m model.EventModel) model.EventModel + GetEvents() (list []model.EventModel) + GetEventByUUID(uuid string) (m model.EventModel) + DeleteEvent(uuid string) + DeleteEventBySerial(serial string) +} + +type eventService struct { + db *gorm.DB +} + +func (e *eventService) CreateEvemt(m model.EventModel) model.EventModel { + e.db.Create(&m) + return m +} +func (e *eventService) GetEvents() (list []model.EventModel) { + e.db.Find(&list) + return +} +func (e *eventService) GetEventByUUID(uuid string) (m model.EventModel) { + e.db.Where("uuid = ?", uuid).First(&m) + return +} +func (e *eventService) DeleteEvent(uuid string) { + e.db.Where("uuid = ?", uuid).Delete(&model.EventModel{}) +} +func (e *eventService) DeleteEventBySerial(serial string) { + list := []model.EventModel{} + e.db.Find(&list) + for _, v := range list { + + if v.SourceID == "local-storage" { + properties := make(map[string]string) + err := json.Unmarshal([]byte(v.Properties), &properties) + if err != nil { + continue + } + if properties["serial"] == serial { + e.db.Delete(&v) + } + } + } +} +func NewEventService(db *gorm.DB) EventService { + return &eventService{db: db} +} diff --git a/service/model/o_user.go b/service/model/o_user.go new file mode 100644 index 0000000..34b080b --- /dev/null +++ b/service/model/o_user.go @@ -0,0 +1,30 @@ +/* + * @Author: LinkLeong link@icewhale.com + * @Date: 2022-05-13 18:15:46 + * @LastEditors: LinkLeong + * @LastEditTime: 2022-07-11 17:57:00 + * @Description: + * @Website: https://www.casaos.io + * Copyright (c) 2022 by icewhale, All Rights Reserved. + */ +package model + +import "time" + +//Soon to be removed +type UserDBModel struct { + Id int `gorm:"column:id;primary_key" json:"id"` + Username string `json:"username"` + Password string `json:"password,omitempty"` + Role string `json:"role"` + Email string `json:"email"` + Nickname string `json:"nickname"` + Avatar string `json:"avatar"` + Description string `json:"description"` + CreatedAt time.Time `gorm:"<-:create;autoCreateTime" json:"created_at,omitempty"` + UpdatedAt time.Time `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at,omitempty"` +} + +func (p *UserDBModel) TableName() string { + return "o_users" +} diff --git a/service/service.go b/service/service.go new file mode 100644 index 0000000..8d29cab --- /dev/null +++ b/service/service.go @@ -0,0 +1,45 @@ +package service + +import ( + "github.com/IceWhaleTech/CasaOS-Common/external" + "gorm.io/gorm" +) + +var MyService Repository + +type Repository interface { + Gateway() external.ManagementService + User() UserService + Event() EventService +} + +func NewService(db *gorm.DB, RuntimePath string) Repository { + + gatewayManagement, err := external.NewManagementService(RuntimePath) + if err != nil { + panic(err) + } + + return &store{ + gateway: gatewayManagement, + user: NewUserService(db), + event: NewEventService(db), + } +} + +type store struct { + gateway external.ManagementService + user UserService + event EventService +} + +func (c *store) Event() EventService { + return c.event +} +func (c *store) Gateway() external.ManagementService { + return c.gateway +} + +func (c *store) User() UserService { + return c.user +} diff --git a/service/user.go b/service/user.go new file mode 100644 index 0000000..54bed10 --- /dev/null +++ b/service/user.go @@ -0,0 +1,128 @@ +/* + * @Author: LinkLeong link@icewhale.com + * @Date: 2022-03-18 11:40:55 + * @LastEditors: LinkLeong + * @LastEditTime: 2022-07-12 10:05:37 + * @Description: + * @Website: https://www.casaos.io + * Copyright (c) 2022 by icewhale, All Rights Reserved. + */ +package service + +import ( + "crypto/ecdsa" + "io" + "mime/multipart" + "os" + + "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" + "github.com/IceWhaleTech/CasaOS-Common/utils/logger" + "github.com/IceWhaleTech/CasaOS-UserService/service/model" + "go.uber.org/zap" + "gorm.io/gorm" +) + +type UserService interface { + UpLoadFile(file multipart.File, name string) error + CreateUser(m model.UserDBModel) model.UserDBModel + GetUserCount() (userCount int64) + UpdateUser(m model.UserDBModel) + UpdateUserPassword(m model.UserDBModel) + GetUserInfoById(id string) (m model.UserDBModel) + GetUserAllInfoById(id string) (m model.UserDBModel) + GetUserAllInfoByName(userName string) (m model.UserDBModel) + DeleteUserById(id string) + DeleteAllUser() + GetUserInfoByUserName(userName string) (m model.UserDBModel) + GetAllUserName() (list []model.UserDBModel) + + GetKeyPair() (*ecdsa.PrivateKey, *ecdsa.PublicKey) +} + +var UserRegisterHash = make(map[string]string) + +type userService struct { + privateKey *ecdsa.PrivateKey // keep this private - NEVER expose it!!! + publicKey *ecdsa.PublicKey + + db *gorm.DB +} + +func (u *userService) DeleteAllUser() { + u.db.Where("1=1").Delete(&model.UserDBModel{}) +} + +func (u *userService) DeleteUserById(id string) { + u.db.Where("id= ?", id).Delete(&model.UserDBModel{}) +} + +func (u *userService) GetAllUserName() (list []model.UserDBModel) { + u.db.Select("username").Find(&list) + return +} + +func (u *userService) CreateUser(m model.UserDBModel) model.UserDBModel { + u.db.Create(&m) + return m +} + +func (u *userService) GetUserCount() (userCount int64) { + u.db.Find(&model.UserDBModel{}).Count(&userCount) + return +} + +func (u *userService) UpdateUser(m model.UserDBModel) { + u.db.Model(&m).Omit("password").Updates(&m) +} + +func (u *userService) UpdateUserPassword(m model.UserDBModel) { + u.db.Model(&m).Update("password", m.Password) +} + +func (u *userService) GetUserAllInfoById(id string) (m model.UserDBModel) { + u.db.Where("id= ?", id).First(&m) + return +} + +func (u *userService) GetUserAllInfoByName(userName string) (m model.UserDBModel) { + u.db.Where("username= ?", userName).First(&m) + return +} + +func (u *userService) GetUserInfoById(id string) (m model.UserDBModel) { + u.db.Select("username", "id", "role", "nickname", "description", "avatar", "email").Where("id= ?", id).First(&m) + return +} + +func (u *userService) GetUserInfoByUserName(userName string) (m model.UserDBModel) { + u.db.Select("username", "id", "role", "nickname", "description", "avatar", "email").Where("username= ?", userName).First(&m) + return +} + +// 上传文件 +func (c *userService) UpLoadFile(file multipart.File, url string) error { + out, _ := os.OpenFile(url, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o644) + defer out.Close() + io.Copy(out, file) + return nil +} + +func (u *userService) GetKeyPair() (*ecdsa.PrivateKey, *ecdsa.PublicKey) { + return u.privateKey, u.publicKey +} + +// 获取用户Service +func NewUserService(db *gorm.DB) UserService { + // DO NOT store private key anywhere - keep it in memory ONLY!!! + privateKey, publicKey, err := jwt.GenerateKeyPair() + if err != nil { + logger.Error("failed to generate key pair for JWT", zap.Error(err)) + return nil + } + + return &userService{ + privateKey: privateKey, + publicKey: publicKey, + db: db, + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..89d3573 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "declaration": true, + "lib": [ + "es2017", + "DOM" + ], + "module": "commonjs", + "target": "es6", + "skipLibCheck": true, + "sourceMap": false, + "strict": true, + "useUnknownInCatchVariables": false, + "resolveJsonModule": true, + "esModuleInterop": true, + "outDir": "dist", + "types": [ + "node" + ], + }, + "exclude": [ + "node_modules" + ], + "main": "generate/index" +} \ No newline at end of file