184 lines
5.8 KiB
Go
184 lines
5.8 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
|
|
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
|
|
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/entity"
|
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
)
|
|
|
|
func TestPhoneRegisterParamRequiresSmsCode(t *testing.T) {
|
|
err := g.Validator().Data(&model.AppPhoneRegisterParam{
|
|
TenantId: "000000",
|
|
Phone: "13800008000",
|
|
Password: "123456",
|
|
NickName: "测试用户",
|
|
}).Run(context.Background())
|
|
if err == nil {
|
|
t.Fatal("AppPhoneRegisterParam should require smsCode")
|
|
}
|
|
}
|
|
|
|
func TestAppSmsCodeHelpersUseRedisKeys(t *testing.T) {
|
|
key := appSmsCacheKey("", "13800008000", "login")
|
|
if key != "app:sms:000000:login:13800008000" {
|
|
t.Fatalf("unexpected sms cache key: %s", key)
|
|
}
|
|
if key := appSmsCooldownCacheKey("", "13800008000"); key != "app:sms:cooldown:000000:13800008000" {
|
|
t.Fatalf("unexpected sms cooldown key: %s", key)
|
|
}
|
|
}
|
|
|
|
func TestAppSmsCooldownScopeAndDuration(t *testing.T) {
|
|
if appSmsCooldownTTL != time.Minute {
|
|
t.Fatalf("sms cooldown = %v, want one minute", appSmsCooldownTTL)
|
|
}
|
|
key := appSmsCooldownCacheKey("000000", "13800008000")
|
|
if key != appSmsCooldownCacheKey("", "13800008000") {
|
|
t.Fatal("default tenant should share the same cooldown key")
|
|
}
|
|
if key == appSmsCooldownCacheKey("000000", "13800008001") {
|
|
t.Fatal("different phones should have independent cooldown keys")
|
|
}
|
|
if key == appSmsCooldownCacheKey("000001", "13800008000") {
|
|
t.Fatal("different tenants should have independent cooldown keys")
|
|
}
|
|
}
|
|
|
|
func TestDeletedRegisterUserNameFitsSysUserUniqueColumn(t *testing.T) {
|
|
name := deletedRegisterUserName(88, "18800004698")
|
|
if name != "del88_314698" {
|
|
t.Fatalf("unexpected deleted register username: %s", name)
|
|
}
|
|
if len(name) > 30 {
|
|
t.Fatalf("deleted register username length = %d, want <= 30", len(name))
|
|
}
|
|
}
|
|
|
|
func TestIsSysUserNameUniqueKeyError(t *testing.T) {
|
|
if !isSysUserNameUniqueKeyError(gerror.New("Error 1062: Duplicate entry '000000-18800004698' for key 'sys_user.uk_user_name'")) {
|
|
t.Fatal("expected sys_user.uk_user_name duplicate error to be recognized")
|
|
}
|
|
if isSysUserNameUniqueKeyError(gerror.New("Error 1062: Duplicate entry 'x' for key 'other_key'")) {
|
|
t.Fatal("unexpected duplicate key match for other indexes")
|
|
}
|
|
}
|
|
|
|
func TestAppWechatMiniSecretMissing(t *testing.T) {
|
|
if !appWechatMiniSecretMissing("") {
|
|
t.Fatal("empty mini app secret should be treated as missing")
|
|
}
|
|
if !appWechatMiniSecretMissing(appWechatMiniAppSecretPlaceholder) {
|
|
t.Fatal("placeholder mini app secret should be treated as missing")
|
|
}
|
|
if appWechatMiniSecretMissing("real-secret") {
|
|
t.Fatal("non-placeholder mini app secret should not be treated as missing")
|
|
}
|
|
}
|
|
|
|
func TestAppEnsureWechatBindPhoneVerifiedSkipsVerifiedPhone(t *testing.T) {
|
|
err := appEnsureWechatBindPhoneVerified(
|
|
context.Background(),
|
|
&model.AppWechatBindPhoneParam{},
|
|
&appWechatBindTicketCache{VerifiedPhone: "13800008000"},
|
|
"13800008000",
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("verified phone should skip captcha verification, got: %v", err)
|
|
}
|
|
|
|
err = appEnsureWechatBindPhoneVerified(
|
|
context.Background(),
|
|
&model.AppWechatBindPhoneParam{},
|
|
&appWechatBindTicketCache{VerifiedPhone: "13800008001"},
|
|
"13800008000",
|
|
)
|
|
if err == nil {
|
|
t.Fatal("different phone should require captcha verification")
|
|
}
|
|
}
|
|
|
|
func TestAvailableAppLoginUsersByPasswordFiltersCandidates(t *testing.T) {
|
|
svc := &sAppAuth{}
|
|
users := []*entity.SysUser{
|
|
appAuthTestUser(1, "phone-a", "right-password"),
|
|
appAuthTestUser(2, "phone-b", "other-password"),
|
|
}
|
|
|
|
matched, err := svc.availableAppLoginUsersByPassword(users, "wrong-password")
|
|
if err != nil {
|
|
t.Fatalf("availableAppLoginUsersByPassword returned error: %v", err)
|
|
}
|
|
if len(matched) != 0 {
|
|
t.Fatalf("wrong password matched %d users, want 0", len(matched))
|
|
}
|
|
|
|
matched, err = svc.availableAppLoginUsersByPassword(users, "right-password")
|
|
if err != nil {
|
|
t.Fatalf("availableAppLoginUsersByPassword returned error: %v", err)
|
|
}
|
|
if len(matched) != 1 || matched[0].UserId != 1 {
|
|
t.Fatalf("right password matched %#v, want only user 1", matched)
|
|
}
|
|
}
|
|
|
|
func appAuthTestUser(userId int64, username string, password string) *entity.SysUser {
|
|
salt := "abcde"
|
|
return &entity.SysUser{
|
|
UserId: userId,
|
|
UserName: username,
|
|
Salt: salt,
|
|
Password: appPasswordEncryptForStore(password, salt),
|
|
Status: consts.SysUserStatusNormal,
|
|
}
|
|
}
|
|
|
|
func TestCallAppCodeHTTPUsesSceneTemplate(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var request struct {
|
|
Config struct {
|
|
Scene string `json:"scene"`
|
|
} `json:"config"`
|
|
Params struct {
|
|
PhoneNumber string `json:"phoneNumber"`
|
|
MsgContent string `json:"msgContent"`
|
|
} `json:"params"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
|
t.Errorf("decode request: %v", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
if request.Config.Scene != "bind_phone" {
|
|
t.Errorf("scene = %q, want bind_phone", request.Config.Scene)
|
|
}
|
|
if request.Params.PhoneNumber != "13800008000" {
|
|
t.Errorf("phoneNumber = %q, want 13800008000", request.Params.PhoneNumber)
|
|
}
|
|
if request.Params.MsgContent != "123456" {
|
|
t.Errorf("msgContent = %q, want raw verification code", request.Params.MsgContent)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"code":0,"message":"发送成功"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := callAppCodeHTTP(context.Background(), appCodeHttpSenderConfig{
|
|
Url: server.URL,
|
|
Method: http.MethodPost,
|
|
BodyTemplate: `{"config":{"scene":"{scene}"},"params":{"phoneNumber":"{contact}","msgContent":"{code}"}}`,
|
|
}, "13800008000", "123456", appSmsServiceScene("wechatBindPhone"))
|
|
if err != nil {
|
|
t.Fatalf("callAppCodeHTTP returned error: %v", err)
|
|
}
|
|
}
|