Просмотр исходного кода

Merge branch 'master' into resetEmptyPassWD

Tao Chen 1 год назад
Родитель
Сommit
5488babfb3

+ 2 - 0
README.md

@@ -159,6 +159,7 @@
159
 lang: "en"
159
 lang: "en"
160
 app:
160
 app:
161
   web-client: 1  # 1:启用 0:禁用
161
   web-client: 1  # 1:启用 0:禁用
162
+  register: false #是否开启注册
162
 gin:
163
 gin:
163
   api-addr: "0.0.0.0:21114"
164
   api-addr: "0.0.0.0:21114"
164
   mode: "release"
165
   mode: "release"
@@ -196,6 +197,7 @@ proxy:
196
 | TZ                                 | 时区                                   | Asia/Shanghai               |
197
 | TZ                                 | 时区                                   | Asia/Shanghai               |
197
 | RUSTDESK_API_LANG                  | 语言                                   | `en`,`zh-CN`                |
198
 | RUSTDESK_API_LANG                  | 语言                                   | `en`,`zh-CN`                |
198
 | RUSTDESK_API_APP_WEB_CLIENT        | 是否启用web-client; 1:启用,0:不启用; 默认启用     | 1                           |
199
 | RUSTDESK_API_APP_WEB_CLIENT        | 是否启用web-client; 1:启用,0:不启用; 默认启用     | 1                           |
200
+| RUSTDESK_API_APP_REGISTER          | 是否开启注册; `true`, `false`  默认`false`   | `false`                     |
199
 | -----GIN配置-----                    | ----------                           | ----------                  |
201
 | -----GIN配置-----                    | ----------                           | ----------                  |
200
 | RUSTDESK_API_GIN_TRUST_PROXY       | 信任的代理IP列表,以`,`分割,默认信任所有              | 192.168.1.2,192.168.1.3     |
202
 | RUSTDESK_API_GIN_TRUST_PROXY       | 信任的代理IP列表,以`,`分割,默认信任所有              | 192.168.1.2,192.168.1.3     |
201
 | -----------GORM配置----------------  | ------------------------------------ | --------------------------- |
203
 | -----------GORM配置----------------  | ------------------------------------ | --------------------------- |

+ 2 - 0
README_EN.md

@@ -165,6 +165,7 @@ installation are `admin` `admin`, please change the password immediately.
165
 lang: "en"
165
 lang: "en"
166
 app:
166
 app:
167
   web-client: 1  # web client route 1:open 0:close  
167
   web-client: 1  # web client route 1:open 0:close  
168
+  register: false #register enable
168
 gin:
169
 gin:
169
   api-addr: "0.0.0.0:21114"
170
   api-addr: "0.0.0.0:21114"
170
   mode: "release"
171
   mode: "release"
@@ -202,6 +203,7 @@ The prefix for variable names is `RUSTDESK_API`. If environment variables exist,
202
 | TZ                                 | timezone                                                  | Asia/Shanghai                 |
203
 | TZ                                 | timezone                                                  | Asia/Shanghai                 |
203
 | RUSTDESK_API_LANG                  | Language                                                  | `en`,`zh-CN`                  |
204
 | RUSTDESK_API_LANG                  | Language                                                  | `en`,`zh-CN`                  |
204
 | RUSTDESK_API_APP_WEB_CLIENT        | web client on/off; 1: on, 0 off, deault 1                 | 1                             |
205
 | RUSTDESK_API_APP_WEB_CLIENT        | web client on/off; 1: on, 0 off, deault 1                 | 1                             |
206
+| RUSTDESK_API_APP_REGISTER          | register enable; `true`, `false`; default:`false`         | `false`                       |
205
 | ----- GIN Configuration -----      | ---------------------------------------                   | ----------------------------- |
207
 | ----- GIN Configuration -----      | ---------------------------------------                   | ----------------------------- |
206
 | RUSTDESK_API_GIN_TRUST_PROXY       | Trusted proxy IPs, separated by commas.                   | 192.168.1.2,192.168.1.3       |
208
 | RUSTDESK_API_GIN_TRUST_PROXY       | Trusted proxy IPs, separated by commas.                   | 192.168.1.2,192.168.1.3       |
207
 | ----- GORM Configuration -----     | ---------------------------------------                   | ----------------------------- |
209
 | ----- GORM Configuration -----     | ---------------------------------------                   | ----------------------------- |

+ 1 - 1
cmd/apimain.go

@@ -101,7 +101,7 @@ func main() {
101
 }
101
 }
102
 
102
 
103
 func DatabaseAutoUpdate() {
103
 func DatabaseAutoUpdate() {
104
-	version := 242
104
+	version := 243
105
 
105
 
106
 	db := global.DB
106
 	db := global.DB
107
 
107
 

+ 1 - 0
conf/config.yaml

@@ -1,6 +1,7 @@
1
 lang: "zh-CN"
1
 lang: "zh-CN"
2
 app:
2
 app:
3
   web-client: 1  # 1:启用 0:禁用
3
   web-client: 1  # 1:启用 0:禁用
4
+  register: false #是否开启注册
4
 gin:
5
 gin:
5
   api-addr: "0.0.0.0:21114"
6
   api-addr: "0.0.0.0:21114"
6
   mode: "release" #release,debug,test
7
   mode: "release" #release,debug,test

+ 2 - 1
config/config.go

@@ -15,7 +15,8 @@ const (
15
 )
15
 )
16
 
16
 
17
 type App struct {
17
 type App struct {
18
-	WebClient int `mapstructure:"web-client"`
18
+	WebClient int  `mapstructure:"web-client"`
19
+	Register  bool `mapstructure:"register"`
19
 }
20
 }
20
 
21
 
21
 type Config struct {
22
 type Config struct {

+ 20 - 0
docker-compose-dev.yaml

@@ -0,0 +1,20 @@
1
+services:
2
+  rustdesk-api:
3
+    build: 
4
+      context: .
5
+      dockerfile: Dockerfile.dev
6
+    # image: lejianwen/rustdesk-api
7
+    container_name: rustdesk-api
8
+    environment:
9
+      - TZ=Asia/Shanghai
10
+      - RUSTDESK_API_RUSTDESK_ID_SERVER=192.168.1.66:21116
11
+      - RUSTDESK_API_RUSTDESK_RELAY_SERVER=192.168.1.66:21117
12
+      - RUSTDESK_API_RUSTDESK_API_SERVER=http://127.0.0.1:21114
13
+      - RUSTDESK_API_RUSTDESK_KEY=123456789
14
+    ports:
15
+      - 21114:21114
16
+    volumes:
17
+      - ./data/rustdesk/api:/app/data #将数据库挂载出来方便备份
18
+      - ./conf:/app/conf # config
19
+      # - ./resources:/app/resources # 静态资源
20
+    restart: unless-stopped

+ 3 - 6
docker-compose.yaml

@@ -1,9 +1,6 @@
1
 services:
1
 services:
2
   rustdesk-api:
2
   rustdesk-api:
3
-    build: 
4
-      context: .
5
-      dockerfile: Dockerfile.dev
6
-    # image: lejianwen/rustdesk-api
3
+    image: lejianwen/rustdesk-api
7
     container_name: rustdesk-api
4
     container_name: rustdesk-api
8
     environment:
5
     environment:
9
       - TZ=Asia/Shanghai
6
       - TZ=Asia/Shanghai
@@ -14,7 +11,7 @@ services:
14
     ports:
11
     ports:
15
       - 21114:21114
12
       - 21114:21114
16
     volumes:
13
     volumes:
17
-      - ./data/rustdesk/api:/app/data #将数据库挂载出来方便备份
18
-      - ./conf:/app/conf # config
14
+      - ./data/rustdesk/api:/app/data # database
15
+      # - ./conf:/app/conf # config
19
       # - ./resources:/app/resources # 静态资源
16
       # - ./resources:/app/resources # 静态资源
20
     restart: unless-stopped
17
     restart: unless-stopped

+ 112 - 0
docs/admin/admin_docs.go

@@ -1453,6 +1453,38 @@ const docTemplateadmin = `{
1453
                 }
1453
                 }
1454
             }
1454
             }
1455
         },
1455
         },
1456
+        "/admin/login-options": {
1457
+            "post": {
1458
+                "description": "登录选项",
1459
+                "consumes": [
1460
+                    "application/json"
1461
+                ],
1462
+                "produces": [
1463
+                    "application/json"
1464
+                ],
1465
+                "tags": [
1466
+                    "登录"
1467
+                ],
1468
+                "summary": "登录选项",
1469
+                "responses": {
1470
+                    "200": {
1471
+                        "description": "OK",
1472
+                        "schema": {
1473
+                            "type": "array",
1474
+                            "items": {
1475
+                                "type": "string"
1476
+                            }
1477
+                        }
1478
+                    },
1479
+                    "500": {
1480
+                        "description": "Internal Server Error",
1481
+                        "schema": {
1482
+                            "$ref": "#/definitions/response.ErrorResponse"
1483
+                        }
1484
+                    }
1485
+                }
1486
+            }
1487
+        },
1456
         "/admin/loginLog/delete": {
1488
         "/admin/loginLog/delete": {
1457
             "post": {
1489
             "post": {
1458
                 "security": [
1490
                 "security": [
@@ -1922,6 +1954,63 @@ const docTemplateadmin = `{
1922
                 }
1954
                 }
1923
             }
1955
             }
