feat: add tenant login IP whitelist management

This commit is contained in:
richjohnrambo
2026-09-09 09:39:55 +08:00
parent 99307f1c98
commit 964746c19b
12 changed files with 400 additions and 9 deletions
@@ -143,3 +143,21 @@ func TestImUserPolicyGroupInputFilter(t *testing.T) {
t.Fatal("无效用户ID应被拒绝")
}
}
func TestImTenantLoginIPWhitelistSaveFilter(t *testing.T) {
in := &ImTenantLoginIPWhitelistSaveInp{
TenantId: 1,
AppList: []string{" 203.0.113.10 ", "2001:db8::/32", "203.0.113.10"},
WebList: []string{"198.51.100.7/24"},
}
if err := in.Filter(context.Background()); err != nil {
t.Fatalf("合法租户登录白名单不应报错: %v", err)
}
if len(in.AppList) != 2 || in.AppList[0] != "203.0.113.10" || in.WebList[0] != "198.51.100.0/24" {
t.Fatalf("IP白名单未正确规范化: app=%v web=%v", in.AppList, in.WebList)
}
in.AppList = []string{"not-an-ip"}
if err := in.Filter(context.Background()); err == nil {
t.Fatal("非法IP地址应被拒绝")
}
}
@@ -2,6 +2,7 @@ package sysin
import (
"context"
"net/netip"
"regexp"
"strings"
@@ -155,3 +156,66 @@ type ImUserPolicyGroupMemberRemoveInp struct {
}
func (in *ImUserPolicyGroupMemberRemoveInp) Filter(ctx context.Context) error { return nil }
type ImTenantLoginIPWhitelistInp struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
}
func (in *ImTenantLoginIPWhitelistInp) Filter(ctx context.Context) error {
if in.TenantId < 0 {
return gerror.New("租户ID不合法")
}
return nil
}
type ImTenantLoginIPWhitelistSaveInp struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
AppList []string `json:"appList" dc:"APP登录IP白名单"`
WebList []string `json:"webList" dc:"Web登录IP白名单"`
}
func (in *ImTenantLoginIPWhitelistSaveInp) Filter(ctx context.Context) (err error) {
if in.TenantId < 0 {
return gerror.New("租户ID不合法")
}
if in.AppList, err = normalizeTenantLoginIPList(in.AppList); err != nil {
return gerror.Wrap(err, "APP登录白名单不合法")
}
if in.WebList, err = normalizeTenantLoginIPList(in.WebList); err != nil {
return gerror.Wrap(err, "Web登录白名单不合法")
}
return nil
}
type ImTenantLoginIPWhitelistModel struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
AppList []string `json:"appList" dc:"APP登录IP白名单"`
WebList []string `json:"webList" dc:"Web登录IP白名单"`
}
func normalizeTenantLoginIPList(values []string) ([]string, error) {
if len(values) > 500 {
return nil, gerror.New("单个渠道最多配置500条IP或CIDR")
}
result := make([]string, 0, len(values))
seen := make(map[string]struct{}, len(values))
for _, value := range values {
value = strings.TrimSpace(value)
if value == "" {
continue
}
if prefix, err := netip.ParsePrefix(value); err == nil {
value = prefix.Masked().String()
} else if address, addressErr := netip.ParseAddr(value); addressErr == nil {
value = address.String()
} else {
return nil, gerror.Newf("%s 不是有效的IPv4、IPv6或CIDR", value)
}
if _, ok := seen[value]; ok {
continue
}
seen[value] = struct{}{}
result = append(result, value)
}
return result, nil
}