add
This commit is contained in:
309
internal/application/api/query_whitelist_application_service.go
Normal file
309
internal/application/api/query_whitelist_application_service.go
Normal file
@@ -0,0 +1,309 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"tyapi-server/internal/application/api/dto"
|
||||
"tyapi-server/internal/domains/api/entities"
|
||||
"tyapi-server/internal/domains/api/repositories"
|
||||
api_services "tyapi-server/internal/domains/api/services"
|
||||
"tyapi-server/internal/shared/interfaces"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type QueryWhitelistApplicationService interface {
|
||||
CreateEntry(ctx context.Context, adminUserID string, req *dto.QueryWhitelistEntryRequest) (*dto.QueryWhitelistEntryResponse, error)
|
||||
UpdateEntry(ctx context.Context, adminUserID, id string, req *dto.QueryWhitelistEntryUpdateRequest) (*dto.QueryWhitelistEntryResponse, error)
|
||||
UpdateEntryStatus(ctx context.Context, adminUserID, id, status string) (*dto.QueryWhitelistEntryResponse, error)
|
||||
DeleteEntry(ctx context.Context, id string) error
|
||||
GetEntry(ctx context.Context, id string) (*dto.QueryWhitelistEntryResponse, error)
|
||||
ListEntries(ctx context.Context, filters map[string]interface{}, options interfaces.ListOptions) (*dto.QueryWhitelistListResponse, error)
|
||||
ImportLegacyEntries(ctx context.Context, adminUserID string) (*dto.QueryWhitelistImportLegacyResponse, error)
|
||||
}
|
||||
|
||||
type QueryWhitelistApplicationServiceImpl struct {
|
||||
repo repositories.QueryWhitelistRepository
|
||||
queryWhitelistSvc api_services.QueryWhitelistService
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func NewQueryWhitelistApplicationService(
|
||||
repo repositories.QueryWhitelistRepository,
|
||||
queryWhitelistSvc api_services.QueryWhitelistService,
|
||||
logger *zap.Logger,
|
||||
) QueryWhitelistApplicationService {
|
||||
return &QueryWhitelistApplicationServiceImpl{
|
||||
repo: repo,
|
||||
queryWhitelistSvc: queryWhitelistSvc,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *QueryWhitelistApplicationServiceImpl) CreateEntry(
|
||||
ctx context.Context,
|
||||
adminUserID string,
|
||||
req *dto.QueryWhitelistEntryRequest,
|
||||
) (*dto.QueryWhitelistEntryResponse, error) {
|
||||
if err := validateQueryWhitelistRequest(req.UserID, req.Name, req.IDCard, req.APICodes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
idCardHash := api_services.HashIDCard(req.IDCard)
|
||||
exists, err := s.repo.ExistsByUserIDCardHashAndName(ctx, req.UserID, idCardHash, strings.TrimSpace(req.Name), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
return nil, fmt.Errorf("该用户下已存在相同的身份证与姓名规则")
|
||||
}
|
||||
|
||||
entry := &entities.QueryWhitelistEntry{
|
||||
UserID: strings.TrimSpace(req.UserID),
|
||||
Name: normalizeWhitelistName(req.Name),
|
||||
IDCardHash: idCardHash,
|
||||
IDCardMasked: api_services.MaskIDCard(req.IDCard),
|
||||
APICodes: entities.APICodeList(req.APICodes),
|
||||
Status: entities.QueryWhitelistStatusEnabled,
|
||||
Remark: strings.TrimSpace(req.Remark),
|
||||
CreatedBy: &adminUserID,
|
||||
}
|
||||
if err := s.repo.Create(ctx, entry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.queryWhitelistSvc.InvalidateCache(entry.UserID, idCardHash)
|
||||
resp := dto.NewQueryWhitelistEntryResponse(entry)
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (s *QueryWhitelistApplicationServiceImpl) UpdateEntry(
|
||||
ctx context.Context,
|
||||
adminUserID, id string,
|
||||
req *dto.QueryWhitelistEntryUpdateRequest,
|
||||
) (*dto.QueryWhitelistEntryResponse, error) {
|
||||
entry, err := s.repo.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fmt.Errorf("规则不存在")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
oldHash := entry.IDCardHash
|
||||
|
||||
if req.Name != "" {
|
||||
entry.Name = normalizeWhitelistName(req.Name)
|
||||
}
|
||||
if req.IDCard != "" {
|
||||
if err := validateIDCard(req.IDCard); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entry.IDCardHash = api_services.HashIDCard(req.IDCard)
|
||||
entry.IDCardMasked = api_services.MaskIDCard(req.IDCard)
|
||||
}
|
||||
if len(req.APICodes) > 0 {
|
||||
if err := validateAPICodes(req.APICodes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entry.APICodes = entities.APICodeList(req.APICodes)
|
||||
}
|
||||
if req.Remark != "" || req.Remark == "" {
|
||||
entry.Remark = strings.TrimSpace(req.Remark)
|
||||
}
|
||||
|
||||
exists, err := s.repo.ExistsByUserIDCardHashAndName(ctx, entry.UserID, entry.IDCardHash, entry.Name, entry.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
return nil, fmt.Errorf("该用户下已存在相同的身份证与姓名规则")
|
||||
}
|
||||
|
||||
entry.UpdatedBy = &adminUserID
|
||||
if err := s.repo.Update(ctx, entry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.queryWhitelistSvc.InvalidateCache(entry.UserID, oldHash)
|
||||
s.queryWhitelistSvc.InvalidateCache(entry.UserID, entry.IDCardHash)
|
||||
resp := dto.NewQueryWhitelistEntryResponse(entry)
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (s *QueryWhitelistApplicationServiceImpl) UpdateEntryStatus(
|
||||
ctx context.Context,
|
||||
adminUserID, id, status string,
|
||||
) (*dto.QueryWhitelistEntryResponse, error) {
|
||||
entry, err := s.repo.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fmt.Errorf("规则不存在")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
entry.Status = status
|
||||
entry.UpdatedBy = &adminUserID
|
||||
if err := s.repo.Update(ctx, entry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.queryWhitelistSvc.InvalidateCache(entry.UserID, entry.IDCardHash)
|
||||
resp := dto.NewQueryWhitelistEntryResponse(entry)
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (s *QueryWhitelistApplicationServiceImpl) DeleteEntry(ctx context.Context, id string) error {
|
||||
entry, err := s.repo.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fmt.Errorf("规则不存在")
|
||||
}
|
||||
return err
|
||||
}
|
||||
if err := s.repo.Delete(ctx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
s.queryWhitelistSvc.InvalidateCache(entry.UserID, entry.IDCardHash)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *QueryWhitelistApplicationServiceImpl) GetEntry(ctx context.Context, id string) (*dto.QueryWhitelistEntryResponse, error) {
|
||||
entry, err := s.repo.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fmt.Errorf("规则不存在")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
resp := dto.NewQueryWhitelistEntryResponse(entry)
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (s *QueryWhitelistApplicationServiceImpl) ListEntries(
|
||||
ctx context.Context,
|
||||
filters map[string]interface{},
|
||||
options interfaces.ListOptions,
|
||||
) (*dto.QueryWhitelistListResponse, error) {
|
||||
if idCard, ok := filters["id_card"].(string); ok && idCard != "" {
|
||||
filters["id_card_hash"] = api_services.HashIDCard(idCard)
|
||||
delete(filters, "id_card")
|
||||
}
|
||||
entries, total, err := s.repo.List(ctx, filters, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items := make([]dto.QueryWhitelistEntryResponse, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
items = append(items, dto.NewQueryWhitelistEntryResponse(entry))
|
||||
}
|
||||
page := options.Page
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
size := options.PageSize
|
||||
if size < 1 {
|
||||
size = 20
|
||||
}
|
||||
return &dto.QueryWhitelistListResponse{
|
||||
Items: items,
|
||||
Total: total,
|
||||
Page: page,
|
||||
Size: size,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *QueryWhitelistApplicationServiceImpl) ImportLegacyEntries(
|
||||
ctx context.Context,
|
||||
adminUserID string,
|
||||
) (*dto.QueryWhitelistImportLegacyResponse, error) {
|
||||
imported := 0
|
||||
skipped := 0
|
||||
for _, idCard := range LegacyHardcodedIDCards {
|
||||
hash := api_services.HashIDCard(idCard)
|
||||
exists, err := s.repo.ExistsByUserIDCardHashAndName(
|
||||
ctx,
|
||||
entities.QueryWhitelistGlobalUserID,
|
||||
hash,
|
||||
entities.QueryWhitelistWildcardName,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
entry := &entities.QueryWhitelistEntry{
|
||||
UserID: entities.QueryWhitelistGlobalUserID,
|
||||
Name: entities.QueryWhitelistWildcardName,
|
||||
IDCardHash: hash,
|
||||
IDCardMasked: api_services.MaskIDCard(idCard),
|
||||
APICodes: entities.APICodeList{"*"},
|
||||
Status: entities.QueryWhitelistStatusEnabled,
|
||||
Remark: "自硬编码迁移-全局",
|
||||
CreatedBy: &adminUserID,
|
||||
}
|
||||
if err := s.repo.Create(ctx, entry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.queryWhitelistSvc.InvalidateCache(entities.QueryWhitelistGlobalUserID, hash)
|
||||
imported++
|
||||
}
|
||||
return &dto.QueryWhitelistImportLegacyResponse{
|
||||
Imported: imported,
|
||||
Skipped: skipped,
|
||||
Total: len(LegacyHardcodedIDCards),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func validateQueryWhitelistRequest(userID, name, idCard string, apiCodes []string) error {
|
||||
userID = strings.TrimSpace(userID)
|
||||
if userID == "" {
|
||||
return fmt.Errorf("user_id 不能为空")
|
||||
}
|
||||
if strings.TrimSpace(name) == "" {
|
||||
return fmt.Errorf("name 不能为空")
|
||||
}
|
||||
if err := validateIDCard(idCard); err != nil {
|
||||
return err
|
||||
}
|
||||
return validateAPICodes(apiCodes)
|
||||
}
|
||||
|
||||
func validateIDCard(idCard string) error {
|
||||
idCard = api_services.NormalizeIDCard(idCard)
|
||||
if len(idCard) != 18 {
|
||||
return fmt.Errorf("身份证号格式不正确")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAPICodes(apiCodes []string) error {
|
||||
if len(apiCodes) == 0 {
|
||||
return fmt.Errorf("api_codes 不能为空")
|
||||
}
|
||||
hasWildcard := false
|
||||
for _, code := range apiCodes {
|
||||
code = strings.TrimSpace(code)
|
||||
if code == "" {
|
||||
return fmt.Errorf("api_codes 不能包含空值")
|
||||
}
|
||||
if code == "*" {
|
||||
hasWildcard = true
|
||||
}
|
||||
}
|
||||
if hasWildcard && len(apiCodes) > 1 {
|
||||
return fmt.Errorf("api_codes 包含 * 时不能与其他编码混用")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeWhitelistName(name string) string {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == entities.QueryWhitelistWildcardName {
|
||||
return entities.QueryWhitelistWildcardName
|
||||
}
|
||||
return name
|
||||
}
|
||||
Reference in New Issue
Block a user