1924
         },
1956
         },
1957
+        "/admin/oidc/auth": {
1958
+            "post": {
1959
+                "description": "OidcAuth",
1960
+                "consumes": [
1961
+                    "application/json"
1962
+                ],
1963
+                "produces": [
1964
+                    "application/json"
1965
+                ],
1966
+                "tags": [
1967
+                    "Oauth"
1968
+                ],
1969
+                "summary": "OidcAuth",
1970
+                "responses": {}
1971
+            }
1972
+        },
1973
+        "/admin/oidc/auth-query": {
1974
+            "get": {
1975
+                "description": "OidcAuthQuery",
1976
+                "consumes": [
1977
+                    "application/json"
1978
+                ],
1979
+                "produces": [
1980
+                    "application/json"
1981
+                ],
1982
+                "tags": [
1983
+                    "Oauth"
1984
+                ],
1985
+                "summary": "OidcAuthQuery",
1986
+                "responses": {
1987
+                    "200": {
1988
+                        "description": "OK",
1989
+                        "schema": {
1990
+                            "allOf": [
1991
+                                {
1992
+                                    "$ref": "#/definitions/response.Response"
1993
+                                },
1994
+                                {
1995
+                                    "type": "object",
1996
+                                    "properties": {
1997
+                                        "data": {
1998
+                                            "$ref": "#/definitions/admin.LoginPayload"
1999
+                                        }
2000
+                                    }
2001
+                                }
2002
+                            ]
2003
+                        }
2004
+                    },
2005
+                    "500": {
2006
+                        "description": "Internal Server Error",
2007
+                        "schema": {
2008
+                            "$ref": "#/definitions/response.Response"
2009
+                        }
2010
+                    }
2011
+                }
2012
+            }
2013
+        },
1925
         "/admin/peer/create": {
2014
         "/admin/peer/create": {
1926
             "post": {
2015
             "post": {
1927
                 "security": [
2016
                 "security": [
@@ -3164,11 +3253,17 @@ const docTemplateadmin = `{
3164
                 "id": {
3253
                 "id": {
3165
                     "type": "integer"
3254
                     "type": "integer"
3166
                 },
3255
                 },
3256
+                "issuer": {
3257
+                    "type": "string"
3258
+                },
3167
                 "op": {
3259
                 "op": {
3168
                     "type": "string"
3260
                     "type": "string"
3169
                 },
3261
                 },
3170
                 "redirect_url": {
3262
                 "redirect_url": {
3171
                     "type": "string"
3263
                     "type": "string"
3264
+                },
3265
+                "scopes": {
3266
+                    "type": "string"
3172
                 }
3267
                 }
3173
             }
3268
             }
3174
         },
3269
         },
@@ -3749,12 +3844,18 @@ const docTemplateadmin = `{
3749
                 "id": {
3844
                 "id": {
3750
                     "type": "integer"
3845
                     "type": "integer"
3751
                 },
3846
                 },
3847
+                "issuer": {
3848
+                    "type": "string"
3849
+                },
3752
                 "op": {
3850
                 "op": {
3753
                     "type": "string"
3851
                     "type": "string"
3754
                 },
3852
                 },
3755
                 "redirect_url": {
3853
                 "redirect_url": {
3756
                     "type": "string"
3854
                     "type": "string"
3757
                 },
3855
                 },
3856
+                "scopes": {
3857
+                    "type": "string"
3858
+                },
3758
                 "updated_at": {
3859
                 "updated_at": {
3759
                     "type": "string"
3860
                     "type": "string"
3760
                 }
3861
                 }
@@ -3795,6 +3896,9 @@ const docTemplateadmin = `{
3795
                 "id": {
3896
                 "id": {
3796
                     "type": "string"
3897
                     "type": "string"
3797
                 },
3898
                 },
3899
+                "last_online_ip": {
3900
+                    "type": "string"
3901
+                },
3798
                 "last_online_time": {
3902
                 "last_online_time": {
3799
                     "type": "integer"
3903
                     "type": "integer"
3800
                 },
3904
                 },
@@ -3964,6 +4068,14 @@ const docTemplateadmin = `{
3964
                 }
4068
                 }
3965
             }
4069
             }
3966
         },
4070
         },
4071
+        "response.ErrorResponse": {
4072
+            "type": "object",
4073
+            "properties": {
4074
+                "error": {
4075
+                    "type": "string"
4076
+                }
4077
+            }
4078
+        },
3967
         "response.Response": {
4079
         "response.Response": {
3968
             "type": "object",
4080
             "type": "object",
3969
             "properties": {
4081
             "properties": {

+ 112 - 0
docs/admin/admin_swagger.json

@@ -1446,6 +1446,38 @@
1446
                 }
1446
                 }
1447
             }
1447
             }
1448
         },
1448
         },
1449
+        "/admin/login-options": {
1450
+            "post": {
1451
+                "description": "登录选项",
1452
+                "consumes": [
1453
+                    "application/json"
1454
+                ],
1455
+                "produces": [
1456
+                    "application/json"
1457
+                ],
1458
+                "tags": [
1459
+                    "登录"
1460
+                ],
1461
+                "summary": "登录选项",
1462
+                "responses": {
1463
+                    "200": {
1464
+                        "description": "OK",
1465
+                        "schema": {
1466
+                            "type": "array",
1467
+                            "items": {
1468
+                                "type": "string"
1469
+                            }
1470
+                        }
1471
+                    },
1472
+                    "500": {
1473
+                        "description": "Internal Server Error",
1474
+                        "schema": {
1475
+                            "$ref": "#/definitions/response.ErrorResponse"
1476
+                        }
1477
+                    }
1478
+                }
1479
+            }
1480
+        },
1449
         "/admin/loginLog/delete": {
1481
         "/admin/loginLog/delete": {
1450
             "post": {
1482
             "post": {
1451
                 "security": [
1483
                 "security": [
@@ -1915,6 +1947,63 @@
1915
                 }
1947
                 }
1916
             }
1948
             }
1917
         },
1949
         },
