Go: add statistics command (#16119)

### What problem does this PR solve?

Prepare for enterprise command

### 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:
Jin Hai
2026-06-18 15:21:44 +08:00
committed by GitHub
parent 351b61a243
commit 20d11648a4
12 changed files with 2889 additions and 465 deletions

View File

@@ -732,50 +732,6 @@ func (c *CLI) SetVariable(cmd *Command) (ResponseIf, error) {
return &result, nil
}
// ListUsers lists all users (admin mode only)
// Returns (result_map, error) - result_map is non-nil for benchmark mode
func (c *CLI) ListUsers(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
// 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.AdminServerClient.RequestWithIterations("GET", "/admin/users", "admin", nil, nil, iterations)
}
resp, err := c.AdminServerClient.Request("GET", "/admin/users", "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))
}
var result CommonResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("list users failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
for _, user := range result.Data {
delete(user, "create_date")
}
result.Duration = resp.Duration
return &result, nil
}
// DropUser deletes a user (admin mode only)
func (c *CLI) DropUser(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
@@ -809,39 +765,6 @@ func (c *CLI) DropUser(cmd *Command) (ResponseIf, error) {
return &result, nil
}
// Show user show user (admin mode only)
func (c *CLI) ShowUser(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
userName, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
resp, err := c.AdminServerClient.Request("GET", fmt.Sprintf("/admin/users/%s", userName), "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to show user: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to show user: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("show user failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
// ListUserDatasets lists datasets for a specific user (admin mode)
// Returns (result_map, error) - result_map is non-nil for benchmark mode
func (c *CLI) ListUserDatasets(cmd *Command) (ResponseIf, error) {
@@ -1612,3 +1535,786 @@ func (c *CLI) AdminRemoveServiceCommand(cmd *Command) (ResponseIf, error) {
result.Duration = resp.Duration
return &result, nil
}
// Show user show user (admin mode only)
func (c *CLI) AdminShowUserInfoCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
userName, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
apiURL := fmt.Sprintf("/admin/users/%s", userName)
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to show user: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to show user: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("show user failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowUserActivityCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
days, ok := cmd.Params["days"].(int)
if !ok {
return nil, fmt.Errorf("days not provided")
}
email, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
payload := map[string]interface{}{
"days": days,
"email": email,
}
apiURL := fmt.Sprintf("/admin/users/%s/activity", email)
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, payload)
if err != nil {
return nil, fmt.Errorf("failed to get user activity: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get user activity: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get user activity failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowUserSummaryCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
userName, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
apiURL := fmt.Sprintf("/admin/users/%s/summary", userName)
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get statistics: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get user summary: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get user summary failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowUserDatasetCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
dataset, ok := cmd.Params["dataset_name"].(string)
if !ok {
return nil, fmt.Errorf("dataset_name not provided")
}
email, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
payload := map[string]interface{}{
"dataset": dataset,
}
apiURL := fmt.Sprintf("/admin/users/%s/dataset", email)
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, payload)
if err != nil {
return nil, fmt.Errorf("failed to get user dataset: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get user dataset: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get user dataset failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowUserStorageCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
email, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
apiURL := fmt.Sprintf("/admin/users/%s/storage", email)
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get user storage: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get user storage: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get user storage failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowUserQuotaCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
email, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
apiURL := fmt.Sprintf("/admin/users/%s/quota", email)
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get user storage: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get user storage: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get user storage failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowUserIndexCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
email, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
apiURL := fmt.Sprintf("/admin/users/%s/index", email)
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get user storage: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get user storage: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get user storage failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowUserPermissionCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
email, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
apiURL := fmt.Sprintf("/admin/users/%s/permission", email)
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get user permission: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get user permission: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get user permission failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowUsersSummaryCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
apiURL := "/admin/users/summary"
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get users summary: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get users summary: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get users summary failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowUsersActivityCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
days, ok := cmd.Params["days"].(int)
if !ok {
return nil, fmt.Errorf("days not provided")
}
window, ok := cmd.Params["window"].(int)
if !ok {
return nil, fmt.Errorf("window not provided")
}
payload := map[string]interface{}{
"days": days,
"window": window,
}
apiURL := "/admin/users/activity"
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, payload)
if err != nil {
return nil, fmt.Errorf("failed to get users activity: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get users activity: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get users activity failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
// ListUsers lists all users (admin mode only)
// Returns (result_map, error) - result_map is non-nil for benchmark mode
func (c *CLI) AdminListUsersCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
// 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.AdminServerClient.RequestWithIterations("GET", "/admin/users", "admin", nil, nil, iterations)
}
resp, err := c.AdminServerClient.Request("GET", "/admin/users", "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))
}
var result CommonResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("list users failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
for _, user := range result.Data {
delete(user, "create_date")
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminListUsersConditionCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
var orderBy *string
var userStatus *string
var top *int
var plan *string
var quota *int
var days *int
orderByStr, ok := cmd.Params["order_by"].(string)
if ok {
orderBy = &orderByStr
}
userStatusStr, ok := cmd.Params["user_status"].(string)
if ok {
userStatus = &userStatusStr
}
topInt, ok := cmd.Params["top"].(int)
if ok {
top = &topInt
}
planStr, ok := cmd.Params["plan"].(string)
if ok {
plan = &planStr
}
quotaInt, ok := cmd.Params["quota"].(int)
if ok {
quota = &quotaInt
}
daysInt, ok := cmd.Params["days"].(int)
if ok {
days = &daysInt
}
payload := map[string]interface{}{
"enterprise": true,
"order_by": orderBy,
"user_status": userStatus,
"top": top,
"plan": plan,
"quota": quota,
"days": days,
}
resp, err := c.AdminServerClient.Request("GET", "/admin/users", "admin", nil, payload)
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))
}
var result CommonResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("list users failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowDataSummaryCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
apiURL := "/admin/data/summary"
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get users summary: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get users summary: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get users summary failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowDataOrphanCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
apiURL := "/admin/data/orphan"
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get orphan data: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get orphan data: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get orphan data failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowDataStorageCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
apiURL := "/admin/data/storage"
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get data storage: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get data storage: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get data storage failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowDataIndexCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
apiURL := "/admin/data/index"
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get data index: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get data index: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get data index failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminShowQuotaSummaryCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
apiURL := "/admin/users/quota/summary"
resp, err := c.AdminServerClient.Request("GET", apiURL, "admin", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get users quota summary: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to get users quota summary: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("get users quota summary failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminPurgeOrphanCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
preview, ok := cmd.Params["preview"].(bool)
if !ok {
return nil, fmt.Errorf("preview not provided")
}
payload := map[string]interface{}{
"preview": preview,
}
apiURL := "/admin/data/orphan"
resp, err := c.AdminServerClient.Request("DELETE", apiURL, "admin", nil, payload)
if err != nil {
return nil, fmt.Errorf("failed to purge orphan data: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to purge orphan data: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("purge orphan data failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminPurgeUserCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
preview, ok := cmd.Params["preview"].(bool)
if !ok {
return nil, fmt.Errorf("preview not provided")
}
userName, ok := cmd.Params["user_name"].(string)
if !ok {
return nil, fmt.Errorf("user_name not provided")
}
payload := map[string]interface{}{
"preview": preview,
}
apiURL := fmt.Sprintf("/admin/users/%s/data", userName)
resp, err := c.AdminServerClient.Request("DELETE", apiURL, "admin", nil, payload)
if err != nil {
return nil, fmt.Errorf("failed to purge user %s: %w", userName, err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to purge user %s: HTTP %d, body: %s", userName, resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("purge user %s failed: invalid JSON (%w)", userName, err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}
func (c *CLI) AdminPurgeUsersCommand(cmd *Command) (ResponseIf, error) {
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
}
var preview bool
var ok bool
var planName string
var planNamePtr *string
var userStatus string
var userStatusPtr *string
var days int
preview, ok = cmd.Params["preview"].(bool)
if !ok {
return nil, fmt.Errorf("preview not provided")
}
planName, ok = cmd.Params["plan_name"].(string)
if ok {
planNamePtr = &planName
}
userStatus, ok = cmd.Params["user_status"].(string)
if ok {
userStatusPtr = &userStatus
}
days, ok = cmd.Params["days"].(int)
if !ok {
return nil, fmt.Errorf("days not provided")
}
payload := map[string]interface{}{
"preview": preview,
"days": days,
"plan": planNamePtr,
"user_status": userStatusPtr,
}
apiURL := "/admin/users/data"
resp, err := c.AdminServerClient.Request("DELETE", apiURL, "admin", nil, payload)
if err != nil {
return nil, fmt.Errorf("failed to purge users data: %w", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("failed to purge users data: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
}
var result CommonDataResponse
if err = json.Unmarshal(resp.Body, &result); err != nil {
return nil, fmt.Errorf("purge users data failed: invalid JSON (%w)", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("%s", result.Message)
}
result.Duration = resp.Duration
return &result, nil
}

View File

@@ -137,12 +137,7 @@ func (p *Parser) parseAdminListCommand() (*Command, error) {
}
return NewCommand("list_services"), nil
case TokenUsers:
p.nextToken()
// Semicolon is optional for SHOW TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return NewCommand("list_users"), nil
return p.parseAdminListUsersCommand()
case TokenRoles:
p.nextToken()
// Semicolon is optional for SHOW TOKEN
@@ -467,31 +462,11 @@ func (p *Parser) parseAdminShowCommand() (*Command, error) {
switch p.curToken.Type {
case TokenVersion:
p.nextToken()
// Semicolon is optional for SHOW TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return NewCommand("show_version"), nil
case TokenToken:
p.nextToken()
// Semicolon is optional for SHOW TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return NewCommand("show_token"), nil
return p.parseAdminShowVersionCommand()
case TokenCurrent:
p.nextToken()
// Semicolon is optional for SHOW TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return NewCommand("show_current"), nil
case TokenUser:
return p.parseShowUser()
return p.parseAdminShowCurrentCommand()
case TokenRole:
return p.parseShowRole()
return p.parseAdminShowRoleCommand()
case TokenVar:
return p.parseShowVariable()
case TokenService:
@@ -504,6 +479,14 @@ func (p *Parser) parseAdminShowCommand() (*Command, error) {
return p.parseUserShowAdmin()
case TokenAPI:
return p.parseUserShowAPI()
case TokenUser:
return p.parseAdminShowUserCommand()
case TokenUsers:
return p.parseAdminShowUsersCommand()
case TokenData:
return p.parseAdminShowDataCommand()
case TokenQuota:
return p.parseAdminShowQuotaCommand()
default:
return nil, fmt.Errorf("unknown SHOW target: %s", p.curToken.Value)
}
@@ -545,7 +528,7 @@ func (p *Parser) parseAdminShowUser() (*Command, error) {
return cmd, nil
}
func (p *Parser) parseAdminShowRole() (*Command, error) {
func (p *Parser) parseAdminShowRoleCommand() (*Command, error) {
p.nextToken() // consume ROLE
roleName, err := p.parseIdentifier()
if err != nil {
@@ -1925,3 +1908,590 @@ func (p *Parser) parseAdminRemoveCommand() (*Command, error) {
}
return cmd, nil
}
// SHOW VERSION;
func (p *Parser) parseAdminShowVersionCommand() (*Command, error) {
p.nextToken() // consume VERSION
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return NewCommand("show_version"), nil
}
// SHOW CURRENT;
func (p *Parser) parseAdminShowCurrentCommand() (*Command, error) {
p.nextToken() // consume CURRENT
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return NewCommand("show_current"), nil
}
// SHOW USER 'user@example.com';
// SHOW USER 'user@example.com' DATASET 'dataset_name';
// SHOW USER 'user@example.com' SUMMARY;
// SHOW USER 'user@example.com' STORAGE;
// SHOW USER 'user@example.com' QUOTA;
// SHOW USER 'user@example.com' INDEX;
func (p *Parser) parseAdminShowUserCommand() (*Command, error) {
p.nextToken() // consume USER
userName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
p.nextToken()
switch p.curToken.Type {
case TokenActivity:
return p.parseAdminShowActivityCommand(userName)
case TokenSummary:
return p.parseAdminShowUserSummaryCommand(userName)
case TokenDataset:
return p.parseAdminShowUserDataSetCommand(userName)
case TokenStorage:
return p.parseAdminShowUserStorageCommand(userName)
case TokenQuota:
return p.parseAdminShowUserQuotaCommand(userName)
case TokenIndex:
return p.parseAdminShowUserIndexCommand(userName)
case TokenPermission:
return p.parseAdminShowUserPermissionCommand(userName)
default:
return p.parseAdminShowUserInfoCommand(userName)
}
}
// SHOW USER 'user@example.com';
func (p *Parser) parseAdminShowUserInfoCommand(userName string) (*Command, error) {
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
cmd := NewCommand("admin_show_user_info_command")
cmd.Params["user_name"] = userName
return cmd, nil
}
// SHOW USER 'user@example.com' ACTIVITY DAYS 30;
func (p *Parser) parseAdminShowActivityCommand(userName string) (*Command, error) {
p.nextToken() // consume ACTIVITY
var days int
var err error
if p.curToken.Type == TokenDays {
p.nextToken() // consume DAYS
days, err = p.parseNumber()
if err != nil {
return nil, err
}
if days < 1 {
return nil, fmt.Errorf("invalid number of DAYS")
}
p.nextToken()
} else {
days = 7
}
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
cmd := NewCommand("admin_show_user_activity_command")
cmd.Params["user_name"] = userName
cmd.Params["days"] = days
return cmd, nil
}
// SHOW USER 'user@example.com' SUMMARY;
func (p *Parser) parseAdminShowUserSummaryCommand(userName string) (*Command, error) {
p.nextToken() // consume SUMMARY
cmd := NewCommand("admin_show_user_summary_command")
cmd.Params["user_name"] = userName
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
// SHOW USER 'user@example.com' DATASET 'dataset_name';
func (p *Parser) parseAdminShowUserDataSetCommand(userName string) (*Command, error) {
p.nextToken() // consume DATASET
var tree = false
var datasetName string
var err error
datasetName, err = p.parseQuotedString()
if err != nil {
return nil, err
}
p.nextToken()
if p.curToken.Type == TokenTree {
tree = true
p.nextToken()
}
cmd := NewCommand("admin_show_user_dataset_command")
cmd.Params["user_name"] = userName
if datasetName != "" {
cmd.Params["dataset_name"] = datasetName
}
if tree {
cmd.Params["tree"] = true
}
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
// SHOW USER 'user@example.com' STORAGE;
func (p *Parser) parseAdminShowUserStorageCommand(userName string) (*Command, error) {
p.nextToken() // consume STORAGE
cmd := NewCommand("admin_show_user_storage_command")
cmd.Params["user_name"] = userName
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
// SHOW USER 'user@example.com' QUOTA;
func (p *Parser) parseAdminShowUserQuotaCommand(userName string) (*Command, error) {
p.nextToken() // consume QUOTA
cmd := NewCommand("admin_show_user_quota_command")
cmd.Params["user_name"] = userName
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
// SHOW USER 'user@example.com' INDEX;
func (p *Parser) parseAdminShowUserIndexCommand(userName string) (*Command, error) {
p.nextToken() // consume INDEX
cmd := NewCommand("admin_show_user_index_command")
cmd.Params["user_name"] = userName
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
// SHOW USER 'user@example.com' PERMISSION;
func (p *Parser) parseAdminShowUserPermissionCommand(userName string) (*Command, error) {
p.nextToken() // consume PERMISSION
cmd := NewCommand("admin_show_user_permission_command")
cmd.Params["user_name"] = userName
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
// SHOW USERS SUMMARY;
// SHOW USERS ACTIVITY;
func (p *Parser) parseAdminShowUsersCommand() (*Command, error) {
p.nextToken() // consume USERS
switch p.curToken.Type {
case TokenSummary:
p.nextToken()
cmd := NewCommand("admin_show_users_summary_command")
return cmd, nil
case TokenActivity:
return p.parseAdminShowUsersActivityCommand()
default:
return nil, fmt.Errorf("invalid command")
}
}
// SHOW USERS ACTIVITY WINDOW 2 DAYS 30;
func (p *Parser) parseAdminShowUsersActivityCommand() (*Command, error) {
p.nextToken() // consume ACTIVITY
var days int
var err error
var windowSize int
commandLoop:
for {
switch p.curToken.Type {
case TokenDays:
p.nextToken()
days, err = p.parseNumber()
if err != nil {
return nil, err
}
if days < 1 {
return nil, fmt.Errorf("invalid number of DAYS")
}
p.nextToken()
case TokenWindow:
p.nextToken()
windowSize, err = p.parseNumber()
if err != nil {
return nil, err
}
if windowSize < 0 {
return nil, fmt.Errorf("invalid number of WINDOWS")
}
p.nextToken()
case TokenSemicolon:
p.nextToken()
break commandLoop // done
default:
// No more options to process
break commandLoop
}
}
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
cmd := NewCommand("admin_show_users_activity_command")
cmd.Params["days"] = days
cmd.Params["window"] = windowSize
return cmd, nil
}
// LIST USERS;
// LIST USERS ACTIVE 30 DAYS; // default 7 days
// LIST USERS INACTIVE 30 DAYS; // default 7 days
// LIST USERS STORAGE TOP 10;
// LIST USERS DOCUMENTS TOP 10;
// LIST USERS INDEX TOP 10;
// LIST USERS QUOTA TOP 10;
// LIST USERS QUOTA OVER;
// LIST USERS PLAN 'plan_name' QUOTA OVER DAYS 30; // default 7 days
// LIST USERS PLAN 'plan_name' DAYS 30; // default 7 days
func (p *Parser) parseAdminListUsersCommand() (*Command, error) {
p.nextToken() // consume USERS
var orderBy string
var userStatus string
var top *int
var plan *string
var quota *int
var days *int
condition := false
commandLoop:
for {
switch p.curToken.Type {
case TokenTop:
condition = true
p.nextToken()
topInt, err := p.parseNumber()
if err != nil {
return nil, err
}
if topInt < 0 {
return nil, fmt.Errorf("invalid number of TOP")
}
p.nextToken()
top = &topInt
case TokenDays:
condition = true
p.nextToken()
daysInt, err := p.parseNumber()
if err != nil {
return nil, err
}
if daysInt < 0 {
return nil, fmt.Errorf("invalid number of DAYS")
}
p.nextToken()
days = &daysInt
case TokenPlan:
condition = true
p.nextToken()
planStr, err := p.parseQuotedString()
if err != nil {
return nil, err
}
if planStr == "" {
return nil, fmt.Errorf("invalid plan")
}
plan = &planStr
p.nextToken()
case TokenQuota:
condition = true
p.nextToken()
quotaInt, err := p.parseNumber()
if err != nil {
return nil, err
}
if quotaInt < 0 {
return nil, fmt.Errorf("invalid number of QUOTA")
}
quota = &quotaInt
p.nextToken()
case TokenDocuments, TokenIndex, TokenStorage:
condition = true
if orderBy != "" {
return nil, fmt.Errorf("order by already set")
}
orderBy = p.curToken.Value
p.nextToken()
case TokenActive, TokenInactive:
condition = true
userStatus = p.curToken.Value
p.nextToken()
case TokenSemicolon:
p.nextToken()
break commandLoop // done
default:
// No more options to process
break commandLoop
}
}
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
if !condition {
return NewCommand("admin_list_users_command"), nil
}
cmd := NewCommand("admin_list_users_condition_command")
if orderBy != "" {
cmd.Params["order_by"] = orderBy
}
if userStatus != "" {
cmd.Params["user_status"] = userStatus
}
if top != nil {
cmd.Params["top"] = *top
}
if plan != nil {
cmd.Params["plan"] = *plan
}
if quota != nil {
cmd.Params["quota"] = *quota
}
if days != nil {
cmd.Params["days"] = *days
}
return cmd, nil
}
// SHOW DATA SUMMARY;
// SHOW DATA ORPHAN;
// SHOW DATA STORAGE;
// SHOW DATA INDEX;
func (p *Parser) parseAdminShowDataCommand() (*Command, error) {
p.nextToken() // consume ALL
var cmd *Command
switch p.curToken.Type {
case TokenSummary:
p.nextToken()
cmd = NewCommand("admin_show_data_summary_command")
case TokenOrphan:
p.nextToken()
cmd = NewCommand("admin_show_data_orphan_command")
case TokenStorage:
p.nextToken()
cmd = NewCommand("admin_show_data_storage_command")
case TokenIndex:
p.nextToken()
cmd = NewCommand("admin_show_data_index_command")
default:
return nil, fmt.Errorf("expected SUMMARY, ORPHAN, STORAGE, INDEX, TASKS, QUOTA_SUMMARY after ALL")
}
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
// SHOW QUOTA SUMMARY;
func (p *Parser) parseAdminShowQuotaCommand() (*Command, error) {
p.nextToken() // consume QUOTA
var cmd *Command
switch p.curToken.Type {
case TokenSummary:
p.nextToken()
cmd = NewCommand("admin_show_quota_summary_command")
default:
return nil, fmt.Errorf("expected SUMMARY after QUOTA")
}
// Semicolon is optional
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
// PURGE PREVIEW ORPHAN
// PURGE ORPHAN
// PURGE PREVIEW USER 'user@example.com';
// PURGE USER
// PURGE PREVIEW USERS PLAN 'plan_name' DAYS 30; // default 7 days
// PURGE USERS PLAN 'plan_name' DAYS 30;
// PURGE PREVIEW USERS INACTIVE PLAN 'plan_name' DAYS 30;
// PURGE USERS INACTIVE PLAN 'plan_name' DAYS 30;
func (p *Parser) parseAdminPurgeCommand() (*Command, error) {
p.nextToken() // consume PURGE
var preview = false
if p.curToken.Type == TokenPreview {
p.nextToken()
preview = true
}
switch p.curToken.Type {
case TokenOrphan:
return p.parseAdminPurgeOrphanCommand(preview)
case TokenUser:
return p.parseAdminPurgeUserCommand(preview)
case TokenUsers:
return p.parseAdminPurgeUsersCommand(preview)
default:
return nil, fmt.Errorf("expected PREVIEW, USER, USERS after PURGE")
}
}
// PURGE PREVIEW ORPHAN
// PURGE ORPHAN
func (p *Parser) parseAdminPurgeOrphanCommand(preview bool) (*Command, error) {
p.nextToken() // consume ORPHAN
cmd := NewCommand("admin_purge_orphan_command")
cmd.Params["preview"] = preview
return cmd, nil
}
// PURGE PREVIEW USER 'user@example.com';
// PURGE USER 'user@example.com';
func (p *Parser) parseAdminPurgeUserCommand(preview bool) (*Command, error) {
p.nextToken() // consume USER
userName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
cmd := NewCommand("admin_purge_user_command")
cmd.Params["preview"] = preview
cmd.Params["user_name"] = userName
return cmd, nil
}
// PURGE PREVIEW USERS PLAN 'plan_name' DAYS 30; // default 7 days
// PURGE USERS PLAN 'plan_name' DAYS 30;
// PURGE PREVIEW USERS INACTIVE PLAN 'plan_name' DAYS 30;
// PURGE USERS INACTIVE PLAN 'plan_name' DAYS 30;
func (p *Parser) parseAdminPurgeUsersCommand(preview bool) (*Command, error) {
p.nextToken() // consume USERS
var userStatus *string = nil
var days *int = nil
var planName *string = nil
commandLoop:
for {
switch p.curToken.Type {
case TokenPlan:
p.nextToken()
if planName != nil {
return nil, fmt.Errorf("duplicate PLAN after USERS")
}
plan, err := p.parseQuotedString()
if err != nil {
return nil, err
}
planName = &plan
p.nextToken()
case TokenDays:
p.nextToken()
if days != nil {
return nil, fmt.Errorf("duplicate DAYS after USERS")
}
dayCount, err := p.parseNumber()
if err != nil {
return nil, err
}
days = &dayCount
p.nextToken()
case TokenInactive:
p.nextToken()
if userStatus != nil {
return nil, fmt.Errorf("duplicate INACTIVE or ACTIVE after USERS")
}
inactiveStatus := "inactive"
userStatus = &inactiveStatus
case TokenActive:
p.nextToken()
if userStatus != nil {
return nil, fmt.Errorf("duplicate INACTIVE or ACTIVE after USERS")
}
activeStatus := "active"
userStatus = &activeStatus
case TokenSemicolon:
p.nextToken()
break commandLoop // done
default:
// No more options to process
break commandLoop
}
}
cmd := NewCommand("admin_purge_users_command")
cmd.Params["preview"] = preview
if planName != nil {
cmd.Params["plan_name"] = *planName
}
if userStatus != nil {
cmd.Params["user_status"] = *userStatus
}
if days != nil {
cmd.Params["days"] = *days
}
return cmd, nil
}

View File

@@ -45,8 +45,6 @@ func (c *CLI) ExecuteAdminCommand(cmd *Command) (ResponseIf, error) {
return c.PingByCommand(cmd)
case "benchmark":
return c.RunBenchmark(cmd)
case "list_users":
return c.ListUsers(cmd)
case "list_services":
return c.ListServices(cmd)
case "grant_admin":
@@ -67,8 +65,6 @@ func (c *CLI) ExecuteAdminCommand(cmd *Command) (ResponseIf, error) {
return c.ShowAdminVersion(cmd)
case "show_current":
return c.ShowCommonCurrent(cmd)
case "show_user":
return c.ShowUser(cmd)
case "list_variables":
return c.ListVariables(cmd)
case "show_variable":
@@ -123,6 +119,46 @@ func (c *CLI) ExecuteAdminCommand(cmd *Command) (ResponseIf, error) {
return c.UserShowMessageQueueCommand(cmd)
case "admin_remove_service_command":
return c.AdminRemoveServiceCommand(cmd)
case "admin_show_user_info_command":
return c.AdminShowUserInfoCommand(cmd)
case "admin_show_user_activity_command":
return c.AdminShowUserActivityCommand(cmd)
case "admin_show_user_summary_command":
return c.AdminShowUserSummaryCommand(cmd)
case "admin_show_user_dataset_command":
return c.AdminShowUserDatasetCommand(cmd)
case "admin_show_user_storage_command":
return c.AdminShowUserStorageCommand(cmd)
case "admin_show_user_quota_command":
return c.AdminShowUserQuotaCommand(cmd)
case "admin_show_user_index_command":
return c.AdminShowUserIndexCommand(cmd)
case "admin_show_user_permission_command":
return c.AdminShowUserPermissionCommand(cmd)
case "admin_show_users_summary_command":
return c.AdminShowUsersSummaryCommand(cmd)
case "admin_show_users_activity_command":
return c.AdminShowUsersActivityCommand(cmd)
case "admin_list_users_command":
return c.AdminListUsersCommand(cmd)
case "admin_list_users_condition_command":
return c.AdminListUsersConditionCommand(cmd)
case "admin_show_quota_summary_command":
return c.AdminShowQuotaSummaryCommand(cmd)
case "admin_show_data_summary_command":
return c.AdminShowDataSummaryCommand(cmd)
case "admin_show_data_orphan_command":
return c.AdminShowDataOrphanCommand(cmd)
case "admin_show_data_storage_command":
return c.AdminShowDataStorageCommand(cmd)
case "admin_show_data_index_command":
return c.AdminShowDataIndexCommand(cmd)
case "admin_purge_orphan_command":
return c.AdminPurgeOrphanCommand(cmd)
case "admin_purge_user_command":
return c.AdminPurgeUserCommand(cmd)
case "admin_purge_users_command":
return c.AdminPurgeUsersCommand(cmd)
// TODO: Implement other commands
case "show_admin_server":
return c.ShowAdminServer(cmd)

View File

@@ -219,6 +219,8 @@ func (l *Lexer) lookupIdent(ident string) Token {
return Token{Type: TokenAlter, Value: ident}
case "ACTIVE":
return Token{Type: TokenActive, Value: ident}
case "INACTIVE":
return Token{Type: TokenInactive, Value: ident}
case "ADMIN":
return Token{Type: TokenAdmin, Value: ident}
case "SERVER":
@@ -487,6 +489,32 @@ func (l *Lexer) lookupIdent(ident string) Token {
return Token{Type: TokenPending, Value: ident}
case "NOACK":
return Token{Type: TokenNoACK, Value: ident}
case "ANALYZE":
return Token{Type: TokenAnalyze, Value: ident}
case "SUMMARY":
return Token{Type: TokenSummary, Value: ident}
case "STORAGE":
return Token{Type: TokenStorage, Value: ident}
case "QUOTA":
return Token{Type: TokenQuota, Value: ident}
case "TREE":
return Token{Type: TokenTree, Value: ident}
case "ORPHAN":
return Token{Type: TokenOrphan, Value: ident}
case "DAYS":
return Token{Type: TokenDays, Value: ident}
case "WINDOW":
return Token{Type: TokenWindow, Value: ident}
case "ACTIVITY":
return Token{Type: TokenActivity, Value: ident}
case "PURGE":
return Token{Type: TokenPurge, Value: ident}
case "PREVIEW":
return Token{Type: TokenPreview, Value: ident}
case "PLAN":
return Token{Type: TokenPlan, Value: ident}
case "DATA":
return Token{Type: TokenData, Value: ident}
case "LOG":
return Token{Type: TokenLog, Value: ident}
case "LEVEL":

View File

@@ -138,6 +138,8 @@ func (p *Parser) parseAdminCommand() (*Command, error) {
return p.parseAdminSaveCommand()
case TokenUse:
return p.parseAdminUseCommand()
case TokenPurge:
return p.parseAdminPurgeCommand()
default:
return nil, fmt.Errorf("unknown command: %s", p.curToken.Value)
}

View File

@@ -41,6 +41,7 @@ const (
TokenUser
TokenAlter
TokenActive
TokenInactive
TokenAdmin
TokenServer
TokenAPI
@@ -175,6 +176,19 @@ const (
TokenPull
TokenPending
TokenNoACK
TokenAnalyze
TokenSummary
TokenStorage
TokenQuota
TokenTree
TokenOrphan
TokenDays
TokenWindow
TokenActivity
TokenData
TokenPurge
TokenPlan
TokenPreview
TokenLog
TokenLevel
TokenDebug

View File

@@ -442,12 +442,7 @@ func (p *Parser) parseShowCommand() (*Command, error) {
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return NewCommand("show_current"), nil
case TokenUser:
return p.parseShowUser()
case TokenRole:
return p.parseShowRole()
case TokenVar:
return p.parseShowVariable()
case TokenService:
@@ -473,60 +468,6 @@ func (p *Parser) parseShowCommand() (*Command, error) {
}
}
func (p *Parser) parseShowUser() (*Command, error) {
p.nextToken() // consume USER
// Check for PERMISSION
if p.curToken.Type == TokenPermission {
p.nextToken()
userName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
cmd := NewCommand("show_user_permission")
cmd.Params["user_name"] = userName
p.nextToken()
// Semicolon is optional for SHOW TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
userName, err := p.parseQuotedString()
if err != nil {
return nil, err
}
cmd := NewCommand("show_user")
cmd.Params["user_name"] = userName
p.nextToken()
// Semicolon is optional for UNSET TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
func (p *Parser) parseShowRole() (*Command, error) {
p.nextToken() // consume ROLE
roleName, err := p.parseIdentifier()
if err != nil {
return nil, err
}
cmd := NewCommand("show_role")
cmd.Params["role_name"] = roleName
p.nextToken()
// Semicolon is optional for UNSET TOKEN
if p.curToken.Type == TokenSemicolon {
p.nextToken()
}
return cmd, nil
}
func (p *Parser) parseShowVariable() (*Command, error) {
p.nextToken() // consume VAR
varName, err := p.parseIdentifier()