Repository: 1Panel-dev/1Panel
Pull request #8135: fix: Fix the problem that the cache clears deleted log files by mistake
Author: login: ssongliu
Labels: name: do-not-merge/release-note-label-needed
name: approved
name: dev-v2
Created: 2025-03-12T10:40:51Z | Merged: 2025-03-12T14:47:03Z



Diff:
diff --git a/agent/app/repo/task.go b/agent/app/repo/task.go
index 5f9f291d0800..716a12539d50 100644
--- a/agent/app/repo/task.go
+++ b/agent/app/repo/task.go
@@ -21,6 +21,7 @@ type ITaskRepo interface {
 	UpdateRunningTaskToFailed() error
 	CountExecutingTask() (int64, error)
 	Delete(opts ...DBOption) error
+	DeleteAll() error
 
 	WithByID(id string) DBOption
 	WithResourceID(id uint) DBOption
@@ -118,3 +119,7 @@ func (u TaskRepo) Delete(opts ...DBOption) error {
 	}
 	return db.Delete(&model.Task{}).Error
 }
+
+func (u TaskRepo) DeleteAll() error {
+	return global.TaskDB.Where("1 = 1").Delete(&model.Task{}).Error
+}
diff --git a/agent/app/service/backup.go b/agent/app/service/backup.go
index e17e0622ac24..65320559578a 100644
--- a/agent/app/service/backup.go
+++ b/agent/app/service/backup.go
@@ -247,7 +247,7 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
 	}
 
 	if newBackup.Type == constant.OneDrive || newBackup.Type == constant.GoogleDrive {
-		if err := loadRefreshTokenByCode(&backup); err != nil {
+		if err := loadRefreshTokenByCode(&newBackup); err != nil {
 			return err
 		}
 	}
diff --git a/agent/app/service/device_clean.go b/agent/app/service/device_clean.go
index 736856b6d1f5..7678f99c3001 100644
--- a/agent/app/service/device_clean.go
+++ b/agent/app/service/device_clean.go
@@ -244,7 +244,7 @@ func (u *DeviceService) Clean(req []dto.Clean) {
 					continue
 				}
 				for _, file := range files {
-					if file.Name() == "1Panel.log" || file.IsDir() {
+					if file.Name() == "1Panel-Core.log" || file.Name() == "1Panel.log" || file.IsDir() {
 						continue
 					}
 					dropFileOrDir(path.Join(global.Dir.BaseDir, logPath, file.Name()))
@@ -253,10 +253,24 @@ func (u *DeviceService) Clean(req []dto.Clean) {
 				dropFileOrDir(path.Join(global.Dir.BaseDir, logPath, item.Name))
 			}
 		case "task_log":
-			pathItem := path.Join(global.Dir.BaseDir, logPath, item.Name)
-			dropFileOrDir(pathItem)
-			if len(item.Name) != 0 {
-				_ = taskRepo.Delete(repo.WithByType(item.Name))
+			if len(item.Name) == 0 {
+				files, _ := os.ReadDir(path.Join(global.Dir.BaseDir, logPath))
+				if len(files) == 0 {
+					continue
+				}
+				for _, file := range files {
+					if file.Name() == "ssl" || !file.IsDir() {
+						continue
+					}
+					dropFileOrDir(path.Join(global.Dir.BaseDir, logPath, file.Name()))
+				}
+				_ = taskRepo.DeleteAll()
+			} else {
+				pathItem := path.Join(global.Dir.BaseDir, logPath, item.Name)
+				dropFileOrDir(pathItem)
+				if len(item.Name) != 0 {
+					_ = taskRepo.Delete(repo.WithByType(item.Name))
+				}
 			}
 		case "images":
 			dropImages()
@@ -326,7 +340,7 @@ func systemClean(taskItem *task.Task) error {
 				if logFiles[i].IsDir() {
 					continue
 				}
-				if logFiles[i].Name() != "1Panel.log" {
+				if logFiles[i].Name() != "1Panel.log" && logFiles[i].Name() != "1Panel-Core.log" {
 					dropWithTask(path.Join(logPath, logFiles[i].Name()), taskItem, &size, &fileCount)
 				}
 			}
@@ -591,7 +605,10 @@ func loadTreeWithAllFile(isCheck bool, originalPath, treeType, pathItem string,
 		return lists
 	}
 	for _, file := range files {
-		if treeType == "system_log" && (file.Name() == "1Panel.log" || file.IsDir()) {
+		if treeType == "upload" && (file.Name() == "theme" && file.IsDir()) {
+			continue
+		}
+		if treeType == "system_log" && (file.Name() == "1Panel-Core.log" || file.Name() == "1Panel.log" || file.IsDir()) {
 			continue
 		}
 		if (treeType == "upload" || treeType == "download") && file.IsDir() && (file.Name() == "app" || file.Name() == "database" || file.Name() == "website" || file.Name() == "directory") {
diff --git a/agent/app/service/snapshot_recover.go b/agent/app/service/snapshot_recover.go
index 398caac0b64b..506fd0d8d538 100644
--- a/agent/app/service/snapshot_recover.go
+++ b/agent/app/service/snapshot_recover.go
@@ -247,10 +247,12 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
 	if err != nil {
 		return err
 	}
-	err = itemHelper.FileOp.CopyFile("/etc/docker/daemon.json", baseDir)
-	itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"), err)
-	if err != nil {
-		return err
+	if itemHelper.FileOp.Stat("/etc/docker/daemon.json") {
+		err = itemHelper.FileOp.CopyFile("/etc/docker/daemon.json", baseDir)
+		itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"), err)
+		if err != nil {
+			return err
+		}
 	}
 	return nil
 }
diff --git a/core/app/service/backup.go b/core/app/service/backup.go
index 2cc130316568..aa3ab995289d 100644
--- a/core/app/service/backup.go
+++ b/core/app/service/backup.go
@@ -211,7 +211,7 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
 	newBackup.Credential = string(itemCredential)
 
 	if newBackup.Type == constant.OneDrive || newBackup.Type == constant.GoogleDrive {
-		if err := u.loadRefreshTokenByCode(&backup); err != nil {
+		if err := u.loadRefreshTokenByCode(&newBackup); err != nil {
 			return err
 		}
 	}
diff --git a/core/log/writer.go b/core/log/writer.go
index 3f0d1abcadef..38c62d6bb444 100644
--- a/core/log/writer.go
+++ b/core/log/writer.go
@@ -1,7 +1,6 @@
 package log
 
 import (
-	"github.com/1Panel-dev/1Panel/core/constant"
 	"log"
 	"os"
 	"path"
@@ -12,6 +11,8 @@ import (
 	"time"
 	"unsafe"
 
+	"github.com/1Panel-dev/1Panel/core/constant"
+
 	"github.com/1Panel-dev/1Panel/core/global"
 )
 
@@ -85,7 +86,7 @@ func NewWriterFromConfig(c *Config) (RollingWriter, error) {
 		return nil, err
 	}
 	filepath := FilePath(c)
-	file, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_APPEND, constant.DirPerm)
+	file, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_APPEND, constant.FilePerm)
 	if err != nil {
 		return nil, err
 	}
diff --git a/frontend/src/views/ai/model/index.vue b/frontend/src/views/ai/model/index.vue
index 299ebe646b4d..b212507b8205 100644
--- a/frontend/src/views/ai/model/index.vue
+++ b/frontend/src/views/ai/model/index.vue
@@ -175,7 +175,7 @@
         <PortJumpDialog ref="dialogPortJumpRef" />
         <BindDomain ref="bindDomainRef" />
 
-        <TaskLog ref="taskLogRef" width="70%" />
+        <TaskLog ref="taskLogRef" width="70%" @close="search" />
     </div>
 </template>
 
diff --git a/frontend/src/views/setting/backup-account/operate/index.vue b/frontend/src/views/setting/backup-account/operate/index.vue
index 0017f224a0ab..c9a9554faadc 100644
--- a/frontend/src/views/setting/backup-account/operate/index.vue
+++ b/frontend/src/views/setting/backup-account/operate/index.vue
@@ -570,8 +570,10 @@ const changeType = async () => {
     switch (dialogData.value.rowData!.type) {
         case 'COS':
         case 'OSS':
-        case 'S3':
             dialogData.value.rowData.varsJson['scType'] = 'Standard';
+            break;
+        case 'S3':
+            dialogData.value.rowData.varsJson['scType'] = 'STANDARD';
             dialogData.value.rowData.varsJson['mode'] = 'virtual hosted';
             break;
         case 'KODO':
diff --git a/frontend/src/views/toolbox/clean/index.vue b/frontend/src/views/toolbox/clean/index.vue
index 204e572db90f..5e347e818f4e 100644
--- a/frontend/src/views/toolbox/clean/index.vue
+++ b/frontend/src/views/toolbox/clean/index.vue
@@ -641,6 +641,7 @@ function load18n(label: string) {
         case 'Container':
         case 'App':
         case 'System':
+        case 'Website':
             return i18n.global.t('menu.' + label.toLowerCase());
         case 'RuntimeExtension':
             return i18n.global.t('website.runtime');


Reviews:
user: login: wanghe-fit2cloud
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-12T10:41:17Z
user: login: wanghe-fit2cloud
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-12T10:41:22Z
user: login: wanghe-fit2cloud
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-12T10:41:27Z
user: login: wanghe-fit2cloud
body: /lgtm
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-12T14:42:03Z

Review comments:
diff_hunk: @@ -591,7 +605,10 @@ func loadTreeWithAllFile(isCheck bool, originalPath, treeType, pathItem string,
 		return lists
 	}
 	for _, file := range files {
-		if treeType == "system_log" && (file.Name() == "1Panel.log" || file.IsDir()) {
+		if treeType == "upload" && (file.Name() == "theme" && file.IsDir()) {
+			continue
+		}
+		if treeType == "system_log" && (file.Name() == "1Panel-Core.log" || file.Name() == "1Panel.log" || file.IsDir()) {
 			continue
 		}
 		if (treeType == "upload" || treeType == "download") && file.IsDir() && (file.Name() == "app" || file.Name() == "database" || file.Name() == "website" || file.Name() == "directory") {
path: agent/app/service/device_clean.go
user: login: wanghe-fit2cloud
body: The code has several irregularities, potential issues, and optimizations that can be addressed:

### Irregularities/Issues:
1. **Duplicate Function Calls**:
   ```go
   dropFileOrDir(path.Join(global.Dir.BaseDir, logPath, file.Name()))
   if len(item.Name) != 0 {
       _ = taskRepo.Delete(repo.WithByType(item.Name))
   }
   ```
   This pattern is used to delete a file or directory based on certain conditions but does not handle the case when `item.Name` is empty.

2. **Unnecessary Logic**:
   In the `systemClean` function, some of the checks for `logFiles[i]` might be redundant or unnecessary depending on the context.

3. **Incorrect Directory Handling**:
   When handling directories in `loadTreeWithAllFile`, there is an unnecessary condition check (`(treeType == "upload" || treeType == "download") &&`). The condition `(file.IsDir() && (file.Name() == "app" || file.Name() == "database" || file.Name() == "website" || file.Name() == "directory"))` already considers the type of directory.

### Optimization Suggestions:
1. **Consolidate Operations**:
   Combine similar operations where possible to reduce redundancy. For example, instead of calling `dropFileOrDir` twice under the same condition, you could consolidate them into one call.

2. **Error Handling**:
   Ensure that all file manipulation operations have proper error handling. This prevents silent failures and makes debugging easier.

3. **Directory Filtering**:
   Improve the filtering logic in functions like `clean`. Instead of checking both `"1Panel.log"` and `"1Panel-Core.log"` separately, consider using a set of allowed filenames or patterns.

4. **Use More Specific Functions**:
   Replace generic utility functions with domain-specific ones wherever practical. For example, use `os.ReadDir` directly without wrapping it in another helper function.

Here's an optimized version of the problematic lines from `clean` and `loadTreeWithAllFile`:

```go
func clean(req []dto.Clean) {
    // Simplified cleaning logic
    logPath := global.Dir.LogPath
    for _, item := range req {
        switch item.Type {
        case "sysLog":
            files, err := os.ReadDir(logPath)
            if err != nil {
                logger.Error(err, "Failed to read logs")
                continue
            }

            var toDelete []string
            for _, file := range files {
                if file.IsDir() || (file.Name() == "ssl") {
                    continue
                }
                toDelete = append(toDelete, filepath.Join(logPath, file.Name()))
            }

            for _, filePath := range toDelete {
                err = ioutil.WriteFile(filePath, nil, 0o644) // Simulate deleting by overwriting
                if err != nil {
                    logger.Errorf("Failed to delete %s", filePath)
                } else {
                    logger.Infof("Deleted %s", filePath)
                }
            }
            
            if err := taskRepo.DeleteAll(); err != nil {
                logger.Error(err, "Failed to delete tasks")
            }
            break

        case "task_log":
            pathItem := path.Join(global.Dir.BaseDir, logPath, item.Name)
            if len(item.Name) > 0 {
                err := taskRepo.Delete(repo.WithByType(item.Name))
                if err != nil {
                    logger.Error(err, "Failed to delete task by name")
                }
            }
            dropFileOrDir(pathItem)
            break

        // Handle other cases similarly...
        }
    }
}

// ... other unchanged parts ...
```

This refined version simplifies conditional checks and consolidates duplicate operations, making the code more readable and efficient.
created_at: 2025-03-12T10:41:17Z
author_association: MEMBER
diff_hunk: @@ -247,10 +247,12 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
 	if err != nil {
 		return err
 	}
-	err = itemHelper.FileOp.CopyFile("/etc/docker/daemon.json", baseDir)
-	itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"), err)
-	if err != nil {
-		return err
+	if itemHelper.FileOp.Stat("/etc/docker/daemon.json") {
+		err = itemHelper.FileOp.CopyFile("/etc/docker/daemon.json", baseDir)
+		itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"), err)
+		if err != nil {
+			return err
+		}
 	}
 	return nil
 }
path: agent/app/service/snapshot_recover.go
user: login: wanghe-fit2cloud
body: No significant discrepancies or issues were found in the provided code snippet. Here is a brief overview of what each part does:

1. **Initial `err` Check**: Before calling `itemHelper.FileOp.CopyFile`, there's an initial check to see if an error (`err`) occurred from previous operations.

2. **Copying `/etc/docker/daemon.json`**:
   - If no errors have occurred up to this point, it proceeds to copy the configuration file using `itemHelper.FileOp.CopyFile`.
   - It logs with a status message about copying `daemon.json`.

3. **Error Handling After Copying**:
   - Similar to the first step, it checks for any errors resulting from attempting to copy the file and returns them if necessary.

The logic looks clean and efficient, ensuring that the file is only copied once and handles potential errors appropriately. No major optimizations or corrections are needed based on the content provided.
created_at: 2025-03-12T10:41:22Z
author_association: MEMBER
diff_hunk: @@ -118,3 +119,7 @@ func (u TaskRepo) Delete(opts ...DBOption) error {
 	}
 	return db.Delete(&model.Task{}).Error
 }
+
+func (u TaskRepo) DeleteAll() error {
+	return global.TaskDB.Where("1 = 1").Delete(&model.Task{}).Error
+}
path: agent/app/repo/task.go
user: login: wanghe-fit2cloud
body: It seems there is an issue with line 122 of the code where `db` is defined without being initialized outside this function. Additionally, the documentation comment after the `DeleteAllFunc()` method needs to be updated to reflect that it only deletes tasks in the default task database. Here's what you can do:

```diff
@@ -21,6 +21,7 @@ type ITaskRepo interface {
 	UpdateRunningTaskToFailed() error
 	CountExecutingTask() (int64, error)
 	Delete(opts ...DBOption) error
+	DeleteAll() error
 
 	WithByID(id string) DBOption
 	WithResourceID(id uint) DBOption
@@ -121,3 +122,0 @@
+
-	var db *gorm.DB = GlobalTaskDB // Update this line if needed
-
	func (u TaskRepo) DeleteAll() error {
--- 119,122 ----

```

This change initializes the `db` variable globally within a package-level scope, ensuring that it is accessible everywhere in your project. The documentation needs to be modified to clarify that `DeleteAll` targets the main/default task repository instead of a specific database option.

---

If you have other questions or need further assistance, feel free to ask!
created_at: 2025-03-12T10:41:27Z
author_association: MEMBER

PR comments:
user: login: f2c-ci-robot[bot]
created_at: 2025-03-12T10:40:56Z
body: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-03-12T10:42:42Z
body: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=1Panel-dev_1Panel&pullRequest=8135) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [C Maintainability Rating on New Code](https://sonarcloud.io/dashboard?id=1Panel-dev_1Panel&pullRequest=8135) (required ≥ A)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=1Panel-dev_1Panel&pullRequest=8135)

##   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/light_bulb-16px.png '') Catch issues before they fail your Quality Gate with our IDE extension ![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/sonarlint-16px.png '') [SonarQube for IDE](https://www.sonarsource.com/products/sonarlint/features/connected-mode/?referrer=pull-request)


author_association: NONE
user: login: wanghe-fit2cloud
created_at: 2025-03-12T14:42:18Z
body: /approve
author_association: MEMBER
user: login: f2c-ci-robot[bot]
created_at: 2025-03-12T14:42:26Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/1Panel-dev/1Panel/pull/8135#issuecomment-2718131091" title="Approved">wanghe-fit2cloud</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=1Panel-dev%2F1Panel).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/1Panel-dev/1Panel/blob/dev-v2/OWNERS)~~ [wanghe-fit2cloud]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: NONE