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 }