Skip to content

Commit a513836

Browse files
committed
add team management features
Signed-off-by: Maximilian <burr.maximilian97@gmail.com>
1 parent 3976207 commit a513836

10 files changed

Lines changed: 517 additions & 16 deletions

api/team.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,23 @@ func (c *Client) DeleteTeam(orgId string, teamId int) error {
104104
r, err := c.api.TeamsAPI.TeamsDeleteTeam(c.ctx, float32(teamId)).Execute()
105105
return cserrors.FormatAPIError(r, err)
106106
}
107+
108+
func (c *Client) AddTeamMember(teamId int, email string, role int) error {
109+
r, err := c.api.TeamsAPI.TeamsInviteMember(c.ctx, float32(teamId)).
110+
TeamsInviteMemberRequest(openapi_client.TeamsInviteMemberRequest{
111+
UserEmail: email,
112+
Role: role,
113+
}).Execute()
114+
if err != nil {
115+
return cserrors.FormatAPIError(r, err)
116+
}
117+
return nil
118+
}
119+
120+
func (c *Client) RemoveTeamMember(teamId int, userId int) error {
121+
r, err := c.api.TeamsAPI.TeamsRemoveMember(c.ctx, float32(teamId), float32(userId)).Execute()
122+
if err != nil {
123+
return cserrors.FormatAPIError(r, err)
124+
}
125+
return nil
126+
}

cli/cmd/client.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ type Client interface {
3636
DeployLandscape(wsId int, profile string) error
3737
CreateTeam(orgId string, name string, dcId int) (*api.Team, error)
3838
DeleteTeam(orgId string, teamId int) error
39+
AddTeamMember(teamId int, email string, role int) error
40+
RemoveTeamMember(teamId int, userId int) error
3941
}
4042

4143
// CommandExecutor abstracts command execution for testing

cli/cmd/mocks.go

Lines changed: 120 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/cmd/team_add_member.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@
44
package cmd
55

66
import (
7+
"errors"
8+
"fmt"
9+
710
"github.com/spf13/cobra"
811
)
912

1013
type AddTeamMemberCmd struct {
11-
cmd *cobra.Command
12-
Opts CreateWorkspaceOpts
14+
cmd *cobra.Command
15+
Opts AddTeamMemberOpts
16+
ClientFactory func(GlobalOptions) (Client, error)
17+
}
18+
19+
type AddTeamMemberOpts struct {
20+
*GlobalOptions
21+
Email string
22+
Role int
23+
TeamId int
1324
}
1425

1526
func AddAddTeamMemberCmd(team *cobra.Command, opts *GlobalOptions) {
@@ -19,14 +30,44 @@ func AddAddTeamMemberCmd(team *cobra.Command, opts *GlobalOptions) {
1930
Short: "Add team member",
2031
Long: `Add team member to a team`,
2132
},
22-
Opts: CreateWorkspaceOpts{
33+
Opts: AddTeamMemberOpts{
2334
GlobalOptions: opts,
2435
},
36+
ClientFactory: NewClient,
2537
}
2638
t.cmd.RunE = t.RunE
39+
t.cmd.Flags().StringVarP(&t.Opts.Email, "email", "e", "", "Team member email")
40+
t.cmd.Flags().IntVarP(&t.Opts.Role, "role", "r", 0, "Team member role 0=admin, 1=member")
2741
AddCmd(team, t.cmd)
2842
}
2943

3044
func (c *AddTeamMemberCmd) RunE(_ *cobra.Command, args []string) error {
45+
client, err := c.ClientFactory(*c.Opts.GlobalOptions)
46+
if err != nil {
47+
return fmt.Errorf("failed to create Codespehre client: %w", err)
48+
}
49+
50+
teamId, err := c.Opts.GetTeamId()
51+
if err != nil {
52+
return err
53+
}
54+
55+
err = c.AddTeamMember(client, teamId, c.Opts.Email, c.Opts.Role)
56+
return err
57+
58+
}
59+
60+
func (c *AddTeamMemberCmd) AddTeamMember(client Client, teamId int, email string, role int) error {
61+
if email == "" {
62+
return errors.New("email cannot be empty")
63+
}
64+
65+
fmt.Printf("add member: %s to team %d with role: %d", email, teamId, role)
66+
67+
err := client.AddTeamMember(teamId, email, role)
68+
if err != nil {
69+
return fmt.Errorf("failed to add member to team: %w", err)
70+
}
71+
3172
return nil
3273
}