1950
+        "/admin/oidc/auth": {
1951
+            "post": {
1952
+                "description": "OidcAuth",
1953
+                "consumes": [
1954
+                    "application/json"
1955
+                ],
1956
+                "produces": [
1957
+                    "application/json"
1958
+                ],
1959
+                "tags": [
1960
+                    "Oauth"
1961
+                ],
1962
+                "summary": "OidcAuth",
1963
+                "responses": {}
1964
+            }
1965
+        },
1966
+        "/admin/oidc/auth-query": {
1967
+            "get": {
1968
+                "description": "OidcAuthQuery",
1969
+                "consumes": [
1970
+                    "application/json"
1971
+                ],
1972
+                "produces": [
1973
+                    "application/json"
1974
+                ],
1975
+                "tags": [
1976
+                    "Oauth"
1977
+                ],
1978
+                "summary": "OidcAuthQuery",
1979
+                "responses": {
1980
+                    "200": {
1981
+                        "description": "OK",
1982
+                        "schema": {
1983
+                            "allOf": [
1984
+                                {
1985
+                                    "$ref": "#/definitions/response.Response"
1986
+                                },
1987
+                                {
1988
+                                    "type": "object",
1989
+                                    "properties": {
1990
+                                        "data": {
1991
+                                            "$ref": "#/definitions/admin.LoginPayload"
1992
+                                        }
1993
+                                    }
1994
+                                }
1995
+                            ]
1996
+                        }
1997
+                    },
1998
+                    "500": {
1999
+                        "description": "Internal Server Error",
2000
+                        "schema": {
2001
+                            "$ref": "#/definitions/response.Response"
2002
+                        }
2003
+                    }
2004
+                }
2005
+            }
2006
+        },
1918
         "/admin/peer/create": {
2007
         "/admin/peer/create": {
1919
             "post": {
2008
             "post": {
1920
                 "security": [
2009
                 "security": [
@@ -3157,11 +3246,17 @@
3157
                 "id": {
3246
                 "id": {
3158
                     "type": "integer"
3247
                     "type": "integer"
3159
                 },
3248
                 },
3249
+                "issuer": {
3250
+                    "type": "string"
3251
+                },
3160
                 "op": {
3252
                 "op": {
3161
                     "type": "string"
3253
                     "type": "string"
3162
                 },
3254
                 },
3163
                 "redirect_url": {
3255
                 "redirect_url": {
3164
                     "type": "string"
3256
                     "type": "string"
3257
+                },
3258
+                "scopes": {
3259
+                    "type": "string"
3165
                 }
3260
                 }
3166
             }
3261
             }
3167
         },
3262
         },
@@ -3742,12 +3837,18 @@
3742
                 "id": {
3837
                 "id": {
3743
                     "type": "integer"
3838
                     "type": "integer"
3744
                 },
3839
                 },
3840
+                "issuer": {
3841
+                    "type": "string"
3842
+                },
3745
                 "op": {
3843
                 "op": {
3746
                     "type": "string"
3844
                     "type": "string"
3747
                 },
3845
                 },
3748
                 "redirect_url": {
3846
                 "redirect_url": {
3749
                     "type": "string"
3847
                     "type": "string"
3750
                 },
3848
                 },
3849
+                "scopes": {
3850
+                    "type": "string"
3851
+                },
3751
                 "updated_at": {
3852
                 "updated_at": {
3752
                     "type": "string"
3853
                     "type": "string"
3753
                 }
3854
                 }
@@ -3788,6 +3889,9 @@
3788
                 "id": {
3889
                 "id": {
3789
                     "type": "string"
3890
                     "type": "string"
3790
                 },
3891
                 },
3892
+                "last_online_ip": {
3893
+                    "type": "string"
3894
+                },
3791
                 "last_online_time": {
3895
                 "last_online_time": {
3792
                     "type": "integer"
3896
                     "type": "integer"
3793
                 },
3897
                 },
@@ -3957,6 +4061,14 @@
3957
                 }
4061
                 }
3958
             }
4062
             }
3959
         },
4063
         },
