mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-04-23 12:16:18 +08:00
fix(dao): Remove unnecessary status filter conditions in user queries (#13698)
### What problem does this PR solve? Fix: Enhanced the user deletion function to return detailed deletion information. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -266,12 +266,18 @@ func (h *Handler) DeleteUser(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.DeleteUser(username); err != nil {
|
||||
result, err := h.service.DeleteUser(username)
|
||||
if err != nil {
|
||||
errorResponse(c, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
successNoData(c, "User deleted successfully")
|
||||
detailsMsg := "Successfully deleted user. Details:\n"
|
||||
for _, detail := range result.DeletedDetails {
|
||||
detailsMsg += detail + "\n"
|
||||
}
|
||||
|
||||
successNoData(c, detailsMsg)
|
||||
}
|
||||
|
||||
// ChangePasswordHTTPRequest change password request
|
||||
|
||||
@ -495,32 +495,49 @@ func (s *Service) GetUserDetails(username string) (map[string]interface{}, error
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteUserResult
|
||||
type DeleteUserResult struct {
|
||||
Username string `json:"username"`
|
||||
TenantLLMCount int `json:"tenant_llm_count"`
|
||||
LangfuseCount int `json:"langfuse_count"`
|
||||
MetadataTable string `json:"metadata_table"`
|
||||
TenantCount int `json:"tenant_count"`
|
||||
UserTenantCount int `json:"user_tenant_count"`
|
||||
UserCount int `json:"user_count"`
|
||||
DeletedDetails []string `json:"deleted_details"`
|
||||
}
|
||||
|
||||
// DeleteUser delete user with cascade delete of all related data
|
||||
// Parameters:
|
||||
// - username: email address of the user to delete
|
||||
//
|
||||
// Returns:
|
||||
// - *DeleteUserResult
|
||||
// - error: error message
|
||||
func (s *Service) DeleteUser(username string) error {
|
||||
func (s *Service) DeleteUser(username string) (*DeleteUserResult, error) {
|
||||
result := &DeleteUserResult{
|
||||
Username: username,
|
||||
DeletedDetails: []string{fmt.Sprintf("Drop user: %s", username)},
|
||||
}
|
||||
userList, err := s.userDAO.ListByEmail(username)
|
||||
if err != nil || len(userList) == 0 {
|
||||
return fmt.Errorf("User '%s' not found", username)
|
||||
return nil, fmt.Errorf("User '%s' not found", username)
|
||||
}
|
||||
|
||||
if len(userList) > 1 {
|
||||
return fmt.Errorf("Exist more than 1 user: %s!", username)
|
||||
return nil, fmt.Errorf("Exist more than 1 user: %s!", username)
|
||||
}
|
||||
|
||||
user := userList[0]
|
||||
|
||||
// Check if user is active - cannot delete active users
|
||||
if user.IsActive == "1" {
|
||||
return fmt.Errorf("User '%s' is active and can't be deleted. Please deactivate the user first", username)
|
||||
return nil, fmt.Errorf("User '%s' is active and can't be deleted. Please deactivate the user first", username)
|
||||
}
|
||||
|
||||
// Check if user is superuser - cannot delete admin accounts
|
||||
if user.IsSuperuser != nil && *user.IsSuperuser {
|
||||
return fmt.Errorf("Cannot delete admin account")
|
||||
return nil, fmt.Errorf("Cannot delete admin account")
|
||||
}
|
||||
|
||||
// Get user-tenant relations
|
||||
@ -541,7 +558,7 @@ func (s *Service) DeleteUser(username string) error {
|
||||
// Start transaction for cascade delete
|
||||
tx := dao.DB.Begin()
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to begin transaction: %w", tx.Error)
|
||||
return nil, fmt.Errorf("failed to begin transaction: %w", tx.Error)
|
||||
}
|
||||
|
||||
// Rollback helper function
|
||||
@ -551,6 +568,7 @@ func (s *Service) DeleteUser(username string) error {
|
||||
}
|
||||
}
|
||||
|
||||
result.DeletedDetails = append(result.DeletedDetails, "Start to delete owned tenant.")
|
||||
// Delete owned tenant data
|
||||
if ownedTenantID != "" {
|
||||
// 1. Get knowledge base IDs
|
||||
@ -628,36 +646,61 @@ func (s *Service) DeleteUser(username string) error {
|
||||
}
|
||||
}
|
||||
|
||||
var tenantLLMCount int64
|
||||
tx.Model(&model.TenantLLM{}).Where("tenant_id = ?", ownedTenantID).Count(&tenantLLMCount)
|
||||
result.TenantLLMCount = int(tenantLLMCount)
|
||||
result.DeletedDetails = append(result.DeletedDetails, fmt.Sprintf("- Deleted %d tenant-LLM records.", tenantLLMCount))
|
||||
|
||||
result.LangfuseCount = 0
|
||||
result.DeletedDetails = append(result.DeletedDetails, fmt.Sprintf("- Deleted %d langfuse records.", result.LangfuseCount))
|
||||
|
||||
metadataTableName := fmt.Sprintf("ragflow_doc_meta_%s", ownedTenantID[:32])
|
||||
result.MetadataTable = metadataTableName
|
||||
result.DeletedDetails = append(result.DeletedDetails, fmt.Sprintf("- Deleted metadata table %s.", metadataTableName))
|
||||
|
||||
// 13. Delete tenant LLM configurations
|
||||
if delErr := tx.Unscoped().Where("tenant_id = ?", ownedTenantID).Delete(&model.TenantLLM{}); delErr.Error != nil {
|
||||
logger.Warn("failed to delete tenant LLM", zap.Error(delErr.Error))
|
||||
}
|
||||
|
||||
var tenantCount int64
|
||||
tx.Model(&model.Tenant{}).Where("id = ?", ownedTenantID).Count(&tenantCount)
|
||||
result.TenantCount = int(tenantCount)
|
||||
// 14. Delete tenant
|
||||
if delErr := tx.Unscoped().Where("id = ?", ownedTenantID).Delete(&model.Tenant{}); delErr.Error != nil {
|
||||
logger.Warn("failed to delete tenant", zap.Error(delErr.Error))
|
||||
}
|
||||
result.DeletedDetails = append(result.DeletedDetails, fmt.Sprintf("- Deleted %d tenant.", result.TenantCount))
|
||||
}
|
||||
|
||||
var userTenantCount int64
|
||||
tx.Model(&model.UserTenant{}).Where("user_id = ?", user.ID).Count(&userTenantCount)
|
||||
result.UserTenantCount = int(userTenantCount)
|
||||
|
||||
// 15. Delete user-tenant relations
|
||||
if delErr := tx.Unscoped().Where("user_id = ?", user.ID).Delete(&model.UserTenant{}); delErr.Error != nil {
|
||||
logger.Warn("failed to delete user-tenant relations", zap.Error(delErr.Error))
|
||||
}
|
||||
result.DeletedDetails = append(result.DeletedDetails, fmt.Sprintf("- Deleted %d user-tenant records.", result.UserTenantCount))
|
||||
|
||||
result.UserCount = 1
|
||||
// 16. Finally, hard delete user
|
||||
if delErr := tx.Unscoped().Where("id = ?", user.ID).Delete(&model.User{}); delErr.Error != nil {
|
||||
rollbackTx()
|
||||
return fmt.Errorf("failed to delete user: %w", delErr.Error)
|
||||
return nil, fmt.Errorf("failed to delete user: %w", delErr.Error)
|
||||
}
|
||||
result.DeletedDetails = append(result.DeletedDetails, fmt.Sprintf("- Deleted %d user.", result.UserCount))
|
||||
|
||||
// Commit transaction
|
||||
if commitErr := tx.Commit(); commitErr.Error != nil {
|
||||
return fmt.Errorf("failed to commit transaction: %w", commitErr.Error)
|
||||
return nil, fmt.Errorf("failed to commit transaction: %w", commitErr.Error)
|
||||
}
|
||||
|
||||
result.DeletedDetails = append(result.DeletedDetails, "Delete done!")
|
||||
|
||||
logger.Info("Delete user success with all related data", zap.String("username", username))
|
||||
|
||||
return nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ChangePassword change user password
|
||||
|
||||
@ -124,6 +124,6 @@ func (dao *UserDAO) HardDelete(id string) error {
|
||||
// Returns all users matching the given email address
|
||||
func (dao *UserDAO) ListByEmail(email string) ([]*model.User, error) {
|
||||
var users []*model.User
|
||||
err := DB.Where("email = ? AND (status != ? OR status IS NULL)", email, "0").Find(&users).Error
|
||||
err := DB.Where("email = ?", email).Find(&users).Error
|
||||
return users, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user