github.com/w3security/vervet/v5@v5.3.1-0.20230618081846-5bd9b5d799dc/internal/cmd/resource.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"sort"
     8  
     9  	"github.com/olekukonko/tablewriter"
    10  	"github.com/urfave/cli/v2"
    11  
    12  	"github.com/w3security/vervet/v5"
    13  	"github.com/w3security/vervet/v5/config"
    14  	"github.com/w3security/vervet/v5/internal/compiler"
    15  )
    16  
    17  // ResourceCommand is the `vervet resource` subcommand.
    18  var ResourceCommand = cli.Command{
    19  	Name:    "resource",
    20  	Aliases: []string{"rc"},
    21  	Flags: []cli.Flag{
    22  		&cli.StringFlag{
    23  			Name:    "config",
    24  			Aliases: []string{"c", "conf"},
    25  			Usage:   "Project configuration file",
    26  		},
    27  	},
    28  	Subcommands: []*cli.Command{{
    29  		Name:      "files",
    30  		Usage:     "List OpenAPI files of versioned resources in a vervet project",
    31  		ArgsUsage: "[api [resource]]",
    32  		Action:    ResourceFiles,
    33  	}, {
    34  		Name:      "info",
    35  		Usage:     "Information about versioned resources in a vervet project",
    36  		ArgsUsage: "[api [resource]]",
    37  		Action:    ResourceShow,
    38  	}},
    39  }
    40  
    41  // ResourceShow is a command that lists all the versions of matching resources.
    42  // It takes optional arguments to filter the output: api resource.
    43  func ResourceShow(ctx *cli.Context) error {
    44  	projectDir, configFile, err := projectConfig(ctx)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	f, err := os.Open(configFile)
    49  	if err != nil {
    50  		return err
    51  	}
    52  	defer f.Close()
    53  	proj, err := config.Load(f)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	err = os.Chdir(projectDir)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	table := tablewriter.NewWriter(os.Stdout)
    62  	table.SetHeader([]string{"API", "Resource", "Version", "Path", "Method", "Operation"})
    63  	for _, apiName := range proj.APINames() {
    64  		if apiArg := ctx.Args().Get(0); apiArg != "" && apiArg != apiName {
    65  			continue
    66  		}
    67  		api := proj.APIs[apiName]
    68  		for _, rcConfig := range api.Resources {
    69  			specFiles, err := compiler.ResourceSpecFiles(rcConfig)
    70  			if err != nil {
    71  				return err
    72  			}
    73  			resources, err := vervet.LoadResourceVersionsFileset(specFiles)
    74  			if err != nil {
    75  				return err
    76  			}
    77  			for _, version := range resources.Versions() {
    78  				rc, err := resources.At(version.String())
    79  				if err != nil {
    80  					return err
    81  				}
    82  				if rcArg := ctx.Args().Get(1); rcArg != "" && rcArg != rc.Name {
    83  					continue
    84  				}
    85  				var pathNames []string
    86  				for k := range rc.Paths {
    87  					pathNames = append(pathNames, k)
    88  				}
    89  				sort.Strings(pathNames)
    90  				for _, pathName := range pathNames {
    91  					pathSpec := rc.Paths[pathName]
    92  					if pathSpec.Get != nil {
    93  						table.Append([]string{apiName, rc.Name, version.String(), pathName, "GET", pathSpec.Get.OperationID})
    94  					}
    95  					if pathSpec.Post != nil {
    96  						table.Append([]string{apiName, rc.Name, version.String(), pathName, "POST", pathSpec.Post.OperationID})
    97  					}
    98  					if pathSpec.Put != nil {
    99  						table.Append([]string{apiName, rc.Name, version.String(), pathName, "PUT", pathSpec.Put.OperationID})
   100  					}
   101  					if pathSpec.Patch != nil {
   102  						table.Append([]string{apiName, rc.Name, version.String(), pathName, "PATCH", pathSpec.Patch.OperationID})
   103  					}
   104  					if pathSpec.Delete != nil {
   105  						table.Append([]string{apiName, rc.Name, version.String(), pathName, "DELETE", pathSpec.Delete.OperationID})
   106  					}
   107  				}
   108  			}
   109  		}
   110  	}
   111  	table.Render()
   112  	return nil
   113  }
   114  
   115  // ResourceFiles is a command that lists all versioned OpenAPI spec files of
   116  // matching resources.
   117  // It takes optional arguments to filter the output: api resource.
   118  func ResourceFiles(ctx *cli.Context) error {
   119  	projectDir, configFile, err := projectConfig(ctx)
   120  	if err != nil {
   121  		return err
   122  	}
   123  	f, err := os.Open(configFile)
   124  	if err != nil {
   125  		return err
   126  	}
   127  	defer f.Close()
   128  	proj, err := config.Load(f)
   129  	if err != nil {
   130  		return err
   131  	}
   132  	err = os.Chdir(projectDir)
   133  	if err != nil {
   134  		return err
   135  	}
   136  	for _, apiName := range proj.APINames() {
   137  		if apiArg := ctx.Args().Get(0); apiArg != "" && apiArg != apiName {
   138  			continue
   139  		}
   140  		api := proj.APIs[apiName]
   141  		for _, rcConfig := range api.Resources {
   142  			specFiles, err := compiler.ResourceSpecFiles(rcConfig)
   143  			if err != nil {
   144  				return err
   145  			}
   146  			sort.Strings(specFiles)
   147  			for i := range specFiles {
   148  				rcName := filepath.Base(filepath.Dir(filepath.Dir(specFiles[i])))
   149  				if rcArg := ctx.Args().Get(1); rcArg != "" && rcArg != rcName {
   150  					continue
   151  				}
   152  				fmt.Println(specFiles[i])
   153  			}
   154  		}
   155  	}
   156  	return nil
   157  }