Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions agent/app/api/v2/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (
)

func (b *BaseApi) CheckBackupUsed(c *gin.Context) {
id, err := helper.GetIntParamByKey(c, "id")
name, err := helper.GetStrParamByKey(c, "name")
if err != nil {
helper.BadRequest(c, err)
return
}

if err := backupService.CheckUsed(id); err != nil {
if err := backupService.CheckUsed(name); err != nil {
helper.BadRequest(c, err)
return
}
Expand Down
7 changes: 7 additions & 0 deletions agent/app/repo/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type IBackupRepo interface {
Create(backup *model.BackupAccount) error
Save(backup *model.BackupAccount) error
Delete(opts ...DBOption) error
WithByPublic(isPublic bool) DBOption

ListRecord(opts ...DBOption) ([]model.BackupRecord, error)
PageRecord(page, size int, opts ...DBOption) (int64, []model.BackupRecord, error)
Expand All @@ -35,6 +36,12 @@ func NewIBackupRepo() IBackupRepo {
return &BackupRepo{}
}

func (u *BackupRepo) WithByPublic(isPublic bool) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("is_public = ?", isPublic)
}
}

func (u *BackupRepo) Get(opts ...DBOption) (model.BackupAccount, error) {
var backup model.BackupAccount
db := global.DB
Expand Down
16 changes: 10 additions & 6 deletions agent/app/service/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
type BackupService struct{}

type IBackupService interface {
CheckUsed(id uint) error
CheckUsed(name string) error
Sync(req dto.SyncFromMaster) error

LoadBackupOptions() ([]dto.BackupOption, error)
Expand Down Expand Up @@ -103,8 +103,8 @@ func (u *BackupService) SearchWithPage(req dto.SearchPageWithType) (int64, inter
item.Vars = string(itemVars)
}
} else {
item.AccessKey = base64.StdEncoding.EncodeToString([]byte(item.AccessKey))
item.Credential = base64.StdEncoding.EncodeToString([]byte(item.Credential))
item.AccessKey, _ = encrypt.StringDecryptWithBase64(item.AccessKey)
item.Credential, _ = encrypt.StringDecryptWithBase64(item.Credential)
}

if account.Type == constant.OneDrive || account.Type == constant.ALIYUN || account.Type == constant.GoogleDrive {
Expand Down Expand Up @@ -394,15 +394,19 @@ func (u *BackupService) LoadBackupOptions() ([]dto.BackupOption, error) {
return data, nil
}

func (u *BackupService) CheckUsed(id uint) error {
func (u *BackupService) CheckUsed(name string) error {
account, _ := backupRepo.Get(repo.WithByName(name), backupRepo.WithByPublic(true))
if account.ID == 0 {
return nil
}
cronjobs, _ := cronjobRepo.List()
for _, job := range cronjobs {
if job.DownloadAccountID == id {
if job.DownloadAccountID == account.ID {
return buserr.New("ErrBackupInUsed")
}
ids := strings.Split(job.SourceAccountIDs, ",")
for _, idItem := range ids {
if idItem == fmt.Sprintf("%v", id) {
if idItem == fmt.Sprintf("%v", account.ID) {
return buserr.New("ErrBackupInUsed")
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, but I cannot review and assess code that is not provided. However, general suggestions regarding regular coding practice may include:

  • Ensuring clear function and variable names
  • Keeping the import statements organized without duplicates
  • Verifying if all required dependencies are included (though it's unclear which framework you're working with from your example)
  • Making sure APIs like AWS S3 or Google Drive calls are secure and properly authenticated

For a full assessment, please provide the relevant code snippet.

Expand Down
7 changes: 7 additions & 0 deletions agent/init/hook/hook.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package hook

import (
"os"
"path"

"github.com/1Panel-dev/1Panel/agent/app/dto"
Expand Down Expand Up @@ -102,4 +103,10 @@ func loadLocalDir() {
return
}
global.Dir.LocalBackupDir = account.BackupPath

if _, err := os.Stat(account.BackupPath); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(account.BackupPath, os.ModePerm); err != nil {
global.LOG.Errorf("mkdir %s failed, err: %v", account.BackupPath, err)
}
}
}
2 changes: 1 addition & 1 deletion agent/router/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func (s *BackupRouter) InitRouter(Router *gin.RouterGroup) {
backupRouter := Router.Group("backups")
baseApi := v2.ApiGroupApp.BaseApi
{
backupRouter.GET("/check/:id", baseApi.CheckBackupUsed)
backupRouter.GET("/check/:name", baseApi.CheckBackupUsed)
backupRouter.POST("/sync", baseApi.SyncBackupAccount)
backupRouter.GET("/options", baseApi.LoadBackupOptions)
backupRouter.POST("/search", baseApi.SearchBackup)
Expand Down
12 changes: 6 additions & 6 deletions core/app/api/v2/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ func (b *BaseApi) CreateBackup(c *gin.Context) {
// @Tags Backup Account
// @Summary Refresh token
// @Accept json
// @Param request body dto.BackupOperate true "request"
// @Param request body dto.OperateByName true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /core/backups/refresh/token [post]
func (b *BaseApi) RefreshToken(c *gin.Context) {
var req dto.OperateByID
var req dto.OperateByName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
Expand Down Expand Up @@ -96,19 +96,19 @@ func (b *BaseApi) LoadBackupClientInfo(c *gin.Context) {
// @Tags Backup Account
// @Summary Delete backup account
// @Accept json
// @Param request body dto.OperateByID true "request"
// @Param request body dto.OperateByName true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /core/backups/del [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"backup_accounts","output_column":"type","output_value":"types"}],"formatZH":"删除备份账号 [types]","formatEN":"delete backup account [types]"}
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除备份账号 [name]","formatEN":"delete backup account [name]"}
func (b *BaseApi) DeleteBackup(c *gin.Context) {
var req dto.OperateByID
var req dto.OperateByName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}

if err := backupService.Delete(req.ID); err != nil {
if err := backupService.Delete(req.Name); err != nil {
helper.InternalServer(c, err)
return
}
Expand Down
4 changes: 4 additions & 0 deletions core/app/dto/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ type OperateByType struct {
Type string `json:"type"`
}

type OperateByName struct {
Name string `json:"name"`
}

type OperateByID struct {
ID uint `json:"id"`
}
Expand Down
21 changes: 11 additions & 10 deletions core/app/service/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ type IBackupService interface {
Create(backupDto dto.BackupOperate) error
GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error)
Update(req dto.BackupOperate) error
Delete(id uint) error
RefreshToken(req dto.OperateByID) error
Delete(name string) error
RefreshToken(req dto.OperateByName) error
}

func NewIBackupService() IBackupService {
Expand Down Expand Up @@ -156,8 +156,8 @@ func (u *BackupService) GetBuckets(req dto.ForBuckets) ([]interface{}, error) {
return client.ListBuckets()
}

func (u *BackupService) Delete(id uint) error {
backup, _ := backupRepo.Get(repo.WithByID(id))
func (u *BackupService) Delete(name string) error {
backup, _ := backupRepo.Get(repo.WithByName(name))
if backup.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
Expand All @@ -167,21 +167,21 @@ func (u *BackupService) Delete(id uint) error {
if backup.Type == constant.Local {
return buserr.New("ErrBackupLocal")
}
if _, err := req_helper.NewLocalClient(fmt.Sprintf("/api/v2/backups/check/%v", id), http.MethodGet, nil); err != nil {
if _, err := req_helper.NewLocalClient(fmt.Sprintf("/api/v2/backups/check/%s", name), http.MethodGet, nil); err != nil {
global.LOG.Errorf("check used of local cronjob failed, err: %v", err)
return buserr.New("ErrBackupInUsed")
}
if err := xpack.CheckBackupUsed(id); err != nil {
if err := xpack.CheckBackupUsed(name); err != nil {
global.LOG.Errorf("check used of node cronjob failed, err: %v", err)
return buserr.New("ErrBackupInUsed")
}

go syncAccountToAgent(backup, "delete")
return backupRepo.Delete(repo.WithByID(id))
return backupRepo.Delete(repo.WithByName(name))
}

func (u *BackupService) Update(req dto.BackupOperate) error {
backup, _ := backupRepo.Get(repo.WithByID(req.ID))
backup, _ := backupRepo.Get(repo.WithByName(req.Name))
if backup.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
Expand All @@ -198,6 +198,7 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
if err := copier.Copy(&newBackup, &req); err != nil {
return buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
newBackup.ID = backup.ID
itemAccessKey, err := base64.StdEncoding.DecodeString(newBackup.AccessKey)
if err != nil {
return err
Expand Down Expand Up @@ -235,8 +236,8 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
return nil
}

func (u *BackupService) RefreshToken(req dto.OperateByID) error {
backup, _ := backupRepo.Get(repo.WithByID(req.ID))
func (u *BackupService) RefreshToken(req dto.OperateByName) error {
backup, _ := backupRepo.Get(repo.WithByName(req.Name))
if backup.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no known irregularities, potential issues, or optimization suggestions for the provided code snippet.

Please note that this check will only cover what you have shown here and may not catch all edge cases or security vulnerabilities related to real-world applications. Regular reviews from more experienced developers would be highly recommended.

Expand Down
2 changes: 1 addition & 1 deletion core/utils/cloud_storage/client/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

func loadParamFromVars(key string, vars map[string]interface{}) string {
if _, ok := vars[key]; !ok {
if key != "bucket" && key != "port" {
if key != "bucket" && key != "port" && key != "authMode" && key != "passPhrase" {
global.LOG.Errorf("load param %s from vars failed, err: not exist!", key)
}
return ""
Expand Down
2 changes: 1 addition & 1 deletion core/utils/xpack/xpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func Proxy(c *gin.Context, currentNode string) {}

func UpdateGroup(name string, group, newGroup uint) error { return nil }

func CheckBackupUsed(id uint) error { return nil }
func CheckBackupUsed(name string) error { return nil }

func RequestToAllAgent(reqUrl, reqMethod string, reqBody io.Reader) error { return nil }

Expand Down
22 changes: 10 additions & 12 deletions frontend/src/api/modules/backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,11 @@ export const getFilesFromBackup = (id: number) => {
};

// backup-core
export const refreshToken = (params: { id: number; isPublic: boolean }) => {
let urlItem = '/core/backups/refresh/token';
if (!params.isPublic || !globalStore.isProductPro) {
urlItem = '/backups/refresh/token';
export const refreshToken = (params: { id: number; name: string; isPublic: boolean }) => {
if (!params.isPublic) {
return http.post('/backups/refresh/token', { id: params.id });
}
return http.post(urlItem, { id: params.id });
return http.post('/core/backups/refresh/token', { name: params.name });
};
export const getClientInfo = (clientType: string) => {
return http.get<Backup.ClientInfo>(`/core/backups/client/${clientType}`);
Expand All @@ -65,7 +64,7 @@ export const addBackup = (params: Backup.BackupOperate) => {
request.credential = Base64.encode(request.credential);
}
let urlItem = '/core/backups';
if (!params.isPublic || !globalStore.isProductPro) {
if (!params.isPublic) {
urlItem = '/backups';
}
return http.post<Backup.BackupOperate>(urlItem, request, TimeoutEnum.T_60S);
Expand All @@ -79,17 +78,16 @@ export const editBackup = (params: Backup.BackupOperate) => {
request.credential = Base64.encode(request.credential);
}
let urlItem = '/core/backups/update';
if (!params.isPublic || !globalStore.isProductPro) {
if (!params.isPublic) {
urlItem = '/backups/update';
}
return http.post(urlItem, request);
};
export const deleteBackup = (params: { id: number; isPublic: boolean }) => {
let urlItem = '/core/backups/del';
if (!params.isPublic || !globalStore.isProductPro) {
urlItem = '/backups/del';
export const deleteBackup = (params: { id: number; name: string; isPublic: boolean }) => {
if (!params.isPublic) {
return http.post('/backups/del', { id: params.id });
}
return http.post(urlItem, { id: params.id });
return http.post('/core/backups/del', { name: params.name });
};
export const listBucket = (params: Backup.ForBucket) => {
let request = deepCopy(params) as Backup.BackupOperate;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no significant changes to the code. The modifications include adding a new refreshToken method that checks whether a token should be fetched from the public API or local storage based on parameters provided. No major discrepancies were found during review.

Expand Down
6 changes: 3 additions & 3 deletions frontend/src/views/setting/backup-account/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,13 @@ const loadEndpoint = (row: any) => {
const onDelete = async (row: Backup.BackupInfo) => {
opRef.value.acceptParams({
title: i18n.global.t('commons.button.delete'),
names: [row.type],
names: ['[ ' + row.type + ' ] ' + row.name],
msg: i18n.global.t('commons.msg.operatorHelper', [
i18n.global.t('setting.backupAccount'),
i18n.global.t('commons.button.delete'),
]),
api: deleteBackup,
params: { id: row.id, isPublic: row.isPublic },
params: { id: row.id, name: row.name, isPublic: row.isPublic },
});
};

Expand All @@ -193,7 +193,7 @@ const onOpenDialog = async (
};

const refreshItemToken = async (row: any) => {
await refreshToken({ id: row.id, isPublic: row.isPublic });
await refreshToken({ id: row.id, name: row.name, isPublic: row.isPublic });
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
search();
};
Expand Down
14 changes: 10 additions & 4 deletions frontend/src/views/setting/backup-account/operate/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
prop="isPublic"
:rules="Rules.requiredSelect"
>
<el-radio-group v-model="dialogData.rowData!.isPublic">
<el-tag v-if="dialogData.title === 'edit'">
{{ dialogData.rowData!.isPublic ? $t('setting.public') : $t('setting.private') }}
</el-tag>
<el-radio-group v-else v-model="dialogData.rowData!.isPublic">
<el-radio :value="true" size="large">{{ $t('setting.public') }}</el-radio>
<el-radio :value="false" size="large">{{ $t('setting.private') }}</el-radio>
<span class="input-help">
{{ dialogData.rowData!.isPublic ? $t('setting.publicHelper') : $t('setting.privateHelper') }}
</span>
</el-radio-group>
<span class="input-help">
{{ dialogData.rowData!.isPublic ? $t('setting.publicHelper') : $t('setting.privateHelper') }}
</span>
</el-form-item>
<el-form-item :label="$t('commons.table.type')" prop="type" :rules="Rules.requiredSelect">
<el-tag v-if="dialogData.title === 'edit'">{{ $t('setting.' + dialogData.rowData!.type) }}</el-tag>
Expand Down Expand Up @@ -440,6 +443,9 @@ const dialogData = ref<DialogProps>({
});
const acceptParams = (params: DialogProps): void => {
dialogData.value = params;
dialogData.value.rowData.varsJson = dialogData.value.rowData!.vars
? JSON.parse(dialogData.value.rowData!.vars)
: {};
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
if (dialogData.value.title === 'create') {
dialogData.value.rowData!.type = 'OSS';
Expand Down
Loading