Initial commit (code only without large binaries)
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package cities
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/iplibraryutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "city")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
CountryId int64
|
||||
ProvinceId int64
|
||||
}) {
|
||||
// 检查权限
|
||||
if !iplibraryutils.CanAccess() {
|
||||
return
|
||||
}
|
||||
this.Data["canAccess"] = true
|
||||
|
||||
if params.CountryId <= 0 || params.ProvinceId <= 0 {
|
||||
params.CountryId = 1 // china
|
||||
params.ProvinceId = 1 // beijing
|
||||
}
|
||||
|
||||
this.Data["countryId"] = params.CountryId
|
||||
this.Data["provinceId"] = params.ProvinceId
|
||||
|
||||
// 所有国家/地区
|
||||
countriesResp, err := this.RPC().RegionCountryRPC().FindAllRegionCountries(this.AdminContext(), &pb.FindAllRegionCountriesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var countryMaps = []maps.Map{}
|
||||
for _, country := range countriesResp.RegionCountries {
|
||||
countryMaps = append(countryMaps, maps.Map{
|
||||
"id": country.Id,
|
||||
"name": country.DisplayName,
|
||||
})
|
||||
}
|
||||
this.Data["countries"] = countryMaps
|
||||
|
||||
// 城市列表
|
||||
citiesResp, err := this.RPC().RegionCityRPC().FindAllRegionCitiesWithRegionProvinceId(this.AdminContext(), &pb.FindAllRegionCitiesWithRegionProvinceIdRequest{
|
||||
RegionProvinceId: params.ProvinceId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var cityMaps = []maps.Map{}
|
||||
for _, city := range citiesResp.RegionCities {
|
||||
if city.Codes == nil {
|
||||
city.Codes = []string{}
|
||||
}
|
||||
if city.CustomCodes == nil {
|
||||
city.CustomCodes = []string{}
|
||||
}
|
||||
cityMaps = append(cityMaps, maps.Map{
|
||||
"id": city.Id,
|
||||
"name": city.Name,
|
||||
"codes": city.Codes,
|
||||
"customName": city.CustomName,
|
||||
"customCodes": city.CustomCodes,
|
||||
})
|
||||
}
|
||||
this.Data["cities"] = cityMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package cities
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type ProvinceOptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ProvinceOptionsAction) RunPost(params struct {
|
||||
CountryId int64
|
||||
}) {
|
||||
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{
|
||||
RegionCountryId: params.CountryId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var provinceMaps = []maps.Map{}
|
||||
for _, province := range provincesResp.RegionProvinces {
|
||||
provinceMaps = append(provinceMaps, maps.Map{
|
||||
"id": province.Id,
|
||||
"name": province.DisplayName,
|
||||
})
|
||||
}
|
||||
this.Data["provinces"] = provinceMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package cities
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
CityId int64
|
||||
}) {
|
||||
cityResp, err := this.RPC().RegionCityRPC().FindRegionCity(this.AdminContext(), &pb.FindRegionCityRequest{RegionCityId: params.CityId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var city = cityResp.RegionCity
|
||||
if city == nil {
|
||||
this.NotFound("regionCity", params.CityId)
|
||||
return
|
||||
}
|
||||
if city.Codes == nil {
|
||||
city.Codes = []string{}
|
||||
}
|
||||
if city.CustomCodes == nil {
|
||||
city.CustomCodes = []string{}
|
||||
}
|
||||
this.Data["city"] = maps.Map{
|
||||
"id": city.Id,
|
||||
"name": city.Name,
|
||||
"codes": city.Codes,
|
||||
"customName": city.CustomName,
|
||||
"customCodes": city.CustomCodes,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
CityId int64
|
||||
CustomName string
|
||||
CustomCodes []string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionCity_LogUpdateRegionCityCustom, params.CityId)
|
||||
|
||||
_, err := this.RPC().RegionCityRPC().UpdateRegionCityCustom(this.AdminContext(), &pb.UpdateRegionCityCustomRequest{
|
||||
RegionCityId: params.CityId,
|
||||
CustomName: params.CustomName,
|
||||
CustomCodes: params.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package countries
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/iplibraryutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "country")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
// 检查权限
|
||||
if !iplibraryutils.CanAccess() {
|
||||
return
|
||||
}
|
||||
this.Data["canAccess"] = true
|
||||
|
||||
countriesResp, err := this.RPC().RegionCountryRPC().FindAllRegionCountries(this.AdminContext(), &pb.FindAllRegionCountriesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var countryMaps = []maps.Map{}
|
||||
for _, country := range countriesResp.RegionCountries {
|
||||
if country.Codes == nil {
|
||||
country.Codes = []string{}
|
||||
}
|
||||
if country.CustomCodes == nil {
|
||||
country.CustomCodes = []string{}
|
||||
}
|
||||
countryMaps = append(countryMaps, maps.Map{
|
||||
"id": country.Id,
|
||||
"name": country.Name,
|
||||
"codes": country.Codes,
|
||||
"customName": country.CustomName,
|
||||
"customCodes": country.CustomCodes,
|
||||
})
|
||||
}
|
||||
this.Data["countries"] = countryMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package countries
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
CountryId int64
|
||||
}) {
|
||||
countryResp, err := this.RPC().RegionCountryRPC().FindRegionCountry(this.AdminContext(), &pb.FindRegionCountryRequest{
|
||||
RegionCountryId: params.CountryId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var country = countryResp.RegionCountry
|
||||
if country == nil {
|
||||
this.NotFound("regionCountry", params.CountryId)
|
||||
return
|
||||
}
|
||||
if country.Codes == nil {
|
||||
country.Codes = []string{}
|
||||
}
|
||||
if country.CustomCodes == nil {
|
||||
country.CustomCodes = []string{}
|
||||
}
|
||||
this.Data["country"] = maps.Map{
|
||||
"id": country.Id,
|
||||
"name": country.Name,
|
||||
"codes": country.Codes,
|
||||
"customName": country.CustomName,
|
||||
"customCodes": country.CustomCodes,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
CountryId int64
|
||||
CustomName string
|
||||
CustomCodes []string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionCountry_LogUpdateRegionCountryCustom, params.CountryId)
|
||||
|
||||
_, err := this.RPC().RegionCountryRPC().UpdateRegionCountryCustom(this.AdminContext(), &pb.UpdateRegionCountryCustomRequest{
|
||||
RegionCountryId: params.CountryId,
|
||||
CustomName: params.CustomName,
|
||||
CustomCodes: params.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
)
|
||||
|
||||
type AddCityCustomCodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AddCityCustomCodeAction) RunPost(params struct {
|
||||
CityId int64
|
||||
Code string
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionCity_LogAddRegionCityCode, params.CityId, params.Code)
|
||||
|
||||
cityResp, err := this.RPC().RegionCityRPC().FindRegionCity(this.AdminContext(), &pb.FindRegionCityRequest{RegionCityId: params.CityId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var city = cityResp.RegionCity
|
||||
if city == nil {
|
||||
this.NotFound("regionCity", params.CityId)
|
||||
return
|
||||
}
|
||||
|
||||
if len(params.Code) > 0 && !lists.ContainsString(city.CustomCodes, params.Code) {
|
||||
city.CustomCodes = append(city.CustomCodes, params.Code)
|
||||
_, err = this.RPC().RegionCityRPC().UpdateRegionCityCustom(this.AdminContext(), &pb.UpdateRegionCityCustomRequest{
|
||||
RegionCityId: params.CityId,
|
||||
CustomName: city.CustomName,
|
||||
CustomCodes: city.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
)
|
||||
|
||||
type AddCountryCustomCodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AddCountryCustomCodeAction) RunPost(params struct {
|
||||
CountryId int64
|
||||
Code string
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionCountry_LogAddRegionCountryCode, params.CountryId, params.Code)
|
||||
|
||||
countryResp, err := this.RPC().RegionCountryRPC().FindRegionCountry(this.AdminContext(), &pb.FindRegionCountryRequest{RegionCountryId: params.CountryId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var country = countryResp.RegionCountry
|
||||
if country == nil {
|
||||
this.NotFound("regionCountry", params.CountryId)
|
||||
return
|
||||
}
|
||||
|
||||
if len(params.Code) > 0 && !lists.ContainsString(country.CustomCodes, params.Code) {
|
||||
country.CustomCodes = append(country.CustomCodes, params.Code)
|
||||
_, err = this.RPC().RegionCountryRPC().UpdateRegionCountryCustom(this.AdminContext(), &pb.UpdateRegionCountryCustomRequest{
|
||||
RegionCountryId: params.CountryId,
|
||||
CustomName: country.CustomName,
|
||||
CustomCodes: country.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
)
|
||||
|
||||
type AddProviderCustomCodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AddProviderCustomCodeAction) RunPost(params struct {
|
||||
ProviderId int64
|
||||
Code string
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionProvider_LogAddRegionProviderCode, params.ProviderId, params.Code)
|
||||
|
||||
providerResp, err := this.RPC().RegionProviderRPC().FindRegionProvider(this.AdminContext(), &pb.FindRegionProviderRequest{RegionProviderId: params.ProviderId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var provider = providerResp.RegionProvider
|
||||
if provider == nil {
|
||||
this.NotFound("regionProvider", params.ProviderId)
|
||||
return
|
||||
}
|
||||
|
||||
if len(params.Code) > 0 && !lists.ContainsString(provider.CustomCodes, params.Code) {
|
||||
provider.CustomCodes = append(provider.CustomCodes, params.Code)
|
||||
_, err = this.RPC().RegionProviderRPC().UpdateRegionProviderCustom(this.AdminContext(), &pb.UpdateRegionProviderCustomRequest{
|
||||
RegionProviderId: params.ProviderId,
|
||||
CustomName: provider.CustomName,
|
||||
CustomCodes: provider.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
)
|
||||
|
||||
type AddProvinceCustomCodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AddProvinceCustomCodeAction) RunPost(params struct {
|
||||
ProvinceId int64
|
||||
Code string
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionProvince_LogAddRegionProvinceCode, params.ProvinceId, params.Code)
|
||||
|
||||
provinceResp, err := this.RPC().RegionProvinceRPC().FindRegionProvince(this.AdminContext(), &pb.FindRegionProvinceRequest{RegionProvinceId: params.ProvinceId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var province = provinceResp.RegionProvince
|
||||
if province == nil {
|
||||
this.NotFound("regionProvince", params.ProvinceId)
|
||||
return
|
||||
}
|
||||
|
||||
if len(params.Code) > 0 && !lists.ContainsString(province.CustomCodes, params.Code) {
|
||||
province.CustomCodes = append(province.CustomCodes, params.Code)
|
||||
_, err = this.RPC().RegionProvinceRPC().UpdateRegionProvinceCustom(this.AdminContext(), &pb.UpdateRegionProvinceCustomRequest{
|
||||
RegionProvinceId: params.ProvinceId,
|
||||
CustomName: province.CustomName,
|
||||
CustomCodes: province.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
)
|
||||
|
||||
type AddTownCustomCodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AddTownCustomCodeAction) RunPost(params struct {
|
||||
TownId int64
|
||||
Code string
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionTown_LogAddRegionTownCode, params.TownId, params.Code)
|
||||
|
||||
townResp, err := this.RPC().RegionTownRPC().FindRegionTown(this.AdminContext(), &pb.FindRegionTownRequest{RegionTownId: params.TownId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var town = townResp.RegionTown
|
||||
if town == nil {
|
||||
this.NotFound("regionTown", params.TownId)
|
||||
return
|
||||
}
|
||||
|
||||
if len(params.Code) > 0 && !lists.ContainsString(town.CustomCodes, params.Code) {
|
||||
town.CustomCodes = append(town.CustomCodes, params.Code)
|
||||
_, err = this.RPC().RegionTownRPC().UpdateRegionTownCustom(this.AdminContext(), &pb.UpdateRegionTownCustomRequest{
|
||||
RegionTownId: params.TownId,
|
||||
CustomName: town.CustomName,
|
||||
CustomCodes: town.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type CitiesAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CitiesAction) RunPost(params struct {
|
||||
LibraryFileId int64
|
||||
Size int
|
||||
}) {
|
||||
missingCitiesResp, err := this.RPC().IPLibraryFileRPC().CheckCitiesWithIPLibraryFileId(this.AdminContext(), &pb.CheckCitiesWithIPLibraryFileIdRequest{
|
||||
IpLibraryFileId: params.LibraryFileId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var missingCityMaps = []maps.Map{}
|
||||
for _, missingCity := range missingCitiesResp.MissingCities {
|
||||
var similarCityMaps = []maps.Map{}
|
||||
for _, city := range missingCity.SimilarCities {
|
||||
similarCityMaps = append(similarCityMaps, maps.Map{
|
||||
"id": city.Id,
|
||||
"displayName": city.DisplayName,
|
||||
})
|
||||
}
|
||||
|
||||
missingCityMaps = append(missingCityMaps, maps.Map{
|
||||
"countryName": missingCity.CountryName,
|
||||
"provinceName": missingCity.ProvinceName,
|
||||
"cityName": missingCity.CityName,
|
||||
"similarCities": similarCityMaps,
|
||||
})
|
||||
|
||||
if params.Size > 0 && len(missingCityMaps) >= params.Size {
|
||||
break
|
||||
}
|
||||
}
|
||||
this.Data["missingCities"] = missingCityMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type CountriesAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CountriesAction) RunPost(params struct {
|
||||
LibraryFileId int64
|
||||
}) {
|
||||
missingCountriesResp, err := this.RPC().IPLibraryFileRPC().CheckCountriesWithIPLibraryFileId(this.AdminContext(), &pb.CheckCountriesWithIPLibraryFileIdRequest{
|
||||
IpLibraryFileId: params.LibraryFileId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var missingCountryMaps = []maps.Map{}
|
||||
for _, missingCountry := range missingCountriesResp.MissingCountries {
|
||||
var similarCountryMaps = []maps.Map{}
|
||||
for _, country := range missingCountry.SimilarCountries {
|
||||
similarCountryMaps = append(similarCountryMaps, maps.Map{
|
||||
"id": country.Id,
|
||||
"displayName": country.DisplayName,
|
||||
})
|
||||
}
|
||||
|
||||
missingCountryMaps = append(missingCountryMaps, maps.Map{
|
||||
"countryName": missingCountry.CountryName,
|
||||
"similarCountries": similarCountryMaps,
|
||||
})
|
||||
}
|
||||
this.Data["missingCountries"] = missingCountryMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type FinishAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *FinishAction) RunPost(params struct {
|
||||
LibraryFileId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.IPLibrary_LogFinishIPLibrary, params.LibraryFileId)
|
||||
|
||||
// set finished
|
||||
_, err := this.RPC().IPLibraryFileRPC().UpdateIPLibraryFileFinished(this.AdminContext(), &pb.UpdateIPLibraryFileFinishedRequest{IpLibraryFileId: params.LibraryFileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// generate
|
||||
_, err = this.RPC().IPLibraryFileRPC().GenerateIPLibraryFile(this.AdminContext(), &pb.GenerateIPLibraryFileRequest{IpLibraryFileId: params.LibraryFileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type GenerateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *GenerateAction) RunPost(params struct {
|
||||
LibraryFileId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.IPLibraryFile_LogGenerateIPLibraryFile, params.LibraryFileId)
|
||||
|
||||
_, err := this.RPC().IPLibraryFileRPC().GenerateIPLibraryFile(this.AdminContext(), &pb.GenerateIPLibraryFileRequest{IpLibraryFileId: params.LibraryFileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type ProvidersAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ProvidersAction) RunPost(params struct {
|
||||
LibraryFileId int64
|
||||
}) {
|
||||
missingProvidersResp, err := this.RPC().IPLibraryFileRPC().CheckProvidersWithIPLibraryFileId(this.AdminContext(), &pb.CheckProvidersWithIPLibraryFileIdRequest{
|
||||
IpLibraryFileId: params.LibraryFileId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var missingProviderMaps = []maps.Map{}
|
||||
for _, missingProvider := range missingProvidersResp.MissingProviders {
|
||||
var similarProviderMaps = []maps.Map{}
|
||||
for _, provider := range missingProvider.SimilarProviders {
|
||||
similarProviderMaps = append(similarProviderMaps, maps.Map{
|
||||
"id": provider.Id,
|
||||
"displayName": provider.DisplayName,
|
||||
})
|
||||
}
|
||||
|
||||
missingProviderMaps = append(missingProviderMaps, maps.Map{
|
||||
"providerName": missingProvider.ProviderName,
|
||||
"similarProviders": similarProviderMaps,
|
||||
})
|
||||
}
|
||||
this.Data["missingProviders"] = missingProviderMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type ProvincesAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ProvincesAction) RunPost(params struct {
|
||||
LibraryFileId int64
|
||||
}) {
|
||||
missingProvincesResp, err := this.RPC().IPLibraryFileRPC().CheckProvincesWithIPLibraryFileId(this.AdminContext(), &pb.CheckProvincesWithIPLibraryFileIdRequest{
|
||||
IpLibraryFileId: params.LibraryFileId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var missingProvinceMaps = []maps.Map{}
|
||||
for _, missingProvince := range missingProvincesResp.MissingProvinces {
|
||||
var similarProvinceMaps = []maps.Map{}
|
||||
for _, province := range missingProvince.SimilarProvinces {
|
||||
similarProvinceMaps = append(similarProvinceMaps, maps.Map{
|
||||
"id": province.Id,
|
||||
"displayName": province.DisplayName,
|
||||
})
|
||||
}
|
||||
|
||||
missingProvinceMaps = append(missingProvinceMaps, maps.Map{
|
||||
"countryName": missingProvince.CountryName,
|
||||
"provinceName": missingProvince.ProvinceName,
|
||||
"similarProvinces": similarProvinceMaps,
|
||||
})
|
||||
}
|
||||
this.Data["missingProvinces"] = missingProvinceMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
)
|
||||
|
||||
type TestFormatAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TestFormatAction) RunPost(params struct {
|
||||
Template string
|
||||
Text string
|
||||
}) {
|
||||
if len(params.Text) == 0 {
|
||||
this.Fail("请先输入测试数据")
|
||||
}
|
||||
|
||||
template, err := iplibrary.NewTemplate(params.Template)
|
||||
if err != nil {
|
||||
this.Fail("数据格式模板解析错误:" + err.Error())
|
||||
}
|
||||
|
||||
var emptyValues = []string{"0", "无"} // TODO
|
||||
|
||||
values, ok := template.Extract(params.Text, emptyValues)
|
||||
if !ok {
|
||||
this.Fail("无法分析数据,填写的测试数据和模板不符合")
|
||||
}
|
||||
this.Data["values"] = values
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type TownsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TownsAction) RunPost(params struct {
|
||||
LibraryFileId int64
|
||||
Size int
|
||||
}) {
|
||||
missingTownsResp, err := this.RPC().IPLibraryFileRPC().CheckTownsWithIPLibraryFileId(this.AdminContext(), &pb.CheckTownsWithIPLibraryFileIdRequest{
|
||||
IpLibraryFileId: params.LibraryFileId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var missingTownMaps = []maps.Map{}
|
||||
for _, missingTown := range missingTownsResp.MissingTowns {
|
||||
var similarTownMaps = []maps.Map{}
|
||||
for _, town := range missingTown.SimilarTowns {
|
||||
similarTownMaps = append(similarTownMaps, maps.Map{
|
||||
"id": town.Id,
|
||||
"displayName": town.DisplayName,
|
||||
})
|
||||
}
|
||||
|
||||
missingTownMaps = append(missingTownMaps, maps.Map{
|
||||
"countryName": missingTown.CountryName,
|
||||
"provinceName": missingTown.ProvinceName,
|
||||
"cityName": missingTown.CityName,
|
||||
"townName": missingTown.TownName,
|
||||
"similarTowns": similarTownMaps,
|
||||
})
|
||||
|
||||
if params.Size > 0 && len(missingTownMaps) >= params.Size {
|
||||
break
|
||||
}
|
||||
}
|
||||
this.Data["missingTowns"] = missingTownMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package creating
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"io"
|
||||
)
|
||||
|
||||
type UploadAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UploadAction) RunPost(params struct {
|
||||
Name string
|
||||
Template string
|
||||
EmptyValues []string
|
||||
Password string
|
||||
File *actions.File
|
||||
}) {
|
||||
if len(params.Name) == 0 {
|
||||
this.Fail("请输入IP库名称")
|
||||
return
|
||||
}
|
||||
|
||||
if len(params.Template) == 0 {
|
||||
this.Fail("请输入数据格式模板")
|
||||
return
|
||||
}
|
||||
|
||||
template, err := iplibrary.NewTemplate(params.Template)
|
||||
if err != nil {
|
||||
this.Fail("模板格式错误:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if params.File == nil {
|
||||
this.Fail("请上传文件")
|
||||
}
|
||||
|
||||
var emptyValues = []string{"0", "无"}
|
||||
|
||||
if len(params.EmptyValues) > 0 {
|
||||
for _, emptyValue := range params.EmptyValues {
|
||||
if !lists.ContainsString(emptyValues, emptyValue) {
|
||||
emptyValues = append(emptyValues, emptyValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||
Filename: params.File.Filename,
|
||||
Size: params.File.Size,
|
||||
IsPublic: false,
|
||||
MimeType: params.File.ContentType,
|
||||
Type: "ipLibraryFile",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var fileId = fileResp.FileId
|
||||
|
||||
fp, err := params.File.OriginFile.Open()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
_ = fp.Close()
|
||||
}()
|
||||
|
||||
var buf = make([]byte, 128*1024)
|
||||
var dataBuf = []byte{}
|
||||
|
||||
var countries = []string{}
|
||||
var provinces = [][2]string{}
|
||||
var cities = [][3]string{}
|
||||
var towns = [][4]string{}
|
||||
var providers = []string{}
|
||||
|
||||
var countryMap = map[string]bool{} // countryName => bool
|
||||
var provinceMap = map[string]bool{} // countryName_provinceName => bool
|
||||
var cityMap = map[string]bool{} // countryName_provinceName_cityName => bool
|
||||
var townMap = map[string]bool{} // countryName_provinceName_cityName_townName => bool
|
||||
var providerMap = map[string]bool{} // providerName => bool
|
||||
|
||||
for {
|
||||
n, err := fp.Read(buf)
|
||||
if n > 0 {
|
||||
var data = buf[:n]
|
||||
|
||||
// upload
|
||||
_, uploadErr := this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||
FileId: fileId,
|
||||
Data: data,
|
||||
})
|
||||
if uploadErr != nil {
|
||||
this.Fail("文件上传失败:" + uploadErr.Error())
|
||||
}
|
||||
|
||||
// parse
|
||||
dataBuf = append(dataBuf, data...)
|
||||
left, valuesList, failLine, parseIsOk, err := this.parse(template, dataBuf, emptyValues)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !parseIsOk {
|
||||
this.Fail("在 '" + failLine + "' 这行分析失败,请对比数据模板,检查数据格式")
|
||||
return
|
||||
}
|
||||
for _, value := range valuesList {
|
||||
var countryName = value["country"]
|
||||
var provinceName = value["province"]
|
||||
var cityName = value["city"]
|
||||
var townName = value["town"]
|
||||
var providerName = value["provider"]
|
||||
|
||||
// country
|
||||
if len(countryName) > 0 {
|
||||
_, ok := countryMap[countryName]
|
||||
if !ok {
|
||||
countries = append(countries, countryName)
|
||||
countryMap[countryName] = true
|
||||
}
|
||||
|
||||
// province
|
||||
if len(provinceName) > 0 {
|
||||
var key = countryName + "_" + provinceName
|
||||
_, ok = provinceMap[key]
|
||||
if !ok {
|
||||
provinceMap[key] = true
|
||||
provinces = append(provinces, [2]string{countryName, provinceName})
|
||||
}
|
||||
|
||||
// city
|
||||
if len(cityName) > 0 {
|
||||
key += "_" + cityName
|
||||
_, ok = cityMap[key]
|
||||
if !ok {
|
||||
cityMap[key] = true
|
||||
cities = append(cities, [3]string{countryName, provinceName, cityName})
|
||||
}
|
||||
|
||||
// town
|
||||
if len(townName) > 0 {
|
||||
key += "_" + townName
|
||||
_, ok = townMap[key]
|
||||
if !ok {
|
||||
townMap[key] = true
|
||||
towns = append(towns, [4]string{countryName, provinceName, cityName, townName})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// provider
|
||||
if len(providerName) > 0 {
|
||||
_, ok := providerMap[providerName]
|
||||
if !ok {
|
||||
providerMap[providerName] = true
|
||||
providers = append(providers, providerName)
|
||||
}
|
||||
}
|
||||
}
|
||||
dataBuf = left
|
||||
}
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
countriesJSON, err := json.Marshal(countries)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
provincesJSON, err := json.Marshal(provinces)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
citiesJSON, err := json.Marshal(cities)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
townsJSON, err := json.Marshal(towns)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
providersJSON, err := json.Marshal(providers)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().IPLibraryFileRPC().CreateIPLibraryFile(this.AdminContext(), &pb.CreateIPLibraryFileRequest{
|
||||
Name: params.Name,
|
||||
Template: params.Template,
|
||||
FileId: fileId,
|
||||
EmptyValues: params.EmptyValues,
|
||||
Password: params.Password,
|
||||
CountriesJSON: countriesJSON,
|
||||
ProvincesJSON: provincesJSON,
|
||||
CitiesJSON: citiesJSON,
|
||||
TownsJSON: townsJSON,
|
||||
ProvidersJSON: providersJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var ipLibraryFileId = createResp.IpLibraryFileId
|
||||
defer this.CreateLogInfo(codes.IPLibraryFile_LogUploadIPLibraryFile, ipLibraryFileId)
|
||||
|
||||
this.Data["libraryFileId"] = ipLibraryFileId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
|
||||
func (this *UploadAction) parse(template *iplibrary.Template, data []byte, emptyValues []string) (left []byte, valuesList []map[string]string, failLine string, ok bool, err error) {
|
||||
ok = true
|
||||
|
||||
if len(data) == 0 {
|
||||
return
|
||||
}
|
||||
for {
|
||||
var index = bytes.IndexByte(data, '\n')
|
||||
if index >= 0 {
|
||||
var line = data[:index+1]
|
||||
values, found := template.Extract(string(line), emptyValues)
|
||||
if found {
|
||||
valuesList = append(valuesList, values)
|
||||
} else {
|
||||
// 防止错误信息太长
|
||||
if len(line) > 256 {
|
||||
line = line[:256]
|
||||
}
|
||||
failLine = string(line)
|
||||
ok = false
|
||||
return
|
||||
}
|
||||
|
||||
data = data[index+1:]
|
||||
} else {
|
||||
left = data
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
ArtifactId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.IPLibraryArtifact_LogDeleteIPLibraryArtifact, params.ArtifactId)
|
||||
|
||||
// 删除数据库中的记录
|
||||
_, err := this.RPC().IPLibraryArtifactRPC().DeleteIPLibraryArtifact(this.AdminContext(), &pb.DeleteIPLibraryArtifactRequest{IpLibraryArtifactId: params.ArtifactId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 删除 EdgeAPI 目录下的 MaxMind 文件(删除所有,因为无法确定具体是哪个文件)
|
||||
_, err = this.RPC().IPLibraryRPC().DeleteMaxMindFile(this.AdminContext(), &pb.DeleteMaxMindFileRequest{
|
||||
Filename: "", // 空字符串表示删除所有
|
||||
})
|
||||
if err != nil {
|
||||
// 记录错误但不影响删除操作
|
||||
this.Fail("删除IP库文件失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type DownloadAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DownloadAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *DownloadAction) RunGet(params struct {
|
||||
ArtifactId int64
|
||||
}) {
|
||||
artifactResp, err := this.RPC().IPLibraryArtifactRPC().FindIPLibraryArtifact(this.AdminContext(), &pb.FindIPLibraryArtifactRequest{
|
||||
IpLibraryArtifactId: params.ArtifactId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var artifact = artifactResp.IpLibraryArtifact
|
||||
if artifact == nil {
|
||||
this.NotFound("IPLibraryArtifact", params.ArtifactId)
|
||||
return
|
||||
}
|
||||
|
||||
var fileId = artifact.FileId
|
||||
if fileId <= 0 {
|
||||
this.WriteString("ip artifact file not generated")
|
||||
return
|
||||
}
|
||||
|
||||
fileResp, err := this.RPC().FileRPC().FindEnabledFile(this.AdminContext(), &pb.FindEnabledFileRequest{FileId: fileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var file = fileResp.File
|
||||
if file == nil {
|
||||
this.WriteString("file not found")
|
||||
return
|
||||
}
|
||||
|
||||
chunkIdsResp, err := this.RPC().FileChunkRPC().FindAllFileChunkIds(this.AdminContext(), &pb.FindAllFileChunkIdsRequest{FileId: file.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.AddHeader("Content-Disposition", "attachment; filename=\"ip-"+artifact.Code+".db\";")
|
||||
this.AddHeader("Content-Length", types.String(file.Size))
|
||||
for _, chunkId := range chunkIdsResp.FileChunkIds {
|
||||
chunkResp, err := this.RPC().FileChunkRPC().DownloadFileChunk(this.AdminContext(), &pb.DownloadFileChunkRequest{FileChunkId: chunkId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var chunk = chunkResp.FileChunk
|
||||
if chunk == nil {
|
||||
break
|
||||
}
|
||||
_, _ = this.Write(chunkResp.FileChunk.Data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Helper struct {
|
||||
}
|
||||
|
||||
func NewHelper() *Helper {
|
||||
return &Helper{}
|
||||
}
|
||||
|
||||
func (this *Helper) BeforeAction(action *actions.ActionObject) {
|
||||
if action.Request.Method != http.MethodGet {
|
||||
return
|
||||
}
|
||||
|
||||
action.Data["mainTab"] = "component"
|
||||
action.Data["secondMenuItem"] = "ip-library"
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/iplibraryutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "ipLibrary", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
this.Data["canAccess"] = iplibraryutils.CanAccess()
|
||||
|
||||
// IP库列表
|
||||
artifactsResp, err := this.RPC().IPLibraryArtifactRPC().FindAllIPLibraryArtifacts(this.AdminContext(), &pb.FindAllIPLibraryArtifactsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var artifactMaps = []maps.Map{}
|
||||
|
||||
// 按创建时间倒序排序,最新的在前
|
||||
artifacts := artifactsResp.IpLibraryArtifacts
|
||||
for i := 0; i < len(artifacts); i++ {
|
||||
for j := i + 1; j < len(artifacts); j++ {
|
||||
if artifacts[i].CreatedAt < artifacts[j].CreatedAt {
|
||||
artifacts[i], artifacts[j] = artifacts[j], artifacts[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 确保最后一个(最新的)是使用中的,其他都是未使用的
|
||||
// 如果列表不为空,将最新的设为使用中,其他设为未使用
|
||||
if len(artifacts) > 0 {
|
||||
latestId := artifacts[0].Id
|
||||
for _, artifact := range artifacts {
|
||||
var shouldBePublic = (artifact.Id == latestId)
|
||||
if artifact.IsPublic != shouldBePublic {
|
||||
// 需要更新状态(这里只标记,不实际更新数据库,因为上传时已经更新了)
|
||||
// 如果数据库状态不一致,这里会显示不一致,但不会自动修复
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, artifact := range artifacts {
|
||||
var meta = &iplibrary.Meta{}
|
||||
if len(artifact.MetaJSON) > 0 {
|
||||
err = json.Unmarshal(artifact.MetaJSON, meta)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 文件信息
|
||||
var fileMap = maps.Map{
|
||||
"size": 0,
|
||||
}
|
||||
if artifact.File != nil {
|
||||
fileMap = maps.Map{
|
||||
"size": artifact.File.Size,
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否使用中:如果是列表中的第一个(最新的),则标记为使用中
|
||||
isPublic := artifact.Id == artifacts[0].Id
|
||||
|
||||
// 根据文件名判断IP库类型
|
||||
libraryType := "未知"
|
||||
if artifact.File != nil && len(artifact.File.Filename) > 0 {
|
||||
filename := strings.ToLower(artifact.File.Filename)
|
||||
if strings.Contains(filename, "city") {
|
||||
libraryType = "city库"
|
||||
} else if strings.Contains(filename, "asn") {
|
||||
libraryType = "asn库"
|
||||
}
|
||||
}
|
||||
|
||||
artifactMaps = append(artifactMaps, maps.Map{
|
||||
"id": artifact.Id,
|
||||
"name": artifact.Name,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", artifact.CreatedAt),
|
||||
"isPublic": isPublic,
|
||||
"fileId": artifact.FileId,
|
||||
"code": artifact.Code,
|
||||
"libraryType": libraryType,
|
||||
"countCountries": len(meta.Countries),
|
||||
"countProvinces": len(meta.Provinces),
|
||||
"countCities": len(meta.Cities),
|
||||
"countTowns": len(meta.Towns),
|
||||
"countProviders": len(meta.Providers),
|
||||
"file": fileMap,
|
||||
})
|
||||
}
|
||||
this.Data["artifacts"] = artifactMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
//go:build plus
|
||||
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/cities"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/countries"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/creating"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/libraries"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/library"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/providers"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/provinces"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/towns"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/settingutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewBasicHelper()).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
|
||||
Helper(NewHelper()).
|
||||
Helper(settingutils.NewHelper("ipLibrary")).
|
||||
|
||||
// IP库
|
||||
Prefix("/settings/ip-library").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/upload", new(UploadAction)).
|
||||
Get("/download", new(DownloadAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Post("/updatePublic", new(UpdatePublicAction)).
|
||||
|
||||
// IP库
|
||||
Prefix("/settings/ip-library/libraries").
|
||||
Get("", new(libraries.IndexAction)).
|
||||
GetPost("/create", new(libraries.CreateAction)).
|
||||
Post("/delete", new(libraries.DeleteAction)).
|
||||
|
||||
// 创建
|
||||
Prefix("/settings/ip-library/creating").
|
||||
Post("/testFormat", new(creating.TestFormatAction)).
|
||||
Post("/upload", new(creating.UploadAction)).
|
||||
Post("/countries", new(creating.CountriesAction)).
|
||||
Post("/provinces", new(creating.ProvincesAction)).
|
||||
Post("/cities", new(creating.CitiesAction)).
|
||||
Post("/towns", new(creating.TownsAction)).
|
||||
Post("/providers", new(creating.ProvidersAction)).
|
||||
Post("/addCountryCustomCode", new(creating.AddCountryCustomCodeAction)).
|
||||
Post("/addProvinceCustomCode", new(creating.AddProvinceCustomCodeAction)).
|
||||
Post("/addCityCustomCode", new(creating.AddCityCustomCodeAction)).
|
||||
Post("/addTownCustomCode", new(creating.AddTownCustomCodeAction)).
|
||||
Post("/addProviderCustomCode", new(creating.AddProviderCustomCodeAction)).
|
||||
Post("/finish", new(creating.FinishAction)).
|
||||
Post("/generate", new(creating.GenerateAction)).
|
||||
|
||||
// 单个IP库
|
||||
Prefix("/settings/ip-library/library").
|
||||
Get("", new(library.IndexAction)).
|
||||
Get("/download", new(library.DownloadAction)).
|
||||
GetPost("/test", new(library.TestAction)).
|
||||
|
||||
// 国家/地区
|
||||
Prefix("/settings/ip-library/countries").
|
||||
Get("", new(countries.IndexAction)).
|
||||
GetPost("/updatePopup", new(countries.UpdatePopupAction)).
|
||||
|
||||
// 省份
|
||||
Prefix("/settings/ip-library/provinces").
|
||||
Get("", new(provinces.IndexAction)).
|
||||
GetPost("/updatePopup", new(provinces.UpdatePopupAction)).
|
||||
|
||||
// 城市
|
||||
Prefix("/settings/ip-library/cities").
|
||||
Get("", new(cities.IndexAction)).
|
||||
GetPost("/updatePopup", new(cities.UpdatePopupAction)).
|
||||
Post("/provinceOptions", new(cities.ProvinceOptionsAction)).
|
||||
|
||||
// 区县
|
||||
Prefix("/settings/ip-library/towns").
|
||||
Get("", new(towns.IndexAction)).
|
||||
GetPost("/updatePopup", new(towns.UpdatePopupAction)).
|
||||
Post("/provinceOptions", new(towns.ProvinceOptionsAction)).
|
||||
Post("/cityOptions", new(towns.CityOptionsAction)).
|
||||
|
||||
// ISP
|
||||
Prefix("/settings/ip-library/providers").
|
||||
Get("", new(providers.IndexAction)).
|
||||
GetPost("/updatePopup", new(providers.UpdatePopupAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package iplibraryutils
|
||||
|
||||
import "github.com/iwind/TeaGo/Tea"
|
||||
|
||||
func CanAccess() bool {
|
||||
return Tea.IsTesting()
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package libraries
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/iplibraryutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type CreateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateAction) Init() {
|
||||
this.Nav("", "", "create")
|
||||
}
|
||||
|
||||
func (this *CreateAction) RunGet(params struct {
|
||||
LibraryFileId int64
|
||||
}) {
|
||||
// 检查权限
|
||||
if !iplibraryutils.CanAccess() {
|
||||
return
|
||||
}
|
||||
this.Data["canAccess"] = true
|
||||
|
||||
// 初始化
|
||||
this.Data["updatingLibraryFile"] = nil
|
||||
|
||||
if params.LibraryFileId > 0 {
|
||||
libraryFileResp, err := this.RPC().IPLibraryFileRPC().FindIPLibraryFile(this.AdminContext(), &pb.FindIPLibraryFileRequest{IpLibraryFileId: params.LibraryFileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var libraryFile = libraryFileResp.IpLibraryFile
|
||||
if libraryFile != nil {
|
||||
this.Data["updatingLibraryFile"] = maps.Map{
|
||||
"id": libraryFile.Id,
|
||||
"name": libraryFile.Name,
|
||||
"template": libraryFile.Template,
|
||||
"emptyValues": libraryFile.EmptyValues,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package libraries
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
LibraryFileId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.IPLibraryFile_LogDeleteIPLibraryFile, params.LibraryFileId)
|
||||
|
||||
_, err := this.RPC().IPLibraryFileRPC().DeleteIPLibraryFile(this.AdminContext(), &pb.DeleteIPLibraryFileRequest{IpLibraryFileId: params.LibraryFileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package libraries
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/iplibraryutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "library")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
this.Data["canAccess"] = iplibraryutils.CanAccess()
|
||||
|
||||
librariesResp, err := this.RPC().IPLibraryFileRPC().FindAllFinishedIPLibraryFiles(this.AdminContext(), &pb.FindAllFinishedIPLibraryFilesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var libraryMaps = []maps.Map{}
|
||||
for _, library := range librariesResp.IpLibraryFiles {
|
||||
if library.EmptyValues == nil {
|
||||
library.EmptyValues = []string{}
|
||||
}
|
||||
libraryMaps = append(libraryMaps, maps.Map{
|
||||
"id": library.Id,
|
||||
"name": library.Name,
|
||||
"template": library.Template,
|
||||
"emptyValues": library.EmptyValues,
|
||||
"generatedTime": timeutil.FormatTime("Y-m-d H:i:s", library.GeneratedAt),
|
||||
"generatedFileId": library.GeneratedFileId,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", library.CreatedAt),
|
||||
})
|
||||
}
|
||||
this.Data["libraries"] = libraryMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package library
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type DownloadAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DownloadAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *DownloadAction) RunGet(params struct {
|
||||
LibraryFileId int64
|
||||
}) {
|
||||
libraryResp, err := this.RPC().IPLibraryFileRPC().FindIPLibraryFile(this.AdminContext(), &pb.FindIPLibraryFileRequest{IpLibraryFileId: params.LibraryFileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var library = libraryResp.IpLibraryFile
|
||||
if library == nil {
|
||||
this.NotFound("IPLibraryFile", params.LibraryFileId)
|
||||
return
|
||||
}
|
||||
|
||||
var fileId = library.GeneratedFileId
|
||||
if fileId <= 0 {
|
||||
this.WriteString("ip library file not generated")
|
||||
return
|
||||
}
|
||||
|
||||
fileResp, err := this.RPC().FileRPC().FindEnabledFile(this.AdminContext(), &pb.FindEnabledFileRequest{FileId: fileId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var file = fileResp.File
|
||||
if file == nil {
|
||||
this.WriteString("file not found")
|
||||
return
|
||||
}
|
||||
|
||||
chunkIdsResp, err := this.RPC().FileChunkRPC().FindAllFileChunkIds(this.AdminContext(), &pb.FindAllFileChunkIdsRequest{FileId: file.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.AddHeader("Content-Disposition", "attachment; filename=\"ip-library.db\";")
|
||||
this.AddHeader("Content-Length", types.String(file.Size))
|
||||
for _, chunkId := range chunkIdsResp.FileChunkIds {
|
||||
chunkResp, err := this.RPC().FileChunkRPC().DownloadFileChunk(this.AdminContext(), &pb.DownloadFileChunkRequest{FileChunkId: chunkId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var chunk = chunkResp.FileChunk
|
||||
if chunk == nil {
|
||||
break
|
||||
}
|
||||
_, _ = this.Write(chunkResp.FileChunk.Data)
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package library
|
||||
|
||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
// TODO
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package library
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"os"
|
||||
)
|
||||
|
||||
type TestAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TestAction) Init() {
|
||||
this.Nav("", "ipLibrary", "test")
|
||||
}
|
||||
|
||||
func (this *TestAction) RunGet(params struct{}) {
|
||||
// 通过 RPC 查询 EdgeAPI 的 MaxMind 文件状态
|
||||
statusResp, err := this.RPC().IPLibraryRPC().FindMaxMindFileStatus(this.AdminContext(), &pb.FindMaxMindFileStatusRequest{})
|
||||
if err != nil {
|
||||
// RPC 调用失败,记录错误并使用本地检查作为后备
|
||||
logs.Println("[IP_LIBRARY_TEST]RPC call failed: " + err.Error())
|
||||
// RPC 调用失败,使用本地检查作为后备
|
||||
iplibDir := Tea.Root + "/data/iplibrary"
|
||||
cityDBPath := iplibDir + "/maxmind-city.mmdb"
|
||||
asnDBPath := iplibDir + "/maxmind-asn.mmdb"
|
||||
|
||||
uploadedCityExists := false
|
||||
uploadedASNExists := false
|
||||
|
||||
if _, err := os.Stat(cityDBPath); err == nil {
|
||||
uploadedCityExists = true
|
||||
}
|
||||
if _, err := os.Stat(asnDBPath); err == nil {
|
||||
uploadedASNExists = true
|
||||
}
|
||||
|
||||
// 检查是否使用了MaxMind库(通过测试查询来判断)
|
||||
testIP := "8.8.8.8"
|
||||
testResult := iplibrary.LookupIP(testIP)
|
||||
usingMaxMind := false
|
||||
if testResult != nil && testResult.IsOk() {
|
||||
if testResult.CountryId() == 0 && len(testResult.CountryName()) > 0 {
|
||||
usingMaxMind = true
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["maxMindCityExists"] = uploadedCityExists
|
||||
this.Data["maxMindASNExists"] = uploadedASNExists
|
||||
this.Data["usingMaxMind"] = usingMaxMind
|
||||
this.Data["usingEmbeddedMaxMind"] = usingMaxMind && !uploadedCityExists
|
||||
} else {
|
||||
// 使用 RPC 返回的状态
|
||||
this.Data["maxMindCityExists"] = statusResp.CityExists
|
||||
this.Data["maxMindASNExists"] = statusResp.AsnExists
|
||||
this.Data["usingMaxMind"] = statusResp.UsingMaxMind
|
||||
this.Data["usingEmbeddedMaxMind"] = statusResp.UsingEmbeddedMaxMind
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *TestAction) RunPost(params struct {
|
||||
Ip string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
if len(params.Ip) == 0 {
|
||||
this.Fail("请输入IP地址")
|
||||
return
|
||||
}
|
||||
|
||||
// 查询IP信息
|
||||
var result = iplibrary.LookupIP(params.Ip)
|
||||
if result == nil || !result.IsOk() {
|
||||
this.Data["result"] = maps.Map{
|
||||
"isOk": false,
|
||||
"ip": params.Ip,
|
||||
"error": "未找到该IP的地理位置信息",
|
||||
}
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
// 判断IP库类型
|
||||
// MaxMind库的特征:CountryId 和 ProvinceId 通常为 0(因为MaxMind不使用ID系统)
|
||||
// 只要查询结果中CountryId为0且有国家名称,就认为是MaxMind(不管文件是否存在,可能是嵌入的)
|
||||
iplibDir := Tea.Root + "/data/iplibrary"
|
||||
cityDBPath := iplibDir + "/maxmind-city.mmdb"
|
||||
|
||||
var libraryType = "默认IP库"
|
||||
var libraryVersion = ""
|
||||
|
||||
// 如果查询结果中CountryId为0(MaxMind特征)且有国家名称,则认为是MaxMind
|
||||
// 不管文件是否存在,因为可能是使用嵌入的 MaxMind 库
|
||||
if result.CountryId() == 0 && len(result.CountryName()) > 0 {
|
||||
libraryType = "MaxMind GeoIP2"
|
||||
libraryVersion = "3"
|
||||
}
|
||||
|
||||
// 通过 RPC 查询 EdgeAPI 的 MaxMind 文件状态
|
||||
statusResp, err := this.RPC().IPLibraryRPC().FindMaxMindFileStatus(this.AdminContext(), &pb.FindMaxMindFileStatusRequest{})
|
||||
uploadedCityExists := false
|
||||
uploadedASNExists := false
|
||||
if err == nil {
|
||||
uploadedCityExists = statusResp.CityExists
|
||||
uploadedASNExists = statusResp.AsnExists
|
||||
} else {
|
||||
// RPC 调用失败,使用本地检查作为后备
|
||||
if _, err := os.Stat(cityDBPath); err == nil {
|
||||
uploadedCityExists = true
|
||||
}
|
||||
asnDBPath := iplibDir + "/maxmind-asn.mmdb"
|
||||
if _, err := os.Stat(asnDBPath); err == nil {
|
||||
uploadedASNExists = true
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否使用了MaxMind库(即使没有上传文件,也可能使用嵌入的默认MaxMind库)
|
||||
usingMaxMind := false
|
||||
if result.CountryId() == 0 && len(result.CountryName()) > 0 {
|
||||
usingMaxMind = true
|
||||
}
|
||||
|
||||
this.Data["result"] = maps.Map{
|
||||
"isDone": true,
|
||||
"isOk": true,
|
||||
"ip": params.Ip,
|
||||
"libraryType": libraryType,
|
||||
"libraryVersion": libraryVersion,
|
||||
"country": result.CountryName(),
|
||||
"countryId": result.CountryId(),
|
||||
"province": result.ProvinceName(),
|
||||
"provinceId": result.ProvinceId(),
|
||||
"city": result.CityName(),
|
||||
"cityId": result.CityId(),
|
||||
"town": result.TownName(),
|
||||
"townId": result.TownId(),
|
||||
"provider": result.ProviderName(),
|
||||
"providerId": result.ProviderId(),
|
||||
"summary": result.Summary(),
|
||||
"regionSummary": result.RegionSummary(),
|
||||
}
|
||||
this.Data["maxMindCityExists"] = uploadedCityExists
|
||||
this.Data["maxMindASNExists"] = uploadedASNExists
|
||||
this.Data["usingMaxMind"] = usingMaxMind
|
||||
this.Data["usingEmbeddedMaxMind"] = usingMaxMind && !uploadedCityExists
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package providers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/iplibraryutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "provider")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
// 检查权限
|
||||
if !iplibraryutils.CanAccess() {
|
||||
return
|
||||
}
|
||||
this.Data["canAccess"] = true
|
||||
|
||||
providersResp, err := this.RPC().RegionProviderRPC().FindAllRegionProviders(this.AdminContext(), &pb.FindAllRegionProvidersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var providerMaps = []maps.Map{}
|
||||
for _, provider := range providersResp.RegionProviders {
|
||||
if provider.Codes == nil {
|
||||
provider.Codes = []string{}
|
||||
}
|
||||
if provider.CustomCodes == nil {
|
||||
provider.CustomCodes = []string{}
|
||||
}
|
||||
providerMaps = append(providerMaps, maps.Map{
|
||||
"id": provider.Id,
|
||||
"name": provider.Name,
|
||||
"codes": provider.Codes,
|
||||
"customName": provider.CustomName,
|
||||
"customCodes": provider.CustomCodes,
|
||||
})
|
||||
}
|
||||
this.Data["providers"] = providerMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package providers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
ProviderId int64
|
||||
}) {
|
||||
providerResp, err := this.RPC().RegionProviderRPC().FindRegionProvider(this.AdminContext(), &pb.FindRegionProviderRequest{RegionProviderId: params.ProviderId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var provider = providerResp.RegionProvider
|
||||
if provider == nil {
|
||||
this.NotFound("regionProvider", params.ProviderId)
|
||||
return
|
||||
}
|
||||
|
||||
if provider.Codes == nil {
|
||||
provider.Codes = []string{}
|
||||
}
|
||||
|
||||
if provider.CustomCodes == nil {
|
||||
provider.CustomCodes = []string{}
|
||||
}
|
||||
|
||||
this.Data["provider"] = maps.Map{
|
||||
"id": provider.Id,
|
||||
"name": provider.Name,
|
||||
"codes": provider.Codes,
|
||||
"customName": provider.CustomName,
|
||||
"customCodes": provider.CustomCodes,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
ProviderId int64
|
||||
CustomName string
|
||||
CustomCodes []string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionProvider_LogUpdateRegionProviderCustom, params.ProviderId)
|
||||
|
||||
_, err := this.RPC().RegionProviderRPC().UpdateRegionProviderCustom(this.AdminContext(), &pb.UpdateRegionProviderCustomRequest{
|
||||
RegionProviderId: params.ProviderId,
|
||||
CustomName: params.CustomName,
|
||||
CustomCodes: params.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package provinces
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/iplibraryutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "province")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
CountryId int64
|
||||
}) {
|
||||
// 检查权限
|
||||
if !iplibraryutils.CanAccess() {
|
||||
return
|
||||
}
|
||||
this.Data["canAccess"] = true
|
||||
|
||||
if params.CountryId <= 0 {
|
||||
params.CountryId = 1 // china
|
||||
}
|
||||
|
||||
this.Data["countryId"] = params.CountryId
|
||||
|
||||
// 所有国家/地区
|
||||
countriesResp, err := this.RPC().RegionCountryRPC().FindAllRegionCountries(this.AdminContext(), &pb.FindAllRegionCountriesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var countryMaps = []maps.Map{}
|
||||
for _, country := range countriesResp.RegionCountries {
|
||||
countryMaps = append(countryMaps, maps.Map{
|
||||
"id": country.Id,
|
||||
"name": country.DisplayName,
|
||||
})
|
||||
}
|
||||
this.Data["countries"] = countryMaps
|
||||
|
||||
// 当前国家/地区下的省份
|
||||
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{
|
||||
RegionCountryId: params.CountryId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var provinceMaps = []maps.Map{}
|
||||
for _, province := range provincesResp.RegionProvinces {
|
||||
if province.Codes == nil {
|
||||
province.Codes = []string{}
|
||||
}
|
||||
if province.CustomCodes == nil {
|
||||
province.CustomCodes = []string{}
|
||||
}
|
||||
provinceMaps = append(provinceMaps, maps.Map{
|
||||
"id": province.Id,
|
||||
"name": province.Name,
|
||||
"codes": province.Codes,
|
||||
"customName": province.CustomName,
|
||||
"customCodes": province.CustomCodes,
|
||||
})
|
||||
}
|
||||
this.Data["provinces"] = provinceMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package provinces
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
ProvinceId int64
|
||||
}) {
|
||||
provinceResp, err := this.RPC().RegionProvinceRPC().FindRegionProvince(this.AdminContext(), &pb.FindRegionProvinceRequest{RegionProvinceId: params.ProvinceId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var province = provinceResp.RegionProvince
|
||||
if province == nil {
|
||||
this.NotFound("regionProvince", params.ProvinceId)
|
||||
return
|
||||
}
|
||||
if province.Codes == nil {
|
||||
province.Codes = []string{}
|
||||
}
|
||||
if province.CustomCodes == nil {
|
||||
province.CustomCodes = []string{}
|
||||
}
|
||||
this.Data["province"] = maps.Map{
|
||||
"id": province.Id,
|
||||
"name": province.Name,
|
||||
"codes": province.Codes,
|
||||
"customName": province.CustomName,
|
||||
"customCodes": province.CustomCodes,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
ProvinceId int64
|
||||
CustomName string
|
||||
CustomCodes []string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionProvince_LogUpdateRegionProvinceCustom, params.ProvinceId)
|
||||
|
||||
_, err := this.RPC().RegionProvinceRPC().UpdateRegionProvinceCustom(this.AdminContext(), &pb.UpdateRegionProvinceCustomRequest{
|
||||
RegionProvinceId: params.ProvinceId,
|
||||
CustomName: params.CustomName,
|
||||
CustomCodes: params.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package towns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type CityOptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CityOptionsAction) RunPost(params struct {
|
||||
ProvinceId int64
|
||||
}) {
|
||||
citiesResp, err := this.RPC().RegionCityRPC().FindAllRegionCitiesWithRegionProvinceId(this.AdminContext(), &pb.FindAllRegionCitiesWithRegionProvinceIdRequest{
|
||||
RegionProvinceId: params.ProvinceId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var cityMaps = []maps.Map{}
|
||||
for _, city := range citiesResp.RegionCities {
|
||||
cityMaps = append(cityMaps, maps.Map{
|
||||
"id": city.Id,
|
||||
"name": city.DisplayName,
|
||||
})
|
||||
}
|
||||
this.Data["cities"] = cityMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package towns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/iplibraryutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "town")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
CountryId int64
|
||||
ProvinceId int64
|
||||
CityId int64
|
||||
}) {
|
||||
// 检查权限
|
||||
if !iplibraryutils.CanAccess() {
|
||||
return
|
||||
}
|
||||
this.Data["canAccess"] = true
|
||||
|
||||
if params.CountryId <= 0 || params.ProvinceId <= 0 || params.CityId <= 0 {
|
||||
params.CountryId = 1 // china
|
||||
params.ProvinceId = 1 // beijing
|
||||
params.CityId = 1 // beijing
|
||||
}
|
||||
|
||||
this.Data["countryId"] = params.CountryId
|
||||
this.Data["provinceId"] = params.ProvinceId
|
||||
this.Data["cityId"] = params.CityId
|
||||
|
||||
// 所有国家/地区
|
||||
countriesResp, err := this.RPC().RegionCountryRPC().FindAllRegionCountries(this.AdminContext(), &pb.FindAllRegionCountriesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var countryMaps = []maps.Map{}
|
||||
for _, country := range countriesResp.RegionCountries {
|
||||
countryMaps = append(countryMaps, maps.Map{
|
||||
"id": country.Id,
|
||||
"name": country.DisplayName,
|
||||
})
|
||||
}
|
||||
this.Data["countries"] = countryMaps
|
||||
|
||||
// 区县列表
|
||||
townsResp, err := this.RPC().RegionTownRPC().FindAllRegionTownsWithRegionCityId(this.AdminContext(), &pb.FindAllRegionTownsWithRegionCityIdRequest{
|
||||
RegionCityId: params.CityId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var townMaps = []maps.Map{}
|
||||
for _, town := range townsResp.RegionTowns {
|
||||
if town.Codes == nil {
|
||||
town.Codes = []string{}
|
||||
}
|
||||
if town.CustomCodes == nil {
|
||||
town.CustomCodes = []string{}
|
||||
}
|
||||
townMaps = append(townMaps, maps.Map{
|
||||
"id": town.Id,
|
||||
"name": town.Name,
|
||||
"codes": town.Codes,
|
||||
"customName": town.CustomName,
|
||||
"customCodes": town.CustomCodes,
|
||||
})
|
||||
}
|
||||
this.Data["towns"] = townMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package towns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type ProvinceOptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ProvinceOptionsAction) RunPost(params struct {
|
||||
CountryId int64
|
||||
}) {
|
||||
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{
|
||||
RegionCountryId: params.CountryId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var provinceMaps = []maps.Map{}
|
||||
for _, province := range provincesResp.RegionProvinces {
|
||||
provinceMaps = append(provinceMaps, maps.Map{
|
||||
"id": province.Id,
|
||||
"name": province.DisplayName,
|
||||
})
|
||||
}
|
||||
this.Data["provinces"] = provinceMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package towns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
TownId int64
|
||||
}) {
|
||||
townResp, err := this.RPC().RegionTownRPC().FindRegionTown(this.AdminContext(), &pb.FindRegionTownRequest{RegionTownId: params.TownId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var town = townResp.RegionTown
|
||||
if town == nil {
|
||||
this.NotFound("regionTown", params.TownId)
|
||||
return
|
||||
}
|
||||
if town.Codes == nil {
|
||||
town.Codes = []string{}
|
||||
}
|
||||
if town.CustomCodes == nil {
|
||||
town.CustomCodes = []string{}
|
||||
}
|
||||
this.Data["town"] = maps.Map{
|
||||
"id": town.Id,
|
||||
"name": town.Name,
|
||||
"codes": town.Codes,
|
||||
"customName": town.CustomName,
|
||||
"customCodes": town.CustomCodes,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
TownId int64
|
||||
CustomName string
|
||||
CustomCodes []string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.RegionTown_LogUpdateRegionTownCustom, params.TownId)
|
||||
|
||||
_, err := this.RPC().RegionTownRPC().UpdateRegionTownCustom(this.AdminContext(), &pb.UpdateRegionTownCustomRequest{
|
||||
RegionTownId: params.TownId,
|
||||
CustomName: params.CustomName,
|
||||
CustomCodes: params.CustomCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type UpdatePublicAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePublicAction) RunPost(params struct {
|
||||
ArtifactId int64
|
||||
IsPublic bool
|
||||
}) {
|
||||
if params.IsPublic {
|
||||
defer this.CreateLogInfo(codes.IPLibraryArtifact_LogUseIPLibraryArtifact, params.ArtifactId)
|
||||
} else {
|
||||
defer this.CreateLogInfo(codes.IPLibraryArtifact_LogCancelIPLibraryArtifact, params.ArtifactId)
|
||||
}
|
||||
|
||||
_, err := this.RPC().IPLibraryArtifactRPC().UpdateIPLibraryArtifactIsPublic(this.AdminContext(), &pb.UpdateIPLibraryArtifactIsPublicRequest{
|
||||
IpLibraryArtifactId: params.ArtifactId,
|
||||
IsPublic: params.IsPublic,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package iplibrary
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/sizes"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library/iplibraryutils"
|
||||
iplib "github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UploadAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UploadAction) Init() {
|
||||
this.Nav("", "", "upload")
|
||||
}
|
||||
|
||||
func (this *UploadAction) RunGet(params struct{}) {
|
||||
this.Data["canAccess"] = iplibraryutils.CanAccess()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UploadAction) RunPost(params struct {
|
||||
Name string
|
||||
File *actions.File
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
if len(params.Name) == 0 {
|
||||
this.FailField("name", "请输入IP库名称")
|
||||
return
|
||||
}
|
||||
|
||||
if params.File == nil {
|
||||
this.Fail("请选择要上传的IP库文件")
|
||||
return
|
||||
}
|
||||
|
||||
fp, err := params.File.OriginFile.Open()
|
||||
if err != nil {
|
||||
this.Fail("读取IP库文件失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
_ = fp.Close()
|
||||
}()
|
||||
|
||||
data, err := io.ReadAll(io.LimitReader(fp, 64*sizes.M)) // 最大不超过64M
|
||||
if err != nil {
|
||||
this.Fail("读取IP库文件失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 只支持 MaxMind 格式文件(.mmdb)
|
||||
filename := strings.ToLower(params.File.Filename)
|
||||
if !strings.HasSuffix(filename, ".mmdb") {
|
||||
this.Fail("只支持 MaxMind 格式文件(.mmdb),请上传 GeoLite2-City.mmdb 或 GeoLite2-ASN.mmdb 文件")
|
||||
return
|
||||
}
|
||||
|
||||
// MaxMind 格式文件,保存到 data/iplibrary/ 目录
|
||||
iplibDir := Tea.Root + "/data/iplibrary"
|
||||
err = os.MkdirAll(iplibDir, 0755)
|
||||
if err != nil {
|
||||
this.Fail("创建IP库目录失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 根据文件名判断是 City 还是 ASN
|
||||
var targetPath string
|
||||
if strings.Contains(filename, "city") {
|
||||
targetPath = filepath.Join(iplibDir, "maxmind-city.mmdb")
|
||||
} else if strings.Contains(filename, "asn") {
|
||||
targetPath = filepath.Join(iplibDir, "maxmind-asn.mmdb")
|
||||
} else {
|
||||
this.Fail("MaxMind 文件名必须包含 'city' 或 'asn'")
|
||||
return
|
||||
}
|
||||
|
||||
// 保存文件(使用临时文件原子替换)
|
||||
tmpPath := targetPath + ".tmp"
|
||||
err = os.WriteFile(tmpPath, data, 0644)
|
||||
if err != nil {
|
||||
this.Fail("保存IP库文件失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 原子替换
|
||||
err = os.Rename(tmpPath, targetPath)
|
||||
if err != nil {
|
||||
os.Remove(tmpPath)
|
||||
this.Fail("替换IP库文件失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 通过 RPC 将文件上传到 EdgeAPI
|
||||
_, err = this.RPC().IPLibraryRPC().UploadMaxMindFile(this.AdminContext(), &pb.UploadMaxMindFileRequest{
|
||||
Filename: params.File.Filename,
|
||||
Data: data,
|
||||
})
|
||||
if err != nil {
|
||||
logs.Println("[IP_LIBRARY]upload MaxMind file to EdgeAPI failed: " + err.Error())
|
||||
// 继续执行,不影响本地保存
|
||||
}
|
||||
|
||||
// 创建简单的 Meta
|
||||
meta := &iplib.Meta{
|
||||
Version: 3,
|
||||
Code: "maxmind",
|
||||
Author: "MaxMind",
|
||||
}
|
||||
meta.Init()
|
||||
|
||||
// TODO 检查是否要自动创建省市区
|
||||
|
||||
// 上传IP库文件到数据库
|
||||
fileResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||
Filename: params.File.Filename,
|
||||
Size: int64(len(data)),
|
||||
IsPublic: false,
|
||||
MimeType: "",
|
||||
Type: "ipLibraryArtifact",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var fileId = fileResp.FileId
|
||||
|
||||
var buf = make([]byte, 256*1024)
|
||||
var dataReader = bytes.NewReader(data)
|
||||
for {
|
||||
n, err := dataReader.Read(buf)
|
||||
if n > 0 {
|
||||
_, chunkErr := this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||
FileId: fileId,
|
||||
Data: buf[:n],
|
||||
})
|
||||
if chunkErr != nil {
|
||||
this.Fail("上传文件到数据库失败:" + chunkErr.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 创建IP库信息
|
||||
metaJSON, err := json.Marshal(meta)
|
||||
if err != nil {
|
||||
this.Fail("元数据编码失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().IPLibraryArtifactRPC().CreateIPLibraryArtifact(this.AdminContext(), &pb.CreateIPLibraryArtifactRequest{
|
||||
FileId: fileId,
|
||||
MetaJSON: metaJSON,
|
||||
Name: params.Name,
|
||||
})
|
||||
if err != nil {
|
||||
this.Fail("创建IP库失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 获取所有IP库记录,将其他记录的 isPublic 设为 false,新上传的设为 true
|
||||
artifactsResp, err := this.RPC().IPLibraryArtifactRPC().FindAllIPLibraryArtifacts(this.AdminContext(), &pb.FindAllIPLibraryArtifactsRequest{})
|
||||
if err != nil {
|
||||
// 如果获取列表失败,不影响上传成功,只记录日志
|
||||
logs.Println("[IP_LIBRARY]failed to get all artifacts: " + err.Error())
|
||||
} else {
|
||||
// 将所有其他记录设为未使用
|
||||
for _, artifact := range artifactsResp.IpLibraryArtifacts {
|
||||
if artifact.Id != createResp.IpLibraryArtifactId {
|
||||
if artifact.IsPublic {
|
||||
// 将其他使用中的记录设为未使用
|
||||
_, err = this.RPC().IPLibraryArtifactRPC().UpdateIPLibraryArtifactIsPublic(this.AdminContext(), &pb.UpdateIPLibraryArtifactIsPublicRequest{
|
||||
IpLibraryArtifactId: artifact.Id,
|
||||
IsPublic: false,
|
||||
})
|
||||
if err != nil {
|
||||
logs.Println("[IP_LIBRARY]failed to update artifact " + fmt.Sprintf("%d", artifact.Id) + " isPublic: " + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 将新上传的记录设为使用中
|
||||
_, err = this.RPC().IPLibraryArtifactRPC().UpdateIPLibraryArtifactIsPublic(this.AdminContext(), &pb.UpdateIPLibraryArtifactIsPublicRequest{
|
||||
IpLibraryArtifactId: createResp.IpLibraryArtifactId,
|
||||
IsPublic: true,
|
||||
})
|
||||
if err != nil {
|
||||
logs.Println("[IP_LIBRARY]failed to set new artifact as public: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
Reference in New Issue
Block a user