feat: assign IM user account numbers

This commit is contained in:
richjohnrambo
2026-09-10 21:51:23 +08:00
parent 51fee50343
commit 928a45ecfb
6 changed files with 112 additions and 27 deletions
+54 -13
View File
@@ -9,6 +9,7 @@ import (
"database/sql"
"encoding/json"
"errors"
"fmt"
"hash/fnv"
"sort"
"strconv"
@@ -762,19 +763,21 @@ func (a *adapter) CreateDb(reset bool) error {
if _, err = tx.Exec(
`CREATE TABLE im_users(
id BIGINT NOT NULL,
username VARCHAR(32) NOT NULL,
createdat DATETIME(3) NOT NULL,
updatedat DATETIME(3) NOT NULL,
state SMALLINT NOT NULL DEFAULT 0,
stateat DATETIME(3),
access JSON,
lastseen DATETIME,
useragent VARCHAR(255) DEFAULT '',
phone VARCHAR(32),
public JSON,
trusted JSON,
id BIGINT NOT NULL,
account_no INT UNSIGNED NOT NULL DEFAULT 0,
username VARCHAR(32) NOT NULL,
createdat DATETIME(3) NOT NULL,
updatedat DATETIME(3) NOT NULL,
state SMALLINT NOT NULL DEFAULT 0,
stateat DATETIME(3),
access JSON,
lastseen DATETIME,
useragent VARCHAR(255) DEFAULT '',
phone VARCHAR(32),
public JSON,
trusted JSON,
PRIMARY KEY(id),
UNIQUE INDEX uk_im_users_account_no(account_no),
UNIQUE INDEX users_username(username),
UNIQUE INDEX users_phone(phone),
INDEX users_state_stateat(state, stateat),
@@ -2230,8 +2233,18 @@ func (a *adapter) UserCreate(user *t.User) error {
user.Phone = canonicalPhone
phone = canonicalPhone
}
if _, err = tx.Exec("INSERT INTO im_users(id,username,createdat,updatedat,state,access,phone,public,trusted) VALUES(?,?,?,?,?,?,?,?,?)",
releaseAccountNoLock, err := lockUserAccountNoSequence(ctx, tx)
if err != nil {
return err
}
defer releaseAccountNoLock()
accountNo, err := nextUserAccountNo(ctx, tx)
if err != nil {
return err
}
if _, err = tx.Exec("INSERT INTO im_users(id,account_no,username,createdat,updatedat,state,access,phone,public,trusted) VALUES(?,?,?,?,?,?,?,?,?,?)",
decoded_uid,
accountNo,
user.Username,
user.CreatedAt,
user.UpdatedAt,
@@ -2260,6 +2273,34 @@ func (a *adapter) UserCreate(user *t.User) error {
return tx.Commit()
}
func lockUserAccountNoSequence(ctx context.Context, tx *sqlx.Tx) (func(), error) {
var locked sql.NullInt64
if err := tx.QueryRowContext(ctx, "SELECT GET_LOCK(CONCAT(DATABASE(), ':im_users_account_no'), 10)").Scan(&locked); err != nil {
return nil, err
}
if !locked.Valid || locked.Int64 != 1 {
return nil, fmt.Errorf("lock user account number sequence timeout")
}
return func() {
_, _ = tx.ExecContext(ctx, "SELECT RELEASE_LOCK(CONCAT(DATABASE(), ':im_users_account_no'))")
}, nil
}
func nextUserAccountNo(ctx context.Context, tx *sqlx.Tx) (int64, error) {
var current sql.NullInt64
err := tx.QueryRowContext(ctx, "SELECT account_no FROM im_users ORDER BY account_no DESC LIMIT 1 FOR UPDATE").Scan(&current)
if err == sql.ErrNoRows {
return 1000, nil
}
if err != nil {
return 0, err
}
if !current.Valid || current.Int64 < 999 {
return 1000, nil
}
return current.Int64 + 1, nil
}
// TenantAuthAddRecord adds the user's Basic authentication record.
func (a *adapter) TenantAuthAddRecord(tenantID t.TenantID, uid t.Uid,
authLvl auth.Level, secret []byte, expires time.Time) error {