mirror of
https://github.com/KaySar12/NextZen-UserService.git
synced 2025-03-15 15:15:35 +07:00
init
This commit is contained in:
commit
3cc6b026cc
148
.goreleaser.debug.yaml
Normal file
148
.goreleaser.debug.yaml
Normal file
@ -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 }}"
|
179
.goreleaser.yaml
Normal file
179
.goreleaser.yaml
Normal file
@ -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 }}"
|
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
201
LICENSE
Normal file
201
LICENSE
Normal file
@ -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.
|
30
README.md
Normal file
30
README.md
Normal file
@ -0,0 +1,30 @@
|
||||
# CasaOS-UserService
|
||||
|
||||
[](https://pkg.go.dev/github.com/IceWhaleTech/CasaOS-UserService) [](https://goreportcard.com/report/github.com/IceWhaleTech/CasaOS-UserService) [](https://github.com/IceWhaleTech/CasaOS-UserService/actions/workflows/release.yml) [](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**
|
||||
```
|
24
api/index.html
Normal file
24
api/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>CasaOS | Developers</title>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<redoc spec-url='user-service/openapi.yaml' expandResponses='all' jsonSampleExpandLevel='all'></redoc>
|
||||
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
||||
</body>
|
||||
|
||||
</html>
|
211
api/user-service/openapi.yaml
Normal file
211
api/user-service/openapi.yaml
Normal file
@ -0,0 +1,211 @@
|
||||
openapi: 3.0.3
|
||||
|
||||
info:
|
||||
title: Casaos User Service API
|
||||
version: v2
|
||||
description: |
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_dark_night_800px.png">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_twilight_blue_800px.png">
|
||||
<img alt="CasaOS" src="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_twilight_blue_800px.png">
|
||||
</picture>
|
||||
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
|
@ -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
|
9
build/sysroot/etc/casaos/user-service.conf.sample
Normal file
9
build/sysroot/etc/casaos/user-service.conf.sample
Normal file
@ -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
|
@ -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
|
37
cmd/migration-tool/log.go
Normal file
37
cmd/migration-tool/log.go
Normal file
@ -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...)
|
||||
}
|
106
cmd/migration-tool/main.go
Normal file
106
cmd/migration-tool/main.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
27
cmd/migration-tool/migration_dummy.go
Normal file
27
cmd/migration-tool/migration_dummy.go
Normal file
@ -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{}
|
||||
}
|
2769
codegen/message_bus/api.go
Normal file
2769
codegen/message_bus/api.go
Normal file
File diff suppressed because it is too large
Load Diff
290
codegen/user_service/user_service_api.go
Normal file
290
codegen/user_service/user_service_api.go
Normal file
@ -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
|
||||
}
|
3
common/version.go
Normal file
3
common/version.go
Normal file
@ -0,0 +1,3 @@
|
||||
package common
|
||||
|
||||
const Version = "0.4.4"
|
1
dist/artifacts.json
vendored
Normal file
1
dist/artifacts.json
vendored
Normal file
@ -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"}}]
|
BIN
dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service
vendored
Normal file
BIN
dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service
vendored
Normal file
Binary file not shown.
131
dist/config.yaml
vendored
Normal file
131
dist/config.yaml
vendored
Normal file
@ -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!<br/>Check it out at <a href="{{ .ReleaseURL }}">{{ .ReleaseURL }}</a>'
|
||||
git:
|
||||
tag_sort: -version:refname
|
||||
github_urls:
|
||||
download: https://github.com
|
||||
gitlab_urls:
|
||||
download: https://gitlab.com
|
1
dist/metadata.json
vendored
Normal file
1
dist/metadata.json
vendored
Normal file
@ -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"}}
|
86
go.mod
Normal file
86
go.mod
Normal file
@ -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
|
||||
)
|
251
go.sum
Normal file
251
go.sum
Normal file
@ -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=
|
176
main.go
Normal file
176
main.go
Normal file
@ -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)
|
||||
}
|
13
model/event.go
Normal file
13
model/event.go
Normal file
@ -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"
|
||||
}
|
19
model/sys_common.go
Normal file
19
model/sys_common.go
Normal file
@ -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:"返回结果"`
|
||||
}
|
16
model/system_model/verify_information.go
Normal file
16
model/system_model/verify_information.go
Normal file
@ -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"`
|
||||
}
|
36
package.json
Normal file
36
package.json
Normal file
@ -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"
|
||||
}
|
5
pkg/config/config.go
Normal file
5
pkg/config/config.go
Normal file
@ -0,0 +1,5 @@
|
||||
package config
|
||||
|
||||
const (
|
||||
UserServiceConfigFilePath = "/etc/casaos/user-service.conf"
|
||||
)
|
94
pkg/config/init.go
Normal file
94
pkg/config/init.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
49
pkg/sqlite/db.go
Normal file
49
pkg/sqlite/db.go
Normal file
@ -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
|
||||
}
|
21
pkg/utils/encryption/md5_helper.go
Normal file
21
pkg/utils/encryption/md5_helper.go
Normal file
@ -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))
|
||||
}
|
145
pkg/utils/file/file.go
Normal file
145
pkg/utils/file/file.go
Normal file
@ -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
|
||||
}
|
182
pkg/utils/file/image.go
Normal file
182
pkg/utils/file/image.go
Normal file
@ -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")
|
||||
}
|
24
pkg/utils/random/random.go
Normal file
24
pkg/utils/random/random.go
Normal file
@ -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)
|
||||
}
|
76
route/event_listen.go
Normal file
76
route/event_listen.go
Normal file
@ -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")
|
||||
}
|
72
route/v1.go
Normal file
72
route/v1.go
Normal file
@ -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
|
||||
}
|
785
route/v1/user.go
Normal file
785
route/v1/user.go
Normal file
@ -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,
|
||||
})
|
||||
}
|
111
route/v2.go
Normal file
111
route/v2.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
25
route/v2/api_route_event.go
Normal file
25
route/v2/api_route_event.go
Normal file
@ -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)
|
||||
}
|
9
route/v2/route.go
Normal file
9
route/v2/route.go
Normal file
@ -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{}
|
||||
}
|
56
service/event.go
Normal file
56
service/event.go
Normal file
@ -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}
|
||||
}
|
30
service/model/o_user.go
Normal file
30
service/model/o_user.go
Normal file
@ -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"
|
||||
}
|
45
service/service.go
Normal file
45
service/service.go
Normal file
@ -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
|
||||
}
|
128
service/user.go
Normal file
128
service/user.go
Normal file
@ -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,
|
||||
}
|
||||
}
|
25
tsconfig.json
Normal file
25
tsconfig.json
Normal file
@ -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"
|
||||
}
|
Loading…
Reference in New Issue
Block a user