cli/cmd/team_add_member_test.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright (c) Codesphere Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package cmd_test
5+
6+
import (
7+
"errors"
8+
9+
"github.com/codesphere-cloud/cs-go/cli/cmd"
10+
. "github.com/onsi/ginkgo/v2"
11+
. "github.com/onsi/gomega"
12+
)
13+
14+
var _ = Describe("AddTeamMember", func() {
15+
var (
16+
mockEnv *cmd.MockEnv
17+
mockClient *cmd.MockClient
18+
c *cmd.AddTeamMemberCmd
19+
teamId int
20+
dcId int
21+
email string
22+
)
23+
24+
BeforeEach(func() {
25+
mockClient = cmd.NewMockClient(GinkgoT())
26+
mockEnv = cmd.NewMockEnv(GinkgoT())
27+
teamId = 42
28+
email = "test@test.com"
29+
dcId = 1 // Default data center ID for testing
30+
c = &cmd.AddTeamMemberCmd{
31+
Opts: cmd.AddTeamMemberOpts{
32+
GlobalOptions: &cmd.GlobalOptions{
33+
Env: mockEnv,
34+
TeamId: teamId,
35+
// OrgId is intentionally left empty here, will be set in BeforeEach for specific contexts
36+
},
37+
Email: email,
38+
TeamId: teamId,
39+
},
40+
ClientFactory: func(opts cmd.GlobalOptions) (cmd.Client, error) {
41+
return mockClient, nil
42+
},
43+
}
44+
// Mock common environment calls needed for client creation
45+
})
46+
47+
AfterEach(func() {
48+
mockEnv.AssertExpectations(GinkgoT())
49+
mockClient.AssertExpectations(GinkgoT())
50+
})
51+
52+
Context("Validation", func() {
53+
It("should fail if the mail is empty", func() {
54+
55+
err := c.AddTeamMember(mockClient, teamId, "", dcId)
56+
57+
Expect(err).To(HaveOccurred())
58+
Expect(err.Error()).To(Equal("email cannot be empty"))
59+
})
60+
})
61+
62+
Context("RunE execution flow", func() {
63+
It("should successfully add a member to a team", func() {
64+
mockClient.EXPECT().AddTeamMember(teamId, email, 0).Return(nil).Once()
65+
66+
err := c.RunE(nil, []string{})
67+
Expect(err).ToNot(HaveOccurred())
68+
})
69+
70+
It("should fail when the token is not allowed to add a member", func() {
71+
mockClient.EXPECT().AddTeamMember(teamId, email, 0).Return(errors.New("failed")).Once()
72+
73+
err := c.RunE(nil, []string{})
74+
Expect(err).To(HaveOccurred())
75+
Expect(err.Error()).To(ContainSubstring("failed to add member to team: "))
76+
})
77+
78+
It("should fail when client creation fails", func() {
79+
c.ClientFactory = func(opts cmd.GlobalOptions) (cmd.Client, error) {
80+
return nil, errors.New("client init failed")
81+
}
82+
83+
err := c.RunE(nil, []string{})
84+
Expect(err).To(HaveOccurred())
85+
Expect(err.Error()).To(ContainSubstring("failed to create Codespehre client: client init failed"))
86+
})
87+
88+
It("should fail when team ID is unavailable", func() {
89+
c.Opts.GlobalOptions.TeamId = -1
90+
mockEnv.EXPECT().GetTeamId().Return(-1, errors.New("CS_TEAM_ID env var required, but not set")).Once()
91+
92+
err := c.RunE(nil, []string{})
93+
Expect(err).To(HaveOccurred())
94+
Expect(err.Error()).To(Equal("CS_TEAM_ID env var required, but not set"))
95+
})
96+
97+
It("should fail when email is empty", func() {
98+
c.Opts.Email = ""
99+
err := c.RunE(nil, []string{})
100+
Expect(err).To(HaveOccurred())
101+
Expect(err.Error()).To(Equal("email cannot be empty"))
102+
})
103+
})
104+
105+
})

cli/cmd/team_remove.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ package cmd
55

66
import (
77
"errors"
8+
"fmt"
9+
810
"github.com/spf13/cobra"
911
)
1012

1113
type RemoveTeamCmd struct {
12-
cmd *cobra.Command
13-
Opts RemoveTeamOpts
14+
cmd *cobra.Command
15+
Opts RemoveTeamOpts
16+
ClientFactory func(GlobalOptions) (Client, error)
1417
}
1518

1619
type RemoveTeamOpts struct {
@@ -28,6 +31,7 @@ func AddRemoveTeamCmd(team *cobra.Command, opts *GlobalOptions) {
2831
Opts: RemoveTeamOpts{
2932
GlobalOptions: opts,
3033
},
34+
ClientFactory: NewClient,
3135
}
3236
t.cmd.RunE = t.RunE
3337
t.cmd.Flags().StringVarP(&t.Opts.name, "name", "n", "", "Team name")
@@ -36,10 +40,9 @@ func AddRemoveTeamCmd(team *cobra.Command, opts *GlobalOptions) {
3640
}
3741

3842
func (c *RemoveTeamCmd) RunE(_ *cobra.Command, args []string) error {
39-
// TODO: Implement team removal logic
40-
client, err := NewClient(*c.Opts.GlobalOptions)
43+
client, err := c.ClientFactory(*c.Opts.GlobalOptions)
4144
if err != nil {
42-
return err
45+
return fmt.Errorf("failed to create Codespehre client: %w", err)
4346
}
4447

4548
orgId, err := c.Opts.GetOrgId()
@@ -52,12 +55,9 @@ func (c *RemoveTeamCmd) RunE(_ *cobra.Command, args []string) error {
5255
return errors.New("team ID not set, use -T or CS_TEAM_ID to set it")
5356
}
5457

55-
//
56-
5758
err = client.DeleteTeam(orgId, teamId)
5859
if err != nil {
59-
return err
60+
return fmt.Errorf("failed to delete team: %w", err)
6061
}
6162
return nil
62-
6363
}

0 commit comments

Comments
 (0)