Skip to content

Commit

Permalink
feat: risks and their permissions, program-members cli (#247)
Browse files Browse the repository at this point in the history
  • Loading branch information
golanglemonade authored Nov 26, 2024
1 parent 196ee98 commit bda1454
Show file tree
Hide file tree
Showing 92 changed files with 12,435 additions and 400 deletions.
4 changes: 0 additions & 4 deletions .buildkite/pipeline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@ steps:
- label: ":golang: go test - {{matrix.version}}"
key: "go_test"
cancel_on_build_failing: true
retry:
automatic:
- exit_status: "*"
limit: 2
env:
TEST_DB_URL: "docker://postgres:{{matrix.version}}"
matrix:
Expand Down
2 changes: 1 addition & 1 deletion .typos.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[files]
extend-exclude = ["db","internal/ent/generated/**","go.mod","go.sum","pkg/testutils/","internal/graphapi/tools_test.go","internal/httpserve/handlers/tools_test.go", "plans.yaml"]
extend-exclude = ["db","internal/ent/generated/**","go.mod","go.sum","pkg/testutils/","internal/graphapi/tools_test.go","internal/httpserve/handlers/tools_test.go", "plans.yaml", "internal/graphapi/_example_test.go"]
ignore-hidden = true
ignore-files = true
ignore-dot = true
Expand Down
7 changes: 7 additions & 0 deletions cmd/cli/Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ tasks:
cmds:
- go run main.go organization-setting get

program:create:
desc: creates an program against a running local instance of the server
cmds:
- go run main.go program create -n "mitb program" -d "program for mitb"

user:verify:
desc: a task to register a user, parse out the token response, and submit it to the verify endpoint
aliases: [verifyuser]
Expand All @@ -70,9 +75,11 @@ tasks:
- task: verifyuser
- task: login
- task: createorg
- task: program:create
- sleep 2
- task: getorgsetting


user:all:another:
desc: a task to register, verify, and login another user
cmds:
Expand Down
67 changes: 67 additions & 0 deletions cmd/cli/cmd/programmembers/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package programmembers

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: "add a user to a program",
Run: func(cmd *cobra.Command, args []string) {
err := create(cmd.Context())
cobra.CheckErr(err)
},
}

func init() {
command.AddCommand(createCmd)

createCmd.Flags().StringP("program-id", "p", "", "program id")
createCmd.Flags().StringP("user-id", "u", "", "user id")
createCmd.Flags().StringP("role", "r", "member", "role to assign the user (member, admin)")
}

// createValidation validates the required fields for the command
func createValidation() (input openlaneclient.CreateProgramMembershipInput, err error) {
input.ProgramID = cmd.Config.String("program-id")
if input.ProgramID == "" {
return input, cmd.NewRequiredFieldMissingError("program id")
}

input.UserID = cmd.Config.String("user-id")
if input.UserID == "" {
return input, cmd.NewRequiredFieldMissingError("user id")
}

// role defaults to `member` so it is not required
role := cmd.Config.String("role")
if role != "" {
r, err := cmd.GetRoleEnum(role)
cobra.CheckErr(err)

input.Role = &r
}

return input, nil
}

// create adds a user to a program in the platform
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.AddUserToProgramWithRole(ctx, input)
cobra.CheckErr(err)

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

import (
"context"
"errors"

"github.com/spf13/cobra"

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

var deleteCmd = &cobra.Command{
Use: "delete",
Short: "remove a user from a program",
Run: func(cmd *cobra.Command, args []string) {
err := delete(cmd.Context())
cobra.CheckErr(err)
},
}

func init() {
command.AddCommand(deleteCmd)

deleteCmd.Flags().StringP("program-id", "g", "", "program id")
deleteCmd.Flags().StringP("user-id", "u", "", "user id")
}

// deleteValidation validates the required fields for the command
func deleteValidation() (where openlaneclient.ProgramMembershipWhereInput, err error) {
programID := cmd.Config.String("program-id")
if programID == "" {
return where, cmd.NewRequiredFieldMissingError("program id")
}

userID := cmd.Config.String("user-id")
if userID == "" {
return where, cmd.NewRequiredFieldMissingError("user id")
}

where.ProgramID = &programID
where.UserID = &userID

return where, nil
}

// delete removes a user from a program in the platform
func delete(ctx context.Context) error {
// setup http client
client, err := cmd.SetupClientWithAuth(ctx)
cobra.CheckErr(err)
defer cmd.StoreSessionCookies(client)

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

programMembers, err := client.GetProgramMembersByProgramID(ctx, &where)
cobra.CheckErr(err)

if len(programMembers.ProgramMemberships.Edges) != 1 {
return errors.New("error getting existing relation") //nolint:err113
}

o, err := client.RemoveUserFromProgram(ctx, programMembers.ProgramMemberships.Edges[0].Node.ID)
cobra.CheckErr(err)

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

import (
"context"

"github.com/spf13/cobra"

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

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

func init() {
command.AddCommand(getCmd)

getCmd.Flags().StringP("program-id", "p", "", "program id to query")
}

// get existing members of a program
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("program-id")
if id == "" {
return cmd.NewRequiredFieldMissingError("program id")
}

where := openlaneclient.ProgramMembershipWhereInput{
ProgramID: &id,
}

o, err := client.GetProgramMembersByProgramID(ctx, &where)
cobra.CheckErr(err)

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

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"
)

// cmd represents the base programMembers command when called without any subcommands
var command = &cobra.Command{
Use: "program-members",
Short: "the subcommands for working with the members of a program",
}

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 output in JSON format
if strings.EqualFold(cmd.OutputFormat, cmd.JSONOutput) {
return jsonOutput(e)
}

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

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

e = nodes
case *openlaneclient.AddUserToProgramWithRole:
e = v.CreateProgramMembership.ProgramMembership
case *openlaneclient.UpdateUserRoleInProgram:
e = v.UpdateProgramMembership.ProgramMembership
case *openlaneclient.RemoveUserFromProgram:
deletedTableOutput(v)
return nil
}

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

var list []openlaneclient.ProgramMembership

err = json.Unmarshal(s, &list)
if err != nil {
var in openlaneclient.ProgramMembership
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.ProgramMembership) {
writer := tables.NewTableWriter(command.OutOrStdout(), "UserID", "DisplayName", "FirstName", "LastName", "Email", "Role")
for _, i := range out {
writer.AddRow(i.UserID, i.User.DisplayName, *i.User.FirstName, *i.User.LastName, i.User.Email, i.Role)
}

writer.Render()
}

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

writer.AddRow(e.DeleteProgramMembership.DeletedID)

writer.Render()
}
Loading

0 comments on commit bda1454

Please sign in to comment.