mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-14 00:48:26 +08:00
Add api tokens commands of go admin cli (#13765)
### What problem does this PR solve? - GENERATE TOKENS OF USER 'xxx@xxx.com' - DROP KEY 'ragflow-yyyyy' OF 'xxx@xxx.com' - LIST KEYS OF 'xxx@xxx.com' ### Type of change - [x] New Feature (non-breaking change which adds functionality) --------- Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
@@ -181,18 +181,18 @@ PY=python3
|
||||
NGINX_CONF_DIR="/etc/nginx/conf.d"
|
||||
if [ -n "$API_PROXY_SCHEME" ]; then
|
||||
if [[ "${API_PROXY_SCHEME}" == "hybrid" ]]; then
|
||||
mv -f "$NGINX_CONF_DIR/ragflow.conf.hybrid" "$NGINX_CONF_DIR/ragflow.conf"
|
||||
cp -f "$NGINX_CONF_DIR/ragflow.conf.hybrid" "$NGINX_CONF_DIR/ragflow.conf"
|
||||
echo "Applied nginx config: ragflow.conf.hybrid"
|
||||
elif [[ "${API_PROXY_SCHEME}" == "go" ]]; then
|
||||
mv -f "$NGINX_CONF_DIR/ragflow.conf.golang" "$NGINX_CONF_DIR/ragflow.conf"
|
||||
cp -f "$NGINX_CONF_DIR/ragflow.conf.golang" "$NGINX_CONF_DIR/ragflow.conf"
|
||||
echo "Applied nginx config: ragflow.conf.golang (default)"
|
||||
else
|
||||
mv -f "$NGINX_CONF_DIR/ragflow.conf.python" "$NGINX_CONF_DIR/ragflow.conf"
|
||||
cp -f "$NGINX_CONF_DIR/ragflow.conf.python" "$NGINX_CONF_DIR/ragflow.conf"
|
||||
echo "Applied nginx config: ragflow.conf.python"
|
||||
fi
|
||||
else
|
||||
# Default to python backend
|
||||
mv -f "$NGINX_CONF_DIR/ragflow.conf.python" "$NGINX_CONF_DIR/ragflow.conf"
|
||||
cp -f "$NGINX_CONF_DIR/ragflow.conf.python" "$NGINX_CONF_DIR/ragflow.conf"
|
||||
echo "Default: applied nginx config: ragflow.conf.python"
|
||||
fi
|
||||
|
||||
|
||||
@@ -870,19 +870,117 @@ func (s *Service) GetUserAgents(username string) ([]map[string]interface{}, erro
|
||||
|
||||
// ListUserAPITokens get user API keys
|
||||
func (s *Service) ListUserAPITokens(username string) ([]map[string]interface{}, error) {
|
||||
// TODO: Implement get API keys
|
||||
return []map[string]interface{}{}, nil
|
||||
// 1. Get user details
|
||||
user, err := s.userDAO.GetByEmail(username)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("user not found: %w", err)
|
||||
}
|
||||
|
||||
// 2. Get user's tenants
|
||||
userTenants, err := s.userTenantDAO.GetByUserID(user.ID)
|
||||
if err != nil || len(userTenants) == 0 {
|
||||
return nil, fmt.Errorf("tenant not found")
|
||||
}
|
||||
|
||||
tenantID := userTenants[0].TenantID
|
||||
|
||||
// 3. Get API tokens by tenant ID
|
||||
tokens, err := s.apiTokenDAO.GetByTenantID(tenantID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get API tokens: %w", err)
|
||||
}
|
||||
|
||||
// 4. Convert to map slice
|
||||
result := make([]map[string]interface{}, 0, len(tokens))
|
||||
for _, token := range tokens {
|
||||
result = append(result, map[string]interface{}{
|
||||
"tenant_id": token.TenantID,
|
||||
"token": token.Token,
|
||||
"beta": token.Beta,
|
||||
"dialog_id": token.DialogID,
|
||||
"source": token.Source,
|
||||
"create_time": token.CreateTime,
|
||||
"create_date": token.CreateDate,
|
||||
"update_time": token.UpdateTime,
|
||||
"update_date": token.UpdateDate,
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GenerateUserAPIToken generate API key for user
|
||||
func (s *Service) GenerateUserAPIToken(username string) (map[string]interface{}, error) {
|
||||
// TODO: Implement generate API key
|
||||
return map[string]interface{}{}, nil
|
||||
// 1. Get user details
|
||||
user, err := s.userDAO.GetByEmail(username)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("user not found: %w", err)
|
||||
}
|
||||
|
||||
// 2. Get user's tenants
|
||||
userTenants, err := s.userTenantDAO.GetByUserID(user.ID)
|
||||
if err != nil || len(userTenants) == 0 {
|
||||
return nil, fmt.Errorf("tenant not found")
|
||||
}
|
||||
|
||||
tenantID := userTenants[0].TenantID
|
||||
|
||||
// 3. Generate API token
|
||||
key := utility.GenerateAPIToken()
|
||||
beta := utility.GenerateBetaAPIToken(key)
|
||||
now := time.Now()
|
||||
nowUnix := now.Unix()
|
||||
|
||||
apiToken := &model.APIToken{
|
||||
TenantID: tenantID,
|
||||
Token: key,
|
||||
Beta: &beta,
|
||||
}
|
||||
apiToken.CreateTime = &nowUnix
|
||||
apiToken.CreateDate = &now
|
||||
|
||||
// 4. Save API token
|
||||
if err := s.apiTokenDAO.Create(apiToken); err != nil {
|
||||
return nil, fmt.Errorf("failed to generate API key: %w", err)
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"tenant_id": tenantID,
|
||||
"token": key,
|
||||
"beta": beta,
|
||||
"create_time": apiToken.CreateTime,
|
||||
"create_date": apiToken.CreateDate,
|
||||
"update_time": apiToken.UpdateTime,
|
||||
"update_date": apiToken.UpdateDate,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteUserAPIToken delete user API key
|
||||
func (s *Service) DeleteUserAPIToken(username, key string) error {
|
||||
// TODO: Implement delete API key
|
||||
// 1. Get user details
|
||||
user, err := s.userDAO.GetByEmail(username)
|
||||
if err != nil {
|
||||
return fmt.Errorf("user not found: %w", err)
|
||||
}
|
||||
|
||||
// 2. Get user's tenants
|
||||
userTenants, err := s.userTenantDAO.GetByUserID(user.ID)
|
||||
if err != nil || len(userTenants) == 0 {
|
||||
return fmt.Errorf("tenant not found")
|
||||
}
|
||||
|
||||
tenantID := userTenants[0].TenantID
|
||||
|
||||
// 3. Delete API token
|
||||
rowsAffected, err := s.apiTokenDAO.DeleteByTenantIDAndToken(tenantID, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete API key: %w", err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("API key not found or could not be deleted")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -983,8 +983,8 @@ func (c *RAGFlowClient) ShowUserPermission(cmd *Command) (ResponseIf, error) {
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// CreateAdminToken generates an API token for a user (admin mode only)
|
||||
func (c *RAGFlowClient) CreateAdminToken(cmd *Command) (ResponseIf, error) {
|
||||
// GenerateAdminToken generates an API token for a user (admin mode only)
|
||||
func (c *RAGFlowClient) GenerateAdminToken(cmd *Command) (ResponseIf, error) {
|
||||
if c.ServerType != "admin" {
|
||||
return nil, fmt.Errorf("this command is only allowed in ADMIN mode")
|
||||
}
|
||||
@@ -1003,7 +1003,7 @@ func (c *RAGFlowClient) CreateAdminToken(cmd *Command) (ResponseIf, error) {
|
||||
return nil, fmt.Errorf("failed to generate token: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
var result CommonResponse
|
||||
var result CommonDataResponse
|
||||
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
||||
return nil, fmt.Errorf("generate token failed: invalid JSON (%w)", err)
|
||||
}
|
||||
@@ -1012,10 +1012,9 @@ func (c *RAGFlowClient) CreateAdminToken(cmd *Command) (ResponseIf, error) {
|
||||
return nil, fmt.Errorf("%s", result.Message)
|
||||
}
|
||||
|
||||
// Remove extra field from data
|
||||
for _, item := range result.Data {
|
||||
delete(item, "extra")
|
||||
}
|
||||
delete(result.Data, "update_date")
|
||||
delete(result.Data, "update_time")
|
||||
delete(result.Data, "create_time")
|
||||
|
||||
result.Duration = resp.Duration
|
||||
return &result, nil
|
||||
@@ -1052,7 +1051,11 @@ func (c *RAGFlowClient) ListAdminTokens(cmd *Command) (ResponseIf, error) {
|
||||
|
||||
// Remove extra field from data
|
||||
for _, item := range result.Data {
|
||||
delete(item, "extra")
|
||||
delete(item, "dialog_id")
|
||||
delete(item, "source")
|
||||
delete(item, "update_date")
|
||||
delete(item, "update_time")
|
||||
delete(item, "create_time")
|
||||
}
|
||||
|
||||
result.Duration = resp.Duration
|
||||
|
||||
1494
internal/cli/admin_parser.go
Normal file
1494
internal/cli/admin_parser.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,6 @@ package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
@@ -34,21 +33,21 @@ import (
|
||||
// ConfigFile represents the rf.yml configuration file structure
|
||||
type ConfigFile struct {
|
||||
Host string `yaml:"host"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
APIToken string `yaml:"api_token"`
|
||||
UserName string `yaml:"user_name"`
|
||||
Password string `yaml:"password"`
|
||||
}
|
||||
|
||||
// ConnectionArgs holds the parsed command line arguments
|
||||
type ConnectionArgs struct {
|
||||
Host string
|
||||
Port int
|
||||
Password string
|
||||
Key string
|
||||
Type string
|
||||
Username string
|
||||
Command string
|
||||
ShowHelp bool
|
||||
Host string
|
||||
Port int
|
||||
Password string
|
||||
APIToken string
|
||||
UserName string
|
||||
Command string
|
||||
ShowHelp bool
|
||||
AdminMode bool
|
||||
}
|
||||
|
||||
// LoadDefaultConfigFile reads the rf.yml file from current directory if it exists
|
||||
@@ -109,23 +108,16 @@ func parseHostPort(hostPort string) (string, int, error) {
|
||||
|
||||
// ParseConnectionArgs parses command line arguments similar to Python's parse_connection_args
|
||||
func ParseConnectionArgs(args []string) (*ConnectionArgs, error) {
|
||||
// First, scan args to check for help and config file
|
||||
// First, scan args to check for help, config file, and admin mode
|
||||
var configFilePath string
|
||||
var hasOtherFlags bool
|
||||
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
if arg == "--help" {
|
||||
if arg == "--help" || arg == "-help" {
|
||||
return &ConnectionArgs{ShowHelp: true}, nil
|
||||
} else if arg == "-f" && i+1 < len(args) {
|
||||
} else if (arg == "-f" || arg == "--config") && i+1 < len(args) {
|
||||
configFilePath = args[i+1]
|
||||
i++
|
||||
} else if strings.HasPrefix(arg, "-") && arg != "-f" {
|
||||
// Check if it's a flag (not a command)
|
||||
if arg == "-h" || arg == "-p" || arg == "-w" || arg == "-k" ||
|
||||
arg == "-u" || arg == "-admin" || arg == "-user" {
|
||||
hasOtherFlags = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,115 +139,116 @@ func ParseConnectionArgs(args []string) (*ConnectionArgs, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if config != nil {
|
||||
if hasOtherFlags {
|
||||
return nil, fmt.Errorf("cannot use command line flags (-h, -p, -w, -k, -u, -admin, -user) when using config file. Please use config file or command line flags, not both")
|
||||
}
|
||||
// Parse arguments manually to support both short and long forms
|
||||
// and to handle priority: command line > config file > defaults
|
||||
|
||||
return buildArgsFromConfig(config, args)
|
||||
}
|
||||
// Create a new flag set
|
||||
fs := flag.NewFlagSet("ragflow_cli", flag.ContinueOnError)
|
||||
|
||||
// Define flags
|
||||
host := fs.String("h", "127.0.0.1", "Admin or RAGFlow service host")
|
||||
port := fs.Int("p", -1, "Admin or RAGFlow service port (default: 9381 for admin, 9380 for user)")
|
||||
password := fs.String("w", "", "Superuser password")
|
||||
key := fs.String("k", "", "API key for authentication")
|
||||
_ = fs.String("f", "", "Path to config file (YAML format)") // Already parsed above
|
||||
_ = fs.Bool("admin", false, "Run in admin mode (default)")
|
||||
userMode := fs.Bool("user", false, "Run in user mode")
|
||||
username := fs.String("u", "", "Username (email). In admin mode defaults to admin@ragflow.io, in user mode required")
|
||||
|
||||
// Parse the arguments
|
||||
if err = fs.Parse(args); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse arguments: %v", err)
|
||||
}
|
||||
|
||||
// Otherwise, use command line flags
|
||||
return buildArgsFromFlags(host, port, password, key, userMode, username, fs.Args())
|
||||
}
|
||||
|
||||
// buildArgsFromConfig builds ConnectionArgs from config file
|
||||
func buildArgsFromConfig(config *ConfigFile, remainingArgs []string) (*ConnectionArgs, error) {
|
||||
// Build result from config file first (if exists), then override with command line flags
|
||||
result := &ConnectionArgs{}
|
||||
|
||||
// Parse host:port from config file
|
||||
if config.Host != "" {
|
||||
host, port, err := parseHostPort(config.Host)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid host in config file: %v", err)
|
||||
// Get non-flag arguments (command to execute)
|
||||
var nonFlagArgs []string
|
||||
|
||||
// Apply config file values first (lower priority)
|
||||
if config != nil {
|
||||
// Parse host:port from config file
|
||||
if config.Host != "" {
|
||||
h, port, err := parseHostPort(config.Host)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid host in config file: %v", err)
|
||||
}
|
||||
result.Host = h
|
||||
result.Port = port
|
||||
}
|
||||
result.Host = host
|
||||
result.Port = port
|
||||
} else {
|
||||
result.UserName = config.UserName
|
||||
result.Password = config.Password
|
||||
result.APIToken = config.APIToken
|
||||
}
|
||||
|
||||
// Override with command line flags (higher priority)
|
||||
// Handle both short and long forms manually
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
switch arg {
|
||||
case "-h", "--host":
|
||||
if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
|
||||
hostVal := args[i+1]
|
||||
h, port, err := parseHostPort(hostVal)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid host format: %v", err)
|
||||
}
|
||||
result.Host = h
|
||||
result.Port = port
|
||||
i++
|
||||
}
|
||||
case "-t", "--token":
|
||||
if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
|
||||
result.APIToken = args[i+1]
|
||||
i++
|
||||
}
|
||||
case "-u", "--user":
|
||||
if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
|
||||
result.UserName = args[i+1]
|
||||
i++
|
||||
}
|
||||
case "-p", "--password":
|
||||
if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
|
||||
result.Password = args[i+1]
|
||||
i++
|
||||
}
|
||||
case "-f", "--config":
|
||||
// Skip config file path (already parsed)
|
||||
if i+1 < len(args) {
|
||||
i++
|
||||
}
|
||||
case "--admin", "-admin":
|
||||
result.AdminMode = true
|
||||
case "--help", "-help":
|
||||
// Already handled above
|
||||
continue
|
||||
default:
|
||||
// Non-flag argument (command)
|
||||
if !strings.HasPrefix(arg, "-") {
|
||||
nonFlagArgs = append(nonFlagArgs, arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set defaults if not provided
|
||||
if result.Host == "" {
|
||||
result.Host = "127.0.0.1"
|
||||
}
|
||||
|
||||
// Apply auth info from config
|
||||
result.Username = config.User
|
||||
result.Password = config.Password
|
||||
result.Key = config.APIToken
|
||||
|
||||
// Determine mode: if config has auth info, use user mode
|
||||
if config.User != "" || config.APIToken != "" {
|
||||
result.Type = "user"
|
||||
} else {
|
||||
result.Type = "admin"
|
||||
result.Username = "admin@ragflow.io"
|
||||
}
|
||||
|
||||
// Set default port if not specified in config
|
||||
if result.Port == -1 {
|
||||
if result.Type == "admin" {
|
||||
result.Port = 9381
|
||||
} else {
|
||||
result.Port = 9380
|
||||
}
|
||||
}
|
||||
|
||||
// Get command from remaining args (no need for quotes or semicolon)
|
||||
if len(remainingArgs) > 0 {
|
||||
result.Command = strings.Join(remainingArgs, " ") + ";"
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// buildArgsFromFlags builds ConnectionArgs from command line flags
|
||||
func buildArgsFromFlags(host *string, port *int, password *string, key *string, userMode *bool, username *string, remainingArgs []string) (*ConnectionArgs, error) {
|
||||
result := &ConnectionArgs{
|
||||
Host: *host,
|
||||
Port: *port,
|
||||
Password: *password,
|
||||
Key: *key,
|
||||
Username: *username,
|
||||
}
|
||||
|
||||
// Determine mode
|
||||
if *userMode {
|
||||
result.Type = "user"
|
||||
} else {
|
||||
result.Type = "admin"
|
||||
}
|
||||
|
||||
// Set default port based on type if not specified
|
||||
if result.Port == -1 {
|
||||
if result.Type == "admin" {
|
||||
if result.Port == -1 || result.Port == 0 {
|
||||
if result.AdminMode {
|
||||
result.Port = 9383
|
||||
} else {
|
||||
result.Port = 9384
|
||||
}
|
||||
}
|
||||
|
||||
// Determine username based on mode
|
||||
if result.Type == "admin" && result.Username == "" {
|
||||
result.Username = "admin@ragflow.io"
|
||||
if result.UserName == "" && result.Password != "" {
|
||||
return nil, fmt.Errorf("username (-u/--user) is required when using password (-p/--password)")
|
||||
}
|
||||
|
||||
// Get command from remaining args (no need for quotes or semicolon)
|
||||
if len(remainingArgs) > 0 {
|
||||
result.Command = strings.Join(remainingArgs, " ") + ";"
|
||||
if result.AdminMode {
|
||||
result.APIToken = ""
|
||||
if result.UserName == "" {
|
||||
result.UserName = "admin@ragflow.io"
|
||||
result.Password = ""
|
||||
}
|
||||
} else {
|
||||
// For user mode
|
||||
// Validate mutual exclusivity: -t and (-u, -p) are mutually exclusive
|
||||
hasToken := result.APIToken != ""
|
||||
hasUserPass := result.UserName != "" || result.Password != ""
|
||||
|
||||
if hasToken && hasUserPass {
|
||||
return nil, fmt.Errorf("cannot use both API token (-t/--token) and username/password (-u/--user, -p/--password). Please use one authentication method")
|
||||
}
|
||||
}
|
||||
|
||||
// Get command from remaining args (non-flag arguments)
|
||||
if len(nonFlagArgs) > 0 {
|
||||
result.Command = strings.Join(nonFlagArgs, " ")
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@@ -268,31 +261,40 @@ func PrintUsage() {
|
||||
Usage: ragflow_cli [options] [command]
|
||||
|
||||
Options:
|
||||
-h string Admin or RAGFlow service host (default "127.0.0.1")
|
||||
-p int Admin or RAGFlow service port (default 9381 for admin, 9380 for user)
|
||||
-w string Superuser password
|
||||
-k string API key for authentication
|
||||
-f string Path to config file (YAML format)
|
||||
-admin Run in admin mode (default)
|
||||
-user Run in user mode
|
||||
-u string Username (email). In admin mode defaults to admin@ragflow.io
|
||||
--help Show this help message
|
||||
-h, --host string RAGFlow service address (host:port, default "127.0.0.1:9380")
|
||||
-t, --token string API token for authentication
|
||||
-u, --user string Username for authentication
|
||||
-p, --password string Password for authentication
|
||||
-f, --config string Path to config file (YAML format)
|
||||
--admin, -admin Run in admin mode
|
||||
--help Show this help message
|
||||
|
||||
Mode:
|
||||
--admin, -admin Run in admin mode (prompt: RAGFlow(admin)>)
|
||||
Default is user mode (prompt: RAGFlow(user)>).
|
||||
|
||||
Authentication:
|
||||
You can authenticate using either:
|
||||
1. API token: -t or --token
|
||||
2. Username and password: -u/--user and -p/--password
|
||||
Note: These two methods are mutually exclusive.
|
||||
|
||||
Configuration File:
|
||||
The CLI will automatically read rf.yml from the current directory if it exists.
|
||||
Use -f to specify a custom config file path.
|
||||
Use -f or --config to specify a custom config file path.
|
||||
Command line options override config file values.
|
||||
|
||||
Config file format:
|
||||
host: 127.0.0.1:9380
|
||||
user: your-email@example.com
|
||||
password: your-password
|
||||
api_token: your-api-token
|
||||
user_name: your-username
|
||||
password: your-password
|
||||
|
||||
When using a config file, you cannot use other command line flags except -help.
|
||||
The command line is only for the SQL command.
|
||||
Note: api_token and user_name/password are mutually exclusive in config file.
|
||||
|
||||
Commands:
|
||||
SQL commands like: LOGIN USER 'email'; LIST USERS; etc.
|
||||
If no command is provided, CLI runs in interactive mode.
|
||||
`)
|
||||
}
|
||||
|
||||
@@ -322,10 +324,11 @@ func NewCLIWithArgs(args *ConnectionArgs) (*CLI, error) {
|
||||
// Create liner first
|
||||
line := liner.NewLiner()
|
||||
|
||||
// Determine server type
|
||||
// Determine server type based on --admin or --user flag
|
||||
// Default to "user" mode if not specified
|
||||
serverType := "user"
|
||||
if args != nil && args.Type != "" {
|
||||
serverType = args.Type
|
||||
if args != nil && args.AdminMode {
|
||||
serverType = "admin"
|
||||
}
|
||||
|
||||
// Create client with password prompt using liner
|
||||
@@ -333,11 +336,19 @@ func NewCLIWithArgs(args *ConnectionArgs) (*CLI, error) {
|
||||
client.PasswordPrompt = line.PasswordPrompt
|
||||
|
||||
// Apply connection arguments if provided
|
||||
client.HTTPClient.Host = args.Host
|
||||
client.HTTPClient.Port = args.Port
|
||||
if args != nil {
|
||||
client.HTTPClient.Host = args.Host
|
||||
if args.Port > 0 {
|
||||
client.HTTPClient.Port = args.Port
|
||||
}
|
||||
|
||||
if args.APIToken != "" {
|
||||
client.HTTPClient.APIToken = args.APIToken
|
||||
}
|
||||
}
|
||||
|
||||
// Set prompt based on server type
|
||||
prompt := "RAGFlow> "
|
||||
prompt := "RAGFlow(user)> "
|
||||
if serverType == "admin" {
|
||||
prompt = "RAGFlow(admin)> "
|
||||
}
|
||||
@@ -352,7 +363,8 @@ func NewCLIWithArgs(args *ConnectionArgs) (*CLI, error) {
|
||||
|
||||
// Run starts the interactive CLI
|
||||
func (c *CLI) Run() error {
|
||||
if c.args.Type == "admin" {
|
||||
// If username is provided without password, prompt for password
|
||||
if c.args != nil && c.args.UserName != "" && c.args.Password == "" && c.args.APIToken == "" {
|
||||
// Allow 3 attempts for password verification
|
||||
maxAttempts := 3
|
||||
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
||||
@@ -448,7 +460,7 @@ func (c *CLI) Run() error {
|
||||
|
||||
func (c *CLI) execute(input string) error {
|
||||
p := NewParser(input)
|
||||
cmd, err := p.Parse()
|
||||
cmd, err := p.Parse(c.args.AdminMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -490,7 +502,7 @@ func (c *CLI) handleMetaCommand(cmd *Command) error {
|
||||
fmt.Println("Switched to ADMIN mode")
|
||||
case "user":
|
||||
c.client.ServerType = "user"
|
||||
c.prompt = "RAGFlow> "
|
||||
c.prompt = "RAGFlow(user)> "
|
||||
fmt.Println("Switched to USER mode")
|
||||
case "host":
|
||||
if len(args) == 0 {
|
||||
@@ -616,7 +628,14 @@ func (c *CLI) VerifyAuth() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.args.Username == "" {
|
||||
// If API token is provided, use it for authentication
|
||||
if c.args.APIToken != "" {
|
||||
// TODO: Implement API token authentication
|
||||
return nil
|
||||
}
|
||||
|
||||
// Otherwise, use username/password authentication
|
||||
if c.args.UserName == "" {
|
||||
return fmt.Errorf("username is required")
|
||||
}
|
||||
|
||||
@@ -626,7 +645,7 @@ func (c *CLI) VerifyAuth() error {
|
||||
|
||||
// Create login command with username and password
|
||||
cmd := NewCommand("login_user")
|
||||
cmd.Params["email"] = c.args.Username
|
||||
cmd.Params["email"] = c.args.UserName
|
||||
cmd.Params["password"] = c.args.Password
|
||||
_, err := c.client.ExecuteCommand(cmd)
|
||||
return err
|
||||
|
||||
@@ -333,8 +333,8 @@ func (c *RAGFlowClient) ExecuteAdminCommand(cmd *Command) (ResponseIf, error) {
|
||||
return c.ListDatasets(cmd)
|
||||
case "list_agents":
|
||||
return c.ListAgents(cmd)
|
||||
case "create_token":
|
||||
return c.CreateAdminToken(cmd)
|
||||
case "generate_token":
|
||||
return c.GenerateAdminToken(cmd)
|
||||
case "list_tokens":
|
||||
return c.ListAdminTokens(cmd)
|
||||
case "drop_token":
|
||||
|
||||
@@ -84,16 +84,12 @@ func (c *HTTPClient) BuildURL(path string, useAPIBase bool) string {
|
||||
// Headers builds the request headers
|
||||
func (c *HTTPClient) Headers(authKind string, extra map[string]string) map[string]string {
|
||||
headers := make(map[string]string)
|
||||
switch authKind {
|
||||
case "api":
|
||||
if c.APIToken != "" {
|
||||
headers["Authorization"] = fmt.Sprintf("Bearer %s", c.APIToken)
|
||||
}
|
||||
case "web", "admin":
|
||||
if c.LoginToken != "" {
|
||||
headers["Authorization"] = c.LoginToken
|
||||
}
|
||||
if c.APIToken != "" {
|
||||
headers["Authorization"] = fmt.Sprintf("Bearer %s", c.APIToken)
|
||||
} else if c.LoginToken != "" {
|
||||
headers["Authorization"] = c.LoginToken
|
||||
}
|
||||
|
||||
for k, v := range extra {
|
||||
headers[k] = v
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1506
internal/cli/user_parser.go
Normal file
1506
internal/cli/user_parser.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -52,16 +52,6 @@ func (dao *UserDAO) GetByTenantID(tenantID string) (*model.User, error) {
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// GetByUsername get user by username
|
||||
func (dao *UserDAO) GetByUsername(username string) (*model.User, error) {
|
||||
var user model.User
|
||||
err := DB.Where("username = ?", username).First(&user).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// GetByEmail get user by email
|
||||
func (dao *UserDAO) GetByEmail(email string) (*model.User, error) {
|
||||
var user model.User
|
||||
|
||||
Reference in New Issue
Block a user