feat: add tenant login IP whitelist management
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user