Files
im_manager/server/internal/logic/sys/im_invite_test.go
T

125 lines
4.3 KiB
Go

package sys
import (
"context"
"os"
"regexp"
"testing"
"time"
"hotgo/internal/library/imtenant"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
"github.com/gogf/gf/v2/database/gdb"
"golang.org/x/crypto/bcrypt"
)
func TestRandomInviteCode(t *testing.T) {
pattern := regexp.MustCompile(`^[A-Za-z]{5}$`)
for i := 0; i < 100; i++ {
code, err := randomInviteCode()
if err != nil {
t.Fatal(err)
}
if !pattern.MatchString(code) {
t.Fatalf("invalid invite code %q", code)
}
}
}
func TestInviteDirectDatabase(t *testing.T) {
link := os.Getenv("IM_MANAGER_INTEGRATION_DSN")
if link == "" {
t.Skip("IM_MANAGER_INTEGRATION_DSN is not set")
}
const group = "im_invite_integration"
if err := gdb.SetConfigGroup(group, gdb.ConfigGroup{{Link: link}}); err != nil {
t.Fatal(err)
}
db, err := gdb.Instance(group)
if err != nil {
t.Fatal(err)
}
ctx := context.Background()
key := "integration-" + time.Now().UTC().Format("20060102150405.000000000")
expiresAt := time.Now().UTC().Add(time.Hour).Round(time.Millisecond)
batch, codes, err := createInviteBatch(ctx, db, 1, 1, 3, expiresAt, "integration", key)
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
_, _ = db.Exec(ctx, "DELETE FROM im_registration_invite_codes WHERE tenant_id=? AND batch_id=?", 1, batch.BatchID)
_, _ = db.Exec(ctx, "DELETE FROM im_registration_invite_batches WHERE tenant_id=? AND id=?", 1, batch.BatchID)
})
if batch.ActiveCount != 3 || len(codes) != 3 {
t.Fatalf("unexpected batch result: %#v codes=%d", batch, len(codes))
}
replayed, replayCodes, err := createInviteBatch(ctx, db, 1, 1, 3, expiresAt, "integration", key)
if err != nil {
t.Fatal(err)
}
if replayed.BatchID != batch.BatchID || len(replayCodes) != 0 {
t.Fatalf("idempotent replay created a new batch: %#v", replayed)
}
items, total, err := queryInviteCodes(ctx, db, imInviteListRequest{TenantID: 1, BatchID: batch.BatchID}, 10, 0)
if err != nil {
t.Fatal(err)
}
if total != 3 || len(items) != 3 {
t.Fatalf("unexpected query result total=%d items=%d", total, len(items))
}
}
func TestResetPasswordDirectDatabase(t *testing.T) {
link := os.Getenv("IM_MANAGER_INTEGRATION_DSN")
if link == "" {
t.Skip("IM_MANAGER_INTEGRATION_DSN is not set")
}
const group = "im_password_reset_integration"
if err := gdb.SetConfigGroup(group, gdb.ConfigGroup{{Link: link}}); err != nil {
t.Fatal(err)
}
db, err := gdb.Instance(group)
if err != nil {
t.Fatal(err)
}
ctx := context.Background()
userID, err := imtenant.NextSnowflakeID(ctx)
if err != nil {
t.Fatal(err)
}
now := time.Now().UTC().Round(time.Millisecond)
username := "integration" + time.Now().UTC().Format("150405000000")
if _, err = db.Exec(ctx, `INSERT INTO im_users(id,username,createdat,updatedat,state,useragent)
VALUES(?,?,?,?,0,'integration-test')`, userID, username, now, now); err != nil {
t.Fatal(err)
}
if _, err = db.Exec(ctx, "INSERT INTO im_auth(userid,authlvl,secret) VALUES(?,20,'old')", userID); err != nil {
_, _ = db.Exec(ctx, "DELETE FROM im_users WHERE id=?", userID)
t.Fatal(err)
}
t.Cleanup(func() {
_, _ = db.Exec(ctx, "DELETE FROM im_business_events_outbox WHERE target=? AND event_type='security.password_reset'", userID)
_, _ = db.Exec(ctx, "DELETE FROM im_user_security WHERE user_id=?", userID)
_, _ = db.Exec(ctx, "DELETE FROM im_auth WHERE userid=?", userID)
_, _ = db.Exec(ctx, "DELETE FROM im_users WHERE id=?", userID)
})
scope := imAdminScope{TenantId: 1, OperatorId: 99, RequestId: "integration-password-reset"}
if err = resetIMUserPassword(ctx, db, scope, userID, "new-password"); err != nil {
t.Fatal(err)
}
secret, err := db.GetValue(ctx, "SELECT secret FROM im_auth WHERE userid=?", userID)
if err != nil || bcrypt.CompareHashAndPassword(secret.Bytes(), []byte("new-password")) != nil {
t.Fatalf("password hash was not updated: %v", err)
}
version, err := db.GetValue(ctx, "SELECT auth_version FROM im_user_security WHERE user_id=?", userID)
if err != nil || version.Int() != 2 {
t.Fatalf("unexpected auth version %d: %v", version.Int(), err)
}
events, err := db.GetValue(ctx, `SELECT COUNT(*) FROM im_business_events_outbox
WHERE target=? AND event_type='security.password_reset' AND status='pending'`, userID)
if err != nil || events.Int() != 1 {
t.Fatalf("password reset event not written: count=%d err=%v", events.Int(), err)
}
}