From eada37678313ce1794925fbfcfa3bb1c28990739 Mon Sep 17 00:00:00 2001 From: ljw <84855512@qq.com> Date: Wed, 30 Oct 2024 15:34:45 +0800 Subject: [PATCH 1/8] add docker-compose-dev.yaml --- docker-compose-dev.yaml | 20 ++++++++++++++++++++ docker-compose.yaml | 9 +++------ 2 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 docker-compose-dev.yaml diff --git a/docker-compose-dev.yaml b/docker-compose-dev.yaml new file mode 100644 index 0000000..d015bc1 --- /dev/null +++ b/docker-compose-dev.yaml @@ -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 \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index d015bc1..75f3a47 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,9 +1,6 @@ services: rustdesk-api: - build: - context: . - dockerfile: Dockerfile.dev - # image: lejianwen/rustdesk-api + image: lejianwen/rustdesk-api container_name: rustdesk-api environment: - TZ=Asia/Shanghai @@ -14,7 +11,7 @@ services: ports: - 21114:21114 volumes: - - ./data/rustdesk/api:/app/data #将数据库挂载出来方便备份 - - ./conf:/app/conf # config + - ./data/rustdesk/api:/app/data # database + # - ./conf:/app/conf # config # - ./resources:/app/resources # 静态资源 restart: unless-stopped \ No newline at end of file From 0ddfbdbd23e0fde0f045814b248a0c52da99b844 Mon Sep 17 00:00:00 2001 From: ljw <84855512@qq.com> Date: Wed, 30 Oct 2024 15:46:12 +0800 Subject: [PATCH 2/8] up v --- cmd/apimain.go | 2 +- docs/admin/admin_docs.go | 15 +++++++++++++ docs/admin/admin_swagger.json | 15 +++++++++++++ docs/admin/admin_swagger.yaml | 10 +++++++++ docs/api/api_docs.go | 2 +- docs/api/api_swagger.json | 2 +- docs/api/api_swagger.yaml | 2 +- http/controller/api/login.go | 2 +- service/oauth.go | 42 +++++++++++++++++------------------ 9 files changed, 66 insertions(+), 26 deletions(-) diff --git a/cmd/apimain.go b/cmd/apimain.go index ae66c10..2589964 100644 --- a/cmd/apimain.go +++ b/cmd/apimain.go @@ -101,7 +101,7 @@ func main() { } func DatabaseAutoUpdate() { - version := 242 + version := 243 db := global.DB diff --git a/docs/admin/admin_docs.go b/docs/admin/admin_docs.go index f4547ab..684818c 100644 --- a/docs/admin/admin_docs.go +++ b/docs/admin/admin_docs.go @@ -3164,11 +3164,17 @@ const docTemplateadmin = `{ "id": { "type": "integer" }, + "issuer": { + "type": "string" + }, "op": { "type": "string" }, "redirect_url": { "type": "string" + }, + "scopes": { + "type": "string" } } }, @@ -3749,12 +3755,18 @@ const docTemplateadmin = `{ "id": { "type": "integer" }, + "issuer": { + "type": "string" + }, "op": { "type": "string" }, "redirect_url": { "type": "string" }, + "scopes": { + "type": "string" + }, "updated_at": { "type": "string" } @@ -3795,6 +3807,9 @@ const docTemplateadmin = `{ "id": { "type": "string" }, + "last_online_ip": { + "type": "string" + }, "last_online_time": { "type": "integer" }, diff --git a/docs/admin/admin_swagger.json b/docs/admin/admin_swagger.json index 7e871e7..27961d3 100644 --- a/docs/admin/admin_swagger.json +++ b/docs/admin/admin_swagger.json @@ -3157,11 +3157,17 @@ "id": { "type": "integer" }, + "issuer": { + "type": "string" + }, "op": { "type": "string" }, "redirect_url": { "type": "string" + }, + "scopes": { + "type": "string" } } }, @@ -3742,12 +3748,18 @@ "id": { "type": "integer" }, + "issuer": { + "type": "string" + }, "op": { "type": "string" }, "redirect_url": { "type": "string" }, + "scopes": { + "type": "string" + }, "updated_at": { "type": "string" } @@ -3788,6 +3800,9 @@ "id": { "type": "string" }, + "last_online_ip": { + "type": "string" + }, "last_online_time": { "type": "integer" }, diff --git a/docs/admin/admin_swagger.yaml b/docs/admin/admin_swagger.yaml index ea9d4f9..1d6aeb2 100644 --- a/docs/admin/admin_swagger.yaml +++ b/docs/admin/admin_swagger.yaml @@ -105,10 +105,14 @@ definitions: type: string id: type: integer + issuer: + type: string op: type: string redirect_url: type: string + scopes: + type: string required: - client_id - client_secret @@ -500,10 +504,14 @@ definitions: type: string id: type: integer + issuer: + type: string op: type: string redirect_url: type: string + scopes: + type: string updated_at: type: string type: object @@ -530,6 +538,8 @@ definitions: type: string id: type: string + last_online_ip: + type: string last_online_time: type: integer memory: diff --git a/docs/api/api_docs.go b/docs/api/api_docs.go index b2fd617..5f3e535 100644 --- a/docs/api/api_docs.go +++ b/docs/api/api_docs.go @@ -834,7 +834,7 @@ const docTemplateapi = `{ } }, "/login-options": { - "post": { + "get": { "description": "登录选项", "consumes": [ "application/json" diff --git a/docs/api/api_swagger.json b/docs/api/api_swagger.json index 4a4ccc5..75feb4e 100644 --- a/docs/api/api_swagger.json +++ b/docs/api/api_swagger.json @@ -827,7 +827,7 @@ } }, "/login-options": { - "post": { + "get": { "description": "登录选项", "consumes": [ "application/json" diff --git a/docs/api/api_swagger.yaml b/docs/api/api_swagger.yaml index 2bd93b4..49c1c70 100644 --- a/docs/api/api_swagger.yaml +++ b/docs/api/api_swagger.yaml @@ -715,7 +715,7 @@ paths: tags: - 登录 /login-options: - post: + get: consumes: - application/json description: 登录选项 diff --git a/http/controller/api/login.go b/http/controller/api/login.go index bae13e1..703d792 100644 --- a/http/controller/api/login.go +++ b/http/controller/api/login.go @@ -81,7 +81,7 @@ func (l *Login) Login(c *gin.Context) { // @Produce json // @Success 200 {object} []string // @Failure 500 {object} response.ErrorResponse -// @Router /login-options [post] +// @Router /login-options [get] func (l *Login) LoginOptions(c *gin.Context) { oauthOks := []string{} err, _ := service.AllService.OauthService.GetOauthConfig(model.OauthTypeGithub) diff --git a/service/oauth.go b/service/oauth.go index ea97608..17a3120 100644 --- a/service/oauth.go +++ b/service/oauth.go @@ -15,9 +15,9 @@ import ( "net/http" "net/url" "strconv" + "strings" "sync" "time" - "strings" ) // Define a struct to parse the .well-known/openid-configuration response @@ -88,10 +88,10 @@ type GoogleUserdata struct { VerifiedEmail bool `json:"verified_email"` } type OidcUserdata struct { - Sub string `json:"sub"` - Email string `json:"email"` - VerifiedEmail bool `json:"email_verified"` - Name string `json:"name"` + Sub string `json:"sub"` + Email string `json:"email"` + VerifiedEmail bool `json:"email_verified"` + Name string `json:"name"` 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 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) - client := getHTTPClientWithProxy() + // Get the HTTP client (with or without proxy based on configuration) + client := getHTTPClientWithProxy() - resp, err := client.Get(configURL) - if err != nil { - return errors.New("failed to fetch OIDC configuration"), OidcEndpoint{} - } - defer resp.Body.Close() + resp, err := client.Get(configURL) + if err != nil { + return errors.New("failed to fetch OIDC configuration"), OidcEndpoint{} + } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return errors.New("OIDC configuration not found, status code: %d"), OidcEndpoint{} - } + if resp.StatusCode != http.StatusOK { + return errors.New("OIDC configuration not found, status code: %d"), OidcEndpoint{} + } - var endpoint OidcEndpoint - if err := json.NewDecoder(resp.Body).Decode(&endpoint); err != nil { - return errors.New("failed to parse OIDC configuration"), OidcEndpoint{} - } + var endpoint OidcEndpoint + if err := json.NewDecoder(resp.Body).Decode(&endpoint); err != nil { + 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 From b3edc9d11206eafe83a2adac996694481a4c7f7f Mon Sep 17 00:00:00 2001 From: ljw <84855512@qq.com> Date: Wed, 30 Oct 2024 19:34:56 +0800 Subject: [PATCH 3/8] up del user --- service/user.go | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/service/user.go b/service/user.go index 6bb431f..59461bb 100644 --- a/service/user.go +++ b/service/user.go @@ -151,15 +151,34 @@ func (us *UserService) Logout(u *model.User, token string) error { // Delete 删除用户和oauth信息 func (us *UserService) Delete(u *model.User) error { - // 删除用户 - if err := global.DB.Delete(u).Error; err != nil { - return err - } - // 删除关联的 OAuth 信息 - if err := AllService.OauthService.DeleteUserByUserId(u.Id); err != nil { - return err - } - return nil + tx := global.DB.Begin() + // 删除用户 + if err := tx.Delete(u).Error; err != nil { + tx.Rollback() + return err + } + // 删除关联的 OAuth 信息 + if err := tx.Where("user_id = ?", u.Id).Delete(&model.UserThird{}).Error; err != 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 更新 @@ -262,14 +281,14 @@ func (us *UserService) RegisterByOauth(thirdType, thirdName, uid string) *model. Username: username, GroupId: 1, } - global.DB.Create(u) + tx.Create(u) if u.Id == 0 { tx.Rollback() return u } ut.UserId = u.Id - global.DB.Create(ut) + tx.Create(ut) tx.Commit() return u From e1424bcea7cb22f6ebf4fa568717d6ee9f6b1aee Mon Sep 17 00:00:00 2001 From: ljw <84855512@qq.com> Date: Wed, 30 Oct 2024 20:59:51 +0800 Subject: [PATCH 4/8] fix buidconfirm --- http/controller/admin/oauth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http/controller/admin/oauth.go b/http/controller/admin/oauth.go index fec011d..3444f3e 100644 --- a/http/controller/admin/oauth.go +++ b/http/controller/admin/oauth.go @@ -102,7 +102,7 @@ func (o *Oauth) BindConfirm(c *gin.Context) { return } 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 { response.Fail(c, 101, response.TranslateMsg(c, "BindFail")) return From 0ed40318cb7a151549117bc9cb271dc4ed4dabef Mon Sep 17 00:00:00 2001 From: ljw <84855512@qq.com> Date: Thu, 31 Oct 2024 14:03:48 +0800 Subject: [PATCH 5/8] up oauth --- docs/admin/admin_docs.go | 97 ++++++++++++ docs/admin/admin_swagger.json | 97 ++++++++++++ docs/admin/admin_swagger.yaml | 61 ++++++++ http/controller/admin/login.go | 36 ++--- http/controller/api/ouath.go | 259 ++++++++++----------------------- service/oauth.go | 2 +- 6 files changed, 355 insertions(+), 197 deletions(-) diff --git a/docs/admin/admin_docs.go b/docs/admin/admin_docs.go index 684818c..8fb653e 100644 --- a/docs/admin/admin_docs.go +++ b/docs/admin/admin_docs.go @@ -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": { "post": { "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": { "post": { "security": [ @@ -3979,6 +4068,14 @@ const docTemplateadmin = `{ } } }, + "response.ErrorResponse": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + } + }, "response.Response": { "type": "object", "properties": { diff --git a/docs/admin/admin_swagger.json b/docs/admin/admin_swagger.json index 27961d3..f41ba63 100644 --- a/docs/admin/admin_swagger.json +++ b/docs/admin/admin_swagger.json @@ -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": { "post": { "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": { "post": { "security": [ @@ -3972,6 +4061,14 @@ } } }, + "response.ErrorResponse": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + } + }, "response.Response": { "type": "object", "properties": { diff --git a/docs/admin/admin_swagger.yaml b/docs/admin/admin_swagger.yaml index 1d6aeb2..1008a77 100644 --- a/docs/admin/admin_swagger.yaml +++ b/docs/admin/admin_swagger.yaml @@ -653,6 +653,11 @@ definitions: total: type: integer type: object + response.ErrorResponse: + properties: + error: + type: string + type: object response.Response: properties: code: @@ -1520,6 +1525,27 @@ paths: summary: 登录 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: post: consumes: @@ -1799,6 +1825,41 @@ paths: summary: Oauth编辑 tags: - 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: post: consumes: diff --git a/http/controller/admin/login.go b/http/controller/admin/login.go index 21f432c..3d6ea12 100644 --- a/http/controller/admin/login.go +++ b/http/controller/admin/login.go @@ -2,15 +2,16 @@ package admin import ( "Gwen/global" + "Gwen/http/controller/api" "Gwen/http/request/admin" + apiReq "Gwen/http/request/api" "Gwen/http/response" adResp "Gwen/http/response/admin" - apiReq "Gwen/http/request/api" - "Gwen/http/controller/api" "Gwen/model" "Gwen/service" "fmt" "github.com/gin-gonic/gin" + "gorm.io/gorm" ) type Login struct { @@ -85,7 +86,6 @@ func (ct *Login) Logout(c *gin.Context) { response.Success(c, nil) } - // LoginOptions // @Tags 登录 // @Summary 登录选项 @@ -95,13 +95,17 @@ func (ct *Login) Logout(c *gin.Context) { // @Success 200 {object} []string // @Failure 500 {object} response.ErrorResponse // @Router /admin/login-options [post] -// 直接调用/api/login的LoginOptions方法 func (ct *Login) LoginOptions(c *gin.Context) { - l := &api.Login{} - l.LoginOptions(c) + res := service.AllService.OauthService.List(1, 100, func(tx *gorm.DB) { + tx.Select("op").Order("id") + }) + var ops []string + for _, v := range res.Oauths { + ops = append(ops, v.Op) + } + response.Success(c, ops) } - // OidcAuth // @Tags Oauth // @Summary OidcAuth @@ -126,13 +130,13 @@ func (ct *Login) OidcAuth(c *gin.Context) { } service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{ - Action: service.OauthActionTypeLogin, - Op: f.Op, - Id: f.Id, + Action: service.OauthActionTypeLogin, + Op: f.Op, + Id: f.Id, DeviceType: "webadmin", // DeviceOs: ct.Platform(c), - DeviceOs: f.DeviceInfo.Os, - Uuid: f.Uuid, + DeviceOs: f.DeviceInfo.Os, + Uuid: f.Uuid, }, 5*60) response.Success(c, gin.H{ @@ -141,8 +145,6 @@ func (ct *Login) OidcAuth(c *gin.Context) { }) } - - // OidcAuthQuery // @Tags Oauth // @Summary OidcAuthQuery @@ -158,12 +160,12 @@ func (ct *Login) OidcAuthQuery(c *gin.Context) { if ut == nil { return } - fmt.Println("u:", u) - fmt.Println("ut:", ut) + //fmt.Println("u:", u) + //fmt.Println("ut:", ut) response.Success(c, &adResp.LoginPayload{ Token: ut.Token, Username: u.Username, RouteNames: service.AllService.UserService.RouteNames(u), Nickname: u.Nickname, }) -} \ No newline at end of file +} diff --git a/http/controller/api/ouath.go b/http/controller/api/ouath.go index 4ad15db..96f7a80 100644 --- a/http/controller/api/ouath.go +++ b/http/controller/api/ouath.go @@ -32,6 +32,7 @@ func (o *Oauth) OidcAuth(c *gin.Context) { response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error()) return } + //fmt.Println(f) if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub && f.Op != model.OauthTypeOidc { response.Error(c, response.TranslateMsg(c, "ParamsError")) return @@ -79,7 +80,7 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken) // 如果 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 } @@ -123,6 +124,9 @@ func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken) // @Router /oidc/auth-query [get] func (o *Oauth) OidcAuthQuery(c *gin.Context) { u, ut := o.OidcAuthQueryPre(c) + if u == nil || ut == nil { + return + } c.JSON(http.StatusOK, apiResp.LoginRes{ AccessToken: ut.Token, Type: "access_token", @@ -157,7 +161,10 @@ func (o *Oauth) OauthCallback(c *gin.Context) { ty := v.Op ac := v.Action var u *model.User + openid := "" + thirdName := "" //fmt.Println("ty ac ", ty, ac) + if ty == model.OauthTypeGithub { code := c.Query("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())) return } - if ac == service.OauthActionTypeBind { - //fmt.Println("bind", ty, userData) - 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 - } - + openid = strconv.Itoa(userData.Id) + thirdName = userData.Login } else if ty == model.OauthTypeGoogle { code := c.Query("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())) return } + openid = userData.Email //将空格替换成_ - googleName := 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 - } + thirdName = strings.Replace(userData.Name, " ", "_", -1) } else if ty == model.OauthTypeOidc { code := c.Query("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())) return } - //将空格替换成_ - // OidcName := strings.Replace(userData.Name, " ", "_", -1) - if ac == service.OauthActionTypeBind { - //fmt.Println("bind", ty, userData) - utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Sub) - 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 - } - //绑定, 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")) + openid = userData.Sub + thirdName = userData.PreferredUsername + } else { + c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ParamsError")) + return + } + if ac == service.OauthActionTypeBind { + + //fmt.Println("bind", ty, userData) + utr := service.AllService.OauthService.UserThirdInfo(ty, openid) + if utr.UserId > 0 { + c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser")) 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 } - 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 - v.ThirdEmail = userData.Email - url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey - c.Redirect(http.StatusFound, url) - return - } - - //自动注册 - u = service.AllService.UserService.RegisterByOidc(userData.PreferredUsername, userData.Sub) - if u.Id == 0 { - c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed")) - return - } + //自动注册 + u = service.AllService.UserService.RegisterByOauth(ty, thirdName, openid) + 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 } - } - // 如果u为空,说明没有绑定用户 - if u == nil { - c.String(http.StatusInternalServerError, response.TranslateMsg(c, "SystemError")) + 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: 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 } - // 认证成功,设置缓存 - 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 } diff --git a/service/oauth.go b/service/oauth.go index e9f4fe7..2880fef 100644 --- a/service/oauth.go +++ b/service/oauth.go @@ -253,6 +253,7 @@ func (os *OauthService) getOidcConfig() (error, *oauth2.Config) { } func getHTTPClientWithProxy() *http.Client { + //todo add timeout if global.Config.Proxy.Enable { if global.Config.Proxy.Host == "" { 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 } - // InfoById 根据id取用户信息 func (os *OauthService) InfoById(id uint) *model.Oauth { u := &model.Oauth{} From e2fda47cbb2fdd4f145d614ee020d6ff291f8c68 Mon Sep 17 00:00:00 2001 From: ljw <84855512@qq.com> Date: Thu, 31 Oct 2024 15:14:30 +0800 Subject: [PATCH 6/8] add register --- conf/config.yaml | 1 + config/config.go | 3 ++- http/controller/admin/login.go | 5 ++++- http/controller/admin/user.go | 38 ++++++++++++++++++++++++++++++++++ http/request/admin/user.go | 6 ++++++ http/router/admin.go | 2 +- model/loginLog.go | 6 ++++++ resources/i18n/en.toml | 4 ++++ resources/i18n/ko.toml | 5 +++++ resources/i18n/ru.toml | 5 +++++ resources/i18n/zh_CN.toml | 4 ++++ service/user.go | 10 +++++++++ 12 files changed, 86 insertions(+), 3 deletions(-) diff --git a/conf/config.yaml b/conf/config.yaml index 01a733b..4e67e3d 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -1,6 +1,7 @@ lang: "zh-CN" app: web-client: 1 # 1:启用 0:禁用 + register: false #是否开启注册 gin: api-addr: "0.0.0.0:21114" mode: "release" #release,debug,test diff --git a/config/config.go b/config/config.go index 86d5d4b..085809e 100644 --- a/config/config.go +++ b/config/config.go @@ -15,7 +15,8 @@ const ( ) type App struct { - WebClient int `mapstructure:"web-client"` + WebClient int `mapstructure:"web-client"` + Register bool `mapstructure:"register"` } type Config struct { diff --git a/http/controller/admin/login.go b/http/controller/admin/login.go index 3d6ea12..ffc5ad9 100644 --- a/http/controller/admin/login.go +++ b/http/controller/admin/login.go @@ -103,7 +103,10 @@ func (ct *Login) LoginOptions(c *gin.Context) { for _, v := range res.Oauths { ops = append(ops, v.Op) } - response.Success(c, ops) + response.Success(c, gin.H{ + "ops": ops, + "register": global.Config.App.Register, + }) } // OidcAuth diff --git a/http/controller/admin/user.go b/http/controller/admin/user.go index 9f7415c..61eca66 100644 --- a/http/controller/admin/user.go +++ b/http/controller/admin/user.go @@ -5,6 +5,7 @@ import ( "Gwen/http/request/admin" "Gwen/http/response" adResp "Gwen/http/response/admin" + "Gwen/model" "Gwen/service" "github.com/gin-gonic/gin" "gorm.io/gorm" @@ -323,3 +324,40 @@ func (ct *User) GroupUsers(c *gin.Context) { } 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, + }) +} diff --git a/http/request/admin/user.go b/http/request/admin/user.go index b1b1719..e29133c 100644 --- a/http/request/admin/user.go +++ b/http/request/admin/user.go @@ -59,3 +59,9 @@ type GroupUsersQuery struct { IsMy int `json:"is_my"` 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"` +} diff --git a/http/router/admin.go b/http/router/admin.go index 2026cc6..89d76cf 100644 --- a/http/router/admin.go +++ b/http/router/admin.go @@ -17,7 +17,7 @@ func Init(g *gin.Engine) { adg := g.Group("/api/admin") LoginBind(adg) - + adg.POST("/user/register", (&admin.User{}).Register) adg.Use(middleware.AdminAuth()) //FileBind(adg) UserBind(adg) diff --git a/model/loginLog.go b/model/loginLog.go index 8405c2f..080e1eb 100644 --- a/model/loginLog.go +++ b/model/loginLog.go @@ -12,6 +12,12 @@ type LoginLog struct { TimeModel } +const ( + LoginLogClientWebAdmin = "webadmin" + LoginLogClientWeb = "webclient" + LoginLogClientApp = "app" +) + const ( LoginLogTypeAccount = "account" LoginLogTypeOauth = "oauth" diff --git a/resources/i18n/en.toml b/resources/i18n/en.toml index 6a66250..24e339a 100644 --- a/resources/i18n/en.toml +++ b/resources/i18n/en.toml @@ -119,3 +119,7 @@ other = "Default Group" description = "Share group" one = "Share Group" other = "Share Group" +[RegisterClosed] +description = "Register closed." +one = "Register closed." +other = "Register closed." diff --git a/resources/i18n/ko.toml b/resources/i18n/ko.toml index 2c8eeda..393fc49 100644 --- a/resources/i18n/ko.toml +++ b/resources/i18n/ko.toml @@ -121,3 +121,8 @@ other = "기본 그룹" description = "Share group." one = "공유 그룹" other = "공유 그룹" + +[RegisterClosed] +description = "Register closed." +one = "가입이 종료되었습니다." +other = "가입이 종료되었습니다." \ No newline at end of file diff --git a/resources/i18n/ru.toml b/resources/i18n/ru.toml index fc0b430..885401a 100644 --- a/resources/i18n/ru.toml +++ b/resources/i18n/ru.toml @@ -127,3 +127,8 @@ other = "Группа по умолчанию" description = "Share group." one = "Общая группа" other = "Общая группа" + +[RegisterClosed] +description = "Register closed." +one = "Регистрация закрыта." +other = "Регистрация закрыта." \ No newline at end of file diff --git a/resources/i18n/zh_CN.toml b/resources/i18n/zh_CN.toml index 46b84e5..1e2f0ad 100644 --- a/resources/i18n/zh_CN.toml +++ b/resources/i18n/zh_CN.toml @@ -121,3 +121,7 @@ other = "默认组" description = "Share group." one = "共享组" other = "共享组" +[RegisterClosed] +description = "Register closed." +one = "注册已关闭。" +other = "注册已关闭。" \ No newline at end of file diff --git a/service/user.go b/service/user.go index 59461bb..e586bfc 100644 --- a/service/user.go +++ b/service/user.go @@ -323,3 +323,13 @@ func (us *UserService) FindLatestUserIdFromLoginLogByUuid(uuid string) uint { global.DB.Where("uuid = ?", uuid).Order("id desc").First(llog) return llog.UserId } + +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 +} From 7cb838693aa0f017303d98780e6be6f3c2020217 Mon Sep 17 00:00:00 2001 From: ljw <84855512@qq.com> Date: Thu, 31 Oct 2024 15:47:39 +0800 Subject: [PATCH 7/8] up readme #28 --- README.md | 1 + README_EN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index cec6cba..b3272c9 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,7 @@ proxy: | TZ | 时区 | Asia/Shanghai | | RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` | | RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 | +| RUSTDESK_API_APP_REGISTER | 是否开启注册; `true`, `false` 默认`false` | `false` | | -----GIN配置----- | ---------- | ---------- | | RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表,以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 | | -----------GORM配置---------------- | ------------------------------------ | --------------------------- | diff --git a/README_EN.md b/README_EN.md index 35d116e..c1b9185 100644 --- a/README_EN.md +++ b/README_EN.md @@ -202,6 +202,7 @@ The prefix for variable names is `RUSTDESK_API`. If environment variables exist, | TZ | timezone | Asia/Shanghai | | 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_REGISTER | register enable; `true`, `false`; default:`false` | `false` | | ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- | | RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 | | ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- | From efead3f9c75409a46606795a2481582d13b0f3db Mon Sep 17 00:00:00 2001 From: ljw <84855512@qq.com> Date: Thu, 31 Oct 2024 15:48:36 +0800 Subject: [PATCH 8/8] up readme #28 --- README.md | 1 + README_EN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index b3272c9..808a48f 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,7 @@ lang: "en" app: web-client: 1 # 1:启用 0:禁用 + register: false #是否开启注册 gin: api-addr: "0.0.0.0:21114" mode: "release" diff --git a/README_EN.md b/README_EN.md index c1b9185..6656590 100644 --- a/README_EN.md +++ b/README_EN.md @@ -165,6 +165,7 @@ installation are `admin` `admin`, please change the password immediately. lang: "en" app: web-client: 1 # web client route 1:open 0:close + register: false #register enable gin: api-addr: "0.0.0.0:21114" mode: "release"