/* * Copyright 2026 Oleg Borodin * * This work is published and licensed under a Creative Commons * Attribution-NonCommercial-NoDerivatives 4.0 International License. * * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ package main import ( "context" "regexp" "strings" "time" "github.com/spf13/cobra" "github.com/spf13/viper" "mstore/pkg/client" "mstore/pkg/descr" ) func (util *GrantUtil) CreateGrantCmds() *cobra.Command { var subCmd = &cobra.Command{ Use: "grants", Short: "Grant operations", Aliases: []string{"grant"}, } const defaultTimeout uint64 = 10 subCmd.PersistentFlags().StringVarP(&util.commonGrantParams.Username, "user", "u", "", "Username") subCmd.PersistentFlags().StringVarP(&util.commonGrantParams.Password, "pass", "p", "", "Password") subCmd.PersistentFlags().Uint64VarP(&util.commonGrantParams.Timeout, "timeout", "t", defaultTimeout, "Operation timeout") subCmd.PersistentFlags().BoolVarP(&util.commonGrantParams.SkipTLSVerify, "skipVerify", "S", true, "Skip server certificate verify") vi := viper.New() vi.SetEnvPrefix("mstore") vi.BindEnv("user") vi.BindEnv("pass") util.commonGrantParams.Username = vi.GetString("user") util.commonGrantParams.Password = vi.GetString("pass") // CreateGrant var createGrantCmd = &cobra.Command{ Use: "create [user:pass@]hostname[:port] username|accountId rigth pattern", Short: "Create grant", Args: cobra.ExactArgs(4), Run: util.CreateGrant, } subCmd.AddCommand(createGrantCmd) // GetGrant var getGrantCmd = &cobra.Command{ Use: "get [user:pass@]hostname[:port] grantId", Short: "Get detail grant info", Args: cobra.ExactArgs(2), Run: util.GetGrant, } subCmd.AddCommand(getGrantCmd) // UpdateGrant var updateGrantCmd = &cobra.Command{ Use: "update [user:pass@]hostname[:port] gruntId newPattern", Short: "Update grant parameters", Args: cobra.ExactArgs(3), Run: util.UpdateGrant, } subCmd.AddCommand(updateGrantCmd) // DeleteGrant var deleteGrantCmd = &cobra.Command{ Use: "delete [user:pass@]hostname[:port] gruntId ", Short: "Delete grant", Args: cobra.ExactArgs(2), Run: util.DeleteGrant, } subCmd.AddCommand(deleteGrantCmd) // ListGrants var listGrantsCmd = &cobra.Command{ Use: "list [user:pass@]hostname[:port] accountId|username", Short: "list user grants", Args: cobra.ExactArgs(2), Run: util.ListGrants, } listGrantsCmd.Flags().BoolVarP(&util.listGrantsParams.Detail, "detail", "d", false, "Show detail information") subCmd.AddCommand(listGrantsCmd) return subCmd } type GrantUtil struct { createGrantParams CreateGrantParams updateGrantParams UpdateGrantParams getGrantParams GetGrantParams deleteGrantParams DeleteGrantParams listGrantsParams ListGrantsParams commonGrantParams CommonGrantParams } type CommonGrantParams struct { Username string Password string Hostname string Timeout uint64 SkipTLSVerify bool } // CreateGrant type CreateGrantParams struct { AccountID string Right string Pattern string } type CreateGrantResult struct { GrantID string `yaml:"grantId"` } func (util *GrantUtil) CreateGrant(cmd *cobra.Command, args []string) { util.commonGrantParams.Hostname = args[0] util.createGrantParams.AccountID = args[1] util.createGrantParams.Right = args[2] util.createGrantParams.Pattern = args[3] res, err := util.createGrant(&util.commonGrantParams, &util.createGrantParams) printResponse(res, err) } func (util *GrantUtil) createGrant(common *CommonGrantParams, params *CreateGrantParams) (*CreateGrantResult, error) { var err error res := &CreateGrantResult{} hostname, err := packUserinfo(common.Hostname, common.Username, common.Password) if err != nil { return res, err } timeout := time.Duration(common.Timeout) * time.Second ctx, _ := context.WithTimeout(context.Background(), timeout) re := regexp.MustCompile(uuidRegex) id := strings.ToLower(params.AccountID) var operRes string if re.MatchString(id) { operRes, err = client.NewClient(common.SkipTLSVerify).CreateGrantByAccountID(ctx, hostname, id, params.Right, params.Pattern) } else { operRes, err = client.NewClient(common.SkipTLSVerify).CreateGrantByUsername(ctx, hostname, params.AccountID, params.Right, params.Pattern) } if err != nil { return res, err } res.GrantID = operRes return res, err } // UpdateGrant type UpdateGrantParams struct { GrantID string Pattern string } type UpdateGrantResult struct{} func (util *GrantUtil) UpdateGrant(cmd *cobra.Command, args []string) { util.commonGrantParams.Hostname = args[0] util.updateGrantParams.GrantID = args[1] util.updateGrantParams.Pattern = args[2] res, err := util.updateGrant(&util.commonGrantParams, &util.updateGrantParams) printResponse(res, err) } func (util *GrantUtil) updateGrant(common *CommonGrantParams, params *UpdateGrantParams) (*UpdateGrantResult, error) { var err error res := &UpdateGrantResult{} hostname, err := packUserinfo(common.Hostname, common.Username, common.Password) if err != nil { return res, err } timeout := time.Duration(common.Timeout) * time.Second ctx, _ := context.WithTimeout(context.Background(), timeout) id := strings.ToLower(params.GrantID) err = client.NewClient(common.SkipTLSVerify).UpdateGrant(ctx, hostname, id, params.Pattern) if err != nil { return res, err } return res, err } // GetGrant type GetGrantParams struct { GrantID string } type GetGrantResult struct { Grant *descr.Grant `yaml:"grant,omitempty"` } func (util *GrantUtil) GetGrant(cmd *cobra.Command, args []string) { util.commonGrantParams.Hostname = args[0] util.getGrantParams.GrantID = args[1] res, err := util.getGrant(&util.commonGrantParams, &util.getGrantParams) printResponse(res, err) } func (util *GrantUtil) getGrant(common *CommonGrantParams, params *GetGrantParams) (*GetGrantResult, error) { var err error res := &GetGrantResult{} hostname, err := packUserinfo(common.Hostname, common.Username, common.Password) if err != nil { return res, err } timeout := time.Duration(common.Timeout) * time.Second ctx, _ := context.WithTimeout(context.Background(), timeout) opRes := &descr.Grant{} id := strings.ToLower(params.GrantID) opRes, err = client.NewClient(common.SkipTLSVerify).GetGrant(ctx, hostname, id) if err != nil { return res, err } res.Grant = opRes return res, err } // DeleteGrant type DeleteGrantParams struct { GrantID string } type DeleteGrantResult struct{} func (util *GrantUtil) DeleteGrant(cmd *cobra.Command, args []string) { util.commonGrantParams.Hostname = args[0] util.deleteGrantParams.GrantID = args[1] res, err := util.deleteGrant(&util.commonGrantParams, &util.deleteGrantParams) printResponse(res, err) } func (util *GrantUtil) deleteGrant(common *CommonGrantParams, params *DeleteGrantParams) (*DeleteGrantResult, error) { var err error res := &DeleteGrantResult{} hostname, err := packUserinfo(common.Hostname, common.Username, common.Password) if err != nil { return res, err } timeout := time.Duration(common.Timeout) * time.Second ctx, _ := context.WithTimeout(context.Background(), timeout) id := strings.ToLower(params.GrantID) err = client.NewClient(common.SkipTLSVerify).DeleteGrant(ctx, hostname, id) if err != nil { return res, err } return res, err } // ListGrants type ListGrantsParams struct { Detail bool AccountID string } type ListGrantsResult struct { Grants []descr.Grant `yaml:"grants,omitempty"` Rights map[string]string `yaml:"rights,omitempty"` } func (util *GrantUtil) ListGrants(cmd *cobra.Command, args []string) { util.commonGrantParams.Hostname = args[0] util.listGrantsParams.AccountID = args[1] res, err := util.listGrants(&util.commonGrantParams, &util.listGrantsParams) printResponse(res, err) } func (util *GrantUtil) listGrants(common *CommonGrantParams, params *ListGrantsParams) (*ListGrantsResult, error) { var err error res := &ListGrantsResult{} hostname, err := packUserinfo(common.Hostname, common.Username, common.Password) if err != nil { return res, err } timeout := time.Duration(common.Timeout) * time.Second ctx, _ := context.WithTimeout(context.Background(), timeout) grants := make([]descr.Grant, 0) re := regexp.MustCompile(uuidRegex) id := strings.ToLower(params.AccountID) if re.MatchString(id) { grants, err = client.NewClient(common.SkipTLSVerify).ListGrantsByAccountID(ctx, hostname, id) } else { grants, err = client.NewClient(common.SkipTLSVerify).ListGrantsByUsername(ctx, hostname, params.AccountID) } if err != nil { return res, err } if params.Detail { res.Grants = grants } else { res.Rights = make(map[string]string, 0) for _, item := range grants { res.Rights[item.ID] = item.Right } } return res, err }