mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 23:41:12 +08:00
feat(cli): Enhance CLI functionality and add administrator mode support (#13539)
### What problem does this PR solve? feat(cli): Enhance CLI functionality and add administrator mode support - Modify `parseActivateUser` in `parser.go` to support 'on'/'off' states - Add administrator mode switching and host port settings functionality to `cli.go` - Implement user management API calls in `client.go` ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@@ -19,7 +19,10 @@ package cli
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"github.com/peterh/liner"
|
||||
)
|
||||
|
||||
@@ -127,6 +130,7 @@ func (c *CLI) execute(input string) error {
|
||||
|
||||
func (c *CLI) handleMetaCommand(cmd *Command) error {
|
||||
command := cmd.Params["command"].(string)
|
||||
args, _ := cmd.Params["args"].([]string)
|
||||
|
||||
switch command {
|
||||
case "q", "quit", "exit":
|
||||
@@ -137,6 +141,39 @@ func (c *CLI) handleMetaCommand(cmd *Command) error {
|
||||
case "c", "clear":
|
||||
// Clear screen (simple approach)
|
||||
fmt.Print("\033[H\033[2J")
|
||||
case "admin":
|
||||
c.client.ServerType = "admin"
|
||||
c.client.HTTPClient.Port = 9381
|
||||
c.prompt = "RAGFlow(admin)> "
|
||||
fmt.Println("Switched to ADMIN mode (port 9381)")
|
||||
case "user":
|
||||
c.client.ServerType = "user"
|
||||
c.client.HTTPClient.Port = 9380
|
||||
c.prompt = "RAGFlow> "
|
||||
fmt.Println("Switched to USER mode (port 9380)")
|
||||
case "host":
|
||||
if len(args) == 0 {
|
||||
fmt.Printf("Current host: %s\n", c.client.HTTPClient.Host)
|
||||
} else {
|
||||
c.client.HTTPClient.Host = args[0]
|
||||
fmt.Printf("Host set to: %s\n", args[0])
|
||||
}
|
||||
case "port":
|
||||
if len(args) == 0 {
|
||||
fmt.Printf("Current port: %d\n", c.client.HTTPClient.Port)
|
||||
} else {
|
||||
port, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid port number: %s", args[0])
|
||||
}
|
||||
if port < 1 || port > 65535 {
|
||||
return fmt.Errorf("port must be between 1 and 65535")
|
||||
}
|
||||
c.client.HTTPClient.Port = port
|
||||
fmt.Printf("Port set to: %d\n", port)
|
||||
}
|
||||
case "status":
|
||||
fmt.Printf("Server: %s:%d (mode: %s)\n", c.client.HTTPClient.Host, c.client.HTTPClient.Port, c.client.ServerType)
|
||||
default:
|
||||
return fmt.Errorf("unknown meta command: \\%s", command)
|
||||
}
|
||||
@@ -148,13 +185,39 @@ func (c *CLI) printHelp() {
|
||||
RAGFlow CLI Help
|
||||
================
|
||||
|
||||
SQL Commands:
|
||||
Meta Commands:
|
||||
\admin - Switch to ADMIN mode (port 9381)
|
||||
\user - Switch to USER mode (port 9380)
|
||||
\host [ip] - Show or set server host (default: 127.0.0.1)
|
||||
\port [num] - Show or set server port (default: 9380 for user, 9381 for admin)
|
||||
\status - Show current connection status
|
||||
\? or \h - Show this help
|
||||
\q or \quit - Exit CLI
|
||||
\c or \clear - Clear screen
|
||||
|
||||
SQL Commands (User Mode):
|
||||
LOGIN USER 'email'; - Login as user
|
||||
REGISTER USER 'name' AS 'nickname' PASSWORD 'pwd'; - Register new user
|
||||
SHOW VERSION; - Show version info
|
||||
SHOW CURRENT USER; - Show current user
|
||||
PING; - Ping server
|
||||
LIST DATASETS; - List user datasets
|
||||
LIST AGENTS; - List user agents
|
||||
LIST CHATS; - List user chats
|
||||
LIST MODEL PROVIDERS; - List model providers
|
||||
LIST DEFAULT MODELS; - List default models
|
||||
|
||||
SQL Commands (Admin Mode):
|
||||
LOGIN USER 'email'; - Login as admin
|
||||
LIST USERS; - List all users
|
||||
SHOW USER 'email'; - Show user details
|
||||
CREATE USER 'email' 'password'; - Create new user
|
||||
DROP USER 'email'; - Delete user
|
||||
ALTER USER PASSWORD 'email' 'new_password'; - Change user password
|
||||
ALTER USER ACTIVE 'email' on/off; - Activate/deactivate user
|
||||
GRANT ADMIN 'email'; - Grant admin role
|
||||
REVOKE ADMIN 'email'; - Revoke admin role
|
||||
LIST SERVICES; - List services
|
||||
SHOW SERVICE <id>; - Show service details
|
||||
PING; - Ping server
|
||||
... and many more
|
||||
|
||||
@@ -172,3 +235,22 @@ For more information, see documentation.
|
||||
func (c *CLI) Cleanup() {
|
||||
fmt.Println("\nCleaning up...")
|
||||
}
|
||||
|
||||
// RunInteractive runs the CLI in interactive mode
|
||||
func RunInteractive() error {
|
||||
cli, err := NewCLI()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create CLI: %v", err)
|
||||
}
|
||||
|
||||
// Handle interrupt signal
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-sigChan
|
||||
cli.Cleanup()
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
return cli.Run()
|
||||
}
|
||||
|
||||
@@ -38,27 +38,130 @@ type RAGFlowClient struct {
|
||||
|
||||
// NewRAGFlowClient creates a new RAGFlow client
|
||||
func NewRAGFlowClient(serverType string) *RAGFlowClient {
|
||||
httpClient := NewHTTPClient()
|
||||
// Set port from configuration file based on server type
|
||||
if serverType == "admin" {
|
||||
httpClient.Port = 9381
|
||||
} else {
|
||||
httpClient.Port = 9380
|
||||
}
|
||||
|
||||
return &RAGFlowClient{
|
||||
HTTPClient: NewHTTPClient(),
|
||||
HTTPClient: httpClient,
|
||||
ServerType: serverType,
|
||||
}
|
||||
}
|
||||
|
||||
// LoginUser performs user login
|
||||
func (c *RAGFlowClient) LoginUser(cmd *Command) error {
|
||||
// LoginUserInteractive performs interactive login with username and password
|
||||
func (c *RAGFlowClient) LoginUserInteractive(username, password string) error {
|
||||
// First, ping the server to check if it's available
|
||||
resp, err := c.HTTPClient.Request("GET", "/system/ping", false, "web", nil, nil)
|
||||
// For admin mode, use /admin/ping with useAPIBase=true
|
||||
// For user mode, use /system/ping with useAPIBase=false
|
||||
var pingPath string
|
||||
var useAPIBase bool
|
||||
if c.ServerType == "admin" {
|
||||
pingPath = "/admin/ping"
|
||||
useAPIBase = true
|
||||
} else {
|
||||
pingPath = "/system/ping"
|
||||
useAPIBase = false
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("GET", pingPath, useAPIBase, "web", nil, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
fmt.Println("Can't access server for login (connection failed)")
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 || string(resp.Body) != "pong" {
|
||||
if resp.StatusCode != 200 {
|
||||
fmt.Println("Server is down")
|
||||
return fmt.Errorf("server is down")
|
||||
}
|
||||
|
||||
// Check response - admin returns JSON with message "PONG", user returns plain "pong"
|
||||
resJSON, err := resp.JSON()
|
||||
if err == nil {
|
||||
// Admin mode returns {"code":0,"message":"PONG"}
|
||||
if msg, ok := resJSON["message"].(string); !ok || msg != "PONG" {
|
||||
fmt.Println("Server is down")
|
||||
return fmt.Errorf("server is down")
|
||||
}
|
||||
} else {
|
||||
// User mode returns plain "pong"
|
||||
if string(resp.Body) != "pong" {
|
||||
fmt.Println("Server is down")
|
||||
return fmt.Errorf("server is down")
|
||||
}
|
||||
}
|
||||
|
||||
// If password is not provided, prompt for it
|
||||
if password == "" {
|
||||
fmt.Printf("password for %s: ", username)
|
||||
var err error
|
||||
password, err = readPassword()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read password: %w", err)
|
||||
}
|
||||
password = strings.TrimSpace(password)
|
||||
}
|
||||
|
||||
// Login
|
||||
token, err := c.loginUser(username, password)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
fmt.Println("Can't access server for login (connection failed)")
|
||||
return err
|
||||
}
|
||||
|
||||
c.HTTPClient.LoginToken = token
|
||||
fmt.Printf("Login user %s successfully\n", username)
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoginUser performs user login
|
||||
func (c *RAGFlowClient) LoginUser(cmd *Command) error {
|
||||
// First, ping the server to check if it's available
|
||||
// For admin mode, use /admin/ping with useAPIBase=true
|
||||
// For user mode, use /system/ping with useAPIBase=false
|
||||
var pingPath string
|
||||
var useAPIBase bool
|
||||
if c.ServerType == "admin" {
|
||||
pingPath = "/admin/ping"
|
||||
useAPIBase = true
|
||||
} else {
|
||||
pingPath = "/system/ping"
|
||||
useAPIBase = false
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("GET", pingPath, useAPIBase, "web", nil, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
fmt.Println("Can't access server for login (connection failed)")
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
fmt.Println("Server is down")
|
||||
return fmt.Errorf("server is down")
|
||||
}
|
||||
|
||||
// Check response - admin returns JSON with message "PONG", user returns plain "pong"
|
||||
resJSON, err := resp.JSON()
|
||||
if err == nil {
|
||||
// Admin mode returns {"code":0,"message":"PONG"}
|
||||
if msg, ok := resJSON["message"].(string); !ok || msg != "PONG" {
|
||||
fmt.Println("Server is down")
|
||||
return fmt.Errorf("server is down")
|
||||
}
|
||||
} else {
|
||||
// User mode returns plain "pong"
|
||||
if string(resp.Body) != "pong" {
|
||||
fmt.Println("Server is down")
|
||||
return fmt.Errorf("server is down")
|
||||
}
|
||||
}
|
||||
|
||||
email, ok := cmd.Params["email"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("email not provided")
|
||||
@@ -503,8 +606,347 @@ func (c *RAGFlowClient) ExecuteCommand(cmd *Command) (map[string]interface{}, er
|
||||
return c.ListDatasets(cmd)
|
||||
case "search_on_datasets":
|
||||
return c.SearchOnDatasets(cmd)
|
||||
case "list_users":
|
||||
return c.ListUsers(cmd)
|
||||
case "grant_admin":
|
||||
return nil, c.GrantAdmin(cmd)
|
||||
case "revoke_admin":
|
||||
return nil, c.RevokeAdmin(cmd)
|
||||
case "show_current_user":
|
||||
return c.ShowCurrentUser(cmd)
|
||||
case "create_user":
|
||||
return nil, c.CreateUser(cmd)
|
||||
case "activate_user":
|
||||
return nil, c.ActivateUser(cmd)
|
||||
case "alter_user":
|
||||
return nil, c.AlterUserPassword(cmd)
|
||||
case "drop_user":
|
||||
return nil, c.DropUser(cmd)
|
||||
// TODO: Implement other commands
|
||||
default:
|
||||
return nil, fmt.Errorf("command '%s' would be executed with API", cmd.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// ListUsers lists all users (admin mode only)
|
||||
// Returns (result_map, error) - result_map is non-nil for benchmark mode
|
||||
func (c *RAGFlowClient) ListUsers(cmd *Command) (map[string]interface{}, error) {
|
||||
if c.ServerType != "admin" {
|
||||
return nil, fmt.Errorf("this command is only allowed in ADMIN mode")
|
||||
}
|
||||
|
||||
// Check for benchmark iterations
|
||||
iterations := 1
|
||||
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
||||
iterations = val
|
||||
}
|
||||
|
||||
if iterations > 1 {
|
||||
// Benchmark mode - return raw result for benchmark stats
|
||||
return c.HTTPClient.RequestWithIterations("GET", "/admin/users", true, "admin", nil, nil, iterations)
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("GET", "/admin/users", true, "admin", nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list users: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to list users: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
resJSON, err := resp.JSON()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid JSON response: %w", err)
|
||||
}
|
||||
|
||||
code, ok := resJSON["code"].(float64)
|
||||
if !ok || code != 0 {
|
||||
msg, _ := resJSON["message"].(string)
|
||||
return nil, fmt.Errorf("failed to list users: %s", msg)
|
||||
}
|
||||
|
||||
data, ok := resJSON["data"].([]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid response format")
|
||||
}
|
||||
|
||||
// Convert to slice of maps and remove sensitive fields
|
||||
tableData := make([]map[string]interface{}, 0, len(data))
|
||||
for _, item := range data {
|
||||
if itemMap, ok := item.(map[string]interface{}); ok {
|
||||
// Remove sensitive fields
|
||||
delete(itemMap, "password")
|
||||
delete(itemMap, "access_token")
|
||||
tableData = append(tableData, itemMap)
|
||||
}
|
||||
}
|
||||
|
||||
PrintTableSimple(tableData)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GrantAdmin grants admin privileges to a user (admin mode only)
|
||||
func (c *RAGFlowClient) GrantAdmin(cmd *Command) error {
|
||||
if c.ServerType != "admin" {
|
||||
return fmt.Errorf("this command is only allowed in ADMIN mode")
|
||||
}
|
||||
|
||||
userName, ok := cmd.Params["user_name"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("user_name not provided")
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("PUT", fmt.Sprintf("/admin/users/%s/admin", userName), true, "admin", nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to grant admin: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to grant admin: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
resJSON, err := resp.JSON()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid JSON response: %w", err)
|
||||
}
|
||||
|
||||
code, ok := resJSON["code"].(float64)
|
||||
if !ok || code != 0 {
|
||||
msg, _ := resJSON["message"].(string)
|
||||
return fmt.Errorf("failed to grant admin: %s", msg)
|
||||
}
|
||||
|
||||
fmt.Printf("Admin role granted to user: %s\n", userName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevokeAdmin revokes admin privileges from a user (admin mode only)
|
||||
func (c *RAGFlowClient) RevokeAdmin(cmd *Command) error {
|
||||
if c.ServerType != "admin" {
|
||||
return fmt.Errorf("this command is only allowed in ADMIN mode")
|
||||
}
|
||||
|
||||
userName, ok := cmd.Params["user_name"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("user_name not provided")
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("DELETE", fmt.Sprintf("/admin/users/%s/admin", userName), true, "admin", nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to revoke admin: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to revoke admin: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
resJSON, err := resp.JSON()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid JSON response: %w", err)
|
||||
}
|
||||
|
||||
code, ok := resJSON["code"].(float64)
|
||||
if !ok || code != 0 {
|
||||
msg, _ := resJSON["message"].(string)
|
||||
return fmt.Errorf("failed to revoke admin: %s", msg)
|
||||
}
|
||||
|
||||
fmt.Printf("Admin role revoked from user: %s\n", userName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShowCurrentUser shows the current logged-in user information
|
||||
// TODO: Implement showing current user information when API is available
|
||||
func (c *RAGFlowClient) ShowCurrentUser(cmd *Command) (map[string]interface{}, error) {
|
||||
// TODO: Call the appropriate API to get current user information
|
||||
// Currently there is no /admin/user/info or /user/info API available
|
||||
// The /admin/auth API only verifies authorization, does not return user info
|
||||
return nil, fmt.Errorf("command 'SHOW CURRENT USER' is not yet implemented")
|
||||
}
|
||||
|
||||
// CreateUser creates a new user (admin mode only)
|
||||
func (c *RAGFlowClient) CreateUser(cmd *Command) error {
|
||||
if c.ServerType != "admin" {
|
||||
return fmt.Errorf("this command is only allowed in ADMIN mode")
|
||||
}
|
||||
|
||||
userName, ok := cmd.Params["user_name"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("user_name not provided")
|
||||
}
|
||||
|
||||
password, ok := cmd.Params["password"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("password not provided")
|
||||
}
|
||||
|
||||
// Encrypt password using RSA
|
||||
encryptedPassword, err := EncryptPassword(password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to encrypt password: %w", err)
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"username": userName,
|
||||
"password": encryptedPassword,
|
||||
"role": "user",
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("POST", "/admin/users", true, "admin", nil, payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create user: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to create user: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
resJSON, err := resp.JSON()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid JSON response: %w", err)
|
||||
}
|
||||
|
||||
code, ok := resJSON["code"].(float64)
|
||||
if !ok || code != 0 {
|
||||
msg, _ := resJSON["message"].(string)
|
||||
return fmt.Errorf("failed to create user: %s", msg)
|
||||
}
|
||||
|
||||
fmt.Printf("User created successfully: %s\n", userName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActivateUser activates or deactivates a user (admin mode only)
|
||||
func (c *RAGFlowClient) ActivateUser(cmd *Command) error {
|
||||
if c.ServerType != "admin" {
|
||||
return fmt.Errorf("this command is only allowed in ADMIN mode")
|
||||
}
|
||||
|
||||
userName, ok := cmd.Params["user_name"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("user_name not provided")
|
||||
}
|
||||
|
||||
activateStatus, ok := cmd.Params["activate_status"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("activate_status not provided")
|
||||
}
|
||||
|
||||
// Validate activate_status
|
||||
if activateStatus != "on" && activateStatus != "off" {
|
||||
return fmt.Errorf("activate_status must be 'on' or 'off'")
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"activate_status": activateStatus,
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("PUT", fmt.Sprintf("/admin/users/%s/activate", userName), true, "admin", nil, payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update user activate status: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to update user activate status: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
resJSON, err := resp.JSON()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid JSON response: %w", err)
|
||||
}
|
||||
|
||||
code, ok := resJSON["code"].(float64)
|
||||
if !ok || code != 0 {
|
||||
msg, _ := resJSON["message"].(string)
|
||||
return fmt.Errorf("failed to update user activate status: %s", msg)
|
||||
}
|
||||
|
||||
fmt.Printf("User '%s' activate status set to '%s'\n", userName, activateStatus)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AlterUserPassword changes a user's password (admin mode only)
|
||||
func (c *RAGFlowClient) AlterUserPassword(cmd *Command) error {
|
||||
if c.ServerType != "admin" {
|
||||
return fmt.Errorf("this command is only allowed in ADMIN mode")
|
||||
}
|
||||
|
||||
userName, ok := cmd.Params["user_name"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("user_name not provided")
|
||||
}
|
||||
|
||||
password, ok := cmd.Params["password"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("password not provided")
|
||||
}
|
||||
|
||||
// Encrypt password using RSA
|
||||
encryptedPassword, err := EncryptPassword(password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to encrypt password: %w", err)
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"new_password": encryptedPassword,
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("PUT", fmt.Sprintf("/admin/users/%s/password", userName), true, "admin", nil, payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to change user password: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to change user password: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
resJSON, err := resp.JSON()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid JSON response: %w", err)
|
||||
}
|
||||
|
||||
code, ok := resJSON["code"].(float64)
|
||||
if !ok || code != 0 {
|
||||
msg, _ := resJSON["message"].(string)
|
||||
return fmt.Errorf("failed to change user password: %s", msg)
|
||||
}
|
||||
|
||||
fmt.Printf("Password changed for user: %s\n", userName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DropUser deletes a user (admin mode only)
|
||||
func (c *RAGFlowClient) DropUser(cmd *Command) error {
|
||||
if c.ServerType != "admin" {
|
||||
return fmt.Errorf("this command is only allowed in ADMIN mode")
|
||||
}
|
||||
|
||||
userName, ok := cmd.Params["user_name"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("user_name not provided")
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Request("DELETE", fmt.Sprintf("/admin/users/%s", userName), true, "admin", nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete user: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to delete user: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
resJSON, err := resp.JSON()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid JSON response: %w", err)
|
||||
}
|
||||
|
||||
code, ok := resJSON["code"].(float64)
|
||||
if !ok || code != 0 {
|
||||
msg, _ := resJSON["message"].(string)
|
||||
return fmt.Errorf("failed to delete user: %s", msg)
|
||||
}
|
||||
|
||||
fmt.Printf("User deleted: %s\n", userName)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -950,10 +950,11 @@ func (p *Parser) parseActivateUser() (*Command, error) {
|
||||
}
|
||||
|
||||
p.nextToken()
|
||||
status, err := p.parseIdentifier()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Accept 'on' or 'off' as identifier
|
||||
status := p.curToken.Value
|
||||
if status != "on" && status != "off" {
|
||||
return nil, fmt.Errorf("expected 'on' or 'off', got %s", p.curToken.Value)
|
||||
}
|
||||
|
||||
cmd := NewCommand("activate_user")
|
||||
cmd.Params["user_name"] = userName
|
||||
@@ -962,7 +963,7 @@ func (p *Parser) parseActivateUser() (*Command, error) {
|
||||
p.nextToken()
|
||||
if err := p.expectSemicolon(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user