74 lines
2.3 KiB
Go
74 lines
2.3 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
|
"github.com/Wei-Shaw/sub2api/internal/pkg/ipgeo"
|
|
"github.com/Wei-Shaw/sub2api/internal/pkg/logger"
|
|
)
|
|
|
|
type registrationIPInfoUpdater interface {
|
|
UpdateRegistrationIPInfo(ctx context.Context, userID int64, info RegistrationIPInfo) error
|
|
}
|
|
|
|
func (s *AuthService) refreshRegistrationIPLocationInBackground(userID int64, rawIP string) {
|
|
if s == nil || s.userRepo == nil || userID <= 0 || strings.TrimSpace(rawIP) == "" {
|
|
return
|
|
}
|
|
go func() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
info, err := lookupRegistrationIPInfo(ctx, rawIP)
|
|
if err != nil {
|
|
logger.LegacyPrintf("service.auth", "[Auth] Failed to lookup registration IP location: user_id=%d ip=%s err=%v", userID, rawIP, err)
|
|
return
|
|
}
|
|
if err := updateUserRegistrationIPInfoWithRepo(ctx, s.userRepo, userID, info); err != nil {
|
|
logger.LegacyPrintf("service.auth", "[Auth] Failed to update registration IP location: user_id=%d ip=%s err=%v", userID, rawIP, err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
func updateUserRegistrationIPInfoWithRepo(ctx context.Context, repo UserRepository, userID int64, info RegistrationIPInfo) error {
|
|
updater, ok := repo.(registrationIPInfoUpdater)
|
|
if !ok {
|
|
return errors.New("registration ip updater is not configured")
|
|
}
|
|
return updater.UpdateRegistrationIPInfo(ctx, userID, info)
|
|
}
|
|
|
|
func lookupRegistrationIPInfo(ctx context.Context, rawIP string) (RegistrationIPInfo, error) {
|
|
ipAddress := strings.TrimSpace(rawIP)
|
|
if ipAddress == "" {
|
|
return RegistrationIPInfo{}, infraerrors.BadRequest("REGISTER_IP_EMPTY", "registration IP is empty")
|
|
}
|
|
geo, err := ipgeo.Lookup(ctx, ipAddress)
|
|
if err != nil {
|
|
return RegistrationIPInfo{}, err
|
|
}
|
|
if geo == nil {
|
|
return RegistrationIPInfo{IPAddress: ipAddress}, nil
|
|
}
|
|
return RegistrationIPInfo{
|
|
IPAddress: firstNonEmptyRegistrationIP(geo.IPAddress, ipAddress),
|
|
Country: geo.Country,
|
|
CountryCode: geo.CountryCode,
|
|
Region: geo.Region,
|
|
City: geo.City,
|
|
Location: geo.Location,
|
|
}, nil
|
|
}
|
|
|
|
func firstNonEmptyRegistrationIP(values ...string) string {
|
|
for _, value := range values {
|
|
if trimmed := strings.TrimSpace(value); trimmed != "" {
|
|
return trimmed
|
|
}
|
|
}
|
|
return ""
|
|
}
|