Repository: 1Panel-dev/1Panel
Pull request #8378: fix: Fix the mysql root account permission switchover exception
Author: login: ssongliu
Labels: name: do-not-merge/release-note-label-needed
name: dev
name: approved
Created: 2025-04-11T02:40:39Z | Merged: 2025-04-11T07:08:02Z



Diff:
diff --git a/backend/utils/mysql/client/local.go b/backend/utils/mysql/client/local.go
index dd9376ad5833..e838882a9e12 100644
--- a/backend/utils/mysql/client/local.go
+++ b/backend/utils/mysql/client/local.go
@@ -188,19 +188,18 @@ func (r *Local) ChangeAccess(info AccessChangeInfo) error {
 		info.Name = "*"
 		info.Password = r.Password
 	}
-	if info.Permission == info.OldPermission {
-		return nil
-	}
-	if err := r.Delete(DeleteInfo{
-		Version:     info.Version,
-		Username:    info.Username,
-		Permission:  info.OldPermission,
-		ForceDelete: true,
-		Timeout:     300}); err != nil {
-		return err
-	}
-	if info.Username == "root" {
-		return nil
+	if info.Permission != info.OldPermission {
+		if err := r.Delete(DeleteInfo{
+			Version:     info.Version,
+			Username:    info.Username,
+			Permission:  info.OldPermission,
+			ForceDelete: true,
+			Timeout:     300}); err != nil {
+			return err
+		}
+		if info.Username == "root" {
+			return nil
+		}
 	}
 	if err := r.CreateUser(CreateInfo{
 		Name:       info.Name,
diff --git a/backend/utils/mysql/client/remote.go b/backend/utils/mysql/client/remote.go
index 794bb0e9df8b..0040254c75f7 100644
--- a/backend/utils/mysql/client/remote.go
+++ b/backend/utils/mysql/client/remote.go
@@ -199,19 +199,18 @@ func (r *Remote) ChangeAccess(info AccessChangeInfo) error {
 		info.Name = "*"
 		info.Password = r.Password
 	}
-	if info.Permission == info.OldPermission {
-		return nil
-	}
-	if err := r.Delete(DeleteInfo{
-		Version:     info.Version,
-		Username:    info.Username,
-		Permission:  info.OldPermission,
-		ForceDelete: true,
-		Timeout:     300}); err != nil {
-		return err
-	}
-	if info.Username == "root" {
-		return nil
+	if info.Permission != info.OldPermission {
+		if err := r.Delete(DeleteInfo{
+			Version:     info.Version,
+			Username:    info.Username,
+			Permission:  info.OldPermission,
+			ForceDelete: true,
+			Timeout:     300}); err != nil {
+			return err
+		}
+		if info.Username == "root" {
+			return nil
+		}
 	}
 	if err := r.CreateUser(CreateInfo{
 		Name:       info.Name,
diff --git a/frontend/src/views/database/mysql/password/index.vue b/frontend/src/views/database/mysql/password/index.vue
index 1093f21959c9..a2a09ec29751 100644
--- a/frontend/src/views/database/mysql/password/index.vue
+++ b/frontend/src/views/database/mysql/password/index.vue
@@ -74,6 +74,8 @@ const changeVisible = ref(false);
 type FormInstance = InstanceType<typeof ElForm>;
 const changeFormRef = ref<FormInstance>();
 const title = ref();
+const oldPrivilege = ref();
+const oldPrivilegeIPs = ref();
 const changeForm = reactive({
     id: 0,
     from: '',
@@ -124,6 +126,8 @@ const acceptParams = (params: DialogProps): void => {
     changeForm.privilegeIPs = params.privilegeIPs;
     changeForm.value = params.value;
     changeVisible.value = true;
+    oldPrivilege.value = params.privilege;
+    oldPrivilegeIPs.value = params.privilegeIPs;
 };
 const emit = defineEmits<{ (e: 'search'): void }>();
 
@@ -167,6 +171,10 @@ const submitChangeInfo = async (formEl: FormInstance | undefined) => {
             }
             return;
         }
+        if (changeForm.privilege === oldPrivilege.value && changeForm.privilegeIPs === oldPrivilegeIPs.value) {
+            changeVisible.value = false;
+            return;
+        }
         if (changeForm.privilege !== 'ip') {
             param.value = changeForm.privilege;
         } else {


Reviews:
user: login: wanghe-fit2cloud
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-11T02:41:01Z
user: login: wanghe-fit2cloud
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-11T02:41:10Z
user: login: wanghe-fit2cloud
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-11T02:41:24Z
user: login: wanghe-fit2cloud
body: /lgtm
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-11T07:06:19Z

Review comments:
diff_hunk: @@ -188,19 +188,18 @@ func (r *Local) ChangeAccess(info AccessChangeInfo) error {
 		info.Name = "*"
 		info.Password = r.Password
 	}
-	if info.Permission == info.OldPermission {
-		return nil
-	}
-	if err := r.Delete(DeleteInfo{
-		Version:     info.Version,
-		Username:    info.Username,
-		Permission:  info.OldPermission,
-		ForceDelete: true,
-		Timeout:     300}); err != nil {
-		return err
-	}
-	if info.Username == "root" {
-		return nil
+	if info.Permission != info.OldPermission {
+		if err := r.Delete(DeleteInfo{
+			Version:     info.Version,
+			Username:    info.Username,
+			Permission:  info.OldPermission,
+			ForceDelete: true,
+			Timeout:     300}); err != nil {
+			return err
+		}
+		if info.Username == "root" {
+			return nil
+		}
 	}
 	if err := r.CreateUser(CreateInfo{
 		Name:       info.Name,
path: backend/utils/mysql/client/local.go
user: login: wanghe-fit2cloud
body: The given code snippet contains two main logic branches:

1. **Regular Branch:**
   - This branch checks if `info.Permission` is equal to `info.OldPermission`.
   - If they are equal, it returns `nil`, effectively skipping the deletion step.
   
2. **Special Case for Root User:**
   - If the current user (`info.Username`) is "root", it also skips the deletion process.

### Potential Issues and Improvements:

1. **Code Reorganization:**
   - It might be beneficial to extract the common logic of checking if `info.Permission == info.OldPermission` into a separate function call to improve readability and maintainability.

2. **Error Handling:**
   - The function does not handle errors returned by `CreateUser`. Although it catches errors from `DeleteInfo`, handling other functions should also be considered within this scope.

3. **Documentation/Comments:**
   - Adding comments explaining each section and key decisions could help clarify the purpose of different parts of the code, especially for others who may read this later.

4. **Variable Naming:**
   - Consistent naming conventions could make the code more readable, such as using camelCase for variable names rather than underscores.

Overall, the overall structure looks clean and well-organized, but these minor improvements can enhance its clarity and robustness.
created_at: 2025-04-11T02:41:01Z
author_association: MEMBER
diff_hunk: @@ -199,19 +199,18 @@ func (r *Remote) ChangeAccess(info AccessChangeInfo) error {
 		info.Name = "*"
 		info.Password = r.Password
 	}
-	if info.Permission == info.OldPermission {
-		return nil
-	}
-	if err := r.Delete(DeleteInfo{
-		Version:     info.Version,
-		Username:    info.Username,
-		Permission:  info.OldPermission,
-		ForceDelete: true,
-		Timeout:     300}); err != nil {
-		return err
-	}
-	if info.Username == "root" {
-		return nil
+	if info.Permission != info.OldPermission {
+		if err := r.Delete(DeleteInfo{
+			Version:     info.Version,
+			Username:    info.Username,
+			Permission:  info.OldPermission,
+			ForceDelete: true,
+			Timeout:     300}); err != nil {
+			return err
+		}
+		if info.Username == "root" {
+			return nil
+		}
 	}
 	if err := r.CreateUser(CreateInfo{
 		Name:       info.Name,
path: backend/utils/mysql/client/remote.go
user: login: wanghe-fit2cloud
body: The provided code has several optimizations and corrections:

1. The `if` statement that checks if `info.Permission == info.OldPermission` is unnecessary if it returns before calling `r.Delete`. You can move the call to `r.CreateUser` outside this block.

2. There should be no need to create an empty user object (`CreateInfo{}`) when creating the root user since the `Name` field is already set. This redundancy can be removed.

3. Ensure that there are proper error handling around critical operations like `r.CreateUser()` in case of any failure during creation.

This refactored version of the function ensures cleaner logic by reducing nested structures where possible:

```
func (r *Remote) ChangeAccess(info AccessChangeInfo) error {
	if info.Username == "root" && info.Permission != info.OldPermission {
		return nil
	}

	if err := r.Delete(DeleteInfo{
		Version:     info.Version,
		Username:    info.Username,
		Permission:  info.OldPermission,
		ForceDelete: true,
		Timeout:     300}); err != nil {
		return err
	}

	return r.CreateUser(CreateInfo{Name: info.Name})
}
```
created_at: 2025-04-11T02:41:10Z
author_association: MEMBER
diff_hunk: @@ -167,6 +171,10 @@ const submitChangeInfo = async (formEl: FormInstance | undefined) => {
             }
             return;
         }
+        if (changeForm.privilege === oldPrivilege.value && changeForm.privilegeIPs === oldPrivilegeIPs.value) {
+            changeVisible.value = false;
+            return;
+        }
         if (changeForm.privilege !== 'ip') {
             param.value = changeForm.privilege;
         } else {
path: frontend/src/views/database/mysql/password/index.vue
user: login: wanghe-fit2cloud
body: There are no major irregularities or obvious issues in this code snippet, but there are some areas that can be optimized or improved:

1. **Consolidate Code**: The two `else` blocks under the conditional checks can be combined to reduce redundancy.

2. **Empty Check**: It's good practice to add an empty string check before comparing strings to avoid unexpected behavior when one of them might be null or undefined.

3. **Simplify Boolean Logic**: You could simplify the boolean logic by checking for equality between arrays explicitly instead of comparing their reference values.

4. **Use Object Destructuring**: If these references will always contain properties with the same names, you could destructure them directly to make the code slightly more concise.

Here is a revised version incorporating these suggestions:

```javascript
if (formEl && formEl.validate(async valid => {
  if (!valid) {            
      return;
  }      
  await validateEmail(changeForm.from);

  if (changeForm.privilege === oldPrivilege.value && equalArrays(changeForm.privilegeIPs, oldPrivilegeIPs.value)) {
      changeVisible.value = false;
      return;
  }

  if (changeForm.privilege !== 'ip') {
      param.value = changeForm.privilege;
  } else {
      // continue processing
  }
})):
```

**Function `equalArrays`:**
If you don't already have such a function, here it is as a helper to compare array elements:

```javascript
function equalArrays(a, b) {
  if (a.length !== b.length)
    return false;

  for (let i = 0; i < a.length; i++) 
      if (a[i] !== b[i])    
          return false;

  return true;
}
```

These improvements should enhance readability, maintainability, and potentially performance marginally.
created_at: 2025-04-11T02:41:23Z
author_association: MEMBER

PR comments:
user: login: f2c-ci-robot[bot]
created_at: 2025-04-11T02:40:43Z
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-04-11T02:41:53Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=1Panel-dev_1Panel&pullRequest=8378) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=1Panel-dev_1Panel&pullRequest=8378&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=1Panel-dev_1Panel&pullRequest=8378&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=1Panel-dev_1Panel&pullRequest=8378&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=1Panel-dev_1Panel&pullRequest=8378&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [33.3% Duplication on New Code](https://sonarcloud.io/component_measures?id=1Panel-dev_1Panel&pullRequest=8378&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=1Panel-dev_1Panel&pullRequest=8378)


author_association: NONE
user: login: wanghe-fit2cloud
created_at: 2025-04-11T07:06:24Z
body: /approve
author_association: MEMBER
user: login: f2c-ci-robot[bot]
created_at: 2025-04-11T07:06:31Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/1Panel-dev/1Panel/pull/8378#issuecomment-2796038904" 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/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