4064
+        "response.ErrorResponse": {
4065
+            "type": "object",
4066
+            "properties": {
4067
+                "error": {
4068
+                    "type": "string"
4069
+                }
4070
+            }
4071
+        },
3960
         "response.Response": {
4072
         "response.Response": {
3961
             "type": "object",
4073
             "type": "object",
3962
             "properties": {
4074
             "properties": {

+ 71 - 0
docs/admin/admin_swagger.yaml

@@ -105,10 +105,14 @@ definitions:
105
         type: string
105
         type: string
106
       id:
106
       id:
107
         type: integer
107
         type: integer
108
+      issuer:
109
+        type: string
108
       op:
110
       op:
109
         type: string
111
         type: string
110
       redirect_url:
112
       redirect_url:
111
         type: string
113
         type: string
114
+      scopes:
115
+        type: string
112
     required:
116
     required:
113
     - client_id
117
     - client_id
114
     - client_secret
118
     - client_secret
@@ -500,10 +504,14 @@ definitions:
500
         type: string
504
         type: string
501
       id:
505
       id:
502
         type: integer
506
         type: integer
507
+      issuer:
508
+        type: string
503
       op:
509
       op:
504
         type: string
510
         type: string
505
       redirect_url:
511
       redirect_url:
506
         type: string
512
         type: string
513
+      scopes:
514
+        type: string
507
       updated_at:
515
       updated_at:
508
         type: string
516
         type: string
509
     type: object
517
     type: object
@@ -530,6 +538,8 @@ definitions:
530
         type: string
538
         type: string
531
       id:
539
       id:
532
         type: string
540
         type: string
541
+      last_online_ip:
542
+        type: string
533
       last_online_time:
543
       last_online_time:
534
         type: integer
544
         type: integer
535
       memory:
545
       memory:
@@ -643,6 +653,11 @@ definitions:
643
       total:
653
       total:
644
         type: integer
654
         type: integer
645
     type: object
655
     type: object
656
+  response.ErrorResponse:
657
+    properties:
658
+      error:
659
+        type: string
660
+    type: object
646
   response.Response:
661
   response.Response:
647
     properties:
662
     properties:
648
       code:
663
       code:
@@ -1510,6 +1525,27 @@ paths:
1510
       summary: 登录
1525
       summary: 登录
1511
       tags:
1526
       tags:
1512
       - 登录
1527
       - 登录
1528
+  /admin/login-options:
1529
+    post:
1530
+      consumes:
1531
+      - application/json
1532
+      description: 登录选项
1533
+      produces:
1534
+      - application/json
1535
+      responses:
1536
+        "200":
1537
+          description: OK
1538
+          schema:
1539
+            items:
1540
+              type: string
1541
+            type: array
1542
+        "500":
1543
+          description: Internal Server Error
1544
+          schema:
1545
+            $ref: '#/definitions/response.ErrorResponse'
1546
+      summary: 登录选项
1547
+      tags:
1548
+      - 登录
1513
   /admin/loginLog/delete:
1549
   /admin/loginLog/delete:
1514
     post:
1550
     post:
1515
       consumes:
1551
       consumes:
@@ -1789,6 +1825,41 @@ paths:
1789
       summary: Oauth编辑
1825
       summary: Oauth编辑
1790
       tags:
1826
       tags:
1791
       - Oauth
1827
       - Oauth
1828
+  /admin/oidc/auth:
1829
+    post:
1830
+      consumes:
1831
+      - application/json
1832
+      description: OidcAuth
1833
+      produces:
1834
+      - application/json
1835
+      responses: {}
1836
+      summary: OidcAuth
1837
+      tags:
1838
+      - Oauth
1839
+  /admin/oidc/auth-query:
1840
+    get:
1841
+      consumes:
1842
+      - application/json
1843
+      description: OidcAuthQuery
1844
+      produces:
1845
+      - application/json
1846
+      responses:
1847
+        "200":
1848
+          description: OK
1849
+          schema:
1850
+            allOf:
1851
+            - $ref: '#/definitions/response.Response'
1852
+            - properties:
1853
+                data:
1854
+                  $ref: '#/definitions/admin.LoginPayload'
1855
+              type: object
1856
+        "500":
1857
+          description: Internal Server Error
1858
+          schema:
1859
+            $ref: '#/definitions/response.Response'
1860
+      summary: OidcAuthQuery
1861
+      tags:
1862
+      - Oauth
1792
   /admin/peer/create:
1863
   /admin/peer/create:
1793
     post:
1864
     post:
1794
       consumes:
1865
       consumes:

+ 1 - 1
docs/api/api_docs.go

@@ -834,7 +834,7 @@ const docTemplateapi = `{
834
             }
834
             }
835
         },
835
         },
836
         "/login-options": {
836
         "/login-options": {
837
-            "post": {
837
+            "get": {
838
                 "description": "登录选项",
838
                 "description": "登录选项",
839
                 "consumes": [
839
                 "consumes": [
840
                     "application/json"
840
                     "application/json"

+ 1 - 1
docs/api/api_swagger.json

@@ -827,7 +827,7 @@
827
             }
827
             }
828
         },
828
         },
829
         "/login-options": {
829
         "/login-options": {
830
-            "post": {
830
+            "get": {
831
                 "description": "登录选项",
831
                 "description": "登录选项",
832
                 "consumes": [
832
                 "consumes": [
833
                     "application/json"
833
                     "application/json"

+ 1 - 1
docs/api/api_swagger.yaml

@@ -715,7 +715,7 @@ paths:
715
       tags:
715
       tags:
716
       - 登录
716
       - 登录
717
   /login-options:
717
   /login-options:
718
-    post:
718
+    get:
719
       consumes:
719
       consumes:
720
       - application/json
720
       - application/json
721
       description: 登录选项
721
       description: 登录选项

+ 22 - 17
http/controller/admin/login.go

@@ -2,15 +2,16 @@ package admin
2
 
2
 
3
 import (
3
 import (
4
 	"Gwen/global"
4
 	"Gwen/global"
5
+	"Gwen/http/controller/api"
5
 	"Gwen/http/request/admin"
6
 	"Gwen/http/request/admin"
7
+	apiReq "Gwen/http/request/api"
6
 	"Gwen/http/response"
8
 	"Gwen/http/response"
7
 	adResp "Gwen/http/response/admin"
9
 	adResp "Gwen/http/response/admin"
8
-	apiReq "Gwen/http/request/api"
9
-	"Gwen/http/controller/api"
10
 	"Gwen/model"
10
 	"Gwen/model"
11
 	"Gwen/service"
11
 	"Gwen/service"
12
 	"fmt"
12
 	"fmt"
13
 	"github.com/gin-gonic/gin"
13
 	"github.com/gin-gonic/gin"
14
+	"gorm.io/gorm"
14
 )
15
 )
15
 
16
 
16
 type Login struct {
17
 type Login struct {
@@ -85,7 +86,6 @@ func (ct *Login) Logout(c *gin.Context) {
85
 	response.Success(c, nil)
86
 	response.Success(c, nil)
86
 }
87
 }
87
 
88
 
88
-
89
 // LoginOptions
89
 // LoginOptions
90
 // @Tags 登录
90
 // @Tags 登录
91
 // @Summary 登录选项
91
 // @Summary 登录选项
@@ -95,13 +95,20 @@ func (ct *Login) Logout(c *gin.Context) {
95
 // @Success 200 {object} []string
95
 // @Success 200 {object} []string
96
 // @Failure 500 {object} response.ErrorResponse
96
 // @Failure 500 {object} response.ErrorResponse
97
 // @Router /admin/login-options [post]
97
 // @Router /admin/login-options [post]
98
-// 直接调用/api/login的LoginOptions方法
99
 func (ct *Login) LoginOptions(c *gin.Context) {
98
 func (ct *Login) LoginOptions(c *gin.Context) {
100
-	l := &api.Login{}
101
-    l.LoginOptions(c)
99
+	res := service.AllService.OauthService.List(1, 100, func(tx *gorm.DB) {
100
+		tx.Select("op").Order("id")
101
+	})
102
+	var ops []string
103
+	for _, v := range res.Oauths {
104
+		ops = append(ops, v.Op)
105
+	}
106
+	response.Success(c, gin.H{
107
+		"ops":      ops,
108
+		"register": global.Config.App.Register,
109
+	})
102
 }
110
 }
103
 
111
 
104
-
105
 // OidcAuth
112
 // OidcAuth
106
 // @Tags Oauth
113
 // @Tags Oauth
107
 // @Summary OidcAuth
114
 // @Summary OidcAuth
@@ -126,13 +133,13 @@ func (ct *Login) OidcAuth(c *gin.Context) {
126
 	}
133
 	}
127
 
134
 
128
 	service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
135
 	service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
129
-		Action: service.OauthActionTypeLogin,
130
-		Op:     	f.Op,
131
-		Id: 		f.Id,
136
+		Action:     service.OauthActionTypeLogin,
137
+		Op:         f.Op,
138
+		Id:         f.Id,
132
 		DeviceType: "webadmin",
139
 		DeviceType: "webadmin",
133
 		// DeviceOs: ct.Platform(c),
140
 		// DeviceOs: ct.Platform(c),
134
-		DeviceOs: 	f.DeviceInfo.Os,
135
-		Uuid: 		f.Uuid,
141
+		DeviceOs: f.DeviceInfo.Os,
142
+		Uuid:     f.Uuid,
136
 	}, 5*60)
143
 	}, 5*60)
137
 
144
 
138
 	response.Success(c, gin.H{
145
 	response.Success(c, gin.H{
@@ -141,8 +148,6 @@ func (ct *Login) OidcAuth(c *gin.Context) {
141
 	})
148
 	})
142
 }
149
 }
143
 
150
 
144
-
145
-
146
 // OidcAuthQuery
151
 // OidcAuthQuery
147
 // @Tags Oauth
152
 // @Tags Oauth
148
 // @Summary OidcAuthQuery
153
 // @Summary OidcAuthQuery
@@ -158,12 +163,12 @@ func (ct *Login) OidcAuthQuery(c *gin.Context) {
158
 	if ut == nil {
163
 	if ut == nil {
159
 		return
164
 		return
160
 	}
165
 	}
161
-	fmt.Println("u:", u)
162
-	fmt.Println("ut:", ut)
166
+	//fmt.Println("u:", u)
167
+	//fmt.Println("ut:", ut)
163
 	response.Success(c, &adResp.LoginPayload{
168
 	response.Success(c, &adResp.LoginPayload{
164
 		Token:      ut.Token,
169
 		Token:      ut.Token,
165
 		Username:   u.Username,
170
 		Username:   u.Username,
166
 		RouteNames: service.AllService.UserService.RouteNames(u),
171
 		RouteNames: service.AllService.UserService.RouteNames(u),
167
 		Nickname:   u.Nickname,
172
 		Nickname:   u.Nickname,
168
 	})
173
 	})
169
-}
174
+}

+ 1 - 1
http/controller/admin/oauth.go

@@ -102,7 +102,7 @@ func (o *Oauth) BindConfirm(c *gin.Context) {
102
 		return
102
 		return
103
 	}
103
 	}
104
 	u := service.AllService.UserService.CurUser(c)
104
 	u := service.AllService.UserService.CurUser(c)
105
-	err = service.AllService.OauthService.BindGithubUser(v.ThirdOpenId, v.ThirdOpenId, u.Id)
105
+	err = service.AllService.OauthService.BindOauthUser(v.Op, v.ThirdOpenId, v.ThirdName, u.Id)
106
 	if err != nil {
106
 	if err != nil {
107
 		response.Fail(c, 101, response.TranslateMsg(c, "BindFail"))
107
 		response.Fail(c, 101, response.TranslateMsg(c, "BindFail"))
108
 		return
108
 		return

+ 38 - 0
http/controller/admin/user.go

@@ -5,6 +5,7 @@ import (
5
 	"Gwen/http/request/admin"
5
 	"Gwen/http/request/admin"
6
 	"Gwen/http/response"
6
 	"Gwen/http/response"
7
 	adResp "Gwen/http/response/admin"
7
 	adResp "Gwen/http/response/admin"
8
+	"Gwen/model"
8
 	"Gwen/service"
9
 	"Gwen/service"
9
 	"github.com/gin-gonic/gin"
10
 	"github.com/gin-gonic/gin"
10
 	"gorm.io/gorm"
11
 	"gorm.io/gorm"
@@ -327,3 +328,40 @@ func (ct *User) GroupUsers(c *gin.Context) {
327
 	}
328
 	}
328
 	response.Success(c, data)
329
 	response.Success(c, data)
329
 }
330
 }
331
+
332
+// Register
333
+func (ct *User) Register(c *gin.Context) {
334
+	if !global.Config.App.Register {
335
+		response.Fail(c, 101, response.TranslateMsg(c, "RegisterClosed"))
336
+		return
337
+	}
338
+	f := &admin.RegisterForm{}
339
+	if err := c.ShouldBindJSON(f); err != nil {
340
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
341
+		return
342
+	}
343
+	errList := global.Validator.ValidStruct(c, f)
344
+	if len(errList) > 0 {
345
+		response.Fail(c, 101, errList[0])
346
+		return
347
+	}
348
+	u := service.AllService.UserService.Register(f.Username, f.Password)
349
+	if u == nil || u.Id == 0 {
350
+		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed"))
351
+		return
352
+	}
353
+	// 注册成功后自动登录
354
+	ut := service.AllService.UserService.Login(u, &model.LoginLog{
355
+		UserId: u.Id,
356
+		Client: model.LoginLogClientWebAdmin,
357
+		Uuid:   "",
358
+		Ip:     c.ClientIP(),
359
+		Type:   model.LoginLogTypeAccount,
360
+	})
361
+	response.Success(c, &adResp.LoginPayload{
362
+		Token:      ut.Token,
363
+		Username:   u.Username,
364
+		RouteNames: service.AllService.UserService.RouteNames(u),
365
+		Nickname:   u.Nickname,
366
+	})
367
+}

+ 1 - 1
http/controller/api/login.go

@@ -81,7 +81,7 @@ func (l *Login) Login(c *gin.Context) {
81
 // @Produce  json
81
 // @Produce  json
82
 // @Success 200 {object} []string
82
 // @Success 200 {object} []string
83
 // @Failure 500 {object} response.ErrorResponse
83
 // @Failure 500 {object} response.ErrorResponse
84
-// @Router /login-options [post]
84
+// @Router /login-options [get]
85
 func (l *Login) LoginOptions(c *gin.Context) {
85
 func (l *Login) LoginOptions(c *gin.Context) {
86
 	oauthOks := []string{}
86
 	oauthOks := []string{}
87
 	err, _ := service.AllService.OauthService.GetOauthConfig(model.OauthTypeGithub)
87
 	err, _ := service.AllService.OauthService.GetOauthConfig(model.OauthTypeGithub)

+ 79 - 178
http/controller/api/ouath.go

@@ -32,6 +32,7 @@ func (o *Oauth) OidcAuth(c *gin.Context) {
32
 		response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
32
 		response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
33
 		return
33
 		return
34
 	}
34
 	}
35
+	//fmt.Println(f)
35
 	if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub && f.Op != model.OauthTypeOidc {
36
 	if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub && f.Op != model.OauthTypeOidc {
36
 		response.Error(c, response.TranslateMsg(c, "ParamsError"))
37
 		response.Error(c, response.TranslateMsg(c, "ParamsError"))
37
 		return
38
 		return
@@ -79,7 +80,7 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken)
79
 
80
 
80
 	// 如果 UserId 为 0,说明还在授权中
81
 	// 如果 UserId 为 0,说明还在授权中
81
 	if v.UserId == 0 {
82
 	if v.UserId == 0 {
82
-		c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress"})
83
+		c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress, please login and bind"})
83
 		return nil, nil
84
 		return nil, nil
84
 	}
85
 	}
85
 
86
 
@@ -123,6 +124,9 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken)
123
 // @Router /oidc/auth-query [get]
124
 // @Router /oidc/auth-query [get]
124
 func (o *Oauth) OidcAuthQuery(c *gin.Context) {
125
 func (o *Oauth) OidcAuthQuery(c *gin.Context) {
125
 	u, ut := o.OidcAuthQueryPre(c)
126
 	u, ut := o.OidcAuthQueryPre(c)
127
+	if u == nil || ut == nil {
128
+		return
129
+	}
126
 	c.JSON(http.StatusOK, apiResp.LoginRes{
130
 	c.JSON(http.StatusOK, apiResp.LoginRes{
127
 		AccessToken: ut.Token,
131
 		AccessToken: ut.Token,
128
 		Type:        "access_token",
132
 		Type:        "access_token",
@@ -157,7 +161,10 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
157
 	ty := v.Op
161
 	ty := v.Op
158
 	ac := v.Action
162
 	ac := v.Action
159
 	var u *model.User
163
 	var u *model.User
164
+	openid := ""
165
+	thirdName := ""
160
 	//fmt.Println("ty ac ", ty, ac)
166
 	//fmt.Println("ty ac ", ty, ac)
167
+
161
 	if ty == model.OauthTypeGithub {
168
 	if ty == model.OauthTypeGithub {
162
 		code := c.Query("code")
169
 		code := c.Query("code")
163
 		err, userData := service.AllService.OauthService.GithubCallback(code)
170
 		err, userData := service.AllService.OauthService.GithubCallback(code)
@@ -165,59 +172,8 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
165
 			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
172
 			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
166
 			return
173
 			return
167
 		}
174
 		}
168
-		if ac == service.OauthActionTypeBind {
169
-			//fmt.Println("bind", ty, userData)
170
-			utr := service.AllService.OauthService.UserThirdInfo(ty, strconv.Itoa(userData.Id))
171
-			if utr.UserId > 0 {
172
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
173
-				return
174
-			}
175
-			//绑定
176
-			u = service.AllService.UserService.InfoById(v.UserId)
177
-			if u == nil {
178
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
179
-				return
180
-			}
181
-			//绑定github
182
-			err = service.AllService.OauthService.BindGithubUser(strconv.Itoa(userData.Id), userData.Login, v.UserId)
183
-			if err != nil {
184
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
185
-				return
186
-			}
187
-			c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
188
-			return
189
-		} else if ac == service.OauthActionTypeLogin {
190
-			//登录
191
-			if v.UserId != 0 {
192
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
193
-				return
194
-			}
195
-			u = service.AllService.UserService.InfoByGithubId(strconv.Itoa(userData.Id))
196
-			if u == nil {
197
-				oa := service.AllService.OauthService.InfoByOp(ty)
198
-				if !*oa.AutoRegister {
199
-					//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
200
-					v.ThirdName = userData.Login
201
-					v.ThirdOpenId = strconv.Itoa(userData.Id)
202
-					url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
203
-					c.Redirect(http.StatusFound, url)
204
-					return
205
-				}
206
-
207
-				//自动注册
208
-				u = service.AllService.UserService.RegisterByGithub(userData.Login, strconv.Itoa(userData.Id))
209
-				if u.Id == 0 {
210
-					c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
211
-					return
212
-				}
213
-			}
214
-
215
-			// v.UserId = u.Id
216
-			// service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
217
-			// c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
218
-			// return
219
-		}
220
-
175
+		openid = strconv.Itoa(userData.Id)
176
+		thirdName = userData.Login
221
 	} else if ty == model.OauthTypeGoogle {
177
 	} else if ty == model.OauthTypeGoogle {
222
 		code := c.Query("code")
178
 		code := c.Query("code")
223
 		err, userData := service.AllService.OauthService.GoogleCallback(code)
179
 		err, userData := service.AllService.OauthService.GoogleCallback(code)
@@ -225,60 +181,9 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
225
 			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
181
 			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
226
 			return
182
 			return
227
 		}
183
 		}
184
+		openid = userData.Email
228
 		//将空格替换成_
185
 		//将空格替换成_
229
-		googleName := strings.Replace(userData.Name, " ", "_", -1)
230
-		if ac == service.OauthActionTypeBind {
231
-			//fmt.Println("bind", ty, userData)
232
-			utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Email)
233
-			if utr.UserId > 0 {
234
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
235
-				return
236
-			}
237
-			//绑定
238
-			u = service.AllService.UserService.InfoById(v.UserId)
239
-			if u == nil {
240
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
241
-				return
242
-			}
243
-			//绑定
244
-			err = service.AllService.OauthService.BindGoogleUser(userData.Email, googleName, v.UserId)
245
-			if err != nil {
246
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
247
-				return
248
-			}
249
-			c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
250
-			return
251
-		} else if ac == service.OauthActionTypeLogin {
252
-			if v.UserId != 0 {
253
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
254
-				return
255
-			}
256
-			u = service.AllService.UserService.InfoByGoogleEmail(userData.Email)
257
-			if u == nil {
258
-				oa := service.AllService.OauthService.InfoByOp(ty)
259
-				if !*oa.AutoRegister {
260
-					//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
261
-
262
-					v.ThirdName = googleName
263
-					v.ThirdOpenId = userData.Email
264
-					url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
265
-					c.Redirect(http.StatusFound, url)
266
-					return
267
-				}
268
-
269
-				//自动注册
270
-				u = service.AllService.UserService.RegisterByGoogle(googleName, userData.Email)
271
-				if u.Id == 0 {
272
-					c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
273
-					return
274
-				}
275
-			}
276
-
277
-			// v.UserId = u.Id
278
-			// service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
279
-			// c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
280
-			// return
281
-		}
186
+		thirdName = strings.Replace(userData.Name, " ", "_", -1)
282
 	} else if ty == model.OauthTypeOidc {
187
 	} else if ty == model.OauthTypeOidc {
283
 		code := c.Query("code")
188
 		code := c.Query("code")
284
 		err, userData := service.AllService.OauthService.OidcCallback(code)
189
 		err, userData := service.AllService.OauthService.OidcCallback(code)
@@ -286,85 +191,81 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
286
 			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
191
 			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
287
 			return
192
 			return
288
 		}
193
 		}
289
-		//将空格替换成_
290
-		// OidcName := strings.Replace(userData.Name, " ", "_", -1)
291
-		if ac == service.OauthActionTypeBind {
292
-			//fmt.Println("bind", ty, userData)
293
-			utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Sub)
294
-			if utr.UserId > 0 {
295
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
296
-				return
297
-			}
298
-			//绑定
299
-			u = service.AllService.UserService.InfoById(v.UserId)
300
-			if u == nil {
301
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
302
-				return
303
-			}
304
-			//绑定, user preffered_username as username
305
-			err = service.AllService.OauthService.BindOidcUser(userData.Sub, userData.PreferredUsername, v.UserId)
306
-			if err != nil {
307
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
308
-				return
309
-			}
310
-			c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
194
+		openid = userData.Sub
195
+		thirdName = userData.PreferredUsername
196
+	} else {
197
+		c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ParamsError"))
198
+		return
199
+	}
200
+	if ac == service.OauthActionTypeBind {
201
+
202
+		//fmt.Println("bind", ty, userData)
203
+		utr := service.AllService.OauthService.UserThirdInfo(ty, openid)
204
+		if utr.UserId > 0 {
205
+			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
311
 			return
206
 			return
312
-		} else if ac == service.OauthActionTypeLogin {
313
-			if v.UserId != 0 {
314
-				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
207
+		}
208
+		//绑定
209
+		u = service.AllService.UserService.InfoById(v.UserId)
210
+		if u == nil {
211
+			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
212
+			return
213
+		}
214
+		//绑定
215
+		err := service.AllService.OauthService.BindOauthUser(ty, openid, thirdName, v.UserId)
216
+		if err != nil {
217
+			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
218
+			return
219
+		}
220
+		c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
221
+		return
222
+
223
+	} else if ac == service.OauthActionTypeLogin {
224
+		//登录
225
+		if v.UserId != 0 {
226
+			c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
227
+			return
228
+		}
229
+		u = service.AllService.UserService.InfoByGithubId(openid)
230
+		if u == nil {
231
+			oa := service.AllService.OauthService.InfoByOp(ty)
232
+			if !*oa.AutoRegister {
233
+				//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
234
+				v.ThirdName = thirdName
235
+				v.ThirdOpenId = openid
236
+				url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
237
+				c.Redirect(http.StatusFound, url)
315
 				return
238
 				return
316
 			}
239
 			}
317
-			u = service.AllService.UserService.InfoByOidcSub(userData.Sub)
318
-			if u == nil {
319
-				oa := service.AllService.OauthService.InfoByOp(ty)
320
-				if !*oa.AutoRegister {
321
-					//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
322
-
323
-					v.ThirdName = userData.PreferredUsername
324
-					v.ThirdOpenId = userData.Sub
325
-					v.ThirdEmail = userData.Email
326
-					url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
327
-					c.Redirect(http.StatusFound, url)
328
-					return
329
-				}
330
 
240
 
331
-				//自动注册
332
-				u = service.AllService.UserService.RegisterByOidc(userData.PreferredUsername, userData.Sub)
333
-				if u.Id == 0 {
334
-					c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
335
-					return
336
-				}
241
+			//自动注册
242
+			u = service.AllService.UserService.RegisterByOauth(ty, thirdName, openid)
243
+			if u.Id == 0 {
244
+				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
245
+				return
337
 			}
246
 			}
338
-
339
-			// v.UserId = u.Id
340
-			// service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
341
-			// c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
342
-			// return
343
 		}
247
 		}
344
-	}
345
-	// 如果u为空,说明没有绑定用户
346
-	if u == nil {
347
-		c.String(http.StatusInternalServerError, response.TranslateMsg(c, "SystemError"))
248
+		v.UserId = u.Id
249
+		service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
250
+		// 如果是webadmin,登录成功后跳转到webadmin
251
+		if v.DeviceType == "webadmin" {
252
+			/*service.AllService.UserService.Login(u, &model.LoginLog{
253
+				UserId:   u.Id,
254
+				Client:   "webadmin",
255
+				Uuid:     "", //must be empty
256
+				Ip:       c.ClientIP(),
257
+				Type:     model.LoginLogTypeOauth,
258
+				Platform: v.DeviceOs,
259
+			})*/
260
+			url := global.Config.Rustdesk.ApiServer + "/_admin/#/"
261
+			c.Redirect(http.StatusFound, url)
262
+			return
263
+		}
264
+		c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
348
 		return
265
 		return
349
-	}
350
-	// 认证成功,设置缓存
351
-	v.UserId = u.Id
352
-	service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
353
-	// 如果是webadmin,登录成功后跳转到webadmin
354
-	if v.DeviceType == "webadmin" {
355
-		service.AllService.UserService.Login(u, &model.LoginLog{
356
-			UserId:   u.Id,
357
-			Client:   "webadmin",
358
-			Uuid:     "",//must be empty
359
-			Ip:       c.ClientIP(),
360
-			Type:     "account",
361
-			Platform: v.DeviceOs,
362
-		})
363
-		url := global.Config.Rustdesk.ApiServer + "/_admin/#/"
364
-		c.Redirect(http.StatusFound, url)
266
+	} else {
267
+		c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ParamsError"))
365
 		return
268
 		return
366
 	}
269
 	}
367
-	c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
368
-	return
369
 
270
 
370
 }
271
 }

+ 6 - 0
http/request/admin/user.go

@@ -59,3 +59,9 @@ type GroupUsersQuery struct {
59
 	IsMy   int  `json:"is_my"`
59
 	IsMy   int  `json:"is_my"`
60
 	UserId uint `json:"user_id"`
60
 	UserId uint `json:"user_id"`
61
 }
61
 }
62
+
63
+type RegisterForm struct {
64
+	Username        string `json:"username" validate:"required,gte=4,lte=10"`
65
+	Password        string `json:"password" validate:"required,gte=4,lte=20"`
66
+	ConfirmPassword string `json:"confirm_password" validate:"required,gte=4,lte=20"`
67
+}

+ 1 - 1
http/router/admin.go

@@ -17,7 +17,7 @@ func Init(g *gin.Engine) {
17
 
17
 
18
 	adg := g.Group("/api/admin")
18
 	adg := g.Group("/api/admin")
19
 	LoginBind(adg)
19
 	LoginBind(adg)
20
-
20
+	adg.POST("/user/register", (&admin.User{}).Register)
21
 	adg.Use(middleware.AdminAuth())
21
 	adg.Use(middleware.AdminAuth())
22
 	//FileBind(adg)
22
 	//FileBind(adg)
23
 	UserBind(adg)
23
 	UserBind(adg)

+ 6 - 0
model/loginLog.go

@@ -12,6 +12,12 @@ type LoginLog struct {
12
 	TimeModel
12
 	TimeModel
13
 }
13
 }
14
 
14
 
15
+const (
16
+	LoginLogClientWebAdmin = "webadmin"
17
+	LoginLogClientWeb      = "webclient"
18
+	LoginLogClientApp      = "app"
19
+)
20
+
15
 const (
21
 const (
16
 	LoginLogTypeAccount = "account"
22
 	LoginLogTypeAccount = "account"
17
 	LoginLogTypeOauth   = "oauth"
23
 	LoginLogTypeOauth   = "oauth"

+ 4 - 0
resources/i18n/en.toml

@@ -119,3 +119,7 @@ other = "Default Group"
119
 description = "Share group"
119
 description = "Share group"
120
 one = "Share Group"
120
 one = "Share Group"
121
 other = "Share Group"
121
 other = "Share Group"
122
+[RegisterClosed]
123
+description = "Register closed."
124
+one = "Register closed."
125
+other = "Register closed."

+ 5 - 0
resources/i18n/ko.toml

@@ -121,3 +121,8 @@ other = "기본 그룹"
121
 description = "Share group."
121
 description = "Share group."
122
 one = "공유 그룹"
122
 one = "공유 그룹"
123
 other = "공유 그룹"
123
 other = "공유 그룹"
124
+
125
+[RegisterClosed]
126
+description = "Register closed."
127
+one = "가입이 종료되었습니다."
128
+other = "가입이 종료되었습니다."

+ 5 - 0
resources/i18n/ru.toml

@@ -127,3 +127,8 @@ other = "Группа по умолчанию"
127
 description = "Share group."
127
 description = "Share group."
128
 one = "Общая группа"
128
 one = "Общая группа"
129
 other = "Общая группа"
129
 other = "Общая группа"
130
+
131
+[RegisterClosed]
132
+description = "Register closed."
133
+one = "Регистрация закрыта."
134
+other = "Регистрация закрыта."

+ 4 - 0
resources/i18n/zh_CN.toml

@@ -121,3 +121,7 @@ other = "默认组"
121
 description = "Share group."
121
 description = "Share group."
122
 one = "共享组"
122
 one = "共享组"
123
 other = "共享组"
123
 other = "共享组"
124
+[RegisterClosed]
125
+description = "Register closed."
126
+one = "注册已关闭。"
127
+other = "注册已关闭。"

+ 22 - 22
service/oauth.go

@@ -15,9 +15,9 @@ import (
15
 	"net/http"
15
 	"net/http"
16
 	"net/url"
16
 	"net/url"
17
 	"strconv"
17
 	"strconv"
18
+	"strings"
18
 	"sync"
19
 	"sync"
19
 	"time"
20
 	"time"
20
-	"strings"
21
 )
21
 )
22
 
22
 
23
 // Define a struct to parse the .well-known/openid-configuration response
23
 // Define a struct to parse the .well-known/openid-configuration response
@@ -88,10 +88,10 @@ type GoogleUserdata struct {
88
 	VerifiedEmail bool   `json:"verified_email"`
88
 	VerifiedEmail bool   `json:"verified_email"`
89
 }
89
 }
90
 type OidcUserdata struct {
90
 type OidcUserdata struct {
91
-	Sub			  string `json:"sub"`
92
-	Email         string `json:"email"`
93
-	VerifiedEmail bool   `json:"email_verified"`
94
-	Name          string `json:"name"`
91
+	Sub               string `json:"sub"`
92
+	Email             string `json:"email"`
93
+	VerifiedEmail     bool   `json:"email_verified"`
94
+	Name              string `json:"name"`
95
 	PreferredUsername string `json:"preferred_username"`
95
 	PreferredUsername string `json:"preferred_username"`
96
 }
96
 }
97
 
97
 
@@ -156,27 +156,27 @@ func (os *OauthService) BeginAuth(op string) (error error, code, url string) {
156
 
156
 
157
 // Method to fetch OIDC configuration dynamically
157
 // Method to fetch OIDC configuration dynamically
158
 func FetchOidcConfig(issuer string) (error, OidcEndpoint) {
158
 func FetchOidcConfig(issuer string) (error, OidcEndpoint) {
159
-    configURL := strings.TrimSuffix(issuer, "/") + "/.well-known/openid-configuration"
159
+	configURL := strings.TrimSuffix(issuer, "/") + "/.well-known/openid-configuration"
160
 
160
 
161
-    // Get the HTTP client (with or without proxy based on configuration)
162
-    client := getHTTPClientWithProxy()
161
+	// Get the HTTP client (with or without proxy based on configuration)
162
+	client := getHTTPClientWithProxy()
163
 
163
 
164
-    resp, err := client.Get(configURL)
165
-    if err != nil {
166
-        return errors.New("failed to fetch OIDC configuration"), OidcEndpoint{}
167
-    }
168
-    defer resp.Body.Close()
164
+	resp, err := client.Get(configURL)
165
+	if err != nil {
166
+		return errors.New("failed to fetch OIDC configuration"), OidcEndpoint{}
167
+	}
168
+	defer resp.Body.Close()
169
 
169
 
170
-    if resp.StatusCode != http.StatusOK {
171
-        return errors.New("OIDC configuration not found, status code: %d"), OidcEndpoint{}
172
-    }
170
+	if resp.StatusCode != http.StatusOK {
171
+		return errors.New("OIDC configuration not found, status code: %d"), OidcEndpoint{}
172
+	}
173
 
173
 
174
-    var endpoint OidcEndpoint
175
-    if err := json.NewDecoder(resp.Body).Decode(&endpoint); err != nil {
176
-        return errors.New("failed to parse OIDC configuration"), OidcEndpoint{}
177
-    }
174
+	var endpoint OidcEndpoint
175
+	if err := json.NewDecoder(resp.Body).Decode(&endpoint); err != nil {
176
+		return errors.New("failed to parse OIDC configuration"), OidcEndpoint{}
177
+	}
178
 
178
 
179
-    return nil, endpoint
179
+	return nil, endpoint
180
 }
180
 }
181
 
181
 
182
 // GetOauthConfig retrieves the OAuth2 configuration based on the provider type
182
 // GetOauthConfig retrieves the OAuth2 configuration based on the provider type
@@ -253,6 +253,7 @@ func (os *OauthService) getOidcConfig() (error, *oauth2.Config) {
253
 }
253
 }
254
 
254
 
255
 func getHTTPClientWithProxy() *http.Client {
255
 func getHTTPClientWithProxy() *http.Client {
256
+	//todo add timeout
256
 	if global.Config.Proxy.Enable {
257
 	if global.Config.Proxy.Enable {
257
 		if global.Config.Proxy.Host == "" {
258
 		if global.Config.Proxy.Host == "" {
258
 			global.Logger.Warn("Proxy is enabled but proxy host is empty.")
259
 			global.Logger.Warn("Proxy is enabled but proxy host is empty.")
@@ -446,7 +447,6 @@ func (os *OauthService) DeleteUserByUserId(userid uint) error {
446
 	return global.DB.Where("user_id = ?", userid).Delete(&model.UserThird{}).Error
447
 	return global.DB.Where("user_id = ?", userid).Delete(&model.UserThird{}).Error
447
 }
448
 }
448
 
449
 
449
-
450
 // InfoById 根据id取用户信息
450
 // InfoById 根据id取用户信息
451
 func (os *OauthService) InfoById(id uint) *model.Oauth {
451
 func (os *OauthService) InfoById(id uint) *model.Oauth {
452
 	u := &model.Oauth{}
452
 	u := &model.Oauth{}

+ 39 - 11
service/user.go

@@ -151,15 +151,34 @@ func (us *UserService) Logout(u *model.User, token string) error {
151
 
151
 
152
 // Delete 删除用户和oauth信息
152
 // Delete 删除用户和oauth信息
153
 func (us *UserService) Delete(u *model.User) error {
153
 func (us *UserService) Delete(u *model.User) error {
154
-    // 删除用户
155
-    if err := global.DB.Delete(u).Error; err != nil {
156
-        return err
157
-    }
158
-    // 删除关联的 OAuth 信息
159
-    if err := AllService.OauthService.DeleteUserByUserId(u.Id); err != nil {
160
-        return err
161
-    }
162
-    return nil
154
+	tx := global.DB.Begin()
155
+	// 删除用户
156
+	if err := tx.Delete(u).Error; err != nil {
157
+		tx.Rollback()
158
+		return err
159
+	}
160
+	// 删除关联的 OAuth 信息
161
+	if err := tx.Where("user_id = ?", u.Id).Delete(&model.UserThird{}).Error; err != nil {
162
+		tx.Rollback()
163
+		return err
164
+	}
165
+	//  删除关联的ab
166
+	if err := tx.Where("user_id = ?", u.Id).Delete(&model.AddressBook{}).Error; err != nil {
167
+		tx.Rollback()
168
+		return err
169
+	}
170
+	//  删除关联的abc
171
+	if err := tx.Where("user_id = ?", u.Id).Delete(&model.AddressBookCollection{}).Error; err != nil {
172
+		tx.Rollback()
173
+		return err
174
+	}
175
+	//  删除关联的abcr
176
+	if err := tx.Where("user_id = ?", u.Id).Delete(&model.AddressBookCollectionRule{}).Error; err != nil {
177
+		tx.Rollback()
178
+		return err
179
+	}
180
+	tx.Commit()
181
+	return nil
163
 }
182
 }
164
 
183
 
165
 // Update 更新
184
 // Update 更新
@@ -262,14 +281,14 @@ func (us *UserService) RegisterByOauth(thirdType, thirdName, uid string) *model.
262
 		Username: username,
281
 		Username: username,
263
 		GroupId:  1,
282
 		GroupId:  1,
264
 	}
283
 	}
265
-	global.DB.Create(u)
284
+	tx.Create(u)
266
 	if u.Id == 0 {
285
 	if u.Id == 0 {
267
 		tx.Rollback()
286
 		tx.Rollback()
268
 		return u
287
 		return u
269
 	}
288
 	}
270
 
289
 
271
 	ut.UserId = u.Id
290
 	ut.UserId = u.Id
272
-	global.DB.Create(ut)
291
+	tx.Create(ut)
273
 
292
 
274
 	tx.Commit()
293
 	tx.Commit()
275
 	return u
294
 	return u
@@ -328,3 +347,12 @@ func (us *UserService) IsPasswordEmptyByUser(u *model.User) bool {
328
 	return us.IsPasswordEmptyById(u.Id)
347
 	return us.IsPasswordEmptyById(u.Id)
329
 }
348
 }
330
 
349
 
350
+func (us *UserService) Register(username string, password string) *model.User {
351
+	u := &model.User{
352
+		Username: username,
353
+		Password: us.EncryptPassword(password),
354
+		GroupId:  1,
355
+	}
356
+	global.DB.Create(u)
357
+	return u
358
+}