Skip to content

Commit

Permalink
feat(strm-1433): implement invite users command (#98)
Browse files Browse the repository at this point in the history
* feat(strm-1433): implement invite users command

* feat(strm-1433): handle issues from response

* fix: update api defs version

Co-authored-by: Bob van den Hoogen <bob@strmprivacy.io>
  • Loading branch information
ivan-p92 and Bob van den Hoogen authored Jul 26, 2022
1 parent f9f9ec8 commit 9b71b21
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 3 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/spf13/cobra v1.3.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.10.0
github.com/strmprivacy/api-definitions-go/v2 v2.43.1
github.com/strmprivacy/api-definitions-go/v2 v2.46.0
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
google.golang.org/grpc v1.46.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/strmprivacy/api-definitions-go/v2 v2.43.1 h1:saiY1lAElmviKOv8e0IjQGpoitypMFHqglWjp1Za3DU=
github.com/strmprivacy/api-definitions-go/v2 v2.43.1/go.mod h1:3uFjMuBEQSzrRQzaKEgIrLbBWRdya9DTYCQZqyS7nEw=
github.com/strmprivacy/api-definitions-go/v2 v2.46.0 h1:0Sq6rDSVGGlL/6wMZXpCvt/SwAtqpiDqN8pU4jeLycE=
github.com/strmprivacy/api-definitions-go/v2 v2.46.0/go.mod h1:3uFjMuBEQSzrRQzaKEgIrLbBWRdya9DTYCQZqyS7nEw=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
Expand Down
3 changes: 3 additions & 0 deletions pkg/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"strmprivacy/strm/pkg/entity/kafka_exporter"
"strmprivacy/strm/pkg/entity/kafka_user"
"strmprivacy/strm/pkg/entity/key_stream"
"strmprivacy/strm/pkg/entity/organization"
"strmprivacy/strm/pkg/entity/project"
"strmprivacy/strm/pkg/entity/schema"
"strmprivacy/strm/pkg/entity/schema_code"
Expand Down Expand Up @@ -47,6 +48,7 @@ func SetupVerbs(rootCmd *cobra.Command) {
rootCmd.AddCommand(cmd.ContextCommand)
rootCmd.AddCommand(cmd.ActivateCmd)
rootCmd.AddCommand(cmd.ArchiveCmd)
rootCmd.AddCommand(cmd.InviteCmd)
}

func SetupServiceClients(accessToken *string) {
Expand All @@ -67,6 +69,7 @@ func SetupServiceClients(accessToken *string) {
installation.SetupClient(clientConnection, ctx)
account.SetupClient(clientConnection, ctx)
project.SetupClient(clientConnection, ctx)
organization.SetupClient(clientConnection, ctx)
}

func ConfigPath() string {
Expand Down
17 changes: 17 additions & 0 deletions pkg/cmd/invite.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cmd

import (
"github.com/spf13/cobra"
"strmprivacy/strm/pkg/common"
"strmprivacy/strm/pkg/entity/organization"
)

var InviteCmd = &cobra.Command{
Use: common.InviteCommandName,
DisableAutoGenTag: true,
Short: "Invite users to your organization",
}

func init() {
InviteCmd.AddCommand(organization.InviteUsersCmd())
}
1 change: 1 addition & 0 deletions pkg/common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const CreateCommandName = "create"
const DeleteCommandName = "delete"
const ActivateCommandName = "activate"
const ArchiveCommandName = "archive"
const InviteCommandName = "invite"

const RecursiveFlagName = "recursive"
const RecursiveFlagUsage = "Retrieve entities and their dependents"
Expand Down
33 changes: 33 additions & 0 deletions pkg/entity/organization/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package organization

import (
"github.com/spf13/cobra"
)

const (
userEmailsFileFlag = "user-emails-file"
)

var inviteLongDoc = `Invite one or more users to your organization, by email.
Either provide the emails comma-separated on the command line, or pass a file
with the -f flag containing one email address per line.
### Usage`

func InviteUsersCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "users [first-email,second-email,...]",
Short: "Invite users to your organization by email",
Long: inviteLongDoc,
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
inviteUsers(args, cmd)
},
Args: cobra.MaximumNArgs(1),
}

flags := cmd.Flags()
flags.StringP(userEmailsFileFlag, "f", "", "file with users to invite, one email per line")
return cmd
}
71 changes: 71 additions & 0 deletions pkg/entity/organization/organization.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package organization

import (
"context"
"errors"
"fmt"
"github.com/spf13/cobra"
"github.com/strmprivacy/api-definitions-go/v2/api/organizations/v1"
"google.golang.org/grpc"
"io/ioutil"
"strings"
"strmprivacy/strm/pkg/common"
"strmprivacy/strm/pkg/util"
)

var client organizations.OrganizationsServiceClient
var apiContext context.Context

func SetupClient(clientConnection *grpc.ClientConn, ctx context.Context) {
apiContext = ctx
client = organizations.NewOrganizationsServiceClient(clientConnection)
}

func inviteUsers(args []string, cmd *cobra.Command) {
if apiContext == nil {
common.CliExit(errors.New(fmt.Sprint("No login information found. Use: `dstrm auth login` first.")))
}
emails := getEmails(args, cmd)
var invites []*organizations.UserInvite
for _, email := range emails {
invites = append(invites, &organizations.UserInvite{Email: email})
}
req := &organizations.InviteUsersRequest{
UserInvites: invites,
}
response, err := client.InviteUsers(apiContext, req)
common.CliExit(err)
handleInviteResponse(response)
}

func handleInviteResponse(response *organizations.InviteUsersResponse) {
fmt.Println(fmt.Sprintf("Invited %d users to your organization.", response.InviteCount))
if len(response.Issues) > 0 {
fmt.Println(fmt.Sprintf("There were %d invites with issues:\n", len(response.Issues)))
inviteIssuesPrinter{}.Print(response.Issues)
}
}

func getEmails(args []string, cmd *cobra.Command) []string {
emailsFile := util.GetStringAndErr(cmd.Flags(), userEmailsFileFlag)
var emails []string

if len(args) == 0 && emailsFile == "" {
common.CliExit(errors.New(fmt.Sprint("Either provide comma-separated emails on the command line, or a file containing emails.")))
} else if len(args) > 0 {
emails = strings.Split(args[0], ",")
} else {
emails = read(emailsFile)
}
return emails
}

func read(emailsFile string) []string {
buf, err := ioutil.ReadFile(emailsFile)
common.CliExit(err)
splitFn := func(c rune) bool {
return c == '\n'
}
// FieldsFunc is used instead of split to filter out any (trailing) empty lines
return strings.FieldsFunc(string(buf), splitFn)
}
29 changes: 29 additions & 0 deletions pkg/entity/organization/printers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package organization

import (
"github.com/jedib0t/go-pretty/v6/table"
"github.com/strmprivacy/api-definitions-go/v2/api/organizations/v1"
"strmprivacy/strm/pkg/util"
)

type inviteIssuesPrinter struct{}

func (p inviteIssuesPrinter) Print(data interface{}) {
issues, _ := (data).([]*organizations.InviteUsersResponse_UserInviteIssue)
rows := make([]table.Row, 0, len(issues))

for _, issue := range issues {
row := table.Row{
issue.Invite.Email,
issue.Message,
}
rows = append(rows, row)
}

header := table.Row{
"Email",
"Issue",
}

util.RenderTable(header, rows)
}

0 comments on commit 9b71b21

Please sign in to comment.