Skip to content

Commit

Permalink
feat: narrative permissions (#251)
Browse files Browse the repository at this point in the history
* feat: narrative permissions

Signed-off-by: Sarah Funkhouser <[email protected]>

* fix linter

Signed-off-by: Sarah Funkhouser <[email protected]>

---------

Signed-off-by: Sarah Funkhouser <[email protected]>
  • Loading branch information
golanglemonade authored Nov 27, 2024
1 parent 38d376b commit 1da1506
Show file tree
Hide file tree
Showing 74 changed files with 10,905 additions and 649 deletions.
1 change: 0 additions & 1 deletion cmd/cli/cmd/internalpolicy/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ func jsonOutput(out any) error {
// tableOutput prints the output in a table format
func tableOutput(out []openlaneclient.InternalPolicy) {
// create a table writer
// TODO: add additional columns to the table writer
writer := tables.NewTableWriter(command.OutOrStdout(), "ID", "Name", "Description", "Status", "Type", "Version", "Purpose", "Background")
for _, i := range out {
writer.AddRow(i.ID, i.Name, *i.Description, *i.Status, *i.PolicyType, *i.Version, *i.PurposeAndScope, *i.Background)
Expand Down
69 changes: 69 additions & 0 deletions cmd/cli/cmd/narrative/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package narrative

import (
"context"

"github.com/spf13/cobra"

"github.com/theopenlane/core/cmd/cli/cmd"
"github.com/theopenlane/core/pkg/openlaneclient"
)

var createCmd = &cobra.Command{
Use: "create",
Short: "create a new narrative",
Run: func(cmd *cobra.Command, args []string) {
err := create(cmd.Context())
cobra.CheckErr(err)
},
}

func init() {
command.AddCommand(createCmd)

// command line flags for the create command
createCmd.Flags().StringP("name", "n", "", "name of the narrative")
createCmd.Flags().StringP("description", "d", "", "description of the narrative")
createCmd.Flags().StringP("satisfies", "a", "", "which controls are satisfied by the narrative")
createCmd.Flags().StringSliceP("programs", "p", []string{}, "program ID(s) associated with the narrative")
}

// createValidation validates the required fields for the command
func createValidation() (input openlaneclient.CreateNarrativeInput, err error) {
// validation of required fields for the create command
// output the input struct with the required fields and optional fields based on the command line flags
input.Name = cmd.Config.String("name")
if input.Name == "" {
return input, cmd.NewRequiredFieldMissingError("name")
}

input.ProgramIDs = cmd.Config.Strings("programs")

description := cmd.Config.String("description")
if description != "" {
input.Description = &description
}

satisfies := cmd.Config.String("satisfies")
if satisfies != "" {
input.Satisfies = &satisfies
}

return input, nil
}

// create a new narrative
func create(ctx context.Context) error {
// setup http client
client, err := cmd.SetupClientWithAuth(ctx)
cobra.CheckErr(err)
defer cmd.StoreSessionCookies(client)

input, err := createValidation()
cobra.CheckErr(err)

o, err := client.CreateNarrative(ctx, input)
cobra.CheckErr(err)

return consoleOutput(o)
}
50 changes: 50 additions & 0 deletions cmd/cli/cmd/narrative/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package narrative

import (
"context"

"github.com/spf13/cobra"

"github.com/theopenlane/core/cmd/cli/cmd"
)

var deleteCmd = &cobra.Command{
Use: "delete",
Short: "delete an existing narrative",
Run: func(cmd *cobra.Command, args []string) {
err := delete(cmd.Context())
cobra.CheckErr(err)
},
}

func init() {
command.AddCommand(deleteCmd)

deleteCmd.Flags().StringP("id", "i", "", "narrative id to delete")
}

// deleteValidation validates the required fields for the command
func deleteValidation() (string, error) {
id := cmd.Config.String("id")
if id == "" {
return "", cmd.NewRequiredFieldMissingError("narrative id")
}

return id, nil
}

// delete an existing narrative in the platform
func delete(ctx context.Context) error {
// setup http client
client, err := cmd.SetupClientWithAuth(ctx)
cobra.CheckErr(err)
defer cmd.StoreSessionCookies(client)

id, err := deleteValidation()
cobra.CheckErr(err)

o, err := client.DeleteNarrative(ctx, id)
cobra.CheckErr(err)

return consoleOutput(o)
}
2 changes: 2 additions & 0 deletions cmd/cli/cmd/narrative/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package narrative is our cobra cli for narrative endpoints
package narrative
48 changes: 48 additions & 0 deletions cmd/cli/cmd/narrative/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package narrative

import (
"context"

"github.com/spf13/cobra"

"github.com/theopenlane/core/cmd/cli/cmd"
)

var getCmd = &cobra.Command{
Use: "get",
Short: "get an existing narrative",
Run: func(cmd *cobra.Command, args []string) {
err := get(cmd.Context())
cobra.CheckErr(err)
},
}

func init() {
command.AddCommand(getCmd)
getCmd.Flags().StringP("id", "i", "", "narrative id to query")
}

// get an existing narrative in the platform
func get(ctx context.Context) error {
// setup http client
client, err := cmd.SetupClientWithAuth(ctx)
cobra.CheckErr(err)
defer cmd.StoreSessionCookies(client)

// filter options
id := cmd.Config.String("id")

// if an narrative ID is provided, filter on that narrative, otherwise get all
if id != "" {
o, err := client.GetNarrativeByID(ctx, id)
cobra.CheckErr(err)

return consoleOutput(o)
}

// get all will be filtered for the authorized organization(s)
o, err := client.GetAllNarratives(ctx)
cobra.CheckErr(err)

return consoleOutput(o)
}
113 changes: 113 additions & 0 deletions cmd/cli/cmd/narrative/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package narrative

import (
"encoding/json"
"strings"

"github.com/spf13/cobra"

"github.com/theopenlane/utils/cli/tables"

"github.com/theopenlane/core/cmd/cli/cmd"
"github.com/theopenlane/core/pkg/openlaneclient"
)

// command represents the base narrative command when called without any subcommands
var command = &cobra.Command{
Use: "narrative",
Short: "the subcommands for working with narratives",
}

func init() {
cmd.RootCmd.AddCommand(command)
}

// consoleOutput prints the output in the console
func consoleOutput(e any) error {
// check if the output format is JSON and print the narratives in JSON format
if strings.EqualFold(cmd.OutputFormat, cmd.JSONOutput) {
return jsonOutput(e)
}

// check the type of the narratives and print them in a table format
switch v := e.(type) {
case *openlaneclient.GetAllNarratives:
var nodes []*openlaneclient.GetAllNarratives_Narratives_Edges_Node

for _, i := range v.Narratives.Edges {
nodes = append(nodes, i.Node)
}

e = nodes
case *openlaneclient.GetNarratives:
var nodes []*openlaneclient.GetNarratives_Narratives_Edges_Node

for _, i := range v.Narratives.Edges {
nodes = append(nodes, i.Node)
}

e = nodes
case *openlaneclient.GetNarrativeByID:
e = v.Narrative
case *openlaneclient.CreateNarrative:
e = v.CreateNarrative.Narrative
case *openlaneclient.UpdateNarrative:
e = v.UpdateNarrative.Narrative
case *openlaneclient.DeleteNarrative:
deletedTableOutput(v)
return nil
}

s, err := json.Marshal(e)
cobra.CheckErr(err)

var list []openlaneclient.Narrative

err = json.Unmarshal(s, &list)
if err != nil {
var in openlaneclient.Narrative
err = json.Unmarshal(s, &in)
cobra.CheckErr(err)

list = append(list, in)
}

tableOutput(list)

return nil
}

// jsonOutput prints the output in a JSON format
func jsonOutput(out any) error {
s, err := json.Marshal(out)
cobra.CheckErr(err)

return cmd.JSONPrint(s)
}

// tableOutput prints the output in a table format
func tableOutput(out []openlaneclient.Narrative) {
// create a table writer
writer := tables.NewTableWriter(command.OutOrStdout(), "ID", "Name", "Description", "Satisfies", "Programs")

for _, i := range out {
programs := []string{}

for _, p := range i.Programs {
programs = append(programs, p.Name)
}

writer.AddRow(i.ID, i.Name, *i.Description, *i.Satisfies, strings.Join(programs, ", "))
}

writer.Render()
}

// deleteTableOutput prints the deleted id in a table format
func deletedTableOutput(e *openlaneclient.DeleteNarrative) {
writer := tables.NewTableWriter(command.OutOrStdout(), "DeletedID")

writer.AddRow(e.DeleteNarrative.DeletedID)

writer.Render()
}
85 changes: 85 additions & 0 deletions cmd/cli/cmd/narrative/update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package narrative

import (
"context"

"github.com/spf13/cobra"

"github.com/theopenlane/core/cmd/cli/cmd"
"github.com/theopenlane/core/pkg/openlaneclient"
)

var updateCmd = &cobra.Command{
Use: "update",
Short: "update an existing narrative",
Run: func(cmd *cobra.Command, args []string) {
err := update(cmd.Context())
cobra.CheckErr(err)
},
}

func init() {
command.AddCommand(updateCmd)

updateCmd.Flags().StringP("id", "i", "", "narrative id to update")

// command line flags for the update command
updateCmd.Flags().StringP("name", "n", "", "name of the narrative")
updateCmd.Flags().StringP("description", "d", "", "description of the narrative")
updateCmd.Flags().StringP("satisfies", "a", "", "which controls are satisfied by the narrative")
updateCmd.Flags().StringSlice("add-programs", []string{}, "add program(s) to the narrative")
updateCmd.Flags().StringSlice("remove-programs", []string{}, "remove program(s) from the narrative")
}

// updateValidation validates the required fields for the command
func updateValidation() (id string, input openlaneclient.UpdateNarrativeInput, err error) {
id = cmd.Config.String("id")
if id == "" {
return id, input, cmd.NewRequiredFieldMissingError("narrative id")
}

// validation of required fields for the update command
// output the input struct with the required fields and optional fields based on the command line flags
name := cmd.Config.String("name")
if name != "" {
input.Name = &name
}

description := cmd.Config.String("description")
if description != "" {
input.Description = &description
}

satisfies := cmd.Config.String("satisfies")
if satisfies != "" {
input.Satisfies = &satisfies
}

addPrograms := cmd.Config.Strings("add-programs")
if len(addPrograms) > 0 {
input.AddProgramIDs = addPrograms
}

removePrograms := cmd.Config.Strings("remove-programs")
if len(removePrograms) > 0 {
input.RemoveProgramIDs = removePrograms
}

return id, input, nil
}

// update an existing narrative in the platform
func update(ctx context.Context) error {
// setup http client
client, err := cmd.SetupClientWithAuth(ctx)
cobra.CheckErr(err)
defer cmd.StoreSessionCookies(client)

id, input, err := updateValidation()
cobra.CheckErr(err)

o, err := client.UpdateNarrative(ctx, id, input)
cobra.CheckErr(err)

return consoleOutput(o)
}
2 changes: 2 additions & 0 deletions cmd/cli/cmd/narrativehistory/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package narrativehistory is our cobra cli for narrativeHistory endpoints
package narrativehistory
Loading

0 comments on commit 1da1506

Please sign in to comment.