Files
iotlcm/server/internal/logic/app/app_auth_test.go
T

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)
}
}