github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/client/cli/auth/rules.go (about)

     1  package cli
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"sort"
     7  	"strings"
     8  	"text/tabwriter"
     9  
    10  	"github.com/tickoalcantara12/micro/v3/client/cli/namespace"
    11  	"github.com/tickoalcantara12/micro/v3/client/cli/util"
    12  	pb "github.com/tickoalcantara12/micro/v3/proto/auth"
    13  	"github.com/tickoalcantara12/micro/v3/service/client"
    14  	"github.com/tickoalcantara12/micro/v3/service/context"
    15  	"github.com/tickoalcantara12/micro/v3/service/errors"
    16  	"github.com/urfave/cli/v2"
    17  )
    18  
    19  func listRules(ctx *cli.Context) error {
    20  	cli := pb.NewRulesService("auth", client.DefaultClient)
    21  
    22  	env, err := util.GetEnv(ctx)
    23  	if err != nil {
    24  		return err
    25  	}
    26  	ns, err := namespace.Get(env.Name)
    27  	if err != nil {
    28  		return fmt.Errorf("Error getting namespace: %v", err)
    29  	}
    30  
    31  	rsp, err := cli.List(context.DefaultContext, &pb.ListRequest{
    32  		Options: &pb.Options{Namespace: ns},
    33  	}, client.WithAuthToken())
    34  	if err != nil {
    35  		return fmt.Errorf("Error listing rules: %v", err)
    36  	}
    37  
    38  	w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
    39  	defer w.Flush()
    40  
    41  	formatResource := func(r *pb.Resource) string {
    42  		return strings.Join([]string{r.Type, r.Name, r.Endpoint}, ":")
    43  	}
    44  
    45  	// sort rules using resource name and priority to keep the list consistent
    46  	sort.Slice(rsp.Rules, func(i, j int) bool {
    47  		resI := formatResource(rsp.Rules[i].Resource) + string(rsp.Rules[i].Priority)
    48  		resJ := formatResource(rsp.Rules[j].Resource) + string(rsp.Rules[j].Priority)
    49  		return sort.StringsAreSorted([]string{resJ, resI})
    50  	})
    51  
    52  	fmt.Fprintln(w, strings.Join([]string{"ID", "Scope", "Access", "Resource", "Priority"}, "\t\t"))
    53  	for _, r := range rsp.Rules {
    54  		res := formatResource(r.Resource)
    55  		if r.Scope == "" {
    56  			r.Scope = "<public>"
    57  		}
    58  		fmt.Fprintln(w, strings.Join([]string{r.Id, r.Scope, r.Access.String(), res, fmt.Sprintf("%d", r.Priority)}, "\t\t"))
    59  	}
    60  
    61  	return nil
    62  }
    63  
    64  func createRule(ctx *cli.Context) error {
    65  	env, err := util.GetEnv(ctx)
    66  	if err != nil {
    67  		return err
    68  	}
    69  	ns, err := namespace.Get(env.Name)
    70  	if err != nil {
    71  		return fmt.Errorf("Error getting namespace: %v", err)
    72  	}
    73  
    74  	rule, err := constructRule(ctx)
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	cli := pb.NewRulesService("auth", client.DefaultClient)
    80  	_, err = cli.Create(context.DefaultContext, &pb.CreateRequest{
    81  		Rule: rule, Options: &pb.Options{Namespace: ns},
    82  	}, client.WithAuthToken())
    83  	if verr := errors.FromError(err); verr != nil {
    84  		return fmt.Errorf("Error: %v", verr.Detail)
    85  	} else if err != nil {
    86  		return err
    87  	}
    88  
    89  	fmt.Println("Rule created")
    90  	return nil
    91  }
    92  
    93  func deleteRule(ctx *cli.Context) error {
    94  	if ctx.Args().Len() != 1 {
    95  		return fmt.Errorf("Expected one argument: ID")
    96  	}
    97  
    98  	env, err := util.GetEnv(ctx)
    99  	if err != nil {
   100  		return err
   101  	}
   102  	ns, err := namespace.Get(env.Name)
   103  	if err != nil {
   104  		return fmt.Errorf("Error getting namespace: %v", err)
   105  	}
   106  
   107  	cli := pb.NewRulesService("auth", client.DefaultClient)
   108  	_, err = cli.Delete(context.DefaultContext, &pb.DeleteRequest{
   109  		Id: ctx.Args().First(), Options: &pb.Options{Namespace: ns},
   110  	}, client.WithAuthToken())
   111  	if verr := errors.FromError(err); err != nil {
   112  		return fmt.Errorf("Error: %v", verr.Detail)
   113  	} else if err != nil {
   114  		return err
   115  	}
   116  
   117  	fmt.Println("Rule deleted")
   118  	return nil
   119  }
   120  
   121  func constructRule(ctx *cli.Context) (*pb.Rule, error) {
   122  	if ctx.Args().Len() != 1 {
   123  		return nil, fmt.Errorf("Too many arguments, expected one argument: ID")
   124  	}
   125  
   126  	var access pb.Access
   127  	switch ctx.String("access") {
   128  	case "granted":
   129  		access = pb.Access_GRANTED
   130  	case "denied":
   131  		access = pb.Access_DENIED
   132  	default:
   133  		return nil, fmt.Errorf("Invalid access: %v, must be granted or denied", ctx.String("access"))
   134  	}
   135  
   136  	resComps := strings.Split(ctx.String("resource"), ":")
   137  	if len(resComps) != 3 {
   138  		return nil, fmt.Errorf("Invalid resource, must be in the format type:name:endpoint")
   139  	}
   140  
   141  	return &pb.Rule{
   142  		Id:       ctx.Args().First(),
   143  		Access:   access,
   144  		Scope:    ctx.String("scope"),
   145  		Priority: int32(ctx.Int("priority")),
   146  		Resource: &pb.Resource{
   147  			Type:     resComps[0],
   148  			Name:     resComps[1],
   149  			Endpoint: resComps[2],
   150  		},
   151  	}, nil
   152  }