feat(19-04): add users.handle, HandleGenerator and user.Created
Generate a unique mention handle on API register and admin create, and fire user.Created from both paths so listeners run in the same write. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
30
updates/202610160002_add_handle_to_users.go
Normal file
30
updates/202610160002_add_handle_to_users.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package updates
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// addHandleToUsers adds users.handle, the unique @mention identity (D-15),
|
||||
// only when it is missing: an application whose users table already has the
|
||||
// column (added on PHP by chatchannels) keeps it and its data. The rollback
|
||||
// is a no-op for the same reason: the column may predate this plugin.
|
||||
var addHandleToUsers = []*gormigrate.Migration{
|
||||
{
|
||||
ID: "202610160002_add_handle_to_users",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Exec(`ALTER TABLE users ADD COLUMN IF NOT EXISTS handle VARCHAR(255) NULL`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Exec(`CREATE UNIQUE INDEX IF NOT EXISTS users_handle_unique ON users (handle)`).Error
|
||||
},
|
||||
Rollback: func(*gorm.DB) error {
|
||||
// No-op: the shared users column may predate the plugin.
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register(addHandleToUsers...)
|
||||
}
|
||||
@@ -50,6 +50,7 @@ func TestCreateOrganisationsMigration(t *testing.T) {
|
||||
"202610040002_add_users_last_seen",
|
||||
"202610040003_create_frontend_permissions",
|
||||
"202610050001_create_oauth_identities",
|
||||
"202610160002_add_handle_to_users",
|
||||
}
|
||||
if len(ids) != len(want) {
|
||||
t.Fatalf("history = %v", ids)
|
||||
@@ -60,9 +61,9 @@ func TestCreateOrganisationsMigration(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// OAuth identities, the three admin migrations, API tokens, user groups, jwt blacklist,
|
||||
// Handle, OAuth identities, the three admin migrations, API tokens, user groups, jwt blacklist,
|
||||
// throttle, extend-users, then organisations.
|
||||
for range 10 {
|
||||
for range 11 {
|
||||
if err := m.RollbackLast(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ func TestUserGroupsMigration(t *testing.T) {
|
||||
t.Fatalf("users_groups primary key = %q", pk)
|
||||
}
|
||||
|
||||
// OAuth identities, frontend permissions, last seen, API tokens, user permissions, then user groups.
|
||||
for range 6 {
|
||||
// Handle, OAuth identities, frontend permissions, last seen, API tokens, user permissions, then user groups.
|
||||
for range 7 {
|
||||
if err := m.RollbackLast(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -47,9 +47,9 @@ func TestExtendUsersMigration(t *testing.T) {
|
||||
if !row.HasSelfSetPassword || row.IsActivated || row.MarketingConsent || row.IsOnboarded {
|
||||
t.Fatalf("defaults = %+v", row)
|
||||
}
|
||||
// OAuth identities, the three admin migrations, API tokens, user groups, jwt blacklist,
|
||||
// Handle, OAuth identities, the three admin migrations, API tokens, user groups, jwt blacklist,
|
||||
// throttle, then extend-users.
|
||||
for range 9 {
|
||||
for range 10 {
|
||||
if err := m.RollbackLast(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -88,8 +88,8 @@ func TestCreateUserThrottleMigration(t *testing.T) {
|
||||
t.Fatalf("missing column %s", col)
|
||||
}
|
||||
}
|
||||
// OAuth identities, the three admin migrations, API tokens, user groups, jwt blacklist, then throttle.
|
||||
for range 8 {
|
||||
// Handle, OAuth identities, the three admin migrations, API tokens, user groups, jwt blacklist, then throttle.
|
||||
for range 9 {
|
||||
if err := m.RollbackLast(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -120,8 +120,8 @@ func TestCreateJwtBlacklistMigration(t *testing.T) {
|
||||
t.Fatalf("missing column %s", col)
|
||||
}
|
||||
}
|
||||
// OAuth identities, the three admin migrations, API tokens, user groups, then jwt blacklist.
|
||||
for range 7 {
|
||||
// Handle, OAuth identities, the three admin migrations, API tokens, user groups, then jwt blacklist.
|
||||
for range 8 {
|
||||
if err := m.RollbackLast(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user