Merge branch 'master' into resetEmptyPassWD
This commit is contained in:
@@ -159,6 +159,7 @@
|
|||||||
lang: "en"
|
lang: "en"
|
||||||
app:
|
app:
|
||||||
web-client: 1 # 1:启用 0:禁用
|
web-client: 1 # 1:启用 0:禁用
|
||||||
|
register: false #是否开启注册
|
||||||
gin:
|
gin:
|
||||||
api-addr: "0.0.0.0:21114"
|
api-addr: "0.0.0.0:21114"
|
||||||
mode: "release"
|
mode: "release"
|
||||||
@@ -196,6 +197,7 @@ proxy:
|
|||||||
| TZ | 时区 | Asia/Shanghai |
|
| TZ | 时区 | Asia/Shanghai |
|
||||||
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
|
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
|
||||||
| RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 |
|
| RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 |
|
||||||
|
| RUSTDESK_API_APP_REGISTER | 是否开启注册; `true`, `false` 默认`false` | `false` |
|
||||||
| -----GIN配置----- | ---------- | ---------- |
|
| -----GIN配置----- | ---------- | ---------- |
|
||||||
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
|
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
|
||||||
| -----------GORM配置---------------- | ------------------------------------ | --------------------------- |
|
| -----------GORM配置---------------- | ------------------------------------ | --------------------------- |
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ installation are `admin` `admin`, please change the password immediately.
|
|||||||
lang: "en"
|
lang: "en"
|
||||||
app:
|
app:
|
||||||
web-client: 1 # web client route 1:open 0:close
|
web-client: 1 # web client route 1:open 0:close
|
||||||
|
register: false #register enable
|
||||||
gin:
|
gin:
|
||||||
api-addr: "0.0.0.0:21114"
|
api-addr: "0.0.0.0:21114"
|
||||||
mode: "release"
|
mode: "release"
|
||||||
@@ -202,6 +203,7 @@ The prefix for variable names is `RUSTDESK_API`. If environment variables exist,
|
|||||||
| TZ | timezone | Asia/Shanghai |
|
| TZ | timezone | Asia/Shanghai |
|
||||||
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
|
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
|
||||||
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, deault 1 | 1 |
|
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, deault 1 | 1 |
|
||||||
|
| RUSTDESK_API_APP_REGISTER | register enable; `true`, `false`; default:`false` | `false` |
|
||||||
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
|
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
|
||||||
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
|
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DatabaseAutoUpdate() {
|
func DatabaseAutoUpdate() {
|
||||||
version := 242
|
version := 243
|
||||||
|
|
||||||
db := global.DB
|
db := global.DB
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
lang: "zh-CN"
|
lang: "zh-CN"
|
||||||
app:
|
app:
|
||||||
web-client: 1 # 1:启用 0:禁用
|
web-client: 1 # 1:启用 0:禁用
|
||||||
|
register: false #是否开启注册
|
||||||
gin:
|
gin:
|
||||||
api-addr: "0.0.0.0:21114"
|
api-addr: "0.0.0.0:21114"
|
||||||
mode: "release" #release,debug,test
|
mode: "release" #release,debug,test
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
WebClient int `mapstructure:"web-client"`
|
WebClient int `mapstructure:"web-client"`
|
||||||
|
Register bool `mapstructure:"register"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
|||||||
20
docker-compose-dev.yaml
Normal file
20
docker-compose-dev.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
services:
|
||||||
|
rustdesk-api:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.dev
|
||||||
|
# image: lejianwen/rustdesk-api
|
||||||
|
container_name: rustdesk-api
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
- RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
|
||||||
|
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
|
||||||
|
- RUSTDESK_API_RUSTDESK_API_SERVER=http://127.0.0.1:21114
|
||||||
|
- RUSTDESK_API_RUSTDESK_KEY=123456789
|
||||||
|
ports:
|
||||||
|
- 21114:21114
|
||||||
|
volumes:
|
||||||
|
- ./data/rustdesk/api:/app/data #将数据库挂载出来方便备份
|
||||||
|
- ./conf:/app/conf # config
|
||||||
|
# - ./resources:/app/resources # 静态资源
|
||||||
|
restart: unless-stopped
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
rustdesk-api:
|
rustdesk-api:
|
||||||
build:
|
image: lejianwen/rustdesk-api
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile.dev
|
|
||||||
# image: lejianwen/rustdesk-api
|
|
||||||
container_name: rustdesk-api
|
container_name: rustdesk-api
|
||||||
environment:
|
environment:
|
||||||
- TZ=Asia/Shanghai
|
- TZ=Asia/Shanghai
|
||||||
@@ -14,7 +11,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 21114:21114
|
- 21114:21114
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/rustdesk/api:/app/data #将数据库挂载出来方便备份
|
- ./data/rustdesk/api:/app/data # database
|
||||||
- ./conf:/app/conf # config
|
# - ./conf:/app/conf # config
|
||||||
# - ./resources:/app/resources # 静态资源
|
# - ./resources:/app/resources # 静态资源
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -1453,6 +1453,38 @@ const docTemplateadmin = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/login-options": {
|
||||||
|
"post": {
|
||||||
|
"description": "登录选项",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"登录"
|
||||||
|
],
|
||||||
|
"summary": "登录选项",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/loginLog/delete": {
|
"/admin/loginLog/delete": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1922,6 +1954,63 @@ const docTemplateadmin = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/oidc/auth": {
|
||||||
|
"post": {
|
||||||
|
"description": "OidcAuth",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Oauth"
|
||||||
|
],
|
||||||
|
"summary": "OidcAuth",
|
||||||
|
"responses": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/admin/oidc/auth-query": {
|
||||||
|
"get": {
|
||||||
|
"description": "OidcAuthQuery",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Oauth"
|
||||||
|
],
|
||||||
|
"summary": "OidcAuthQuery",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"$ref": "#/definitions/admin.LoginPayload"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/peer/create": {
|
"/admin/peer/create": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -3164,11 +3253,17 @@ const docTemplateadmin = `{
|
|||||||
"id": {
|
"id": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"issuer": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"op": {
|
"op": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"redirect_url": {
|
"redirect_url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"scopes": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3749,12 +3844,18 @@ const docTemplateadmin = `{
|
|||||||
"id": {
|
"id": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"issuer": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"op": {
|
"op": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"redirect_url": {
|
"redirect_url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"scopes": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"updated_at": {
|
"updated_at": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@@ -3795,6 +3896,9 @@ const docTemplateadmin = `{
|
|||||||
"id": {
|
"id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"last_online_ip": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"last_online_time": {
|
"last_online_time": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
@@ -3964,6 +4068,14 @@ const docTemplateadmin = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"response.ErrorResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"error": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"response.Response": {
|
"response.Response": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -1446,6 +1446,38 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/login-options": {
|
||||||
|
"post": {
|
||||||
|
"description": "登录选项",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"登录"
|
||||||
|
],
|
||||||
|
"summary": "登录选项",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/loginLog/delete": {
|
"/admin/loginLog/delete": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1915,6 +1947,63 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/oidc/auth": {
|
||||||
|
"post": {
|
||||||
|
"description": "OidcAuth",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Oauth"
|
||||||
|
],
|
||||||
|
"summary": "OidcAuth",
|
||||||
|
"responses": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/admin/oidc/auth-query": {
|
||||||
|
"get": {
|
||||||
|
"description": "OidcAuthQuery",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Oauth"
|
||||||
|
],
|
||||||
|
"summary": "OidcAuthQuery",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"$ref": "#/definitions/admin.LoginPayload"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/peer/create": {
|
"/admin/peer/create": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -3157,11 +3246,17 @@
|
|||||||
"id": {
|
"id": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"issuer": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"op": {
|
"op": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"redirect_url": {
|
"redirect_url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"scopes": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3742,12 +3837,18 @@
|
|||||||
"id": {
|
"id": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"issuer": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"op": {
|
"op": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"redirect_url": {
|
"redirect_url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"scopes": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"updated_at": {
|
"updated_at": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@@ -3788,6 +3889,9 @@
|
|||||||
"id": {
|
"id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"last_online_ip": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"last_online_time": {
|
"last_online_time": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
@@ -3957,6 +4061,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"response.ErrorResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"error": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"response.Response": {
|
"response.Response": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -105,10 +105,14 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
id:
|
id:
|
||||||
type: integer
|
type: integer
|
||||||
|
issuer:
|
||||||
|
type: string
|
||||||
op:
|
op:
|
||||||
type: string
|
type: string
|
||||||
redirect_url:
|
redirect_url:
|
||||||
type: string
|
type: string
|
||||||
|
scopes:
|
||||||
|
type: string
|
||||||
required:
|
required:
|
||||||
- client_id
|
- client_id
|
||||||
- client_secret
|
- client_secret
|
||||||
@@ -500,10 +504,14 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
id:
|
id:
|
||||||
type: integer
|
type: integer
|
||||||
|
issuer:
|
||||||
|
type: string
|
||||||
op:
|
op:
|
||||||
type: string
|
type: string
|
||||||
redirect_url:
|
redirect_url:
|
||||||
type: string
|
type: string
|
||||||
|
scopes:
|
||||||
|
type: string
|
||||||
updated_at:
|
updated_at:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
@@ -530,6 +538,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
id:
|
id:
|
||||||
type: string
|
type: string
|
||||||
|
last_online_ip:
|
||||||
|
type: string
|
||||||
last_online_time:
|
last_online_time:
|
||||||
type: integer
|
type: integer
|
||||||
memory:
|
memory:
|
||||||
@@ -643,6 +653,11 @@ definitions:
|
|||||||
total:
|
total:
|
||||||
type: integer
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
|
response.ErrorResponse:
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
response.Response:
|
response.Response:
|
||||||
properties:
|
properties:
|
||||||
code:
|
code:
|
||||||
@@ -1510,6 +1525,27 @@ paths:
|
|||||||
summary: 登录
|
summary: 登录
|
||||||
tags:
|
tags:
|
||||||
- 登录
|
- 登录
|
||||||
|
/admin/login-options:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 登录选项
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.ErrorResponse'
|
||||||
|
summary: 登录选项
|
||||||
|
tags:
|
||||||
|
- 登录
|
||||||
/admin/loginLog/delete:
|
/admin/loginLog/delete:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
@@ -1789,6 +1825,41 @@ paths:
|
|||||||
summary: Oauth编辑
|
summary: Oauth编辑
|
||||||
tags:
|
tags:
|
||||||
- Oauth
|
- Oauth
|
||||||
|
/admin/oidc/auth:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: OidcAuth
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses: {}
|
||||||
|
summary: OidcAuth
|
||||||
|
tags:
|
||||||
|
- Oauth
|
||||||
|
/admin/oidc/auth-query:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: OidcAuthQuery
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/definitions/response.Response'
|
||||||
|
- properties:
|
||||||
|
data:
|
||||||
|
$ref: '#/definitions/admin.LoginPayload'
|
||||||
|
type: object
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.Response'
|
||||||
|
summary: OidcAuthQuery
|
||||||
|
tags:
|
||||||
|
- Oauth
|
||||||
/admin/peer/create:
|
/admin/peer/create:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
|
|||||||
@@ -834,7 +834,7 @@ const docTemplateapi = `{
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/login-options": {
|
"/login-options": {
|
||||||
"post": {
|
"get": {
|
||||||
"description": "登录选项",
|
"description": "登录选项",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
|
|||||||
@@ -827,7 +827,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/login-options": {
|
"/login-options": {
|
||||||
"post": {
|
"get": {
|
||||||
"description": "登录选项",
|
"description": "登录选项",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
|
|||||||
@@ -715,7 +715,7 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- 登录
|
- 登录
|
||||||
/login-options:
|
/login-options:
|
||||||
post:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: 登录选项
|
description: 登录选项
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ package admin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"Gwen/global"
|
"Gwen/global"
|
||||||
|
"Gwen/http/controller/api"
|
||||||
"Gwen/http/request/admin"
|
"Gwen/http/request/admin"
|
||||||
|
apiReq "Gwen/http/request/api"
|
||||||
"Gwen/http/response"
|
"Gwen/http/response"
|
||||||
adResp "Gwen/http/response/admin"
|
adResp "Gwen/http/response/admin"
|
||||||
apiReq "Gwen/http/request/api"
|
|
||||||
"Gwen/http/controller/api"
|
|
||||||
"Gwen/model"
|
"Gwen/model"
|
||||||
"Gwen/service"
|
"Gwen/service"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Login struct {
|
type Login struct {
|
||||||
@@ -85,7 +86,6 @@ func (ct *Login) Logout(c *gin.Context) {
|
|||||||
response.Success(c, nil)
|
response.Success(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// LoginOptions
|
// LoginOptions
|
||||||
// @Tags 登录
|
// @Tags 登录
|
||||||
// @Summary 登录选项
|
// @Summary 登录选项
|
||||||
@@ -95,13 +95,20 @@ func (ct *Login) Logout(c *gin.Context) {
|
|||||||
// @Success 200 {object} []string
|
// @Success 200 {object} []string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /admin/login-options [post]
|
// @Router /admin/login-options [post]
|
||||||
// 直接调用/api/login的LoginOptions方法
|
|
||||||
func (ct *Login) LoginOptions(c *gin.Context) {
|
func (ct *Login) LoginOptions(c *gin.Context) {
|
||||||
l := &api.Login{}
|
res := service.AllService.OauthService.List(1, 100, func(tx *gorm.DB) {
|
||||||
l.LoginOptions(c)
|
tx.Select("op").Order("id")
|
||||||
|
})
|
||||||
|
var ops []string
|
||||||
|
for _, v := range res.Oauths {
|
||||||
|
ops = append(ops, v.Op)
|
||||||
|
}
|
||||||
|
response.Success(c, gin.H{
|
||||||
|
"ops": ops,
|
||||||
|
"register": global.Config.App.Register,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// OidcAuth
|
// OidcAuth
|
||||||
// @Tags Oauth
|
// @Tags Oauth
|
||||||
// @Summary OidcAuth
|
// @Summary OidcAuth
|
||||||
@@ -126,13 +133,13 @@ func (ct *Login) OidcAuth(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
|
service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
|
||||||
Action: service.OauthActionTypeLogin,
|
Action: service.OauthActionTypeLogin,
|
||||||
Op: f.Op,
|
Op: f.Op,
|
||||||
Id: f.Id,
|
Id: f.Id,
|
||||||
DeviceType: "webadmin",
|
DeviceType: "webadmin",
|
||||||
// DeviceOs: ct.Platform(c),
|
// DeviceOs: ct.Platform(c),
|
||||||
DeviceOs: f.DeviceInfo.Os,
|
DeviceOs: f.DeviceInfo.Os,
|
||||||
Uuid: f.Uuid,
|
Uuid: f.Uuid,
|
||||||
}, 5*60)
|
}, 5*60)
|
||||||
|
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
@@ -141,8 +148,6 @@ func (ct *Login) OidcAuth(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// OidcAuthQuery
|
// OidcAuthQuery
|
||||||
// @Tags Oauth
|
// @Tags Oauth
|
||||||
// @Summary OidcAuthQuery
|
// @Summary OidcAuthQuery
|
||||||
@@ -158,12 +163,12 @@ func (ct *Login) OidcAuthQuery(c *gin.Context) {
|
|||||||
if ut == nil {
|
if ut == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("u:", u)
|
//fmt.Println("u:", u)
|
||||||
fmt.Println("ut:", ut)
|
//fmt.Println("ut:", ut)
|
||||||
response.Success(c, &adResp.LoginPayload{
|
response.Success(c, &adResp.LoginPayload{
|
||||||
Token: ut.Token,
|
Token: ut.Token,
|
||||||
Username: u.Username,
|
Username: u.Username,
|
||||||
RouteNames: service.AllService.UserService.RouteNames(u),
|
RouteNames: service.AllService.UserService.RouteNames(u),
|
||||||
Nickname: u.Nickname,
|
Nickname: u.Nickname,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ func (o *Oauth) BindConfirm(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
u := service.AllService.UserService.CurUser(c)
|
u := service.AllService.UserService.CurUser(c)
|
||||||
err = service.AllService.OauthService.BindGithubUser(v.ThirdOpenId, v.ThirdOpenId, u.Id)
|
err = service.AllService.OauthService.BindOauthUser(v.Op, v.ThirdOpenId, v.ThirdName, u.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Fail(c, 101, response.TranslateMsg(c, "BindFail"))
|
response.Fail(c, 101, response.TranslateMsg(c, "BindFail"))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"Gwen/http/request/admin"
|
"Gwen/http/request/admin"
|
||||||
"Gwen/http/response"
|
"Gwen/http/response"
|
||||||
adResp "Gwen/http/response/admin"
|
adResp "Gwen/http/response/admin"
|
||||||
|
"Gwen/model"
|
||||||
"Gwen/service"
|
"Gwen/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -327,3 +328,40 @@ func (ct *User) GroupUsers(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
response.Success(c, data)
|
response.Success(c, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register
|
||||||
|
func (ct *User) Register(c *gin.Context) {
|
||||||
|
if !global.Config.App.Register {
|
||||||
|
response.Fail(c, 101, response.TranslateMsg(c, "RegisterClosed"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f := &admin.RegisterForm{}
|
||||||
|
if err := c.ShouldBindJSON(f); err != nil {
|
||||||
|
response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
errList := global.Validator.ValidStruct(c, f)
|
||||||
|
if len(errList) > 0 {
|
||||||
|
response.Fail(c, 101, errList[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u := service.AllService.UserService.Register(f.Username, f.Password)
|
||||||
|
if u == nil || u.Id == 0 {
|
||||||
|
response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 注册成功后自动登录
|
||||||
|
ut := service.AllService.UserService.Login(u, &model.LoginLog{
|
||||||
|
UserId: u.Id,
|
||||||
|
Client: model.LoginLogClientWebAdmin,
|
||||||
|
Uuid: "",
|
||||||
|
Ip: c.ClientIP(),
|
||||||
|
Type: model.LoginLogTypeAccount,
|
||||||
|
})
|
||||||
|
response.Success(c, &adResp.LoginPayload{
|
||||||
|
Token: ut.Token,
|
||||||
|
Username: u.Username,
|
||||||
|
RouteNames: service.AllService.UserService.RouteNames(u),
|
||||||
|
Nickname: u.Nickname,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ func (l *Login) Login(c *gin.Context) {
|
|||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} []string
|
// @Success 200 {object} []string
|
||||||
// @Failure 500 {object} response.ErrorResponse
|
// @Failure 500 {object} response.ErrorResponse
|
||||||
// @Router /login-options [post]
|
// @Router /login-options [get]
|
||||||
func (l *Login) LoginOptions(c *gin.Context) {
|
func (l *Login) LoginOptions(c *gin.Context) {
|
||||||
oauthOks := []string{}
|
oauthOks := []string{}
|
||||||
err, _ := service.AllService.OauthService.GetOauthConfig(model.OauthTypeGithub)
|
err, _ := service.AllService.OauthService.GetOauthConfig(model.OauthTypeGithub)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ func (o *Oauth) OidcAuth(c *gin.Context) {
|
|||||||
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
//fmt.Println(f)
|
||||||
if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub && f.Op != model.OauthTypeOidc {
|
if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub && f.Op != model.OauthTypeOidc {
|
||||||
response.Error(c, response.TranslateMsg(c, "ParamsError"))
|
response.Error(c, response.TranslateMsg(c, "ParamsError"))
|
||||||
return
|
return
|
||||||
@@ -79,7 +80,7 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken)
|
|||||||
|
|
||||||
// 如果 UserId 为 0,说明还在授权中
|
// 如果 UserId 为 0,说明还在授权中
|
||||||
if v.UserId == 0 {
|
if v.UserId == 0 {
|
||||||
c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress"})
|
c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress, please login and bind"})
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +124,9 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken)
|
|||||||
// @Router /oidc/auth-query [get]
|
// @Router /oidc/auth-query [get]
|
||||||
func (o *Oauth) OidcAuthQuery(c *gin.Context) {
|
func (o *Oauth) OidcAuthQuery(c *gin.Context) {
|
||||||
u, ut := o.OidcAuthQueryPre(c)
|
u, ut := o.OidcAuthQueryPre(c)
|
||||||
|
if u == nil || ut == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
c.JSON(http.StatusOK, apiResp.LoginRes{
|
c.JSON(http.StatusOK, apiResp.LoginRes{
|
||||||
AccessToken: ut.Token,
|
AccessToken: ut.Token,
|
||||||
Type: "access_token",
|
Type: "access_token",
|
||||||
@@ -157,7 +161,10 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
|
|||||||
ty := v.Op
|
ty := v.Op
|
||||||
ac := v.Action
|
ac := v.Action
|
||||||
var u *model.User
|
var u *model.User
|
||||||
|
openid := ""
|
||||||
|
thirdName := ""
|
||||||
//fmt.Println("ty ac ", ty, ac)
|
//fmt.Println("ty ac ", ty, ac)
|
||||||
|
|
||||||
if ty == model.OauthTypeGithub {
|
if ty == model.OauthTypeGithub {
|
||||||
code := c.Query("code")
|
code := c.Query("code")
|
||||||
err, userData := service.AllService.OauthService.GithubCallback(code)
|
err, userData := service.AllService.OauthService.GithubCallback(code)
|
||||||
@@ -165,59 +172,8 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
|
|||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ac == service.OauthActionTypeBind {
|
openid = strconv.Itoa(userData.Id)
|
||||||
//fmt.Println("bind", ty, userData)
|
thirdName = userData.Login
|
||||||
utr := service.AllService.OauthService.UserThirdInfo(ty, strconv.Itoa(userData.Id))
|
|
||||||
if utr.UserId > 0 {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//绑定
|
|
||||||
u = service.AllService.UserService.InfoById(v.UserId)
|
|
||||||
if u == nil {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//绑定github
|
|
||||||
err = service.AllService.OauthService.BindGithubUser(strconv.Itoa(userData.Id), userData.Login, v.UserId)
|
|
||||||
if err != nil {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
|
|
||||||
return
|
|
||||||
} else if ac == service.OauthActionTypeLogin {
|
|
||||||
//登录
|
|
||||||
if v.UserId != 0 {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
u = service.AllService.UserService.InfoByGithubId(strconv.Itoa(userData.Id))
|
|
||||||
if u == nil {
|
|
||||||
oa := service.AllService.OauthService.InfoByOp(ty)
|
|
||||||
if !*oa.AutoRegister {
|
|
||||||
//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
|
|
||||||
v.ThirdName = userData.Login
|
|
||||||
v.ThirdOpenId = strconv.Itoa(userData.Id)
|
|
||||||
url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
|
|
||||||
c.Redirect(http.StatusFound, url)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//自动注册
|
|
||||||
u = service.AllService.UserService.RegisterByGithub(userData.Login, strconv.Itoa(userData.Id))
|
|
||||||
if u.Id == 0 {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// v.UserId = u.Id
|
|
||||||
// service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
|
|
||||||
// c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
|
|
||||||
// return
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if ty == model.OauthTypeGoogle {
|
} else if ty == model.OauthTypeGoogle {
|
||||||
code := c.Query("code")
|
code := c.Query("code")
|
||||||
err, userData := service.AllService.OauthService.GoogleCallback(code)
|
err, userData := service.AllService.OauthService.GoogleCallback(code)
|
||||||
@@ -225,60 +181,9 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
|
|||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
openid = userData.Email
|
||||||
//将空格替换成_
|
//将空格替换成_
|
||||||
googleName := strings.Replace(userData.Name, " ", "_", -1)
|
thirdName = strings.Replace(userData.Name, " ", "_", -1)
|
||||||
if ac == service.OauthActionTypeBind {
|
|
||||||
//fmt.Println("bind", ty, userData)
|
|
||||||
utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Email)
|
|
||||||
if utr.UserId > 0 {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//绑定
|
|
||||||
u = service.AllService.UserService.InfoById(v.UserId)
|
|
||||||
if u == nil {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//绑定
|
|
||||||
err = service.AllService.OauthService.BindGoogleUser(userData.Email, googleName, v.UserId)
|
|
||||||
if err != nil {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
|
|
||||||
return
|
|
||||||
} else if ac == service.OauthActionTypeLogin {
|
|
||||||
if v.UserId != 0 {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
u = service.AllService.UserService.InfoByGoogleEmail(userData.Email)
|
|
||||||
if u == nil {
|
|
||||||
oa := service.AllService.OauthService.InfoByOp(ty)
|
|
||||||
if !*oa.AutoRegister {
|
|
||||||
//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
|
|
||||||
|
|
||||||
v.ThirdName = googleName
|
|
||||||
v.ThirdOpenId = userData.Email
|
|
||||||
url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
|
|
||||||
c.Redirect(http.StatusFound, url)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//自动注册
|
|
||||||
u = service.AllService.UserService.RegisterByGoogle(googleName, userData.Email)
|
|
||||||
if u.Id == 0 {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// v.UserId = u.Id
|
|
||||||
// service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
|
|
||||||
// c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
|
|
||||||
// return
|
|
||||||
}
|
|
||||||
} else if ty == model.OauthTypeOidc {
|
} else if ty == model.OauthTypeOidc {
|
||||||
code := c.Query("code")
|
code := c.Query("code")
|
||||||
err, userData := service.AllService.OauthService.OidcCallback(code)
|
err, userData := service.AllService.OauthService.OidcCallback(code)
|
||||||
@@ -286,85 +191,81 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
|
|||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//将空格替换成_
|
openid = userData.Sub
|
||||||
// OidcName := strings.Replace(userData.Name, " ", "_", -1)
|
thirdName = userData.PreferredUsername
|
||||||
if ac == service.OauthActionTypeBind {
|
} else {
|
||||||
//fmt.Println("bind", ty, userData)
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ParamsError"))
|
||||||
utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Sub)
|
return
|
||||||
if utr.UserId > 0 {
|
}
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
|
if ac == service.OauthActionTypeBind {
|
||||||
return
|
|
||||||
}
|
//fmt.Println("bind", ty, userData)
|
||||||
//绑定
|
utr := service.AllService.OauthService.UserThirdInfo(ty, openid)
|
||||||
u = service.AllService.UserService.InfoById(v.UserId)
|
if utr.UserId > 0 {
|
||||||
if u == nil {
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//绑定, user preffered_username as username
|
|
||||||
err = service.AllService.OauthService.BindOidcUser(userData.Sub, userData.PreferredUsername, v.UserId)
|
|
||||||
if err != nil {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
|
|
||||||
return
|
return
|
||||||
} else if ac == service.OauthActionTypeLogin {
|
}
|
||||||
if v.UserId != 0 {
|
//绑定
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
|
u = service.AllService.UserService.InfoById(v.UserId)
|
||||||
|
if u == nil {
|
||||||
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//绑定
|
||||||
|
err := service.AllService.OauthService.BindOauthUser(ty, openid, thirdName, v.UserId)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
|
||||||
|
return
|
||||||
|
|
||||||
|
} else if ac == service.OauthActionTypeLogin {
|
||||||
|
//登录
|
||||||
|
if v.UserId != 0 {
|
||||||
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u = service.AllService.UserService.InfoByGithubId(openid)
|
||||||
|
if u == nil {
|
||||||
|
oa := service.AllService.OauthService.InfoByOp(ty)
|
||||||
|
if !*oa.AutoRegister {
|
||||||
|
//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
|
||||||
|
v.ThirdName = thirdName
|
||||||
|
v.ThirdOpenId = openid
|
||||||
|
url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
|
||||||
|
c.Redirect(http.StatusFound, url)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
u = service.AllService.UserService.InfoByOidcSub(userData.Sub)
|
|
||||||
if u == nil {
|
|
||||||
oa := service.AllService.OauthService.InfoByOp(ty)
|
|
||||||
if !*oa.AutoRegister {
|
|
||||||
//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
|
|
||||||
|
|
||||||
v.ThirdName = userData.PreferredUsername
|
//自动注册
|
||||||
v.ThirdOpenId = userData.Sub
|
u = service.AllService.UserService.RegisterByOauth(ty, thirdName, openid)
|
||||||
v.ThirdEmail = userData.Email
|
if u.Id == 0 {
|
||||||
url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
|
||||||
c.Redirect(http.StatusFound, url)
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//自动注册
|
|
||||||
u = service.AllService.UserService.RegisterByOidc(userData.PreferredUsername, userData.Sub)
|
|
||||||
if u.Id == 0 {
|
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// v.UserId = u.Id
|
|
||||||
// service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
|
|
||||||
// c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
|
|
||||||
// return
|
|
||||||
}
|
}
|
||||||
}
|
v.UserId = u.Id
|
||||||
// 如果u为空,说明没有绑定用户
|
service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
|
||||||
if u == nil {
|
// 如果是webadmin,登录成功后跳转到webadmin
|
||||||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "SystemError"))
|
if v.DeviceType == "webadmin" {
|
||||||
|
/*service.AllService.UserService.Login(u, &model.LoginLog{
|
||||||
|
UserId: u.Id,
|
||||||
|
Client: "webadmin",
|
||||||
|
Uuid: "", //must be empty
|
||||||
|
Ip: c.ClientIP(),
|
||||||
|
Type: model.LoginLogTypeOauth,
|
||||||
|
Platform: v.DeviceOs,
|
||||||
|
})*/
|
||||||
|
url := global.Config.Rustdesk.ApiServer + "/_admin/#/"
|
||||||
|
c.Redirect(http.StatusFound, url)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ParamsError"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 认证成功,设置缓存
|
|
||||||
v.UserId = u.Id
|
|
||||||
service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
|
|
||||||
// 如果是webadmin,登录成功后跳转到webadmin
|
|
||||||
if v.DeviceType == "webadmin" {
|
|
||||||
service.AllService.UserService.Login(u, &model.LoginLog{
|
|
||||||
UserId: u.Id,
|
|
||||||
Client: "webadmin",
|
|
||||||
Uuid: "",//must be empty
|
|
||||||
Ip: c.ClientIP(),
|
|
||||||
Type: "account",
|
|
||||||
Platform: v.DeviceOs,
|
|
||||||
})
|
|
||||||
url := global.Config.Rustdesk.ApiServer + "/_admin/#/"
|
|
||||||
c.Redirect(http.StatusFound, url)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,3 +59,9 @@ type GroupUsersQuery struct {
|
|||||||
IsMy int `json:"is_my"`
|
IsMy int `json:"is_my"`
|
||||||
UserId uint `json:"user_id"`
|
UserId uint `json:"user_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RegisterForm struct {
|
||||||
|
Username string `json:"username" validate:"required,gte=4,lte=10"`
|
||||||
|
Password string `json:"password" validate:"required,gte=4,lte=20"`
|
||||||
|
ConfirmPassword string `json:"confirm_password" validate:"required,gte=4,lte=20"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func Init(g *gin.Engine) {
|
|||||||
|
|
||||||
adg := g.Group("/api/admin")
|
adg := g.Group("/api/admin")
|
||||||
LoginBind(adg)
|
LoginBind(adg)
|
||||||
|
adg.POST("/user/register", (&admin.User{}).Register)
|
||||||
adg.Use(middleware.AdminAuth())
|
adg.Use(middleware.AdminAuth())
|
||||||
//FileBind(adg)
|
//FileBind(adg)
|
||||||
UserBind(adg)
|
UserBind(adg)
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ type LoginLog struct {
|
|||||||
TimeModel
|
TimeModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
LoginLogClientWebAdmin = "webadmin"
|
||||||
|
LoginLogClientWeb = "webclient"
|
||||||
|
LoginLogClientApp = "app"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LoginLogTypeAccount = "account"
|
LoginLogTypeAccount = "account"
|
||||||
LoginLogTypeOauth = "oauth"
|
LoginLogTypeOauth = "oauth"
|
||||||
|
|||||||
@@ -119,3 +119,7 @@ other = "Default Group"
|
|||||||
description = "Share group"
|
description = "Share group"
|
||||||
one = "Share Group"
|
one = "Share Group"
|
||||||
other = "Share Group"
|
other = "Share Group"
|
||||||
|
[RegisterClosed]
|
||||||
|
description = "Register closed."
|
||||||
|
one = "Register closed."
|
||||||
|
other = "Register closed."
|
||||||
|
|||||||
@@ -121,3 +121,8 @@ other = "기본 그룹"
|
|||||||
description = "Share group."
|
description = "Share group."
|
||||||
one = "공유 그룹"
|
one = "공유 그룹"
|
||||||
other = "공유 그룹"
|
other = "공유 그룹"
|
||||||
|
|
||||||
|
[RegisterClosed]
|
||||||
|
description = "Register closed."
|
||||||
|
one = "가입이 종료되었습니다."
|
||||||
|
other = "가입이 종료되었습니다."
|
||||||
@@ -127,3 +127,8 @@ other = "Группа по умолчанию"
|
|||||||
description = "Share group."
|
description = "Share group."
|
||||||
one = "Общая группа"
|
one = "Общая группа"
|
||||||
other = "Общая группа"
|
other = "Общая группа"
|
||||||
|
|
||||||
|
[RegisterClosed]
|
||||||
|
description = "Register closed."
|
||||||
|
one = "Регистрация закрыта."
|
||||||
|
other = "Регистрация закрыта."
|
||||||
@@ -121,3 +121,7 @@ other = "默认组"
|
|||||||
description = "Share group."
|
description = "Share group."
|
||||||
one = "共享组"
|
one = "共享组"
|
||||||
other = "共享组"
|
other = "共享组"
|
||||||
|
[RegisterClosed]
|
||||||
|
description = "Register closed."
|
||||||
|
one = "注册已关闭。"
|
||||||
|
other = "注册已关闭。"
|
||||||
@@ -15,9 +15,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Define a struct to parse the .well-known/openid-configuration response
|
// Define a struct to parse the .well-known/openid-configuration response
|
||||||
@@ -88,10 +88,10 @@ type GoogleUserdata struct {
|
|||||||
VerifiedEmail bool `json:"verified_email"`
|
VerifiedEmail bool `json:"verified_email"`
|
||||||
}
|
}
|
||||||
type OidcUserdata struct {
|
type OidcUserdata struct {
|
||||||
Sub string `json:"sub"`
|
Sub string `json:"sub"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
VerifiedEmail bool `json:"email_verified"`
|
VerifiedEmail bool `json:"email_verified"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
PreferredUsername string `json:"preferred_username"`
|
PreferredUsername string `json:"preferred_username"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,27 +156,27 @@ func (os *OauthService) BeginAuth(op string) (error error, code, url string) {
|
|||||||
|
|
||||||
// Method to fetch OIDC configuration dynamically
|
// Method to fetch OIDC configuration dynamically
|
||||||
func FetchOidcConfig(issuer string) (error, OidcEndpoint) {
|
func FetchOidcConfig(issuer string) (error, OidcEndpoint) {
|
||||||
configURL := strings.TrimSuffix(issuer, "/") + "/.well-known/openid-configuration"
|
configURL := strings.TrimSuffix(issuer, "/") + "/.well-known/openid-configuration"
|
||||||
|
|
||||||
// Get the HTTP client (with or without proxy based on configuration)
|
// Get the HTTP client (with or without proxy based on configuration)
|
||||||
client := getHTTPClientWithProxy()
|
client := getHTTPClientWithProxy()
|
||||||
|
|
||||||
resp, err := client.Get(configURL)
|
resp, err := client.Get(configURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to fetch OIDC configuration"), OidcEndpoint{}
|
return errors.New("failed to fetch OIDC configuration"), OidcEndpoint{}
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return errors.New("OIDC configuration not found, status code: %d"), OidcEndpoint{}
|
return errors.New("OIDC configuration not found, status code: %d"), OidcEndpoint{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var endpoint OidcEndpoint
|
var endpoint OidcEndpoint
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&endpoint); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&endpoint); err != nil {
|
||||||
return errors.New("failed to parse OIDC configuration"), OidcEndpoint{}
|
return errors.New("failed to parse OIDC configuration"), OidcEndpoint{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, endpoint
|
return nil, endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOauthConfig retrieves the OAuth2 configuration based on the provider type
|
// GetOauthConfig retrieves the OAuth2 configuration based on the provider type
|
||||||
@@ -253,6 +253,7 @@ func (os *OauthService) getOidcConfig() (error, *oauth2.Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getHTTPClientWithProxy() *http.Client {
|
func getHTTPClientWithProxy() *http.Client {
|
||||||
|
//todo add timeout
|
||||||
if global.Config.Proxy.Enable {
|
if global.Config.Proxy.Enable {
|
||||||
if global.Config.Proxy.Host == "" {
|
if global.Config.Proxy.Host == "" {
|
||||||
global.Logger.Warn("Proxy is enabled but proxy host is empty.")
|
global.Logger.Warn("Proxy is enabled but proxy host is empty.")
|
||||||
@@ -446,7 +447,6 @@ func (os *OauthService) DeleteUserByUserId(userid uint) error {
|
|||||||
return global.DB.Where("user_id = ?", userid).Delete(&model.UserThird{}).Error
|
return global.DB.Where("user_id = ?", userid).Delete(&model.UserThird{}).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// InfoById 根据id取用户信息
|
// InfoById 根据id取用户信息
|
||||||
func (os *OauthService) InfoById(id uint) *model.Oauth {
|
func (os *OauthService) InfoById(id uint) *model.Oauth {
|
||||||
u := &model.Oauth{}
|
u := &model.Oauth{}
|
||||||
|
|||||||
@@ -151,15 +151,34 @@ func (us *UserService) Logout(u *model.User, token string) error {
|
|||||||
|
|
||||||
// Delete 删除用户和oauth信息
|
// Delete 删除用户和oauth信息
|
||||||
func (us *UserService) Delete(u *model.User) error {
|
func (us *UserService) Delete(u *model.User) error {
|
||||||
// 删除用户
|
tx := global.DB.Begin()
|
||||||
if err := global.DB.Delete(u).Error; err != nil {
|
// 删除用户
|
||||||
return err
|
if err := tx.Delete(u).Error; err != nil {
|
||||||
}
|
tx.Rollback()
|
||||||
// 删除关联的 OAuth 信息
|
return err
|
||||||
if err := AllService.OauthService.DeleteUserByUserId(u.Id); err != nil {
|
}
|
||||||
return err
|
// 删除关联的 OAuth 信息
|
||||||
}
|
if err := tx.Where("user_id = ?", u.Id).Delete(&model.UserThird{}).Error; err != nil {
|
||||||
return nil
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 删除关联的ab
|
||||||
|
if err := tx.Where("user_id = ?", u.Id).Delete(&model.AddressBook{}).Error; err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 删除关联的abc
|
||||||
|
if err := tx.Where("user_id = ?", u.Id).Delete(&model.AddressBookCollection{}).Error; err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 删除关联的abcr
|
||||||
|
if err := tx.Where("user_id = ?", u.Id).Delete(&model.AddressBookCollectionRule{}).Error; err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tx.Commit()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update 更新
|
// Update 更新
|
||||||
@@ -262,14 +281,14 @@ func (us *UserService) RegisterByOauth(thirdType, thirdName, uid string) *model.
|
|||||||
Username: username,
|
Username: username,
|
||||||
GroupId: 1,
|
GroupId: 1,
|
||||||
}
|
}
|
||||||
global.DB.Create(u)
|
tx.Create(u)
|
||||||
if u.Id == 0 {
|
if u.Id == 0 {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
ut.UserId = u.Id
|
ut.UserId = u.Id
|
||||||
global.DB.Create(ut)
|
tx.Create(ut)
|
||||||
|
|
||||||
tx.Commit()
|
tx.Commit()
|
||||||
return u
|
return u
|
||||||
@@ -328,3 +347,12 @@ func (us *UserService) IsPasswordEmptyByUser(u *model.User) bool {
|
|||||||
return us.IsPasswordEmptyById(u.Id)
|
return us.IsPasswordEmptyById(u.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (us *UserService) Register(username string, password string) *model.User {
|
||||||
|
u := &model.User{
|
||||||
|
Username: username,
|
||||||
|
Password: us.EncryptPassword(password),
|
||||||
|
GroupId: 1,
|
||||||
|
}
|
||||||
|
global.DB.Create(u)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user