feat: edit org display names and descriptions (#13474)

This commit is contained in:
Kayla Washburn-Love
2024-06-06 10:59:59 -06:00
committed by GitHub
parent 1131772e79
commit 44a70a5bc2
22 changed files with 359 additions and 90 deletions

23
coderd/apidoc/docs.go generated
View File

@ -8973,6 +8973,13 @@ const docTemplate = `{
"name"
],
"properties": {
"description": {
"type": "string"
},
"display_name": {
"description": "DisplayName will default to the same value as ` + "`" + `Name` + "`" + ` if not provided.",
"type": "string"
},
"name": {
"type": "string"
}
@ -10587,6 +10594,7 @@ const docTemplate = `{
"type": "object",
"required": [
"created_at",
"display_name",
"id",
"is_default",
"name",
@ -10597,6 +10605,12 @@ const docTemplate = `{
"type": "string",
"format": "date-time"
},
"description": {
"type": "string"
},
"display_name": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
@ -12305,10 +12319,13 @@ const docTemplate = `{
},
"codersdk.UpdateOrganizationRequest": {
"type": "object",
"required": [
"name"
],
"properties": {
"description": {
"type": "string"
},
"display_name": {
"type": "string"
},
"name": {
"type": "string"
}

View File

@ -7995,6 +7995,13 @@
"type": "object",
"required": ["name"],
"properties": {
"description": {
"type": "string"
},
"display_name": {
"description": "DisplayName will default to the same value as `Name` if not provided.",
"type": "string"
},
"name": {
"type": "string"
}
@ -9516,12 +9523,25 @@
},
"codersdk.Organization": {
"type": "object",
"required": ["created_at", "id", "is_default", "name", "updated_at"],
"required": [
"created_at",
"display_name",
"id",
"is_default",
"name",
"updated_at"
],
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": "string"
},
"display_name": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
@ -11145,8 +11165,13 @@
},
"codersdk.UpdateOrganizationRequest": {
"type": "object",
"required": ["name"],
"properties": {
"description": {
"type": "string"
},
"display_name": {
"type": "string"
},
"name": {
"type": "string"
}

View File

@ -336,6 +336,7 @@ func Organization(t testing.TB, db database.Store, orig database.Organization) d
org, err := db.InsertOrganization(genCtx, database.InsertOrganizationParams{
ID: takeFirst(orig.ID, uuid.New()),
Name: takeFirst(orig.Name, namesgenerator.GetRandomName(1)),
DisplayName: takeFirst(orig.Name, namesgenerator.GetRandomName(1)),
Description: takeFirst(orig.Description, namesgenerator.GetRandomName(1)),
CreatedAt: takeFirst(orig.CreatedAt, dbtime.Now()),
UpdatedAt: takeFirst(orig.UpdatedAt, dbtime.Now()),

View File

@ -86,6 +86,7 @@ func New() database.Store {
defaultOrg, err := q.InsertOrganization(context.Background(), database.InsertOrganizationParams{
ID: uuid.New(),
Name: "first-organization",
DisplayName: "first-organization",
Description: "Builtin default organization.",
CreatedAt: dbtime.Now(),
UpdatedAt: dbtime.Now(),
@ -6179,11 +6180,13 @@ func (q *FakeQuerier) InsertOrganization(_ context.Context, arg database.InsertO
defer q.mutex.Unlock()
organization := database.Organization{
ID: arg.ID,
Name: arg.Name,
CreatedAt: arg.CreatedAt,
UpdatedAt: arg.UpdatedAt,
IsDefault: len(q.organizations) == 0,
ID: arg.ID,
Name: arg.Name,
DisplayName: arg.DisplayName,
Description: arg.Description,
CreatedAt: arg.CreatedAt,
UpdatedAt: arg.UpdatedAt,
IsDefault: len(q.organizations) == 0,
}
q.organizations = append(q.organizations, organization)
return organization, nil
@ -7324,6 +7327,8 @@ func (q *FakeQuerier) UpdateOrganization(_ context.Context, arg database.UpdateO
for i, org := range q.organizations {
if org.ID == arg.ID {
org.Name = arg.Name
org.DisplayName = arg.DisplayName
org.Description = arg.Description
q.organizations[i] = org
return org, nil
}

View File

@ -585,7 +585,8 @@ CREATE TABLE organizations (
description text NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
is_default boolean DEFAULT false NOT NULL
is_default boolean DEFAULT false NOT NULL,
display_name text NOT NULL
);
CREATE TABLE parameter_schemas (

View File

@ -0,0 +1,2 @@
alter table organizations
drop column display_name;

View File

@ -0,0 +1,10 @@
-- This default is just a temporary thing to avoid null errors when first creating the column.
alter table organizations
add column display_name text not null default '';
update organizations
set display_name = name;
-- We can remove the default now that everything has been copied.
alter table organizations
alter column display_name drop default;

View File

@ -1927,6 +1927,7 @@ type Organization struct {
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
IsDefault bool `db:"is_default" json:"is_default"`
DisplayName string `db:"display_name" json:"display_name"`
}
type OrganizationMember struct {

View File

@ -3949,7 +3949,7 @@ func (q *sqlQuerier) DeleteOrganization(ctx context.Context, id uuid.UUID) error
const getDefaultOrganization = `-- name: GetDefaultOrganization :one
SELECT
id, name, description, created_at, updated_at, is_default
id, name, description, created_at, updated_at, is_default, display_name
FROM
organizations
WHERE
@ -3968,13 +3968,14 @@ func (q *sqlQuerier) GetDefaultOrganization(ctx context.Context) (Organization,
&i.CreatedAt,
&i.UpdatedAt,
&i.IsDefault,
&i.DisplayName,
)
return i, err
}
const getOrganizationByID = `-- name: GetOrganizationByID :one
SELECT
id, name, description, created_at, updated_at, is_default
id, name, description, created_at, updated_at, is_default, display_name
FROM
organizations
WHERE
@ -3991,13 +3992,14 @@ func (q *sqlQuerier) GetOrganizationByID(ctx context.Context, id uuid.UUID) (Org
&i.CreatedAt,
&i.UpdatedAt,
&i.IsDefault,
&i.DisplayName,
)
return i, err
}
const getOrganizationByName = `-- name: GetOrganizationByName :one
SELECT
id, name, description, created_at, updated_at, is_default
id, name, description, created_at, updated_at, is_default, display_name
FROM
organizations
WHERE
@ -4016,13 +4018,14 @@ func (q *sqlQuerier) GetOrganizationByName(ctx context.Context, name string) (Or
&i.CreatedAt,
&i.UpdatedAt,
&i.IsDefault,
&i.DisplayName,
)
return i, err
}
const getOrganizations = `-- name: GetOrganizations :many
SELECT
id, name, description, created_at, updated_at, is_default
id, name, description, created_at, updated_at, is_default, display_name
FROM
organizations
`
@ -4043,6 +4046,7 @@ func (q *sqlQuerier) GetOrganizations(ctx context.Context) ([]Organization, erro
&i.CreatedAt,
&i.UpdatedAt,
&i.IsDefault,
&i.DisplayName,
); err != nil {
return nil, err
}
@ -4059,7 +4063,7 @@ func (q *sqlQuerier) GetOrganizations(ctx context.Context) ([]Organization, erro
const getOrganizationsByUserID = `-- name: GetOrganizationsByUserID :many
SELECT
id, name, description, created_at, updated_at, is_default
id, name, description, created_at, updated_at, is_default, display_name
FROM
organizations
WHERE
@ -4089,6 +4093,7 @@ func (q *sqlQuerier) GetOrganizationsByUserID(ctx context.Context, userID uuid.U
&i.CreatedAt,
&i.UpdatedAt,
&i.IsDefault,
&i.DisplayName,
); err != nil {
return nil, err
}
@ -4105,15 +4110,16 @@ func (q *sqlQuerier) GetOrganizationsByUserID(ctx context.Context, userID uuid.U
const insertOrganization = `-- name: InsertOrganization :one
INSERT INTO
organizations (id, "name", description, created_at, updated_at, is_default)
organizations (id, "name", display_name, description, created_at, updated_at, is_default)
VALUES
-- If no organizations exist, and this is the first, make it the default.
($1, $2, $3, $4, $5, (SELECT TRUE FROM organizations LIMIT 1) IS NULL) RETURNING id, name, description, created_at, updated_at, is_default
($1, $2, $3, $4, $5, $6, (SELECT TRUE FROM organizations LIMIT 1) IS NULL) RETURNING id, name, description, created_at, updated_at, is_default, display_name
`
type InsertOrganizationParams struct {
ID uuid.UUID `db:"id" json:"id"`
Name string `db:"name" json:"name"`
DisplayName string `db:"display_name" json:"display_name"`
Description string `db:"description" json:"description"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
@ -4123,6 +4129,7 @@ func (q *sqlQuerier) InsertOrganization(ctx context.Context, arg InsertOrganizat
row := q.db.QueryRowContext(ctx, insertOrganization,
arg.ID,
arg.Name,
arg.DisplayName,
arg.Description,
arg.CreatedAt,
arg.UpdatedAt,
@ -4135,6 +4142,7 @@ func (q *sqlQuerier) InsertOrganization(ctx context.Context, arg InsertOrganizat
&i.CreatedAt,
&i.UpdatedAt,
&i.IsDefault,
&i.DisplayName,
)
return i, err
}
@ -4144,20 +4152,30 @@ UPDATE
organizations
SET
updated_at = $1,
name = $2
name = $2,
display_name = $3,
description = $4
WHERE
id = $3
RETURNING id, name, description, created_at, updated_at, is_default
id = $5
RETURNING id, name, description, created_at, updated_at, is_default, display_name
`
type UpdateOrganizationParams struct {
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
Name string `db:"name" json:"name"`
ID uuid.UUID `db:"id" json:"id"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
Name string `db:"name" json:"name"`
DisplayName string `db:"display_name" json:"display_name"`
Description string `db:"description" json:"description"`
ID uuid.UUID `db:"id" json:"id"`
}
func (q *sqlQuerier) UpdateOrganization(ctx context.Context, arg UpdateOrganizationParams) (Organization, error) {
row := q.db.QueryRowContext(ctx, updateOrganization, arg.UpdatedAt, arg.Name, arg.ID)
row := q.db.QueryRowContext(ctx, updateOrganization,
arg.UpdatedAt,
arg.Name,
arg.DisplayName,
arg.Description,
arg.ID,
)
var i Organization
err := row.Scan(
&i.ID,
@ -4166,6 +4184,7 @@ func (q *sqlQuerier) UpdateOrganization(ctx context.Context, arg UpdateOrganizat
&i.CreatedAt,
&i.UpdatedAt,
&i.IsDefault,
&i.DisplayName,
)
return i, err
}

View File

@ -49,17 +49,19 @@ WHERE
-- name: InsertOrganization :one
INSERT INTO
organizations (id, "name", description, created_at, updated_at, is_default)
organizations (id, "name", display_name, description, created_at, updated_at, is_default)
VALUES
-- If no organizations exist, and this is the first, make it the default.
($1, $2, $3, $4, $5, (SELECT TRUE FROM organizations LIMIT 1) IS NULL) RETURNING *;
(@id, @name, @display_name, @description, @created_at, @updated_at, (SELECT TRUE FROM organizations LIMIT 1) IS NULL) RETURNING *;
-- name: UpdateOrganization :one
UPDATE
organizations
SET
updated_at = @updated_at,
name = @name
name = @name,
display_name = @display_name,
description = @description
WHERE
id = @id
RETURNING *;

View File

@ -46,25 +46,27 @@ func init() {
valid := NameValid(str)
return valid == nil
}
for _, tag := range []string{"username", "template_name", "workspace_name", "oauth2_app_name"} {
for _, tag := range []string{"username", "organization_name", "template_name", "workspace_name", "oauth2_app_name"} {
err := Validate.RegisterValidation(tag, nameValidator)
if err != nil {
panic(err)
}
}
templateDisplayNameValidator := func(fl validator.FieldLevel) bool {
displayNameValidator := func(fl validator.FieldLevel) bool {
f := fl.Field().Interface()
str, ok := f.(string)
if !ok {
return false
}
valid := TemplateDisplayNameValid(str)
valid := DisplayNameValid(str)
return valid == nil
}
err := Validate.RegisterValidation("template_display_name", templateDisplayNameValidator)
if err != nil {
panic(err)
for _, displayNameTag := range []string{"organization_display_name", "template_display_name"} {
err := Validate.RegisterValidation(displayNameTag, displayNameValidator)
if err != nil {
panic(err)
}
}
templateVersionNameValidator := func(fl validator.FieldLevel) bool {
@ -76,7 +78,7 @@ func init() {
valid := TemplateVersionNameValid(str)
return valid == nil
}
err = Validate.RegisterValidation("template_version_name", templateVersionNameValidator)
err := Validate.RegisterValidation("template_version_name", templateVersionNameValidator)
if err != nil {
panic(err)
}

View File

@ -65,8 +65,8 @@ func TemplateVersionNameValid(str string) error {
return nil
}
// TemplateDisplayNameValid returns whether the input string is a valid template display name.
func TemplateDisplayNameValid(str string) error {
// DisplayNameValid returns whether the input string is a valid template display name.
func DisplayNameValid(str string) error {
if len(str) == 0 {
return nil // empty display_name is correct
}

View File

@ -117,7 +117,7 @@ func TestTemplateDisplayNameValid(t *testing.T) {
testCase := testCase
t.Run(testCase.Name, func(t *testing.T) {
t.Parallel()
valid := httpapi.TemplateDisplayNameValid(testCase.Name)
valid := httpapi.DisplayNameValid(testCase.Name)
require.Equal(t, testCase.Valid, valid == nil)
})
}

View File

@ -74,12 +74,17 @@ func (api *API) postOrganizations(rw http.ResponseWriter, r *http.Request) {
var organization database.Organization
err = api.Database.InTx(func(tx database.Store) error {
if req.DisplayName == "" {
req.DisplayName = req.Name
}
organization, err = tx.InsertOrganization(ctx, database.InsertOrganizationParams{
ID: uuid.New(),
Name: req.Name,
DisplayName: req.DisplayName,
Description: req.Description,
CreatedAt: dbtime.Now(),
UpdatedAt: dbtime.Now(),
Description: "",
})
if err != nil {
return xerrors.Errorf("create organization: %w", err)
@ -146,11 +151,38 @@ func (api *API) patchOrganization(rw http.ResponseWriter, r *http.Request) {
return
}
organization, err := api.Database.UpdateOrganization(ctx, database.UpdateOrganizationParams{
ID: organization.ID,
UpdatedAt: dbtime.Now(),
Name: req.Name,
err := database.ReadModifyUpdate(api.Database, func(tx database.Store) error {
var err error
organization, err = tx.GetOrganizationByID(ctx, organization.ID)
if err != nil {
return err
}
updateOrgParams := database.UpdateOrganizationParams{
UpdatedAt: dbtime.Now(),
ID: organization.ID,
Name: organization.Name,
DisplayName: organization.DisplayName,
Description: organization.Description,
}
if req.Name != "" {
updateOrgParams.Name = req.Name
}
if req.DisplayName != "" {
updateOrgParams.DisplayName = req.DisplayName
}
if req.Description != "" {
updateOrgParams.Description = req.Description
}
organization, err = tx.UpdateOrganization(ctx, updateOrgParams)
if err != nil {
return err
}
return nil
})
if httpapi.Is404Error(err) {
httpapi.ResourceNotFound(rw)
return
@ -212,10 +244,12 @@ func (api *API) deleteOrganization(rw http.ResponseWriter, r *http.Request) {
// convertOrganization consumes the database representation and outputs an API friendly representation.
func convertOrganization(organization database.Organization) codersdk.Organization {
return codersdk.Organization{
ID: organization.ID,
Name: organization.Name,
CreatedAt: organization.CreatedAt,
UpdatedAt: organization.UpdatedAt,
IsDefault: organization.IsDefault,
ID: organization.ID,
Name: organization.Name,
DisplayName: organization.DisplayName,
Description: organization.Description,
CreatedAt: organization.CreatedAt,
UpdatedAt: organization.UpdatedAt,
IsDefault: organization.IsDefault,
}
}

View File

@ -20,7 +20,8 @@ func TestMultiOrgFetch(t *testing.T) {
makeOrgs := []string{"foo", "bar", "baz"}
for _, name := range makeOrgs {
_, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: name,
Name: name,
DisplayName: name,
})
require.NoError(t, err)
}
@ -45,7 +46,8 @@ func TestOrganizationsByUser(t *testing.T) {
// Make an extra org, and it should not be defaulted.
notDefault, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "another",
Name: "another",
DisplayName: "Another",
})
require.NoError(t, err)
require.False(t, notDefault.IsDefault, "only 1 default org allowed")
@ -73,7 +75,8 @@ func TestOrganizationByUserAndName(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitLong)
org, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "another",
Name: "another",
DisplayName: "Another",
})
require.NoError(t, err)
_, err = other.OrganizationByUserAndName(ctx, codersdk.Me, org.Name)
@ -106,23 +109,58 @@ func TestPostOrganizationsByUser(t *testing.T) {
org, err := client.Organization(ctx, user.OrganizationID)
require.NoError(t, err)
_, err = client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: org.Name,
Name: org.Name,
DisplayName: org.DisplayName,
})
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusConflict, apiErr.StatusCode())
})
t.Run("InvalidName", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
_ = coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitLong)
_, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "A name which is definitely not url safe",
DisplayName: "New",
})
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
})
t.Run("Create", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
_ = coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitLong)
_, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "new",
DisplayName: "New",
Description: "A new organization to love and cherish forever.",
})
require.NoError(t, err)
require.Equal(t, "new", o.Name)
require.Equal(t, "New", o.DisplayName)
require.Equal(t, "A new organization to love and cherish forever.", o.Description)
})
t.Run("CreateWithoutExplicitDisplayName", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
_ = coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitLong)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "new",
})
require.NoError(t, err)
require.Equal(t, "new", o.Name)
require.Equal(t, "new", o.DisplayName) // should match the given `Name`
})
}
@ -137,7 +175,8 @@ func TestPatchOrganizationsByUser(t *testing.T) {
originalOrg, err := client.Organization(ctx, user.OrganizationID)
require.NoError(t, err)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "something-unique",
Name: "something-unique",
DisplayName: "Something Unique",
})
require.NoError(t, err)
@ -156,7 +195,8 @@ func TestPatchOrganizationsByUser(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "something-unique",
Name: "something-unique",
DisplayName: "Something Unique",
})
require.NoError(t, err)
@ -168,6 +208,26 @@ func TestPatchOrganizationsByUser(t *testing.T) {
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
})
t.Run("InvalidName", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
_ = coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitMedium)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "something-unique",
DisplayName: "Something Unique",
})
require.NoError(t, err)
_, err = client.UpdateOrganization(ctx, o.ID.String(), codersdk.UpdateOrganizationRequest{
Name: "something unique but not url safe",
})
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
})
t.Run("UpdateById", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
@ -175,7 +235,8 @@ func TestPatchOrganizationsByUser(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "new",
Name: "new",
DisplayName: "New",
})
require.NoError(t, err)
@ -193,7 +254,8 @@ func TestPatchOrganizationsByUser(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "new",
Name: "new",
DisplayName: "New",
})
require.NoError(t, err)
@ -202,6 +264,49 @@ func TestPatchOrganizationsByUser(t *testing.T) {
})
require.NoError(t, err)
require.Equal(t, "new-new", o.Name)
require.Equal(t, "New", o.DisplayName) // didn't change
})
t.Run("UpdateDisplayName", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
_ = coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitMedium)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "new",
DisplayName: "New",
})
require.NoError(t, err)
o, err = client.UpdateOrganization(ctx, o.Name, codersdk.UpdateOrganizationRequest{
DisplayName: "The Newest One",
})
require.NoError(t, err)
require.Equal(t, "new", o.Name) // didn't change
require.Equal(t, "The Newest One", o.DisplayName)
})
t.Run("UpdateDescription", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
_ = coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitMedium)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "new",
DisplayName: "New",
})
require.NoError(t, err)
o, err = client.UpdateOrganization(ctx, o.Name, codersdk.UpdateOrganizationRequest{
Description: "wow, this organization description is so updated!",
})
require.NoError(t, err)
require.Equal(t, "new", o.Name) // didn't change
require.Equal(t, "New", o.DisplayName) // didn't change
require.Equal(t, "wow, this organization description is so updated!", o.Description)
})
}
@ -229,7 +334,8 @@ func TestDeleteOrganizationsByUser(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "doomed",
Name: "doomed",
DisplayName: "Doomed",
})
require.NoError(t, err)
@ -244,7 +350,8 @@ func TestDeleteOrganizationsByUser(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
o, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
Name: "doomed",
Name: "doomed",
DisplayName: "Doomed",
})
require.NoError(t, err)

View File

@ -728,7 +728,7 @@ func TestWorkspaceDeleteSuspendedUser(t *testing.T) {
validateCalls++
if userSuspended {
// Simulate the user being suspended from the IDP too.
return "", http.StatusForbidden, fmt.Errorf("user is suspended")
return "", http.StatusForbidden, xerrors.New("user is suspended")
}
return "OK", 0, nil
},