From 51ca71c503fc9d7bde05a6eefc03f5ffd39046ec Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Tue, 30 Jun 2026 04:08:50 +0000 Subject: [PATCH 01/10] feat: database migration --- .../000534_all_service_accounts_all_the_time.down.sql | 2 ++ .../000534_all_service_accounts_all_the_time.up.sql | 9 +++++++++ 2 files changed, 11 insertions(+) create mode 100644 coderd/database/migrations/000534_all_service_accounts_all_the_time.down.sql create mode 100644 coderd/database/migrations/000534_all_service_accounts_all_the_time.up.sql diff --git a/coderd/database/migrations/000534_all_service_accounts_all_the_time.down.sql b/coderd/database/migrations/000534_all_service_accounts_all_the_time.down.sql new file mode 100644 index 0000000000000..b668af387a28f --- /dev/null +++ b/coderd/database/migrations/000534_all_service_accounts_all_the_time.down.sql @@ -0,0 +1,2 @@ +-- We do not track which users were converted to service accounts. +-- This is a destructive migration that cannot be undone. diff --git a/coderd/database/migrations/000534_all_service_accounts_all_the_time.up.sql b/coderd/database/migrations/000534_all_service_accounts_all_the_time.up.sql new file mode 100644 index 0000000000000..b3d5556adb973 --- /dev/null +++ b/coderd/database/migrations/000534_all_service_accounts_all_the_time.up.sql @@ -0,0 +1,9 @@ +-- Convert legacy users created with login_type 'none' into service accounts. +-- Service accounts require empty email per users_email_not_empty. +UPDATE users +SET is_service_account = true, + email = '' +WHERE login_type = 'none' + AND is_service_account = false + -- `prebuilds@system` user should not convert it to service account. + AND is_system = false; From 8285fccc4c32f0c79ca0409a0b9ddf550575bf84 Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Tue, 30 Jun 2026 04:22:45 +0000 Subject: [PATCH 02/10] feat: align cli and backend to disallow `login_type = none` --- cli/usercreate.go | 6 ++++++ coderd/userauth_test.go | 16 +++++++++++----- coderd/users.go | 7 +++++++ coderd/users_test.go | 11 +++++------ 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/cli/usercreate.go b/cli/usercreate.go index 1a904582593e2..24c8ea606a361 100644 --- a/cli/usercreate.go +++ b/cli/usercreate.go @@ -49,6 +49,12 @@ func (r *RootCmd) userCreate() *serpent.Command { if disableLogin && loginType != "" { return xerrors.New("You cannot specify both --disable-login and --login-type") } + if disableLogin && !serviceAccount { + return xerrors.New("--disable-login is deprecated. Use --service-account for machine-to-machine access.") + } + if loginType == string(codersdk.LoginTypeNone) && !serviceAccount { + return xerrors.New("Login type 'none' requires --service-account.") + } client, err := r.InitClient(inv) if err != nil { diff --git a/coderd/userauth_test.go b/coderd/userauth_test.go index 8e4c230c4f308..7e7f748af43ec 100644 --- a/coderd/userauth_test.go +++ b/coderd/userauth_test.go @@ -153,13 +153,19 @@ func TestUserLogin(t *testing.T) { t.Run("LoginTypeNone", func(t *testing.T) { t.Parallel() - anotherClient, anotherUser := coderdtest.CreateAnotherUserMutators(t, client, user.OrganizationID, nil, func(r *codersdk.CreateUserRequestWithOrgs) { - r.Password = "" - r.UserLoginType = codersdk.LoginTypeNone + client, db := coderdtest.NewWithDatabase(t, nil) + first := coderdtest.CreateFirstUser(t, client) + + noneUser := dbgen.User(t, db, database.User{ + LoginType: database.LoginTypeNone, + }) + dbgen.OrganizationMember(t, db, database.OrganizationMember{ + OrganizationID: first.OrganizationID, + UserID: noneUser.ID, }) - _, err := anotherClient.LoginWithPassword(context.Background(), codersdk.LoginWithPasswordRequest{ - Email: anotherUser.Email, + _, err := client.LoginWithPassword(context.Background(), codersdk.LoginWithPasswordRequest{ + Email: noneUser.Email, Password: "SomeSecurePassword!", }) require.Error(t, err) diff --git a/coderd/users.go b/coderd/users.go index d067a637347f3..8725598598aed 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -488,6 +488,13 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) { req.UserLoginType = codersdk.LoginTypePassword } + if !req.ServiceAccount && req.UserLoginType == codersdk.LoginTypeNone { + httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ + Message: "Login type 'none' requires a service account.", + }) + return + } + if req.UserLoginType != codersdk.LoginTypePassword && req.Password != "" { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: fmt.Sprintf("Password cannot be set for non-password (%q) authentication.", req.UserLoginType), diff --git a/coderd/users_test.go b/coderd/users_test.go index 2893c7126b4a2..2a621e2772dc1 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -952,18 +952,17 @@ func TestPostUsers(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() - user, err := client.CreateUserWithOrgs(ctx, codersdk.CreateUserRequestWithOrgs{ + _, err := client.CreateUserWithOrgs(ctx, codersdk.CreateUserRequestWithOrgs{ OrganizationIDs: []uuid.UUID{first.OrganizationID}, Email: "another@user.org", Username: "someone-else", Password: "", UserLoginType: codersdk.LoginTypeNone, }) - require.NoError(t, err) - - found, err := client.User(ctx, user.ID.String()) - require.NoError(t, err) - require.Equal(t, found.LoginType, codersdk.LoginTypeNone) + var apiErr *codersdk.Error + require.ErrorAs(t, err, &apiErr) + require.Equal(t, http.StatusBadRequest, apiErr.StatusCode()) + require.Contains(t, apiErr.Message, "service account") }) t.Run("CreateOIDCLoginType", func(t *testing.T) { From 519607e89d0e0c9e13e908d419797206702eecde Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Tue, 30 Jun 2026 04:31:16 +0000 Subject: [PATCH 03/10] fix: rename migration to `legacy_none_login_to_password.*` --- .../000534_all_service_accounts_all_the_time.down.sql | 2 -- .../000534_all_service_accounts_all_the_time.up.sql | 9 --------- .../000534_legacy_none_login_to_password.down.sql | 2 ++ .../000534_legacy_none_login_to_password.up.sql | 9 +++++++++ 4 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 coderd/database/migrations/000534_all_service_accounts_all_the_time.down.sql delete mode 100644 coderd/database/migrations/000534_all_service_accounts_all_the_time.up.sql create mode 100644 coderd/database/migrations/000534_legacy_none_login_to_password.down.sql create mode 100644 coderd/database/migrations/000534_legacy_none_login_to_password.up.sql diff --git a/coderd/database/migrations/000534_all_service_accounts_all_the_time.down.sql b/coderd/database/migrations/000534_all_service_accounts_all_the_time.down.sql deleted file mode 100644 index b668af387a28f..0000000000000 --- a/coderd/database/migrations/000534_all_service_accounts_all_the_time.down.sql +++ /dev/null @@ -1,2 +0,0 @@ --- We do not track which users were converted to service accounts. --- This is a destructive migration that cannot be undone. diff --git a/coderd/database/migrations/000534_all_service_accounts_all_the_time.up.sql b/coderd/database/migrations/000534_all_service_accounts_all_the_time.up.sql deleted file mode 100644 index b3d5556adb973..0000000000000 --- a/coderd/database/migrations/000534_all_service_accounts_all_the_time.up.sql +++ /dev/null @@ -1,9 +0,0 @@ --- Convert legacy users created with login_type 'none' into service accounts. --- Service accounts require empty email per users_email_not_empty. -UPDATE users -SET is_service_account = true, - email = '' -WHERE login_type = 'none' - AND is_service_account = false - -- `prebuilds@system` user should not convert it to service account. - AND is_system = false; diff --git a/coderd/database/migrations/000534_legacy_none_login_to_password.down.sql b/coderd/database/migrations/000534_legacy_none_login_to_password.down.sql new file mode 100644 index 0000000000000..b6ae9ef796235 --- /dev/null +++ b/coderd/database/migrations/000534_legacy_none_login_to_password.down.sql @@ -0,0 +1,2 @@ +-- We do not track which users had login_type 'none' before this migration. +-- This is a destructive migration that cannot be undone. diff --git a/coderd/database/migrations/000534_legacy_none_login_to_password.up.sql b/coderd/database/migrations/000534_legacy_none_login_to_password.up.sql new file mode 100644 index 0000000000000..82c13214e7169 --- /dev/null +++ b/coderd/database/migrations/000534_legacy_none_login_to_password.up.sql @@ -0,0 +1,9 @@ +-- Convert legacy users created with login_type 'none' to password auth. +-- OSS deployments cannot create service accounts without Premium. Existing +-- API tokens remain valid; admins can set a password if password login is +-- desired. +UPDATE users +SET login_type = 'password' +WHERE login_type = 'none' + AND is_service_account = false + AND is_system = false; From 0006c5439edaffb8209573935ad4137012df5ca6 Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Mon, 20 Jul 2026 02:58:25 +0000 Subject: [PATCH 04/10] =?UTF-8?q?=F0=9F=A4=96=20fix(coderd/database)!:=20r?= =?UTF-8?q?enumber=20legacy=20none->password=20migration=20to=20000548?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ord.down.sql => 000548_legacy_none_login_to_password.down.sql} | 0 ...assword.up.sql => 000548_legacy_none_login_to_password.up.sql} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename coderd/database/migrations/{000534_legacy_none_login_to_password.down.sql => 000548_legacy_none_login_to_password.down.sql} (100%) rename coderd/database/migrations/{000534_legacy_none_login_to_password.up.sql => 000548_legacy_none_login_to_password.up.sql} (100%) diff --git a/coderd/database/migrations/000534_legacy_none_login_to_password.down.sql b/coderd/database/migrations/000548_legacy_none_login_to_password.down.sql similarity index 100% rename from coderd/database/migrations/000534_legacy_none_login_to_password.down.sql rename to coderd/database/migrations/000548_legacy_none_login_to_password.down.sql diff --git a/coderd/database/migrations/000534_legacy_none_login_to_password.up.sql b/coderd/database/migrations/000548_legacy_none_login_to_password.up.sql similarity index 100% rename from coderd/database/migrations/000534_legacy_none_login_to_password.up.sql rename to coderd/database/migrations/000548_legacy_none_login_to_password.up.sql From 3ceb7218108ffede0655be7c9c550dc17969de7a Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Mon, 20 Jul 2026 03:18:45 +0000 Subject: [PATCH 05/10] =?UTF-8?q?=F0=9F=A4=96=20test(coderd):=20converted?= =?UTF-8?q?=20login=5Ftype=3Dnone=20users=20cannot=20authenticate=20with?= =?UTF-8?q?=20a=20password?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coderd/users_test.go | 56 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/coderd/users_test.go b/coderd/users_test.go index bc4fea6ecc5c0..1b3916fe9b72a 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -287,6 +287,62 @@ func TestPostLogin(t *testing.T) { require.NotContains(t, apiErr.Message, string(codersdk.LoginTypeOIDC)) }) + // Regression: the legacy `login_type = 'none'` migration converts these + // accounts to password auth, but they have no password hash. Converting + // login type must never let someone authenticate with an empty or guessed + // password. + t.Run("ConvertedNoneUserHasNoUsablePassword", func(t *testing.T) { + t.Parallel() + client, db := coderdtest.NewWithDatabase(t, nil) + ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) + defer cancel() + + // A legacy machine user was created with login_type 'none' and no + // password. dbgen.User substitutes a random hash for an empty one, so + // clear it explicitly to match the real account. + noneUser := dbgen.User(t, db, database.User{ + Email: "legacy-machine-user@coder.com", + LoginType: database.LoginTypeNone, + }) + //nolint:gocritic // Test setup requires a system context to clear the hash. + err := db.UpdateUserHashedPassword(dbauthz.AsSystemRestricted(ctx), database.UpdateUserHashedPasswordParams{ + ID: noneUser.ID, + HashedPassword: []byte{}, + }) + require.NoError(t, err) + + // Apply the migration's conversion: login_type 'none' -> 'password'. + //nolint:gocritic // Test setup requires a system context to convert the login type. + _, err = db.UpdateUserLoginType(dbauthz.AsSystemRestricted(ctx), database.UpdateUserLoginTypeParams{ + NewLoginType: database.LoginTypePassword, + UserID: noneUser.ID, + }) + require.NoError(t, err) + + // Neither an empty password nor a guessed one may authenticate. An empty + // password is rejected by request validation (400); a non-empty guess + // fails the hash comparison against the empty stored hash (401). Both must + // deny access. + cases := []struct { + name string + password string + wantStatus int + }{ + {"EmptyPassword", "", http.StatusBadRequest}, + {"GuessedPassword", "hunter2", http.StatusUnauthorized}, + } + for _, tc := range cases { + anonClient := codersdk.New(client.URL) + _, err := anonClient.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{ + Email: noneUser.Email, + Password: tc.password, + }) + var apiErr *codersdk.Error + require.ErrorAs(t, err, &apiErr, "%s must not authenticate", tc.name) + require.Equal(t, tc.wantStatus, apiErr.StatusCode(), "%s", tc.name) + } + }) + t.Run("Suspended", func(t *testing.T) { t.Parallel() auditor := audit.NewMock() From 5bc979403b9a05959b7a71b99a6a24adb969f39e Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Mon, 20 Jul 2026 03:36:01 +0000 Subject: [PATCH 06/10] =?UTF-8?q?=F0=9F=A4=96=20test(coderd/database/migra?= =?UTF-8?q?tions):=20verify=20000548=20converts=20only=20legacy=20none=20u?= =?UTF-8?q?sers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coderd/database/migrations/migrate_test.go | 83 ++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/coderd/database/migrations/migrate_test.go b/coderd/database/migrations/migrate_test.go index 11897bec83c5e..6abd7e9ea1853 100644 --- a/coderd/database/migrations/migrate_test.go +++ b/coderd/database/migrations/migrate_test.go @@ -1717,6 +1717,89 @@ func TestMigration000546ChatHistoryAPIKeyConstraints(t *testing.T) { } } +func TestMigration000548LegacyNoneLoginToPassword(t *testing.T) { + t.Parallel() + + const priorMigrationVersion = 547 + + sqlDB := testSQLDB(t) + + next, err := migrations.Stepper(sqlDB) + require.NoError(t, err) + for { + version, more, err := next() + require.NoError(t, err) + if !more || version == priorMigrationVersion { + break + } + } + + ctx := testutil.Context(t, testutil.WaitSuperLong) + now := time.Now().UTC().Truncate(time.Microsecond) + + legacyNoneID := uuid.New() + serviceAccountID := uuid.New() + systemID := uuid.New() + passwordID := uuid.New() + + // A legacy machine user: login_type 'none', not a service account, not a + // system user. This is the only row the migration should convert. + _, err = sqlDB.ExecContext(ctx, + `INSERT INTO users (id, username, email, hashed_password, created_at, updated_at, status, rbac_roles, login_type, is_service_account, is_system) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, + legacyNoneID, "legacy-none", "legacy-none@test.com", []byte{}, now, now, "active", pq.StringArray{}, "none", false, false) + require.NoError(t, err) + + // A service account must keep login_type 'none' (a CHECK constraint requires + // service accounts to use 'none' and an empty email). + _, err = sqlDB.ExecContext(ctx, + `INSERT INTO users (id, username, email, hashed_password, created_at, updated_at, status, rbac_roles, login_type, is_service_account, is_system) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, + serviceAccountID, "service-account", "", []byte{}, now, now, "active", pq.StringArray{}, "none", true, false) + require.NoError(t, err) + + // A system user must be left untouched. + _, err = sqlDB.ExecContext(ctx, + `INSERT INTO users (id, username, email, hashed_password, created_at, updated_at, status, rbac_roles, login_type, is_service_account, is_system) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, + systemID, "system-user", "system@test.com", []byte{}, now, now, "active", pq.StringArray{}, "none", false, true) + require.NoError(t, err) + + // An existing password user must be left untouched. + _, err = sqlDB.ExecContext(ctx, + `INSERT INTO users (id, username, email, hashed_password, created_at, updated_at, status, rbac_roles, login_type, is_service_account, is_system) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, + passwordID, "password-user", "password@test.com", []byte("hashed"), now, now, "active", pq.StringArray{}, "password", false, false) + require.NoError(t, err) + + migrationSQL, err := os.ReadFile("000548_legacy_none_login_to_password.up.sql") + require.NoError(t, err) + _, err = sqlDB.ExecContext(ctx, string(migrationSQL)) + require.NoError(t, err) + + getUser := func(t *testing.T, id uuid.UUID) (loginType, email string) { + t.Helper() + err := sqlDB.QueryRowContext(ctx, + `SELECT login_type::text, email FROM users WHERE id = $1`, id).Scan(&loginType, &email) + require.NoError(t, err) + return loginType, email + } + + // The legacy machine user is converted to password auth with its email + // preserved. + gotLoginType, gotEmail := getUser(t, legacyNoneID) + require.Equal(t, "password", gotLoginType) + require.Equal(t, "legacy-none@test.com", gotEmail) + + // Service accounts, system users, and existing password users are unchanged. + gotLoginType, _ = getUser(t, serviceAccountID) + require.Equal(t, "none", gotLoginType) + gotLoginType, _ = getUser(t, systemID) + require.Equal(t, "none", gotLoginType) + gotLoginType, _ = getUser(t, passwordID) + require.Equal(t, "password", gotLoginType) +} + func TestMigration000498SoftDeleteStaleWorkspaceAgents(t *testing.T) { t.Parallel() From f66df67a5a87bb3d39e4e1a31a9347e473c34966 Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Mon, 20 Jul 2026 03:55:40 +0000 Subject: [PATCH 07/10] =?UTF-8?q?=F0=9F=A4=96=20docs(cli/usercreate):=20po?= =?UTF-8?q?int=20deprecated=20--disable-login=20help=20at=20--service-acco?= =?UTF-8?q?unt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cli/usercreate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/usercreate.go b/cli/usercreate.go index 24c8ea606a361..7174e3becb9bf 100644 --- a/cli/usercreate.go +++ b/cli/usercreate.go @@ -206,7 +206,7 @@ Create a workspace `+pretty.Sprint(cliui.DefaultStyles.Code, "coder create")+`! { Flag: "disable-login", Hidden: true, - Description: "Deprecated: Use '--login-type=none'. \nDisabling login for a user prevents the user from authenticating via password or IdP login. Authentication requires an API key/token generated by an admin. " + + Description: "Deprecated: Use '--service-account' for machine-to-machine access. \nDisabling login for a user prevents the user from authenticating via password or IdP login. Authentication requires an API key/token generated by an admin. " + "Be careful when using this flag as it can lock the user out of their account.", Value: serpent.BoolOf(&disableLogin), }, From 0e0b4f793e93a664c2da49b591cc6a6a4603a3b2 Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Tue, 21 Jul 2026 04:47:39 +0000 Subject: [PATCH 08/10] =?UTF-8?q?=F0=9F=A4=96=20fix(cli/usercreate):=20add?= =?UTF-8?q?ress=20review,=20group=20non-service-account=20checks,=20add=20?= =?UTF-8?q?tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cli/usercreate.go | 21 ++++++++++----------- cli/usercreate_test.go | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/cli/usercreate.go b/cli/usercreate.go index 7174e3becb9bf..dbbe92be664af 100644 --- a/cli/usercreate.go +++ b/cli/usercreate.go @@ -44,16 +44,15 @@ func (r *RootCmd) userCreate() *serpent.Command { case disableLogin: return xerrors.New("You cannot use --disable-login with --service-account") } - } - - if disableLogin && loginType != "" { - return xerrors.New("You cannot specify both --disable-login and --login-type") - } - if disableLogin && !serviceAccount { - return xerrors.New("--disable-login is deprecated. Use --service-account for machine-to-machine access.") - } - if loginType == string(codersdk.LoginTypeNone) && !serviceAccount { - return xerrors.New("Login type 'none' requires --service-account.") + } else { + switch { + case disableLogin && loginType != "": + return xerrors.New("You cannot specify both --disable-login and --login-type") + case disableLogin: + return xerrors.New("--disable-login is deprecated. Use --service-account for machine-to-machine access.") + case loginType == string(codersdk.LoginTypeNone): + return xerrors.New("Login type 'none' is deprecated. Use --service-account for machine-to-machine access.") + } } client, err := r.InitClient(inv) @@ -206,7 +205,7 @@ Create a workspace `+pretty.Sprint(cliui.DefaultStyles.Code, "coder create")+`! { Flag: "disable-login", Hidden: true, - Description: "Deprecated: Use '--service-account' for machine-to-machine access. \nDisabling login for a user prevents the user from authenticating via password or IdP login. Authentication requires an API key/token generated by an admin. " + + Description: "Deprecated: Use --service-account (requires Premium) for machine-to-machine access. \nDisabling login for a user prevents the user from authenticating via password or IdP login. Authentication requires an API key/token generated by an admin. " + "Be careful when using this flag as it can lock the user out of their account.", Value: serpent.BoolOf(&disableLogin), }, diff --git a/cli/usercreate_test.go b/cli/usercreate_test.go index 7453d371238f7..5fc9c86d81f7c 100644 --- a/cli/usercreate_test.go +++ b/cli/usercreate_test.go @@ -160,6 +160,21 @@ func TestUserCreate(t *testing.T) { args: []string{"--service-account", "-u", "dean", "--password", "1n5ecureP4ssw0rd!"}, err: "You cannot use --password with --service-account", }, + { + name: "DisableLogin", + args: []string{"--disable-login", "-u", "dean"}, + err: "--disable-login is deprecated. Use --service-account for machine-to-machine access.", + }, + { + name: "LoginTypeNone", + args: []string{"--login-type", "none", "-u", "dean"}, + err: "Login type 'none' is deprecated. Use --service-account for machine-to-machine access.", + }, + { + name: "DisableLoginWithLoginType", + args: []string{"--disable-login", "--login-type", "password", "-u", "dean"}, + err: "You cannot specify both --disable-login and --login-type", + }, } for _, tt := range tests { From ef679640f500fb0a8f8e5c471a529fcd3d54ea2c Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Tue, 21 Jul 2026 05:51:57 +0000 Subject: [PATCH 09/10] =?UTF-8?q?=F0=9F=A4=96=20fix(coderd/database)!:=20r?= =?UTF-8?q?enumber=20legacy=20none->password=20migration=20to=20000549?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...wn.sql => 000549_legacy_none_login_to_password.down.sql} | 0 ...d.up.sql => 000549_legacy_none_login_to_password.up.sql} | 0 coderd/database/migrations/migrate_test.go | 6 +++--- 3 files changed, 3 insertions(+), 3 deletions(-) rename coderd/database/migrations/{000548_legacy_none_login_to_password.down.sql => 000549_legacy_none_login_to_password.down.sql} (100%) rename coderd/database/migrations/{000548_legacy_none_login_to_password.up.sql => 000549_legacy_none_login_to_password.up.sql} (100%) diff --git a/coderd/database/migrations/000548_legacy_none_login_to_password.down.sql b/coderd/database/migrations/000549_legacy_none_login_to_password.down.sql similarity index 100% rename from coderd/database/migrations/000548_legacy_none_login_to_password.down.sql rename to coderd/database/migrations/000549_legacy_none_login_to_password.down.sql diff --git a/coderd/database/migrations/000548_legacy_none_login_to_password.up.sql b/coderd/database/migrations/000549_legacy_none_login_to_password.up.sql similarity index 100% rename from coderd/database/migrations/000548_legacy_none_login_to_password.up.sql rename to coderd/database/migrations/000549_legacy_none_login_to_password.up.sql diff --git a/coderd/database/migrations/migrate_test.go b/coderd/database/migrations/migrate_test.go index 6abd7e9ea1853..0202ee80a3833 100644 --- a/coderd/database/migrations/migrate_test.go +++ b/coderd/database/migrations/migrate_test.go @@ -1717,10 +1717,10 @@ func TestMigration000546ChatHistoryAPIKeyConstraints(t *testing.T) { } } -func TestMigration000548LegacyNoneLoginToPassword(t *testing.T) { +func TestMigration000549LegacyNoneLoginToPassword(t *testing.T) { t.Parallel() - const priorMigrationVersion = 547 + const priorMigrationVersion = 548 sqlDB := testSQLDB(t) @@ -1772,7 +1772,7 @@ func TestMigration000548LegacyNoneLoginToPassword(t *testing.T) { passwordID, "password-user", "password@test.com", []byte("hashed"), now, now, "active", pq.StringArray{}, "password", false, false) require.NoError(t, err) - migrationSQL, err := os.ReadFile("000548_legacy_none_login_to_password.up.sql") + migrationSQL, err := os.ReadFile("000549_legacy_none_login_to_password.up.sql") require.NoError(t, err) _, err = sqlDB.ExecContext(ctx, string(migrationSQL)) require.NoError(t, err) From 854ce1c862b13fbd5a755e55088ccd4c4d45482a Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Tue, 28 Jul 2026 03:58:53 +0000 Subject: [PATCH 10/10] =?UTF-8?q?=F0=9F=A4=96=20chore(coderd/database/migr?= =?UTF-8?q?ations):=20renumber=20legacy=20none=20login=20migration=20to=20?= =?UTF-8?q?000554?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...wn.sql => 000554_legacy_none_login_to_password.down.sql} | 0 ...d.up.sql => 000554_legacy_none_login_to_password.up.sql} | 0 coderd/database/migrations/migrate_test.go | 6 +++--- 3 files changed, 3 insertions(+), 3 deletions(-) rename coderd/database/migrations/{000549_legacy_none_login_to_password.down.sql => 000554_legacy_none_login_to_password.down.sql} (100%) rename coderd/database/migrations/{000549_legacy_none_login_to_password.up.sql => 000554_legacy_none_login_to_password.up.sql} (100%) diff --git a/coderd/database/migrations/000549_legacy_none_login_to_password.down.sql b/coderd/database/migrations/000554_legacy_none_login_to_password.down.sql similarity index 100% rename from coderd/database/migrations/000549_legacy_none_login_to_password.down.sql rename to coderd/database/migrations/000554_legacy_none_login_to_password.down.sql diff --git a/coderd/database/migrations/000549_legacy_none_login_to_password.up.sql b/coderd/database/migrations/000554_legacy_none_login_to_password.up.sql similarity index 100% rename from coderd/database/migrations/000549_legacy_none_login_to_password.up.sql rename to coderd/database/migrations/000554_legacy_none_login_to_password.up.sql diff --git a/coderd/database/migrations/migrate_test.go b/coderd/database/migrations/migrate_test.go index 0202ee80a3833..f7f2ec7561650 100644 --- a/coderd/database/migrations/migrate_test.go +++ b/coderd/database/migrations/migrate_test.go @@ -1717,10 +1717,10 @@ func TestMigration000546ChatHistoryAPIKeyConstraints(t *testing.T) { } } -func TestMigration000549LegacyNoneLoginToPassword(t *testing.T) { +func TestMigration000554LegacyNoneLoginToPassword(t *testing.T) { t.Parallel() - const priorMigrationVersion = 548 + const priorMigrationVersion = 553 sqlDB := testSQLDB(t) @@ -1772,7 +1772,7 @@ func TestMigration000549LegacyNoneLoginToPassword(t *testing.T) { passwordID, "password-user", "password@test.com", []byte("hashed"), now, now, "active", pq.StringArray{}, "password", false, false) require.NoError(t, err) - migrationSQL, err := os.ReadFile("000549_legacy_none_login_to_password.up.sql") + migrationSQL, err := os.ReadFile("000554_legacy_none_login_to_password.up.sql") require.NoError(t, err) _, err = sqlDB.ExecContext(ctx, string(migrationSQL)) require.NoError(t, err)