mirror of
https://github.com/coder/coder.git
synced 2026-06-03 13:08:25 +00:00
d29a168785
The removal of that permission from the role broke valid use cases (e.g. a site owner user creating a workspace owned by a system account and then trying to share it with another user). The bulk of the PR is made up of the rollbacks of the previously introduced test updates necessitated by the removal. Related to: https://github.com/coder/internal/issues/1285
338 lines
12 KiB
Go
338 lines
12 KiB
Go
package cli_test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/coder/coder/v2/cli/clitest"
|
|
"github.com/coder/coder/v2/coderd/coderdtest"
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/coderd/database/dbfake"
|
|
"github.com/coder/coder/v2/coderd/rbac"
|
|
"github.com/coder/coder/v2/codersdk"
|
|
"github.com/coder/coder/v2/testutil"
|
|
)
|
|
|
|
func TestSharingShare(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("ShareWithUsers_Simple", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var (
|
|
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{
|
|
DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) {
|
|
dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)}
|
|
}),
|
|
})
|
|
orgOwner = coderdtest.CreateFirstUser(t, client)
|
|
workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID))
|
|
workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
|
|
OwnerID: workspaceOwner.ID,
|
|
OrganizationID: orgOwner.OrganizationID,
|
|
}).Do().Workspace
|
|
_, toShareWithUser = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID)
|
|
)
|
|
|
|
ctx := testutil.Context(t, testutil.WaitMedium)
|
|
inv, root := clitest.New(t, "sharing", "add", workspace.Name, "--user", toShareWithUser.Username)
|
|
clitest.SetupConfig(t, workspaceOwnerClient, root)
|
|
|
|
out := new(bytes.Buffer)
|
|
inv.Stdout = out
|
|
err := inv.WithContext(ctx).Run()
|
|
require.NoError(t, err)
|
|
|
|
acl, err := workspaceOwnerClient.WorkspaceACL(inv.Context(), workspace.ID)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, acl.Users, codersdk.WorkspaceUser{
|
|
MinimalUser: codersdk.MinimalUser{
|
|
ID: toShareWithUser.ID,
|
|
Username: toShareWithUser.Username,
|
|
Name: toShareWithUser.Name,
|
|
AvatarURL: toShareWithUser.AvatarURL,
|
|
},
|
|
Role: codersdk.WorkspaceRole("use"),
|
|
})
|
|
|
|
assert.Contains(t, out.String(), toShareWithUser.Username)
|
|
assert.Contains(t, out.String(), codersdk.WorkspaceRoleUse)
|
|
})
|
|
|
|
t.Run("ShareWithUsers_Multiple", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var (
|
|
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{
|
|
DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) {
|
|
dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)}
|
|
}),
|
|
})
|
|
orgOwner = coderdtest.CreateFirstUser(t, client)
|
|
|
|
workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID))
|
|
workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
|
|
OwnerID: workspaceOwner.ID,
|
|
OrganizationID: orgOwner.OrganizationID,
|
|
}).Do().Workspace
|
|
|
|
_, toShareWithUser1 = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID)
|
|
_, toShareWithUser2 = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID)
|
|
)
|
|
|
|
ctx := testutil.Context(t, testutil.WaitMedium)
|
|
inv, root := clitest.New(t,
|
|
"sharing",
|
|
"add", workspace.Name,
|
|
fmt.Sprintf("--user=%s,%s", toShareWithUser1.Username, toShareWithUser2.Username),
|
|
)
|
|
clitest.SetupConfig(t, workspaceOwnerClient, root)
|
|
|
|
out := new(bytes.Buffer)
|
|
inv.Stdout = out
|
|
err := inv.WithContext(ctx).Run()
|
|
require.NoError(t, err)
|
|
|
|
acl, err := workspaceOwnerClient.WorkspaceACL(inv.Context(), workspace.ID)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, acl.Users, codersdk.WorkspaceUser{
|
|
MinimalUser: codersdk.MinimalUser{
|
|
ID: toShareWithUser1.ID,
|
|
Username: toShareWithUser1.Username,
|
|
Name: toShareWithUser1.Name,
|
|
AvatarURL: toShareWithUser1.AvatarURL,
|
|
},
|
|
Role: codersdk.WorkspaceRoleUse,
|
|
})
|
|
assert.Contains(t, acl.Users, codersdk.WorkspaceUser{
|
|
MinimalUser: codersdk.MinimalUser{
|
|
ID: toShareWithUser2.ID,
|
|
Username: toShareWithUser2.Username,
|
|
Name: toShareWithUser2.Name,
|
|
AvatarURL: toShareWithUser2.AvatarURL,
|
|
},
|
|
Role: codersdk.WorkspaceRoleUse,
|
|
})
|
|
|
|
assert.Contains(t, out.String(), toShareWithUser1.Username)
|
|
assert.Contains(t, out.String(), toShareWithUser2.Username)
|
|
})
|
|
|
|
t.Run("ShareWithUsers_Roles", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var (
|
|
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{
|
|
DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) {
|
|
dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)}
|
|
}),
|
|
})
|
|
orgOwner = coderdtest.CreateFirstUser(t, client)
|
|
workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID))
|
|
workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
|
|
OwnerID: workspaceOwner.ID,
|
|
OrganizationID: orgOwner.OrganizationID,
|
|
}).Do().Workspace
|
|
_, toShareWithUser = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID)
|
|
)
|
|
|
|
ctx := testutil.Context(t, testutil.WaitMedium)
|
|
inv, root := clitest.New(t, "sharing", "add", workspace.Name,
|
|
"--user", fmt.Sprintf("%s:admin", toShareWithUser.Username),
|
|
)
|
|
clitest.SetupConfig(t, workspaceOwnerClient, root)
|
|
|
|
out := new(bytes.Buffer)
|
|
inv.Stdout = out
|
|
err := inv.WithContext(ctx).Run()
|
|
require.NoError(t, err)
|
|
|
|
acl, err := workspaceOwnerClient.WorkspaceACL(inv.Context(), workspace.ID)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, acl.Users, codersdk.WorkspaceUser{
|
|
MinimalUser: codersdk.MinimalUser{
|
|
ID: toShareWithUser.ID,
|
|
Username: toShareWithUser.Username,
|
|
Name: toShareWithUser.Name,
|
|
AvatarURL: toShareWithUser.AvatarURL,
|
|
},
|
|
Role: codersdk.WorkspaceRoleAdmin,
|
|
})
|
|
|
|
found := false
|
|
for _, line := range strings.Split(out.String(), "\n") {
|
|
if strings.Contains(line, toShareWithUser.Username) && strings.Contains(line, string(codersdk.WorkspaceRoleAdmin)) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, found, fmt.Sprintf("expected to find the username %s and role %s in the command: %s", toShareWithUser.Username, codersdk.WorkspaceRoleAdmin, out.String()))
|
|
})
|
|
}
|
|
|
|
func TestSharingStatus(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("ListSharedUsers", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var (
|
|
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{
|
|
DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) {
|
|
dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)}
|
|
}),
|
|
})
|
|
orgOwner = coderdtest.CreateFirstUser(t, client)
|
|
workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID))
|
|
workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
|
|
OwnerID: workspaceOwner.ID,
|
|
OrganizationID: orgOwner.OrganizationID,
|
|
}).Do().Workspace
|
|
_, toShareWithUser = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID)
|
|
ctx = testutil.Context(t, testutil.WaitMedium)
|
|
)
|
|
|
|
err := client.UpdateWorkspaceACL(ctx, workspace.ID, codersdk.UpdateWorkspaceACL{
|
|
UserRoles: map[string]codersdk.WorkspaceRole{
|
|
toShareWithUser.ID.String(): codersdk.WorkspaceRoleUse,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
inv, root := clitest.New(t, "sharing", "status", workspace.Name)
|
|
clitest.SetupConfig(t, workspaceOwnerClient, root)
|
|
|
|
out := new(bytes.Buffer)
|
|
inv.Stdout = out
|
|
err = inv.WithContext(ctx).Run()
|
|
require.NoError(t, err)
|
|
|
|
found := false
|
|
for _, line := range strings.Split(out.String(), "\n") {
|
|
if strings.Contains(line, toShareWithUser.Username) && strings.Contains(line, string(codersdk.WorkspaceRoleUse)) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, found, "expected to find username %s with role %s in the output: %s", toShareWithUser.Username, codersdk.WorkspaceRoleUse, out.String())
|
|
})
|
|
}
|
|
|
|
func TestSharingRemove(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("RemoveSharedUser_Simple", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var (
|
|
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{
|
|
DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) {
|
|
dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)}
|
|
}),
|
|
})
|
|
orgOwner = coderdtest.CreateFirstUser(t, client)
|
|
workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID))
|
|
workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
|
|
OwnerID: workspaceOwner.ID,
|
|
OrganizationID: orgOwner.OrganizationID,
|
|
}).Do().Workspace
|
|
_, toRemoveUser = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID)
|
|
_, toShareWithUser = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID)
|
|
)
|
|
|
|
ctx := testutil.Context(t, testutil.WaitMedium)
|
|
|
|
// Share the workspace with a user to later remove
|
|
err := client.UpdateWorkspaceACL(ctx, workspace.ID, codersdk.UpdateWorkspaceACL{
|
|
UserRoles: map[string]codersdk.WorkspaceRole{
|
|
toShareWithUser.ID.String(): codersdk.WorkspaceRoleUse,
|
|
toRemoveUser.ID.String(): codersdk.WorkspaceRoleUse,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
inv, root := clitest.New(t,
|
|
"sharing",
|
|
"remove",
|
|
workspace.Name,
|
|
"--user", toRemoveUser.Username,
|
|
)
|
|
clitest.SetupConfig(t, workspaceOwnerClient, root)
|
|
|
|
out := new(bytes.Buffer)
|
|
inv.Stdout = out
|
|
err = inv.WithContext(ctx).Run()
|
|
require.NoError(t, err)
|
|
|
|
acl, err := workspaceOwnerClient.WorkspaceACL(inv.Context(), workspace.ID)
|
|
require.NoError(t, err)
|
|
|
|
removedCorrectUser := true
|
|
keptOtherUser := false
|
|
for _, user := range acl.Users {
|
|
if user.ID == toRemoveUser.ID {
|
|
removedCorrectUser = false
|
|
}
|
|
|
|
if user.ID == toShareWithUser.ID {
|
|
keptOtherUser = true
|
|
}
|
|
}
|
|
assert.True(t, removedCorrectUser)
|
|
assert.True(t, keptOtherUser)
|
|
})
|
|
|
|
t.Run("RemoveSharedUser_Multiple", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var (
|
|
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{
|
|
DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) {
|
|
dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)}
|
|
}),
|
|
})
|
|
orgOwner = coderdtest.CreateFirstUser(t, client)
|
|
workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID))
|
|
workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
|
|
OwnerID: workspaceOwner.ID,
|
|
OrganizationID: orgOwner.OrganizationID,
|
|
}).Do().Workspace
|
|
_, toRemoveUser1 = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID)
|
|
_, toRemoveUser2 = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID)
|
|
)
|
|
|
|
ctx := testutil.Context(t, testutil.WaitMedium)
|
|
|
|
// Share the workspace with a user to later remove
|
|
err := client.UpdateWorkspaceACL(ctx, workspace.ID, codersdk.UpdateWorkspaceACL{
|
|
UserRoles: map[string]codersdk.WorkspaceRole{
|
|
toRemoveUser2.ID.String(): codersdk.WorkspaceRoleUse,
|
|
toRemoveUser1.ID.String(): codersdk.WorkspaceRoleUse,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
inv, root := clitest.New(t,
|
|
"sharing",
|
|
"remove",
|
|
workspace.Name,
|
|
fmt.Sprintf("--user=%s,%s", toRemoveUser1.Username, toRemoveUser2.Username),
|
|
)
|
|
clitest.SetupConfig(t, workspaceOwnerClient, root)
|
|
|
|
out := new(bytes.Buffer)
|
|
inv.Stdout = out
|
|
err = inv.WithContext(ctx).Run()
|
|
require.NoError(t, err)
|
|
|
|
acl, err := workspaceOwnerClient.WorkspaceACL(inv.Context(), workspace.ID)
|
|
require.NoError(t, err)
|
|
assert.Empty(t, acl.Users)
|
|
})
|
|
}
|