feat(server): 添加服务器地理位置信息字段
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 7m3s
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 7m3s
为服务器模型添加经度、纬度及中心点坐标字段,并在相关逻辑中处理这些字段 同时修复服务器用户列表缓存功能
This commit is contained in:
parent
071bb1940d
commit
15f4e69dc3
@ -47,6 +47,10 @@ type (
|
|||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
|
Longitude string `json:"longitude"`
|
||||||
|
Latitude string `json:"latitude"`
|
||||||
|
LatitudeCenter string `json:"latitude_center"`
|
||||||
|
LongitudeCenter string `json:"longitude_center"`
|
||||||
CreatedAt int64 `json:"created_at"`
|
CreatedAt int64 `json:"created_at"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
0
initialize/migrate/database/02119_node.down.sql
Normal file
0
initialize/migrate/database/02119_node.down.sql
Normal file
67
initialize/migrate/database/02119_node.up.sql
Normal file
67
initialize/migrate/database/02119_node.up.sql
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
-- Add longitude if not exists
|
||||||
|
SET @col_exists := (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'servers'
|
||||||
|
AND COLUMN_NAME = 'longitude'
|
||||||
|
);
|
||||||
|
SET @sql := IF(
|
||||||
|
@col_exists = 0,
|
||||||
|
'ALTER TABLE `servers` ADD COLUMN `longitude` VARCHAR(255) DEFAULT '''' COMMENT ''longitude''',
|
||||||
|
'SELECT 1'
|
||||||
|
);
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- Add latitude if not exists
|
||||||
|
SET @col_exists := (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'servers'
|
||||||
|
AND COLUMN_NAME = 'latitude'
|
||||||
|
);
|
||||||
|
SET @sql := IF(
|
||||||
|
@col_exists = 0,
|
||||||
|
'ALTER TABLE `servers` ADD COLUMN `latitude` VARCHAR(255) DEFAULT '''' COMMENT ''latitude''',
|
||||||
|
'SELECT 1'
|
||||||
|
);
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- Add longitude_center if not exists
|
||||||
|
SET @col_exists := (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'servers'
|
||||||
|
AND COLUMN_NAME = 'longitude_center'
|
||||||
|
);
|
||||||
|
SET @sql := IF(
|
||||||
|
@col_exists = 0,
|
||||||
|
'ALTER TABLE `servers` ADD COLUMN `longitude_center` VARCHAR(255) DEFAULT '''' COMMENT ''longitude center''',
|
||||||
|
'SELECT 1'
|
||||||
|
);
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- Add latitude_center if not exists
|
||||||
|
SET @col_exists := (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'servers'
|
||||||
|
AND COLUMN_NAME = 'latitude_center'
|
||||||
|
);
|
||||||
|
SET @sql := IF(
|
||||||
|
@col_exists = 0,
|
||||||
|
'ALTER TABLE `servers` ADD COLUMN `latitude_center` VARCHAR(255) DEFAULT '''' COMMENT ''latitude center''',
|
||||||
|
'SELECT 1'
|
||||||
|
);
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
@ -99,6 +99,10 @@ func (l *CreateServerLogic) CreateServer(req *types.CreateServerRequest) error {
|
|||||||
} else {
|
} else {
|
||||||
data.City = result.City
|
data.City = result.City
|
||||||
data.Country = result.Country
|
data.Country = result.Country
|
||||||
|
data.Latitude = result.Latitude
|
||||||
|
data.Longitude = result.Longitude
|
||||||
|
data.LatitudeCenter = result.LatitudeCenter
|
||||||
|
data.LongitudeCenter = result.LongitudeCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = l.svcCtx.NodeModel.InsertServer(l.ctx, &data)
|
err = l.svcCtx.NodeModel.InsertServer(l.ctx, &data)
|
||||||
|
|||||||
@ -47,6 +47,10 @@ func (l *UpdateServerLogic) UpdateServer(req *types.UpdateServerRequest) error {
|
|||||||
} else {
|
} else {
|
||||||
data.City = result.City
|
data.City = result.City
|
||||||
data.Country = result.Country
|
data.Country = result.Country
|
||||||
|
data.Latitude = result.Latitude
|
||||||
|
data.Longitude = result.Longitude
|
||||||
|
data.LatitudeCenter = result.LatitudeCenter
|
||||||
|
data.LongitudeCenter = result.LongitudeCenter
|
||||||
}
|
}
|
||||||
// update address
|
// update address
|
||||||
data.Address = req.Address
|
data.Address = req.Address
|
||||||
|
|||||||
@ -137,17 +137,21 @@ func (l *QueryUserSubscribeNodeListLogic) getServers(userSub *user.Subscribe) (u
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
userSubscribeNode := &types.UserSubscribeNodeInfo{
|
userSubscribeNode := &types.UserSubscribeNodeInfo{
|
||||||
Id: n.Id,
|
Id: n.Id,
|
||||||
Name: n.Name,
|
Name: n.Name,
|
||||||
Uuid: userSub.UUID,
|
Uuid: userSub.UUID,
|
||||||
Protocol: n.Protocol,
|
Protocol: n.Protocol,
|
||||||
Protocols: server.Protocols,
|
Protocols: server.Protocols,
|
||||||
Port: n.Port,
|
Port: n.Port,
|
||||||
Address: n.Address,
|
Address: n.Address,
|
||||||
Tags: strings.Split(n.Tags, ","),
|
Tags: strings.Split(n.Tags, ","),
|
||||||
Country: server.Country,
|
Country: server.Country,
|
||||||
City: server.City,
|
City: server.City,
|
||||||
CreatedAt: n.CreatedAt.Unix(),
|
Latitude: server.Latitude,
|
||||||
|
Longitude: server.Longitude,
|
||||||
|
LongitudeCenter: server.LongitudeCenter,
|
||||||
|
LatitudeCenter: server.LatitudeCenter,
|
||||||
|
CreatedAt: n.CreatedAt.Unix(),
|
||||||
}
|
}
|
||||||
userSubscribeNodes = append(userSubscribeNodes, userSubscribeNode)
|
userSubscribeNodes = append(userSubscribeNodes, userSubscribeNode)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,6 +69,15 @@ func (l *UnbindDeviceLogic) UnbindDevice(req *types.UnbindDeviceRequest) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "delete device online record err: %v", err)
|
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "delete device online record err: %v", err)
|
||||||
}
|
}
|
||||||
|
var count int64
|
||||||
|
err = tx.Model(user.AuthMethods{}).Where("user_id = ?", deleteDevice.UserId).Count(&count).Error
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "count user auth methods err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if count < 1 {
|
||||||
|
_ = tx.Where("id = ?", deleteDevice.UserId).Delete(&user.User{}).Error
|
||||||
|
}
|
||||||
|
|
||||||
//remove device cache
|
//remove device cache
|
||||||
deviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, deleteDevice.Identifier)
|
deviceCacheKey := fmt.Sprintf("%v:%v", config.DeviceCacheKeyKey, deleteDevice.Identifier)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -32,24 +33,23 @@ func NewGetServerUserListLogic(ctx *gin.Context, svcCtx *svc.ServiceContext) *Ge
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListRequest) (resp *types.GetServerUserListResponse, err error) {
|
func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListRequest) (resp *types.GetServerUserListResponse, err error) {
|
||||||
//TODO Cache bug, temporarily disable the use of cache
|
cacheKey := fmt.Sprintf("%s%d", node.ServerUserListCacheKey, req.ServerId)
|
||||||
//cacheKey := fmt.Sprintf("%s%d", node.ServerUserListCacheKey, req.ServerId)
|
cache, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||||
//cache, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
if cache != "" {
|
||||||
//if cache != "" {
|
etag := tool.GenerateETag([]byte(cache))
|
||||||
// etag := tool.GenerateETag([]byte(cache))
|
resp = &types.GetServerUserListResponse{}
|
||||||
// resp = &types.GetServerUserListResponse{}
|
// Check If-None-Match header
|
||||||
// // Check If-None-Match header
|
if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
||||||
// if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
return nil, xerr.StatusNotModified
|
||||||
// return nil, xerr.StatusNotModified
|
}
|
||||||
// }
|
l.ctx.Header("ETag", etag)
|
||||||
// l.ctx.Header("ETag", etag)
|
err = json.Unmarshal([]byte(cache), resp)
|
||||||
// err = json.Unmarshal([]byte(cache), resp)
|
if err != nil {
|
||||||
// if err != nil {
|
l.Errorw("[ServerUserListCacheKey] json unmarshal error", logger.Field("error", err.Error()))
|
||||||
// l.Errorw("[ServerUserListCacheKey] json unmarshal error", logger.Field("error", err.Error()))
|
return nil, err
|
||||||
// return nil, err
|
}
|
||||||
// }
|
return resp, nil
|
||||||
// return resp, nil
|
}
|
||||||
//}
|
|
||||||
server, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
server, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -121,11 +121,10 @@ func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListR
|
|||||||
val, _ := json.Marshal(resp)
|
val, _ := json.Marshal(resp)
|
||||||
etag := tool.GenerateETag(val)
|
etag := tool.GenerateETag(val)
|
||||||
l.ctx.Header("ETag", etag)
|
l.ctx.Header("ETag", etag)
|
||||||
//TODO Cache bug, temporarily disable the use of cache
|
err = l.svcCtx.Redis.Set(l.ctx, cacheKey, string(val), -1).Err()
|
||||||
//err = l.svcCtx.Redis.Set(l.ctx, cacheKey, string(val), -1).Err()
|
if err != nil {
|
||||||
//if err != nil {
|
l.Errorw("[ServerUserListCacheKey] redis set error", logger.Field("error", err.Error()))
|
||||||
// l.Errorw("[ServerUserListCacheKey] redis set error", logger.Field("error", err.Error()))
|
}
|
||||||
//}
|
|
||||||
// Check If-None-Match header
|
// Check If-None-Match header
|
||||||
if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
||||||
return nil, xerr.StatusNotModified
|
return nil, xerr.StatusNotModified
|
||||||
|
|||||||
@ -15,12 +15,16 @@ type Server struct {
|
|||||||
Country string `gorm:"type:varchar(128);not null;default:'';comment:Country"`
|
Country string `gorm:"type:varchar(128);not null;default:'';comment:Country"`
|
||||||
City string `gorm:"type:varchar(128);not null;default:'';comment:City"`
|
City string `gorm:"type:varchar(128);not null;default:'';comment:City"`
|
||||||
//Ratio float32 `gorm:"type:DECIMAL(4,2);not null;default:0;comment:Traffic Ratio"`
|
//Ratio float32 `gorm:"type:DECIMAL(4,2);not null;default:0;comment:Traffic Ratio"`
|
||||||
Address string `gorm:"type:varchar(100);not null;default:'';comment:Server Address"`
|
Address string `gorm:"type:varchar(100);not null;default:'';comment:Server Address"`
|
||||||
Sort int `gorm:"type:int;not null;default:0;comment:Sort"`
|
Sort int `gorm:"type:int;not null;default:0;comment:Sort"`
|
||||||
Protocols string `gorm:"type:text;default:null;comment:Protocol"`
|
Protocols string `gorm:"type:text;default:null;comment:Protocol"`
|
||||||
LastReportedAt *time.Time `gorm:"comment:Last Reported Time"`
|
LastReportedAt *time.Time `gorm:"comment:Last Reported Time"`
|
||||||
CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"`
|
Longitude string `gorm:"type:varchar(50);not null;default:'0.0';comment:Longitude"`
|
||||||
UpdatedAt time.Time `gorm:"comment:Update Time"`
|
Latitude string `gorm:"type:varchar(50);not null;default:'0.0';comment:Latitude"`
|
||||||
|
LongitudeCenter string `gorm:"type:varchar(50);not null;default:'0.0';comment:Center Longitude"`
|
||||||
|
LatitudeCenter string `gorm:"type:varchar(50);not null;default:'0.0';comment:Center Latitude"`
|
||||||
|
CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"`
|
||||||
|
UpdatedAt time.Time `gorm:"comment:Update Time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Server) TableName() string {
|
func (*Server) TableName() string {
|
||||||
|
|||||||
@ -2664,17 +2664,21 @@ type UserSubscribeLog struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UserSubscribeNodeInfo struct {
|
type UserSubscribeNodeInfo struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Uuid string `json:"uuid"`
|
Uuid string `json:"uuid"`
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
Protocols string `json:"protocols"`
|
Protocols string `json:"protocols"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
CreatedAt int64 `json:"created_at"`
|
Longitude string `json:"longitude"`
|
||||||
|
Latitude string `json:"latitude"`
|
||||||
|
LatitudeCenter string `json:"latitude_center"`
|
||||||
|
LongitudeCenter string `json:"longitude_center"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserSubscribeTrafficLog struct {
|
type UserSubscribeTrafficLog struct {
|
||||||
|
|||||||
2524
pkg/ip/center.go
Normal file
2524
pkg/ip/center.go
Normal file
File diff suppressed because it is too large
Load Diff
22
pkg/ip/ip.go
22
pkg/ip/ip.go
@ -74,6 +74,12 @@ func GetRegionByIp(ip string) (*GeoLocationResponse, error) {
|
|||||||
if response.Country == "" {
|
if response.Country == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
response.LatitudeCenter, response.LongitudeCenter, _ = GetCapitalCoordinates(fmt.Sprintf("%s,%s", response.Country, response.City))
|
||||||
|
if response.LatitudeCenter == "" || response.LongitudeCenter == "" {
|
||||||
|
response.LatitudeCenter = response.Latitude
|
||||||
|
response.LongitudeCenter = response.Longitude
|
||||||
|
|
||||||
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,11 +187,13 @@ func decompressResponse(resp *http.Response) ([]byte, error) {
|
|||||||
|
|
||||||
// GeoLocationResponse represents the geolocation data returned by the API.
|
// GeoLocationResponse represents the geolocation data returned by the API.
|
||||||
type GeoLocationResponse struct {
|
type GeoLocationResponse struct {
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
CountryName string `json:"country_name"`
|
CountryName string `json:"country_name"`
|
||||||
Region string `json:"region"`
|
Region string `json:"region"`
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
Latitude string `json:"latitude"`
|
Latitude string `json:"latitude"`
|
||||||
Longitude string `json:"longitude"`
|
Longitude string `json:"longitude"`
|
||||||
Loc string `json:"loc"`
|
LatitudeCenter string `json:"latitude_center"`
|
||||||
|
LongitudeCenter string `json:"longitude_center"`
|
||||||
|
Loc string `json:"loc"`
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user