Skip to content

Commit 2bf2f88

Browse files
authored
feat: implement 'is_default' org field (coder#12142)
The first organization created is now marked as "default". This is to allow "single org" behavior as we move to a multi org codebase. It is intentional that the user cannot change the default org at this stage. Only 1 default org can exist, and it is always the first org. Closes: coder#11961
1 parent a67362f commit 2bf2f88

19 files changed

+101
-16
lines changed

coderd/apidoc/docs.go

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

coderd/apidoc/swagger.json

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmem/dbmem.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5285,6 +5285,7 @@ func (q *FakeQuerier) InsertOrganization(_ context.Context, arg database.InsertO
52855285
Name: arg.Name,
52865286
CreatedAt: arg.CreatedAt,
52875287
UpdatedAt: arg.UpdatedAt,
5288+
IsDefault: len(q.organizations) == 0,
52885289
}
52895290
q.organizations = append(q.organizations, organization)
52905291
return organization, nil

coderd/database/dump.sql

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DROP INDEX organizations_single_default_org;
2+
ALTER TABLE organizations DROP COLUMN is_default;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
-- This migration is intended to maintain the existing behavior of single org
2+
-- deployments, while allowing for multi-org deployments. By default, this organization
3+
-- will be used when no organization is specified.
4+
ALTER TABLE organizations ADD COLUMN is_default BOOLEAN NOT NULL DEFAULT FALSE;
5+
6+
-- Only 1 org should ever be set to is_default.
7+
create unique index organizations_single_default_org on organizations (is_default)
8+
where is_default = true;
9+
10+
UPDATE
11+
organizations
12+
SET
13+
is_default = true
14+
WHERE
15+
-- The first organization created will be the default.
16+
id = (SELECT id FROM organizations ORDER BY organizations.created_at ASC LIMIT 1 );

coderd/database/models.go

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

coderd/database/querier_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,34 @@ func TestUserChangeLoginType(t *testing.T) {
494494
require.Equal(t, bobExpPass, bob.HashedPassword, "hashed password should not change")
495495
}
496496

497+
func TestDefaultOrg(t *testing.T) {
498+
t.Parallel()
499+
if testing.Short() {
500+
t.SkipNow()
501+
}
502+
503+
sqlDB := testSQLDB(t)
504+
err := migrations.Up(sqlDB)
505+
require.NoError(t, err)
506+
db := database.New(sqlDB)
507+
ctx := context.Background()
508+
509+
// Should start with 0 orgs
510+
all, err := db.GetOrganizations(ctx)
511+
require.NoError(t, err)
512+
require.Len(t, all, 0)
513+
514+
org, err := db.InsertOrganization(ctx, database.InsertOrganizationParams{
515+
ID: uuid.New(),
516+
Name: "default",
517+
Description: "",
518+
CreatedAt: dbtime.Now(),
519+
UpdatedAt: dbtime.Now(),
520+
})
521+
require.NoError(t, err)
522+
require.True(t, org.IsDefault, "first org should always be default")
523+
}
524+
497525
type tvArgs struct {
498526
Status database.ProvisionerJobStatus
499527
// CreateWorkspace is true if we should create a workspace for the template version

coderd/database/queries.sql.go

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

coderd/database/queries/organizations.sql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ WHERE
3939

4040
-- name: InsertOrganization :one
4141
INSERT INTO
42-
organizations (id, "name", description, created_at, updated_at)
42+
organizations (id, "name", description, created_at, updated_at, is_default)
4343
VALUES
44-
($1, $2, $3, $4, $5) RETURNING *;
44+
-- If no organizations exist, and this is the first, make it the default.
45+
($1, $2, $3, $4, $5, (SELECT TRUE FROM organizations LIMIT 1) IS NULL) RETURNING *;

coderd/database/unique_constraint.go

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

coderd/organizations.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,6 @@ func convertOrganization(organization database.Organization) codersdk.Organizati
118118
Name: organization.Name,
119119
CreatedAt: organization.CreatedAt,
120120
UpdatedAt: organization.UpdatedAt,
121+
IsDefault: organization.IsDefault,
121122
}
122123
}

coderd/organizations_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ func TestOrganizationsByUser(t *testing.T) {
2424
require.NoError(t, err)
2525
require.NotNil(t, orgs)
2626
require.Len(t, orgs, 1)
27+
require.True(t, orgs[0].IsDefault, "first org is always default")
28+
29+
// Make an extra org, and it should not be defaulted.
30+
notDefault, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
31+
Name: "another",
32+
})
33+
require.NoError(t, err)
34+
require.False(t, notDefault.IsDefault, "only 1 default org allowed")
2735
}
2836

2937
func TestOrganizationByUserAndName(t *testing.T) {

codersdk/organizations.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type Organization struct {
3030
Name string `json:"name" validate:"required"`
3131
CreatedAt time.Time `json:"created_at" validate:"required" format:"date-time"`
3232
UpdatedAt time.Time `json:"updated_at" validate:"required" format:"date-time"`
33+
IsDefault bool `json:"is_default" validate:"required"`
3334
}
3435

3536
type OrganizationMember struct {

docs/api/organizations.md

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

docs/api/schemas.md

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

docs/api/users.md

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

site/src/api/typesGenerated.ts

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

site/src/testHelpers/entities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const MockOrganization: TypesGen.Organization = {
1616
name: "Test Organization",
1717
created_at: "",
1818
updated_at: "",
19+
is_default: true,
1920
};
2021

2122
export const MockTemplateDAUResponse: TypesGen.DAUsResponse = {

0 commit comments

Comments
 (0)