feat: migrate IM identity and snowflake primary keys
This commit is contained in:
+116
-123
@@ -152,7 +152,8 @@ func (a *adapter) TenantUserGet(id t.TenantID, uid t.Uid) (*t.User, error) {
|
||||
defer cancel()
|
||||
}
|
||||
var user t.User
|
||||
err = a.db.GetContext(ctx, &user, "SELECT * FROM im_users WHERE tenant_id=? AND id=? AND state!=?",
|
||||
err = a.db.GetContext(ctx, &user, `SELECT tenant_id,id,createdat,updatedat,state,stateat,access,lastseen,useragent,
|
||||
COALESCE(phone,'') AS phone,public,trusted FROM im_users WHERE tenant_id=? AND id=? AND state!=?`,
|
||||
id, decodeUID(uid), t.StateDeleted)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
@@ -200,9 +201,11 @@ func (a *adapter) tenantUserGetAllTx(ctx context.Context, tx *sqlx.Tx, id t.Tena
|
||||
var q string
|
||||
var params []any
|
||||
if a.tenantScopedDB {
|
||||
q, params, _ = sqlx.In("SELECT * FROM im_users WHERE id IN (?) AND state!=?", args, t.StateDeleted)
|
||||
q, params, _ = sqlx.In(`SELECT id,createdat,updatedat,state,stateat,access,lastseen,useragent,
|
||||
COALESCE(phone,'') AS phone,public,trusted FROM im_users WHERE id IN (?) AND state!=?`, args, t.StateDeleted)
|
||||
} else {
|
||||
q, params, _ = sqlx.In("SELECT * FROM im_users WHERE tenant_id=? AND id IN (?) AND state!=?", id, args, t.StateDeleted)
|
||||
q, params, _ = sqlx.In(`SELECT tenant_id,id,createdat,updatedat,state,stateat,access,lastseen,useragent,
|
||||
COALESCE(phone,'') AS phone,public,trusted FROM im_users WHERE tenant_id=? AND id IN (?) AND state!=?`, id, args, t.StateDeleted)
|
||||
}
|
||||
query := a.db.Rebind(q)
|
||||
var rows *sqlx.Rows
|
||||
@@ -308,9 +311,6 @@ func (a *adapter) TenantUserDelete(id t.TenantID, uid t.Uid, hard bool) error {
|
||||
if _, err = tx.Exec("DELETE FROM im_credentials WHERE userid=?", decoded); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tx.Exec("DELETE FROM im_usertags WHERE tenant_id=? AND userid=?", id, decoded); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tx.Exec("DELETE FROM im_users WHERE tenant_id=? AND id=?", id, decoded); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -389,7 +389,11 @@ func (a *adapter) TenantUserUpdate(id t.TenantID, uid t.Uid, update map[string]a
|
||||
}
|
||||
}()
|
||||
decoded := decodeUID(uid)
|
||||
update = withoutUserTags(update)
|
||||
cols, args := common.UpdateByMap(update)
|
||||
if len(cols) == 0 {
|
||||
return tx.Commit()
|
||||
}
|
||||
args = append(args, id, decoded)
|
||||
res, err := tx.Exec("UPDATE im_users SET "+strings.Join(cols, ",")+" WHERE tenant_id=? AND id=?", args...)
|
||||
if err != nil {
|
||||
@@ -404,14 +408,6 @@ func (a *adapter) TenantUserUpdate(id t.TenantID, uid t.Uid, update map[string]a
|
||||
return err
|
||||
}
|
||||
}
|
||||
if tags := common.ExtractTags(update); tags != nil {
|
||||
if _, err = tx.Exec("DELETE FROM im_usertags WHERE tenant_id=? AND userid=?", id, decoded); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addTenantTags(tx, id, "im_usertags", "userid", decoded, tags, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
@@ -426,43 +422,7 @@ func (a *adapter) TenantUserUpdateTags(id t.TenantID, uid t.Uid, add, remove, re
|
||||
if a.tenantScopedDB {
|
||||
return a.UserUpdateTags(uid, add, remove, reset)
|
||||
}
|
||||
ctx, cancel := a.getContextForTx()
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
tx, err := a.db.BeginTxx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
decoded := decodeUID(uid)
|
||||
if reset != nil {
|
||||
if _, err = tx.Exec("DELETE FROM im_usertags WHERE tenant_id=? AND userid=?", id, decoded); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
add, remove = reset, nil
|
||||
}
|
||||
if err = addTenantTags(tx, id, "im_usertags", "userid", decoded, add, reset == nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(remove) > 0 {
|
||||
q, params, _ := sqlx.In("DELETE FROM im_usertags WHERE tenant_id=? AND userid=? AND tag IN (?)", id, decoded, remove)
|
||||
if _, err = tx.Exec(tx.Rebind(q), params...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var allTags []string
|
||||
if err = tx.Select(&allTags, "SELECT tag FROM im_usertags WHERE tenant_id=? AND userid=?", id, decoded); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = tx.Exec("UPDATE im_users SET tags=? WHERE tenant_id=? AND id=?", t.StringSlice(allTags), id, decoded); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return allTags, tx.Commit()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (a *adapter) TenantUserUnreadCount(id t.TenantID, uids ...t.Uid) (map[t.Uid]int, error) {
|
||||
@@ -1520,7 +1480,7 @@ func (a *adapter) TenantFind(id t.TenantID, caller, promoPrefix string, req [][]
|
||||
stateConstraint := ""
|
||||
if activeOnly {
|
||||
args = append(args, t.StateOK)
|
||||
stateConstraint = "u.state=? AND "
|
||||
stateConstraint = "t.state=? AND "
|
||||
}
|
||||
index := make(map[string]struct{})
|
||||
for _, tag := range allTags {
|
||||
@@ -1531,27 +1491,7 @@ func (a *adapter) TenantFind(id t.TenantID, caller, promoPrefix string, req [][]
|
||||
if promoPrefix != "" {
|
||||
matcher = "SUM(CASE WHEN LOCATE('" + promoPrefix + "', tg.tag)=1 THEN 20 ELSE 1 END)"
|
||||
}
|
||||
query := "SELECT u.id,u.createdat,u.updatedat,0,u.access,0 AS subcnt,u.public,u.trusted,u.tags," + matcher + " AS matches " +
|
||||
"FROM im_users AS u JOIN im_usertags AS tg ON tg.tenant_id=u.tenant_id AND tg.userid=u.id " +
|
||||
"WHERE u.tenant_id=? AND " + stateConstraint + "tg.tag IN (?" + strings.Repeat(",?", len(allTags)-1) + ") " +
|
||||
"GROUP BY u.id,u.createdat,u.updatedat,u.access,u.public,u.trusted,u.tags "
|
||||
if len(allReq) > 0 {
|
||||
q, addArgs := common.DisjunctionSql(req, "tg.tag")
|
||||
query += q
|
||||
args = append(args, addArgs...)
|
||||
}
|
||||
query += "UNION ALL "
|
||||
args = append(args, id)
|
||||
if activeOnly {
|
||||
args = append(args, t.StateOK)
|
||||
stateConstraint = "t.state=? AND "
|
||||
} else {
|
||||
stateConstraint = ""
|
||||
}
|
||||
for _, tag := range allTags {
|
||||
args = append(args, tag)
|
||||
}
|
||||
query += "SELECT t.name AS topic,t.createdat,t.updatedat,t.usebt,t.access,t.subcnt,t.public,t.trusted,t.tags," + matcher + " AS matches " +
|
||||
query := "SELECT t.name AS topic,t.createdat,t.updatedat,t.usebt,t.access,t.subcnt,t.public,t.trusted,t.tags," + matcher + " AS matches " +
|
||||
"FROM im_topics AS t JOIN im_topictags AS tg ON t.tenant_id=tg.tenant_id AND t.name=tg.topic " +
|
||||
"WHERE t.tenant_id=? AND " + stateConstraint + "tg.tag IN (?" + strings.Repeat(",?", len(allTags)-1) + ") " +
|
||||
"GROUP BY t.name,t.createdat,t.updatedat,t.usebt,t.access,t.subcnt,t.public,t.trusted,t.tags "
|
||||
@@ -1622,9 +1562,7 @@ func (a *adapter) TenantFindOne(id t.TenantID, tag string) (string, error) {
|
||||
}
|
||||
rows, err := a.db.QueryxContext(ctx,
|
||||
"SELECT tp.name AS topic FROM im_topics AS tp LEFT JOIN im_topictags AS tt ON tp.tenant_id=tt.tenant_id AND tp.name=tt.topic "+
|
||||
"WHERE tp.tenant_id=? AND tt.tag=? UNION ALL "+
|
||||
"SELECT u.id AS topic FROM im_users AS u LEFT JOIN im_usertags AS ut ON u.tenant_id=ut.tenant_id AND ut.userid=u.id "+
|
||||
"WHERE u.tenant_id=? AND ut.tag=? LIMIT 1", id, tag, id, tag)
|
||||
"WHERE tp.tenant_id=? AND tt.tag=? LIMIT 1", id, tag)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -3816,7 +3754,11 @@ func (a *adapter) TenantUserProfileGet(id t.TenantID, uid t.Uid) (*t.UserProfile
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx, `INSERT IGNORE INTO im_user_profiles(user_id,public_account) VALUES(?,?)`, decodeUID(uid), uid.UserId()); err != nil {
|
||||
profileID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx, `INSERT IGNORE INTO im_user_profiles(id,user_id,public_account) VALUES(?,?,?)`, profileID, decodeUID(uid), uid.UserId()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a.userProfileByUID(ctx, uid)
|
||||
@@ -3839,7 +3781,11 @@ func (a *adapter) TenantUserProfileUpdate(id t.TenantID, uid t.Uid, patch t.User
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx, `INSERT IGNORE INTO im_user_profiles(user_id,public_account) VALUES(?,?)`, decodeUID(uid), uid.UserId()); err != nil {
|
||||
profileID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx, `INSERT IGNORE INTO im_user_profiles(id,user_id,public_account) VALUES(?,?,?)`, profileID, decodeUID(uid), uid.UserId()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sets := []string{"version=version+1", "updated_at=CURRENT_TIMESTAMP(3)"}
|
||||
@@ -3873,6 +3819,10 @@ func (a *adapter) TenantUserProfileUpdate(id t.TenantID, uid t.Uid, patch t.User
|
||||
sets = append(sets, "region=?")
|
||||
args = append(args, strings.TrimSpace(*patch.Region))
|
||||
}
|
||||
if patch.Email != nil {
|
||||
sets = append(sets, "email=?")
|
||||
args = append(args, strings.TrimSpace(*patch.Email))
|
||||
}
|
||||
args = append(args, decodeUID(uid), patch.Version)
|
||||
res, err := a.db.ExecContext(ctx, `UPDATE im_user_profiles SET `+strings.Join(sets, ",")+` WHERE user_id=? AND version=?`, args...)
|
||||
if err != nil {
|
||||
@@ -3902,7 +3852,11 @@ func (a *adapter) TenantUserPrivacyGet(id t.TenantID, uid t.Uid) (*t.UserPrivacy
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx, `INSERT IGNORE INTO im_user_privacy_settings(user_id,add_me_methods) VALUES(?,'{"account":true,"phone":true,"qr":true,"group":true}')`, decodeUID(uid)); err != nil {
|
||||
privacyID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx, `INSERT IGNORE INTO im_user_privacy_settings(id,user_id,add_me_methods) VALUES(?,?,'{"account":true,"phone":true,"qr":true,"group":true}')`, privacyID, decodeUID(uid)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a.userPrivacyByUID(ctx, uid)
|
||||
@@ -3925,7 +3879,11 @@ func (a *adapter) TenantUserPrivacyUpdate(id t.TenantID, uid t.Uid, patch t.User
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx, `INSERT IGNORE INTO im_user_privacy_settings(user_id,add_me_methods) VALUES(?,'{"account":true,"phone":true,"qr":true,"group":true}')`, decodeUID(uid)); err != nil {
|
||||
privacyID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx, `INSERT IGNORE INTO im_user_privacy_settings(id,user_id,add_me_methods) VALUES(?,?,'{"account":true,"phone":true,"qr":true,"group":true}')`, privacyID, decodeUID(uid)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sets := []string{"version=version+1", "updated_at=CURRENT_TIMESTAMP(3)"}
|
||||
@@ -4048,12 +4006,16 @@ func (a *adapter) TenantDevicePushTokenUpsert(id t.TenantID, token *t.DevicePush
|
||||
token.Token = strings.TrimSpace(token.Token)
|
||||
token.AppVersion = strings.TrimSpace(token.AppVersion)
|
||||
token.Platform = strings.ToLower(strings.TrimSpace(token.Platform))
|
||||
_, err := a.db.ExecContext(ctx,
|
||||
`INSERT INTO im_device_push_tokens(device_id,user_id,provider,token,app_version,platform,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,?)
|
||||
tokenID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = a.db.ExecContext(ctx,
|
||||
`INSERT INTO im_device_push_tokens(id,device_id,user_id,provider,token,app_version,platform,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?)
|
||||
ON DUPLICATE KEY UPDATE device_id=VALUES(device_id),user_id=VALUES(user_id),provider=VALUES(provider),token=VALUES(token),
|
||||
app_version=VALUES(app_version),platform=VALUES(platform),updated_at=VALUES(updated_at)`,
|
||||
token.DeviceID, decodeUID(token.UserID), token.Provider, token.Token, token.AppVersion, token.Platform, now, now)
|
||||
tokenID, token.DeviceID, decodeUID(token.UserID), token.Provider, token.Token, token.AppVersion, token.Platform, now, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -4515,12 +4477,14 @@ func (a *adapter) userProfileByUID(ctx context.Context, uid t.Uid) (*t.UserProfi
|
||||
Signature string
|
||||
Gender string
|
||||
Region string
|
||||
Email string
|
||||
PublicAccount string `db:"public_account"`
|
||||
Version int
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}{}
|
||||
if err := sqlx.GetContext(ctx, a.db, &row, `SELECT * FROM im_user_profiles WHERE user_id=?`, decodeUID(uid)); err != nil {
|
||||
if err := sqlx.GetContext(ctx, a.db, &row, `SELECT user_id,avatar_file_id,nickname,birth_date,signature,gender,region,email,
|
||||
public_account,version,created_at,updated_at FROM im_user_profiles WHERE user_id=?`, decodeUID(uid)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
profile := &t.UserProfile{
|
||||
@@ -4530,6 +4494,7 @@ func (a *adapter) userProfileByUID(ctx context.Context, uid t.Uid) (*t.UserProfi
|
||||
Signature: row.Signature,
|
||||
Gender: row.Gender,
|
||||
Region: row.Region,
|
||||
Email: row.Email,
|
||||
PublicAccount: row.PublicAccount,
|
||||
Version: row.Version,
|
||||
CreatedAt: row.CreatedAt,
|
||||
@@ -4552,7 +4517,8 @@ func (a *adapter) userPrivacyByUID(ctx context.Context, uid t.Uid) (*t.UserPriva
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}{}
|
||||
if err := sqlx.GetContext(ctx, a.db, &row, `SELECT * FROM im_user_privacy_settings WHERE user_id=?`, decodeUID(uid)); err != nil {
|
||||
if err := sqlx.GetContext(ctx, a.db, &row, `SELECT user_id,add_me_methods,profile_visibility,last_seen_visibility,
|
||||
read_receipts,version,created_at,updated_at FROM im_user_privacy_settings WHERE user_id=?`, decodeUID(uid)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
settings := &t.UserPrivacySettings{
|
||||
@@ -5615,11 +5581,15 @@ func (a *adapter) TenantUserSecurityGetAuthVersion(id t.TenantID, uid t.Uid) (in
|
||||
}
|
||||
decoded := decodeUID(uid)
|
||||
now := t.TimeNow()
|
||||
_, err := a.db.ExecContext(ctx,
|
||||
`INSERT INTO im_user_security(user_id,auth_version,created_at,updated_at)
|
||||
VALUES(?,?,?,?)
|
||||
securityID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
_, err = a.db.ExecContext(ctx,
|
||||
`INSERT INTO im_user_security(id,user_id,auth_version,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?)
|
||||
ON DUPLICATE KEY UPDATE auth_version=auth_version`,
|
||||
decoded, 1, now, now)
|
||||
securityID, decoded, 1, now, now)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -5666,14 +5636,18 @@ func (a *adapter) TenantUserSecurityBumpAuthVersion(id t.TenantID, uid t.Uid, up
|
||||
}
|
||||
}()
|
||||
decoded := decodeUID(uid)
|
||||
securityID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if _, err = tx.ExecContext(ctx,
|
||||
`INSERT INTO im_user_security(user_id,auth_version,password_updated_at,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?)
|
||||
`INSERT INTO im_user_security(id,user_id,auth_version,password_updated_at,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
auth_version=auth_version+1,
|
||||
password_updated_at=VALUES(password_updated_at),
|
||||
updated_at=VALUES(updated_at)`,
|
||||
decoded, 2, updatedAt, updatedAt, updatedAt); err != nil {
|
||||
securityID, decoded, 2, updatedAt, updatedAt, updatedAt); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var version int
|
||||
@@ -5911,12 +5885,16 @@ func (a *adapter) TenantIndependentPasswordUpsert(id t.TenantID, pass *t.Indepen
|
||||
now := t.TimeNow()
|
||||
pass.CreatedAt = now
|
||||
pass.UpdatedAt = now
|
||||
_, err := a.db.ExecContext(ctx,
|
||||
settingsID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = a.db.ExecContext(ctx,
|
||||
`INSERT INTO im_youth_mode_settings
|
||||
(user_id,purpose,password_hash,failed_attempts,locked_until,created_at,updated_at)
|
||||
VALUES(?,?,?,0,NULL,?,?)
|
||||
(id,user_id,purpose,password_hash,failed_attempts,locked_until,created_at,updated_at)
|
||||
VALUES(?,?,?,?,0,NULL,?,?)
|
||||
ON DUPLICATE KEY UPDATE password_hash=VALUES(password_hash),failed_attempts=0,locked_until=NULL,updated_at=VALUES(updated_at)`,
|
||||
decodeUID(pass.UserID), pass.Purpose, pass.PasswordHash, pass.CreatedAt, pass.UpdatedAt)
|
||||
settingsID, decodeUID(pass.UserID), pass.Purpose, pass.PasswordHash, pass.CreatedAt, pass.UpdatedAt)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6478,10 +6456,14 @@ func (a *adapter) TenantFriendRequestAccept(id t.TenantID, requestID string, act
|
||||
row.UpdatedAt = handledAt
|
||||
}
|
||||
for _, pair := range [][2]t.Uid{{applicant, target}, {target, applicant}} {
|
||||
friendshipID, idErr := nextSnowflakeID()
|
||||
if idErr != nil {
|
||||
return nil, idErr
|
||||
}
|
||||
if _, err = tx.ExecContext(ctx,
|
||||
"INSERT INTO im_friendships(user_id,peer_id,status,topic,created_at,updated_at) VALUES(?,?,?,?,?,?) "+
|
||||
"INSERT INTO im_friendships(id,user_id,peer_id,status,topic,created_at,updated_at) VALUES(?,?,?,?,?,?,?) "+
|
||||
"ON DUPLICATE KEY UPDATE status=VALUES(status),topic=VALUES(topic),updated_at=VALUES(updated_at)",
|
||||
decodeUID(pair[0]), decodeUID(pair[1]), t.RelationshipFriend, topic, handledAt, handledAt); err != nil {
|
||||
friendshipID, decodeUID(pair[0]), decodeUID(pair[1]), t.RelationshipFriend, topic, handledAt, handledAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -6642,10 +6624,14 @@ func (a *adapter) TenantFriendshipUpsertPair(id t.TenantID, uid1, uid2 t.Uid, to
|
||||
defer cancel()
|
||||
}
|
||||
for _, pair := range [][2]t.Uid{{uid1, uid2}, {uid2, uid1}} {
|
||||
friendshipID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := a.db.ExecContext(ctx,
|
||||
"INSERT INTO im_friendships(user_id,peer_id,status,topic,created_at,updated_at) VALUES(?,?,?,?,?,?) "+
|
||||
"INSERT INTO im_friendships(id,user_id,peer_id,status,topic,created_at,updated_at) VALUES(?,?,?,?,?,?,?) "+
|
||||
"ON DUPLICATE KEY UPDATE status=VALUES(status),topic=VALUES(topic),updated_at=VALUES(updated_at)",
|
||||
decodeUID(pair[0]), decodeUID(pair[1]), t.RelationshipFriend, topic, now, now); err != nil {
|
||||
friendshipID, decodeUID(pair[0]), decodeUID(pair[1]), t.RelationshipFriend, topic, now, now); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -6680,13 +6666,13 @@ func (a *adapter) TenantFriendshipList(id t.TenantID, uid t.Uid, queryText, init
|
||||
}
|
||||
if q := strings.TrimSpace(queryText); q != "" {
|
||||
like := "%" + q + "%"
|
||||
where = append(where, "(fs.remark LIKE ? OR CAST(u.public AS CHAR) LIKE ? OR CAST(u.tags AS CHAR) LIKE ?)")
|
||||
args = append(args, like, like, like)
|
||||
where = append(where, "(fs.remark LIKE ? OR p.nickname LIKE ? OR p.public_account LIKE ? OR CAST(u.public AS CHAR) LIKE ?)")
|
||||
args = append(args, like, like, like, like)
|
||||
}
|
||||
if initial = strings.TrimSpace(initial); initial != "" {
|
||||
like := initial + "%"
|
||||
where = append(where, "(fs.remark LIKE ? OR CAST(u.public AS CHAR) LIKE ?)")
|
||||
args = append(args, like, like)
|
||||
where = append(where, "(fs.remark LIKE ? OR p.nickname LIKE ? OR CAST(u.public AS CHAR) LIKE ?)")
|
||||
args = append(args, like, like, like)
|
||||
}
|
||||
args = append(args, limit+1)
|
||||
ctx, cancel := a.getContext()
|
||||
@@ -6696,6 +6682,7 @@ func (a *adapter) TenantFriendshipList(id t.TenantID, uid t.Uid, queryText, init
|
||||
rows, err := a.db.QueryxContext(ctx, `SELECT fs.*,u.public,u.trusted
|
||||
FROM im_friendships AS fs
|
||||
JOIN im_users AS u ON u.id=fs.peer_id
|
||||
LEFT JOIN im_user_profiles AS p ON p.user_id=u.id
|
||||
WHERE `+strings.Join(where, " AND ")+`
|
||||
ORDER BY fs.peer_id ASC LIMIT ?`, args...)
|
||||
if err != nil {
|
||||
@@ -6776,7 +6763,8 @@ func (a *adapter) TenantFriendshipGet(id t.TenantID, userID, peerID t.Uid) (*t.F
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}{}
|
||||
err := a.db.GetContext(ctx, &row, "SELECT * FROM im_friendships WHERE user_id=? AND peer_id=?",
|
||||
err := a.db.GetContext(ctx, &row, `SELECT user_id,peer_id,status,remark,topic,created_at,updated_at
|
||||
FROM im_friendships WHERE user_id=? AND peer_id=?`,
|
||||
decodeUID(userID), decodeUID(peerID))
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
@@ -6871,7 +6859,8 @@ func (a *adapter) TenantUserBlockGet(id t.TenantID, blockerID, blockedID t.Uid)
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}{}
|
||||
err := a.db.GetContext(ctx, &row, "SELECT * FROM im_user_blocks WHERE blocker_id=? AND blocked_id=?",
|
||||
err := a.db.GetContext(ctx, &row, `SELECT blocker_id,blocked_id,created_at,updated_at
|
||||
FROM im_user_blocks WHERE blocker_id=? AND blocked_id=?`,
|
||||
decodeUID(blockerID), decodeUID(blockedID))
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
@@ -6919,7 +6908,7 @@ func (a *adapter) TenantUserBlockList(id t.TenantID, blockerID t.Uid, cursor str
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
rows, err := a.db.QueryxContext(ctx, `SELECT b.*,u.public,u.trusted
|
||||
rows, err := a.db.QueryxContext(ctx, `SELECT b.blocker_id,b.blocked_id,b.created_at,b.updated_at,u.public,u.trusted
|
||||
FROM im_user_blocks AS b
|
||||
LEFT JOIN im_users AS u ON u.id=b.blocked_id
|
||||
WHERE `+strings.Join(where, " AND ")+`
|
||||
@@ -6986,10 +6975,14 @@ func (a *adapter) TenantUserBlockUpsert(id t.TenantID, blockerID, blockedID t.Ui
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
_, err := a.db.ExecContext(ctx,
|
||||
"INSERT INTO im_user_blocks(blocker_id,blocked_id,created_at,updated_at) VALUES(?,?,?,?) "+
|
||||
blockID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = a.db.ExecContext(ctx,
|
||||
"INSERT INTO im_user_blocks(id,blocker_id,blocked_id,created_at,updated_at) VALUES(?,?,?,?,?) "+
|
||||
"ON DUPLICATE KEY UPDATE updated_at=VALUES(updated_at)",
|
||||
decodeUID(blockerID), decodeUID(blockedID), now, now)
|
||||
blockID, decodeUID(blockerID), decodeUID(blockedID), now, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -7048,24 +7041,23 @@ func (a *adapter) TenantUserSearch(id t.TenantID, viewer t.Uid, queryText, searc
|
||||
where = append(where, "u.id>?")
|
||||
args = append(args, parsed)
|
||||
}
|
||||
joins := []string{"LEFT JOIN im_user_privacy_settings AS privacy ON privacy.user_id=u.id"}
|
||||
joins := []string{
|
||||
"LEFT JOIN im_user_privacy_settings AS privacy ON privacy.user_id=u.id",
|
||||
"LEFT JOIN im_user_profiles AS profile ON profile.user_id=u.id",
|
||||
}
|
||||
addMethod := "account"
|
||||
switch searchType {
|
||||
case "", "account":
|
||||
like := "%" + queryText + "%"
|
||||
joins = append(joins, "LEFT JOIN im_usertags AS ut ON ut.userid=u.id")
|
||||
where = append(where, "(ut.tag LIKE ? OR CAST(u.public AS CHAR) LIKE ? OR u.id=?)")
|
||||
args = append(args, like, like, userIDNumericArg(queryText))
|
||||
where = append(where, "(profile.nickname LIKE ? OR profile.public_account LIKE ? OR CAST(u.public AS CHAR) LIKE ? OR u.id=?)")
|
||||
args = append(args, like, like, like, userIDNumericArg(queryText))
|
||||
case "exact_account":
|
||||
joins = append(joins, "LEFT JOIN im_usertags AS ut ON ut.userid=u.id")
|
||||
where = append(where, "(ut.tag=? OR u.id=?)")
|
||||
args = append(args, queryText, userIDNumericArg(queryText))
|
||||
joins = append(joins, "LEFT JOIN im_auth AS account_auth ON account_auth.userid=u.id AND account_auth.scheme='basic'")
|
||||
where = append(where, "(profile.public_account=? OR account_auth.uname=? OR u.id=?)")
|
||||
args = append(args, queryText, strings.TrimPrefix(queryText, "basic:"), userIDNumericArg(queryText))
|
||||
case "phone":
|
||||
addMethod = "phone"
|
||||
where = append(where, `EXISTS (
|
||||
SELECT 1 FROM im_credentials AS c
|
||||
WHERE c.userid=u.id AND c.method='tel' AND c.value=? AND c.done=true
|
||||
)`)
|
||||
where = append(where, "u.phone=?")
|
||||
args = append(args, queryText)
|
||||
default:
|
||||
return nil, "", t.ErrMalformed
|
||||
@@ -7080,7 +7072,8 @@ func (a *adapter) TenantUserSearch(id t.TenantID, viewer t.Uid, queryText, searc
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
rows, err := a.db.QueryxContext(ctx, `SELECT DISTINCT u.* FROM im_users AS u `+strings.Join(joins, " ")+`
|
||||
rows, err := a.db.QueryxContext(ctx, `SELECT DISTINCT u.id,u.createdat,u.updatedat,u.state,u.stateat,u.access,u.lastseen,u.useragent,
|
||||
COALESCE(u.phone,'') AS phone,u.public,u.trusted FROM im_users AS u `+strings.Join(joins, " ")+`
|
||||
WHERE `+strings.Join(where, " AND ")+` ORDER BY u.id ASC LIMIT ?`, args...)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
||||
Reference in New Issue
Block a user