mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 应用商店离线包改为从 gitee github 获取
This commit is contained in:
parent
9c1fef0309
commit
80a0dfdfc0
@ -58,7 +58,7 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := settingService.Update(c, req.Key, req.Value); err != nil {
|
||||
if err := settingService.Update(req.Key, req.Value); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
@ -240,12 +240,12 @@ func (b *BaseApi) MFABind(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := settingService.Update(c, "MFAStatus", "enable"); err != nil {
|
||||
if err := settingService.Update("MFAStatus", "enable"); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := settingService.Update(c, "MFASecret", req.Secret); err != nil {
|
||||
if err := settingService.Update("MFASecret", req.Secret); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ type SettingInfo struct {
|
||||
EmailVars string `json:"emailVars"`
|
||||
WeChatVars string `json:"weChatVars"`
|
||||
DingVars string `json:"dingVars"`
|
||||
|
||||
AppStoreVersion string `json:"appStoreVersion"`
|
||||
}
|
||||
|
||||
type SettingUpdate struct {
|
||||
|
@ -333,14 +333,12 @@ func (a AppService) SyncInstalled(installId uint) error {
|
||||
}
|
||||
|
||||
func (a AppService) SyncAppList() error {
|
||||
if err := getAppFromOss(); err != nil {
|
||||
if err := getAppFromRepo(); err != nil {
|
||||
global.LOG.Errorf("get app from oss error: %s", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
appDir := constant.AppResourceDir
|
||||
listFile := path.Join(appDir, "list.json")
|
||||
|
||||
content, err := os.ReadFile(listFile)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -354,22 +352,18 @@ func (a AppService) SyncAppList() error {
|
||||
tags []*model.Tag
|
||||
appTags []*model.AppTag
|
||||
)
|
||||
|
||||
for _, t := range list.Tags {
|
||||
tags = append(tags, &model.Tag{
|
||||
Key: t.Key,
|
||||
Name: t.Name,
|
||||
})
|
||||
}
|
||||
|
||||
oldApps, err := appRepo.GetBy()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
appsMap := getApps(oldApps, list.Items)
|
||||
|
||||
for _, l := range list.Items {
|
||||
|
||||
app := appsMap[l.Key]
|
||||
icon, err := os.ReadFile(path.Join(appDir, l.Key, "metadata", "logo.png"))
|
||||
if err != nil {
|
||||
@ -433,9 +427,7 @@ func (a AppService) SyncAppList() error {
|
||||
updateArray = append(updateArray, v)
|
||||
}
|
||||
}
|
||||
|
||||
tx, ctx := getTxAndContext()
|
||||
|
||||
if len(addAppArray) > 0 {
|
||||
if err := appRepo.BatchCreate(ctx, addAppArray); err != nil {
|
||||
tx.Rollback()
|
||||
@ -461,7 +453,6 @@ func (a AppService) SyncAppList() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
apps := append(addAppArray, updateArray...)
|
||||
|
||||
var (
|
||||
@ -478,7 +469,6 @@ func (a AppService) SyncAppList() error {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range a.Details {
|
||||
d.AppId = a.ID
|
||||
if d.ID == 0 {
|
||||
@ -488,7 +478,6 @@ func (a AppService) SyncAppList() error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(addDetails) > 0 {
|
||||
if err := appDetailRepo.BatchCreate(ctx, addDetails); err != nil {
|
||||
tx.Rollback()
|
||||
|
@ -4,9 +4,8 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/git"
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
@ -500,46 +499,32 @@ func handleErr(install model.AppInstall, err error, out string) error {
|
||||
return reErr
|
||||
}
|
||||
|
||||
func getAppFromOss() error {
|
||||
res, err := http.Get(global.CONF.System.AppOss + "/apps/apps.json")
|
||||
func getAppFromRepo() error {
|
||||
repoInfo, err := git.CheckAndGetInfo(global.CONF.System.AppRepoOwner, global.CONF.System.AppRepoName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
appByte, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var ossConfig dto.AppOssConfig
|
||||
if err := json.Unmarshal(appByte, &ossConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
appDir := constant.AppResourceDir
|
||||
content, _ := os.ReadFile(path.Join(appDir, "list.json"))
|
||||
|
||||
if content != nil {
|
||||
oldConfig := &dto.AppOssConfig{}
|
||||
if err := json.Unmarshal(content, oldConfig); err != nil {
|
||||
setting, err := NewISettingService().GetSettingInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if oldConfig.Version == ossConfig.Version {
|
||||
if !common.CompareVersion(repoInfo.Version, setting.AppStoreVersion) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
downloadUrl := fmt.Sprintf("%sapps-%s.tar.gz", repoInfo.DownloadPath, repoInfo.Version)
|
||||
fileOp := files.NewFileOp()
|
||||
|
||||
if _, err := fileOp.CopyAndBackup(appDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
packagePath := path.Join(constant.ResourceDir, path.Base(ossConfig.Package))
|
||||
if err := fileOp.DownloadFile(ossConfig.Package, packagePath); err != nil {
|
||||
packagePath := path.Join(constant.ResourceDir, path.Base(downloadUrl))
|
||||
if err := fileOp.DownloadFile(downloadUrl, packagePath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.Decompress(packagePath, constant.ResourceDir, files.Zip); err != nil {
|
||||
if err := fileOp.Decompress(packagePath, constant.ResourceDir, files.TarGz); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = NewISettingService().Update("AppStoreVersion", repoInfo.Version)
|
||||
defer func() {
|
||||
_ = fileOp.DeleteFile(packagePath)
|
||||
}()
|
||||
|
@ -17,7 +17,7 @@ type SettingService struct{}
|
||||
|
||||
type ISettingService interface {
|
||||
GetSettingInfo() (*dto.SettingInfo, error)
|
||||
Update(c *gin.Context, key, value string) error
|
||||
Update(key, value string) error
|
||||
UpdatePassword(c *gin.Context, old, new string) error
|
||||
UpdatePort(port uint) error
|
||||
HandlePasswordExpired(c *gin.Context, old, new string) error
|
||||
@ -48,7 +48,7 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
|
||||
return &info, err
|
||||
}
|
||||
|
||||
func (u *SettingService) Update(c *gin.Context, key, value string) error {
|
||||
func (u *SettingService) Update(key, value string) error {
|
||||
if key == "ExpirationDays" {
|
||||
timeout, _ := strconv.Atoi(value)
|
||||
if err := settingRepo.Update("ExpirationTime", time.Now().AddDate(0, 0, timeout).Format("2006-01-02 15:04:05")); err != nil {
|
||||
|
@ -33,7 +33,7 @@ func NewIUpgradeService() IUpgradeService {
|
||||
}
|
||||
|
||||
func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) {
|
||||
currentVerion, err := settingRepo.Get(settingRepo.WithByKey("SystemVersion"))
|
||||
currentVersion, err := settingRepo.Get(settingRepo.WithByKey("SystemVersion"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -57,7 +57,7 @@ func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) {
|
||||
}
|
||||
}
|
||||
if len(releaseInfo.NewVersion) != 0 {
|
||||
isNew, err := compareVersion(currentVerion.Value, releaseInfo.NewVersion)
|
||||
isNew, err := compareVersion(currentVersion.Value, releaseInfo.NewVersion)
|
||||
if !isNew && err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -183,8 +183,8 @@ func (u *UpgradeService) handleRollback(fileOp files.FileOp, originalDir string,
|
||||
func (u *UpgradeService) loadLatestFromGithub() (dto.UpgradeInfo, error) {
|
||||
var info dto.UpgradeInfo
|
||||
client := github.NewClient(nil)
|
||||
ctx, cancle := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancle()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
stats, res, err := client.Repositories.GetLatestRelease(ctx, "wanghe-fit2cloud", "1Panel")
|
||||
if res.StatusCode != 200 || err != nil {
|
||||
return info, fmt.Errorf("load upgrade info from github failed, err: %v", err)
|
||||
@ -198,8 +198,8 @@ func (u *UpgradeService) loadLatestFromGithub() (dto.UpgradeInfo, error) {
|
||||
func (u *UpgradeService) loadLatestFromGitee() (dto.UpgradeInfo, error) {
|
||||
var info dto.UpgradeInfo
|
||||
client := gitee.NewAPIClient(gitee.NewConfiguration())
|
||||
ctx, cancle := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancle()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
stats, res, err := client.RepositoriesApi.GetV5ReposOwnerRepoReleasesLatest(ctx, "wanghe-fit2cloud", "1Panel", &gitee.GetV5ReposOwnerRepoReleasesLatestOpts{})
|
||||
if res.StatusCode != 200 || err != nil {
|
||||
return info, fmt.Errorf("load upgrade info from gitee failed, err: %v", err)
|
||||
|
@ -9,4 +9,6 @@ type System struct {
|
||||
Cache string `mapstructure:"cache"`
|
||||
Backup string `mapstructure:"backup"`
|
||||
AppOss string `mapstructure:"app_oss"`
|
||||
AppRepoOwner string `mapstructure:"app_repo_owner"`
|
||||
AppRepoName string `mapstructure:"app_repo_name"`
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ var (
|
||||
ErrTokenParse = errors.New("ErrTokenParse")
|
||||
|
||||
ErrPageGenerate = errors.New("generate page info failed")
|
||||
ErrRepoNotValid = "ErrRepoNotValid"
|
||||
)
|
||||
|
||||
// api
|
||||
|
@ -11,7 +11,7 @@ ErrNotLogin: "User is not Login: {{ .detail }}"
|
||||
ErrNotSafety: "The login status of the current user is unsafe: {{ .detail }}"
|
||||
ErrPasswordExpired: "The current password has expired: {{ .detail }}"
|
||||
ErrNotSupportType: "The system does not support the current type: {{ .detail }}"
|
||||
|
||||
ErrRepoNotValid: "Remote repository verification failed!"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "Name is already exist"
|
||||
|
@ -11,7 +11,7 @@ ErrNotLogin: "用户未登录: {{ .detail }}"
|
||||
ErrNotSafety: "当前用户登录状态不安全: {{ .detail }}"
|
||||
ErrPasswordExpired: "当前密码已过期: {{ .detail }}"
|
||||
ErrNotSupportType: "系统暂不支持当前类型: {{ .detail }}"
|
||||
|
||||
ErrRepoNotValid: "远程仓库校验失败!"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "名称已存在"
|
||||
|
@ -139,6 +139,9 @@ var AddTableSetting = &gormigrate.Migration{
|
||||
if err := tx.Create(&model.Setting{Key: "SystemStatus", Value: "Free"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "AppStoreVersion", Value: "0"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ func Init() {
|
||||
v.SetConfigType("yaml")
|
||||
if fileOp.Stat("/opt/1panel/conf/app.yaml") {
|
||||
v.SetConfigName("app")
|
||||
v.AddConfigPath(path.Join("/opt/1pane/conf"))
|
||||
v.AddConfigPath(path.Join("/opt/1panel/conf"))
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
panic(fmt.Errorf("Fatal error config file: %s \n", err))
|
||||
}
|
||||
|
79
backend/utils/git/git.go
Normal file
79
backend/utils/git/git.go
Normal file
@ -0,0 +1,79 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gitee.com/openeuler/go-gitee/gitee"
|
||||
"github.com/google/go-github/github"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RepoInfo struct {
|
||||
RepoType string
|
||||
Version string
|
||||
ReleaseNote string
|
||||
CreatedAt string
|
||||
DownloadPath string
|
||||
}
|
||||
|
||||
var gitRepoTypes = []string{"gitee", "github"}
|
||||
|
||||
func CheckAndGetInfo(owner, repoName string) (*RepoInfo, error) {
|
||||
for _, repoType := range gitRepoTypes {
|
||||
url := fmt.Sprintf("https://%s.com/%s/%s", repoType, owner, repoName)
|
||||
if checkValid(url) {
|
||||
res, err := getLatestRepoInfo(repoType, owner, repoName)
|
||||
if err == nil {
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, errors.New("remote repo get failed")
|
||||
}
|
||||
|
||||
func checkValid(addr string) bool {
|
||||
timeout := 2 * time.Second
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
client := http.Client{
|
||||
Transport: tr,
|
||||
Timeout: timeout,
|
||||
}
|
||||
if _, err := client.Get(addr); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getLatestRepoInfo(repoType, owner, repoName string) (*RepoInfo, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
var repoInfo RepoInfo
|
||||
repoInfo.RepoType = repoType
|
||||
if repoType == "gitee" {
|
||||
client := gitee.NewAPIClient(gitee.NewConfiguration())
|
||||
stats, res, err := client.RepositoriesApi.GetV5ReposOwnerRepoReleasesLatest(ctx, owner, repoName, &gitee.GetV5ReposOwnerRepoReleasesLatestOpts{})
|
||||
if res.StatusCode != 200 || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoInfo.Version = stats.Name
|
||||
repoInfo.ReleaseNote = stats.Body
|
||||
repoInfo.CreatedAt = stats.CreatedAt.Format("2006-01-02 15:04:05")
|
||||
repoInfo.DownloadPath = fmt.Sprintf("https://gitee.com/%s/%s/releases/download/%s/", owner, repoName, repoInfo.Version)
|
||||
} else {
|
||||
client := github.NewClient(nil)
|
||||
stats, res, err := client.Repositories.GetLatestRelease(ctx, owner, repoName)
|
||||
if res.StatusCode != 200 || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoInfo.Version = *stats.Name
|
||||
repoInfo.ReleaseNote = *stats.Body
|
||||
repoInfo.CreatedAt = stats.PublishedAt.Add(8 * time.Hour).Format("2006-01-02 15:04:05")
|
||||
repoInfo.DownloadPath = fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/", owner, repoName, repoInfo.Version)
|
||||
}
|
||||
return &repoInfo, nil
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
system:
|
||||
db_file: 1Panel.db
|
||||
app_oss: "https://1panel.oss-cn-hangzhou.aliyuncs.com"
|
||||
app_repo_owner: "1Panel-dev"
|
||||
app_repo_name: 'appstore'
|
||||
|
||||
log:
|
||||
level: debug
|
||||
|
Loading…
x
Reference in New Issue
Block a user