From 1232c3cd9c2698804c298ea9a0ffed6db3c34fc5 Mon Sep 17 00:00:00 2001 From: RockYang Date: Sat, 4 May 2024 21:30:29 +0800 Subject: [PATCH] fix bug for license synchronize --- api/Makefile | 2 +- api/core/app_server.go | 2 + api/service/license_service.go | 105 ++++++++++++++++++++++----------- build/dockerfile-api-go | 4 +- web/src/utils/http.js | 11 +++- 5 files changed, 82 insertions(+), 42 deletions(-) diff --git a/api/Makefile b/api/Makefile index deafd9ff..e72ae935 100644 --- a/api/Makefile +++ b/api/Makefile @@ -1,5 +1,5 @@ SHELL=/usr/bin/env bash -NAME := chatgpt-plus +NAME := geekai all: amd64 arm64 amd64: diff --git a/api/core/app_server.go b/api/core/app_server.go index fc410bb1..16040f12 100644 --- a/api/core/app_server.go +++ b/api/core/app_server.go @@ -200,8 +200,10 @@ func authorizeMiddleware(s *AppServer, client *redis.Client) gin.HandlerFunc { func needLogin(c *gin.Context) bool { if c.Request.URL.Path == "/api/user/login" || + c.Request.URL.Path == "/api/user/logout" || c.Request.URL.Path == "/api/user/resetPass" || c.Request.URL.Path == "/api/admin/login" || + c.Request.URL.Path == "/api/admin/logout" || c.Request.URL.Path == "/api/admin/login/captcha" || c.Request.URL.Path == "/api/user/register" || c.Request.URL.Path == "/api/user/session" || diff --git a/api/service/license_service.go b/api/service/license_service.go index 18f1d6d1..8a2fe29f 100644 --- a/api/service/license_service.go +++ b/api/service/license_service.go @@ -16,7 +16,7 @@ import ( type LicenseService struct { config types.ApiConfig levelDB *store.LevelDB - license types.License + license *types.License urlWhiteList []string machineId string } @@ -29,18 +29,20 @@ func NewLicenseService(server *core.AppServer, levelDB *store.LevelDB) *LicenseS if err == nil { machineId = info.HostID } + logger.Infof("License: %+v", license) return &LicenseService{ config: server.Config.ApiConfig, levelDB: levelDB, - license: license, + license: &license, machineId: machineId, } } type License struct { Name string `json:"name"` - Value string `json:"license"` + License string `json:"license"` Mid string `json:"mid"` + ActiveAt int64 `json:"active_at"` ExpiredAt int64 `json:"expired_at"` UserNum int `json:"user_num"` } @@ -68,7 +70,7 @@ func (s *LicenseService) ActiveLicense(license string, machineId string) error { return fmt.Errorf("激活失败:%v", res.Message) } - s.license = types.License{ + s.license = &types.License{ Key: license, MachineId: machineId, UserNum: res.Data.UserNum, @@ -85,50 +87,81 @@ func (s *LicenseService) ActiveLicense(license string, machineId string) error { // SyncLicense 定期同步 License func (s *LicenseService) SyncLicense() { go func() { + retryCounter := 0 for { - var res struct { - Code types.BizCode `json:"code"` - Message string `json:"message"` - Data struct { - License License `json:"license"` - Urls []string `json:"urls"` - } - } - apiURL := fmt.Sprintf("%s/%s", s.config.ApiURL, "api/license/check") - response, err := req.C().R(). - SetBody(map[string]string{"license": s.license.Key, "machine_id": s.machineId}). - SetSuccessResult(&res).Post(apiURL) + license, err := s.fetchLicense() if err != nil { - logger.Errorf("发送激活请求失败: %v", err) - goto next - } - if response.IsErrorState() { - logger.Errorf("激活失败:%v", response.Status) - goto next - } - if res.Code != types.Success { - logger.Errorf("激活失败:%v", res.Message) + retryCounter++ + if retryCounter < 5 { + logger.Error(err) + } s.license.IsActive = false - goto next + } else { + s.license = license } - s.license = types.License{ - Key: res.Data.License.Value, - MachineId: res.Data.License.Mid, - UserNum: res.Data.License.UserNum, - ExpiredAt: res.Data.License.ExpiredAt, - IsActive: true, + urls, err := s.fetchUrlWhiteList() + if err == nil { + s.urlWhiteList = urls } - s.urlWhiteList = res.Data.Urls - //logger.Debugf("同步 License 成功:%v\n%v", s.license, s.urlWhiteList) - next: + time.Sleep(time.Second * 10) } }() } +func (s *LicenseService) fetchLicense() (*types.License, error) { + var res struct { + Code types.BizCode `json:"code"` + Message string `json:"message"` + Data License `json:"data"` + } + apiURL := fmt.Sprintf("%s/%s", s.config.ApiURL, "api/license/check") + response, err := req.C().R(). + SetBody(map[string]string{"license": s.license.Key, "machine_id": s.machineId}). + SetSuccessResult(&res).Post(apiURL) + if err != nil { + return nil, fmt.Errorf("发送激活请求失败: %v", err) + } + if response.IsErrorState() { + return nil, fmt.Errorf("激活失败:%v", response.Status) + } + if res.Code != types.Success { + return nil, fmt.Errorf("激活失败:%v", res.Message) + } + + return &types.License{ + Key: res.Data.License, + MachineId: res.Data.Mid, + UserNum: res.Data.UserNum, + ExpiredAt: res.Data.ExpiredAt, + IsActive: true, + }, nil +} + +func (s *LicenseService) fetchUrlWhiteList() ([]string, error) { + var res struct { + Code types.BizCode `json:"code"` + Message string `json:"message"` + Data []string `json:"data"` + } + apiURL := fmt.Sprintf("%s/%s", s.config.ApiURL, "api/license/urls") + response, err := req.C().R().SetSuccessResult(&res).Get(apiURL) + if err != nil { + return nil, fmt.Errorf("发送请求失败: %v", err) + } + if response.IsErrorState() { + return nil, fmt.Errorf("发送请求失败:%v", response.Status) + } + if res.Code != types.Success { + return nil, fmt.Errorf("获取白名单失败:%v", res.Message) + } + + return res.Data, nil +} + // GetLicense 获取许可信息 -func (s *LicenseService) GetLicense() types.License { +func (s *LicenseService) GetLicense() *types.License { return s.license } diff --git a/build/dockerfile-api-go b/build/dockerfile-api-go index 6c701581..a865f430 100644 --- a/build/dockerfile-api-go +++ b/build/dockerfile-api-go @@ -4,9 +4,9 @@ FROM registry.cn-hangzhou.aliyuncs.com/geekmaster/alpine:3.18.2 MAINTAINER yangjian WORKDIR /var/www/app -COPY ./api/bin/chatgpt-plus-linux /var/www/app +COPY ./api/bin/geekai-linux /var/www/app EXPOSE 5678 # 容器启动时执行的命令 -CMD ["./chatgpt-plus-linux"] +CMD ["./geekai-linux"] diff --git a/web/src/utils/http.js b/web/src/utils/http.js index 7f5b3caf..d6fb22be 100644 --- a/web/src/utils/http.js +++ b/web/src/utils/http.js @@ -1,5 +1,5 @@ import axios from 'axios' -import {getAdminToken, getSessionId, getUserToken} from "@/store/session"; +import {getAdminToken, getSessionId, getUserToken, removeAdminToken, removeUserToken} from "@/store/session"; axios.defaults.timeout = 180000 axios.defaults.baseURL = process.env.VUE_APP_API_HOST @@ -22,9 +22,14 @@ axios.interceptors.response.use( let data = response.data; if (data.code === 0) { return response - } else { - return Promise.reject(response.data) + } else if (data.code === 400) { + if (response.request.responseURL.indexOf("/api/admin") !== -1) { + removeAdminToken() + } else { + removeUserToken() + } } + return Promise.reject(response.data) }, error => { return Promise.reject(error) })