merge: 合并OMC分支
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/global"
|
||||
@@ -14,13 +15,197 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
UriCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrEvent"
|
||||
UriCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrFile"
|
||||
UriIMSCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrEvent"
|
||||
UriIMSCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrFile"
|
||||
UriSMFCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/smf/objectType/cdrEvent"
|
||||
UriSMFCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/smf/objectType/cdrFile"
|
||||
|
||||
CustomUriCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrEvent"
|
||||
CustomUriCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrFile"
|
||||
CustomUriIMSCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrEvent"
|
||||
CustomUriIMSCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrFile"
|
||||
CustomUriSMFCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrEvent"
|
||||
CustomUriSMFCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrFile"
|
||||
)
|
||||
|
||||
// SMF CDR
|
||||
type CdrSubscriptionID struct {
|
||||
SubscriptionIDType string `json:"subscriptionIDType"`
|
||||
SubscriptionIDData string `json:"subscriptionIDData"`
|
||||
}
|
||||
|
||||
type CdrNetWorkFuctionInfomation struct {
|
||||
NetworkFunctionality string `json:"networkFunctionality"`
|
||||
NetworkFunctionName string `json:"networkFunctionName,omitempty"`
|
||||
NetworkFunctionIPv4Address string `json:"networkFunctionIPv4Address,omitempty"`
|
||||
NetworkFunctionIPv6Address string `json:"networkFunctionIPv6Address,omitempty"`
|
||||
}
|
||||
|
||||
type SMFTrigger string
|
||||
|
||||
const (
|
||||
TimeThresholdReached SMFTrigger = "timeThresholdReached"
|
||||
VolumeThresholdReached SMFTrigger = "volumeThresholdReached"
|
||||
UnitThresholdReached SMFTrigger = "unitThresholdReached"
|
||||
TimeQuotaExhausted SMFTrigger = "timeQuotaExhausted"
|
||||
VolumeQuotaExhausted SMFTrigger = "volumeQuotaExhausted"
|
||||
UnitQuotaExhausted SMFTrigger = "unitQuotaExhausted"
|
||||
ExpiryOfQuotaValidityTime SMFTrigger = "expiryOfQuotaValidityTime"
|
||||
ExpiryOfQuotaHoldingTime SMFTrigger = "expiryOfQuotaHoldingTime"
|
||||
EndOfPDUSession SMFTrigger = "endOfPDUSession"
|
||||
)
|
||||
|
||||
type CdrSMFTrigger struct {
|
||||
SMFTrigger SMFTrigger `json:"sMFTrigger"`
|
||||
}
|
||||
|
||||
type CdrQuotaManagementIndicator string
|
||||
|
||||
// List of QuotaManagementIndicator
|
||||
const (
|
||||
Cdr_QMI_ONLINE_CHARGING CdrQuotaManagementIndicator = "ONLINE_CHARGING"
|
||||
Cdr_QMI_OFFLINE_CHARGING CdrQuotaManagementIndicator = "OFFLINE_CHARGING"
|
||||
Cdr_QMI_QUOTA_MANAGEMENT_SUSPENDED CdrQuotaManagementIndicator = "QUOTA_MANAGEMENT_SUSPENDED"
|
||||
)
|
||||
|
||||
type CdrUsedUnitContainer struct {
|
||||
ServiceIdentifier *int32 `json:"serviceIdentifier,omitempty"`
|
||||
QuotaManagementIndicatorExt CdrQuotaManagementIndicator `json:"quotaManagementIndicatorExt,omitempty"`
|
||||
Triggers []SMFTrigger `json:"triggers,omitempty"`
|
||||
TriggerTimestamp *time.Time `json:"triggerTimestamp,omitempty"`
|
||||
Time *uint32 `json:"time,omitempty"`
|
||||
DataTotalVolume *uint64 `json:"dataTotalVolume,omitempty"`
|
||||
DataVolumeUplink *uint64 `json:"dataVolumeUplink,omitempty"`
|
||||
DataVolumeDownlink *uint64 `json:"dataVolumeDownlink,omitempty"`
|
||||
ServiceSpecificUnits *uint64 `json:"serviceSpecificUnits,omitempty"`
|
||||
EventTimeStamp *time.Time `json:"eventTimeStamp,omitempty"`
|
||||
LocalSequenceNumber int32 `json:"localSequenceNumber"`
|
||||
//PDUContainerInformation *PduContainerInformation `json:"pDUContainerInformation,omitempty"`
|
||||
//NSPAContainerInformation *NspaContainerInformation `json:"nSPAContainerInformation,omitempty"`
|
||||
}
|
||||
|
||||
type CdrMultipleUnitUsage struct {
|
||||
RatingGroup uint32 `json:"ratingGroup" yaml:"ratingGroup" bson:"ratingGroup" mapstructure:"RatingGroup"`
|
||||
UsedUnitContainer []CdrUsedUnitContainer `json:"usedUnitContainer,omitempty" yaml:"usedUnitContainer" bson:"usedUnitContainer" mapstructure:"UsedUnitContainer"`
|
||||
//UPFID string `json:"uPFID,omitempty" yaml:"uPFID" bson:"uPFID" mapstructure:"UPFID"`
|
||||
}
|
||||
|
||||
type CdrSubscriberEquipmentNumber struct {
|
||||
SubscriberEquipmentNumberType string `json:"subscriberEquipmentNumberType"`
|
||||
SubscriberEquipmentNumberData string `json:"subscriberEquipmentNumberData"`
|
||||
}
|
||||
|
||||
type CdrNetworkSliceInstanceID struct {
|
||||
SST int32 `json:"sST"`
|
||||
|
||||
SD string `json:"sD,omitempty"`
|
||||
}
|
||||
|
||||
type CdrPduAddress struct {
|
||||
PDUIPv4Address string `json:"pDUIPv4Address,omitempty"`
|
||||
PDUIPv6AddresswithPrefix string `json:"pDUIPv6AddresswithPrefix,omitempty"`
|
||||
IPV4dynamicAddressFlag bool `json:"iPV4dynamicAddressFlag,omitempty"`
|
||||
IPV6dynamicPrefixFlag bool `json:"iPv6dynamicPrefixFlag,omitempty"`
|
||||
}
|
||||
|
||||
type CdrArp struct {
|
||||
PriorityLevel int32 `json:"priorityLevel"`
|
||||
PreemptionCapability string `json:"preemptionCapability"`
|
||||
PreemptionVulnerability string `json:"preemptionVulnerability"`
|
||||
}
|
||||
|
||||
type CdrAuthorizedQosInformation struct {
|
||||
FiveQi int `json:"fiveQi"`
|
||||
ARP *CdrArp `json:"aRP,omitempty"`
|
||||
PriorityLevel *int32 `json:"priorityLevel,omitempty"`
|
||||
AverWindow *int32 `json:"averWindow,omitempty"`
|
||||
MaxDataBurstVol *int32 `json:"maxDataBurstVol,omitempty"`
|
||||
}
|
||||
|
||||
type CdrSubscribedDefaultQos struct {
|
||||
FiveQi int32 `json:"fiveQi,omitempty"`
|
||||
ARP CdrArp `json:"aRP,omitempty"`
|
||||
PriorityLevel *int32 `json:"priorityLevel,omitempty"`
|
||||
}
|
||||
|
||||
type CdrSessionAmbr struct {
|
||||
Uplink string `json:"uplink"`
|
||||
|
||||
Downlink string `json:"downlink"`
|
||||
}
|
||||
|
||||
type CdrPDUSessionChargingInformation struct {
|
||||
PDUSessionChargingID int32 `json:"pDUSessionChargingID"`
|
||||
UserIdentifier string `json:"userIdentifier,omitempty"` // isdn
|
||||
UserEquipmentInfo *CdrSubscriberEquipmentNumber `json:"userEquipmentInfo,omitempty"` // imei/imeisv
|
||||
//UserLocationInfomation *UserLocation `json:"userLocationinfo,omitempty"`
|
||||
UserRoamerInOut string `json:"userRoamerInOut,omitempty"`
|
||||
PDUSessionId int32 `json:"pDUSessionId"`
|
||||
NetworkSliceInstanceID *CdrNetworkSliceInstanceID `json:"networkSliceInstanceID,omitempty"`
|
||||
//PDUType PduSessionType `json:"pDUType,omitempty"`
|
||||
SSCMode string `json:"sSCMode,omitempty"`
|
||||
DNNID string `json:"dNNID"`
|
||||
SUPIPLMNIdentifier string `json:"sUPIPLMNIdentifier,omitempty"`
|
||||
//ServingNetworkFunctionID *ServingNetworkFunctionId `json:"servingNetworkFunctionID,omitempty"`
|
||||
//RATType RatType `json:"rATType,omitempty"`
|
||||
DataNetworkNameIdentifier string `json:"dataNetworkNameIdentifier,omitempty"`
|
||||
PDUAddress CdrPduAddress `json:"pDUAddress,omitempty"`
|
||||
AuthorizedQoSInformation *CdrAuthorizedQosInformation `json:"authorizedQoSInformation,omitempty"`
|
||||
UETimeZone string `json:"uETimeZone,omitempty"`
|
||||
PDUSessionstartTime *time.Time `json:"pDUSessionstartTime,omitempty"`
|
||||
PDUSessionstopTime *time.Time `json:"pDUSessionstopTime,omitempty"`
|
||||
Diagnostics *int `json:"diagnostics,omitempty"`
|
||||
ChargingCharacteristics string `json:"chargingCharacteristics,omitempty"`
|
||||
ChChSelectionMode string `json:"chChSelectionMode,omitempty"`
|
||||
ThreeGPPPSDataOffStatus string `json:"threeGPPPSDataOffStatus,omitempty"`
|
||||
//RANSecondaryRATUsageReport *RanSecondaryRatUsageReport `json:"rANSecondaryRATUsageReport,omitempty"`
|
||||
SubscribedQoSInformation *CdrSubscribedDefaultQos `json:"subscribedQoSInformation,omitempty"`
|
||||
AuthorizedSessionAMBR *CdrSessionAmbr `json:"authorizedSessionAMBR,omitempty"`
|
||||
SubscribedSessionAMBR *CdrSessionAmbr `json:"subscribedSessionAMBR,omitempty"`
|
||||
ServingCNPLMNID string `json:"servingCNPLMNID,omitempty"`
|
||||
DnnSelectionMode string `json:"dnnSelectionMode,omitempty"`
|
||||
HomeProvidedChargingID int32 `json:"homeProvidedChargingID,omitempty"`
|
||||
|
||||
//MAPDUNon3GPPUserLocationInfo *UserLocation `json:"mAPDUNon3GPPUserLocationInfo,omitempty" yaml:"mAPDUNon3GPPUserLocationInfo" bson:"mAPDUNon3GPPUserLocationInfo" mapstructure:"MAPDUNon3GPPUserLocationInfo"`
|
||||
//PresenceReportingAreaInformation map[string]PresenceInfo `json:"presenceReportingAreaInformation,omitempty" yaml:"presenceReportingAreaInformation" bson:"presenceReportingAreaInformation" mapstructure:"PresenceReportingAreaInformation"`
|
||||
}
|
||||
|
||||
type CauseForRecordClosing string
|
||||
|
||||
const (
|
||||
NormalRelease CauseForRecordClosing = "normalRelease"
|
||||
PartialRecord CauseForRecordClosing = "partialRecord"
|
||||
AbnormalRelease CauseForRecordClosing = "abnormalRelease"
|
||||
CAMELInitCallRelease CauseForRecordClosing = "cAMELInitCallRelease"
|
||||
VolumeLimit CauseForRecordClosing = "volumeLimit"
|
||||
TimeLimit CauseForRecordClosing = "timeLimit"
|
||||
ServingNodeChange CauseForRecordClosing = "servingNodeChange"
|
||||
MaxChangeCond CauseForRecordClosing = "maxChangeCond"
|
||||
ManagementIntervention CauseForRecordClosing = "managementIntervention"
|
||||
IntraSGSNIntersystemChange CauseForRecordClosing = "intraSGSNIntersystemChange"
|
||||
RATChange CauseForRecordClosing = "rATChange"
|
||||
MSTimeZoneChange CauseForRecordClosing = "mSTimeZoneChange"
|
||||
SGSNPLMNIDChange CauseForRecordClosing = "sGSNPLMNIDChange "
|
||||
SGWChange CauseForRecordClosing = "sGWChange"
|
||||
APNAMBRChange CauseForRecordClosing = "aPNAMBRChange"
|
||||
)
|
||||
|
||||
type ChargingRecord struct {
|
||||
RecordType string `json:"recordType"`
|
||||
ChargingID int `json:"chargingID"`
|
||||
RecordingNetworkFunctionID string `json:"recordingNetworkFunctionID"` // UUID
|
||||
SubscriberIdentifier CdrSubscriptionID `json:"subscriberIdentifier,omitempty"`
|
||||
NFunctionConsumerInformation CdrNetWorkFuctionInfomation `json:"nFunctionConsumerInformation"`
|
||||
Triggers []CdrSMFTrigger `json:"triggers,omitempty"`
|
||||
ListOfMultipleUnitUsage []CdrMultipleUnitUsage `json:"listOfMultipleUnitUsage,omitempty"`
|
||||
RecordOpeningTime string `json:"recordOpeningTime"`
|
||||
Duration int `json:"duration"`
|
||||
RecordSequenceNumber int `json:"recordSequenceNumber,omitempty"`
|
||||
CauseForRecClosing CauseForRecordClosing `json:"causeForRecClosing"`
|
||||
Diagnostics *int `json:"diagnostics,omitempty"`
|
||||
LocalRecordSequenceNumber int `json:"localRecordSequenceNumber,omitempty"`
|
||||
PDUSessionChargingInformation CdrPDUSessionChargingInformation `json:"pDUSessionChargingInformation,omitempty"`
|
||||
InvocationTimestamp string `json:"invocationTimestamp,omitempty"`
|
||||
}
|
||||
|
||||
type CDREvent struct {
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
NeName string `json:"neName" xorm:"ne_name"`
|
||||
@@ -29,8 +214,8 @@ type CDREvent struct {
|
||||
CDR map[string]any `json:"CDR" xorm:"cdr_json"`
|
||||
}
|
||||
|
||||
func PostCDREventFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PostCDREventFromNF processing... ")
|
||||
func PostCDREventFromIMS(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PostCDREventFromIMS processing... ")
|
||||
|
||||
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
@@ -49,9 +234,9 @@ func PostCDREventFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
log.Trace("cdrEvent:", cdrEvent)
|
||||
|
||||
affected, err := dborm.XormInsertTableOne("cdr_event", cdrEvent)
|
||||
affected, err := dborm.XormInsertTableOne("cdr_event_ims", cdrEvent)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert cdr_event:", err)
|
||||
log.Error("Failed to insert cdr_event_ims:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
@@ -65,3 +250,36 @@ func PostCDREventFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
func PostCDREventFromSMF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PostCDREventFromSMF processing... ")
|
||||
|
||||
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("Faile to io.ReadAll: ", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
cdrEvent := new(CDREvent)
|
||||
err = json.Unmarshal(body, &cdrEvent)
|
||||
if cdrEvent.NeType == "" || err != nil {
|
||||
log.Error("Failed to Unmarshal cdrEvent:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("cdrEvent:", cdrEvent)
|
||||
|
||||
affected, err := dborm.XormInsertTableOne("cdr_event_smf", cdrEvent)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert cdr_event_smf:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 推送到ws订阅组
|
||||
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_SMF_CDR, cdrEvent)
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/ctx"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
neModel "nms_cxy/src/modules/network_element/model"
|
||||
neService "nms_cxy/src/modules/network_element/service"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -154,21 +156,21 @@ func DeleteLcenseFile(w http.ResponseWriter, r *http.Request) {
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
type MMLRequest struct {
|
||||
MML []string `json:"mml"`
|
||||
}
|
||||
// type MMLRequest struct {
|
||||
// MML []string `json:"mml"`
|
||||
// }
|
||||
|
||||
var TIME_DELAY_AFTER_WRITE time.Duration = 200
|
||||
var TIME_DEAD_LINE time.Duration = 10
|
||||
// var TIME_DELAY_AFTER_WRITE time.Duration = 200
|
||||
// var TIME_DEAD_LINE time.Duration = 10
|
||||
|
||||
func init() {
|
||||
if config.GetYamlConfig().MML.Sleep != 0 {
|
||||
TIME_DELAY_AFTER_WRITE = time.Duration(config.GetYamlConfig().MML.Sleep)
|
||||
}
|
||||
if config.GetYamlConfig().MML.DeadLine != 0 {
|
||||
TIME_DEAD_LINE = time.Duration(config.GetYamlConfig().MML.DeadLine)
|
||||
}
|
||||
}
|
||||
// func init() {
|
||||
// if config.GetYamlConfig().MML.Sleep != 0 {
|
||||
// TIME_DELAY_AFTER_WRITE = time.Duration(config.GetYamlConfig().MML.Sleep)
|
||||
// }
|
||||
// if config.GetYamlConfig().MML.DeadLine != 0 {
|
||||
// TIME_DEAD_LINE = time.Duration(config.GetYamlConfig().MML.DeadLine)
|
||||
// }
|
||||
// }
|
||||
|
||||
func UploadLicenseFileData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("UploadLicenseFileData processing... ")
|
||||
@@ -274,12 +276,13 @@ func UploadLicenseFileData(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
// backup system.ini to system.ini.bak
|
||||
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
||||
cpCmd := fmt.Sprintf("sudo cp -f %s/system.ini %s/system.ini.bak", neLicensePath, neLicensePath)
|
||||
cpCmd := fmt.Sprintf("sudo test -f %s/system.ini && cp -f %s/system.ini %s/system.ini.bak||echo 0",
|
||||
neLicensePath, neLicensePath, neLicensePath)
|
||||
cmd = exec.Command("ssh", sshHost, cpCmd)
|
||||
out, err = cmd.CombinedOutput()
|
||||
log.Debugf("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Error("Faile to execute cp command:", err)
|
||||
log.Errorf("Faile to execute cp command:%v, cmd:%s", err, cpCmd)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
@@ -503,22 +506,54 @@ func UploadLicenseFileData(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
*/
|
||||
neLicense := dborm.NeLicense{
|
||||
|
||||
// neLicense := dborm.NeLicense{
|
||||
// NeType: neTypeUpper,
|
||||
// NeID: neId,
|
||||
// Status: "ACTIVE",
|
||||
// Path: licensePath,
|
||||
// FileName: licenseFileName,
|
||||
// Comment: comment,
|
||||
// }
|
||||
|
||||
// log.Debug("neLicense:", neLicense)
|
||||
// _, err = dborm.XormInsertTableOne("ne_license", neLicense)
|
||||
// if err != nil {
|
||||
// log.Error("Faile to XormInsertTableOne:", err)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// }
|
||||
|
||||
neLicense := neModel.NeLicense{
|
||||
NeType: neTypeUpper,
|
||||
NeID: neId,
|
||||
Status: "ACTIVE",
|
||||
Path: licensePath,
|
||||
FileName: licenseFileName,
|
||||
Comment: comment,
|
||||
NeId: neId,
|
||||
Status: "0",
|
||||
LicensePath: neFilePath,
|
||||
Remark: comment,
|
||||
}
|
||||
|
||||
log.Debug("neLicense:", neLicense)
|
||||
_, err = dborm.XormInsertTableOne("ne_license", neLicense)
|
||||
if err != nil {
|
||||
log.Error("Faile to XormInsertTableOne:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
|
||||
// 检查是否存在授权记录
|
||||
neLicense2 := neService.NewNeLicenseImpl.SelectByNeTypeAndNeID(neTypeUpper, neId)
|
||||
if neLicense2.NeId != neId {
|
||||
// 读取授权码
|
||||
code, _ := neService.NewNeLicenseImpl.ReadLicenseInfo(neLicense)
|
||||
neLicense.ActivationRequestCode = code
|
||||
|
||||
neLicense.CreateBy = ctx.LoginUserToUserName(r)
|
||||
insertId := neService.NewNeLicenseImpl.Insert(neLicense)
|
||||
if insertId != "" {
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
return
|
||||
}
|
||||
|
||||
} else {
|
||||
neLicense2.UpdateBy = ctx.LoginUserToUserName(r)
|
||||
upRows := neService.NewNeLicenseImpl.Update(neLicense2)
|
||||
if upRows > 0 {
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
}
|
||||
|
||||
@@ -142,7 +142,8 @@ func PostNeInfo(w http.ResponseWriter, r *http.Request) {
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
neInfo.UpdateTime = time.Now().Format(time.DateTime)
|
||||
//neInfo.UpdateTime = time.Now().Format(time.DateTime)
|
||||
neInfo.UpdateTime = time.Now()
|
||||
log.Debug("NE info:", neInfo)
|
||||
|
||||
//if !config.GetYamlConfig().OMC.Chk2Ne {
|
||||
@@ -166,7 +167,7 @@ func PostNeInfo(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
hostUri := global.CombineHostUri(neInfo.Ip, neInfo.Port)
|
||||
//hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
apiUri := fmt.Sprintf("%s/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig", config.DefaultUriPrefix, strings.ToLower(neInfo.NeType))
|
||||
apiUri := fmt.Sprintf("%s/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig?ne_id=%s", config.DefaultUriPrefix, strings.ToLower(neInfo.NeType), neInfo.NeId)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, apiUri)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
@@ -252,7 +253,7 @@ func PutNeInfo(w http.ResponseWriter, r *http.Request) {
|
||||
neInfo := new(dborm.NeInfo)
|
||||
_ = json.Unmarshal(body, neInfo)
|
||||
neInfo.NeType = strings.ToUpper(neType)
|
||||
neInfo.UpdateTime = time.Now().Format(time.DateTime)
|
||||
neInfo.UpdateTime = time.Now()
|
||||
log.Debug("NE info:", neInfo)
|
||||
|
||||
//if !config.GetYamlConfig().OMC.Chk2Ne {
|
||||
@@ -276,7 +277,7 @@ func PutNeInfo(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
hostUri := global.CombineHostUri(neInfo.Ip, neInfo.Port)
|
||||
//hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
apiUri := fmt.Sprintf("%s/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig", config.DefaultUriPrefix, neTypeLower)
|
||||
apiUri := fmt.Sprintf("%s/systemManagement/v1/elementType/%s/objectType/config/omcNeConfig?ne_id=%s", config.DefaultUriPrefix, neTypeLower, neInfo.NeId)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, apiUri)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
@@ -858,15 +859,20 @@ func PostNeServiceAction(w http.ResponseWriter, r *http.Request) {
|
||||
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
||||
switch neTypeLower {
|
||||
case "omc":
|
||||
actionCmd := fmt.Sprintf("sudo %s/bin/omcsvc.sh %s", config.GetYamlConfig().NE.OmcDir, action)
|
||||
cmd := exec.Command("ssh", sshHost, actionCmd)
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Debugf("Exec output: %v", string(out))
|
||||
if err != nil {
|
||||
log.Errorf("Faile to execute ssh %s omc:%v", action, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// send 204 to fe firstly
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
//actionCmd := fmt.Sprintf("sudo %s/bin/omcsvc.sh %s", config.GetYamlConfig().NE.OmcDir, action)
|
||||
actionCmd := fmt.Sprintf("sudo systemctl %s restagent", action)
|
||||
go RunSSHCmd(sshHost, actionCmd)
|
||||
return
|
||||
}
|
||||
// cmd := exec.Command("ssh", sshHost, actionCmd)
|
||||
// out, err := cmd.CombinedOutput()
|
||||
// log.Debugf("Exec output: %v", string(out))
|
||||
// if err != nil {
|
||||
// log.Errorf("Faile to execute ssh %s omc:%v", action, err)
|
||||
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||
// return
|
||||
// }
|
||||
case "ims":
|
||||
switch action {
|
||||
case "start", "stop":
|
||||
|
||||
@@ -3,7 +3,7 @@ package cm
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/ctx"
|
||||
"nms_cxy/lib/global"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/lib/services"
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
neService "nms_cxy/src/modules/network_element/service"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
@@ -41,7 +42,7 @@ func GetParamConfigFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
neInfo := neService.NewNeInfoImpl.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
var response services.DataResponse
|
||||
if neInfo.NeId == neId {
|
||||
if neInfo.NeId == neId && neInfo.NeId != "" {
|
||||
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
@@ -77,7 +78,7 @@ func PostParamConfigToNF(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
neInfo := neService.NewNeInfoImpl.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
if neInfo.NeId != neId {
|
||||
if neInfo.NeId != neId || neInfo.NeId == "" {
|
||||
log.Error("neId is empty")
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
@@ -129,7 +130,7 @@ func PutParamConfigToNF(w http.ResponseWriter, r *http.Request) {
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
neInfo := neService.NewNeInfoImpl.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
if neInfo.NeId != neId {
|
||||
if neInfo.NeId != neId || neInfo.NeId == "" {
|
||||
log.Error("neId is empty")
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
@@ -182,7 +183,7 @@ func DeleteParamConfigToNF(w http.ResponseWriter, r *http.Request) {
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
neInfo := neService.NewNeInfoImpl.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
if neInfo.NeId != neId {
|
||||
if neInfo.NeId != neId || neInfo.NeId == "" {
|
||||
log.Error("neId is empty")
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
|
||||
@@ -20,9 +20,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
SoftwareStatusUploaded = "Uploaded"
|
||||
SoftwareStatusInactive = "Inactive"
|
||||
SoftwareStatusActive = "Active"
|
||||
SoftwareStatusUploaded = "3"
|
||||
SoftwareStatusInactive = "3"
|
||||
SoftwareStatusActive = "1"
|
||||
DigestsSignOkString = "digests signatures OK"
|
||||
SoftwareVerifiedOk = "Verified OK"
|
||||
)
|
||||
@@ -213,6 +213,17 @@ func UploadSoftwareMultiFile(w http.ResponseWriter, r *http.Request) {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
sql := fmt.Sprintf("select * from ne_software where ne_type='%s' and version='%s'", neTypeUpper, version)
|
||||
neSoftwareInfo, _ := dborm.XormGetDataBySQL(sql)
|
||||
if len(*neSoftwareInfo) >= 1 {
|
||||
services.ResponseWithJson(w, 200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "Software version already exists",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
md5Param := services.GetUriParamString(r, "md5Sum", ",", false, false)
|
||||
|
||||
softwarePath := fmt.Sprintf("%s/%s", config.GetYamlConfig().OMC.Software, neTypeLower)
|
||||
@@ -314,7 +325,7 @@ func UploadSoftwareMultiFile(w http.ResponseWriter, r *http.Request) {
|
||||
result := verify_signature(config.GetYamlConfig().Auth.PublicKey, cmsFilePath, rpmFilePath)
|
||||
log.Debug("result:", result.String())
|
||||
if !strings.Contains(result.String(), SoftwareVerifiedOk) {
|
||||
err := global.ErrCMNotMatchSignFile
|
||||
err = global.ErrCMNotMatchSignFile
|
||||
log.Error(err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
@@ -408,7 +419,7 @@ func DownloadSoftwareFile(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
fileName := (*neSoftware)[0]["file_name"]
|
||||
fileName := (*neSoftware)[0]["name"]
|
||||
path := (*neSoftware)[0]["path"]
|
||||
md5Sum := (*neSoftware)[0]["md5_sum"]
|
||||
|
||||
@@ -462,7 +473,7 @@ func DeleteSoftwareFile(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
fileName := (*neSoftware)[0]["file_name"]
|
||||
fileName := (*neSoftware)[0]["name"]
|
||||
path := (*neSoftware)[0]["path"]
|
||||
filePath := fmt.Sprintf("%s/%s", path, fileName)
|
||||
err = os.Remove(filePath)
|
||||
@@ -549,7 +560,7 @@ func DistributeSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
fileName := (*neSoftware)[0]["file_name"]
|
||||
fileName := (*neSoftware)[0]["name"]
|
||||
path := (*neSoftware)[0]["path"]
|
||||
srcFile := fmt.Sprintf("%s/%s", path, fileName)
|
||||
|
||||
@@ -600,7 +611,7 @@ func DistributeSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
||||
Version: (*neSoftware)[0]["version"],
|
||||
FilePath: fmt.Sprintf("%s/software/%s/%s", config.GetYamlConfig().NE.OmcDir, neTypeLower, fileName),
|
||||
PreVersion: (*neVersion)[0]["version"],
|
||||
PreFile: (*neVersion)[0]["file_path"],
|
||||
PreFile: (*neVersion)[0]["path"],
|
||||
Status: SoftwareStatusInactive,
|
||||
}
|
||||
|
||||
@@ -684,21 +695,29 @@ func ActiveSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Trace("neVersion:", neVersion)
|
||||
|
||||
if !config.GetYamlConfig().OMC.TestMode {
|
||||
filePath := (*neVersion)[0]["file_path"]
|
||||
filePath := (*neVersion)[0]["path"]
|
||||
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
||||
srcFile := fmt.Sprintf("%s/actpkg.sh", config.GetYamlConfig().OMC.BinDir)
|
||||
|
||||
runCmd := fmt.Sprintf("sudo rm -f %s/actpkg.sh", config.GetYamlConfig().NE.ScpDir)
|
||||
err = RunSSHCmd(sshHost, runCmd)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to run cmd: %s", runCmd)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
srcFile := fmt.Sprintf("%s/actpkg.sh", config.GetYamlConfig().OMC.BinDir)
|
||||
scpDir := fmt.Sprintf("%s@%s:%s", config.GetYamlConfig().NE.User,
|
||||
neInfo.Ip, config.GetYamlConfig().NE.ScpDir)
|
||||
cmd := exec.Command("scp", "-r", srcFile, scpDir)
|
||||
_, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Errorf("Faile to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
|
||||
log.Errorf("Failed to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
runCmd := fmt.Sprintf("sudo %s/actpkg.sh '%s' %s",
|
||||
runCmd = fmt.Sprintf("sudo %s/actpkg.sh '%s' %s",
|
||||
config.GetYamlConfig().NE.ScpDir, filePath, neTypeUpper)
|
||||
if neTypeLower == "omc" {
|
||||
idNeVersion, _ := strconv.Atoi((*neVersion)[0]["id"])
|
||||
@@ -886,6 +905,14 @@ func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if !config.GetYamlConfig().OMC.TestMode {
|
||||
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
||||
runCmd := fmt.Sprintf("sudo rm -f %s/rbkpkg.sh", config.GetYamlConfig().NE.ScpDir)
|
||||
err = RunSSHCmd(sshHost, runCmd)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to run cmd: %s", runCmd)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
srcFile := fmt.Sprintf("%s/rbkpkg.sh", config.GetYamlConfig().OMC.BinDir)
|
||||
|
||||
scpDir := fmt.Sprintf("%s@%s:%s", config.GetYamlConfig().NE.User,
|
||||
@@ -898,7 +925,7 @@ func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
runCmd := fmt.Sprintf("sudo %s/rbkpkg.sh '%s' %s",
|
||||
runCmd = fmt.Sprintf("sudo %s/rbkpkg.sh '%s' %s",
|
||||
config.GetYamlConfig().NE.ScpDir, filePath, neTypeUpper)
|
||||
if neTypeLower == "omc" {
|
||||
idNeVersion, _ := strconv.Atoi((*neVersion)[0]["id"])
|
||||
@@ -908,7 +935,7 @@ func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
||||
PreVersion: "-",
|
||||
PreFile: "-",
|
||||
NewVersion: (*neVersion)[0]["version"],
|
||||
NewFile: (*neVersion)[0]["file_path"],
|
||||
NewFile: (*neVersion)[0]["path"],
|
||||
Status: SoftwareStatusActive,
|
||||
}
|
||||
|
||||
@@ -919,7 +946,7 @@ func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
RunSSHCmd(sshHost, runCmd)
|
||||
go RunSSHCmd(sshHost, runCmd)
|
||||
return
|
||||
}
|
||||
err = RunSSHCmd(sshHost, runCmd)
|
||||
@@ -1010,7 +1037,7 @@ func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
||||
PreVersion: "-",
|
||||
PreFile: "-",
|
||||
NewVersion: (*neVersion)[0]["version"],
|
||||
NewFile: (*neVersion)[0]["file_path"],
|
||||
NewFile: (*neVersion)[0]["path"],
|
||||
Status: SoftwareStatusActive,
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/ctx"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/global"
|
||||
"nms_cxy/lib/log"
|
||||
@@ -77,18 +77,20 @@ type DatabaseClient struct {
|
||||
|
||||
var DbClient DatabaseClient
|
||||
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error {
|
||||
// DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
// dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName, dbParam)
|
||||
DbClient.dbType = dbType
|
||||
DbClient.dbConnMaxLifetime = 0
|
||||
DbClient.dbMaxIdleConns = 0
|
||||
DbClient.dbMaxOpenConns = 0
|
||||
|
||||
if log.GetLevel() == log.LOG_TRACE {
|
||||
DbClient.IsShowSQL = true
|
||||
}
|
||||
log.Debugf("dbType:%s dbUrl:%s:******@tcp(%s:%s)/%s??charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbType, dbUser, dbHost, dbPort, dbName)
|
||||
log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl)
|
||||
|
||||
var err error
|
||||
DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
|
||||
@@ -99,6 +101,8 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
|
||||
DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
|
||||
DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
|
||||
DbClient.XEngine.DatabaseTZ = time.Local // 必须
|
||||
DbClient.XEngine.TZLocation = time.Local // 必须
|
||||
if DbClient.IsShowSQL {
|
||||
//DbClient.XEngine.SetLogger(&log.Elogger)
|
||||
DbClient.XEngine.ShowSQL(true)
|
||||
@@ -188,13 +192,13 @@ func ExtDatabaseExecSQL(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseExecSQL processing... ")
|
||||
|
||||
var sql []string
|
||||
var err error
|
||||
// var err error
|
||||
|
||||
_, err = services.CheckExtValidRequest(w, r)
|
||||
if err != nil {
|
||||
log.Error("Request error:", err)
|
||||
return
|
||||
}
|
||||
// _, err = services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
//vars := mux.Vars(r)
|
||||
//tblName := vars["objectTypeValue"]
|
||||
@@ -249,11 +253,11 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseGetData processing... ")
|
||||
|
||||
var sql []string
|
||||
token, err := services.CheckExtValidRequest(w, r)
|
||||
if err != nil {
|
||||
log.Error("Request error:", err)
|
||||
return
|
||||
}
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
pack := "dbrest"
|
||||
vars := mux.Vars(r)
|
||||
@@ -261,7 +265,7 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
dbname := vars["elementTypeValue"]
|
||||
tbname := vars["objectTypeValue"]
|
||||
|
||||
log.Debugf("token:%s, method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", token, r.Method, module, dbname, tbname, pack)
|
||||
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
@@ -295,12 +299,11 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
for i, s := range sql {
|
||||
log.Tracef("SQL[%d]: %s", i, sql[i])
|
||||
|
||||
rows := make([]map[string]interface{}, 0)
|
||||
mapRows := make(map[string]interface{})
|
||||
|
||||
if s != "" {
|
||||
// err = XEngine.SQL(s).Find(&rows)
|
||||
if IsQuerySQL(s) == false {
|
||||
if !IsQuerySQL(s) {
|
||||
services.ResponseNotAcceptable406QuerySQLError(w)
|
||||
return
|
||||
}
|
||||
@@ -310,7 +313,7 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
querySQL = querySQL + " " + ls
|
||||
}
|
||||
log.Debug("querySQL:", querySQL)
|
||||
rows, err = DbClient.XEngine.QueryInterface(querySQL)
|
||||
rows, err := DbClient.XEngine.QueryInterface(querySQL)
|
||||
if err != nil {
|
||||
log.Error("SQL failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
@@ -332,11 +335,11 @@ func ExtDatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
func ExtDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseInsertData processing... ")
|
||||
|
||||
token, err := services.CheckExtValidRequest(w, r)
|
||||
if err != nil {
|
||||
log.Error("Request error:", err)
|
||||
return
|
||||
}
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
|
||||
if err != nil {
|
||||
@@ -351,7 +354,7 @@ func ExtDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
|
||||
tbname := vars["objectTypeValue"]
|
||||
pack := "dbrest"
|
||||
|
||||
log.Debugf("token:%s, method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", token, r.Method, module, dbname, tbname, pack)
|
||||
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
@@ -396,11 +399,11 @@ func ExtDatabaseInsertData(w http.ResponseWriter, r *http.Request) {
|
||||
func ExtDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseUpdateData processing... ")
|
||||
|
||||
token, err := services.CheckExtValidRequest(w, r)
|
||||
if err != nil {
|
||||
log.Error("Request error:", err)
|
||||
return
|
||||
}
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
module := ""
|
||||
@@ -408,7 +411,7 @@ func ExtDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
|
||||
tbname := vars["objectTypeValue"]
|
||||
pack := "dbrest"
|
||||
|
||||
log.Debugf("token:%s, method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", token, r.Method, module, dbname, tbname, pack)
|
||||
log.Debugf("method:%s, module:%s, dbname:%s, tbname:%s, pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
@@ -460,11 +463,11 @@ func ExtDatabaseUpdateData(w http.ResponseWriter, r *http.Request) {
|
||||
func ExtDatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseDeleteData processing... ")
|
||||
|
||||
token, err := services.CheckExtValidRequest(w, r)
|
||||
if err != nil {
|
||||
log.Error("Request error:", err)
|
||||
return
|
||||
}
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
module := ""
|
||||
@@ -472,7 +475,7 @@ func ExtDatabaseDeleteData(w http.ResponseWriter, r *http.Request) {
|
||||
tbname := vars["objectTypeValue"]
|
||||
pack := "dbreset"
|
||||
|
||||
log.Debugf("token:%s, method:%s, module:%, dbname:%s, tbname:%s pack:%s", token, r.Method, module, dbname, tbname, pack)
|
||||
log.Debugf("method:%s, module:%, dbname:%s, tbname:%s pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
@@ -548,7 +551,7 @@ func DatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if s != "" {
|
||||
// err = XEngine.SQL(s).Find(&rows)
|
||||
if IsQuerySQL(s) == false {
|
||||
if !IsQuerySQL(s) {
|
||||
services.ResponseNotAcceptable406QuerySQLError(w)
|
||||
return
|
||||
}
|
||||
@@ -560,8 +563,8 @@ func DatabaseGetData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("querySQL:", querySQL)
|
||||
rows, err = DbClient.XEngine.QueryInterface(querySQL)
|
||||
if err != nil {
|
||||
log.Error("SQL failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
log.Error("QueryInterface failed:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
tableName := GetTableName(s)
|
||||
|
||||
@@ -2,27 +2,36 @@ package event
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/ctx"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/global"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
wsService "nms_cxy/src/modules/ws/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var (
|
||||
UriUEEvent = "/upload-ue/v1/:eventType"
|
||||
// 走Gin
|
||||
UriUEEventAMF = "/upload-ue/v1/:eventType"
|
||||
// 走Mux
|
||||
UriUEEvent = config.DefaultUriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
|
||||
CustomUriUEEvent = config.UriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
|
||||
)
|
||||
|
||||
type UEEvent struct {
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
NeName string `json:"neName" xorm:"ne_name"`
|
||||
RmUID string `json:"rmUID" xorm:"rm_uid"`
|
||||
Timestamp int `json:"timestamp" xorm:"timestamp"`
|
||||
Timestamp int64 `json:"timestamp" xorm:"timestamp"`
|
||||
EventType string `json:"eventType" xorm:"event_type"`
|
||||
EventJson map[string]any `json:"eventJSON" xorm:"event_json"`
|
||||
}
|
||||
@@ -52,13 +61,13 @@ func PostUEEventFromAMF(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
ueEvent.NeType = "AMF"
|
||||
ueEvent.Timestamp = int(time.Now().Unix())
|
||||
ueEvent.Timestamp = time.Now().Unix()
|
||||
ueEvent.EventType = eventType
|
||||
log.Trace("ueEvent:", ueEvent)
|
||||
log.Trace("ueEvent AMF:", ueEvent)
|
||||
|
||||
affected, err := dborm.XormInsertTableOne("ue_event", ueEvent)
|
||||
affected, err := dborm.XormInsertTableOne("ue_event_amf", ueEvent)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert ue_event:", err)
|
||||
log.Error("Failed to insert ue_event_amf:", err)
|
||||
services.ResponseInternalServerError500ProcessError(c.Writer, err)
|
||||
return
|
||||
}
|
||||
@@ -68,3 +77,30 @@ func PostUEEventFromAMF(c *gin.Context) {
|
||||
|
||||
services.ResponseStatusOK204NoContent(c.Writer)
|
||||
}
|
||||
|
||||
func PostUEEvent(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PostUEEvent processing... ")
|
||||
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
var ueEvent UEEvent
|
||||
if err := ctx.ShouldBindJSON(r, &ueEvent); err != nil {
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
ueEvent.NeType = strings.ToUpper(neType)
|
||||
tableName := fmt.Sprintf("ue_event_%s", strings.ToLower(neType))
|
||||
affected, err := dborm.XormInsertTableOne(tableName, ueEvent)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert "+tableName, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 推送到ws订阅组
|
||||
if ueEvent.NeType == "MME" {
|
||||
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_MME_UE, ueEvent)
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/ctx"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/file"
|
||||
"nms_cxy/lib/log"
|
||||
|
||||
@@ -15,9 +15,6 @@ import (
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
"nms_cxy/src/framework/utils/date"
|
||||
neDataModel "nms_cxy/src/modules/network_data/model"
|
||||
nmsCXYService "nms_cxy/src/modules/nms_cxy/service"
|
||||
|
||||
"xorm.io/xorm"
|
||||
|
||||
@@ -155,9 +152,9 @@ type DatabaseClient struct {
|
||||
|
||||
var DbClient DatabaseClient
|
||||
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName, dbParam)
|
||||
DbClient.dbType = dbType
|
||||
DbClient.dbConnMaxLifetime = 0
|
||||
DbClient.dbMaxIdleConns = 0
|
||||
@@ -165,8 +162,7 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
if log.GetLevel() == log.LOG_TRACE {
|
||||
DbClient.IsShowSQL = true
|
||||
}
|
||||
log.Debugf("dbType:%s dbUrl:%s:******@tcp(%s:%s)/%s??charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbType, dbUser, dbHost, dbPort, dbName)
|
||||
log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl)
|
||||
|
||||
var err error
|
||||
DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
|
||||
@@ -177,6 +173,8 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
|
||||
DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
|
||||
DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
|
||||
DbClient.XEngine.DatabaseTZ = time.Local // 必须
|
||||
DbClient.XEngine.TZLocation = time.Local // 必须
|
||||
if DbClient.IsShowSQL {
|
||||
DbClient.XEngine.ShowSQL(true)
|
||||
}
|
||||
@@ -287,9 +285,6 @@ func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
continue
|
||||
}
|
||||
|
||||
//
|
||||
pushKafka(alarmData)
|
||||
} else {
|
||||
affected, err := session.Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId).
|
||||
Cols("alarm_status", "clear_type", "clear_time").
|
||||
@@ -299,9 +294,6 @@ func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
continue
|
||||
}
|
||||
|
||||
//
|
||||
pushKafka(alarmData)
|
||||
}
|
||||
log.Trace("alarmData:", alarmData)
|
||||
var currentSeq string
|
||||
@@ -444,12 +436,21 @@ func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
SetAlarmAckInfo(valueJson, &alarmData)
|
||||
}
|
||||
log.Debug("alarmData:", alarmData)
|
||||
if alarmData.OrigSeverity == "Event" && config.GetYamlConfig().Alarm.SplitEventAlarm {
|
||||
affected, err := xEngine.Table("alarm_event").InsertOne(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm_event:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
affected, err := session.Insert(alarmData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm data:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
continue
|
||||
}
|
||||
}
|
||||
alarmLog := new(AlarmLog)
|
||||
alarmLog.NeType = alarmData.NeType
|
||||
alarmLog.NeId = alarmData.NeId
|
||||
@@ -460,21 +461,18 @@ func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
alarmLog.EventTime = eventTime
|
||||
log.Trace("alarmLog:", alarmLog)
|
||||
|
||||
affected, err = session.Insert(alarmLog)
|
||||
affected, err := session.Insert(alarmLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert alarm_log:", err)
|
||||
}
|
||||
session.Commit()
|
||||
|
||||
//
|
||||
pushKafka(alarmData)
|
||||
}
|
||||
if config.GetYamlConfig().Alarm.ForwardAlarm {
|
||||
if err = AlarmEmailForward(&alarmData); err != nil {
|
||||
log.Error("Failed to AlarmEmailForward:", err)
|
||||
}
|
||||
if err = AlarmForwardBySMSC(&alarmData); err != nil {
|
||||
log.Error("Failed to AlarmForwardBySMSC:", err)
|
||||
if err = AlarmSMSForward(&alarmData); err != nil {
|
||||
log.Error("Failed to AlarmSMSForward:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -482,25 +480,26 @@ func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
|
||||
// pushKafka 告警推送kafka
|
||||
func pushKafka(alarmData Alarm) {
|
||||
neAlarm := neDataModel.Alarm{
|
||||
AlarmSeq: fmt.Sprint(alarmData.AlarmSeq),
|
||||
AlarmTitle: alarmData.AlarmTitle,
|
||||
AlarmStatus: fmt.Sprint(alarmData.AlarmStatus),
|
||||
AlarmType: alarmData.AlarmType,
|
||||
OrigSeverity: alarmData.OrigSeverity,
|
||||
EventTime: date.ParseStrToDate(alarmData.EventTime, date.YYYY_MM_DD_HH_MM_SS),
|
||||
ID: alarmData.AlarmId,
|
||||
AlarmCode: fmt.Sprint(alarmData.AlarmCode),
|
||||
SpecificProblem: alarmData.SpecificProblem,
|
||||
ObjectUid: alarmData.ObjectUid,
|
||||
NeName: alarmData.NeName,
|
||||
AlarmId: alarmData.ObjectUid,
|
||||
ObjectName: alarmData.ObjectName,
|
||||
AddInfo: alarmData.AddInfo,
|
||||
}
|
||||
nmsCXYService.NewAlarmImpl.KafkaPush(neAlarm)
|
||||
type AlarmEvent struct {
|
||||
AlarmSeq int `json:"alarmSeq"`
|
||||
AlarmId string `json:"alarmId" xorm:"alarm_id"`
|
||||
NeId string `json:"neId"`
|
||||
AlarmCode int `json:"alarmCode"`
|
||||
AlarmTitle string `json:"alarmTitle"`
|
||||
EventTime string `json:"eventTime"`
|
||||
AlarmType string `json:"alarmType"`
|
||||
OrigSeverity string `json:"origSeverity"`
|
||||
PVFlag string `json:"pvFlag" xorm:"pv_flag"`
|
||||
NeName string `json:"neName"`
|
||||
NeType string `json:"neType"`
|
||||
ObjectUid string `json:"objectUid" xorm:"object_uid"`
|
||||
ObjectName string `json:"objectName" xorm:"object_name"`
|
||||
ObjectType string `json:"objectType" xorm:"object_type"`
|
||||
LocationInfo string `json:"locationInfo"`
|
||||
Province string `json:"province"`
|
||||
SpecificProblem string `json:"specificProblem"`
|
||||
SpecificProblemID string `json:"specificProblemID" xorm:"specific_problem_id"`
|
||||
AddInfo string `json:"addInfo"`
|
||||
}
|
||||
|
||||
// process alarm get from NFs
|
||||
@@ -768,8 +767,8 @@ func GetAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
if err = AlarmEmailForward(&alarmData); err != nil {
|
||||
log.Error("Failed to AlarmEmailForward:", err)
|
||||
}
|
||||
if err = AlarmForwardBySMSC(&alarmData); err != nil {
|
||||
log.Error("Failed to AlarmForwardBySMSC:", err)
|
||||
if err = AlarmSMSForward(&alarmData); err != nil {
|
||||
log.Error("Failed to AlarmSMSForward:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/dborm"
|
||||
@@ -16,7 +17,24 @@ import (
|
||||
"github.com/linxGnu/gosmpp/pdu"
|
||||
)
|
||||
|
||||
func AlarmForwardBySMS(alarmData *Alarm) error {
|
||||
func AlarmSMSForward(alarmData *Alarm) error {
|
||||
switch config.GetYamlConfig().Alarm.SMProxy {
|
||||
case "sms":
|
||||
users, err := AlarmForwardBySMS(alarmData)
|
||||
writeLog(alarmData, users, "SMS", err)
|
||||
return err
|
||||
case "smsc":
|
||||
users, err := AlarmForwardBySMPP(alarmData)
|
||||
writeLog(alarmData, users, "SMS", err)
|
||||
return err
|
||||
default:
|
||||
users, err := AlarmForwardBySMPP(alarmData)
|
||||
writeLog(alarmData, users, "SMS", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func AlarmForwardBySMS(alarmData *Alarm) (string, error) {
|
||||
log.Info("AlarmForwardBySMS processing... ")
|
||||
|
||||
SMSFforwardconfig := config.GetYamlConfig().Alarm.SMS
|
||||
@@ -30,17 +48,17 @@ func AlarmForwardBySMS(alarmData *Alarm) error {
|
||||
toUsers, err := dborm.XormGetAlarmForward("SMS")
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetAlarmForward:", err)
|
||||
return err
|
||||
return "", err
|
||||
} else if toUsers == nil {
|
||||
err := errors.New("not found forward phone number")
|
||||
log.Error(err)
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
userList := strings.Join(*toUsers, ",")
|
||||
|
||||
for _, toUser := range *toUsers {
|
||||
// 短信相关参数
|
||||
params := url.Values{}
|
||||
params.Set("PhoneNumbers", toUser)
|
||||
params.Set("PhoneNumbers", userList)
|
||||
params.Set("SignName", SMSFforwardconfig.SignName)
|
||||
params.Set("TemplateCode", SMSFforwardconfig.TemplateCode)
|
||||
params.Set("TemplateParam", `{"message":"alarm"}`)
|
||||
@@ -52,69 +70,52 @@ func AlarmForwardBySMS(alarmData *Alarm) error {
|
||||
req, err := http.NewRequest("GET", reqURL, nil)
|
||||
if err != nil {
|
||||
log.Error("Failed to create request:", err)
|
||||
return err
|
||||
return userList, err
|
||||
}
|
||||
|
||||
// 添加请求头部
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Authorization", "APPCODE "+accessKeySecret)
|
||||
|
||||
forwardLog := &dborm.AlarmForwardLog{
|
||||
NeType: alarmData.NeType,
|
||||
NeID: alarmData.NeId,
|
||||
AlarmID: alarmData.AlarmId,
|
||||
AlarmTitle: alarmData.AlarmTitle,
|
||||
AlarmSeq: alarmData.AlarmSeq,
|
||||
EventTime: alarmData.EventTime,
|
||||
ToUser: toUser,
|
||||
}
|
||||
// 发送请求
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
operResult := fmt.Sprintf("Failed to send request:%v", err)
|
||||
log.Error(operResult)
|
||||
forwardLog.OperResult = operResult
|
||||
affected, err := dborm.XormInsertAlarmForwardLog(forwardLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert data:", err)
|
||||
}
|
||||
continue
|
||||
log.Error("Failed to send request:%v", err)
|
||||
return userList, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 解析响应
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
operResult := "SMS sent successfully!"
|
||||
log.Info(operResult)
|
||||
forwardLog.OperResult = operResult
|
||||
affected, err := dborm.XormInsertAlarmForwardLog(forwardLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert data:", err)
|
||||
continue
|
||||
switch resp.StatusCode {
|
||||
case http.StatusOK, http.StatusAccepted, http.StatusNoContent, http.StatusCreated:
|
||||
return userList, nil
|
||||
default:
|
||||
err := fmt.Errorf("Failed to send SMS: %s(Code=%d)", resp.Status, resp.StatusCode)
|
||||
log.Error(err)
|
||||
return userList, err
|
||||
}
|
||||
} else {
|
||||
operResult := fmt.Sprintf("Failed to send SMS, StatusCode=%d", resp.StatusCode)
|
||||
log.Error(operResult)
|
||||
forwardLog.OperResult = operResult
|
||||
affected, err := dborm.XormInsertAlarmForwardLog(forwardLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert data:", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func AlarmForwardBySMPP(alarmData *Alarm) error {
|
||||
func AlarmForwardBySMPP(alarmData *Alarm) (string, error) {
|
||||
log.Info("AlarmForwardBySMPP processing... ")
|
||||
|
||||
toUsers, err := dborm.XormGetAlarmForward("SMS")
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetAlarmForward:", err)
|
||||
return "", err
|
||||
} else if toUsers == nil {
|
||||
err := errors.New("not found forward phone number")
|
||||
log.Error(err)
|
||||
return "", err
|
||||
}
|
||||
userList := strings.Join(*toUsers, ",")
|
||||
|
||||
auth := gosmpp.Auth{
|
||||
SMSC: config.GetYamlConfig().Alarm.SMSC.Addr,
|
||||
SystemID: config.GetYamlConfig().Alarm.SMSC.UserName,
|
||||
SystemID: config.GetYamlConfig().Alarm.SMSC.SystemID,
|
||||
Password: config.GetYamlConfig().Alarm.SMSC.Password,
|
||||
SystemType: "",
|
||||
SystemType: config.GetYamlConfig().Alarm.SMSC.SystemType,
|
||||
}
|
||||
|
||||
// conn, err := gosmpp.NonTLSDialer(auth.SMSC)
|
||||
@@ -142,24 +143,34 @@ func AlarmForwardBySMPP(alarmData *Alarm) error {
|
||||
},
|
||||
}, -1)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
log.Error("Failed to create SMPP new session:", err)
|
||||
return userList, err
|
||||
}
|
||||
defer func() {
|
||||
_ = trans.Close()
|
||||
}()
|
||||
|
||||
toUsers, err := dborm.XormGetAlarmForward("SMS")
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetAlarmForward:", err)
|
||||
return err
|
||||
} else if toUsers == nil {
|
||||
err := errors.New("not found forward phone number")
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
// sending SMS(s)
|
||||
for _, toUser := range *toUsers {
|
||||
// var results []string
|
||||
// for _, toUser := range *toUsers {
|
||||
message := "Alarm Notification: " + alarmData.AlarmTitle + " from " + alarmData.NeType + " " + alarmData.NeId + " at " + alarmData.EventTime
|
||||
if err = trans.Transceiver().Submit(newSubmitSM(userList, message)); err != nil {
|
||||
// result := fmt.Sprintf("Failed to submit %s hort message:%s", toUser, err.Error())
|
||||
// results = append(results, result)
|
||||
log.Error("Failed to submit hort message:", err)
|
||||
return userList, err
|
||||
}
|
||||
// }
|
||||
return userList, nil
|
||||
}
|
||||
|
||||
func writeLog(alarmData *Alarm, toUser, forwardBy string, err error) error {
|
||||
var result string
|
||||
if err == nil {
|
||||
result = "SMS sent successfully"
|
||||
} else {
|
||||
result = err.Error()
|
||||
}
|
||||
forwardLog := &dborm.AlarmForwardLog{
|
||||
NeType: alarmData.NeType,
|
||||
NeID: alarmData.NeId,
|
||||
@@ -167,24 +178,15 @@ func AlarmForwardBySMPP(alarmData *Alarm) error {
|
||||
AlarmTitle: alarmData.AlarmTitle,
|
||||
AlarmSeq: alarmData.AlarmSeq,
|
||||
EventTime: alarmData.EventTime,
|
||||
Interface: forwardBy,
|
||||
ToUser: toUser,
|
||||
}
|
||||
message := alarmData.AlarmTitle + "from" + alarmData.NeType + alarmData.NeId + "at" + alarmData.EventTime
|
||||
if err = trans.Transceiver().Submit(newSubmitSM(toUser, message)); err != nil {
|
||||
operResult := fmt.Sprintf("Failed to submit short message:%v", err)
|
||||
log.Error(operResult)
|
||||
forwardLog.OperResult = operResult
|
||||
} else {
|
||||
operResult := "SMS sent successfully!"
|
||||
log.Trace(operResult)
|
||||
forwardLog.OperResult = operResult
|
||||
OperResult: result,
|
||||
}
|
||||
|
||||
affected, err := dborm.XormInsertAlarmForwardLog(forwardLog)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert data:", err)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package fm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/omc/config"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/go-gsm/ucp"
|
||||
)
|
||||
|
||||
func AlarmForwardBySMSC(alarmData *Alarm) error {
|
||||
opt := &ucp.Options{
|
||||
Addr: config.GetYamlConfig().Alarm.SMSC.Addr,
|
||||
User: config.GetYamlConfig().Alarm.SMSC.UserName,
|
||||
Password: config.GetYamlConfig().Alarm.SMSC.Password,
|
||||
AccessCode: "",
|
||||
}
|
||||
|
||||
client := ucp.New(opt)
|
||||
if err := client.Connect(); err != nil {
|
||||
log.Error("Failed to connect:", err)
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
reader, _ := readline.New(">>> ")
|
||||
defer reader.Close()
|
||||
|
||||
for {
|
||||
fmt.Print(">>> ")
|
||||
lines, _ := reader.Readline()
|
||||
fields := strings.Fields(lines)
|
||||
|
||||
if len(fields) == 1 {
|
||||
// exit CLI
|
||||
if fields[0] == "exit" {
|
||||
return nil
|
||||
}
|
||||
// display help message
|
||||
if fields[0] == "help" {
|
||||
log.Trace("\n\tSend a 'message' to 'receiver' with a 'sender' mask\n\t>>> sender receiver message\n\n\tExit the cli\n\t>>> exit\n")
|
||||
}
|
||||
}
|
||||
|
||||
// sender receiver message...
|
||||
if len(fields) >= 3 {
|
||||
sender := fields[0]
|
||||
receiver := fields[1]
|
||||
message := strings.Join(fields[2:], " ")
|
||||
ids, err := client.Send(sender, receiver, message)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
} else {
|
||||
log.Debug("%v", ids)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ type ApiResponse struct {
|
||||
ResultMessage interface{}
|
||||
}
|
||||
|
||||
var globalSession = session.NewSessManager("omc")
|
||||
var globalSession = session.NewSessManager("restagent")
|
||||
|
||||
func init() {
|
||||
conf := config.GetYamlConfig()
|
||||
|
||||
@@ -50,9 +50,9 @@ var DbClient DatabaseClient
|
||||
// conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
||||
// }
|
||||
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName, dbParam)
|
||||
DbClient.dbType = dbType
|
||||
DbClient.dbConnMaxLifetime = 0
|
||||
DbClient.dbMaxIdleConns = 0
|
||||
@@ -60,8 +60,7 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
if log.GetLevel() == log.LOG_TRACE {
|
||||
DbClient.IsShowSQL = true
|
||||
}
|
||||
log.Debugf("dbType:%s dbUrl:%s:******@tcp(%s:%s)/%s??charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbType, dbUser, dbHost, dbPort, dbName)
|
||||
log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl)
|
||||
|
||||
var err error
|
||||
DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
|
||||
@@ -72,6 +71,8 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
|
||||
DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
|
||||
DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
|
||||
DbClient.XEngine.DatabaseTZ = time.Local // 必须
|
||||
DbClient.XEngine.TZLocation = time.Local // 必须
|
||||
if DbClient.IsShowSQL {
|
||||
DbClient.XEngine.ShowSQL(true)
|
||||
}
|
||||
@@ -83,18 +84,18 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
func ExtDatabaseBackupData(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("ExtDatabaseBackupData processing... ")
|
||||
|
||||
token, err := services.CheckExtValidRequest(w, r)
|
||||
if err != nil {
|
||||
log.Error("Request error:", err)
|
||||
return
|
||||
}
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
vars := mux.Vars(r)
|
||||
module := vars["managementModule"]
|
||||
dbname := vars["dataStorage"]
|
||||
tbname := vars["dataObject"]
|
||||
pack := "lm"
|
||||
log.Debugf("token:%s, method:%s, module:%s dbname:%s, tbname:%s pack:%s", token, r.Method, module, dbname, tbname, pack)
|
||||
log.Debugf("method:%s, module:%s dbname:%s, tbname:%s pack:%s", r.Method, module, dbname, tbname, pack)
|
||||
// exist, err := services.CheckUserPermission(token, strings.ToLower(r.Method), module, dbname, tbname, pack)
|
||||
// if err != nil {
|
||||
// log.Error("Failed to get permission:", err)
|
||||
|
||||
@@ -1,314 +0,0 @@
|
||||
package maintenance
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
)
|
||||
|
||||
// (1) OMC能够对相关的文件系统资源、内存、CPU资源、数据存储空间、数据库空间等系统指标进行监控管理;
|
||||
// 对于虚拟化部署OMC系统,能够对虚机内存、虚机CPU、虚拟存储空间、文件系统资源、数据库空间等指标进行监控,提供界面截图 ;
|
||||
|
||||
// (2) 系统监控指标的采样时间和阈值可由用户设定,超过阈值将产生不同级别的告警,提供界面截图 ;
|
||||
|
||||
// (3) OMC能够方便的查询数据库连接情况;并可手工干预数据库的连接,能方便的终结非法的数据库连接 ;
|
||||
|
||||
// (4) 用户能方便的查询系统进程、应用进程等的进程名、进程类型、开始时间、运行主机等信息,提供界面截图
|
||||
// (5) 用户能方便的对系统进程、应用进程等做中断或者启动操作,提供界面截图
|
||||
|
||||
// (6) 对于文件系统资源、内存、CPU资源、数据存储空间、数据库空间等系统指标数据,要求OMC能够保存至少3个月,提供界面截图 ;
|
||||
// (7) 用户可以按照需求自定义报表模板并生成OMC系统维护数据报表,提供界面截图 ;
|
||||
|
||||
// (8) OMC具备自身告警管理功能,对于传统OMC系统,如:服务器单电源告警,存储硬盘告警、OMC系统软件故障等;
|
||||
// 对于虚拟化OMC系统,如虚机告警、虚拟硬盘告警等,提供界面截图 。
|
||||
|
||||
var (
|
||||
// parameter config management
|
||||
Uri = config.UriPrefix + "/maintenance/{apiVersion}/zz"
|
||||
|
||||
// (1) OMC能够对相关的文件系统资源、内存、CPU资源、数据存储空间、数据库空间等系统指标进行监控管理;
|
||||
UriPref = config.UriPrefix + "/maintenance/{apiVersion}/pref"
|
||||
|
||||
// (6) 对于文件系统资源、内存、CPU资源、数据存储空间、数据库空间等系统指标数据,要求OMC能够保存至少3个月,提供界面截图 ;
|
||||
UriPrefLog = config.UriPrefix + "/maintenance/{apiVersion}/prefLog"
|
||||
|
||||
// (2) 系统监控指标的采样时间和阈值可由用户设定,超过阈值将产生不同级别的告警,提供界面截图 ;
|
||||
UriConfig = config.UriPrefix + "/maintenance/{apiVersion}/config"
|
||||
|
||||
// (3) OMC能够方便的查询数据库连接情况;并可手工干预数据库的连接,能方便的终结非法的数据库连接
|
||||
UriSqlClient = config.UriPrefix + "/maintenance/{apiVersion}/sqlClient"
|
||||
|
||||
// (4) 用户能方便的查询系统进程、应用进程等的进程名、进程类型、开始时间、运行主机等信息,提供界面截图
|
||||
// (5) 用户能方便的对系统进程、应用进程等做中断或者启动操作,提供界面截图
|
||||
UriTop = config.UriPrefix + "/maintenance/{apiVersion}/top"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 定時收集 TODO
|
||||
prefLogSave("")
|
||||
}
|
||||
|
||||
func List(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("zz List")
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
|
||||
// 性能指標
|
||||
func prefInfo(dirName string) map[string]any {
|
||||
data := make(map[string]any)
|
||||
|
||||
// 显示文件資源目录
|
||||
dirPath := "D://"
|
||||
if runtime.GOOS == "linux" {
|
||||
dirPath = "/home"
|
||||
}
|
||||
// 訪問下級
|
||||
if dirName != "" {
|
||||
dirPath = path.Join(dirPath, dirName)
|
||||
}
|
||||
dir_list, e := os.ReadDir(dirPath)
|
||||
if e != nil {
|
||||
log.Error(e)
|
||||
}
|
||||
list := make([]map[string]any, 0)
|
||||
for _, v := range dir_list {
|
||||
o, err := v.Info()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, map[string]any{
|
||||
"name": o.Name(),
|
||||
"size": o.Size(),
|
||||
"mode": o.Mode().String(),
|
||||
"modTime": o.ModTime().Format("2006-01-02 15:04:05"),
|
||||
"isDir": o.IsDir(),
|
||||
})
|
||||
}
|
||||
data["dirList"] = list
|
||||
|
||||
// 文件資源使用率
|
||||
u, _ := disk.Usage(dirPath)
|
||||
usedGB := int(u.Used) / (1024 * 1024 * 1024 * 1)
|
||||
data["dirUse"] = fmt.Sprintf("%d", usedGB)
|
||||
|
||||
// CPU使用率
|
||||
percent, err := cpu.Percent(time.Second, false)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
data["cpuUse"] = fmt.Sprintf("%.2f", percent[0])
|
||||
|
||||
// 内存使用率
|
||||
memInfo, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
data["memUse"] = memInfo.UsedPercent
|
||||
|
||||
// 獲取數據庫占用空間
|
||||
if dborm.DbClient.XEngine != nil {
|
||||
conf := config.GetYamlConfig()
|
||||
result, err := dborm.DbClient.XEngine.QueryString(`SELECT
|
||||
CONCAT(TRUNCATE(SUM(data_length)/1024/1024,2),'MB') AS data_size,
|
||||
CONCAT(TRUNCATE(SUM(max_data_length)/1024/1024,2),'MB') AS max_data_size,
|
||||
CONCAT(TRUNCATE(SUM(data_free)/1024/1024,2),'MB') AS data_free,
|
||||
CONCAT(TRUNCATE(SUM(index_length)/1024/1024,2),'MB') AS index_size
|
||||
FROM information_schema.tables WHERE TABLE_SCHEMA = ?;
|
||||
`, conf.Database.Name)
|
||||
if err == nil {
|
||||
data["dbInfo"] = result[0]
|
||||
} else {
|
||||
data["dbInfo"] = map[string]string{}
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// 性能指標存入數據庫
|
||||
func prefLogSave(dirName string) {
|
||||
if dborm.DbClient.XEngine != nil {
|
||||
data := prefInfo(dirName)
|
||||
|
||||
dirListByte, err := json.Marshal(data["dirList"])
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
dbInfoByte, err := json.Marshal(data["dbInfo"])
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
rse, err := dborm.DbClient.XEngine.Exec(`INSERT INTO sys_perf_data
|
||||
(id, create_time, dir_used, dir_list, db_info, mem_used, cpu_used)
|
||||
VALUES(NULL, NOW(), ?, ?, ?, ?, ?);
|
||||
`, data["dirUse"], string(dirListByte), string(dbInfoByte), data["memUse"], data["cpuUse"])
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
fmt.Println(rse.LastInsertId())
|
||||
}
|
||||
}
|
||||
|
||||
// GET http://192.168.21.183:3040/api/rest/maintenance/v1/pref?dir=true
|
||||
func Pref(w http.ResponseWriter, r *http.Request) {
|
||||
// 知道下級文件資源目录
|
||||
dirName := r.URL.Query().Get("dirName")
|
||||
data := prefInfo(dirName)
|
||||
services.ResponseWithJson(w, http.StatusOK, data)
|
||||
}
|
||||
|
||||
// POST http://192.168.21.183:3040/api/rest/maintenance/v1/config
|
||||
func Config(w http.ResponseWriter, r *http.Request) {
|
||||
// json 請求參數獲取
|
||||
var bodyArgs struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 進行值更新
|
||||
if dborm.DbClient.XEngine != nil {
|
||||
result, err := dborm.DbClient.XEngine.QueryString("SELECT * FROM information_schema.processlist")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(result)
|
||||
rse, err := dborm.DbClient.XEngine.Exec("UPDATE sys_config SET value = ? where id = ?", "true", 100)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(rse)
|
||||
}
|
||||
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
|
||||
// http://192.168.21.183:3040/api/rest/maintenance/v1/sqlClient?type=close
|
||||
// http://192.168.21.183:3040/api/rest/maintenance/v1/sqlClient?type=connet
|
||||
// http://192.168.21.183:3040/api/rest/maintenance/v1/sqlClient?type=user
|
||||
func SqlClient(w http.ResponseWriter, r *http.Request) {
|
||||
// 关闭
|
||||
isClose := r.URL.Query().Get("type")
|
||||
if isClose == "close" && dborm.DbClient.XEngine != nil {
|
||||
dborm.DbClient.XEngine.Close()
|
||||
}
|
||||
|
||||
// 重连
|
||||
isConnet := r.URL.Query().Get("type")
|
||||
if isConnet == "connet" && dborm.DbClient.XEngine == nil {
|
||||
conf := config.GetYamlConfig()
|
||||
err := dborm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
||||
if err != nil {
|
||||
fmt.Println("dborm.initDbClient err:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 查询实例
|
||||
isUser := r.URL.Query().Get("type")
|
||||
if isUser == "user" && dborm.DbClient.XEngine != nil {
|
||||
result, err := dborm.DbClient.XEngine.QueryString("SELECT * FROM information_schema.processlist")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(result)
|
||||
rse, err := dborm.DbClient.XEngine.Exec("KILL CONNECTION CONNECTION_ID()")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(rse)
|
||||
}
|
||||
|
||||
// 进行连接测试
|
||||
err := dborm.DbClient.XEngine.Ping()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
|
||||
// GET http://192.168.21.183:3040/api/rest/maintenance/v1/top?grep=
|
||||
func Top(w http.ResponseWriter, r *http.Request) {
|
||||
// 過濾命令
|
||||
grep := r.URL.Query().Get("grep")
|
||||
// 命令拼接
|
||||
var cmd *exec.Cmd
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
command := "ps -ef "
|
||||
if grep != "" {
|
||||
command += grep
|
||||
}
|
||||
cmd = exec.Command(command)
|
||||
case "windows":
|
||||
command := "wmic process list brief "
|
||||
if grep != "" {
|
||||
command += grep
|
||||
}
|
||||
cmd = exec.Command("cmd", "/C", command)
|
||||
}
|
||||
|
||||
out, err := cmd.CombinedOutput()
|
||||
fmt.Println(string(out))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
services.ResponseWithJson(w, http.StatusOK, string(out))
|
||||
}
|
||||
|
||||
// PATCH http://192.168.21.183:3040/api/rest/maintenance/v1/top?ops=&name=
|
||||
func TopOps(w http.ResponseWriter, r *http.Request) {
|
||||
// json 請求參數獲取
|
||||
var bodyArgs struct {
|
||||
Ops string `json:"ops"`
|
||||
Pid string `json:"pid"`
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
// 命令拼接
|
||||
var cmd *exec.Cmd
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
switch bodyArgs.Ops {
|
||||
case "kill":
|
||||
cmd = exec.Command("kill", "-9", bodyArgs.Pid)
|
||||
}
|
||||
case "windows":
|
||||
switch bodyArgs.Ops {
|
||||
case "kill":
|
||||
cmd = exec.Command("cmd", "/C", "taskkill", "-PID", bodyArgs.Pid, "-F")
|
||||
}
|
||||
}
|
||||
|
||||
out, err := cmd.CombinedOutput()
|
||||
fmt.Println(string(out))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
services.ResponseWithJson(w, http.StatusOK, string(out))
|
||||
}
|
||||
@@ -52,16 +52,24 @@ var (
|
||||
CustomUriOmMmlInt = config.UriPrefix + "/omManagement/{apiVersion}/mml/{neType}/{neId}"
|
||||
)
|
||||
|
||||
var TIME_DELAY_AFTER_WRITE time.Duration = 200
|
||||
var TIME_DEAD_LINE time.Duration = 10
|
||||
var (
|
||||
TIME_DELAY_AFTER_WRITE time.Duration = 200
|
||||
TIME_DEAD_LINE time.Duration = 10
|
||||
WIN_ROW_SIZE int16 = 200
|
||||
WIN_COL_SIZE int16 = 120
|
||||
BUFFER_SIZE int = 65535
|
||||
)
|
||||
|
||||
func init() {
|
||||
func InitMML() {
|
||||
if config.GetYamlConfig().MML.Sleep != 0 {
|
||||
TIME_DELAY_AFTER_WRITE = time.Duration(config.GetYamlConfig().MML.Sleep)
|
||||
}
|
||||
if config.GetYamlConfig().MML.DeadLine != 0 {
|
||||
TIME_DEAD_LINE = time.Duration(config.GetYamlConfig().MML.DeadLine)
|
||||
}
|
||||
WIN_ROW_SIZE = config.GetYamlConfig().MML.SizeRow
|
||||
WIN_COL_SIZE = config.GetYamlConfig().MML.SizeCol
|
||||
BUFFER_SIZE = config.GetYamlConfig().MML.BufferSize
|
||||
}
|
||||
|
||||
func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -79,8 +87,7 @@ func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var buf [20 * 1024]byte
|
||||
//buf := make([]byte, 0)
|
||||
buf := make([]byte, BUFFER_SIZE)
|
||||
var n int
|
||||
var mmlResult []string
|
||||
port2 := 5002
|
||||
@@ -91,6 +98,7 @@ func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
|
||||
if neInfo != nil {
|
||||
hostMML := fmt.Sprintf("%s:%d", neInfo.Ip, port2)
|
||||
conn, err := net.Dial("tcp", hostMML)
|
||||
//conn, err := net.Dial("tcp", hostMML)
|
||||
if err != nil {
|
||||
errMsg := fmt.Sprintf("Failed to dial %s: %v", hostMML, err)
|
||||
log.Error(errMsg)
|
||||
@@ -112,6 +120,15 @@ func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// 发送窗口大小设置命令
|
||||
conn.Write([]byte{255, 251, 31}) // 发送WILL WINDOW SIZE
|
||||
conn.Write([]byte{
|
||||
255, 250, 31,
|
||||
byte(WIN_COL_SIZE >> 8), byte(WIN_COL_SIZE & 0xFF),
|
||||
byte(WIN_ROW_SIZE >> 8), byte(WIN_ROW_SIZE & 0xFF),
|
||||
255, 240,
|
||||
}) // 发送设置 WINDOW SIZE
|
||||
|
||||
conn.SetDeadline(time.Now().Add(TIME_DEAD_LINE * time.Second))
|
||||
loginStr := fmt.Sprintf("%s\n%s\n", config.GetYamlConfig().MML.User, config.GetYamlConfig().MML.Password)
|
||||
_, err = conn.Write([]byte(loginStr))
|
||||
@@ -173,7 +190,7 @@ func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
|
||||
//re2 := regexp.MustCompile(`\x00`) // 匹配空字符
|
||||
re2 := regexp.MustCompile(`[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\x1B]`) // 匹配空字符和包含␛的控制字符
|
||||
//re := regexp.MustCompile(`[\x00-\x1F\x7F]`)
|
||||
result := re1.ReplaceAllString(string(buf[0:n-len(neType)-2]), "")
|
||||
result := re1.ReplaceAllString(string(buf[0:n]), "")
|
||||
result = re2.ReplaceAllString(result, "")
|
||||
mmlResult = append(mmlResult, result)
|
||||
}
|
||||
@@ -187,11 +204,11 @@ func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
|
||||
func PostMMLToNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostMMLToNF processing... ")
|
||||
|
||||
token, err := services.CheckExtValidRequest(w, r)
|
||||
if err != nil {
|
||||
log.Error("Request error:", err)
|
||||
return
|
||||
}
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// 经过测试,linux下,延时需要大于100ms
|
||||
// var TIME_DELAY_AFTER_WRITE time.Duration = 200
|
||||
// var TIME_DEAD_LINE time.Duration = 10
|
||||
@@ -215,8 +232,7 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
log.Debug("neType:", neType, "neId", neId)
|
||||
|
||||
log.Debugf("token:%s, method:%s, managementType:%s dbname:%s, tbname:%s pack:%s",
|
||||
token, r.Method, module, neType, neId[0], pack)
|
||||
log.Debugf("method:%s, managementType:%s dbname:%s, tbname:%s pack:%s", r.Method, module, neType, neId[0], pack)
|
||||
|
||||
var buf [20 * 1024]byte
|
||||
//buf := make([]byte, 0)
|
||||
@@ -251,7 +267,7 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
neInfo := new(dborm.NeInfo)
|
||||
neInfo, err = dborm.XormGetNeInfo(neType, neId[0])
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId[0])
|
||||
if err != nil {
|
||||
log.Error("dborm.XormGetNeInfo is failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
@@ -632,11 +648,11 @@ func PostMMLToNF(w http.ResponseWriter, r *http.Request) {
|
||||
func PostMMLToOMC(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostMMLToOMC processing... ")
|
||||
|
||||
token, err := services.CheckExtValidRequest(w, r)
|
||||
if err != nil {
|
||||
log.Error("Failed to CheckMmlValidRequest:", err)
|
||||
return
|
||||
}
|
||||
// token, err := services.CheckExtValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Failed to CheckMmlValidRequest:", err)
|
||||
// return
|
||||
// }
|
||||
|
||||
params := r.URL.Query()
|
||||
neId := params["ne_id"]
|
||||
@@ -647,7 +663,7 @@ func PostMMLToOMC(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
neInfo := new(dborm.NeInfo)
|
||||
neInfo, err = dborm.XormGetNeInfo("OMC", neId[0])
|
||||
neInfo, err := dborm.XormGetNeInfo("OMC", neId[0])
|
||||
if err != nil {
|
||||
log.Error("dborm.XormGetNeInfo is failed:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
@@ -671,7 +687,7 @@ func PostMMLToOMC(w http.ResponseWriter, r *http.Request) {
|
||||
MmlHome: config.GetYamlConfig().MML.MmlHome,
|
||||
Limit: 50,
|
||||
User: "",
|
||||
SessionToken: token, // 旧token
|
||||
SessionToken: "", // 旧token
|
||||
Authorization: r.Header.Get(tokenConst.HEADER_KEY), // 请求Token
|
||||
HttpUri: hostUri,
|
||||
UserAgent: config.GetDefaultUserAgent(),
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package monitor
|
||||
|
||||
import "time"
|
||||
|
||||
type MonitorBase struct {
|
||||
ID uint `xorm:"id" json:"id"`
|
||||
CreatedAt time.Time `xorm:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `xorm:"updated_at" json:"updatedAt"`
|
||||
|
||||
Cpu float64 `xorm:"cpu" json:"cpu"`
|
||||
|
||||
LoadUsage float64 `xorm:"load_usage" json:"loadUsage"`
|
||||
CpuLoad1 float64 `xorm:"cpu_load1" json:"cpuLoad1"`
|
||||
CpuLoad5 float64 `xorm:"cpu_load5" json:"cpuLoad5"`
|
||||
CpuLoad15 float64 `xorm:"cpu_load15" json:"cpuLoad15"`
|
||||
|
||||
Memory float64 `xorm:"memory" json:"memory"`
|
||||
|
||||
DbSize uint `xorm:"db_size" json:"dbSize"`
|
||||
}
|
||||
|
||||
type MonitorIO struct {
|
||||
ID uint `xorm:"id" json:"id"`
|
||||
CreatedAt time.Time `xorm:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `xorm:"updated_at" json:"updatedAt"`
|
||||
|
||||
Name string `xorm:"name" json:"name"`
|
||||
Read uint64 `xorm:"read" json:"read"`
|
||||
Write uint64 `xorm:"write" json:"write"`
|
||||
Count uint64 `xorm:"count" json:"count"`
|
||||
Time uint64 `xorm:"time" json:"time"`
|
||||
}
|
||||
|
||||
type MonitorNetwork struct {
|
||||
ID uint `xorm:"id" json:"id"`
|
||||
CreatedAt time.Time `xorm:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `xorm:"updated_at" json:"updatedAt"`
|
||||
|
||||
Name string `xorm:"name" json:"name"`
|
||||
Up float64 `xorm:"up" json:"up"`
|
||||
Down float64 `xorm:"down" json:"down"`
|
||||
}
|
||||
|
||||
type MonitorSearch struct {
|
||||
Param string `json:"param" validate:"required,oneof=all cpu memory load io network"`
|
||||
Info string `json:"info"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
EndTime time.Time `json:"endTime"`
|
||||
}
|
||||
|
||||
type MonitorData struct {
|
||||
Param string `json:"param" validate:"required,oneof=cpu memory load io network"`
|
||||
Date []time.Time `json:"date"`
|
||||
Value []interface{} `json:"value"`
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
"github.com/shirou/gopsutil/net"
|
||||
)
|
||||
|
||||
// 点击【主机 - 监控】菜单,进入监控报表,直观的了解服务器的运行状态,包含【平均负载】、【CPU性能监控】、【内存使用监控】、【磁盘IO监控】、【网络IO监控】
|
||||
|
||||
// 可以查看昨天,今天,最近7天,最近30天,自定义时间的监控指标情况。
|
||||
// 默认监控是开启的,可以在【面板设置 - 监控】页面中根据需求对监控进行开启和关闭。
|
||||
// 监控数据默认保存30天,可以自行修改,也可手动清理该日志。
|
||||
|
||||
var (
|
||||
// IP地址
|
||||
UriIPAddr = config.DefaultUriPrefix + "/monitor/{apiVersion}/monitor/ipaddr"
|
||||
// 可选网络
|
||||
UriNetOpt = config.DefaultUriPrefix + "/monitor/{apiVersion}/monitor/netoptions"
|
||||
// 可选磁盘
|
||||
UriIoOpt = config.DefaultUriPrefix + "/monitor/{apiVersion}/monitor/iooptions"
|
||||
// 加载
|
||||
UriLoad = config.DefaultUriPrefix + "/monitor/{apiVersion}/monitor/load"
|
||||
|
||||
// IP地址
|
||||
UriIPAddrOAM = config.UriPrefix + "/monitor/{apiVersion}/monitor/ipaddr"
|
||||
// 可选网络
|
||||
UriNetOptOAM = config.UriPrefix + "/monitor/{apiVersion}/monitor/netoptions"
|
||||
// 可选磁盘
|
||||
UriIoOptOAM = config.UriPrefix + "/monitor/{apiVersion}/monitor/iooptions"
|
||||
// 加载
|
||||
UriLoadOAM = config.UriPrefix + "/monitor/{apiVersion}/monitor/load"
|
||||
)
|
||||
|
||||
// IPAddr IP地址
|
||||
func IPAddr(w http.ResponseWriter, r *http.Request) {
|
||||
ipAddrs := []map[string]string{}
|
||||
interfaces, err := net.Interfaces()
|
||||
if err == nil {
|
||||
for _, iface := range interfaces {
|
||||
addrs := map[string]string{}
|
||||
for _, v := range iface.Addrs {
|
||||
prefix := strings.Split(v.Addr, "/")[0]
|
||||
if strings.Contains(prefix, "::") {
|
||||
addrs["IPv6"] = prefix
|
||||
}
|
||||
if strings.Contains(prefix, ".") {
|
||||
addrs["IPv4"] = prefix
|
||||
}
|
||||
}
|
||||
ipAddrs = append(ipAddrs, addrs)
|
||||
}
|
||||
}
|
||||
services.ResponseWithJson(w, 200, ipAddrs)
|
||||
}
|
||||
|
||||
// Netoptions 可选网络
|
||||
func Netoptions(w http.ResponseWriter, r *http.Request) {
|
||||
netStat, _ := net.IOCounters(true)
|
||||
var options []string
|
||||
options = append(options, "all")
|
||||
for _, net := range netStat {
|
||||
options = append(options, net.Name)
|
||||
}
|
||||
sort.Strings(options)
|
||||
services.ResponseWithJson(w, 200, options)
|
||||
}
|
||||
|
||||
// Iooptions 可选磁盘
|
||||
func Iooptions(w http.ResponseWriter, r *http.Request) {
|
||||
diskStat, _ := disk.IOCounters()
|
||||
var options []string
|
||||
options = append(options, "all")
|
||||
for _, net := range diskStat {
|
||||
options = append(options, net.Name)
|
||||
}
|
||||
sort.Strings(options)
|
||||
services.ResponseWithJson(w, 200, options)
|
||||
}
|
||||
|
||||
// LoadMonitor 载入监控
|
||||
func LoadMonitor(w http.ResponseWriter, r *http.Request) {
|
||||
// json 請求參數獲取
|
||||
var bodyArgs MonitorSearch
|
||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
||||
if err != nil || dborm.DbClient.XEngine == nil {
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
loc := time.Now().Location()
|
||||
bodyArgs.StartTime = bodyArgs.StartTime.In(loc)
|
||||
bodyArgs.EndTime = bodyArgs.EndTime.In(loc)
|
||||
|
||||
var backdatas []MonitorData
|
||||
if bodyArgs.Param == "all" || bodyArgs.Param == "cpu" || bodyArgs.Param == "memory" || bodyArgs.Param == "load" {
|
||||
var bases []MonitorBase
|
||||
err := dborm.DbClient.XEngine.Table("monitor_base").
|
||||
Where("created_at > ? AND created_at < ?", bodyArgs.StartTime, bodyArgs.EndTime).
|
||||
Desc("created_at").
|
||||
Find(&bases)
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var itemData MonitorData
|
||||
itemData.Param = "base"
|
||||
for _, base := range bases {
|
||||
itemData.Date = append(itemData.Date, base.CreatedAt)
|
||||
itemData.Value = append(itemData.Value, base)
|
||||
}
|
||||
backdatas = append(backdatas, itemData)
|
||||
}
|
||||
if bodyArgs.Param == "all" || bodyArgs.Param == "io" {
|
||||
var bases []MonitorIO
|
||||
err := dborm.DbClient.XEngine.Table("monitor_io").
|
||||
Where("created_at > ? AND created_at < ?", bodyArgs.StartTime, bodyArgs.EndTime).
|
||||
Desc("created_at").
|
||||
Find(&bases)
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var itemData MonitorData
|
||||
itemData.Param = "io"
|
||||
for _, base := range bases {
|
||||
itemData.Date = append(itemData.Date, base.CreatedAt)
|
||||
itemData.Value = append(itemData.Value, base)
|
||||
}
|
||||
backdatas = append(backdatas, itemData)
|
||||
}
|
||||
if bodyArgs.Param == "all" || bodyArgs.Param == "network" {
|
||||
var bases []MonitorNetwork
|
||||
err := dborm.DbClient.XEngine.Table("monitor_network").
|
||||
Where("name = ? AND created_at > ? AND created_at < ?", bodyArgs.Info, bodyArgs.StartTime, bodyArgs.EndTime).
|
||||
Desc("created_at").
|
||||
Find(&bases)
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var itemData MonitorData
|
||||
itemData.Param = "network"
|
||||
for _, base := range bases {
|
||||
itemData.Date = append(itemData.Date, base.CreatedAt)
|
||||
itemData.Value = append(itemData.Value, base)
|
||||
}
|
||||
backdatas = append(backdatas, itemData)
|
||||
}
|
||||
services.ResponseWithJson(w, 200, backdatas)
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/omc/config"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/load"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
)
|
||||
|
||||
type MonitorService struct{}
|
||||
|
||||
type IMonitorService interface {
|
||||
Run()
|
||||
}
|
||||
|
||||
func NewIMonitorService() IMonitorService {
|
||||
return &MonitorService{}
|
||||
}
|
||||
|
||||
func (m *MonitorService) Run() {
|
||||
// monitorStatus, _ := dborm.XormGetConfig("SystemMonitor", "MonitorStatus")
|
||||
// if monitorStatus["value"] == "disable" {
|
||||
// return
|
||||
// }
|
||||
var itemModel MonitorBase
|
||||
itemModel.CreatedAt = time.Now()
|
||||
itemModel.UpdatedAt = time.Now()
|
||||
|
||||
totalPercent, _ := cpu.Percent(3*time.Second, false)
|
||||
if len(totalPercent) == 1 {
|
||||
itemModel.Cpu = totalPercent[0]
|
||||
}
|
||||
cpuCount, _ := cpu.Counts(false)
|
||||
|
||||
loadInfo, _ := load.Avg()
|
||||
itemModel.CpuLoad1 = loadInfo.Load1
|
||||
itemModel.CpuLoad5 = loadInfo.Load5
|
||||
itemModel.CpuLoad15 = loadInfo.Load15
|
||||
itemModel.LoadUsage = loadInfo.Load1 / (float64(cpuCount*2) * 0.75) * 100
|
||||
|
||||
memoryInfo, _ := mem.VirtualMemory()
|
||||
itemModel.Memory = memoryInfo.UsedPercent
|
||||
|
||||
var dataSize int
|
||||
conf := config.GetYamlConfig()
|
||||
result, err := dborm.DbClient.XEngine.QueryString("SELECT SUM(data_length) AS data_size FROM information_schema.tables WHERE TABLE_SCHEMA = ?;", conf.Database.Name)
|
||||
if err != nil {
|
||||
dataSize = 0
|
||||
} else {
|
||||
v, _ := strconv.Atoi(result[0]["data_size"])
|
||||
dataSize = v
|
||||
}
|
||||
itemModel.DbSize = uint(dataSize)
|
||||
|
||||
_, errx := dborm.DbClient.XEngine.Table("monitor_base").Insert(itemModel)
|
||||
if errx != nil {
|
||||
log.Errorf("Insert basic monitoring data failed, err: %v", err)
|
||||
}
|
||||
|
||||
go loadDiskIO()
|
||||
go loadNetIO()
|
||||
|
||||
// 删除保留的记录
|
||||
// monitorStoreDays, _ := dborm.XormGetConfig("SystemMonitor", "MonitorStoreDays")
|
||||
// if monitorStoreDays["value"] != "" {
|
||||
// return
|
||||
// }
|
||||
// storeDays, err := strconv.Atoi(MonitorStoreDays.Value)
|
||||
// if err != nil {
|
||||
// timeForDelete := time.Now().AddDate(0, 0, -storeDays)
|
||||
// DelMonitorBase(timeForDelete)
|
||||
// DelMonitorIO(timeForDelete)
|
||||
// DelMonitorNet(timeForDelete)
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
func loadDiskIO() {
|
||||
ioStat, _ := disk.IOCounters()
|
||||
|
||||
time.Sleep(60 * time.Second)
|
||||
|
||||
ioStat2, _ := disk.IOCounters()
|
||||
var ioList []MonitorIO
|
||||
for _, io2 := range ioStat2 {
|
||||
for _, io1 := range ioStat {
|
||||
if io2.Name == io1.Name {
|
||||
var itemIO MonitorIO
|
||||
itemIO.CreatedAt = time.Now()
|
||||
itemIO.UpdatedAt = time.Now()
|
||||
|
||||
itemIO.Name = io1.Name
|
||||
if io2.ReadBytes != 0 && io1.ReadBytes != 0 && io2.ReadBytes > io1.ReadBytes {
|
||||
itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / 60)
|
||||
}
|
||||
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
|
||||
itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / 60)
|
||||
}
|
||||
|
||||
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
|
||||
itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / 60)
|
||||
}
|
||||
writeCount := uint64(0)
|
||||
if io2.WriteCount != 0 && io1.WriteCount != 0 && io2.WriteCount > io1.WriteCount {
|
||||
writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / 60)
|
||||
}
|
||||
if writeCount > itemIO.Count {
|
||||
itemIO.Count = writeCount
|
||||
}
|
||||
|
||||
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
|
||||
itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / 60)
|
||||
}
|
||||
writeTime := uint64(0)
|
||||
if io2.WriteTime != 0 && io1.WriteTime != 0 && io2.WriteTime > io1.WriteTime {
|
||||
writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / 60)
|
||||
}
|
||||
if writeTime > itemIO.Time {
|
||||
itemIO.Time = writeTime
|
||||
}
|
||||
ioList = append(ioList, itemIO)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err := dborm.DbClient.XEngine.Table("monitor_io").Insert(ioList)
|
||||
if err != nil {
|
||||
log.Errorf("Insert io monitoring data failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func loadNetIO() {
|
||||
netStat, _ := net.IOCounters(true)
|
||||
netStatAll, _ := net.IOCounters(false)
|
||||
|
||||
time.Sleep(60 * time.Second)
|
||||
|
||||
netStat2, _ := net.IOCounters(true)
|
||||
var netList []MonitorNetwork
|
||||
for _, net2 := range netStat2 {
|
||||
for _, net1 := range netStat {
|
||||
if net2.Name == net1.Name {
|
||||
var itemNet MonitorNetwork
|
||||
itemNet.CreatedAt = time.Now()
|
||||
itemNet.UpdatedAt = time.Now()
|
||||
|
||||
itemNet.Name = net1.Name
|
||||
|
||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60
|
||||
}
|
||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60
|
||||
}
|
||||
netList = append(netList, itemNet)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
netStatAll2, _ := net.IOCounters(false)
|
||||
for _, net2 := range netStatAll2 {
|
||||
for _, net1 := range netStatAll {
|
||||
if net2.Name == net1.Name {
|
||||
var itemNet MonitorNetwork
|
||||
itemNet.Name = net1.Name
|
||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60
|
||||
}
|
||||
|
||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60
|
||||
}
|
||||
netList = append(netList, itemNet)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err := dborm.DbClient.XEngine.Table("monitor_network").Insert(netList)
|
||||
if err != nil {
|
||||
log.Errorf("Insert network monitoring data failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var c *cron.Cron
|
||||
var monitorCronID int
|
||||
|
||||
func init() {
|
||||
c = cron.New()
|
||||
c.Start()
|
||||
monitorCronID = 0
|
||||
}
|
||||
|
||||
// StartMonitor 开始监控任务 removeBefore删除上次任务,间隔interval分钟
|
||||
func StartMonitor(removeBefore bool, interval string) error {
|
||||
if removeBefore {
|
||||
c.Remove(cron.EntryID(monitorCronID))
|
||||
}
|
||||
|
||||
// 读取配置
|
||||
if interval == "" {
|
||||
v, err := dborm.XormGetConfig("SystemMonitor", "sampleTime")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := make(map[string]any)
|
||||
err = json.Unmarshal([]byte(v["value_json"].(string)), &data)
|
||||
if err != nil {
|
||||
log.Error("json StartMonitor:%s", err.Error())
|
||||
return err
|
||||
}
|
||||
interval = data["sampleTime"].(string)
|
||||
}
|
||||
|
||||
imservice := NewIMonitorService()
|
||||
monitorID, err := c.AddJob(fmt.Sprintf("@every %sm", interval), imservice)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imservice.Run()
|
||||
monitorCronID = int(monitorID)
|
||||
return nil
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package psnet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/lib/wsinfo"
|
||||
"nms_cxy/omc/config"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
)
|
||||
|
||||
var (
|
||||
// websockte通信
|
||||
UriWs = config.DefaultUriPrefix + "/monitor/{apiVersion}/psnet/ws"
|
||||
// 停止进程
|
||||
UriStop = config.DefaultUriPrefix + "/monitor/{apiVersion}/psnet/stop"
|
||||
|
||||
// 检查ip端口请求
|
||||
UriPing = config.DefaultUriPrefix + "/monitor/{apiVersion}/psnet/ping"
|
||||
)
|
||||
|
||||
// 进程管理
|
||||
var wsUpgrade = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
// ProcessWs
|
||||
func ProcessWs(w http.ResponseWriter, r *http.Request) {
|
||||
ws, err := wsUpgrade.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
wsClient := wsinfo.NewWsClient("processClient", ws)
|
||||
go wsClient.Read()
|
||||
go wsClient.Write()
|
||||
}
|
||||
|
||||
// 停止进程 {"PID":30040}
|
||||
func StopProcess(w http.ResponseWriter, r *http.Request) {
|
||||
// json 請求參數獲取
|
||||
var bodyArgs struct {
|
||||
PID int32 `json:"PID" validate:"required"`
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
proc, err := process.NewProcess(bodyArgs.PID)
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
if err := proc.Kill(); err != nil {
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
|
||||
// 检查ip端口请求
|
||||
func Ping(w http.ResponseWriter, r *http.Request) {
|
||||
// json 請求參數獲取
|
||||
var bodyArgs struct {
|
||||
Host string `json:"host" validate:"required"`
|
||||
Port string `json:"port" validate:"required"`
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
||||
if err != nil {
|
||||
log.Error("io.ReadAll is failed:", err)
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%s", bodyArgs.Host, bodyArgs.Port), 3*time.Second)
|
||||
if err != nil {
|
||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
services.ResponseStatusOK200Null(w)
|
||||
|
||||
}
|
||||
@@ -36,7 +36,7 @@ type ApiResponse struct {
|
||||
ResultMessage interface{}
|
||||
}
|
||||
|
||||
var globalSession = session.NewSessManager("omc")
|
||||
var globalSession = session.NewSessManager("restagent")
|
||||
|
||||
var (
|
||||
MAX_RMUID_NUM int
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"math"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/dborm"
|
||||
@@ -65,6 +66,26 @@ type GoldKpi struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
}
|
||||
|
||||
type KpiData struct {
|
||||
ID int `json:"id" xorm:"pk 'id' '<-' autoincr"`
|
||||
NEType string `json:"neType" xorm:"ne_type"`
|
||||
NEName string `json:"neName" xorm:"ne_name"`
|
||||
RmUid string `json:"rmUid" xorm:"rm_uid"`
|
||||
Date string `json:"date" xorm:"date"`
|
||||
StartTime string `json:"startTime" xorm:"start_time"`
|
||||
EndTime string `json:"endTime" xorm:"end_time"`
|
||||
Index int `json:"index" xorm:"index"`
|
||||
Granularity int8 `json:"granularity" xorm:"granularity"`
|
||||
KPIValues []KPIVal `json:"kpiValues" xorm:"json 'kpi_values'"`
|
||||
//CreatedAt int64 `json:"createdAt" xorm:"created 'created_at'"`
|
||||
CreatedAt int64 `json:"createdAt" xorm:"'created_at'"`
|
||||
}
|
||||
type KPIVal struct {
|
||||
KPIID string `json:"kpi_id" xorm:"kpi_id"`
|
||||
Value int64 `json:"value" xorm:"value"`
|
||||
Err string `json:"err" xorm:"err"`
|
||||
}
|
||||
|
||||
var (
|
||||
// performance management
|
||||
PerformanceUri = config.DefaultUriPrefix + "/performanceManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/kpiReport/{index}"
|
||||
@@ -98,9 +119,9 @@ type DatabaseClient struct {
|
||||
|
||||
var DbClient DatabaseClient
|
||||
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName, dbParam)
|
||||
DbClient.dbType = dbType
|
||||
DbClient.dbConnMaxLifetime = 0
|
||||
DbClient.dbMaxIdleConns = 0
|
||||
@@ -108,8 +129,7 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
if log.GetLevel() == log.LOG_TRACE {
|
||||
DbClient.IsShowSQL = true
|
||||
}
|
||||
log.Debugf("dbType:%s dbUrl:%s:******@tcp(%s:%s)/%s??charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbType, dbUser, dbHost, dbPort, dbName)
|
||||
log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl)
|
||||
|
||||
var err error
|
||||
DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
|
||||
@@ -120,11 +140,28 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
|
||||
DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
|
||||
DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
|
||||
DbClient.XEngine.DatabaseTZ = time.Local // 必须
|
||||
DbClient.XEngine.TZLocation = time.Local // 必须
|
||||
if DbClient.IsShowSQL {
|
||||
DbClient.XEngine.ShowSQL(true)
|
||||
}
|
||||
xEngine = DbClient.XEngine
|
||||
|
||||
// exist, err := xEngine.IsTableExist("kpi_report")
|
||||
// if err != nil {
|
||||
// log.Error("Failed to IsTableExist:", err)
|
||||
// return err
|
||||
// }
|
||||
// if exist {
|
||||
// // 复制表结构到新表
|
||||
// sql := fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` AS SELECT * FROM kpi_report WHERE 1=0", "kpi_report_amf")
|
||||
// _, err := xEngine.Exec(sql)
|
||||
// if err != nil {
|
||||
// log.Error("Failed to Exec:", err)
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -155,7 +192,7 @@ func GetDateTimeFromTimeString(fmtString string, timeString string) string {
|
||||
return t.Format(global.DateTime)
|
||||
}
|
||||
|
||||
// process alarm post message from NFs
|
||||
// process KPI report post message from NFs
|
||||
func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostKPIReportFromNF processing... ")
|
||||
|
||||
@@ -167,6 +204,91 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
log.Error("Faile to io.ReadAll: ", err)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//log.Trace("Request body:", string(body))
|
||||
kpiReport := new(KpiReport)
|
||||
_ = json.Unmarshal(body, &kpiReport)
|
||||
//log.Trace("kpiReport:", kpiReport)
|
||||
|
||||
layout := time.RFC3339Nano
|
||||
//kpiDate := GetDateFromTimeString(layout, kpiReport.Task.Period.StartTime)
|
||||
kpiIndex, _ := strconv.Atoi(vars["index"])
|
||||
startTime := global.GetFmtTimeString(layout, kpiReport.Task.Period.StartTime, time.DateTime)
|
||||
endTime := global.GetFmtTimeString(layout, kpiReport.Task.Period.EndTime, time.DateTime)
|
||||
// get time granularity from startTime and endTime
|
||||
seconds, _ := global.GetSecondDuration(startTime, endTime)
|
||||
var granularity int8 = 60
|
||||
if seconds != 0 && seconds <= math.MaxInt8 && seconds >= math.MinInt8 {
|
||||
granularity = int8(seconds)
|
||||
}
|
||||
|
||||
// 黄金指标事件对象
|
||||
kpiEvent := map[string]any{
|
||||
// kip_id ...
|
||||
"neType": kpiReport.Task.NE.NeType,
|
||||
"neName": kpiReport.Task.NE.NEName,
|
||||
"startIndex": kpiIndex,
|
||||
"timeGroup": startTime,
|
||||
}
|
||||
// insert into new kpi_report_xxx table
|
||||
kpiData := new(KpiData)
|
||||
kpiData.Date = startTime
|
||||
kpiData.Index = kpiIndex
|
||||
//stime, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.StartTime, time.Local)
|
||||
//etime, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.EndTime, time.Local)
|
||||
kpiData.StartTime = startTime
|
||||
kpiData.EndTime = endTime
|
||||
kpiData.Granularity = granularity
|
||||
kpiData.NEName = kpiReport.Task.NE.NEName
|
||||
kpiData.NEType = kpiReport.Task.NE.NeType
|
||||
kpiData.RmUid = kpiReport.Task.NE.RmUID
|
||||
kpiVal := new(KPIVal)
|
||||
kpiData.CreatedAt = time.Now().UnixMilli()
|
||||
for _, k := range kpiReport.Task.NE.KPIs {
|
||||
kpiEvent[k.KPIID] = k.Value // kip_id
|
||||
|
||||
kpiVal.KPIID = k.KPIID
|
||||
kpiVal.Value = int64(k.Value)
|
||||
kpiVal.Err = k.Err
|
||||
kpiData.KPIValues = append(kpiData.KPIValues, *kpiVal)
|
||||
}
|
||||
|
||||
// insert kpi_report table, no session
|
||||
tableName := "kpi_report_" + strings.ToLower(kpiReport.Task.NE.NeType)
|
||||
affected, err := xEngine.Table(tableName).Insert(kpiData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Errorf("Failed to insert %s:%v", tableName, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 推送到ws订阅组
|
||||
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI, kpiEvent)
|
||||
if kpiReport.Task.NE.NeType == "UPF" {
|
||||
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI_UPF, kpiEvent)
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
// post kpi report from NEs, insert insto gold_kpi table, discard...
|
||||
func PostGoldKPIFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("PostKPIReportFromNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
apiVer := vars["apiVersion"]
|
||||
if apiVer != global.ApiVersionV1 {
|
||||
log.Error("Uri api version is invalid. apiVersion:", apiVer)
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||
if err != nil {
|
||||
@@ -205,12 +327,32 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
"startIndex": goldKpi.Index,
|
||||
"timeGroup": goldKpi.StartTime,
|
||||
}
|
||||
// insert into new kpi_report_xxx table
|
||||
kpiData := new(KpiData)
|
||||
kpiData.Date = goldKpi.Date
|
||||
kpiData.Index = goldKpi.Index
|
||||
//st, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.StartTime, time.Local)
|
||||
//et, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.EndTime, time.Local)
|
||||
kpiData.StartTime = goldKpi.StartTime
|
||||
kpiData.EndTime = goldKpi.EndTime
|
||||
kpiData.Granularity = goldKpi.Granularity
|
||||
kpiData.NEName = goldKpi.NEName
|
||||
kpiData.NEType = goldKpi.NEType
|
||||
kpiData.RmUid = goldKpi.RmUid
|
||||
kpiVal := new(KPIVal)
|
||||
kpiData.CreatedAt = time.Now().UnixMilli()
|
||||
for _, k := range kpiReport.Task.NE.KPIs {
|
||||
kpiEvent[k.KPIID] = k.Value // kip_id
|
||||
goldKpi.KpiId = k.KPIID
|
||||
goldKpi.Value = k.Value
|
||||
goldKpi.Error = k.Err
|
||||
log.Trace("goldKpi:", goldKpi)
|
||||
|
||||
kpiVal.KPIID = k.KPIID
|
||||
kpiVal.Value = int64(k.Value)
|
||||
kpiVal.Err = k.Err
|
||||
kpiData.KPIValues = append(kpiData.KPIValues, *kpiVal)
|
||||
|
||||
//log.Trace("goldKpi:", goldKpi)
|
||||
|
||||
// 启动事务
|
||||
err := session.Begin()
|
||||
@@ -244,13 +386,22 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// insert kpi_report table, no session
|
||||
tableName := "kpi_report_" + strings.ToLower(kpiReport.Task.NE.NeType)
|
||||
affected, err := xEngine.Table(tableName).Insert(kpiData)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Errorf("Failed to insert %s:%v", tableName, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 推送到ws订阅组
|
||||
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI, kpiEvent)
|
||||
if goldKpi.NEType == "UPF" {
|
||||
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI_UPF, kpiEvent)
|
||||
}
|
||||
|
||||
services.ResponseStatusOK200Null(w)
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
type MeasureTask struct {
|
||||
@@ -903,9 +1054,9 @@ func PostMeasurementFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
layout := time.RFC3339
|
||||
measurement.Date = GetDateFromTimeString(layout, measurement.StartTime)
|
||||
measurement.StartTime = GetDateTimeFromTimeString(layout, measurement.StartTime)
|
||||
affected, err := session.Table("northbound_pm").Insert(measurement)
|
||||
affected, err := session.Table("nbi_pm").Insert(measurement)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert northbound_pm:", err)
|
||||
log.Error("Failed to insert nbi_pm:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
@@ -986,9 +1137,9 @@ func GetMeasurementFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
layout := time.RFC3339
|
||||
measurement.Date = GetDateFromTimeString(layout, measurement.StartTime)
|
||||
measurement.StartTime = GetDateTimeFromTimeString(layout, measurement.StartTime)
|
||||
affected, err := session.Table("northbound_pm").Insert(measurement)
|
||||
affected, err := session.Table("nbi_pm").Insert(measurement)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert northbound_pm:", err)
|
||||
log.Error("Failed to insert nbi_pm:", err)
|
||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,56 +2,24 @@ package security
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/features/security/service"
|
||||
sysConfigService "nms_cxy/features/sys_config/service"
|
||||
"nms_cxy/lib/core/account"
|
||||
"nms_cxy/lib/core/cache"
|
||||
"nms_cxy/lib/core/constants/cachekey"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/vo/result"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/global"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/lib/oauth"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
srcConfig "nms_cxy/src/framework/config"
|
||||
"nms_cxy/src/framework/i18n"
|
||||
"nms_cxy/src/framework/redis"
|
||||
|
||||
"github.com/mojocn/base64Captcha"
|
||||
)
|
||||
|
||||
var (
|
||||
UriOauthToken2 = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token2"
|
||||
UriOauthToken = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
|
||||
UriOauthHandshake = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
|
||||
|
||||
CustomUriOauthToken = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
|
||||
CustomUriOauthHandshake = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
|
||||
|
||||
// 系统登录
|
||||
UriLogin = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/login"
|
||||
CustomUriLogin = config.UriPrefix + "/securityManagement/{apiVersion}/login"
|
||||
|
||||
// 获取验证码
|
||||
UriCaptchaImage = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/captchaImage"
|
||||
CustomUriCaptchaImage = config.UriPrefix + "/securityManagement/{apiVersion}/captchaImage"
|
||||
|
||||
// 登录用户信息
|
||||
UriUserInfo = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/getUserInfo"
|
||||
CustomUriUserInfo = config.UriPrefix + "/securityManagement/{apiVersion}/getUserInfo"
|
||||
|
||||
// 登录用户路由信息
|
||||
UriRouters = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/getRouters"
|
||||
CustomUriRouters = config.UriPrefix + "/securityManagement/{apiVersion}/getRouters"
|
||||
)
|
||||
|
||||
func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -136,14 +104,8 @@ func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
// 缓存用户信息
|
||||
account.CacheLoginUser(user)
|
||||
redis.SetByExpire("", "session_token", token, time.Second*1800)
|
||||
// 角色权限集合,管理员拥有所有权限
|
||||
userId := fmt.Sprint(user.Id)
|
||||
isAdmin := srcConfig.IsAdmin(userId)
|
||||
roles, perms := service.NewServiceAccount.RoleAndMenuPerms(userId, isAdmin)
|
||||
services.ResponseStatusOK200LoginWhitRP(w, token, user, roles, perms)
|
||||
empty := []string{}
|
||||
services.ResponseStatusOK200LoginWhitRP(w, token, user, empty, empty)
|
||||
return
|
||||
}
|
||||
services.ResponseBadRequest400IncorrectLogin(w)
|
||||
@@ -225,212 +187,3 @@ func HandshakeFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
services.ResponseStatusOK200Null(w)
|
||||
}
|
||||
|
||||
// 系统登录
|
||||
//
|
||||
// POST /login
|
||||
func LoginOMC(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("LoginOMC processing... ")
|
||||
var body struct {
|
||||
Username string `json:"username" binding:"required"` // Username 用户名
|
||||
Password string `json:"password" binding:"required"` // Password 用户密码
|
||||
Code string `json:"code"` // Code 验证码
|
||||
UUID string `json:"uuid"` // UUID 验证码唯一标识
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil {
|
||||
log.Error("Invalid Json Format")
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
// response 400-5
|
||||
if body.Username == "" || body.Password == "" {
|
||||
log.Error("Wrong parameter value")
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 校验验证码
|
||||
// 从数据库配置获取验证码开关 true开启,false关闭
|
||||
captchaEnabledStr := sysConfigService.NewServiceSysConfig.SelectConfigValueByKey("sys.account.captchaEnabled")
|
||||
captchaEnabled, err := strconv.ParseBool(captchaEnabledStr)
|
||||
if err != nil {
|
||||
captchaEnabled = false
|
||||
}
|
||||
if captchaEnabled {
|
||||
if body.Code == "" || body.UUID == "" {
|
||||
log.Error("Authentication failed, mismatch captcha")
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "Verification code information error"))
|
||||
return
|
||||
}
|
||||
verifyKey := cachekey.CAPTCHA_CODE_KEY + body.UUID
|
||||
captcha, ok := cache.GetLocalTTL(verifyKey)
|
||||
if captcha == nil || !ok {
|
||||
log.Error("Authentication failed, captcha emtry")
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "The verification code has expired"))
|
||||
return
|
||||
}
|
||||
cache.DeleteLocalTTL(verifyKey)
|
||||
if captcha.(string) != body.Code {
|
||||
log.Error("Authentication failed, not match captcha")
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "Verification code error"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
validUser, user, err := dborm.XormCheckLoginUser(body.Username, body.Password, config.GetYamlConfig().Auth.Crypt)
|
||||
if !validUser || err != nil {
|
||||
// response 400-4
|
||||
log.Error("Authentication failed, mismatch user or password")
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
token := oauth.GenRandToken("omc") // Generate new token to session ID
|
||||
sourceAddr := r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")]
|
||||
affected, err := dborm.XormInsertSession(body.Username, sourceAddr, token,
|
||||
config.GetExpiresFromConfig(), config.GetYamlConfig().Auth.Session)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormInsertSession:", err)
|
||||
if affected == -1 {
|
||||
services.ResponseForbidden403MultiLoginNotAllowed(w)
|
||||
} else {
|
||||
services.ResponseBadRequest400IncorrectLogin(w)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
// 缓存用户信息
|
||||
account.CacheLoginUser(user)
|
||||
redis.SetByExpire("", "session_token", token, time.Second*1800)
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"accessToken": token,
|
||||
}))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
//
|
||||
// GET /captchaImage
|
||||
func CaptchaImage(w http.ResponseWriter, r *http.Request) {
|
||||
configService := sysConfigService.NewServiceSysConfig
|
||||
|
||||
// 从数据库配置获取验证码开关 true开启,false关闭
|
||||
captchaEnabledStr := configService.SelectConfigValueByKey("sys.account.captchaEnabled")
|
||||
captchaEnabled, err := strconv.ParseBool(captchaEnabledStr)
|
||||
if err != nil {
|
||||
captchaEnabled = false
|
||||
}
|
||||
if !captchaEnabled {
|
||||
ctx.JSON(w, 200, result.Ok(map[string]any{
|
||||
"captchaEnabled": captchaEnabled,
|
||||
}))
|
||||
return
|
||||
}
|
||||
|
||||
// 生成唯一标识
|
||||
verifyKey := ""
|
||||
data := map[string]any{
|
||||
"captchaEnabled": captchaEnabled,
|
||||
"uuid": "",
|
||||
"img": "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
|
||||
}
|
||||
|
||||
// char 字符验证
|
||||
driverCaptcha := &base64Captcha.DriverString{
|
||||
//Height png height in pixel.
|
||||
Height: 40,
|
||||
// Width Captcha png width in pixel.
|
||||
Width: 120,
|
||||
//NoiseCount text noise count.
|
||||
NoiseCount: 4,
|
||||
//Length random string length.
|
||||
Length: 4,
|
||||
//Source is a unicode which is the rand string from.
|
||||
Source: "023456789abcdefghjkmnprstuvwxyz",
|
||||
//ShowLineOptions := OptionShowHollowLine | OptionShowSlimeLine | OptionShowSineLine .
|
||||
ShowLineOptions: base64Captcha.OptionShowHollowLine,
|
||||
//BgColor captcha image background color (optional)
|
||||
BgColor: &color.RGBA{
|
||||
R: 250,
|
||||
G: 250,
|
||||
B: 250,
|
||||
A: 255, // 不透明
|
||||
},
|
||||
}
|
||||
// 验证码生成
|
||||
id, question, answer := driverCaptcha.GenerateIdQuestionAnswer()
|
||||
// 验证码表达式解析输出
|
||||
item, err := driverCaptcha.DrawCaptcha(question)
|
||||
if err != nil {
|
||||
log.Infof("Generate Id Question Answer %s : %v", question, err)
|
||||
} else {
|
||||
data["uuid"] = id
|
||||
data["img"] = item.EncodeB64string()
|
||||
verifyKey = cachekey.CAPTCHA_CODE_KEY + id
|
||||
cache.SetLocalTTL(verifyKey, answer, 120*time.Second)
|
||||
}
|
||||
|
||||
// 本地开发下返回验证码结果,方便接口调试
|
||||
// text, ok := cache.GetLocalTTL(verifyKey)
|
||||
// if ok {
|
||||
// data["text"] = text.(string)
|
||||
// }
|
||||
|
||||
ctx.JSON(w, 200, result.Ok(data))
|
||||
}
|
||||
|
||||
// 登录用户信息
|
||||
func UserInfo(w http.ResponseWriter, r *http.Request) {
|
||||
loginUser, err := ctx.LoginUser(r)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.OkData(err.Error()))
|
||||
}
|
||||
// 角色权限集合,管理员拥有所有权限
|
||||
userId := fmt.Sprint(loginUser.UserID)
|
||||
isAdmin := srcConfig.IsAdmin(userId)
|
||||
roles, perms := service.NewServiceAccount.RoleAndMenuPerms(userId, isAdmin)
|
||||
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"user": loginUser.User,
|
||||
"roles": roles,
|
||||
"permissions": perms,
|
||||
}))
|
||||
}
|
||||
|
||||
// 登录用户路由信息
|
||||
func Routers(w http.ResponseWriter, r *http.Request) {
|
||||
userID := ctx.LoginUserToUserID(r)
|
||||
|
||||
// 前端路由,管理员拥有所有
|
||||
isAdmin := srcConfig.IsAdmin(userID)
|
||||
buildMenus := service.NewServiceAccount.RouteMenus(userID, isAdmin)
|
||||
ctx.JSON(w, 200, result.OkData(buildMenus))
|
||||
}
|
||||
|
||||
// 鉴权登录接口
|
||||
var UriOauthToken = "/api/rest/securityManagement/{apiVersion}/oauth/token"
|
||||
|
||||
// 鉴权登录接口
|
||||
func OauthToken(w http.ResponseWriter, r *http.Request) {
|
||||
language := ctx.AcceptLanguage(r)
|
||||
var querys struct {
|
||||
Group string `form:"group" binding:"required"`
|
||||
Type string `form:"type" binding:"omitempty,oneof=node edge combo"`
|
||||
}
|
||||
if err := ctx.ShouldBindQuery(r, &querys); err != nil {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
apiVersion := ctx.Param(r, "apiVersion")
|
||||
if apiVersion == "v1" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
menuService "nms_cxy/features/sys_menu/service"
|
||||
roleService "nms_cxy/features/sys_role/service"
|
||||
userService "nms_cxy/features/sys_user/service"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/core/vo"
|
||||
)
|
||||
|
||||
// 实例化服务层 ServiceAccount 结构体
|
||||
var NewServiceAccount = &ServiceAccount{
|
||||
sysUserService: userService.NewServiceSysUser,
|
||||
sysRoleService: roleService.NewServiceSysRole,
|
||||
sysMenuService: menuService.NewServiceSysMenu,
|
||||
}
|
||||
|
||||
// 账号身份操作服务 服务层处理
|
||||
type ServiceAccount struct {
|
||||
// 用户信息服务
|
||||
sysUserService *userService.ServiceSysUser
|
||||
// 角色服务
|
||||
sysRoleService *roleService.ServiceSysRole
|
||||
// 菜单服务
|
||||
sysMenuService *menuService.ServiceSysMenu
|
||||
}
|
||||
|
||||
// RoleAndMenuPerms 角色和菜单数据权限
|
||||
func (s *ServiceAccount) RoleAndMenuPerms(userId string, isAdmin bool) ([]string, []string) {
|
||||
if isAdmin {
|
||||
return []string{"admin"}, []string{"*:*:*"}
|
||||
} else {
|
||||
// 角色key
|
||||
roleGroup := []string{}
|
||||
roles := s.sysRoleService.SelectRoleListByUserId(userId)
|
||||
for _, role := range roles {
|
||||
roleGroup = append(roleGroup, role.RoleKey)
|
||||
}
|
||||
// 菜单权限key
|
||||
perms := s.sysMenuService.SelectMenuPermsByUserId(userId)
|
||||
return parse.RemoveDuplicates(roleGroup), parse.RemoveDuplicates(perms)
|
||||
}
|
||||
}
|
||||
|
||||
// RouteMenus 前端路由所需要的菜单
|
||||
func (s *ServiceAccount) RouteMenus(userId string, isAdmin bool) []vo.Router {
|
||||
var buildMenus []vo.Router
|
||||
if isAdmin {
|
||||
menus := s.sysMenuService.SelectMenuTreeByUserId("*")
|
||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||||
} else {
|
||||
menus := s.sysMenuService.SelectMenuTreeByUserId(userId)
|
||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||||
}
|
||||
return buildMenus
|
||||
}
|
||||
@@ -510,7 +510,7 @@ func GetOneSysinfoFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
if systemState.OsInfo != "" {
|
||||
osInfo = systemState.OsInfo
|
||||
}
|
||||
dbInfo := "adb v1.0.1"
|
||||
dbInfo := "kvdb v1.0.1"
|
||||
if systemState.OsInfo != "" {
|
||||
dbInfo = systemState.DbInfo
|
||||
}
|
||||
@@ -656,7 +656,7 @@ func GetAllSysinfoFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
if systemState.OsInfo != "" {
|
||||
osInfo = systemState.OsInfo
|
||||
}
|
||||
dbInfo := "adb v1.0.1"
|
||||
dbInfo := "kvdb v1.0.1"
|
||||
if systemState.OsInfo != "" {
|
||||
dbInfo = systemState.DbInfo
|
||||
}
|
||||
@@ -857,7 +857,8 @@ func GetStateFromNFOld(w http.ResponseWriter, r *http.Request) {
|
||||
case "all":
|
||||
// query all NFs
|
||||
// create rest client
|
||||
restHostPort := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port)
|
||||
|
||||
restHostPort := config.GetOMCHostUrl()
|
||||
getNeInfoPattern := fmt.Sprintf(config.DefaultUriPrefix+"/databaseManagement/v1/elementType/%s/objectType/ne_info",
|
||||
config.GetYamlConfig().Database.Name)
|
||||
getNeInfoURI := restHostPort + getNeInfoPattern + "?WHERE=status+in+('0','3')"
|
||||
@@ -878,7 +879,7 @@ func GetStateFromNFOld(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
neList, _ = dborm.XormParseResult(resp.Body())
|
||||
default:
|
||||
restHostPort := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port)
|
||||
restHostPort := config.GetOMCHostUrl()
|
||||
getNeInfoPattern := fmt.Sprintf(config.DefaultUriPrefix+"/databaseManagement/v1/elementType/%s/objectType/ne_info",
|
||||
config.GetYamlConfig().Database.Name)
|
||||
getNeInfoURI := restHostPort + getNeInfoPattern
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
package sysconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/sys_config/model"
|
||||
"nms_cxy/features/sys_config/service"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/core/vo/result"
|
||||
"nms_cxy/lib/midware"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
)
|
||||
|
||||
// 参数配置信息接口添加到路由
|
||||
func Routers() []services.RouterItem {
|
||||
// 实例化控制层 SysConfigApi 结构体
|
||||
var apis = &SysConfigApi{
|
||||
sysConfigService: service.NewServiceSysConfig,
|
||||
}
|
||||
|
||||
rs := [...]services.RouterItem{
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/configs",
|
||||
Handler: apis.List,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/config/{configId}",
|
||||
Handler: apis.Info,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "POST",
|
||||
Pattern: "/config",
|
||||
Handler: apis.Add,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/config",
|
||||
Handler: apis.Edit,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "DELETE",
|
||||
Pattern: "/config/{configIds}",
|
||||
Handler: apis.Remove,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/config/refreshCache",
|
||||
Handler: apis.RefreshCache,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/config/configKey/{configKey}",
|
||||
Handler: apis.ConfigKey,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
// 添加更多的 Router 对象...
|
||||
}
|
||||
|
||||
// 生成两组前缀路由
|
||||
rsPrefix := []services.RouterItem{}
|
||||
for _, v := range rs {
|
||||
path := "/configManage/{apiVersion}" + v.Pattern
|
||||
// 固定前缀
|
||||
v.Pattern = config.DefaultUriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
// 可配置
|
||||
v.Pattern = config.UriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
}
|
||||
return rsPrefix
|
||||
}
|
||||
|
||||
// 参数配置信息
|
||||
//
|
||||
// PATH /configManage
|
||||
type SysConfigApi struct {
|
||||
// 参数配置服务
|
||||
sysConfigService *service.ServiceSysConfig
|
||||
}
|
||||
|
||||
// 参数配置列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *SysConfigApi) List(w http.ResponseWriter, r *http.Request) {
|
||||
querys := ctx.QueryMap(r)
|
||||
data := s.sysConfigService.SelectConfigPage(querys)
|
||||
ctx.JSON(w, 200, result.Ok(data))
|
||||
}
|
||||
|
||||
// 参数配置信息
|
||||
//
|
||||
// GET /:configId
|
||||
func (s *SysConfigApi) Info(w http.ResponseWriter, r *http.Request) {
|
||||
configId := ctx.Param(r, "configId")
|
||||
if configId == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
data := s.sysConfigService.SelectConfigById(configId)
|
||||
if data.ConfigID == configId {
|
||||
ctx.JSON(w, 200, result.OkData(data))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 参数配置新增
|
||||
//
|
||||
// POST /
|
||||
func (s *SysConfigApi) Add(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysConfig
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.ConfigID != "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查属性值唯一
|
||||
uniqueConfigKey := s.sysConfigService.CheckUniqueConfigKey(body.ConfigKey, "")
|
||||
if !uniqueConfigKey {
|
||||
msg := fmt.Sprintf("[%s] Parameter key name already exists", body.ConfigKey)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
||||
insertId := s.sysConfigService.InsertConfig(body)
|
||||
if insertId != "" {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 参数配置修改
|
||||
//
|
||||
// PUT /
|
||||
func (s *SysConfigApi) Edit(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysConfig
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.ConfigID == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查属性值唯一
|
||||
uniqueConfigKey := s.sysConfigService.CheckUniqueConfigKey(body.ConfigKey, body.ConfigID)
|
||||
if !uniqueConfigKey {
|
||||
msg := fmt.Sprintf("[%s] Parameter key name already exists", body.ConfigKey)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否存在
|
||||
config := s.sysConfigService.SelectConfigById(body.ConfigID)
|
||||
if config.ConfigID != body.ConfigID {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access parameter configuration data!"))
|
||||
return
|
||||
}
|
||||
|
||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
||||
rows := s.sysConfigService.UpdateConfig(body)
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 参数配置删除
|
||||
//
|
||||
// DELETE /:configIds
|
||||
func (s *SysConfigApi) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
configIds := ctx.Param(r, "configIds")
|
||||
if configIds == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
// 处理字符转id数组后去重
|
||||
ids := strings.Split(configIds, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
rows, err := s.sysConfigService.DeleteConfigByIds(uniqueIDs)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
msg := fmt.Sprintf("删除成功:%d", rows)
|
||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// 参数配置刷新缓存
|
||||
//
|
||||
// PUT /refreshCache
|
||||
func (s *SysConfigApi) RefreshCache(w http.ResponseWriter, r *http.Request) {
|
||||
s.sysConfigService.ResetConfigCache()
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
}
|
||||
|
||||
// 参数配置根据参数键名
|
||||
//
|
||||
// GET /configKey/:configKey
|
||||
func (s *SysConfigApi) ConfigKey(w http.ResponseWriter, r *http.Request) {
|
||||
configKey := ctx.Param(r, "configKey")
|
||||
if configKey == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
key := s.sysConfigService.SelectConfigValueByKey(configKey)
|
||||
if key != "" {
|
||||
ctx.JSON(w, 200, result.OkData(key))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package model
|
||||
|
||||
// 参数配置对象 sys_config
|
||||
type SysConfig struct {
|
||||
// 参数主键
|
||||
ConfigID string `json:"configId"`
|
||||
// 参数名称
|
||||
ConfigName string `json:"configName" binding:"required"`
|
||||
// 参数键名
|
||||
ConfigKey string `json:"configKey" binding:"required"`
|
||||
// 参数键值
|
||||
ConfigValue string `json:"configValue" binding:"required"`
|
||||
// 系统内置(Y是 N否)
|
||||
ConfigType string `json:"configType"`
|
||||
// 创建者
|
||||
CreateBy string `json:"createBy"`
|
||||
// 创建时间
|
||||
CreateTime int64 `json:"createTime"`
|
||||
// 更新者
|
||||
UpdateBy string `json:"updateBy"`
|
||||
// 更新时间
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
// 备注
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
@@ -1,336 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/features/sys_config/model"
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/date"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoSysConfig 结构体
|
||||
var NewRepoSysConfig = &RepoSysConfig{
|
||||
selectSql: `select
|
||||
config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark
|
||||
from sys_config`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"config_id": "ConfigID",
|
||||
"config_name": "ConfigName",
|
||||
"config_key": "ConfigKey",
|
||||
"config_value": "ConfigValue",
|
||||
"config_type": "ConfigType",
|
||||
"remark": "Remark",
|
||||
"create_by": "CreateBy",
|
||||
"create_time": "CreateTime",
|
||||
"update_by": "UpdateBy",
|
||||
"update_time": "UpdateTime",
|
||||
},
|
||||
}
|
||||
|
||||
// RepoSysConfig 参数配置表 数据层处理
|
||||
type RepoSysConfig struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *RepoSysConfig) convertResultRows(rows []map[string]any) []model.SysConfig {
|
||||
arr := make([]model.SysConfig, 0)
|
||||
for _, row := range rows {
|
||||
sysConfig := model.SysConfig{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
datasource.SetFieldValue(&sysConfig, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, sysConfig)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectDictDataPage 分页查询参数配置列表数据
|
||||
func (r *RepoSysConfig) SelectConfigPage(query map[string]any) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if v, ok := query["configName"]; ok && v != "" {
|
||||
conditions = append(conditions, "config_name like concat(?, '%')")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["configType"]; ok && v != "" {
|
||||
conditions = append(conditions, "config_type = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["configKey"]; ok && v != "" {
|
||||
conditions = append(conditions, "config_key like concat(?, '%')")
|
||||
params = append(params, v)
|
||||
}
|
||||
beginTime, ok := query["beginTime"]
|
||||
if !ok {
|
||||
beginTime, ok = query["params[beginTime]"]
|
||||
}
|
||||
if ok && beginTime != "" {
|
||||
conditions = append(conditions, "create_time >= ?")
|
||||
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
|
||||
params = append(params, beginDate.UnixMilli())
|
||||
}
|
||||
endTime, ok := query["endTime"]
|
||||
if !ok {
|
||||
endTime, ok = query["params[endTime]"]
|
||||
}
|
||||
if ok && endTime != "" {
|
||||
conditions = append(conditions, "create_time <= ?")
|
||||
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
|
||||
params = append(params, endDate.UnixMilli())
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from sys_config"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
log.Errorf("total err => %v", err)
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": []model.SysConfig{},
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": rows,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectConfigList 查询参数配置列表
|
||||
func (r *RepoSysConfig) SelectConfigList(sysConfig model.SysConfig) []model.SysConfig {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysConfig.ConfigName != "" {
|
||||
conditions = append(conditions, "config_name like concat(?, '%')")
|
||||
params = append(params, sysConfig.ConfigName)
|
||||
}
|
||||
if sysConfig.ConfigType != "" {
|
||||
conditions = append(conditions, "config_type = ?")
|
||||
params = append(params, sysConfig.ConfigType)
|
||||
}
|
||||
if sysConfig.ConfigKey != "" {
|
||||
conditions = append(conditions, "config_key like concat(?, '%')")
|
||||
params = append(params, sysConfig.ConfigKey)
|
||||
}
|
||||
if sysConfig.CreateTime > 0 {
|
||||
conditions = append(conditions, "create_time >= ?")
|
||||
params = append(params, sysConfig.CreateTime)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysConfig{}
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectConfigValueByKey 通过参数键名查询参数键值
|
||||
func (r *RepoSysConfig) SelectConfigValueByKey(configKey string) string {
|
||||
querySql := "select config_value as 'str' from sys_config where config_key = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{configKey})
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return ""
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return fmt.Sprint(results[0]["str"])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SelectConfigByIds 通过配置ID查询参数配置信息
|
||||
func (r *RepoSysConfig) SelectConfigByIds(configIds []string) []model.SysConfig {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(configIds))
|
||||
querySql := r.selectSql + " where config_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(configIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysConfig{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// CheckUniqueConfig 校验配置参数是否唯一
|
||||
func (r *RepoSysConfig) CheckUniqueConfig(sysConfig model.SysConfig) string {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysConfig.ConfigKey != "" {
|
||||
conditions = append(conditions, "config_key = ?")
|
||||
params = append(params, sysConfig.ConfigKey)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := "select config_id as 'str' from sys_config " + whereSql + " limit 1"
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err %v", err)
|
||||
return ""
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return fmt.Sprint(results[0]["str"])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// InsertConfig 新增参数配置
|
||||
func (r *RepoSysConfig) InsertConfig(sysConfig model.SysConfig) string {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysConfig.ConfigName != "" {
|
||||
params["config_name"] = sysConfig.ConfigName
|
||||
}
|
||||
if sysConfig.ConfigKey != "" {
|
||||
params["config_key"] = sysConfig.ConfigKey
|
||||
}
|
||||
if sysConfig.ConfigValue != "" {
|
||||
params["config_value"] = sysConfig.ConfigValue
|
||||
}
|
||||
if sysConfig.ConfigType != "" {
|
||||
params["config_type"] = sysConfig.ConfigType
|
||||
}
|
||||
if sysConfig.Remark != "" {
|
||||
params["remark"] = sysConfig.Remark
|
||||
}
|
||||
if sysConfig.CreateBy != "" {
|
||||
params["create_by"] = sysConfig.CreateBy
|
||||
params["create_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
||||
sql := "insert into sys_config (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
||||
|
||||
// 执行插入
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
|
||||
insertId, err := results.LastInsertId()
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(insertId)
|
||||
}
|
||||
|
||||
// UpdateConfig 修改参数配置
|
||||
func (r *RepoSysConfig) UpdateConfig(sysConfig model.SysConfig) int64 {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysConfig.ConfigName != "" {
|
||||
params["config_name"] = sysConfig.ConfigName
|
||||
}
|
||||
if sysConfig.ConfigKey != "" {
|
||||
params["config_key"] = sysConfig.ConfigKey
|
||||
}
|
||||
if sysConfig.ConfigValue != "" {
|
||||
params["config_value"] = sysConfig.ConfigValue
|
||||
}
|
||||
if sysConfig.ConfigType != "" {
|
||||
params["config_type"] = sysConfig.ConfigType
|
||||
}
|
||||
if sysConfig.Remark != "" {
|
||||
params["remark"] = sysConfig.Remark
|
||||
}
|
||||
if sysConfig.UpdateBy != "" {
|
||||
params["update_by"] = sysConfig.UpdateBy
|
||||
params["update_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, values := datasource.KeyValueByUpdate(params)
|
||||
sql := "update sys_config set " + strings.Join(keys, ",") + " where config_id = ?"
|
||||
|
||||
// 执行更新
|
||||
values = append(values, sysConfig.ConfigID)
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("update row : %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("update err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// DeleteConfigByIds 批量删除参数配置信息
|
||||
func (r *RepoSysConfig) DeleteConfigByIds(configIds []string) int64 {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(configIds))
|
||||
sql := "delete from sys_config where config_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(configIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"nms_cxy/features/sys_config/model"
|
||||
"nms_cxy/lib/core/cache"
|
||||
"nms_cxy/lib/core/constants/cachekey"
|
||||
)
|
||||
|
||||
// 实例化服务层 ServiceSysConfig 结构体
|
||||
var NewServiceSysConfig = &ServiceSysConfig{
|
||||
sysConfigRepository: NewRepoSysConfig,
|
||||
}
|
||||
|
||||
// ServiceSysConfig 参数配置 服务层处理
|
||||
type ServiceSysConfig struct {
|
||||
// 参数配置表
|
||||
sysConfigRepository *RepoSysConfig
|
||||
}
|
||||
|
||||
// SelectDictDataPage 分页查询参数配置列表数据
|
||||
func (r *ServiceSysConfig) SelectConfigPage(query map[string]any) map[string]any {
|
||||
return r.sysConfigRepository.SelectConfigPage(query)
|
||||
}
|
||||
|
||||
// SelectConfigList 查询参数配置列表
|
||||
func (r *ServiceSysConfig) SelectConfigList(sysConfig model.SysConfig) []model.SysConfig {
|
||||
return r.sysConfigRepository.SelectConfigList(sysConfig)
|
||||
}
|
||||
|
||||
// SelectConfigValueByKey 通过参数键名查询参数键值
|
||||
func (r *ServiceSysConfig) SelectConfigValueByKey(configKey string) string {
|
||||
cacheKey := r.getCacheKey(configKey)
|
||||
// 从缓存中读取
|
||||
cacheValue, ok := cache.GetLocal(cacheKey)
|
||||
if cacheValue != nil && ok {
|
||||
return cacheValue.(string)
|
||||
}
|
||||
// 无缓存时读取数据放入缓存中
|
||||
configValue := r.sysConfigRepository.SelectConfigValueByKey(configKey)
|
||||
if configValue != "" {
|
||||
cache.SetLocal(cacheKey, configValue)
|
||||
return configValue
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SelectConfigById 通过配置ID查询参数配置信息
|
||||
func (r *ServiceSysConfig) SelectConfigById(configId string) model.SysConfig {
|
||||
if configId == "" {
|
||||
return model.SysConfig{}
|
||||
}
|
||||
configs := r.sysConfigRepository.SelectConfigByIds([]string{configId})
|
||||
if len(configs) > 0 {
|
||||
return configs[0]
|
||||
}
|
||||
return model.SysConfig{}
|
||||
}
|
||||
|
||||
// CheckUniqueConfigKey 校验参数键名是否唯一
|
||||
func (r *ServiceSysConfig) CheckUniqueConfigKey(configKey, configId string) bool {
|
||||
uniqueId := r.sysConfigRepository.CheckUniqueConfig(model.SysConfig{
|
||||
ConfigKey: configKey,
|
||||
})
|
||||
if uniqueId == configId {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// InsertConfig 新增参数配置
|
||||
func (r *ServiceSysConfig) InsertConfig(sysConfig model.SysConfig) string {
|
||||
configId := r.sysConfigRepository.InsertConfig(sysConfig)
|
||||
if configId != "" {
|
||||
r.loadingConfigCache(sysConfig.ConfigKey)
|
||||
}
|
||||
return configId
|
||||
}
|
||||
|
||||
// UpdateConfig 修改参数配置
|
||||
func (r *ServiceSysConfig) UpdateConfig(sysConfig model.SysConfig) int64 {
|
||||
rows := r.sysConfigRepository.UpdateConfig(sysConfig)
|
||||
if rows > 0 {
|
||||
r.loadingConfigCache(sysConfig.ConfigKey)
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// DeleteConfigByIds 批量删除参数配置信息
|
||||
func (r *ServiceSysConfig) DeleteConfigByIds(configIds []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
configs := r.sysConfigRepository.SelectConfigByIds(configIds)
|
||||
if len(configs) <= 0 {
|
||||
return 0, errors.New("does not have permission to access parameter configuration data")
|
||||
}
|
||||
for _, config := range configs {
|
||||
// 检查是否为内置参数
|
||||
if config.ConfigType == "Y" {
|
||||
return 0, errors.New(config.ConfigID + " Configuration parameters are built-in parameters and their deletion is prohibited!")
|
||||
}
|
||||
// 清除缓存
|
||||
r.clearConfigCache(config.ConfigKey)
|
||||
}
|
||||
if len(configs) == len(configIds) {
|
||||
rows := r.sysConfigRepository.DeleteConfigByIds(configIds)
|
||||
return rows, nil
|
||||
}
|
||||
return 0, errors.New("failed to delete parameter configuration information")
|
||||
}
|
||||
|
||||
// ResetConfigCache 重置参数缓存数据
|
||||
func (r *ServiceSysConfig) ResetConfigCache() {
|
||||
r.clearConfigCache("*")
|
||||
r.loadingConfigCache("*")
|
||||
}
|
||||
|
||||
// getCacheKey 组装缓存key
|
||||
func (r *ServiceSysConfig) getCacheKey(configKey string) string {
|
||||
return cachekey.SYS_CONFIG_KEY + configKey
|
||||
}
|
||||
|
||||
// loadingConfigCache 加载参数缓存数据
|
||||
func (r *ServiceSysConfig) loadingConfigCache(configKey string) {
|
||||
// 查询全部参数
|
||||
if configKey == "*" {
|
||||
sysConfigs := r.SelectConfigList(model.SysConfig{})
|
||||
for _, v := range sysConfigs {
|
||||
key := r.getCacheKey(v.ConfigKey)
|
||||
cache.DeleteLocal(key)
|
||||
cache.SetLocal(key, v.ConfigValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
// 指定参数
|
||||
if configKey != "" {
|
||||
cacheValue := r.sysConfigRepository.SelectConfigValueByKey(configKey)
|
||||
if cacheValue != "" {
|
||||
key := r.getCacheKey(configKey)
|
||||
cache.DeleteLocal(key)
|
||||
cache.SetLocal(key, cacheValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// clearConfigCache 清空参数缓存数据
|
||||
func (r *ServiceSysConfig) clearConfigCache(configKey string) bool {
|
||||
key := r.getCacheKey(configKey)
|
||||
keys := cache.GetLocalKeys(key)
|
||||
for _, v := range keys {
|
||||
cache.DeleteLocal(v)
|
||||
}
|
||||
return len(keys) > 0
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
package sysdictdata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/sys_dict_data/model"
|
||||
sysDictDataService "nms_cxy/features/sys_dict_data/service"
|
||||
sysDictTypeService "nms_cxy/features/sys_dict_type/service"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/core/vo/result"
|
||||
"nms_cxy/lib/midware"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
)
|
||||
|
||||
// 字典类型对应的字典数据信息接口添加到路由
|
||||
func Routers() []services.RouterItem {
|
||||
// 实例化控制层 SysDictDataApi 结构体
|
||||
var apis = &SysDictDataApi{
|
||||
sysDictDataService: sysDictDataService.NewServiceSysDictData,
|
||||
sysDictTypeService: sysDictTypeService.NewServiceSysDictType,
|
||||
}
|
||||
|
||||
rs := [...]services.RouterItem{
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/dictDatas",
|
||||
Handler: apis.List,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/dictData/{dictCode}",
|
||||
Handler: apis.Info,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "POST",
|
||||
Pattern: "/dictData",
|
||||
Handler: apis.Add,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/dictData",
|
||||
Handler: apis.Edit,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "DELETE",
|
||||
Pattern: "/dictData/{dictCodes}",
|
||||
Handler: apis.Remove,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/dictData/type/{dictType}",
|
||||
Handler: apis.DictType,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
// 添加更多的 Router 对象...
|
||||
}
|
||||
|
||||
// 生成两组前缀路由
|
||||
rsPrefix := []services.RouterItem{}
|
||||
for _, v := range rs {
|
||||
path := "/dictDataManage/{apiVersion}" + v.Pattern
|
||||
// 固定前缀
|
||||
v.Pattern = config.DefaultUriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
// 可配置
|
||||
v.Pattern = config.UriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
}
|
||||
return rsPrefix
|
||||
}
|
||||
|
||||
// 字典类型对应的字典数据信息
|
||||
//
|
||||
// PATH /dictDataManage
|
||||
type SysDictDataApi struct {
|
||||
// 字典数据服务
|
||||
sysDictDataService *sysDictDataService.ServiceSysDictData
|
||||
// 字典类型服务
|
||||
sysDictTypeService *sysDictTypeService.ServiceSysDictType
|
||||
}
|
||||
|
||||
// 字典数据列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *SysDictDataApi) List(w http.ResponseWriter, r *http.Request) {
|
||||
querys := ctx.QueryMap(r)
|
||||
data := s.sysDictDataService.SelectDictDataPage(querys)
|
||||
ctx.JSON(w, 200, result.Ok(data))
|
||||
}
|
||||
|
||||
// 字典数据详情
|
||||
//
|
||||
// GET /:dictCode
|
||||
func (s *SysDictDataApi) Info(w http.ResponseWriter, r *http.Request) {
|
||||
dictCode := ctx.Param(r, "dictCode")
|
||||
if dictCode == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
data := s.sysDictDataService.SelectDictDataByCode(dictCode)
|
||||
if data.DictCode == dictCode {
|
||||
ctx.JSON(w, 200, result.OkData(data))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 字典数据新增
|
||||
//
|
||||
// POST /
|
||||
func (s *SysDictDataApi) Add(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysDictData
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.DictCode != "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典类型是否存在
|
||||
sysDictType := s.sysDictTypeService.SelectDictTypeByType(body.DictType)
|
||||
if sysDictType.DictType != body.DictType {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary type data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典标签唯一
|
||||
uniqueDictLabel := s.sysDictDataService.CheckUniqueDictLabel(body.DictType, body.DictLabel, "")
|
||||
if !uniqueDictLabel {
|
||||
msg := fmt.Sprintf("[%s] The subscript signature of this dictionary type already exists", body.DictLabel)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典键值唯一
|
||||
uniqueDictValue := s.sysDictDataService.CheckUniqueDictValue(body.DictType, body.DictValue, "")
|
||||
if !uniqueDictValue {
|
||||
msg := fmt.Sprintf("[%s] The label value under this dictionary type already exists", body.DictValue)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
||||
insertId := s.sysDictDataService.InsertDictData(body)
|
||||
if insertId != "" {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 字典类型修改
|
||||
//
|
||||
// PUT /
|
||||
func (s *SysDictDataApi) Edit(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysDictData
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.DictCode == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典类型是否存在
|
||||
sysDictType := s.sysDictTypeService.SelectDictTypeByType(body.DictType)
|
||||
if sysDictType.DictType != body.DictType {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary type data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典编码是否存在
|
||||
SysDictDataApi := s.sysDictDataService.SelectDictDataByCode(body.DictCode)
|
||||
if SysDictDataApi.DictCode != body.DictCode {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary encoding data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典标签唯一
|
||||
uniqueDictLabel := s.sysDictDataService.CheckUniqueDictLabel(body.DictType, body.DictLabel, body.DictCode)
|
||||
if !uniqueDictLabel {
|
||||
msg := fmt.Sprintf("Data modification failed for [%s], the dictionary type subscript signature already exists", body.DictLabel)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典键值唯一
|
||||
uniqueDictValue := s.sysDictDataService.CheckUniqueDictValue(body.DictType, body.DictValue, body.DictCode)
|
||||
if !uniqueDictValue {
|
||||
msg := fmt.Sprintf("Data modification failed for [%s], label value already exists under this dictionary type", body.DictValue)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
||||
rows := s.sysDictDataService.UpdateDictData(body)
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 字典数据删除
|
||||
//
|
||||
// DELETE /:dictCodes
|
||||
func (s *SysDictDataApi) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
dictCodes := ctx.Param(r, "dictCodes")
|
||||
if dictCodes == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
// 处理字符转id数组后去重
|
||||
ids := strings.Split(dictCodes, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
rows, err := s.sysDictDataService.DeleteDictDataByCodes(uniqueIDs)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// 字典数据列表(指定字典类型)
|
||||
//
|
||||
// GET /type/:dictType
|
||||
func (s *SysDictDataApi) DictType(w http.ResponseWriter, r *http.Request) {
|
||||
dictType := ctx.Param(r, "dictType")
|
||||
if dictType == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
data := s.sysDictDataService.SelectDictDataByType(dictType)
|
||||
ctx.JSON(w, 200, result.OkData(data))
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package model
|
||||
|
||||
// SysDictData 字典数据对象 sys_dict_data
|
||||
type SysDictData struct {
|
||||
// 字典编码
|
||||
DictCode string `json:"dictCode"`
|
||||
// 字典排序
|
||||
DictSort int `json:"dictSort"`
|
||||
// 字典标签
|
||||
DictLabel string `json:"dictLabel" binding:"required"`
|
||||
// 字典键值
|
||||
DictValue string `json:"dictValue" binding:"required"`
|
||||
// 字典类型
|
||||
DictType string `json:"dictType" binding:"required"`
|
||||
// 样式属性(样式扩展)
|
||||
TagClass string `json:"tagClass"`
|
||||
// 标签类型(预设颜色)
|
||||
TagType string `json:"tagType"`
|
||||
// 状态(0停用 1正常)
|
||||
Status string `json:"status"`
|
||||
// 创建者
|
||||
CreateBy string `json:"createBy"`
|
||||
// 创建时间
|
||||
CreateTime int64 `json:"createTime"`
|
||||
// 更新者
|
||||
UpdateBy string `json:"updateBy"`
|
||||
// 更新时间
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
// 备注
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
@@ -1,369 +0,0 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/features/sys_dict_data/model"
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoSysDictData 结构体
|
||||
var NewRepoSysDictData = &RepoSysDictData{
|
||||
selectSql: `select
|
||||
dict_code, dict_sort, dict_label, dict_value, dict_type, tag_class, tag_type, status, create_by, create_time, remark
|
||||
from sys_dict_data`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"dict_code": "DictCode",
|
||||
"dict_sort": "DictSort",
|
||||
"dict_label": "DictLabel",
|
||||
"dict_value": "DictValue",
|
||||
"dict_type": "DictType",
|
||||
"tag_class": "TagClass",
|
||||
"tag_type": "TagType",
|
||||
"status": "Status",
|
||||
"remark": "Remark",
|
||||
"create_by": "CreateBy",
|
||||
"create_time": "CreateTime",
|
||||
"update_by": "UpdateBy",
|
||||
"update_time": "UpdateTime",
|
||||
},
|
||||
}
|
||||
|
||||
// RepoSysDictData 字典类型数据表 数据层处理
|
||||
type RepoSysDictData struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *RepoSysDictData) convertResultRows(rows []map[string]any) []model.SysDictData {
|
||||
arr := make([]model.SysDictData, 0)
|
||||
for _, row := range rows {
|
||||
sysDictData := model.SysDictData{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
datasource.SetFieldValue(&sysDictData, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, sysDictData)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectDictDataPage 根据条件分页查询字典数据
|
||||
func (r *RepoSysDictData) SelectDictDataPage(query map[string]any) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if v, ok := query["dictType"]; ok && v != "" {
|
||||
conditions = append(conditions, "dict_type = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["dictLabel"]; ok && v != "" {
|
||||
conditions = append(conditions, "dict_label like concat(?, '%')")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["status"]; ok && v != "" {
|
||||
conditions = append(conditions, "status = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from sys_dict_data"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
log.Errorf("total err => %v", err)
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": []model.SysDictData{},
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " order by dict_sort asc limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": rows,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectDictDataList 根据条件查询字典数据
|
||||
func (r *RepoSysDictData) SelectDictDataList(sysDictData model.SysDictData) []model.SysDictData {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysDictData.DictLabel != "" {
|
||||
conditions = append(conditions, "dict_label like concat(?, '%')")
|
||||
params = append(params, sysDictData.DictLabel)
|
||||
}
|
||||
if sysDictData.DictType != "" {
|
||||
conditions = append(conditions, "dict_type = ?")
|
||||
params = append(params, sysDictData.DictType)
|
||||
}
|
||||
if sysDictData.Status != "" {
|
||||
conditions = append(conditions, "status = ?")
|
||||
params = append(params, sysDictData.Status)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
orderSql := " order by dict_sort asc "
|
||||
querySql := r.selectSql + whereSql + orderSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysDictData{}
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectDictDataByCodes 根据字典数据编码查询信息
|
||||
func (r *RepoSysDictData) SelectDictDataByCodes(dictCodes []string) []model.SysDictData {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(dictCodes))
|
||||
querySql := r.selectSql + " where dict_code in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(dictCodes)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysDictData{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// CountDictDataByType 查询字典数据
|
||||
func (r *RepoSysDictData) CountDictDataByType(dictType string) int64 {
|
||||
querySql := "select count(1) as 'total' from sys_dict_data where dict_type = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{dictType})
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return 0
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return parse.Number(results[0]["total"])
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// CheckUniqueDictData 校验字典数据是否唯一
|
||||
func (r *RepoSysDictData) CheckUniqueDictData(sysDictData model.SysDictData) string {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysDictData.DictType != "" {
|
||||
conditions = append(conditions, "dict_type = ?")
|
||||
params = append(params, sysDictData.DictType)
|
||||
}
|
||||
if sysDictData.DictLabel != "" {
|
||||
conditions = append(conditions, "dict_label = ?")
|
||||
params = append(params, sysDictData.DictLabel)
|
||||
}
|
||||
if sysDictData.DictValue != "" {
|
||||
conditions = append(conditions, "dict_value = ?")
|
||||
params = append(params, sysDictData.DictValue)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := "select dict_code as 'str' from sys_dict_data " + whereSql + " limit 1"
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err %v", err)
|
||||
return ""
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return fmt.Sprint(results[0]["str"])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// DeleteDictDataByCodes 批量删除字典数据信息
|
||||
func (r *RepoSysDictData) DeleteDictDataByCodes(dictCodes []string) int64 {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(dictCodes))
|
||||
sql := "delete from sys_dict_data where dict_code in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(dictCodes)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// InsertDictData 新增字典数据信息
|
||||
func (r *RepoSysDictData) InsertDictData(sysDictData model.SysDictData) string {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysDictData.DictSort > 0 {
|
||||
params["dict_sort"] = sysDictData.DictSort
|
||||
}
|
||||
if sysDictData.DictLabel != "" {
|
||||
params["dict_label"] = sysDictData.DictLabel
|
||||
}
|
||||
if sysDictData.DictValue != "" {
|
||||
params["dict_value"] = sysDictData.DictValue
|
||||
}
|
||||
if sysDictData.DictType != "" {
|
||||
params["dict_type"] = sysDictData.DictType
|
||||
}
|
||||
if sysDictData.TagClass != "" {
|
||||
params["tag_class"] = sysDictData.TagClass
|
||||
}
|
||||
if sysDictData.TagType != "" {
|
||||
params["tag_type"] = sysDictData.TagType
|
||||
}
|
||||
if sysDictData.Status != "" {
|
||||
params["status"] = sysDictData.Status
|
||||
}
|
||||
if sysDictData.Remark != "" {
|
||||
params["remark"] = sysDictData.Remark
|
||||
}
|
||||
if sysDictData.CreateBy != "" {
|
||||
params["create_by"] = sysDictData.CreateBy
|
||||
params["create_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
||||
sql := "insert into sys_dict_data (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
||||
|
||||
// 执行插入
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
insertId, err := results.LastInsertId()
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(insertId)
|
||||
}
|
||||
|
||||
// UpdateDictData 修改字典数据信息
|
||||
func (r *RepoSysDictData) UpdateDictData(sysDictData model.SysDictData) int64 {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysDictData.DictSort > 0 {
|
||||
params["dict_sort"] = sysDictData.DictSort
|
||||
}
|
||||
if sysDictData.DictLabel != "" {
|
||||
params["dict_label"] = sysDictData.DictLabel
|
||||
}
|
||||
if sysDictData.DictValue != "" {
|
||||
params["dict_value"] = sysDictData.DictValue
|
||||
}
|
||||
if sysDictData.DictType != "" {
|
||||
params["dict_type"] = sysDictData.DictType
|
||||
}
|
||||
if sysDictData.TagClass != "" {
|
||||
params["tag_class"] = sysDictData.TagClass
|
||||
}
|
||||
if sysDictData.TagType != "" {
|
||||
params["tag_type"] = sysDictData.TagType
|
||||
}
|
||||
if sysDictData.Status != "" {
|
||||
params["status"] = sysDictData.Status
|
||||
}
|
||||
if sysDictData.Remark != "" {
|
||||
params["remark"] = sysDictData.Remark
|
||||
}
|
||||
if sysDictData.UpdateBy != "" {
|
||||
params["update_by"] = sysDictData.UpdateBy
|
||||
params["update_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, values := datasource.KeyValueByUpdate(params)
|
||||
sql := "update sys_dict_data set " + strings.Join(keys, ",") + " where dict_code = ?"
|
||||
|
||||
// 执行更新
|
||||
values = append(values, sysDictData.DictCode)
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("update row : %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("update err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// UpdateDictDataType 同步修改字典类型
|
||||
func (r *RepoSysDictData) UpdateDictDataType(oldDictType string, newDictType string) int64 {
|
||||
// 参数拼接
|
||||
params := make([]any, 0)
|
||||
if oldDictType == "" || newDictType == "" {
|
||||
return 0
|
||||
}
|
||||
params = append(params, newDictType)
|
||||
params = append(params, oldDictType)
|
||||
|
||||
// 构建执行语句
|
||||
sql := "update sys_dict_data set dict_type = ? where dict_type = ?"
|
||||
|
||||
// 执行更新
|
||||
results, err := datasource.ExecDB("", sql, params)
|
||||
if err != nil {
|
||||
log.Errorf("update row : %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("update err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"nms_cxy/features/sys_dict_data/model"
|
||||
"nms_cxy/features/sys_dict_data/repo"
|
||||
sysDictTypeService "nms_cxy/features/sys_dict_type/service"
|
||||
)
|
||||
|
||||
// 实例化服务层 ServiceSysDictData 结构体
|
||||
var NewServiceSysDictData = &ServiceSysDictData{
|
||||
sysDictDataRepository: *repo.NewRepoSysDictData,
|
||||
sysDictTypeService: *sysDictTypeService.NewServiceSysDictType,
|
||||
}
|
||||
|
||||
// ServiceSysDictData 字典类型数据 服务层处理
|
||||
type ServiceSysDictData struct {
|
||||
// 字典数据服务
|
||||
sysDictDataRepository repo.RepoSysDictData
|
||||
// 字典类型服务
|
||||
sysDictTypeService sysDictTypeService.ServiceSysDictType
|
||||
}
|
||||
|
||||
// SelectDictDataPage 根据条件分页查询字典数据
|
||||
func (r *ServiceSysDictData) SelectDictDataPage(query map[string]any) map[string]any {
|
||||
return r.sysDictDataRepository.SelectDictDataPage(query)
|
||||
}
|
||||
|
||||
// SelectDictDataList 根据条件查询字典数据
|
||||
func (r *ServiceSysDictData) SelectDictDataList(sysDictData model.SysDictData) []model.SysDictData {
|
||||
return r.sysDictDataRepository.SelectDictDataList(sysDictData)
|
||||
}
|
||||
|
||||
// SelectDictDataByCode 根据字典数据编码查询信息
|
||||
func (r *ServiceSysDictData) SelectDictDataByCode(dictCode string) model.SysDictData {
|
||||
if dictCode == "" {
|
||||
return model.SysDictData{}
|
||||
}
|
||||
dictCodes := r.sysDictDataRepository.SelectDictDataByCodes([]string{dictCode})
|
||||
if len(dictCodes) > 0 {
|
||||
return dictCodes[0]
|
||||
}
|
||||
return model.SysDictData{}
|
||||
}
|
||||
|
||||
// SelectDictDataByType 根据字典类型查询信息
|
||||
func (r *ServiceSysDictData) SelectDictDataByType(dictType string) []model.SysDictData {
|
||||
return r.sysDictTypeService.DictDataCache(dictType)
|
||||
}
|
||||
|
||||
// CheckUniqueDictLabel 校验字典标签是否唯一
|
||||
func (r *ServiceSysDictData) CheckUniqueDictLabel(dictType, dictLabel, dictCode string) bool {
|
||||
uniqueId := r.sysDictDataRepository.CheckUniqueDictData(model.SysDictData{
|
||||
DictType: dictType,
|
||||
DictLabel: dictLabel,
|
||||
})
|
||||
if uniqueId == dictCode {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// CheckUniqueDictValue 校验字典键值是否唯一
|
||||
func (r *ServiceSysDictData) CheckUniqueDictValue(dictType, dictValue, dictCode string) bool {
|
||||
uniqueId := r.sysDictDataRepository.CheckUniqueDictData(model.SysDictData{
|
||||
DictType: dictType,
|
||||
DictValue: dictValue,
|
||||
})
|
||||
if uniqueId == dictCode {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// DeleteDictDataByCodes 批量删除字典数据信息
|
||||
func (r *ServiceSysDictData) DeleteDictDataByCodes(dictCodes []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
dictDatas := r.sysDictDataRepository.SelectDictDataByCodes(dictCodes)
|
||||
if len(dictDatas) <= 0 {
|
||||
return 0, errors.New("does not have permission to access dictionary-encoded data")
|
||||
}
|
||||
if len(dictDatas) == len(dictCodes) {
|
||||
for _, v := range dictDatas {
|
||||
// 刷新缓存
|
||||
r.sysDictTypeService.ClearDictCache(v.DictType)
|
||||
r.sysDictTypeService.LoadingDictCache(v.DictType)
|
||||
}
|
||||
rows := r.sysDictDataRepository.DeleteDictDataByCodes(dictCodes)
|
||||
return rows, nil
|
||||
}
|
||||
return 0, errors.New("failed to delete dictionary data information")
|
||||
}
|
||||
|
||||
// InsertDictData 新增字典数据信息
|
||||
func (r *ServiceSysDictData) InsertDictData(sysDictData model.SysDictData) string {
|
||||
insertId := r.sysDictDataRepository.InsertDictData(sysDictData)
|
||||
if insertId != "" {
|
||||
r.sysDictTypeService.LoadingDictCache(sysDictData.DictType)
|
||||
}
|
||||
return insertId
|
||||
}
|
||||
|
||||
// UpdateDictData 修改字典数据信息
|
||||
func (r *ServiceSysDictData) UpdateDictData(sysDictData model.SysDictData) int64 {
|
||||
rows := r.sysDictDataRepository.UpdateDictData(sysDictData)
|
||||
if rows > 0 {
|
||||
r.sysDictTypeService.LoadingDictCache(sysDictData.DictType)
|
||||
}
|
||||
return rows
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
package sysdicttype
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/sys_dict_type/model"
|
||||
sysDictTypeService "nms_cxy/features/sys_dict_type/service"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/core/vo/result"
|
||||
"nms_cxy/lib/midware"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
)
|
||||
|
||||
// 字典类型信息接口添加到路由
|
||||
func Routers() []services.RouterItem {
|
||||
// 实例化控制层 SysDictTypeApi 结构体
|
||||
var apis = &SysDictTypeApi{
|
||||
sysDictTypeService: *sysDictTypeService.NewServiceSysDictType,
|
||||
}
|
||||
|
||||
rs := [...]services.RouterItem{
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/dictTypes",
|
||||
Handler: apis.List,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/dictType/{dictId}",
|
||||
Handler: apis.Info,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "POST",
|
||||
Pattern: "/dictType",
|
||||
Handler: apis.Add,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/dictType",
|
||||
Handler: apis.Edit,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "DELETE",
|
||||
Pattern: "/dictType/{dictIds}",
|
||||
Handler: apis.Remove,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/dictType/refreshCache",
|
||||
Handler: apis.RefreshCache,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/dictTypes/optionselect",
|
||||
Handler: apis.DictOptionselect,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
// 添加更多的 Router 对象...
|
||||
}
|
||||
|
||||
// 生成两组前缀路由
|
||||
rsPrefix := []services.RouterItem{}
|
||||
for _, v := range rs {
|
||||
path := "/dictTypegManage/{apiVersion}" + v.Pattern
|
||||
// 固定前缀
|
||||
v.Pattern = config.DefaultUriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
// 可配置
|
||||
v.Pattern = config.UriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
}
|
||||
return rsPrefix
|
||||
}
|
||||
|
||||
// 字典类型信息
|
||||
//
|
||||
// PATH /dictTypegManage
|
||||
type SysDictTypeApi struct {
|
||||
// 字典类型服务
|
||||
sysDictTypeService sysDictTypeService.ServiceSysDictType
|
||||
}
|
||||
|
||||
// 字典类型列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *SysDictTypeApi) List(w http.ResponseWriter, r *http.Request) {
|
||||
querys := ctx.QueryMap(r)
|
||||
data := s.sysDictTypeService.SelectDictTypePage(querys)
|
||||
ctx.JSON(w, 200, result.Ok(data))
|
||||
}
|
||||
|
||||
// 字典类型信息
|
||||
//
|
||||
// GET /:dictId
|
||||
func (s *SysDictTypeApi) Info(w http.ResponseWriter, r *http.Request) {
|
||||
dictId := ctx.Param(r, "dictId")
|
||||
if dictId == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
data := s.sysDictTypeService.SelectDictTypeByID(dictId)
|
||||
if data.DictID == dictId {
|
||||
ctx.JSON(w, 200, result.OkData(data))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 字典类型新增
|
||||
//
|
||||
// POST /
|
||||
func (s *SysDictTypeApi) Add(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysDictType
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.DictID != "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典名称唯一
|
||||
uniqueDictName := s.sysDictTypeService.CheckUniqueDictName(body.DictName, "")
|
||||
if !uniqueDictName {
|
||||
msg := fmt.Sprintf("Failed to add dictionary '%s', dictionary name already exists", body.DictName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典类型唯一
|
||||
uniqueDictType := s.sysDictTypeService.CheckUniqueDictType(body.DictType, "")
|
||||
if !uniqueDictType {
|
||||
msg := fmt.Sprintf("Failed to add dictionary '%s', dictionary type already exists", body.DictType)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
||||
insertId := s.sysDictTypeService.InsertDictType(body)
|
||||
if insertId != "" {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 字典类型修改
|
||||
//
|
||||
// PUT /
|
||||
func (s *SysDictTypeApi) Edit(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysDictType
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.DictID == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查数据是否存在
|
||||
dictInfo := s.sysDictTypeService.SelectDictTypeByID(body.DictID)
|
||||
if dictInfo.DictID != body.DictID {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary type data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典名称唯一
|
||||
uniqueDictName := s.sysDictTypeService.CheckUniqueDictName(body.DictName, body.DictID)
|
||||
if !uniqueDictName {
|
||||
msg := fmt.Sprintf("Dictionary modification failed for [%s], dictionary name already exists", body.DictName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查字典类型唯一
|
||||
uniqueDictType := s.sysDictTypeService.CheckUniqueDictType(body.DictType, body.DictID)
|
||||
if !uniqueDictType {
|
||||
msg := fmt.Sprintf("Dictionary modification failed for [%s], dictionary type already exists", body.DictType)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
||||
rows := s.sysDictTypeService.UpdateDictType(body)
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 字典类型删除
|
||||
//
|
||||
// DELETE /:dictIds
|
||||
func (s *SysDictTypeApi) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
dictIds := ctx.Param(r, "dictIds")
|
||||
if dictIds == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
// 处理字符转id数组后去重
|
||||
ids := strings.Split(dictIds, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
rows, err := s.sysDictTypeService.DeleteDictTypeByIDs(uniqueIDs)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// 字典类型刷新缓存
|
||||
//
|
||||
// PUT /refreshCache
|
||||
func (s *SysDictTypeApi) RefreshCache(w http.ResponseWriter, r *http.Request) {
|
||||
s.sysDictTypeService.ResetDictCache()
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
}
|
||||
|
||||
// 字典类型选择框列表
|
||||
//
|
||||
// GET /getDictOptionselect
|
||||
func (s *SysDictTypeApi) DictOptionselect(w http.ResponseWriter, r *http.Request) {
|
||||
data := s.sysDictTypeService.SelectDictTypeList(model.SysDictType{
|
||||
Status: "1",
|
||||
})
|
||||
|
||||
type labelValue struct {
|
||||
Label string `json:"label"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// 数据组
|
||||
arr := []labelValue{}
|
||||
for _, v := range data {
|
||||
arr = append(arr, labelValue{
|
||||
Label: v.DictName,
|
||||
Value: v.DictType,
|
||||
})
|
||||
}
|
||||
ctx.JSON(w, 200, result.OkData(arr))
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package model
|
||||
|
||||
// SysDictType 字典类型对象 sys_dict_type
|
||||
type SysDictType struct {
|
||||
// 字典主键
|
||||
DictID string `json:"dictId"`
|
||||
// 字典名称
|
||||
DictName string `json:"dictName" binding:"required"`
|
||||
// 字典类型
|
||||
DictType string `json:"dictType" binding:"required"`
|
||||
// 状态(0停用 1正常)
|
||||
Status string `json:"status"`
|
||||
// 创建者
|
||||
CreateBy string `json:"createBy"`
|
||||
// 创建时间
|
||||
CreateTime int64 `json:"createTime"`
|
||||
// 更新者
|
||||
UpdateBy string `json:"updateBy"`
|
||||
// 更新时间
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
// 备注
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
@@ -1,330 +0,0 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/features/sys_dict_type/model"
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/date"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoSysDictType 结构体
|
||||
var NewRepoSysDictType = &RepoSysDictType{
|
||||
selectSql: `select
|
||||
dict_id, dict_name, dict_type, status, create_by, create_time, remark
|
||||
from sys_dict_type`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"dict_id": "DictID",
|
||||
"dict_name": "DictName",
|
||||
"dict_type": "DictType",
|
||||
"remark": "Remark",
|
||||
"status": "Status",
|
||||
"create_by": "CreateBy",
|
||||
"create_time": "CreateTime",
|
||||
"update_by": "UpdateBy",
|
||||
"update_time": "UpdateTime",
|
||||
},
|
||||
}
|
||||
|
||||
// RepoSysDictType 字典类型表 数据层处理
|
||||
type RepoSysDictType struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *RepoSysDictType) convertResultRows(rows []map[string]any) []model.SysDictType {
|
||||
arr := make([]model.SysDictType, 0)
|
||||
for _, row := range rows {
|
||||
sysDictType := model.SysDictType{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
datasource.SetFieldValue(&sysDictType, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, sysDictType)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectDictTypePage 根据条件分页查询字典类型
|
||||
func (r *RepoSysDictType) SelectDictTypePage(query map[string]any) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if v, ok := query["dictName"]; ok && v != "" {
|
||||
conditions = append(conditions, "dict_name like concat(?, '%')")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["dictType"]; ok && v != "" {
|
||||
conditions = append(conditions, "dict_type like concat(?, '%')")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["status"]; ok && v != "" {
|
||||
conditions = append(conditions, "status = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
beginTime, ok := query["beginTime"]
|
||||
if !ok {
|
||||
beginTime, ok = query["params[beginTime]"]
|
||||
}
|
||||
if ok && beginTime != "" {
|
||||
conditions = append(conditions, "create_time >= ?")
|
||||
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
|
||||
params = append(params, beginDate.UnixMilli())
|
||||
}
|
||||
endTime, ok := query["endTime"]
|
||||
if !ok {
|
||||
endTime, ok = query["params[endTime]"]
|
||||
}
|
||||
if ok && endTime != "" {
|
||||
conditions = append(conditions, "create_time <= ?")
|
||||
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
|
||||
params = append(params, endDate.UnixMilli())
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from sys_dict_type"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
log.Errorf("total err => %v", err)
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": []model.SysDictType{},
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": rows,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectDictTypeList 根据条件查询字典类型
|
||||
func (r *RepoSysDictType) SelectDictTypeList(sysDictType model.SysDictType) []model.SysDictType {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysDictType.DictName != "" {
|
||||
conditions = append(conditions, "dict_name like concat(?, '%')")
|
||||
params = append(params, sysDictType.DictName)
|
||||
}
|
||||
if sysDictType.DictType != "" {
|
||||
conditions = append(conditions, "dict_type like concat(?, '%')")
|
||||
params = append(params, sysDictType.DictType)
|
||||
}
|
||||
if sysDictType.Status != "" {
|
||||
conditions = append(conditions, "status = ?")
|
||||
params = append(params, sysDictType.Status)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysDictType{}
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectDictTypeByIDs 根据字典类型ID查询信息
|
||||
func (r *RepoSysDictType) SelectDictTypeByIDs(dictIDs []string) []model.SysDictType {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(dictIDs))
|
||||
querySql := r.selectSql + " where dict_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(dictIDs)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysDictType{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectDictTypeByType 根据字典类型查询信息
|
||||
func (r *RepoSysDictType) SelectDictTypeByType(dictType string) model.SysDictType {
|
||||
querySql := r.selectSql + " where dict_type = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{dictType})
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return model.SysDictType{}
|
||||
}
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
if len(rows) > 0 {
|
||||
return rows[0]
|
||||
}
|
||||
return model.SysDictType{}
|
||||
}
|
||||
|
||||
// CheckUniqueDictType 校验字典是否唯一
|
||||
func (r *RepoSysDictType) CheckUniqueDictType(sysDictType model.SysDictType) string {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysDictType.DictName != "" {
|
||||
conditions = append(conditions, "dict_name = ?")
|
||||
params = append(params, sysDictType.DictName)
|
||||
}
|
||||
if sysDictType.DictType != "" {
|
||||
conditions = append(conditions, "dict_type = ?")
|
||||
params = append(params, sysDictType.DictType)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := "select dict_id as 'str' from sys_dict_type " + whereSql + " limit 1"
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err %v", err)
|
||||
return ""
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return fmt.Sprint(results[0]["str"])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// InsertDictType 新增字典类型信息
|
||||
func (r *RepoSysDictType) InsertDictType(sysDictType model.SysDictType) string {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysDictType.DictName != "" {
|
||||
params["dict_name"] = sysDictType.DictName
|
||||
}
|
||||
if sysDictType.DictType != "" {
|
||||
params["dict_type"] = sysDictType.DictType
|
||||
}
|
||||
if sysDictType.Status != "" {
|
||||
params["status"] = sysDictType.Status
|
||||
}
|
||||
if sysDictType.Remark != "" {
|
||||
params["remark"] = sysDictType.Remark
|
||||
}
|
||||
if sysDictType.CreateBy != "" {
|
||||
params["create_by"] = sysDictType.CreateBy
|
||||
params["create_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
||||
sql := "insert into sys_dict_type (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
||||
|
||||
// 执行插入
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
insertId, err := results.LastInsertId()
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(insertId)
|
||||
}
|
||||
|
||||
// UpdateDictType 修改字典类型信息
|
||||
func (r *RepoSysDictType) UpdateDictType(sysDictType model.SysDictType) int64 {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysDictType.DictName != "" {
|
||||
params["dict_name"] = sysDictType.DictName
|
||||
}
|
||||
if sysDictType.DictType != "" {
|
||||
params["dict_type"] = sysDictType.DictType
|
||||
}
|
||||
if sysDictType.Status != "" {
|
||||
params["status"] = sysDictType.Status
|
||||
}
|
||||
if sysDictType.Remark != "" {
|
||||
params["remark"] = sysDictType.Remark
|
||||
}
|
||||
if sysDictType.UpdateBy != "" {
|
||||
params["update_by"] = sysDictType.UpdateBy
|
||||
params["update_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, values := datasource.KeyValueByUpdate(params)
|
||||
sql := "update sys_dict_type set " + strings.Join(keys, ",") + " where dict_id = ?"
|
||||
|
||||
// 执行更新
|
||||
values = append(values, sysDictType.DictID)
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("update row : %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("update err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// DeleteDictTypeByIDs 批量删除字典类型信息
|
||||
func (r *RepoSysDictType) DeleteDictTypeByIDs(dictIDs []string) int64 {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(dictIDs))
|
||||
sql := "delete from sys_dict_type where dict_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(dictIDs)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
sysDictDataModel "nms_cxy/features/sys_dict_data/model"
|
||||
sysDictDataRepo "nms_cxy/features/sys_dict_data/repo"
|
||||
sysDictTypeModel "nms_cxy/features/sys_dict_type/model"
|
||||
"nms_cxy/features/sys_dict_type/repo"
|
||||
"nms_cxy/lib/core/cache"
|
||||
"nms_cxy/lib/core/constants/cachekey"
|
||||
)
|
||||
|
||||
// 实例化服务层 ServiceSysDictType 结构体
|
||||
var NewServiceSysDictType = &ServiceSysDictType{
|
||||
sysDictTypeRepository: *repo.NewRepoSysDictType,
|
||||
sysDictDataRepository: *sysDictDataRepo.NewRepoSysDictData,
|
||||
}
|
||||
|
||||
// ServiceSysDictType 字典类型 服务层处理
|
||||
type ServiceSysDictType struct {
|
||||
// 字典类型服务
|
||||
sysDictTypeRepository repo.RepoSysDictType
|
||||
// 字典数据服务
|
||||
sysDictDataRepository sysDictDataRepo.RepoSysDictData
|
||||
}
|
||||
|
||||
// SelectDictTypePage 根据条件分页查询字典类型
|
||||
func (r *ServiceSysDictType) SelectDictTypePage(query map[string]any) map[string]any {
|
||||
return r.sysDictTypeRepository.SelectDictTypePage(query)
|
||||
}
|
||||
|
||||
// SelectDictTypeList 根据条件查询字典类型
|
||||
func (r *ServiceSysDictType) SelectDictTypeList(sysDictType sysDictTypeModel.SysDictType) []sysDictTypeModel.SysDictType {
|
||||
return r.sysDictTypeRepository.SelectDictTypeList(sysDictType)
|
||||
}
|
||||
|
||||
// SelectDictTypeByID 根据字典类型ID查询信息
|
||||
func (r *ServiceSysDictType) SelectDictTypeByID(dictID string) sysDictTypeModel.SysDictType {
|
||||
if dictID == "" {
|
||||
return sysDictTypeModel.SysDictType{}
|
||||
}
|
||||
dictTypes := r.sysDictTypeRepository.SelectDictTypeByIDs([]string{dictID})
|
||||
if len(dictTypes) > 0 {
|
||||
return dictTypes[0]
|
||||
}
|
||||
return sysDictTypeModel.SysDictType{}
|
||||
}
|
||||
|
||||
// SelectDictTypeByType 根据字典类型查询信息
|
||||
func (r *ServiceSysDictType) SelectDictTypeByType(dictType string) sysDictTypeModel.SysDictType {
|
||||
return r.sysDictTypeRepository.SelectDictTypeByType(dictType)
|
||||
}
|
||||
|
||||
// CheckUniqueDictName 校验字典名称是否唯一
|
||||
func (r *ServiceSysDictType) CheckUniqueDictName(dictName, dictID string) bool {
|
||||
uniqueId := r.sysDictTypeRepository.CheckUniqueDictType(sysDictTypeModel.SysDictType{
|
||||
DictName: dictName,
|
||||
})
|
||||
if uniqueId == dictID {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// CheckUniqueDictType 校验字典类型是否唯一
|
||||
func (r *ServiceSysDictType) CheckUniqueDictType(dictType, dictID string) bool {
|
||||
uniqueId := r.sysDictTypeRepository.CheckUniqueDictType(sysDictTypeModel.SysDictType{
|
||||
DictType: dictType,
|
||||
})
|
||||
if uniqueId == dictID {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// InsertDictType 新增字典类型信息
|
||||
func (r *ServiceSysDictType) InsertDictType(sysDictType sysDictTypeModel.SysDictType) string {
|
||||
insertId := r.sysDictTypeRepository.InsertDictType(sysDictType)
|
||||
if insertId != "" {
|
||||
r.LoadingDictCache(sysDictType.DictType)
|
||||
}
|
||||
return insertId
|
||||
}
|
||||
|
||||
// UpdateDictType 修改字典类型信息
|
||||
func (r *ServiceSysDictType) UpdateDictType(sysDictType sysDictTypeModel.SysDictType) int64 {
|
||||
data := r.sysDictTypeRepository.SelectDictTypeByIDs([]string{sysDictType.DictID})
|
||||
if len(data) == 0 {
|
||||
return 0
|
||||
}
|
||||
// 修改字典类型key时同步更新其字典数据的类型key
|
||||
oldDictType := data[0].DictType
|
||||
rows := r.sysDictTypeRepository.UpdateDictType(sysDictType)
|
||||
if rows > 0 && oldDictType != "" && oldDictType != sysDictType.DictType {
|
||||
r.sysDictDataRepository.UpdateDictDataType(oldDictType, sysDictType.DictType)
|
||||
}
|
||||
// 刷新缓存
|
||||
r.ClearDictCache(oldDictType)
|
||||
r.LoadingDictCache(sysDictType.DictType)
|
||||
return rows
|
||||
}
|
||||
|
||||
// DeleteDictTypeByIDs 批量删除字典类型信息
|
||||
func (r *ServiceSysDictType) DeleteDictTypeByIDs(dictIDs []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
dictTypes := r.sysDictTypeRepository.SelectDictTypeByIDs(dictIDs)
|
||||
if len(dictTypes) <= 0 {
|
||||
return 0, errors.New("no permission to access dictionary type data")
|
||||
}
|
||||
for _, v := range dictTypes {
|
||||
// 字典类型下级含有数据
|
||||
useCount := r.sysDictDataRepository.CountDictDataByType(v.DictType)
|
||||
if useCount > 0 {
|
||||
msg := fmt.Sprintf("[%s] Dictionary data exists and cannot be deleted. ", v.DictName)
|
||||
return 0, errors.New(msg)
|
||||
}
|
||||
// 清除缓存
|
||||
r.ClearDictCache(v.DictType)
|
||||
}
|
||||
if len(dictTypes) == len(dictIDs) {
|
||||
rows := r.sysDictTypeRepository.DeleteDictTypeByIDs(dictIDs)
|
||||
return rows, nil
|
||||
}
|
||||
return 0, errors.New("failed to delete dictionary data information")
|
||||
}
|
||||
|
||||
// ResetDictCache 重置字典缓存数据
|
||||
func (r *ServiceSysDictType) ResetDictCache() {
|
||||
r.ClearDictCache("*")
|
||||
r.LoadingDictCache("")
|
||||
}
|
||||
|
||||
// getCacheKey 组装缓存key
|
||||
func (r *ServiceSysDictType) getDictCache(dictType string) string {
|
||||
return cachekey.SYS_DICT_KEY + dictType
|
||||
}
|
||||
|
||||
// LoadingDictCache 加载字典缓存数据
|
||||
func (r *ServiceSysDictType) LoadingDictCache(dictType string) {
|
||||
sysDictData := sysDictDataModel.SysDictData{
|
||||
Status: "1",
|
||||
}
|
||||
|
||||
// 指定字典类型
|
||||
if dictType != "" {
|
||||
sysDictData.DictType = dictType
|
||||
// 删除缓存
|
||||
key := r.getDictCache(dictType)
|
||||
cache.DeleteLocal(key)
|
||||
}
|
||||
|
||||
sysDictDataList := r.sysDictDataRepository.SelectDictDataList(sysDictData)
|
||||
if len(sysDictDataList) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 将字典数据按类型分组
|
||||
m := make(map[string][]sysDictDataModel.SysDictData, 0)
|
||||
for _, v := range sysDictDataList {
|
||||
key := v.DictType
|
||||
if item, ok := m[key]; ok {
|
||||
m[key] = append(item, v)
|
||||
} else {
|
||||
m[key] = []sysDictDataModel.SysDictData{v}
|
||||
}
|
||||
}
|
||||
|
||||
// 放入缓存
|
||||
for k, v := range m {
|
||||
key := r.getDictCache(k)
|
||||
values, _ := json.Marshal(v)
|
||||
cache.SetLocal(key, string(values))
|
||||
}
|
||||
}
|
||||
|
||||
// ClearDictCache 清空字典缓存数据
|
||||
func (r *ServiceSysDictType) ClearDictCache(dictType string) bool {
|
||||
key := r.getDictCache(dictType)
|
||||
keys := cache.GetLocalKeys(key)
|
||||
for _, v := range keys {
|
||||
cache.DeleteLocal(v)
|
||||
}
|
||||
return len(keys) > 0
|
||||
}
|
||||
|
||||
// DictDataCache 获取字典数据缓存数据
|
||||
func (r *ServiceSysDictType) DictDataCache(dictType string) []sysDictDataModel.SysDictData {
|
||||
data := []sysDictDataModel.SysDictData{}
|
||||
key := r.getDictCache(dictType)
|
||||
jsonAny, ok := cache.GetLocal(key)
|
||||
if jsonAny != nil && ok {
|
||||
err := json.Unmarshal([]byte(jsonAny.(string)), &data)
|
||||
if err != nil {
|
||||
data = []sysDictDataModel.SysDictData{}
|
||||
}
|
||||
} else {
|
||||
data = r.sysDictDataRepository.SelectDictDataList(sysDictDataModel.SysDictData{
|
||||
Status: "1",
|
||||
DictType: dictType,
|
||||
})
|
||||
if len(data) > 0 {
|
||||
cache.DeleteLocal(key)
|
||||
values, _ := json.Marshal(data)
|
||||
cache.SetLocal(key, string(values))
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
@@ -1,354 +0,0 @@
|
||||
package sysmenu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"nms_cxy/features/sys_menu/consts"
|
||||
"nms_cxy/features/sys_menu/model"
|
||||
"nms_cxy/features/sys_menu/service"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/utils/regular"
|
||||
"nms_cxy/lib/core/vo/result"
|
||||
"nms_cxy/lib/midware"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
srcConfig "nms_cxy/src/framework/config"
|
||||
)
|
||||
|
||||
// 菜单接口添加到路由
|
||||
func Routers() []services.RouterItem {
|
||||
// 实例化控制层 SysMenuApi 结构体
|
||||
var apis = &SysMenuApi{
|
||||
sysMenuService: service.NewServiceSysMenu,
|
||||
}
|
||||
|
||||
rs := [...]services.RouterItem{
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/menus",
|
||||
Handler: apis.List,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/menu/{menuId}",
|
||||
Handler: apis.Info,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "POST",
|
||||
Pattern: "/menu",
|
||||
Handler: apis.Add,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/menu",
|
||||
Handler: apis.Edit,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "DELETE",
|
||||
Pattern: "/menu/{menuId}",
|
||||
Handler: apis.Remove,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/menus/treeSelect",
|
||||
Handler: apis.TreeSelect,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/menu/roleMenuTreeSelect/{roleId}",
|
||||
Handler: apis.RoleMenuTreeSelect,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
// 添加更多的 Router 对象...
|
||||
}
|
||||
|
||||
// 生成两组前缀路由
|
||||
rsPrefix := []services.RouterItem{}
|
||||
for _, v := range rs {
|
||||
path := "/menuManage/{apiVersion}" + v.Pattern
|
||||
// 固定前缀
|
||||
v.Pattern = config.DefaultUriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
// 可配置
|
||||
v.Pattern = config.UriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
}
|
||||
return rsPrefix
|
||||
}
|
||||
|
||||
// // 实例化控制层 SysMenuApi 结构体
|
||||
// var NewSysMenu = &SysMenuApi{
|
||||
// sysMenuService: NewServiceSysMenu,
|
||||
// }
|
||||
|
||||
// 菜单信息
|
||||
//
|
||||
// PATH /menuManage
|
||||
type SysMenuApi struct {
|
||||
// 菜单服务
|
||||
sysMenuService *service.ServiceSysMenu
|
||||
}
|
||||
|
||||
// 菜单列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *SysMenuApi) List(w http.ResponseWriter, r *http.Request) {
|
||||
query := model.SysMenu{}
|
||||
if v := ctx.GetQuery(r, "menuName"); v != "" {
|
||||
query.MenuName = v
|
||||
}
|
||||
if v := ctx.GetQuery(r, "status"); v != "" {
|
||||
query.Status = v
|
||||
}
|
||||
|
||||
userId := ctx.LoginUserToUserID(r)
|
||||
if srcConfig.IsAdmin(userId) {
|
||||
userId = "*"
|
||||
}
|
||||
data := s.sysMenuService.SelectMenuList(query, userId)
|
||||
ctx.JSON(w, 200, result.OkData(data))
|
||||
}
|
||||
|
||||
// 菜单信息
|
||||
//
|
||||
// GET /:menuId
|
||||
func (s *SysMenuApi) Info(w http.ResponseWriter, r *http.Request) {
|
||||
menuId := ctx.Param(r, "menuId")
|
||||
if menuId == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
data := s.sysMenuService.SelectMenuById(menuId)
|
||||
if data.MenuID == menuId {
|
||||
ctx.JSON(w, 200, result.OkData(data))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 菜单新增
|
||||
//
|
||||
// POST /
|
||||
func (s *SysMenuApi) Add(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysMenu
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.MenuID != "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 目录和菜单检查地址唯一
|
||||
if consts.TYPE_DIR == body.MenuType || consts.TYPE_MENU == body.MenuType {
|
||||
uniqueNenuPath := s.sysMenuService.CheckUniqueMenuPath(body.Path, "")
|
||||
if !uniqueNenuPath {
|
||||
msg := fmt.Sprintf("菜单新增【%s】失败,菜单路由地址已存在", body.MenuName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 检查名称唯一
|
||||
uniqueNenuName := s.sysMenuService.CheckUniqueMenuName(body.MenuName, body.ParentID, "")
|
||||
if !uniqueNenuName {
|
||||
msg := fmt.Sprintf("菜单新增【%s】失败,菜单名称已存在", body.MenuName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 外链菜单需要符合网站http(s)开头
|
||||
if body.IsFrame == "0" && !regular.ValidHttp(body.Path) {
|
||||
msg := fmt.Sprintf("菜单新增【%s】失败,非内部地址必须以http(s)://开头", body.MenuName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
||||
insertId := s.sysMenuService.InsertMenu(body)
|
||||
if insertId != "" {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 菜单修改
|
||||
//
|
||||
// PUT /
|
||||
func (s *SysMenuApi) Edit(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysMenu
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.MenuID == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 上级菜单不能选自己
|
||||
if body.MenuID == body.ParentID {
|
||||
msg := fmt.Sprintf("Menu modification failed for [%s], parent menu cannot select itself", body.MenuName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查数据是否存在
|
||||
menuInfo := s.sysMenuService.SelectMenuById(body.MenuID)
|
||||
if menuInfo.MenuID != body.MenuID {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access menu data"))
|
||||
return
|
||||
}
|
||||
// 父级ID不为0是要检查
|
||||
if body.ParentID != "0" {
|
||||
menuParent := s.sysMenuService.SelectMenuById(body.ParentID)
|
||||
if menuParent.MenuID != body.ParentID {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access menu data"))
|
||||
return
|
||||
}
|
||||
// 禁用菜单时检查父菜单是否使用
|
||||
if body.Status == "1" && menuParent.Status == "0" {
|
||||
ctx.JSON(w, 200, result.ErrMsg("Parent menu not enabled!"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 目录和菜单检查地址唯一
|
||||
if consts.TYPE_DIR == body.MenuType || consts.TYPE_MENU == body.MenuType {
|
||||
uniqueNenuPath := s.sysMenuService.CheckUniqueMenuPath(body.Path, body.MenuID)
|
||||
if !uniqueNenuPath {
|
||||
msg := fmt.Sprintf("菜单修改【%s】失败,菜单路由地址已存在", body.MenuName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 检查名称唯一
|
||||
uniqueNenuName := s.sysMenuService.CheckUniqueMenuName(body.MenuName, body.ParentID, body.MenuID)
|
||||
if !uniqueNenuName {
|
||||
msg := fmt.Sprintf("菜单修改【%s】失败,菜单名称已存在", body.MenuName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 外链菜单需要符合网站http(s)开头
|
||||
if body.IsFrame == "0" && !regular.ValidHttp(body.Path) {
|
||||
msg := fmt.Sprintf("菜单修改【%s】失败,非内部地址必须以http(s)://开头", body.MenuName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 禁用菜单时检查子菜单是否使用
|
||||
if body.Status == "0" {
|
||||
hasStatus := s.sysMenuService.HasChildByMenuIdAndStatus(body.MenuID, "1")
|
||||
if hasStatus > 0 {
|
||||
msg := fmt.Sprintf("不允许禁用,存在使用子菜单数:%d", hasStatus)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
||||
rows := s.sysMenuService.UpdateMenu(body)
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 菜单删除
|
||||
//
|
||||
// DELETE /:menuId
|
||||
func (s *SysMenuApi) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
menuId := ctx.Param(r, "menuId")
|
||||
if menuId == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查数据是否存在
|
||||
menu := s.sysMenuService.SelectMenuById(menuId)
|
||||
if menu.MenuID != menuId {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access menu data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否存在子菜单
|
||||
hasChild := s.sysMenuService.HasChildByMenuIdAndStatus(menuId, "")
|
||||
if hasChild > 0 {
|
||||
msg := fmt.Sprintf("Deletion not allowed, there are sub orders: %d", hasChild)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否分配给角色
|
||||
existRole := s.sysMenuService.CheckMenuExistRole(menuId)
|
||||
if existRole > 0 {
|
||||
msg := fmt.Sprintf("Deletion not allowed, menu already assigned to roles: %d", existRole)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
rows := s.sysMenuService.DeleteMenuById(menuId)
|
||||
if rows > 0 {
|
||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 菜单树结构列表
|
||||
//
|
||||
// GET /treeSelect
|
||||
func (s *SysMenuApi) TreeSelect(w http.ResponseWriter, r *http.Request) {
|
||||
query := model.SysMenu{}
|
||||
if v := ctx.GetQuery(r, "menuName"); v != "" {
|
||||
query.MenuName = v
|
||||
}
|
||||
if v := ctx.GetQuery(r, "status"); v != "" {
|
||||
query.Status = v
|
||||
}
|
||||
|
||||
userId := ctx.LoginUserToUserID(r)
|
||||
if srcConfig.IsAdmin(userId) {
|
||||
userId = "*"
|
||||
}
|
||||
data := s.sysMenuService.SelectMenuTreeSelectByUserId(query, userId)
|
||||
ctx.JSON(w, 200, result.OkData(data))
|
||||
|
||||
}
|
||||
|
||||
// 菜单树结构列表(指定角色)
|
||||
//
|
||||
// GET /roleMenuTreeSelect/:roleId
|
||||
func (s *SysMenuApi) RoleMenuTreeSelect(w http.ResponseWriter, r *http.Request) {
|
||||
roleId := ctx.Param(r, "roleId")
|
||||
if roleId == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
query := model.SysMenu{}
|
||||
if v := ctx.GetQuery(r, "menuName"); v != "" {
|
||||
query.MenuName = v
|
||||
}
|
||||
if v := ctx.GetQuery(r, "status"); v != "" {
|
||||
query.Status = v
|
||||
}
|
||||
|
||||
userId := ctx.LoginUserToUserID(r)
|
||||
if srcConfig.IsAdmin(userId) {
|
||||
userId = "*"
|
||||
}
|
||||
menuTreeSelect := s.sysMenuService.SelectMenuTreeSelectByUserId(query, userId)
|
||||
checkedKeys := s.sysMenuService.SelectMenuListByRoleId(roleId)
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"menus": menuTreeSelect,
|
||||
"checkedKeys": checkedKeys,
|
||||
}))
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package consts
|
||||
|
||||
// 系统菜单常量信息
|
||||
|
||||
const (
|
||||
// 组件布局类型-基础布局组件标识
|
||||
COMPONENT_LAYOUT_BASIC = "BasicLayout"
|
||||
// 组件布局类型-空白布局组件标识
|
||||
COMPONENT_LAYOUT_BLANK = "BlankLayout"
|
||||
// 组件布局类型-内链接布局组件标识
|
||||
COMPONENT_LAYOUT_LINK = "LinkLayout"
|
||||
)
|
||||
|
||||
const (
|
||||
// 菜单类型-目录
|
||||
TYPE_DIR = "D"
|
||||
// 菜单类型-菜单
|
||||
TYPE_MENU = "M"
|
||||
// 菜单类型-按钮
|
||||
TYPE_BUTTON = "B"
|
||||
)
|
||||
|
||||
// 菜单内嵌地址标识-带/前缀
|
||||
const PATH_INLINE = "/inline"
|
||||
@@ -1,46 +0,0 @@
|
||||
package model
|
||||
|
||||
// SysMenu 菜单权限对象 sys_menu
|
||||
type SysMenu struct {
|
||||
// 菜单ID
|
||||
MenuID string `json:"menuId"`
|
||||
// 菜单名称
|
||||
MenuName string `json:"menuName" binding:"required"`
|
||||
// 父菜单ID 默认0
|
||||
ParentID string `json:"parentId" binding:"required"`
|
||||
// 显示顺序
|
||||
MenuSort int `json:"menuSort"`
|
||||
// 路由地址
|
||||
Path string `json:"path"`
|
||||
// 组件路径
|
||||
Component string `json:"component"`
|
||||
// 是否内部跳转(0否 1是)
|
||||
IsFrame string `json:"isFrame"`
|
||||
// 是否缓存(0不缓存 1缓存)
|
||||
IsCache string `json:"isCache"`
|
||||
// 菜单类型(D目录 M菜单 B按钮)
|
||||
MenuType string `json:"menuType" binding:"required"`
|
||||
// 是否显示(0隐藏 1显示)
|
||||
Visible string `json:"visible"`
|
||||
// 菜单状态(0停用 1正常)
|
||||
Status string `json:"status"`
|
||||
// 权限标识
|
||||
Perms string `json:"perms"`
|
||||
// 菜单图标(#无图标)
|
||||
Icon string `json:"icon"`
|
||||
// 创建者
|
||||
CreateBy string `json:"createBy"`
|
||||
// 创建时间
|
||||
CreateTime int64 `json:"createTime"`
|
||||
// 更新者
|
||||
UpdateBy string `json:"updateBy"`
|
||||
// 更新时间
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
// 备注
|
||||
Remark string `json:"remark"`
|
||||
|
||||
// ====== 非数据库字段属性 ======
|
||||
|
||||
// 子菜单
|
||||
Children []SysMenu `json:"children,omitempty"`
|
||||
}
|
||||
@@ -1,475 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/features/sys_menu/consts"
|
||||
"nms_cxy/features/sys_menu/model"
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoSysMenu 结构体
|
||||
var NewRepoSysMenu = &RepoSysMenu{
|
||||
selectSql: `select
|
||||
m.menu_id, m.menu_name, m.parent_id, m.menu_sort, m.path, m.component, m.is_frame, m.is_cache, m.menu_type, m.visible, m.status, ifnull(m.perms,'') as perms, m.icon, m.create_time, m.remark
|
||||
from sys_menu m`,
|
||||
|
||||
selectSqlByUser: `select distinct
|
||||
m.menu_id, m.menu_name, m.parent_id, m.menu_sort, m.path, m.component, m.is_frame, m.is_cache, m.menu_type, m.visible, m.status, ifnull(m.perms,'') as perms, m.icon, m.create_time, m.remark
|
||||
from sys_menu m
|
||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||
left join sys_user_role ur on rm.role_id = ur.role_id
|
||||
left join sys_role ro on ur.role_id = ro.role_id`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"menu_id": "MenuID",
|
||||
"menu_name": "MenuName",
|
||||
"parent_name": "ParentName",
|
||||
"parent_id": "ParentID",
|
||||
"path": "Path",
|
||||
"menu_sort": "MenuSort",
|
||||
"component": "Component",
|
||||
"is_frame": "IsFrame",
|
||||
"is_cache": "IsCache",
|
||||
"menu_type": "MenuType",
|
||||
"visible": "Visible",
|
||||
"status": "Status",
|
||||
"perms": "Perms",
|
||||
"icon": "Icon",
|
||||
"create_by": "CreateBy",
|
||||
"create_time": "CreateTime",
|
||||
"update_by": "UpdateBy",
|
||||
"update_time": "UpdateTime",
|
||||
"remark": "Remark",
|
||||
},
|
||||
}
|
||||
|
||||
// RepoSysMenu 菜单表 数据层处理
|
||||
type RepoSysMenu struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 查询视图用户对象SQL
|
||||
selectSqlByUser string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *RepoSysMenu) convertResultRows(rows []map[string]any) []model.SysMenu {
|
||||
arr := make([]model.SysMenu, 0)
|
||||
for _, row := range rows {
|
||||
sysMenu := model.SysMenu{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
datasource.SetFieldValue(&sysMenu, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, sysMenu)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectMenuList 查询系统菜单列表
|
||||
func (r *RepoSysMenu) SelectMenuList(sysMenu model.SysMenu, userId string) []model.SysMenu {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysMenu.MenuName != "" {
|
||||
conditions = append(conditions, "m.menu_name like concat('%', concat(?, '%'))")
|
||||
params = append(params, sysMenu.MenuName)
|
||||
}
|
||||
if sysMenu.Visible != "" {
|
||||
conditions = append(conditions, "m.visible = ?")
|
||||
params = append(params, sysMenu.Visible)
|
||||
}
|
||||
if sysMenu.Status != "" {
|
||||
conditions = append(conditions, "m.status = ?")
|
||||
params = append(params, sysMenu.Status)
|
||||
}
|
||||
|
||||
fromSql := r.selectSql
|
||||
|
||||
// 个人菜单
|
||||
if userId != "*" {
|
||||
fromSql = r.selectSqlByUser
|
||||
conditions = append(conditions, "ur.user_id = ?")
|
||||
params = append(params, userId)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
orderSql := " order by m.parent_id, m.menu_sort"
|
||||
querySql := fromSql + whereSql + orderSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysMenu{}
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectMenuPermsByUserId 根据用户ID查询权限
|
||||
func (r *RepoSysMenu) SelectMenuPermsByUserId(userId string) []string {
|
||||
querySql := `select distinct m.perms as 'str' from sys_menu m
|
||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||
left join sys_user_role ur on rm.role_id = ur.role_id
|
||||
left join sys_role r on r.role_id = ur.role_id
|
||||
where m.status = '1' and m.perms != '' and r.status = '1' and ur.user_id = ? `
|
||||
|
||||
// 查询结果
|
||||
results, err := datasource.RawDB("", querySql, []any{userId})
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// 读取结果
|
||||
rows := make([]string, 0)
|
||||
for _, m := range results {
|
||||
rows = append(rows, fmt.Sprintf("%v", m["str"]))
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// SelectMenuTreeByUserId 根据用户ID查询菜单
|
||||
func (r *RepoSysMenu) SelectMenuTreeByUserId(userId string) []model.SysMenu {
|
||||
var params []any
|
||||
var querySql string
|
||||
|
||||
if userId == "*" {
|
||||
// 管理员全部菜单
|
||||
querySql = r.selectSql + ` where
|
||||
m.menu_type in (?,?) and m.status = '1'
|
||||
order by m.parent_id, m.menu_sort`
|
||||
params = append(params, consts.TYPE_DIR)
|
||||
params = append(params, consts.TYPE_MENU)
|
||||
} else {
|
||||
// 用户ID权限
|
||||
querySql = r.selectSqlByUser + ` where
|
||||
m.menu_type in (?, ?) and m.status = '1'
|
||||
and ur.user_id = ? and ro.status = '1'
|
||||
order by m.parent_id, m.menu_sort`
|
||||
params = append(params, consts.TYPE_DIR)
|
||||
params = append(params, consts.TYPE_MENU)
|
||||
params = append(params, userId)
|
||||
}
|
||||
|
||||
// 查询结果
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysMenu{}
|
||||
}
|
||||
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectMenuListByRoleId 根据角色ID查询菜单树信息
|
||||
func (r *RepoSysMenu) SelectMenuListByRoleId(roleId string, menuCheckStrictly bool) []string {
|
||||
querySql := `select m.menu_id as 'str' from sys_menu m
|
||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||
where rm.role_id = ? `
|
||||
var params []any
|
||||
params = append(params, roleId)
|
||||
// 展开
|
||||
if menuCheckStrictly {
|
||||
querySql += ` and m.menu_id not in
|
||||
(select m.parent_id from sys_menu m
|
||||
inner join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||
and rm.role_id = ?) `
|
||||
params = append(params, roleId)
|
||||
}
|
||||
|
||||
// 查询结果
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []string{}
|
||||
}
|
||||
|
||||
if len(results) > 0 {
|
||||
ids := make([]string, 0)
|
||||
for _, v := range results {
|
||||
ids = append(ids, fmt.Sprintf("%v", v["str"]))
|
||||
}
|
||||
return ids
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// SelectMenuByIds 根据菜单ID查询信息
|
||||
func (r *RepoSysMenu) SelectMenuByIds(menuIds []string) []model.SysMenu {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(menuIds))
|
||||
querySql := r.selectSql + " where m.menu_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(menuIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysMenu{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// HasChildByMenuIdAndStatus 存在菜单子节点数量与状态
|
||||
func (r *RepoSysMenu) HasChildByMenuIdAndStatus(menuId, status string) int64 {
|
||||
querySql := "select count(1) as 'total' from sys_menu where parent_id = ?"
|
||||
params := []any{menuId}
|
||||
|
||||
// 菜单状态
|
||||
if status != "" {
|
||||
querySql += " and status = ?"
|
||||
params = append(params, status)
|
||||
}
|
||||
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return 0
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return parse.Number(results[0]["total"])
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InsertMenu 新增菜单信息
|
||||
func (r *RepoSysMenu) InsertMenu(sysMenu model.SysMenu) string {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysMenu.MenuID != "" {
|
||||
params["menu_id"] = sysMenu.MenuID
|
||||
}
|
||||
if sysMenu.ParentID != "" {
|
||||
params["parent_id"] = sysMenu.ParentID
|
||||
}
|
||||
if sysMenu.MenuName != "" {
|
||||
params["menu_name"] = sysMenu.MenuName
|
||||
}
|
||||
if sysMenu.MenuSort > 0 {
|
||||
params["menu_sort"] = sysMenu.MenuSort
|
||||
}
|
||||
if sysMenu.Path != "" {
|
||||
params["path"] = sysMenu.Path
|
||||
}
|
||||
if sysMenu.Component != "" {
|
||||
params["component"] = sysMenu.Component
|
||||
}
|
||||
if sysMenu.IsFrame != "" {
|
||||
params["is_frame"] = sysMenu.IsFrame
|
||||
}
|
||||
if sysMenu.IsCache != "" {
|
||||
params["is_cache"] = sysMenu.IsCache
|
||||
}
|
||||
if sysMenu.MenuType != "" {
|
||||
params["menu_type"] = sysMenu.MenuType
|
||||
}
|
||||
if sysMenu.Visible != "" {
|
||||
params["visible"] = sysMenu.Visible
|
||||
}
|
||||
if sysMenu.Status != "" {
|
||||
params["status"] = sysMenu.Status
|
||||
}
|
||||
if sysMenu.Perms != "" {
|
||||
params["perms"] = sysMenu.Perms
|
||||
}
|
||||
if sysMenu.Icon != "" {
|
||||
params["icon"] = sysMenu.Icon
|
||||
} else {
|
||||
params["icon"] = "#"
|
||||
}
|
||||
if sysMenu.Remark != "" {
|
||||
params["remark"] = sysMenu.Remark
|
||||
}
|
||||
if sysMenu.CreateBy != "" {
|
||||
params["create_by"] = sysMenu.CreateBy
|
||||
params["create_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 根据菜单类型重置参数
|
||||
if sysMenu.MenuType == consts.TYPE_BUTTON {
|
||||
params["component"] = ""
|
||||
params["path"] = ""
|
||||
params["icon"] = "#"
|
||||
params["is_cache"] = "1"
|
||||
params["is_frame"] = "1"
|
||||
params["visible"] = "1"
|
||||
params["status"] = "1"
|
||||
}
|
||||
if sysMenu.MenuType == consts.TYPE_DIR {
|
||||
params["component"] = ""
|
||||
params["perms"] = ""
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
||||
sql := "insert into sys_menu (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
||||
|
||||
// 执行插入
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
|
||||
insertId, err := results.LastInsertId()
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(insertId)
|
||||
}
|
||||
|
||||
// UpdateMenu 修改菜单信息
|
||||
func (r *RepoSysMenu) UpdateMenu(sysMenu model.SysMenu) int64 {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysMenu.MenuID != "" {
|
||||
params["menu_id"] = sysMenu.MenuID
|
||||
}
|
||||
if sysMenu.ParentID != "" {
|
||||
params["parent_id"] = sysMenu.ParentID
|
||||
}
|
||||
if sysMenu.MenuName != "" {
|
||||
params["menu_name"] = sysMenu.MenuName
|
||||
}
|
||||
if sysMenu.MenuSort > 0 {
|
||||
params["menu_sort"] = sysMenu.MenuSort
|
||||
}
|
||||
if sysMenu.Path != "" {
|
||||
params["path"] = sysMenu.Path
|
||||
}
|
||||
if sysMenu.Component != "" {
|
||||
params["component"] = sysMenu.Component
|
||||
}
|
||||
if sysMenu.IsFrame != "" {
|
||||
params["is_frame"] = sysMenu.IsFrame
|
||||
}
|
||||
if sysMenu.IsCache != "" {
|
||||
params["is_cache"] = sysMenu.IsCache
|
||||
}
|
||||
if sysMenu.MenuType != "" {
|
||||
params["menu_type"] = sysMenu.MenuType
|
||||
}
|
||||
if sysMenu.Visible != "" {
|
||||
params["visible"] = sysMenu.Visible
|
||||
}
|
||||
if sysMenu.Status != "" {
|
||||
params["status"] = sysMenu.Status
|
||||
}
|
||||
if sysMenu.Perms != "" {
|
||||
params["perms"] = sysMenu.Perms
|
||||
}
|
||||
if sysMenu.Icon != "" {
|
||||
params["icon"] = sysMenu.Icon
|
||||
} else {
|
||||
params["icon"] = "#"
|
||||
}
|
||||
if sysMenu.Remark != "" {
|
||||
params["remark"] = sysMenu.Remark
|
||||
}
|
||||
if sysMenu.UpdateBy != "" {
|
||||
params["update_by"] = sysMenu.UpdateBy
|
||||
params["update_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 根据菜单类型重置参数
|
||||
if sysMenu.MenuType == consts.TYPE_BUTTON {
|
||||
params["component"] = ""
|
||||
params["path"] = ""
|
||||
params["icon"] = "#"
|
||||
params["is_cache"] = "1"
|
||||
params["is_frame"] = "1"
|
||||
params["visible"] = "1"
|
||||
params["status"] = "1"
|
||||
}
|
||||
if sysMenu.MenuType == consts.TYPE_DIR {
|
||||
params["component"] = ""
|
||||
params["perms"] = ""
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, values := datasource.KeyValueByUpdate(params)
|
||||
sql := "update sys_menu set " + strings.Join(keys, ",") + " where menu_id = ?"
|
||||
|
||||
// 执行更新
|
||||
values = append(values, sysMenu.MenuID)
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("update row : %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("update err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// DeleteMenuById 删除菜单管理信息
|
||||
func (r *RepoSysMenu) DeleteMenuById(menuId string) int64 {
|
||||
sql := "delete from sys_menu where menu_id = ?"
|
||||
results, err := datasource.ExecDB("", sql, []any{menuId})
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// CheckUniqueMenu 校验菜单是否唯一
|
||||
func (r *RepoSysMenu) CheckUniqueMenu(sysMenu model.SysMenu) string {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysMenu.MenuName != "" {
|
||||
conditions = append(conditions, "menu_name = ?")
|
||||
params = append(params, sysMenu.MenuName)
|
||||
}
|
||||
if sysMenu.ParentID != "" {
|
||||
conditions = append(conditions, "parent_id = ?")
|
||||
params = append(params, sysMenu.ParentID)
|
||||
}
|
||||
if sysMenu.Path != "" {
|
||||
conditions = append(conditions, "path = ?")
|
||||
params = append(params, sysMenu.Path)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
if whereSql == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := "select menu_id as 'str' from sys_menu " + whereSql + " limit 1"
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err %v", err)
|
||||
return ""
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return fmt.Sprint(results[0]["str"])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -1,408 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/sys_menu/consts"
|
||||
"nms_cxy/features/sys_menu/model"
|
||||
sysRoleService "nms_cxy/features/sys_role/service"
|
||||
sysrolemenu "nms_cxy/features/sys_role_menu"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/core/utils/regular"
|
||||
"nms_cxy/lib/core/vo"
|
||||
)
|
||||
|
||||
// 实例化服务层 ServiceSysMenu 结构体
|
||||
var NewServiceSysMenu = &ServiceSysMenu{
|
||||
sysMenuRepository: NewRepoSysMenu,
|
||||
sysRoleMenuRepository: sysrolemenu.NewRepoSysRoleMenu,
|
||||
sysRoleRepository: sysRoleService.NewRepoSysRole,
|
||||
}
|
||||
|
||||
// ServiceSysMenu 菜单 服务层处理
|
||||
type ServiceSysMenu struct {
|
||||
// 菜单服务
|
||||
sysMenuRepository *RepoSysMenu
|
||||
// 角色与菜单关联服务
|
||||
sysRoleMenuRepository *sysrolemenu.RepoSysRoleMenu
|
||||
// 角色服务
|
||||
sysRoleRepository *sysRoleService.RepoSysRole
|
||||
}
|
||||
|
||||
// SelectMenuList 查询系统菜单列表
|
||||
func (r *ServiceSysMenu) SelectMenuList(sysMenu model.SysMenu, userId string) []model.SysMenu {
|
||||
return r.sysMenuRepository.SelectMenuList(sysMenu, userId)
|
||||
}
|
||||
|
||||
// SelectMenuPermsByUserId 根据用户ID查询权限
|
||||
func (r *ServiceSysMenu) SelectMenuPermsByUserId(userId string) []string {
|
||||
return r.sysMenuRepository.SelectMenuPermsByUserId(userId)
|
||||
}
|
||||
|
||||
// SelectMenuTreeByUserId 根据用户ID查询菜单
|
||||
func (r *ServiceSysMenu) SelectMenuTreeByUserId(userId string) []model.SysMenu {
|
||||
sysMenus := r.sysMenuRepository.SelectMenuTreeByUserId(userId)
|
||||
return r.parseDataToTree(sysMenus)
|
||||
}
|
||||
|
||||
// SelectMenuTreeSelectByUserId 根据用户ID查询菜单树结构信息
|
||||
func (r *ServiceSysMenu) SelectMenuTreeSelectByUserId(sysMenu model.SysMenu, userId string) []vo.TreeSelect {
|
||||
sysMenus := r.sysMenuRepository.SelectMenuList(sysMenu, userId)
|
||||
|
||||
// 过滤旧前端菜单
|
||||
sysMenusF := []model.SysMenu{}
|
||||
for _, v := range sysMenus {
|
||||
if v.Perms != "page" {
|
||||
continue
|
||||
}
|
||||
sysMenusF = append(sysMenusF, v)
|
||||
}
|
||||
|
||||
menus := r.parseDataToTree(sysMenusF)
|
||||
tree := make([]vo.TreeSelect, 0)
|
||||
for _, menu := range menus {
|
||||
tree = append(tree, sysMenuTreeSelect(menu))
|
||||
}
|
||||
return tree
|
||||
}
|
||||
|
||||
// sysMenuTreeSelect 使用给定的 SysMenu 对象解析为 TreeSelect 对象
|
||||
func sysMenuTreeSelect(sysMenu model.SysMenu) vo.TreeSelect {
|
||||
t := vo.TreeSelect{}
|
||||
t.ID = sysMenu.MenuID
|
||||
t.Label = sysMenu.MenuName
|
||||
t.Title = sysMenu.MenuName
|
||||
|
||||
if len(sysMenu.Children) > 0 {
|
||||
for _, menu := range sysMenu.Children {
|
||||
child := sysMenuTreeSelect(menu)
|
||||
t.Children = append(t.Children, child)
|
||||
}
|
||||
} else {
|
||||
t.Children = []vo.TreeSelect{}
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// SelectMenuListByRoleId 根据角色ID查询菜单树信息 TODO
|
||||
func (r *ServiceSysMenu) SelectMenuListByRoleId(roleId string) []string {
|
||||
roles := r.sysRoleRepository.SelectRoleByIds([]string{roleId})
|
||||
if len(roles) > 0 {
|
||||
role := roles[0]
|
||||
if role.RoleID == roleId {
|
||||
return r.sysMenuRepository.SelectMenuListByRoleId(
|
||||
role.RoleID,
|
||||
role.MenuCheckStrictly == "1",
|
||||
)
|
||||
}
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// SelectMenuById 根据菜单ID查询信息
|
||||
func (r *ServiceSysMenu) SelectMenuById(menuId string) model.SysMenu {
|
||||
if menuId == "" {
|
||||
return model.SysMenu{}
|
||||
}
|
||||
menus := r.sysMenuRepository.SelectMenuByIds([]string{menuId})
|
||||
if len(menus) > 0 {
|
||||
return menus[0]
|
||||
}
|
||||
return model.SysMenu{}
|
||||
}
|
||||
|
||||
// HasChildByMenuIdAndStatus 存在菜单子节点数量与状态
|
||||
func (r *ServiceSysMenu) HasChildByMenuIdAndStatus(menuId, status string) int64 {
|
||||
return r.sysMenuRepository.HasChildByMenuIdAndStatus(menuId, status)
|
||||
}
|
||||
|
||||
// CheckMenuExistRole 查询菜单是否存在角色
|
||||
func (r *ServiceSysMenu) CheckMenuExistRole(menuId string) int64 {
|
||||
return r.sysRoleMenuRepository.CheckMenuExistRole(menuId)
|
||||
}
|
||||
|
||||
// InsertMenu 新增菜单信息
|
||||
func (r *ServiceSysMenu) InsertMenu(sysMenu model.SysMenu) string {
|
||||
return r.sysMenuRepository.InsertMenu(sysMenu)
|
||||
}
|
||||
|
||||
// UpdateMenu 修改菜单信息
|
||||
func (r *ServiceSysMenu) UpdateMenu(sysMenu model.SysMenu) int64 {
|
||||
return r.sysMenuRepository.UpdateMenu(sysMenu)
|
||||
}
|
||||
|
||||
// DeleteMenuById 删除菜单管理信息
|
||||
func (r *ServiceSysMenu) DeleteMenuById(menuId string) int64 {
|
||||
// 删除菜单与角色关联
|
||||
r.sysRoleMenuRepository.DeleteMenuRole([]string{menuId})
|
||||
return r.sysMenuRepository.DeleteMenuById(menuId)
|
||||
}
|
||||
|
||||
// CheckUniqueMenuName 校验菜单名称是否唯一
|
||||
func (r *ServiceSysMenu) CheckUniqueMenuName(menuName, parentId, menuId string) bool {
|
||||
uniqueId := r.sysMenuRepository.CheckUniqueMenu(model.SysMenu{
|
||||
MenuName: menuName,
|
||||
ParentID: parentId,
|
||||
})
|
||||
if uniqueId == menuId {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// CheckUniqueMenuPath 校验路由地址是否唯一(针对目录和菜单)
|
||||
func (r *ServiceSysMenu) CheckUniqueMenuPath(path, menuId string) bool {
|
||||
uniqueId := r.sysMenuRepository.CheckUniqueMenu(model.SysMenu{
|
||||
Path: path,
|
||||
})
|
||||
if uniqueId == menuId {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// BuildRouteMenus 构建前端路由所需要的菜单
|
||||
func (r *ServiceSysMenu) BuildRouteMenus(sysMenus []model.SysMenu, prefix string) []vo.Router {
|
||||
routers := []vo.Router{}
|
||||
for _, item := range sysMenus {
|
||||
router := vo.Router{}
|
||||
router.Name = r.getRouteName(item)
|
||||
router.Path = r.getRouterPath(item)
|
||||
router.Component = r.getComponent(item)
|
||||
router.Meta = r.getRouteMeta(item)
|
||||
|
||||
// 子项菜单 目录类型 非路径链接
|
||||
cMenus := item.Children
|
||||
if len(cMenus) > 0 && item.MenuType == consts.TYPE_DIR && !regular.ValidHttp(item.Path) {
|
||||
// 获取重定向地址
|
||||
redirectPrefix, redirectPath := r.getRouteRedirect(
|
||||
cMenus,
|
||||
router.Path,
|
||||
prefix,
|
||||
)
|
||||
router.Redirect = redirectPath
|
||||
// 子菜单进入递归
|
||||
router.Children = r.BuildRouteMenus(cMenus, redirectPrefix)
|
||||
} else if item.ParentID == "0" && item.IsFrame == "1" && item.MenuType == consts.TYPE_MENU {
|
||||
// 父菜单 内部跳转 菜单类型
|
||||
menuPath := "/" + item.MenuID
|
||||
childPath := menuPath + r.getRouterPath(item)
|
||||
children := vo.Router{
|
||||
Name: r.getRouteName(item),
|
||||
Path: childPath,
|
||||
Component: item.Component,
|
||||
Meta: r.getRouteMeta(item),
|
||||
}
|
||||
router.Meta.HideChildInMenu = true
|
||||
router.Children = append(router.Children, children)
|
||||
router.Name = item.MenuID
|
||||
router.Path = menuPath
|
||||
router.Redirect = childPath
|
||||
router.Component = consts.COMPONENT_LAYOUT_BASIC
|
||||
} else if item.ParentID == "0" && item.IsFrame == "1" && regular.ValidHttp(item.Path) {
|
||||
// 父菜单 内部跳转 路径链接
|
||||
menuPath := "/" + item.MenuID
|
||||
childPath := menuPath + r.getRouterPath(item)
|
||||
children := vo.Router{
|
||||
Name: r.getRouteName(item),
|
||||
Path: childPath,
|
||||
Component: consts.COMPONENT_LAYOUT_LINK,
|
||||
Meta: r.getRouteMeta(item),
|
||||
}
|
||||
router.Meta.HideChildInMenu = true
|
||||
router.Children = append(router.Children, children)
|
||||
router.Name = item.MenuID
|
||||
router.Path = menuPath
|
||||
router.Redirect = childPath
|
||||
router.Component = consts.COMPONENT_LAYOUT_BASIC
|
||||
}
|
||||
|
||||
routers = append(routers, router)
|
||||
}
|
||||
return routers
|
||||
}
|
||||
|
||||
// getRouteName 获取路由名称 路径英文首字母大写
|
||||
func (r *ServiceSysMenu) getRouteName(sysMenu model.SysMenu) string {
|
||||
routerName := parse.FirstUpper(sysMenu.Path)
|
||||
// 路径链接
|
||||
if regular.ValidHttp(sysMenu.Path) {
|
||||
return routerName[:5] + "Link" + sysMenu.MenuID
|
||||
}
|
||||
return routerName
|
||||
}
|
||||
|
||||
// getRouterPath 获取路由地址
|
||||
func (r *ServiceSysMenu) getRouterPath(sysMenu model.SysMenu) string {
|
||||
routerPath := sysMenu.Path
|
||||
|
||||
// 显式路径
|
||||
if routerPath == "" || strings.HasPrefix(routerPath, "/") {
|
||||
return routerPath
|
||||
}
|
||||
|
||||
// 路径链接 内部跳转
|
||||
if regular.ValidHttp(routerPath) && sysMenu.IsFrame == "1" {
|
||||
routerPath = regular.Replace(routerPath, `/^http(s)?:\/\/+/`, "")
|
||||
routerPath = base64.StdEncoding.EncodeToString([]byte(routerPath))
|
||||
}
|
||||
|
||||
// 父菜单 内部跳转
|
||||
if sysMenu.ParentID == "0" && sysMenu.IsFrame == "1" {
|
||||
routerPath = "/" + routerPath
|
||||
}
|
||||
|
||||
return routerPath
|
||||
}
|
||||
|
||||
// getComponent 获取组件信息
|
||||
func (r *ServiceSysMenu) getComponent(sysMenu model.SysMenu) string {
|
||||
// 内部跳转 路径链接
|
||||
if sysMenu.IsFrame == "1" && regular.ValidHttp(sysMenu.Path) {
|
||||
return consts.COMPONENT_LAYOUT_LINK
|
||||
}
|
||||
|
||||
// 非父菜单 目录类型
|
||||
if sysMenu.ParentID != "0" && sysMenu.MenuType == consts.TYPE_DIR {
|
||||
return consts.COMPONENT_LAYOUT_BLANK
|
||||
}
|
||||
|
||||
// 组件路径 内部跳转 菜单类型
|
||||
if sysMenu.Component != "" && sysMenu.IsFrame == "1" && sysMenu.MenuType == consts.TYPE_MENU {
|
||||
// 父菜单套外层布局
|
||||
if sysMenu.ParentID == "0" {
|
||||
return consts.COMPONENT_LAYOUT_BASIC
|
||||
}
|
||||
return sysMenu.Component
|
||||
}
|
||||
|
||||
return consts.COMPONENT_LAYOUT_BASIC
|
||||
}
|
||||
|
||||
// getRouteMeta 获取路由元信息
|
||||
func (r *ServiceSysMenu) getRouteMeta(sysMenu model.SysMenu) vo.RouterMeta {
|
||||
meta := vo.RouterMeta{}
|
||||
if sysMenu.Icon == "#" {
|
||||
meta.Icon = ""
|
||||
} else {
|
||||
meta.Icon = sysMenu.Icon
|
||||
}
|
||||
meta.Title = sysMenu.MenuName
|
||||
meta.HideChildInMenu = false
|
||||
meta.HideInMenu = sysMenu.Visible == "0"
|
||||
meta.Cache = sysMenu.IsCache == "1"
|
||||
meta.Target = ""
|
||||
|
||||
// 路径链接 非内部跳转
|
||||
if regular.ValidHttp(sysMenu.Path) && sysMenu.IsFrame == "0" {
|
||||
meta.Target = "_blank"
|
||||
}
|
||||
|
||||
return meta
|
||||
}
|
||||
|
||||
// getRouteRedirect 获取路由重定向地址(针对目录)
|
||||
//
|
||||
// cMenus 子菜单数组
|
||||
// routerPath 当前菜单路径
|
||||
// prefix 菜单重定向路径前缀
|
||||
func (r *ServiceSysMenu) getRouteRedirect(cMenus []model.SysMenu, routerPath string, prefix string) (string, string) {
|
||||
redirectPath := ""
|
||||
|
||||
// 重定向为首个显示并启用的子菜单
|
||||
var firstChild *model.SysMenu
|
||||
for _, item := range cMenus {
|
||||
if item.IsFrame == "1" && item.Visible == "1" {
|
||||
firstChild = &item
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 检查内嵌隐藏菜单是否可做重定向
|
||||
if firstChild == nil {
|
||||
for _, item := range cMenus {
|
||||
if item.IsFrame == "1" && item.Visible == "1" && strings.Contains(item.Path, consts.PATH_INLINE) {
|
||||
firstChild = &item
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if firstChild != nil {
|
||||
firstChildPath := r.getRouterPath(*firstChild)
|
||||
if strings.HasPrefix(firstChildPath, "/") {
|
||||
redirectPath = firstChildPath
|
||||
} else {
|
||||
// 拼接追加路径
|
||||
if !strings.HasPrefix(routerPath, "/") {
|
||||
prefix += "/"
|
||||
}
|
||||
prefix = prefix + routerPath
|
||||
redirectPath = prefix + "/" + firstChildPath
|
||||
}
|
||||
}
|
||||
|
||||
return prefix, redirectPath
|
||||
}
|
||||
|
||||
// parseDataToTree 将数据解析为树结构,构建前端所需要下拉树结构
|
||||
func (r *ServiceSysMenu) parseDataToTree(sysMenus []model.SysMenu) []model.SysMenu {
|
||||
// 节点分组
|
||||
nodesMap := make(map[string][]model.SysMenu)
|
||||
// 节点id
|
||||
treeIds := []string{}
|
||||
// 树节点
|
||||
tree := []model.SysMenu{}
|
||||
|
||||
for _, item := range sysMenus {
|
||||
parentID := item.ParentID
|
||||
// 分组
|
||||
mapItem, ok := nodesMap[parentID]
|
||||
if !ok {
|
||||
mapItem = []model.SysMenu{}
|
||||
}
|
||||
mapItem = append(mapItem, item)
|
||||
nodesMap[parentID] = mapItem
|
||||
// 记录节点ID
|
||||
treeIds = append(treeIds, item.MenuID)
|
||||
}
|
||||
|
||||
for key, value := range nodesMap {
|
||||
// 选择不是节点ID的作为树节点
|
||||
found := false
|
||||
for _, id := range treeIds {
|
||||
if id == key {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
tree = append(tree, value...)
|
||||
}
|
||||
}
|
||||
|
||||
for i, node := range tree {
|
||||
iN := r.parseDataToTreeComponet(node, &nodesMap)
|
||||
tree[i] = iN
|
||||
}
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
// parseDataToTreeComponet 递归函数处理子节点
|
||||
func (r *ServiceSysMenu) parseDataToTreeComponet(node model.SysMenu, nodesMap *map[string][]model.SysMenu) model.SysMenu {
|
||||
id := node.MenuID
|
||||
children, ok := (*nodesMap)[id]
|
||||
if ok {
|
||||
node.Children = children
|
||||
}
|
||||
if len(node.Children) > 0 {
|
||||
for i, child := range node.Children {
|
||||
icN := r.parseDataToTreeComponet(child, nodesMap)
|
||||
node.Children[i] = icN
|
||||
}
|
||||
}
|
||||
return node
|
||||
}
|
||||
@@ -1,368 +0,0 @@
|
||||
package sysrole
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/sys_role/model"
|
||||
"nms_cxy/features/sys_role/service"
|
||||
userService "nms_cxy/features/sys_user/service"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/core/vo/result"
|
||||
"nms_cxy/lib/midware"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
)
|
||||
|
||||
// 角色接口添加到路由
|
||||
func Routers() []services.RouterItem {
|
||||
// 实例化控制层 SysRoleApi 结构体
|
||||
var apis = &SysRoleApi{
|
||||
sysRoleService: service.NewServiceSysRole,
|
||||
sysUserService: userService.NewServiceSysUser,
|
||||
}
|
||||
|
||||
rs := [...]services.RouterItem{
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/roles",
|
||||
Handler: apis.List,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/role/{roleId}",
|
||||
Handler: apis.Info,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "POST",
|
||||
Pattern: "/role",
|
||||
Handler: apis.Add,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/role",
|
||||
Handler: apis.Edit,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "DELETE",
|
||||
Pattern: "/role/{roleIds}",
|
||||
Handler: apis.Remove,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/role/changeStatus",
|
||||
Handler: apis.Status,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/role/authUser/allocatedList",
|
||||
Handler: apis.AuthUserAllocatedList,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/role/authUser/checked",
|
||||
Handler: apis.AuthUserChecked,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
// 添加更多的 Router 对象...
|
||||
}
|
||||
|
||||
// 生成两组前缀路由
|
||||
rsPrefix := []services.RouterItem{}
|
||||
for _, v := range rs {
|
||||
path := "/roleManage/{apiVersion}" + v.Pattern
|
||||
// 固定前缀
|
||||
v.Pattern = config.DefaultUriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
// 可配置
|
||||
v.Pattern = config.UriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
}
|
||||
return rsPrefix
|
||||
}
|
||||
|
||||
// // 实例化控制层 SysRoleApi 结构体
|
||||
// var NewSysRole = &SysRoleApi{
|
||||
// sysRoleService: sysrole.NewServiceSysRole,
|
||||
// sysUserService: sysuser.NewServiceSysUser,
|
||||
// }
|
||||
|
||||
// 角色信息
|
||||
//
|
||||
// PATH /roleManage
|
||||
type SysRoleApi struct {
|
||||
// 角色服务
|
||||
sysRoleService *service.ServiceSysRole
|
||||
// 用户服务
|
||||
sysUserService *userService.ServiceSysUser
|
||||
}
|
||||
|
||||
// 角色列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *SysRoleApi) List(w http.ResponseWriter, r *http.Request) {
|
||||
querys := ctx.QueryMap(r)
|
||||
data := s.sysRoleService.SelectRolePage(querys)
|
||||
ctx.JSON(w, 200, result.Ok(data))
|
||||
}
|
||||
|
||||
// 角色信息详情
|
||||
//
|
||||
// GET /:roleId
|
||||
func (s *SysRoleApi) Info(w http.ResponseWriter, r *http.Request) {
|
||||
roleId := ctx.Param(r, "roleId")
|
||||
if roleId == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
data := s.sysRoleService.SelectRoleById(roleId)
|
||||
if data.RoleID == roleId {
|
||||
ctx.JSON(w, 200, result.OkData(data))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 角色信息新增
|
||||
//
|
||||
// POST /
|
||||
func (s *SysRoleApi) Add(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysRole
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.RoleID != "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断角色名称是否唯一
|
||||
uniqueRoleName := s.sysRoleService.CheckUniqueRoleName(body.RoleName, "")
|
||||
if !uniqueRoleName {
|
||||
msg := fmt.Sprintf("[%s] Role name already exists", body.RoleName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断角色键值是否唯一
|
||||
uniqueRoleKey := s.sysRoleService.CheckUniqueRoleKey(body.RoleKey, "")
|
||||
if !uniqueRoleKey {
|
||||
msg := fmt.Sprintf("[%s] The role key value already exists", body.RoleName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
||||
insertId := s.sysRoleService.InsertRole(body)
|
||||
if insertId != "" {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 角色信息修改
|
||||
//
|
||||
// PUT /
|
||||
func (s *SysRoleApi) Edit(w http.ResponseWriter, r *http.Request) {
|
||||
var body model.SysRole
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.RoleID == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否管理员角色
|
||||
if body.RoleID == "1" {
|
||||
ctx.JSON(w, 200, result.ErrMsg("Operation of administrator role is not allowed"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否存在
|
||||
role := s.sysRoleService.SelectRoleById(body.RoleID)
|
||||
if role.RoleID != body.RoleID {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access role data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断角色名称是否唯一
|
||||
uniqueRoleName := s.sysRoleService.CheckUniqueRoleName(body.RoleName, body.RoleID)
|
||||
if !uniqueRoleName {
|
||||
msg := fmt.Sprintf("[%s] Role name already exists", body.RoleName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断角色键值是否唯一
|
||||
uniqueRoleKey := s.sysRoleService.CheckUniqueRoleKey(body.RoleKey, body.RoleID)
|
||||
if !uniqueRoleKey {
|
||||
msg := fmt.Sprintf("[%s] The role key value already exists", body.RoleName)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
||||
rows := s.sysRoleService.UpdateRole(body)
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 角色信息删除
|
||||
//
|
||||
// DELETE /:roleIds
|
||||
func (s *SysRoleApi) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
roleIds := ctx.Param(r, "roleIds")
|
||||
if roleIds == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
// 处理字符转id数组后去重
|
||||
ids := strings.Split(roleIds, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
// 检查是否管理员角色
|
||||
for _, id := range uniqueIDs {
|
||||
if id == "1" {
|
||||
ctx.JSON(w, 200, result.ErrMsg("Operation of administrator role is not allowed"))
|
||||
return
|
||||
}
|
||||
}
|
||||
rows, err := s.sysRoleService.DeleteRoleByIds(uniqueIDs)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// 角色状态变更
|
||||
//
|
||||
// PUT /changeStatus
|
||||
func (s *SysRoleApi) Status(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
// 角色ID
|
||||
RoleID string `json:"roleId" binding:"required"`
|
||||
// 状态
|
||||
Status string `json:"status" binding:"required"`
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否管理员角色
|
||||
if body.RoleID == "1" {
|
||||
ctx.JSON(w, 200, result.ErrMsg("Operation of administrator role is not allowed"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否存在
|
||||
role := s.sysRoleService.SelectRoleById(body.RoleID)
|
||||
if role.RoleID != body.RoleID {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access role data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 与旧值相等不变更
|
||||
if role.Status == body.Status {
|
||||
ctx.JSON(w, 200, result.ErrMsg("Change status equals old value!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 更新状态不刷新缓存
|
||||
userName := ctx.LoginUserToUserName(r)
|
||||
SysRoleApi := model.SysRole{
|
||||
RoleID: body.RoleID,
|
||||
Status: body.Status,
|
||||
UpdateBy: userName,
|
||||
}
|
||||
rows := s.sysRoleService.UpdateRole(SysRoleApi)
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 角色分配用户列表
|
||||
//
|
||||
// GET /authUser/allocatedList
|
||||
func (s *SysRoleApi) AuthUserAllocatedList(w http.ResponseWriter, r *http.Request) {
|
||||
querys := ctx.QueryMap(r)
|
||||
roleId, ok := querys["roleId"]
|
||||
if !ok || roleId == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否存在
|
||||
role := s.sysRoleService.SelectRoleById(roleId.(string))
|
||||
if role.RoleID != roleId {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access role data!"))
|
||||
return
|
||||
}
|
||||
|
||||
data := s.sysUserService.SelectAllocatedPage(querys)
|
||||
ctx.JSON(w, 200, result.Ok(data))
|
||||
}
|
||||
|
||||
// 角色分配选择授权
|
||||
//
|
||||
// PUT /authUser/checked
|
||||
func (s *SysRoleApi) AuthUserChecked(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
// 角色ID
|
||||
RoleID string `json:"roleId" binding:"required"`
|
||||
// 用户ID组
|
||||
UserIDs string `json:"userIds" binding:"required"`
|
||||
// 选择操作 添加true 取消false
|
||||
Checked bool `json:"checked"`
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 处理字符转id数组后去重
|
||||
ids := strings.Split(body.UserIDs, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否存在
|
||||
role := s.sysRoleService.SelectRoleById(body.RoleID)
|
||||
if role.RoleID != body.RoleID {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access role data!"))
|
||||
return
|
||||
}
|
||||
|
||||
var rows int64
|
||||
if body.Checked {
|
||||
rows = s.sysRoleService.InsertAuthUsers(body.RoleID, uniqueIDs)
|
||||
} else {
|
||||
rows = s.sysRoleService.DeleteAuthUsers(body.RoleID, uniqueIDs)
|
||||
}
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package model
|
||||
|
||||
// SysRole 角色对象 sys_role
|
||||
type SysRole struct {
|
||||
// 角色ID
|
||||
RoleID string `json:"roleId"`
|
||||
// 角色名称
|
||||
RoleName string `json:"roleName" binding:"required"`
|
||||
// 角色键值
|
||||
RoleKey string `json:"roleKey" binding:"required"`
|
||||
// 显示顺序
|
||||
RoleSort int `json:"roleSort"`
|
||||
// 菜单树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示)
|
||||
MenuCheckStrictly string `json:"menuCheckStrictly"`
|
||||
// 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示)
|
||||
DeptCheckStrictly string `json:"deptCheckStrictly"`
|
||||
// 角色状态(0停用 1正常)
|
||||
Status string `json:"status"`
|
||||
// 删除标志(0代表存在 1代表删除)
|
||||
DelFlag string `json:"delFlag"`
|
||||
// 创建者
|
||||
CreateBy string `json:"createBy"`
|
||||
// 创建时间
|
||||
CreateTime int64 `json:"createTime"`
|
||||
// 更新者
|
||||
UpdateBy string `json:"updateBy"`
|
||||
// 更新时间
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
// 备注
|
||||
Remark string `json:"remark"`
|
||||
|
||||
// ====== 非数据库字段属性 ======
|
||||
|
||||
// 菜单组
|
||||
MenuIds []string `json:"menuIds,omitempty"`
|
||||
// 部门组(数据权限)
|
||||
DeptIds []string `json:"deptIds,omitempty"`
|
||||
}
|
||||
@@ -1,362 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/features/sys_role/model"
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/date"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoSysRole 结构体
|
||||
var NewRepoSysRole = &RepoSysRole{
|
||||
selectSql: `select distinct
|
||||
r.role_id, r.role_name, r.role_key, r.role_sort, r.menu_check_strictly,
|
||||
r.dept_check_strictly, r.status, r.del_flag, r.create_time, r.remark
|
||||
from sys_role r
|
||||
left join sys_user_role ur on ur.role_id = r.role_id
|
||||
left join user u on u.id = ur.user_id`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"role_id": "RoleID",
|
||||
"role_name": "RoleName",
|
||||
"role_key": "RoleKey",
|
||||
"role_sort": "RoleSort",
|
||||
"menu_check_strictly": "MenuCheckStrictly",
|
||||
"dept_check_strictly": "DeptCheckStrictly",
|
||||
"status": "Status",
|
||||
"del_flag": "DelFlag",
|
||||
"create_by": "CreateBy",
|
||||
"create_time": "CreateTime",
|
||||
"update_by": "UpdateBy",
|
||||
"update_time": "UpdateTime",
|
||||
"remark": "Remark",
|
||||
},
|
||||
}
|
||||
|
||||
// RepoSysRole 角色表 数据层处理
|
||||
type RepoSysRole struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *RepoSysRole) convertResultRows(rows []map[string]any) []model.SysRole {
|
||||
arr := make([]model.SysRole, 0)
|
||||
for _, row := range rows {
|
||||
sysRole := model.SysRole{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
datasource.SetFieldValue(&sysRole, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, sysRole)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectRolePage 根据条件分页查询角色数据
|
||||
func (r *RepoSysRole) SelectRolePage(query map[string]any) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if v, ok := query["roleId"]; ok && v != "" {
|
||||
conditions = append(conditions, "r.role_id = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["roleName"]; ok && v != "" {
|
||||
conditions = append(conditions, "r.role_name like concat('%', concat(?, '%'))")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["roleKey"]; ok && v != "" {
|
||||
conditions = append(conditions, "r.role_key like concat('%', concat(?, '%'))")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["status"]; ok && v != "" {
|
||||
conditions = append(conditions, "r.status = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
beginTime, ok := query["beginTime"]
|
||||
if !ok {
|
||||
beginTime, ok = query["params[beginTime]"]
|
||||
}
|
||||
if ok && beginTime != "" {
|
||||
conditions = append(conditions, "r.create_time >= ?")
|
||||
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
|
||||
params = append(params, beginDate.UnixMilli())
|
||||
}
|
||||
endTime, ok := query["endTime"]
|
||||
if !ok {
|
||||
endTime, ok = query["params[endTime]"]
|
||||
}
|
||||
if ok && endTime != "" {
|
||||
conditions = append(conditions, "r.create_time <= ?")
|
||||
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
|
||||
params = append(params, endDate.UnixMilli())
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := " where r.del_flag = '0' "
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " and " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := `select count(distinct r.role_id) as 'total' from sys_role r
|
||||
left join sys_user_role ur on ur.role_id = r.role_id
|
||||
left join user u on u.id = ur.user_id`
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
log.Errorf("total err => %v", err)
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": []model.SysRole{},
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " order by r.role_sort asc limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": rows,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectRoleList 根据条件查询角色数据
|
||||
func (r *RepoSysRole) SelectRoleList(sysRole model.SysRole) []model.SysRole {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysRole.RoleID != "" {
|
||||
conditions = append(conditions, "r.role_id = ?")
|
||||
params = append(params, sysRole.RoleID)
|
||||
}
|
||||
if sysRole.RoleKey != "" {
|
||||
conditions = append(conditions, "r.role_key like concat('%', concat(?, '%'))")
|
||||
params = append(params, sysRole.RoleKey)
|
||||
}
|
||||
if sysRole.RoleName != "" {
|
||||
conditions = append(conditions, "r.role_name like concat('%', concat(?, '%'))")
|
||||
params = append(params, sysRole.RoleName)
|
||||
}
|
||||
if sysRole.Status != "" {
|
||||
conditions = append(conditions, "r.status = ?")
|
||||
params = append(params, sysRole.Status)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := " where r.del_flag = '0' "
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " and " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
orderSql := " order by r.role_sort"
|
||||
querySql := r.selectSql + whereSql + orderSql
|
||||
rows, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysRole{}
|
||||
}
|
||||
return r.convertResultRows(rows)
|
||||
}
|
||||
|
||||
// SelectRoleListByUserId 根据用户ID获取角色选择框列表
|
||||
func (r *RepoSysRole) SelectRoleListByUserId(userId string) []model.SysRole {
|
||||
querySql := r.selectSql + " where r.del_flag = '0' and ur.user_id = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{userId})
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysRole{}
|
||||
}
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectRoleByIds 通过角色ID查询角色
|
||||
func (r *RepoSysRole) SelectRoleByIds(roleIds []string) []model.SysRole {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(roleIds))
|
||||
querySql := r.selectSql + " where r.role_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(roleIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []model.SysRole{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// UpdateRole 修改角色信息
|
||||
func (r *RepoSysRole) UpdateRole(sysRole model.SysRole) int64 {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysRole.RoleName != "" {
|
||||
params["role_name"] = sysRole.RoleName
|
||||
}
|
||||
if sysRole.RoleKey != "" {
|
||||
params["role_key"] = sysRole.RoleKey
|
||||
}
|
||||
if sysRole.RoleSort > 0 {
|
||||
params["role_sort"] = sysRole.RoleSort
|
||||
}
|
||||
if sysRole.MenuCheckStrictly != "" {
|
||||
params["menu_check_strictly"] = sysRole.MenuCheckStrictly
|
||||
}
|
||||
if sysRole.DeptCheckStrictly != "" {
|
||||
params["dept_check_strictly"] = sysRole.DeptCheckStrictly
|
||||
}
|
||||
if sysRole.Status != "" {
|
||||
params["status"] = sysRole.Status
|
||||
}
|
||||
if sysRole.Remark != "" {
|
||||
params["remark"] = sysRole.Remark
|
||||
}
|
||||
if sysRole.UpdateBy != "" {
|
||||
params["update_by"] = sysRole.UpdateBy
|
||||
params["update_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, values := datasource.KeyValueByUpdate(params)
|
||||
sql := "update sys_role set " + strings.Join(keys, ",") + " where role_id = ?"
|
||||
|
||||
// 执行更新
|
||||
values = append(values, sysRole.RoleID)
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("update row : %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("update err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// InsertRole 新增角色信息
|
||||
func (r *RepoSysRole) InsertRole(sysRole model.SysRole) string {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysRole.RoleID != "" {
|
||||
params["role_id"] = sysRole.RoleID
|
||||
}
|
||||
if sysRole.RoleName != "" {
|
||||
params["role_name"] = sysRole.RoleName
|
||||
}
|
||||
if sysRole.RoleKey != "" {
|
||||
params["role_key"] = sysRole.RoleKey
|
||||
}
|
||||
if sysRole.RoleSort > 0 {
|
||||
params["role_sort"] = sysRole.RoleSort
|
||||
}
|
||||
if sysRole.MenuCheckStrictly != "" {
|
||||
params["menu_check_strictly"] = sysRole.MenuCheckStrictly
|
||||
}
|
||||
if sysRole.DeptCheckStrictly != "" {
|
||||
params["dept_check_strictly"] = sysRole.DeptCheckStrictly
|
||||
}
|
||||
if sysRole.Status != "" {
|
||||
params["status"] = sysRole.Status
|
||||
}
|
||||
if sysRole.Remark != "" {
|
||||
params["remark"] = sysRole.Remark
|
||||
}
|
||||
if sysRole.CreateBy != "" {
|
||||
params["create_by"] = sysRole.CreateBy
|
||||
params["create_time"] = time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// 构建执行语句
|
||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
||||
sql := "insert into sys_role (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
||||
|
||||
// 执行插入
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
insertId, err := results.LastInsertId()
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(insertId)
|
||||
}
|
||||
|
||||
// DeleteRoleByIds 批量删除角色信息
|
||||
func (r *RepoSysRole) DeleteRoleByIds(roleIds []string) int64 {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(roleIds))
|
||||
sql := "update sys_role set del_flag = '1' where role_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(roleIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// CheckUniqueRole 校验角色是否唯一
|
||||
func (r *RepoSysRole) CheckUniqueRole(sysRole model.SysRole) string {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysRole.RoleName != "" {
|
||||
conditions = append(conditions, "r.role_name = ?")
|
||||
params = append(params, sysRole.RoleName)
|
||||
}
|
||||
if sysRole.RoleKey != "" {
|
||||
conditions = append(conditions, "r.role_key = ?")
|
||||
params = append(params, sysRole.RoleKey)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := "select role_id as 'str' from sys_role r " + whereSql + " and r.del_flag = '0' limit 1"
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err %v", err)
|
||||
return ""
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return fmt.Sprint(results[0]["str"])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"nms_cxy/features/sys_role/model"
|
||||
sysrolemenu "nms_cxy/features/sys_role_menu"
|
||||
sysuserrole "nms_cxy/features/sys_user_role"
|
||||
)
|
||||
|
||||
// 实例化服务层 ServiceSysRole 结构体
|
||||
var NewServiceSysRole = &ServiceSysRole{
|
||||
sysRoleRepository: NewRepoSysRole,
|
||||
sysUserRoleRepository: sysuserrole.NewRepoSysUserRole,
|
||||
sysRoleMenuRepository: sysrolemenu.NewRepoSysRoleMenu,
|
||||
}
|
||||
|
||||
// ServiceSysRole 角色 服务层处理
|
||||
type ServiceSysRole struct {
|
||||
// 角色服务
|
||||
sysRoleRepository *RepoSysRole
|
||||
// 用户与角色关联服务
|
||||
sysUserRoleRepository *sysuserrole.RepoSysUserRole
|
||||
// 角色与菜单关联服务
|
||||
sysRoleMenuRepository *sysrolemenu.RepoSysRoleMenu
|
||||
}
|
||||
|
||||
// SelectRolePage 根据条件分页查询角色数据
|
||||
func (r *ServiceSysRole) SelectRolePage(query map[string]any) map[string]any {
|
||||
return r.sysRoleRepository.SelectRolePage(query)
|
||||
}
|
||||
|
||||
// SelectRoleList 根据条件查询角色数据
|
||||
func (r *ServiceSysRole) SelectRoleList(sysRole model.SysRole) []model.SysRole {
|
||||
return r.sysRoleRepository.SelectRoleList(sysRole)
|
||||
}
|
||||
|
||||
// SelectRoleListByUserId 根据用户ID获取角色选择框列表
|
||||
func (r *ServiceSysRole) SelectRoleListByUserId(userId string) []model.SysRole {
|
||||
return r.sysRoleRepository.SelectRoleListByUserId(userId)
|
||||
}
|
||||
|
||||
// SelectRoleById 通过角色ID查询角色
|
||||
func (r *ServiceSysRole) SelectRoleById(roleId string) model.SysRole {
|
||||
if roleId == "" {
|
||||
return model.SysRole{}
|
||||
}
|
||||
posts := r.sysRoleRepository.SelectRoleByIds([]string{roleId})
|
||||
if len(posts) > 0 {
|
||||
return posts[0]
|
||||
}
|
||||
return model.SysRole{}
|
||||
}
|
||||
|
||||
// UpdateRole 修改角色信息
|
||||
func (r *ServiceSysRole) UpdateRole(sysRole model.SysRole) int64 {
|
||||
rows := r.sysRoleRepository.UpdateRole(sysRole)
|
||||
if rows > 0 {
|
||||
// 删除角色与菜单关联
|
||||
r.sysRoleMenuRepository.DeleteRoleMenu([]string{sysRole.RoleID})
|
||||
if len(sysRole.MenuIds) > 0 {
|
||||
r.insertRoleMenu(sysRole.RoleID, sysRole.MenuIds)
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// InsertRole 新增角色信息
|
||||
func (r *ServiceSysRole) InsertRole(sysRole model.SysRole) string {
|
||||
insertId := r.sysRoleRepository.InsertRole(sysRole)
|
||||
if insertId != "" && len(sysRole.MenuIds) > 0 {
|
||||
r.insertRoleMenu(insertId, sysRole.MenuIds)
|
||||
}
|
||||
return insertId
|
||||
}
|
||||
|
||||
// insertRoleMenu 新增角色菜单信息
|
||||
func (r *ServiceSysRole) insertRoleMenu(roleId string, menuIds []string) int64 {
|
||||
if roleId == "" || len(menuIds) <= 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
sysRoleMenus := []sysrolemenu.SysRoleMenu{}
|
||||
for _, menuId := range menuIds {
|
||||
if menuId == "" {
|
||||
continue
|
||||
}
|
||||
sysRoleMenus = append(sysRoleMenus, sysrolemenu.NewSysRoleMenu(roleId, menuId))
|
||||
}
|
||||
|
||||
return r.sysRoleMenuRepository.BatchRoleMenu(sysRoleMenus)
|
||||
}
|
||||
|
||||
// DeleteRoleByIds 批量删除角色信息
|
||||
func (r *ServiceSysRole) DeleteRoleByIds(roleIds []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
roles := r.sysRoleRepository.SelectRoleByIds(roleIds)
|
||||
if len(roles) <= 0 {
|
||||
return 0, errors.New("no permission to access role data")
|
||||
}
|
||||
for _, role := range roles {
|
||||
// 检查是否为已删除
|
||||
if role.DelFlag == "1" {
|
||||
return 0, errors.New(role.RoleID + " The character information has been deleted")
|
||||
}
|
||||
// 检查分配用户
|
||||
userCount := r.sysUserRoleRepository.CountUserRoleByRoleId(role.RoleID)
|
||||
if userCount > 0 {
|
||||
msg := fmt.Sprintf("[%s] has been assigned to a user and cannot be deleted", role.RoleName)
|
||||
return 0, errors.New(msg)
|
||||
}
|
||||
}
|
||||
if len(roles) == len(roleIds) {
|
||||
// 删除角色与菜单关联
|
||||
r.sysRoleMenuRepository.DeleteRoleMenu(roleIds)
|
||||
rows := r.sysRoleRepository.DeleteRoleByIds(roleIds)
|
||||
return rows, nil
|
||||
}
|
||||
return 0, errors.New("failed to delete role information")
|
||||
}
|
||||
|
||||
// CheckUniqueRoleName 校验角色名称是否唯一
|
||||
func (r *ServiceSysRole) CheckUniqueRoleName(roleName, roleId string) bool {
|
||||
uniqueId := r.sysRoleRepository.CheckUniqueRole(model.SysRole{
|
||||
RoleName: roleName,
|
||||
})
|
||||
if uniqueId == roleId {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// CheckUniqueRoleKey 校验角色权限是否唯一
|
||||
func (r *ServiceSysRole) CheckUniqueRoleKey(roleKey, roleId string) bool {
|
||||
uniqueId := r.sysRoleRepository.CheckUniqueRole(model.SysRole{
|
||||
RoleKey: roleKey,
|
||||
})
|
||||
if uniqueId == roleId {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// DeleteAuthUsers 批量取消授权用户角色
|
||||
func (r *ServiceSysRole) DeleteAuthUsers(roleId string, userIds []string) int64 {
|
||||
return r.sysUserRoleRepository.DeleteUserRoleByRoleId(roleId, userIds)
|
||||
}
|
||||
|
||||
// InsertAuthUsers 批量新增授权用户角色
|
||||
func (r *ServiceSysRole) InsertAuthUsers(roleId string, userIds []string) int64 {
|
||||
if roleId == "" || len(userIds) <= 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
sysUserRoles := []sysuserrole.SysUserRole{}
|
||||
for _, userId := range userIds {
|
||||
if userId == "" {
|
||||
continue
|
||||
}
|
||||
sysUserRoles = append(sysUserRoles, sysuserrole.NewSysUserRole(userId, roleId))
|
||||
}
|
||||
|
||||
return r.sysUserRoleRepository.BatchUserRole(sysUserRoles)
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package sysrolemenu
|
||||
|
||||
// SysRoleMenu 角色和菜单关联对象 sys_role_menu
|
||||
type SysRoleMenu struct {
|
||||
RoleID string `json:"roleId"` // 角色ID
|
||||
MenuID string `json:"menuId"` // 菜单ID
|
||||
}
|
||||
|
||||
// NewSysRoleMenu 创建角色和菜单关联对象的构造函数
|
||||
func NewSysRoleMenu(roleID string, menuID string) SysRoleMenu {
|
||||
return SysRoleMenu{
|
||||
RoleID: roleID,
|
||||
MenuID: menuID,
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package sysrolemenu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoSysRoleMenu 结构体
|
||||
var NewRepoSysRoleMenu = &RepoSysRoleMenu{}
|
||||
|
||||
// RepoSysRoleMenu 角色与菜单关联表 数据层处理
|
||||
type RepoSysRoleMenu struct{}
|
||||
|
||||
// CheckMenuExistRole 查询菜单分配给角色使用数量
|
||||
func (r *RepoSysRoleMenu) CheckMenuExistRole(menuId string) int64 {
|
||||
querySql := "select count(1) as 'total' from sys_role_menu where menu_id = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{menuId})
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return 0
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return parse.Number(results[0]["total"])
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// DeleteRoleMenu 批量删除角色和菜单关联
|
||||
func (r *RepoSysRoleMenu) DeleteRoleMenu(roleIds []string) int64 {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(roleIds))
|
||||
sql := "delete from sys_role_menu where role_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(roleIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// DeleteMenuRole 批量删除菜单和角色关联
|
||||
func (r *RepoSysRoleMenu) DeleteMenuRole(menuIds []string) int64 {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(menuIds))
|
||||
sql := "delete from sys_role_menu where menu_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(menuIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// BatchRoleMenu 批量新增角色菜单信息
|
||||
func (r *RepoSysRoleMenu) BatchRoleMenu(sysRoleMenus []SysRoleMenu) int64 {
|
||||
keyValues := make([]string, 0)
|
||||
for _, item := range sysRoleMenus {
|
||||
keyValues = append(keyValues, fmt.Sprintf("(%s,%s)", item.RoleID, item.MenuID))
|
||||
}
|
||||
sql := "insert into sys_role_menu(role_id, menu_id) values " + strings.Join(keyValues, ",")
|
||||
results, err := datasource.ExecDB("", sql, nil)
|
||||
if err != nil {
|
||||
log.Errorf("insert err => %v", err)
|
||||
return 0
|
||||
}
|
||||
insertId, err := results.LastInsertId()
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
return insertId
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
package sysuser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
sysRoleModel "nms_cxy/features/sys_role/model"
|
||||
sysRoleService "nms_cxy/features/sys_role/service"
|
||||
sysUserModel "nms_cxy/features/sys_user/model"
|
||||
"nms_cxy/features/sys_user/service"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/core/vo/result"
|
||||
"nms_cxy/lib/midware"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
srcConfig "nms_cxy/src/framework/config"
|
||||
)
|
||||
|
||||
// 用户接口添加到路由
|
||||
func Routers() []services.RouterItem {
|
||||
// 实例化控制层 SysUserApi 结构体
|
||||
var apis = &SysUserApi{
|
||||
sysUserService: service.NewServiceSysUser,
|
||||
sysRoleService: sysRoleService.NewServiceSysRole,
|
||||
}
|
||||
|
||||
rs := [...]services.RouterItem{
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/users",
|
||||
Handler: apis.List,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "GET",
|
||||
Pattern: "/user/{userId}",
|
||||
Handler: apis.Info,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "POST",
|
||||
Pattern: "/user",
|
||||
Handler: apis.Add,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "PUT",
|
||||
Pattern: "/user",
|
||||
Handler: apis.Edit,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
{
|
||||
Method: "DELETE",
|
||||
Pattern: "/user/{userIds}",
|
||||
Handler: apis.Remove,
|
||||
Middleware: midware.Authorize(nil),
|
||||
},
|
||||
// 添加更多的 Router 对象...
|
||||
}
|
||||
|
||||
// 生成两组前缀路由
|
||||
rsPrefix := []services.RouterItem{}
|
||||
for _, v := range rs {
|
||||
path := "/userManage/{apiVersion}" + v.Pattern
|
||||
// 固定前缀
|
||||
v.Pattern = config.DefaultUriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
// 可配置
|
||||
v.Pattern = config.UriPrefix + path
|
||||
rsPrefix = append(rsPrefix, v)
|
||||
}
|
||||
return rsPrefix
|
||||
}
|
||||
|
||||
// // 实例化控制层 SysUserApi 结构体
|
||||
// var NewSysUser = &SysUserApi{
|
||||
// sysUserService: service.NewSysUserImpl,
|
||||
// sysRoleService: service.NewSysRoleImpl,
|
||||
// sysPostService: service.NewSysPostImpl,
|
||||
// sysDictDataService: service.NewSysDictDataImpl,
|
||||
// }
|
||||
|
||||
// 用户信息
|
||||
//
|
||||
// PATH /system/user
|
||||
type SysUserApi struct {
|
||||
// 用户服务
|
||||
sysUserService *service.ServiceSysUser
|
||||
// 角色服务
|
||||
sysRoleService *sysRoleService.ServiceSysRole
|
||||
}
|
||||
|
||||
// 用户信息列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *SysUserApi) List(w http.ResponseWriter, r *http.Request) {
|
||||
querys := ctx.QueryMap(r)
|
||||
data := s.sysUserService.SelectUserPage(querys)
|
||||
ctx.JSON(w, 200, result.Ok(data))
|
||||
}
|
||||
|
||||
// 用户信息详情
|
||||
//
|
||||
// GET /:userId
|
||||
func (s *SysUserApi) Info(w http.ResponseWriter, r *http.Request) {
|
||||
userId := ctx.Param(r, "userId")
|
||||
if userId == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
// 查询系统角色列表
|
||||
roles := s.sysRoleService.SelectRoleList(sysRoleModel.SysRole{})
|
||||
|
||||
// 不是系统指定管理员需要排除其角色
|
||||
if !srcConfig.IsAdmin(userId) {
|
||||
rolesFilter := make([]sysRoleModel.SysRole, 0)
|
||||
for _, r := range roles {
|
||||
if r.RoleID != "1" {
|
||||
rolesFilter = append(rolesFilter, r)
|
||||
}
|
||||
}
|
||||
roles = rolesFilter
|
||||
}
|
||||
|
||||
// 新增用户时,用户ID为0
|
||||
if userId == "0" {
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"user": map[string]any{},
|
||||
"roleIds": []string{},
|
||||
"roles": roles,
|
||||
}))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户是否存在
|
||||
user := s.sysUserService.SelectUserById(userId)
|
||||
if user.Id != userId {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 角色ID组
|
||||
roleIds := make([]string, 0)
|
||||
for _, r := range user.Roles {
|
||||
roleIds = append(roleIds, r.RoleID)
|
||||
}
|
||||
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"user": user,
|
||||
"roleIds": roleIds,
|
||||
"roles": roles,
|
||||
}))
|
||||
}
|
||||
|
||||
// 用户信息新增
|
||||
//
|
||||
// POST /
|
||||
func (s *SysUserApi) Add(w http.ResponseWriter, r *http.Request) {
|
||||
var body sysUserModel.SysUser
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.Id != "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户登录账号是否唯一
|
||||
uniqueUserName := s.sysUserService.CheckUniqueUserName(body.AccountId, "")
|
||||
if !uniqueUserName {
|
||||
msg := fmt.Sprintf("[%s] Login account already exists", body.AccountId)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
insertId := s.sysUserService.InsertUser(body)
|
||||
if insertId != "" {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 用户信息修改
|
||||
//
|
||||
// POST /
|
||||
func (s *SysUserApi) Edit(w http.ResponseWriter, r *http.Request) {
|
||||
var body sysUserModel.SysUser
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.Id == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否管理员用户
|
||||
// if srcConfig.IsAdmin(body.Id) {
|
||||
// ctx.JSON(w, 200, result.ErrMsg("不允许操作管理员用户"))
|
||||
// return
|
||||
// }
|
||||
|
||||
user := s.sysUserService.SelectUserById(body.Id)
|
||||
if user.Id != body.Id {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户登录账号是否唯一
|
||||
uniqueUserName := s.sysUserService.CheckUniqueUserName(body.AccountId, body.Id)
|
||||
if !uniqueUserName {
|
||||
msg := fmt.Sprintf("[%s] Login account already exists", body.AccountId)
|
||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||
return
|
||||
}
|
||||
|
||||
body.AccountId = "" // 忽略修改登录用户名称
|
||||
// body.Password = "" // 忽略修改密码
|
||||
rows := s.sysUserService.UpdateUserAndRolePost(body)
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 用户信息删除
|
||||
//
|
||||
// DELETE /:userIds
|
||||
func (s *SysUserApi) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
userIds := ctx.Param(r, "userIds")
|
||||
if userIds == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
// 处理字符转id数组后去重
|
||||
ids := strings.Split(userIds, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
rows, err := s.sysUserService.DeleteUserByIds(uniqueIDs)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// 用户重置密码
|
||||
//
|
||||
// PUT /resetPwd
|
||||
func (s *SysUserApi) ResetPwd(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
UserID string `json:"userId" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
if err := ctx.ShouldBindJSON(r, &body); err != nil {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否管理员用户
|
||||
if srcConfig.IsAdmin(body.UserID) {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
||||
return
|
||||
}
|
||||
|
||||
user := s.sysUserService.SelectUserById(body.UserID)
|
||||
if user.Id != body.UserID {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
||||
return
|
||||
}
|
||||
|
||||
SysUserApi := sysUserModel.SysUser{
|
||||
Id: body.UserID,
|
||||
Password: body.Password,
|
||||
}
|
||||
rows := s.sysUserService.UpdateUser(SysUserApi)
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 用户状态修改
|
||||
//
|
||||
// PUT /changeStatus
|
||||
func (s *SysUserApi) Status(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
UserID string `json:"userId" binding:"required"`
|
||||
Status string `json:"status" binding:"required"`
|
||||
}
|
||||
if err := ctx.ShouldBindJSON(r, &body); err != nil {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否存在
|
||||
user := s.sysUserService.SelectUserById(body.UserID)
|
||||
if user.Id != body.UserID {
|
||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
||||
return
|
||||
}
|
||||
|
||||
// 与旧值相等不变更
|
||||
if user.Status == body.Status {
|
||||
ctx.JSON(w, 200, result.ErrMsg("Change status equals old value!"))
|
||||
return
|
||||
}
|
||||
|
||||
SysUserApi := sysUserModel.SysUser{
|
||||
Id: body.UserID,
|
||||
Status: body.Status,
|
||||
}
|
||||
rows := s.sysUserService.UpdateUser(SysUserApi)
|
||||
if rows > 0 {
|
||||
ctx.JSON(w, 200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
ctx.JSON(w, 200, result.Err(nil))
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package model
|
||||
|
||||
import "nms_cxy/features/sys_role/model"
|
||||
|
||||
type SysUser struct {
|
||||
Id string `json:"id" xorm:"pk 'id' autoincr"`
|
||||
AccountId string `json:"accountId" xorm:"account_id"`
|
||||
Name string `json:"name" xorm:"name"`
|
||||
Sn string `json:"sn"`
|
||||
Gender string `json:"gender"`
|
||||
Description string `json:"description"`
|
||||
TelephoneNumber string `json:"telephoneNumber" xorm:"telephone_number"`
|
||||
Mobile string `json:"mobile"`
|
||||
Email string `json:"email" xorm:"email"`
|
||||
StartTime string `json:"startTime" xorm:"start_time"`
|
||||
EndTime string `json:"endTime" xorm:"end_time"`
|
||||
IdCardNumber string `json:"idCardNumber"`
|
||||
EmployeeNumber string `json:"employeeNumber"`
|
||||
Organize string `json:"organize"`
|
||||
EmployeeType string `json:"employeeType"`
|
||||
SupporterCorpName string `json:"supporterCorpName"`
|
||||
RealName string `json:"realName" xorm:"real_name"`
|
||||
Password string `json:"password" xorm:"-"`
|
||||
PasswordSha512 string `json:"-" xorm:"-"`
|
||||
ChangePasswordFlag int `json:"changePasswordFlag"`
|
||||
PasswordExpiration string `json:"passwordExpiration" xorm:"password_expiration"`
|
||||
Status string `json:"status"`
|
||||
UserExpiration string `json:"userExpiration" xorm:"user_expiration"`
|
||||
GroupName string `json:"groupName" xorm:"group_name"`
|
||||
Profile string `json:"-" xorm:"profile"`
|
||||
Phone string `json:"phone" xorm:"phone"`
|
||||
CreateTime string `json:"createTime" xorm:"create_time"`
|
||||
UpdateTime string `json:"updateTime" xorm:"update_time"`
|
||||
Unit string `json:"unit" xorm:"unit"`
|
||||
|
||||
// 角色对象组
|
||||
Roles []model.SysRole `json:"roles"`
|
||||
// 角色ID - 参数提交绑定
|
||||
RoleID string `json:"roleId,omitempty"`
|
||||
// 角色组 - 参数提交绑定
|
||||
RoleIDs []string `json:"roleIds,omitempty"`
|
||||
}
|
||||
@@ -1,578 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
sysRoleModel "nms_cxy/features/sys_role/model"
|
||||
sysUserModel "nms_cxy/features/sys_user/model"
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/date"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/src/framework/utils/crypto"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoSysUser 结构体
|
||||
var NewRepoSysUser = &RepoSysUser{
|
||||
selectSql: `select u.id,
|
||||
u.account_id, u.name, u.sn, u.gender, u.description, u.telephone_number, u.mobile, u.email,
|
||||
u.start_time, u.end_time, u.id_card_number, u.employee_number,
|
||||
u.organize, u.employee_type, u.supporter_corp_name, u.real_name, u.password, u.password_sha512,
|
||||
u.change_password_flag,u.password_expiration, u.status, u.user_expiration, u.group_name,
|
||||
u.profile, u.phone, u.create_time, u.update_time, u.unit,
|
||||
r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
|
||||
from user u
|
||||
left join sys_user_role ur on u.id = ur.user_id
|
||||
left join sys_role r on r.role_id = ur.role_id`,
|
||||
|
||||
sysUserMap: map[string]string{
|
||||
"id": "Id",
|
||||
"account_id": "AccountId",
|
||||
"name": "Name",
|
||||
"sn": "Sn",
|
||||
"gender": "Gender",
|
||||
"description": "Description",
|
||||
"telephone_number": "TelephoneNumber",
|
||||
"mobile": "Mobile",
|
||||
"email": "Email",
|
||||
"start_time": "StartTime",
|
||||
"end_time": "EndTime",
|
||||
"id_card_number": "IdCardNumber",
|
||||
"employee_number": "EmployeeNumber",
|
||||
"organize": "Organize",
|
||||
"employee_type": "EmployeeType",
|
||||
"supporter_corp_name": "SupporterCorpName",
|
||||
"real_name": "RealName",
|
||||
"password": "Password",
|
||||
"password_sha512": "PasswordSha512",
|
||||
"change_password_flag": "ChangePasswordFlag",
|
||||
"password_expiration": "PasswordExpiration",
|
||||
"status": "Status",
|
||||
"user_expiration": "UserExpiration",
|
||||
"group_name": "GroupName",
|
||||
"profile": "Profile",
|
||||
"phone": "Phone",
|
||||
"create_time": "CreateTime",
|
||||
"update_time": "UpdateTime",
|
||||
"unit": "Unit",
|
||||
},
|
||||
|
||||
sysRoleMap: map[string]string{
|
||||
"role_id": "RoleID",
|
||||
"role_name": "RoleName",
|
||||
"role_key": "RoleKey",
|
||||
"role_sort": "RoleSort",
|
||||
"data_scope": "DataScope",
|
||||
"role_status": "Status",
|
||||
},
|
||||
}
|
||||
|
||||
// RepoSysUser 用户表 数据层处理
|
||||
type RepoSysUser struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 用户信息实体映射
|
||||
sysUserMap map[string]string
|
||||
// 用户角色实体映射 一对多
|
||||
sysRoleMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *RepoSysUser) convertResultRows(rows []map[string]any) []sysUserModel.SysUser {
|
||||
arr := make([]sysUserModel.SysUser, 0)
|
||||
|
||||
for _, row := range rows {
|
||||
sysUser := sysUserModel.SysUser{}
|
||||
sysRole := sysRoleModel.SysRole{}
|
||||
sysUser.Roles = []sysRoleModel.SysRole{}
|
||||
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.sysUserMap[key]; ok {
|
||||
datasource.SetFieldValue(&sysUser, keyMapper, value)
|
||||
}
|
||||
if keyMapper, ok := r.sysRoleMap[key]; ok {
|
||||
datasource.SetFieldValue(&sysRole, keyMapper, value)
|
||||
}
|
||||
}
|
||||
|
||||
if sysRole.RoleKey != "" {
|
||||
sysUser.Roles = append(sysUser.Roles, sysRole)
|
||||
}
|
||||
|
||||
one := true
|
||||
for i, a := range arr {
|
||||
if a.Id == sysUser.Id {
|
||||
arrUser := &arr[i]
|
||||
arrUser.Roles = append(arrUser.Roles, sysUser.Roles...)
|
||||
one = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if one {
|
||||
arr = append(arr, sysUser)
|
||||
}
|
||||
}
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectUserPage 根据条件分页查询用户列表
|
||||
func (r *RepoSysUser) SelectUserPage(query map[string]any) map[string]any {
|
||||
selectUserSql := `select u.id,
|
||||
u.account_id, u.name, u.sn, u.gender, u.description, u.telephone_number, u.mobile, u.email,
|
||||
u.start_time, u.end_time, u.id_card_number, u.employee_number,
|
||||
u.organize, u.employee_type, u.supporter_corp_name, u.real_name,
|
||||
u.change_password_flag,u.password_expiration, u.status, u.user_expiration, u.group_name,
|
||||
u.profile, u.phone, u.create_time, u.update_time, u.unit
|
||||
from user u`
|
||||
selectUserTotalSql := `select count(distinct u.id) as 'total' from user u`
|
||||
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if v, ok := query["accountId"]; ok && v != "" {
|
||||
conditions = append(conditions, "u.account_id = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["name"]; ok && v != "" {
|
||||
conditions = append(conditions, "u.name concat('%', concat(?, '%'))")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["status"]; ok && v != "" {
|
||||
conditions = append(conditions, "u.status = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["phonenumber"]; ok && v != "" {
|
||||
conditions = append(conditions, "u.phonenumber like concat('%', concat(?, '%'))")
|
||||
params = append(params, v)
|
||||
}
|
||||
beginTime, ok := query["beginTime"]
|
||||
if !ok {
|
||||
beginTime, ok = query["params[beginTime]"]
|
||||
}
|
||||
if ok && beginTime != "" {
|
||||
conditions = append(conditions, "u.login_date >= ?")
|
||||
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
|
||||
params = append(params, beginDate.UnixMilli())
|
||||
}
|
||||
endTime, ok := query["endTime"]
|
||||
if !ok {
|
||||
endTime, ok = query["params[endTime]"]
|
||||
}
|
||||
if ok && endTime != "" {
|
||||
conditions = append(conditions, "u.login_date <= ?")
|
||||
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
|
||||
params = append(params, endDate.UnixMilli())
|
||||
}
|
||||
if v, ok := query["deptId"]; ok && v != "" {
|
||||
conditions = append(conditions, "(u.dept_id = ? or u.dept_id in ( select t.dept_id from sys_dept t where find_in_set(?, ancestors) ))")
|
||||
params = append(params, v)
|
||||
params = append(params, v)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := selectUserTotalSql + whereSql
|
||||
totalRows, err := datasource.RawDB("", totalSql, params)
|
||||
if err != nil {
|
||||
log.Errorf("total err => %v", err)
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": []sysUserModel.SysUser{},
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 查询数据
|
||||
querySql := selectUserSql + whereSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": rows,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectAllocatedPage 根据条件分页查询分配用户角色列表
|
||||
func (r *RepoSysUser) SelectAllocatedPage(query map[string]any) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if v, ok := query["name"]; ok && v != "" {
|
||||
conditions = append(conditions, "u.name like concat('%', concat(?, '%'))")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["phone"]; ok && v != "" {
|
||||
conditions = append(conditions, "u.phone like concat('%', concat(?, '%'))")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["status"]; ok && v != "" {
|
||||
conditions = append(conditions, "u.status = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
// 分配角色用户
|
||||
if allocated, ok := query["allocated"]; ok && allocated != "" {
|
||||
if roleId, ok := query["roleId"]; ok && roleId != "" {
|
||||
if parse.Boolean(allocated) {
|
||||
conditions = append(conditions, "r.role_id = ?")
|
||||
params = append(params, roleId)
|
||||
} else {
|
||||
conditions = append(conditions, `(r.role_id != ? or r.role_id IS NULL)
|
||||
and u.id not in (
|
||||
select u.id from user u
|
||||
inner join sys_user_role ur on u.id = ur.user_id
|
||||
and ur.role_id = ?
|
||||
)`)
|
||||
params = append(params, roleId)
|
||||
params = append(params, roleId)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := `select count(distinct u.id) as 'total' from user u
|
||||
left join sys_user_role ur on u.id = ur.user_id
|
||||
left join sys_role r on r.role_id = ur.role_id`
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
log.Errorf("total err => %v", err)
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": []sysUserModel.SysUser{},
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 查询数据
|
||||
querySql := `select distinct
|
||||
u.id, u.account_id, u.name, u.gender, u.email,
|
||||
u.phone, u.status, u.create_time, u.real_name
|
||||
from user u
|
||||
left join sys_user_role ur on u.id = ur.user_id
|
||||
left join sys_role r on r.role_id = ur.role_id`
|
||||
querySql = querySql + whereSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
return map[string]any{
|
||||
"total": total,
|
||||
"rows": rows,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectUserList 根据条件查询用户列表
|
||||
func (r *RepoSysUser) SelectUserList(sysUser sysUserModel.SysUser, dataScopeSQL string) []sysUserModel.SysUser {
|
||||
selectUserSql := `select
|
||||
u.id, u.account_id, u.name, u.real_name, u.email, u.gender, u.phone, u.create_time, u.status, u.description
|
||||
from user u`
|
||||
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysUser.AccountId != "" {
|
||||
conditions = append(conditions, "u.account_id = ?")
|
||||
params = append(params, sysUser.AccountId)
|
||||
}
|
||||
if sysUser.Name != "" {
|
||||
conditions = append(conditions, "u.name like concat('%', concat(?, '%'))")
|
||||
params = append(params, sysUser.Name)
|
||||
}
|
||||
if sysUser.Status != "" {
|
||||
conditions = append(conditions, "u.status = ?")
|
||||
params = append(params, sysUser.Status)
|
||||
}
|
||||
if sysUser.Phone != "" {
|
||||
conditions = append(conditions, "u.phone like concat('%', concat(?, '%'))")
|
||||
params = append(params, sysUser.Phone)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := selectUserSql + whereSql + dataScopeSQL
|
||||
rows, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []sysUserModel.SysUser{}
|
||||
}
|
||||
return r.convertResultRows(rows)
|
||||
}
|
||||
|
||||
// SelectUserByIds 通过用户ID查询用户
|
||||
func (r *RepoSysUser) SelectUserByIds(userIds []string) []sysUserModel.SysUser {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(userIds))
|
||||
querySql := r.selectSql + " where u.id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(userIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return []sysUserModel.SysUser{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectUserByUserName 通过用户登录账号查询用户
|
||||
func (r *RepoSysUser) SelectUserByUserName(userName string) sysUserModel.SysUser {
|
||||
querySql := r.selectSql + " where u.name = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{userName})
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return sysUserModel.SysUser{}
|
||||
}
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
if len(rows) > 0 {
|
||||
return rows[0]
|
||||
}
|
||||
return sysUserModel.SysUser{}
|
||||
}
|
||||
|
||||
// InsertUser 新增用户信息
|
||||
func (r *RepoSysUser) InsertUser(sysUser sysUserModel.SysUser) string {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysUser.AccountId != "" {
|
||||
params["account_id"] = sysUser.AccountId
|
||||
}
|
||||
if sysUser.Name != "" {
|
||||
params["name"] = sysUser.Name
|
||||
}
|
||||
if sysUser.Sn != "" {
|
||||
params["sn"] = sysUser.Sn
|
||||
} else {
|
||||
params["sn"] = ""
|
||||
}
|
||||
if sysUser.RealName != "" {
|
||||
params["real_name"] = sysUser.RealName
|
||||
} else {
|
||||
params["real_name"] = ""
|
||||
}
|
||||
if sysUser.Gender != "" {
|
||||
params["gender"] = sysUser.Gender
|
||||
}
|
||||
if sysUser.Email != "" {
|
||||
params["email"] = sysUser.Email
|
||||
} else {
|
||||
params["email"] = ""
|
||||
}
|
||||
if sysUser.Phone != "" {
|
||||
params["phone"] = sysUser.Phone
|
||||
} else {
|
||||
params["phone"] = ""
|
||||
}
|
||||
if sysUser.Unit != "" {
|
||||
params["unit"] = sysUser.Unit
|
||||
} else {
|
||||
params["unit"] = ""
|
||||
}
|
||||
|
||||
if sysUser.Organize != "" {
|
||||
params["organize"] = sysUser.Organize
|
||||
}
|
||||
if sysUser.Password != "" {
|
||||
password := crypto.BcryptHash(sysUser.Password)
|
||||
params["password"] = password
|
||||
}
|
||||
if sysUser.Status != "" {
|
||||
params["status"] = sysUser.Status
|
||||
}
|
||||
if sysUser.PasswordExpiration != "" {
|
||||
params["password_expiration"] = sysUser.PasswordExpiration
|
||||
}
|
||||
if sysUser.UserExpiration != "" {
|
||||
params["user_expiration"] = sysUser.UserExpiration
|
||||
}
|
||||
if sysUser.GroupName != "" {
|
||||
params["group_name"] = sysUser.GroupName
|
||||
}
|
||||
params["create_time"] = time.Now()
|
||||
|
||||
// 构建执行语句
|
||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
||||
sql := "insert into user (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
||||
|
||||
// 执行插入
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
insertId, err := results.LastInsertId()
|
||||
if err != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(insertId)
|
||||
}
|
||||
|
||||
// UpdateUser 修改用户信息
|
||||
func (r *RepoSysUser) UpdateUser(sysUser sysUserModel.SysUser) int64 {
|
||||
// 参数拼接
|
||||
params := make(map[string]any)
|
||||
if sysUser.Name != "" {
|
||||
params["name"] = sysUser.Name
|
||||
}
|
||||
if sysUser.Sn != "" {
|
||||
params["sn"] = sysUser.Sn
|
||||
} else {
|
||||
params["sn"] = ""
|
||||
}
|
||||
if sysUser.RealName != "" {
|
||||
params["real_name"] = sysUser.RealName
|
||||
} else {
|
||||
params["real_name"] = ""
|
||||
}
|
||||
if sysUser.Gender != "" {
|
||||
params["gender"] = sysUser.Gender
|
||||
}
|
||||
if sysUser.Email != "" {
|
||||
params["email"] = sysUser.Email
|
||||
} else {
|
||||
params["email"] = ""
|
||||
}
|
||||
if sysUser.Phone != "" {
|
||||
params["phone"] = sysUser.Phone
|
||||
} else {
|
||||
params["phone"] = ""
|
||||
}
|
||||
if sysUser.Unit != "" {
|
||||
params["unit"] = sysUser.Unit
|
||||
} else {
|
||||
params["unit"] = ""
|
||||
}
|
||||
|
||||
if sysUser.Organize != "" {
|
||||
params["organize"] = sysUser.Organize
|
||||
}
|
||||
if sysUser.Password != "" {
|
||||
password := crypto.BcryptHash(sysUser.Password)
|
||||
params["password"] = password
|
||||
}
|
||||
if sysUser.Status != "" {
|
||||
params["status"] = sysUser.Status
|
||||
}
|
||||
if sysUser.PasswordExpiration != "" {
|
||||
params["password_expiration"] = sysUser.PasswordExpiration
|
||||
}
|
||||
if sysUser.UserExpiration != "" {
|
||||
params["user_expiration"] = sysUser.UserExpiration
|
||||
}
|
||||
if sysUser.GroupName != "" {
|
||||
params["group_name"] = sysUser.GroupName
|
||||
}
|
||||
params["update_time"] = time.Now()
|
||||
|
||||
// 构建执行语句
|
||||
keys, values := datasource.KeyValueByUpdate(params)
|
||||
sql := "update user set " + strings.Join(keys, ",") + " where id = ?"
|
||||
|
||||
// 执行更新
|
||||
values = append(values, sysUser.Id)
|
||||
results, err := datasource.ExecDB("", sql, values)
|
||||
if err != nil {
|
||||
log.Errorf("update row : %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("update err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// DeleteUserByIds 批量删除用户信息
|
||||
func (r *RepoSysUser) DeleteUserByIds(userIds []string) int64 {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(userIds))
|
||||
sql := "delete from user where id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(userIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// CheckUniqueUser 校验用户信息是否唯一
|
||||
func (r *RepoSysUser) CheckUniqueUser(sysUser sysUserModel.SysUser) string {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if sysUser.Name != "" {
|
||||
conditions = append(conditions, "name = ?")
|
||||
params = append(params, sysUser.Name)
|
||||
}
|
||||
if sysUser.AccountId != "" {
|
||||
conditions = append(conditions, "account_id = ?")
|
||||
params = append(params, sysUser.AccountId)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := "select id as 'str' from user " + whereSql + " limit 1"
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err %v", err)
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return fmt.Sprint(results[0]["str"])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
sysUserModel "nms_cxy/features/sys_user/model"
|
||||
sysuserrole "nms_cxy/features/sys_user_role"
|
||||
)
|
||||
|
||||
// 实例化服务层 ServiceSysUser 结构体
|
||||
var NewServiceSysUser = &ServiceSysUser{
|
||||
sysUserRepository: NewRepoSysUser,
|
||||
sysUserRoleRepository: sysuserrole.NewRepoSysUserRole,
|
||||
}
|
||||
|
||||
// ServiceSysUser 用户 服务层处理
|
||||
type ServiceSysUser struct {
|
||||
// 用户服务
|
||||
sysUserRepository *RepoSysUser
|
||||
// 用户与角色服务
|
||||
sysUserRoleRepository *sysuserrole.RepoSysUserRole
|
||||
}
|
||||
|
||||
// SelectUserPage 根据条件分页查询用户列表
|
||||
func (r *ServiceSysUser) SelectUserPage(query map[string]any) map[string]any {
|
||||
return r.sysUserRepository.SelectUserPage(query)
|
||||
}
|
||||
|
||||
// SelectUserList 根据条件查询用户列表
|
||||
func (r *ServiceSysUser) SelectUserList(sysUser sysUserModel.SysUser) []sysUserModel.SysUser {
|
||||
return []sysUserModel.SysUser{}
|
||||
}
|
||||
|
||||
// SelectAllocatedPage 根据条件分页查询分配用户角色列表
|
||||
func (r *ServiceSysUser) SelectAllocatedPage(query map[string]any) map[string]any {
|
||||
return r.sysUserRepository.SelectAllocatedPage(query)
|
||||
}
|
||||
|
||||
// SelectUserByUserName 通过用户名查询用户
|
||||
func (r *ServiceSysUser) SelectUserByUserName(userName string) sysUserModel.SysUser {
|
||||
return r.sysUserRepository.SelectUserByUserName(userName)
|
||||
}
|
||||
|
||||
// SelectUserById 通过用户ID查询用户
|
||||
func (r *ServiceSysUser) SelectUserById(userId string) sysUserModel.SysUser {
|
||||
if userId == "" {
|
||||
return sysUserModel.SysUser{}
|
||||
}
|
||||
users := r.sysUserRepository.SelectUserByIds([]string{userId})
|
||||
if len(users) > 0 {
|
||||
return users[0]
|
||||
}
|
||||
return sysUserModel.SysUser{}
|
||||
}
|
||||
|
||||
// InsertUser 新增用户信息
|
||||
func (r *ServiceSysUser) InsertUser(sysUser sysUserModel.SysUser) string {
|
||||
// 新增用户信息
|
||||
insertId := r.sysUserRepository.InsertUser(sysUser)
|
||||
if insertId != "" {
|
||||
// 新增用户角色信息
|
||||
r.insertUserRole(insertId, sysUser.RoleIDs)
|
||||
}
|
||||
return insertId
|
||||
}
|
||||
|
||||
// insertUserRole 新增用户角色信息
|
||||
func (r *ServiceSysUser) insertUserRole(userId string, roleIds []string) int64 {
|
||||
if userId == "" || len(roleIds) <= 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
sysUserRoles := []sysuserrole.SysUserRole{}
|
||||
for _, roleId := range roleIds {
|
||||
// 管理员角色禁止操作,只能通过配置指定用户ID分配
|
||||
if roleId == "" || roleId == "1" {
|
||||
continue
|
||||
}
|
||||
sysUserRoles = append(sysUserRoles, sysuserrole.NewSysUserRole(userId, roleId))
|
||||
}
|
||||
|
||||
return r.sysUserRoleRepository.BatchUserRole(sysUserRoles)
|
||||
}
|
||||
|
||||
// UpdateUser 修改用户信息
|
||||
func (r *ServiceSysUser) UpdateUser(sysUser sysUserModel.SysUser) int64 {
|
||||
return r.sysUserRepository.UpdateUser(sysUser)
|
||||
}
|
||||
|
||||
// UpdateUserAndRolePost 修改用户信息同时更新角色和岗位
|
||||
func (r *ServiceSysUser) UpdateUserAndRolePost(sysUser sysUserModel.SysUser) int64 {
|
||||
userId := fmt.Sprint(sysUser.Id)
|
||||
// 删除用户与角色关联
|
||||
r.sysUserRoleRepository.DeleteUserRole([]string{userId})
|
||||
// 新增用户角色信息
|
||||
r.insertUserRole(userId, sysUser.RoleIDs)
|
||||
return r.sysUserRepository.UpdateUser(sysUser)
|
||||
}
|
||||
|
||||
// DeleteUserByIds 批量删除用户信息
|
||||
func (r *ServiceSysUser) DeleteUserByIds(userIds []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
users := r.sysUserRepository.SelectUserByIds(userIds)
|
||||
if len(users) <= 0 {
|
||||
return 0, errors.New("no permission to access user data")
|
||||
}
|
||||
if len(users) == len(userIds) {
|
||||
// 删除用户与角色关联
|
||||
r.sysUserRoleRepository.DeleteUserRole(userIds)
|
||||
// ... 注意其他userId进行关联的表
|
||||
// 删除用户
|
||||
rows := r.sysUserRepository.DeleteUserByIds(userIds)
|
||||
return rows, nil
|
||||
}
|
||||
return 0, errors.New("failed to delete user information")
|
||||
}
|
||||
|
||||
// CheckUniqueUserName 校验用户名称是否唯一
|
||||
func (r *ServiceSysUser) CheckUniqueUserName(accountId, userId string) bool {
|
||||
uniqueId := r.sysUserRepository.CheckUniqueUser(sysUserModel.SysUser{
|
||||
AccountId: accountId,
|
||||
})
|
||||
if uniqueId == userId {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// CheckUniquePhone 校验手机号码是否唯一
|
||||
func (r *ServiceSysUser) CheckUniquePhone(phonenumber, userId string) bool {
|
||||
uniqueId := r.sysUserRepository.CheckUniqueUser(sysUserModel.SysUser{
|
||||
Phone: phonenumber,
|
||||
})
|
||||
if uniqueId == userId {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
|
||||
// CheckUniqueEmail 校验email是否唯一
|
||||
func (r *ServiceSysUser) CheckUniqueEmail(email, userId string) bool {
|
||||
uniqueId := r.sysUserRepository.CheckUniqueUser(sysUserModel.SysUser{
|
||||
Email: email,
|
||||
})
|
||||
if uniqueId == userId {
|
||||
return true
|
||||
}
|
||||
return uniqueId == ""
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package sysuserrole
|
||||
|
||||
// SysUserRole 用户和角色关联对象 sys_user_role
|
||||
type SysUserRole struct {
|
||||
UserID string `json:"userId"` // 用户ID
|
||||
RoleID string `json:"roleId"` // 角色ID
|
||||
}
|
||||
|
||||
// NewSysUserRole 创建用户和角色关联对象的构造函数
|
||||
func NewSysUserRole(userID string, roleID string) SysUserRole {
|
||||
return SysUserRole{
|
||||
UserID: userID,
|
||||
RoleID: roleID,
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package sysuserrole
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoSysUserRole 结构体
|
||||
var NewRepoSysUserRole = &RepoSysUserRole{}
|
||||
|
||||
// RepoSysUserRole 用户与角色关联表 数据层处理
|
||||
type RepoSysUserRole struct{}
|
||||
|
||||
// CountUserRoleByRoleId 通过角色ID查询角色使用数量
|
||||
func (r *RepoSysUserRole) CountUserRoleByRoleId(roleId string) int64 {
|
||||
querySql := "select count(1) as total from sys_user_role where role_id = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{roleId})
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return 0
|
||||
}
|
||||
if len(results) > 0 {
|
||||
return parse.Number(results[0]["total"])
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// BatchUserRole 批量新增用户角色信息
|
||||
func (r *RepoSysUserRole) BatchUserRole(sysUserRoles []SysUserRole) int64 {
|
||||
keyValues := make([]string, 0)
|
||||
for _, item := range sysUserRoles {
|
||||
keyValues = append(keyValues, fmt.Sprintf("(%s,%s)", item.UserID, item.RoleID))
|
||||
}
|
||||
sql := "insert into sys_user_role(user_id, role_id) values " + strings.Join(keyValues, ",")
|
||||
results, err := datasource.ExecDB("", sql, nil)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// DeleteUserRole 批量删除用户和角色关联
|
||||
func (r *RepoSysUserRole) DeleteUserRole(userIds []string) int64 {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(userIds))
|
||||
sql := "delete from sys_user_role where user_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(userIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
|
||||
// DeleteUserRoleByRoleId 批量取消授权用户角色
|
||||
func (r *RepoSysUserRole) DeleteUserRoleByRoleId(roleId string, userIds []string) int64 {
|
||||
placeholder := datasource.KeyPlaceholderByQuery(len(userIds))
|
||||
sql := "delete from sys_user_role where role_id= ? and user_id in (" + placeholder + ")"
|
||||
parameters := datasource.ConvertIdsSlice(userIds)
|
||||
parameters = append([]any{roleId}, parameters...)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
affected, err := results.RowsAffected()
|
||||
if err != nil {
|
||||
log.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return affected
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
package trace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/conf"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/vo/result"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/omc/config"
|
||||
"nms_cxy/src/framework/utils/cmd"
|
||||
"nms_cxy/src/framework/utils/ssh"
|
||||
)
|
||||
|
||||
var (
|
||||
UriTcpdumpTask = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeTask"
|
||||
CustomUriTcpdumpTask = config.UriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeTask" // decode message api
|
||||
|
||||
UriTcpdumpPcapDownload = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/tcpdumpPcapDownload"
|
||||
CustomUriTcpdumpPcapDownload = config.UriPrefix + "/traceManagement/{apiVersion}/tcpdumpPcapDownload" // decode message api
|
||||
|
||||
UriTcpdumpNeUPFTask = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeUPFTask"
|
||||
CustomUriTcpdumpNeUPFTask = config.UriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeUPFTask" // decode message api
|
||||
)
|
||||
|
||||
// NeInfo 网元信息
|
||||
func NeInfo(neType, neId string) (*dborm.NeInfo, error) {
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("dborm.XormGetNeInfo is failed:", err)
|
||||
return nil, err
|
||||
}
|
||||
if neInfo == nil || neInfo.Ip == "" {
|
||||
return nil, fmt.Errorf("not ne_info or not IP")
|
||||
}
|
||||
return neInfo, nil
|
||||
}
|
||||
|
||||
// TcpdumpNeTask 网元发送执行 pcap
|
||||
func TcpdumpNeTask(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
NeType string `json:"neType"` // 网元类型
|
||||
NeId string `json:"neId"` // 网元ID
|
||||
Timeout int `json:"timeout"` // 超时时间
|
||||
Cmd string `json:"cmd"` // 命令
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.NeType == "" || body.NeId == "" || body.Timeout < 5 || body.Cmd == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
neInfo, err := NeInfo(body.NeType, body.NeId)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
filePcapName := fmt.Sprintf("tmp_%s_%s_%d.pcap", body.NeType, body.NeId, time.Now().UnixMilli())
|
||||
fileLogName := fmt.Sprintf("tmp_%s_%s_%d.log", body.NeType, body.NeId, time.Now().UnixMilli())
|
||||
writeLog := fmt.Sprintf(" >> %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件,放置弹出code 127
|
||||
cmdStr := fmt.Sprintf("cd /tmp \nsudo timeout %d tcpdump -i any %s -s0 -w %s", body.Timeout, body.Cmd, filePcapName)
|
||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr+writeLog)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"cmd": cmdStr,
|
||||
"msg": msg,
|
||||
"fileName": filePcapName,
|
||||
}))
|
||||
}
|
||||
|
||||
// TcpdumpPcapDownload 网元抓包pcap文件下载
|
||||
func TcpdumpPcapDownload(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
NeType string `json:"neType"` // 网元类型
|
||||
NeId string `json:"neId"` // 网元ID
|
||||
FileName string `json:"fileName"` // 文件名
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.NeType == "" || body.NeId == "" || body.FileName == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
neInfo, err := NeInfo(body.NeType, body.NeId)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
nePath := fmt.Sprintf("/tmp/%s", body.FileName)
|
||||
localPath := fmt.Sprintf("%s/tcpdump/pcap/%s", conf.Get("ne.omcdir"), body.FileName)
|
||||
err = ssh.FileSCPNeToLocal(neInfo.Ip, nePath, localPath)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.FileAttachment(w, r, localPath, body.FileName)
|
||||
}
|
||||
|
||||
// TcpdumpNeUPFTask 网元UPF发送执行 pcap
|
||||
func TcpdumpNeUPFTask(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
NeType string `json:"neType"` // 网元类型
|
||||
NeId string `json:"neId"` // 网元ID
|
||||
Cmd string `json:"cmd"` // 命令
|
||||
RunType string `json:"runType"` // 执行开始start还是停止stop
|
||||
}
|
||||
err := ctx.ShouldBindJSON(r, &body)
|
||||
if err != nil || body.NeType != "UPF" || body.NeId == "" || body.Cmd == "" {
|
||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
||||
return
|
||||
}
|
||||
|
||||
neInfo, err := NeInfo(body.NeType, body.NeId)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 开始telnet
|
||||
if body.RunType == "start_telnet" {
|
||||
// 创建TCP连接
|
||||
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", neInfo.Ip, 5002))
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
||||
cmdStr := fmt.Sprintf("pcap dispatch trace on max 100000 file %s", filePcapName)
|
||||
|
||||
fmt.Fprintln(conn, cmdStr)
|
||||
|
||||
// 读取内容
|
||||
time.Sleep(time.Duration(200) * time.Millisecond)
|
||||
buf := make([]byte, 1024*8)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
} else {
|
||||
str := string(buf[0:n])
|
||||
s := strings.Index(str, "pcap dispatch trace:")
|
||||
if s != -1 {
|
||||
e := strings.Index(str, "\r\nupfd1#")
|
||||
str = str[s:e]
|
||||
} else {
|
||||
str = fmt.Sprintf("Executed, please stop before proceeding %d", n)
|
||||
}
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"cmd": cmdStr,
|
||||
"msg": str,
|
||||
"fileName": filePcapName,
|
||||
}))
|
||||
}
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
// 停止telnet
|
||||
if body.RunType == "stop_telnet" {
|
||||
// 创建TCP连接
|
||||
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", neInfo.Ip, 5002))
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
||||
cmdStr := "pcap dispatch trace off"
|
||||
|
||||
fmt.Fprintln(conn, cmdStr)
|
||||
|
||||
// 读取内容
|
||||
time.Sleep(time.Duration(200) * time.Millisecond)
|
||||
buf := make([]byte, 1024*8)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
} else {
|
||||
str := string(buf[0:n])
|
||||
s := strings.Index(str, "pcap dispatch trace:")
|
||||
if s == -1 {
|
||||
s = strings.Index(str, "Write ")
|
||||
}
|
||||
if s != -1 {
|
||||
e := strings.Index(str, "\r\nupfd1#")
|
||||
str = str[s:e]
|
||||
} else {
|
||||
str = "No stoppable found"
|
||||
}
|
||||
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"cmd": cmdStr,
|
||||
"msg": str,
|
||||
"fileName": filePcapName,
|
||||
}))
|
||||
}
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// 开始 -脚本
|
||||
if body.RunType == "start2" {
|
||||
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
|
||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
||||
// 复制文件到网元上
|
||||
err := ssh.FileSCPLocalToNe(neInfo.Ip, "C:\\AMP\\Probject\\ems_backend\\omc\\backup\\upf_pcap", "/tmp")
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
writeLog := fmt.Sprintf(" >> %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件,放置弹出code 127
|
||||
cmdStr := fmt.Sprintf("cd /tmp \nchmod +x upf_pcap\n./upf_pcap '192.168.4.139' 'root' 'Admin123@pl' 'pcap dispatch trace on max 100000 file %s' %s ", fileLogName, writeLog)
|
||||
|
||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
} else {
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"cmd": cmdStr,
|
||||
"msg": msg,
|
||||
"fileName": filePcapName,
|
||||
}))
|
||||
}
|
||||
return
|
||||
}
|
||||
// 停止 -脚本
|
||||
if body.RunType == "stop2" {
|
||||
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
|
||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
||||
// cmdStr := "cd /tmp \nexpect /tmp/cat.sh "
|
||||
err := ssh.FileSCPLocalToNe(neInfo.Ip, "C:\\AMP\\Probject\\ems_backend\\omc\\backup\\upf_pcap", "/tmp")
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
writeLog := fmt.Sprintf(" >> %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件,放置弹出code 127
|
||||
cmdStr := fmt.Sprintf("cd /tmp \nchmod +x upf_pcap\n./upf_pcap '192.168.4.139' 'root' 'Admin123@pl' 'pcap dispatch trace off' %s ", writeLog)
|
||||
|
||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
} else {
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"cmd": cmdStr,
|
||||
"msg": msg,
|
||||
"fileName": filePcapName,
|
||||
}))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 开始-脚本字符串
|
||||
if body.RunType == "start_str" {
|
||||
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
|
||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
||||
scriptStr := "set capcmd [lindex $argv 0]\nspawn telnet localhost 5002\nexpect \"upfd1# \"\nsend \"$capcmd\\n\"\nexpect \"upfd1# \"\nsend \"quit\\n\"\nexpect \"eof\""
|
||||
writeLog := fmt.Sprintf(" > %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件输出,避免弹出code 127
|
||||
|
||||
capCmdStr := fmt.Sprintf("%s file %s", body.Cmd, filePcapName)
|
||||
|
||||
cmdStr := fmt.Sprintf("cd /tmp\n\necho '%s' > cap.sh\n\nchmod +x cap.sh\n\nexpect ./cap.sh '%s'%s", scriptStr, capCmdStr, writeLog)
|
||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
} else {
|
||||
s := strings.Index(msg, "pcap dispatch trace:")
|
||||
if s != -1 {
|
||||
e := strings.Index(msg, "\r\nupfd1#")
|
||||
msg = msg[s:e]
|
||||
} else {
|
||||
msg = "Executed, please stop before proceeding"
|
||||
}
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"cmd": capCmdStr,
|
||||
"msg": msg,
|
||||
"fileName": filePcapName,
|
||||
}))
|
||||
}
|
||||
return
|
||||
}
|
||||
// 停止-脚本字符串
|
||||
if body.RunType == "stop_str" {
|
||||
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
|
||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
||||
scriptStr := "set capcmd [lindex $argv 0]\nspawn telnet localhost 5002\nexpect \"upfd1# \"\nsend \"$capcmd\\n\"\nexpect \"upfd1# \"\nsend \"quit\\n\"\nexpect \"eof\""
|
||||
writeLog := fmt.Sprintf(" > %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件输出,避免弹出code 127
|
||||
|
||||
capCmdStr := body.Cmd
|
||||
|
||||
cmdStr := fmt.Sprintf("cd /tmp\n\necho '%s' > cap.sh\n\nchmod +x cap.sh\n\nexpect ./cap.sh '%s'%s", scriptStr, capCmdStr, writeLog)
|
||||
|
||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
||||
} else {
|
||||
s := strings.Index(msg, "pcap dispatch trace:")
|
||||
if s == -1 {
|
||||
s = strings.Index(msg, "Write ")
|
||||
}
|
||||
if s != -1 {
|
||||
e := strings.Index(msg, "\r\nupfd1#")
|
||||
msg = msg[s:e]
|
||||
} else {
|
||||
msg = "No stoppable found"
|
||||
}
|
||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||
"cmd": capCmdStr,
|
||||
"msg": msg,
|
||||
"fileName": filePcapName,
|
||||
}))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(w, 200, result.ErrMsg("runType is start or stop"))
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
||||
package model
|
||||
|
||||
// UdmAuthUser UDM鉴权用户
|
||||
type UdmAuthUser struct {
|
||||
ID string `json:"id" xorm:"pk 'id' autoincr"`
|
||||
Imsi string `json:"imsi" xorm:"imsi"` // SIM卡号
|
||||
Amf string `json:"amf" xorm:"amf"` // ANF
|
||||
Status string `json:"status" xorm:"status"` // 状态
|
||||
Ki string `json:"ki" xorm:"ki"` // ki
|
||||
AlgoIndex string `json:"algoIndex" xorm:"algo_index"` //
|
||||
Opc string `json:"opc" xorm:"opc"`
|
||||
NeID string `json:"neId" xorm:"ne_id"` // UDM网元标识-子系统
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package model
|
||||
|
||||
// UdmSubUser UDM签约用户
|
||||
type UdmSubUser struct {
|
||||
ID string `json:"id" xorm:"pk 'id' autoincr"`
|
||||
Msisdn string `json:"msisdn" xorm:"msisdn"` // 相当手机号
|
||||
Imsi string `json:"imsi" xorm:"imsi"` // SIM卡号
|
||||
Ambr string `json:"ambr" xorm:"ambr"`
|
||||
Nssai string `json:"nssai" xorm:"nssai"`
|
||||
Rat string `json:"rat" xorm:"rat"`
|
||||
Arfb string `json:"arfb" xorm:"arfb"`
|
||||
Sar string `json:"sar" xorm:"sar"`
|
||||
Cn string `json:"cn" xorm:"cn"`
|
||||
SmData string `json:"smData" xorm:"sm_data"`
|
||||
SmfSel string `json:"smfSel" xorm:"smf_sel"`
|
||||
EpsDat string `json:"epsDat" xorm:"eps_dat"`
|
||||
NeID string `json:"neId" xorm:"ne_id"` // UDM网元标识-子系统
|
||||
|
||||
EpsFlag string `json:"epsFlag" xorm:"eps_flag"`
|
||||
EpsOdb string `json:"epsOdb" xorm:"eps_odb"`
|
||||
HplmnOdb string `json:"hplmnOdb" xorm:"hplmn_odb"`
|
||||
Ard string `json:"ard" xorm:"ard"`
|
||||
Epstpl string `json:"epstpl" xorm:"epstpl"`
|
||||
ContextId string `json:"contextId" xorm:"context_id"`
|
||||
ApnContext string `json:"apnContext" xorm:"apn_context"`
|
||||
StaticIp string `json:"staticIp" xorm:"static_ip"`
|
||||
|
||||
SubNum string `json:"subNum,omitempty" xorm:"-"` // 批量数
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/udm_user/model"
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoUdmAuthUser 结构体
|
||||
var NewRepoUdmAuthUser = &RepoUdmAuthUser{
|
||||
selectSql: `select
|
||||
id, imsi, amf, status, ki, algo_index, opc, ne_id
|
||||
from u_auth_user`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"imsi": "Imsi",
|
||||
"amf": "Amf",
|
||||
"status": "Status",
|
||||
"ki": "Ki",
|
||||
"algo_index": "AlgoIndex",
|
||||
"opc": "Opc",
|
||||
"ne_id": "NeID",
|
||||
},
|
||||
}
|
||||
|
||||
// RepoUdmAuthUser UDM鉴权用户 数据层处理
|
||||
type RepoUdmAuthUser struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *RepoUdmAuthUser) convertResultRows(rows []map[string]any) []model.UdmAuthUser {
|
||||
arr := make([]model.UdmAuthUser, 0)
|
||||
for _, row := range rows {
|
||||
UdmUser := model.UdmAuthUser{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
datasource.SetFieldValue(&UdmUser, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, UdmUser)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *RepoUdmAuthUser) SelectPage(query map[string]any) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if v, ok := query["imsi"]; ok && v != "" {
|
||||
conditions = append(conditions, "imsi like concat(concat('%', ?), '%')")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["neId"]; ok && v != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
result := map[string]any{
|
||||
"total": 0,
|
||||
"rows": []model.UdmAuthUser{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from u_auth_user"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
log.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
sortSql := ""
|
||||
if v, ok := query["sortField"]; ok && v != "" {
|
||||
if v == "imsi" {
|
||||
sortSql += " order by imsi "
|
||||
}
|
||||
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
|
||||
if o == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + sortSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectList 根据实体查询
|
||||
func (r *RepoUdmAuthUser) SelectList(auth model.UdmAuthUser) []model.UdmAuthUser {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if auth.Imsi != "" {
|
||||
conditions = append(conditions, "imsi = ?")
|
||||
params = append(params, auth.Imsi)
|
||||
}
|
||||
if auth.NeID != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, auth.NeID)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + " order by imsi asc "
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// ClearAndInsert 清空ne_id后新增实体
|
||||
func (r *RepoUdmAuthUser) ClearAndInsert(neID string, authArr []model.UdmAuthUser) int64 {
|
||||
var num int64 = 0
|
||||
|
||||
// 清空指定ne_id
|
||||
_, err := datasource.ExecDB("", "TRUNCATE TABLE u_auth_user", nil)
|
||||
// _, err := datasource.ExecDB("", "DELETE FROM u_auth_user WHERE ne_id = ?", []any{neID})
|
||||
if err != nil {
|
||||
log.Errorf("TRUNCATE err => %v", err)
|
||||
}
|
||||
|
||||
n := len(authArr)
|
||||
batchSize := 2000
|
||||
for i := 0; i < n; i += batchSize {
|
||||
end := i + batchSize
|
||||
if end > n {
|
||||
end = n
|
||||
}
|
||||
batch := authArr[i:end]
|
||||
|
||||
// 调用 InsertMulti 函数将批量数据插入数据库
|
||||
results, err := datasource.DefaultDB().Table("u_auth_user").InsertMulti(batch)
|
||||
if err != nil {
|
||||
log.Errorf("InsertMulti err => %v", err)
|
||||
continue
|
||||
}
|
||||
num += results
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// Insert 新增实体
|
||||
func (r *RepoUdmAuthUser) Insert(authUser model.UdmAuthUser) int64 {
|
||||
results, err := datasource.DefaultDB().Table("u_auth_user").Insert(authUser)
|
||||
if err != nil {
|
||||
log.Errorf("Insert err => %v", err)
|
||||
return results
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// Insert 批量添加
|
||||
func (r *RepoUdmAuthUser) Inserts(authUsers []model.UdmAuthUser) int64 {
|
||||
var num int64
|
||||
n := len(authUsers)
|
||||
batchSize := 2000
|
||||
for i := 0; i < n; i += batchSize {
|
||||
end := i + batchSize
|
||||
if end > n {
|
||||
end = n
|
||||
}
|
||||
batch := authUsers[i:end]
|
||||
|
||||
// 调用 InsertMulti 函数将批量数据插入数据库
|
||||
results, err := datasource.DefaultDB().Table("u_auth_user").InsertMulti(batch)
|
||||
if err != nil {
|
||||
log.Errorf("Insert err => %v", err)
|
||||
continue
|
||||
}
|
||||
num += results
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// Update 修改更新
|
||||
func (r *RepoUdmAuthUser) Update(neID string, authUser model.UdmAuthUser) int64 {
|
||||
// 查询先
|
||||
var user model.UdmAuthUser
|
||||
has, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi = ? and ne_id = ?", authUser.Imsi, neID).Get(&user)
|
||||
if !has || err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
if authUser.Ki != "" && authUser.Ki != user.Ki {
|
||||
user.Ki = authUser.Ki
|
||||
}
|
||||
if authUser.Amf != "" && authUser.Amf != user.Amf {
|
||||
user.Amf = authUser.Amf
|
||||
}
|
||||
if authUser.AlgoIndex != "" && authUser.AlgoIndex != user.AlgoIndex {
|
||||
user.AlgoIndex = authUser.AlgoIndex
|
||||
}
|
||||
if authUser.Opc != "" && authUser.Opc != user.Opc {
|
||||
user.Opc = authUser.Opc
|
||||
}
|
||||
|
||||
results, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi = ? and ne_id = ?", user.Imsi, user.NeID).Update(user)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// Delete 删除实体
|
||||
func (r *RepoUdmAuthUser) Delete(neID, imsi string) int64 {
|
||||
results, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi = ? and ne_id = ?", imsi, neID).Delete()
|
||||
if err != nil {
|
||||
return results
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// Delete 删除范围实体
|
||||
func (r *RepoUdmAuthUser) Deletes(neID, imsi, num string) int64 {
|
||||
imsiV, err := strconv.Atoi(imsi)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
numV, err := strconv.Atoi(num)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
results, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi >= ? and imsi < ? and ne_id = ?", imsiV, imsiV+numV, neID).Delete()
|
||||
if err != nil {
|
||||
return results
|
||||
}
|
||||
return results
|
||||
}
|
||||
@@ -1,450 +0,0 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/udm_user/model"
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
// 实例化数据层 RepoUdmSubUser 结构体
|
||||
var NewRepoUdmSubUser = &RepoUdmSubUser{
|
||||
selectSql: `select
|
||||
id, msisdn, imsi, ambr, nssai, rat, arfb, sar, cn, sm_data, smf_sel, eps_dat, ne_id, eps_flag, eps_odb, hplmn_odb, ard, epstpl, context_id, apn_context, static_ip
|
||||
from u_sub_user`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"msisdn": "Msisdn",
|
||||
"imsi": "Imsi",
|
||||
"ambr": "Ambr",
|
||||
"nssai": "Nssai",
|
||||
"rat": "Rat",
|
||||
"arfb": "Arfb",
|
||||
"sar": "Sar",
|
||||
"cn": "Cn",
|
||||
"sm_data": "SmData",
|
||||
"smf_sel": "SmfSel",
|
||||
"eps_dat": "EpsDat",
|
||||
"ne_id": "NeID",
|
||||
"eps_flag": "EpsFlag",
|
||||
"eps_odb": "EpsOdb",
|
||||
"hplmn_odb": "HplmnOdb",
|
||||
"ard": "Ard",
|
||||
"epstpl": "Epstpl",
|
||||
"context_id": "ContextId",
|
||||
"apn_context": "ApnContext",
|
||||
"static_ip": "StaticIp",
|
||||
},
|
||||
}
|
||||
|
||||
// RepoUdmSubUser UDM签约用户 数据层处理
|
||||
type RepoUdmSubUser struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *RepoUdmSubUser) convertResultRows(rows []map[string]any) []model.UdmSubUser {
|
||||
arr := make([]model.UdmSubUser, 0)
|
||||
for _, row := range rows {
|
||||
UdmUser := model.UdmSubUser{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
datasource.SetFieldValue(&UdmUser, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, UdmUser)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询字典类型
|
||||
func (r *RepoUdmSubUser) SelectPage(query map[string]any) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if v, ok := query["msisdn"]; ok && v != "" {
|
||||
conditions = append(conditions, "msisdn like concat(concat('%', ?), '%')")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["imsi"]; ok && v != "" {
|
||||
conditions = append(conditions, "imsi like concat(concat('%', ?), '%')")
|
||||
params = append(params, v)
|
||||
}
|
||||
if v, ok := query["neId"]; ok && v != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, v)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
result := map[string]any{
|
||||
"total": 0,
|
||||
"rows": []model.UdmAuthUser{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from u_sub_user"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
log.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
sortSql := ""
|
||||
if v, ok := query["sortField"]; ok && v != "" {
|
||||
if v == "imsi" {
|
||||
sortSql += " order by imsi "
|
||||
}
|
||||
if v == "msisdn" {
|
||||
sortSql += " order by msisdn "
|
||||
}
|
||||
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
|
||||
if o == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + sortSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
return result
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectList 根据实体查询
|
||||
func (r *RepoUdmSubUser) SelectList(auth model.UdmSubUser) []model.UdmSubUser {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if auth.Imsi != "" {
|
||||
conditions = append(conditions, "imsi = ?")
|
||||
params = append(params, auth.Imsi)
|
||||
}
|
||||
if auth.NeID != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, auth.NeID)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + " order by imsi asc "
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
log.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// ClearAndInsert 清空ne_id后新增实体
|
||||
func (r *RepoUdmSubUser) ClearAndInsert(neID string, subArr []model.UdmSubUser) int64 {
|
||||
var num int64 = 0
|
||||
|
||||
// 清空指定ne_id
|
||||
_, err := datasource.ExecDB("", "TRUNCATE TABLE u_sub_user", nil)
|
||||
// _, err := datasource.ExecDB("", "DELETE FROM u_sub_user WHERE ne_id = ?", []any{neID})
|
||||
if err != nil {
|
||||
log.Errorf("TRUNCATE err => %v", err)
|
||||
}
|
||||
|
||||
n := len(subArr)
|
||||
batchSize := 2000
|
||||
for i := 0; i < n; i += batchSize {
|
||||
end := i + batchSize
|
||||
if end > n {
|
||||
end = n
|
||||
}
|
||||
batch := subArr[i:end]
|
||||
|
||||
// 调用 InsertMulti 函数将批量数据插入数据库
|
||||
results, err := datasource.DefaultDB().Table("u_sub_user").InsertMulti(batch)
|
||||
if err != nil {
|
||||
log.Errorf("InsertMulti err => %v", err)
|
||||
continue
|
||||
}
|
||||
num += results
|
||||
}
|
||||
|
||||
// for _, u := range subArr {
|
||||
// u.NeID = neID
|
||||
// results, err := datasource.DefaultDB().Table("u_sub_user").Insert(u)
|
||||
// if err != nil {
|
||||
// return num
|
||||
// }
|
||||
// num += results
|
||||
// }
|
||||
return num
|
||||
}
|
||||
|
||||
// Insert 新增实体
|
||||
func (r *RepoUdmSubUser) Insert(subUser model.UdmSubUser) int64 {
|
||||
results, err := datasource.DefaultDB().Table("u_sub_user").Insert(subUser)
|
||||
if err != nil {
|
||||
log.Errorf("Insert err => %v", err)
|
||||
return results
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// Insert 批量添加
|
||||
func (r *RepoUdmSubUser) Inserts(subUser []model.UdmSubUser) int64 {
|
||||
var num int64
|
||||
n := len(subUser)
|
||||
batchSize := 2000
|
||||
for i := 0; i < n; i += batchSize {
|
||||
end := i + batchSize
|
||||
if end > n {
|
||||
end = n
|
||||
}
|
||||
batch := subUser[i:end]
|
||||
|
||||
// 调用 InsertMulti 函数将批量数据插入数据库
|
||||
results, err := datasource.DefaultDB().Table("u_sub_user").InsertMulti(batch)
|
||||
if err != nil {
|
||||
log.Errorf("Insert err => %v", err)
|
||||
continue
|
||||
}
|
||||
num += results
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// Insert4G 批量添加4G用户
|
||||
func (r *RepoUdmSubUser) Insert4G(neID string, subUser model.UdmSubUser) int64 {
|
||||
var insertNum int64
|
||||
|
||||
imsiV, err := strconv.Atoi(subUser.Imsi)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
numV, err := strconv.Atoi(subUser.SubNum)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
subUser.NeID = neID
|
||||
for i := 0; i < numV; i++ {
|
||||
subUser.Imsi = fmt.Sprint(imsiV + i)
|
||||
|
||||
results, err := datasource.DefaultDB().Table("u_sub_user").Insert(subUser)
|
||||
if err == nil {
|
||||
log.Errorf("Insert err => %v", err)
|
||||
insertNum += results
|
||||
}
|
||||
}
|
||||
|
||||
return insertNum
|
||||
}
|
||||
|
||||
// Update 修改更新
|
||||
func (r *RepoUdmSubUser) Update(neID string, authUser model.UdmSubUser) int64 {
|
||||
// 查询先
|
||||
var user model.UdmSubUser
|
||||
has, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", authUser.Imsi, neID).Get(&user)
|
||||
if !has || err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
if authUser.Msisdn != "" && authUser.Msisdn != user.Msisdn {
|
||||
user.Msisdn = authUser.Msisdn
|
||||
}
|
||||
if authUser.Ambr != "" && authUser.Ambr != user.Ambr {
|
||||
user.Ambr = authUser.Ambr
|
||||
}
|
||||
if authUser.Arfb != "" && authUser.Arfb != user.Arfb {
|
||||
user.Arfb = authUser.Arfb
|
||||
}
|
||||
if authUser.Sar != "" && authUser.Sar != user.Sar {
|
||||
user.Sar = authUser.Sar
|
||||
}
|
||||
if authUser.Rat != "" && authUser.Rat != user.Rat {
|
||||
user.Rat = authUser.Rat
|
||||
}
|
||||
if authUser.Cn != "" && authUser.Cn != user.Cn {
|
||||
user.Cn = authUser.Cn
|
||||
}
|
||||
if authUser.SmfSel != "" && authUser.SmfSel != user.SmfSel {
|
||||
user.SmfSel = authUser.SmfSel
|
||||
}
|
||||
if authUser.SmData != "" && authUser.SmData != user.SmData {
|
||||
user.SmData = authUser.SmData
|
||||
}
|
||||
if authUser.EpsDat != "" && authUser.EpsDat != user.EpsDat {
|
||||
user.EpsDat = authUser.EpsDat
|
||||
}
|
||||
if authUser.EpsFlag != "" && authUser.EpsFlag != user.EpsFlag {
|
||||
user.EpsFlag = authUser.EpsFlag
|
||||
}
|
||||
if authUser.EpsOdb != "" && authUser.EpsDat != user.EpsDat {
|
||||
user.EpsOdb = authUser.EpsOdb
|
||||
}
|
||||
if authUser.HplmnOdb != "" && authUser.HplmnOdb != user.HplmnOdb {
|
||||
user.HplmnOdb = authUser.HplmnOdb
|
||||
}
|
||||
if authUser.Epstpl != "" && authUser.Epstpl != user.Epstpl {
|
||||
user.Epstpl = authUser.Epstpl
|
||||
}
|
||||
if authUser.Ard != "" && authUser.Ard != user.Ard {
|
||||
user.Ard = authUser.Ard
|
||||
}
|
||||
if authUser.ContextId != "" && authUser.ContextId != user.ContextId {
|
||||
user.ContextId = authUser.ContextId
|
||||
}
|
||||
if authUser.ApnContext != "" && authUser.ApnContext != user.ApnContext {
|
||||
user.ApnContext = authUser.ApnContext
|
||||
}
|
||||
if authUser.StaticIp != "" && authUser.StaticIp != user.StaticIp {
|
||||
user.StaticIp = authUser.StaticIp
|
||||
}
|
||||
|
||||
results, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", user.Imsi, user.NeID).Update(user)
|
||||
if err != nil {
|
||||
log.Errorf("Update err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// Update4GIP 批量修改4G IP
|
||||
func (r *RepoUdmSubUser) Update4GIP(neID string, subUser model.UdmSubUser) int64 {
|
||||
var insertNum int64
|
||||
|
||||
imsiV, err := strconv.Atoi(subUser.Imsi)
|
||||
if err != nil || subUser.StaticIp == "" {
|
||||
return insertNum
|
||||
}
|
||||
numV, err := strconv.Atoi(subUser.SubNum)
|
||||
if err != nil {
|
||||
return insertNum
|
||||
}
|
||||
|
||||
for i := 0; i < numV; i++ {
|
||||
subUser.Imsi = fmt.Sprint(imsiV + i)
|
||||
|
||||
// 查询先
|
||||
var user model.UdmSubUser
|
||||
has, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", subUser.Imsi, neID).Get(&user)
|
||||
if has && err == nil {
|
||||
// IP会自动递增
|
||||
parts := strings.Split(subUser.StaticIp, ".")
|
||||
lastPart := parts[3]
|
||||
lastNum, _ := strconv.Atoi(lastPart)
|
||||
lastNum += i
|
||||
newLastPart := strconv.Itoa(lastNum)
|
||||
parts[3] = newLastPart
|
||||
newIP := strings.Join(parts, ".")
|
||||
user.StaticIp = newIP
|
||||
// 更新
|
||||
results, err := datasource.DefaultDB().Table("u_sub_user").Update(user)
|
||||
if err == nil {
|
||||
log.Errorf("Update err => %v", err)
|
||||
insertNum += results
|
||||
}
|
||||
}
|
||||
}
|
||||
return insertNum
|
||||
}
|
||||
|
||||
// UpdateSmData 批量修改sm-data
|
||||
func (r *RepoUdmSubUser) UpdateSmData(neID string, subUser model.UdmSubUser) int64 {
|
||||
var insertNum int64
|
||||
|
||||
imsiV, err := strconv.Atoi(subUser.Imsi)
|
||||
if err != nil || subUser.StaticIp == "" {
|
||||
return insertNum
|
||||
}
|
||||
numV, err := strconv.Atoi(subUser.SubNum)
|
||||
if err != nil {
|
||||
return insertNum
|
||||
}
|
||||
|
||||
for i := 0; i < numV; i++ {
|
||||
subUser.Imsi = fmt.Sprint(imsiV + i)
|
||||
|
||||
// 查询先
|
||||
var user model.UdmSubUser
|
||||
has, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", subUser.Imsi, neID).Get(&user)
|
||||
if has && err == nil {
|
||||
// IP会自动递增,需提前规划好DNN对应的IP;如dnn不需要绑定IP则不带此字段名
|
||||
// parts := strings.Split(subUser.SmData, "&")
|
||||
user.SmData = subUser.SmData
|
||||
// 更新
|
||||
results, err := datasource.DefaultDB().Table("u_sub_user").Update(user)
|
||||
if err == nil {
|
||||
log.Errorf("Update err => %v", err)
|
||||
insertNum += results
|
||||
}
|
||||
}
|
||||
}
|
||||
return insertNum
|
||||
}
|
||||
|
||||
// Delete 删除实体
|
||||
func (r *RepoUdmSubUser) Delete(neID, imsi string) int64 {
|
||||
results, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", imsi, neID).Delete()
|
||||
if err != nil {
|
||||
log.Errorf("Delete err => %v", err)
|
||||
return results
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// Delete 删除范围实体
|
||||
func (r *RepoUdmSubUser) Deletes(neID, imsi, num string) int64 {
|
||||
imsiV, err := strconv.Atoi(imsi)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
numV, err := strconv.Atoi(num)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
results, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi >= ? and imsi < ? and ne_id = ?", imsiV, imsiV+numV, neID).Delete()
|
||||
if err != nil {
|
||||
log.Errorf("Delete err => %v", err)
|
||||
return results
|
||||
}
|
||||
return results
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/udm_user/model"
|
||||
"nms_cxy/src/framework/redis"
|
||||
)
|
||||
|
||||
// phoneImsiList 获取所有imsi
|
||||
// func phoneImsiList() map[string]string {
|
||||
// phoneAndImsiArr := make(map[string]string, 0)
|
||||
// phoneKeys, err := redis.GetKeys("udmuser", "1*********")
|
||||
// if err != nil {
|
||||
// return phoneAndImsiArr
|
||||
// }
|
||||
// for _, phone := range phoneKeys {
|
||||
// imsi, err := redis.Get("udmuser", phone)
|
||||
// if err != nil {
|
||||
// continue
|
||||
// }
|
||||
// phoneAndImsiArr[phone] = imsi
|
||||
// }
|
||||
// return phoneAndImsiArr
|
||||
// }
|
||||
|
||||
// redisUdmAuthUserList UDM鉴权用户
|
||||
func redisUdmAuthUserList() []model.UdmAuthUser {
|
||||
user := []model.UdmAuthUser{}
|
||||
ausfArr, err := redis.GetKeys("udmuser", "ausf:*")
|
||||
if err != nil {
|
||||
return user
|
||||
}
|
||||
for _, key := range ausfArr {
|
||||
m, err := redis.GetHash("udmuser", key)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// 跳过-号数据
|
||||
imsi := key[5:]
|
||||
if strings.Contains(imsi, "-") {
|
||||
continue
|
||||
}
|
||||
|
||||
status := "0"
|
||||
if _, ok := m["auth_success"]; ok {
|
||||
status = "1"
|
||||
}
|
||||
amf := ""
|
||||
if v, ok := m["amf"]; ok {
|
||||
amf = strings.Replace(v, "\r\n", "", 1)
|
||||
}
|
||||
a := model.UdmAuthUser{
|
||||
Imsi: imsi,
|
||||
Amf: amf,
|
||||
Status: status,
|
||||
Ki: m["ki"],
|
||||
AlgoIndex: m["algo"],
|
||||
Opc: m["opc"],
|
||||
}
|
||||
user = append(user, a)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
// redisUdmSubUserList UDM签约用户
|
||||
func redisUdmSubUserList() []model.UdmSubUser {
|
||||
user := []model.UdmSubUser{}
|
||||
udmsdArr, err := redis.GetKeys("udmuser", "udm-sd:*")
|
||||
if err != nil {
|
||||
return user
|
||||
}
|
||||
for _, key := range udmsdArr {
|
||||
m, err := redis.GetHash("udmuser", key)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
a := model.UdmSubUser{
|
||||
Imsi: key[7:],
|
||||
Msisdn: m["gpsi"], // 46003550072 strings.TrimPrefix(m["gpsi"], "86"),
|
||||
SmfSel: m["smf-sel"],
|
||||
SmData: m["sm-dat"], // 1-000001&cmnet&ims&3gnet
|
||||
}
|
||||
|
||||
// def_ambr,def_nssai,0,def_arfb,def_sar,3,1,12000,1,1000,0,1,-
|
||||
if v, ok := m["am-dat"]; ok {
|
||||
arr := strings.Split(v, ",")
|
||||
a.Ambr = arr[0]
|
||||
a.Nssai = arr[1]
|
||||
a.Rat = arr[2]
|
||||
a.Arfb = arr[3]
|
||||
a.Sar = arr[4]
|
||||
a.Cn = arr[5]
|
||||
}
|
||||
// 1,64,24,65,def_eps,1,2,010200000000,-
|
||||
if v, ok := m["eps-dat"]; ok {
|
||||
arr := strings.Split(v, ",")
|
||||
// 跳过非常规数据
|
||||
if len(arr) > 9 {
|
||||
continue
|
||||
}
|
||||
a.EpsDat = v
|
||||
a.EpsFlag = arr[0]
|
||||
a.EpsOdb = arr[1]
|
||||
a.HplmnOdb = arr[2]
|
||||
a.Ard = arr[3]
|
||||
a.Epstpl = arr[4]
|
||||
a.ContextId = arr[5]
|
||||
a.ApnContext = arr[7]
|
||||
// [6] 是不要的,导入和导出不用
|
||||
a.StaticIp = arr[8]
|
||||
}
|
||||
|
||||
user = append(user, a)
|
||||
}
|
||||
return user
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"nms_cxy/features/udm_user/model"
|
||||
"nms_cxy/features/udm_user/repo"
|
||||
)
|
||||
|
||||
// 实例化服务层 ServiceUdmAuthUser 结构体
|
||||
var NewServiceUdmAuthUser = &ServiceUdmAuthUser{
|
||||
repoAuthUser: *repo.NewRepoUdmAuthUser,
|
||||
}
|
||||
|
||||
// ServiceUdmAuthUser UDM鉴权用户 服务层处理
|
||||
type ServiceUdmAuthUser struct {
|
||||
repoAuthUser repo.RepoUdmAuthUser
|
||||
}
|
||||
|
||||
// Save UDM鉴权用户-获取全部保存数据库
|
||||
func (r *ServiceUdmAuthUser) Save(neID string) int64 {
|
||||
var num int64 = 0
|
||||
authArr := redisUdmAuthUserList()
|
||||
// 有数据才清空
|
||||
if len(authArr) == 0 {
|
||||
return num
|
||||
}
|
||||
go r.repoAuthUser.ClearAndInsert(neID, authArr)
|
||||
return int64(len(authArr))
|
||||
}
|
||||
|
||||
// Page UDM签约用户-分页查询数据库
|
||||
func (r *ServiceUdmAuthUser) Page(query map[string]any) map[string]any {
|
||||
return r.repoAuthUser.SelectPage(query)
|
||||
}
|
||||
|
||||
// List UDM签约用户-查询数据库
|
||||
func (r *ServiceUdmAuthUser) List(authUser model.UdmAuthUser) []model.UdmAuthUser {
|
||||
return r.repoAuthUser.SelectList(authUser)
|
||||
}
|
||||
|
||||
// Insert UDM鉴权用户-新增单个
|
||||
// imsi长度15,ki长度32,opc长度0或者32
|
||||
func (r *ServiceUdmAuthUser) Insert(neID string, authUser model.UdmAuthUser) int64 {
|
||||
authUser.NeID = neID
|
||||
authUser.Status = "0"
|
||||
return r.repoAuthUser.Insert(authUser)
|
||||
}
|
||||
|
||||
// Insert UDM鉴权用户-批量添加
|
||||
func (r *ServiceUdmAuthUser) Inserts(neID string, authUser model.UdmAuthUser, num string) int64 {
|
||||
var arr []model.UdmAuthUser
|
||||
|
||||
imsiVlen := len(authUser.Imsi)
|
||||
imsiV, err := strconv.Atoi(authUser.Imsi)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
numV, err := strconv.Atoi(num)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
authUser.NeID = neID
|
||||
authUser.Status = "0"
|
||||
for i := 0; i < numV; i++ {
|
||||
imsi := fmt.Sprint(imsiV + i)
|
||||
if len(imsi) < imsiVlen {
|
||||
imsi = fmt.Sprintf("%0*s", imsiVlen, imsi)
|
||||
}
|
||||
authUser.Imsi = imsi
|
||||
arr = append(arr, authUser)
|
||||
}
|
||||
|
||||
return r.repoAuthUser.Inserts(arr)
|
||||
}
|
||||
|
||||
// InsertCSV UDM鉴权用户-批量添加
|
||||
func (r *ServiceUdmAuthUser) InsertCSV(neID string, data []map[string]string) int64 {
|
||||
var arr []model.UdmAuthUser
|
||||
for _, v := range data {
|
||||
var authUser model.UdmAuthUser
|
||||
authUser.NeID = neID
|
||||
authUser.Status = "0"
|
||||
if s, ok := v["imsi"]; ok {
|
||||
authUser.Imsi = s
|
||||
}
|
||||
if s, ok := v["ki"]; ok {
|
||||
authUser.Ki = s
|
||||
}
|
||||
if s, ok := v["algo"]; ok {
|
||||
authUser.AlgoIndex = s
|
||||
}
|
||||
if s, ok := v["amf"]; ok {
|
||||
authUser.Amf = s
|
||||
}
|
||||
if s, ok := v["opc"]; ok {
|
||||
authUser.Opc = s
|
||||
}
|
||||
|
||||
if authUser.Imsi == "" {
|
||||
continue
|
||||
}
|
||||
arr = append(arr, authUser)
|
||||
}
|
||||
return r.repoAuthUser.Inserts(arr)
|
||||
}
|
||||
|
||||
// InsertTxt UDM鉴权用户-批量添加
|
||||
func (r *ServiceUdmAuthUser) InsertTxt(neID string, data [][]string) int64 {
|
||||
var arr []model.UdmAuthUser
|
||||
for _, v := range data {
|
||||
if len(v) < 4 {
|
||||
continue
|
||||
}
|
||||
var authUser model.UdmAuthUser
|
||||
authUser.NeID = neID
|
||||
authUser.Status = "0"
|
||||
authUser.Imsi = v[0]
|
||||
authUser.Ki = v[1]
|
||||
authUser.AlgoIndex = v[2]
|
||||
authUser.Amf = v[3]
|
||||
if len(v) == 5 {
|
||||
authUser.Opc = v[4]
|
||||
}
|
||||
|
||||
if authUser.Imsi == "" {
|
||||
continue
|
||||
}
|
||||
arr = append(arr, authUser)
|
||||
}
|
||||
|
||||
return r.repoAuthUser.Inserts(arr)
|
||||
}
|
||||
|
||||
// Insert UDM鉴权用户-修改更新
|
||||
func (r *ServiceUdmAuthUser) Update(neID string, authUser model.UdmAuthUser) int64 {
|
||||
return r.repoAuthUser.Update(neID, authUser)
|
||||
}
|
||||
|
||||
// Insert UDM鉴权用户-删除单个
|
||||
func (r *ServiceUdmAuthUser) Delete(neID, imsi string) int64 {
|
||||
return r.repoAuthUser.Delete(neID, imsi)
|
||||
}
|
||||
|
||||
// Insert UDM鉴权用户-删除范围
|
||||
func (r *ServiceUdmAuthUser) Deletes(neID, imsi, num string) int64 {
|
||||
return r.repoAuthUser.Deletes(neID, imsi, num)
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/udm_user/model"
|
||||
"nms_cxy/features/udm_user/repo"
|
||||
)
|
||||
|
||||
// 实例化服务层 ServiceUdmSubUser 结构体
|
||||
var NewServiceUdmSubUser = &ServiceUdmSubUser{
|
||||
repoSunUser: *repo.NewRepoUdmSubUser,
|
||||
}
|
||||
|
||||
// ServiceUdmSubUser UDM签约用户 服务层处理
|
||||
type ServiceUdmSubUser struct {
|
||||
repoSunUser repo.RepoUdmSubUser
|
||||
}
|
||||
|
||||
// Save UDM签约用户-获取全部保存数据库
|
||||
func (r *ServiceUdmSubUser) Save(neID string) int64 {
|
||||
var num int64 = 0
|
||||
subArr := redisUdmSubUserList()
|
||||
// 有数据才清空
|
||||
if len(subArr) == 0 {
|
||||
return num
|
||||
}
|
||||
go r.repoSunUser.ClearAndInsert(neID, subArr)
|
||||
return int64(len(subArr))
|
||||
}
|
||||
|
||||
// Page UDM签约用户-分页查询数据库
|
||||
func (r *ServiceUdmSubUser) Page(query map[string]any) map[string]any {
|
||||
return r.repoSunUser.SelectPage(query)
|
||||
}
|
||||
|
||||
// List UDM签约用户-查询数据库
|
||||
func (r *ServiceUdmSubUser) List(subUser model.UdmSubUser) []model.UdmSubUser {
|
||||
return r.repoSunUser.SelectList(subUser)
|
||||
}
|
||||
|
||||
// Insert UDM签约用户-新增单个
|
||||
// imsi长度15,ki长度32,opc长度0或者32
|
||||
func (r *ServiceUdmSubUser) Insert(neID string, subUser model.UdmSubUser) int64 {
|
||||
subUser.NeID = neID
|
||||
return r.repoSunUser.Insert(subUser)
|
||||
}
|
||||
|
||||
// Insert UDM签约用户-批量添加
|
||||
func (r *ServiceUdmSubUser) Inserts(neID string, subUser model.UdmSubUser, num string) int64 {
|
||||
var arr []model.UdmSubUser
|
||||
|
||||
imsiVlen := len(subUser.Imsi)
|
||||
imsiV, err := strconv.Atoi(subUser.Imsi)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
msisdnVlen := len(subUser.Msisdn)
|
||||
msisdnV, err := strconv.Atoi(subUser.Msisdn)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
numV, err := strconv.Atoi(num)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
subUser.NeID = neID
|
||||
for i := 0; i < numV; i++ {
|
||||
msisdn := fmt.Sprint(msisdnV + i)
|
||||
if len(msisdn) < msisdnVlen {
|
||||
msisdn = fmt.Sprintf("%0*s", msisdnVlen, msisdn)
|
||||
}
|
||||
subUser.Msisdn = msisdn
|
||||
|
||||
imsi := fmt.Sprint(imsiV + i)
|
||||
if len(imsi) < imsiVlen {
|
||||
imsi = fmt.Sprintf("%0*s", imsiVlen, imsi)
|
||||
}
|
||||
subUser.Imsi = imsi
|
||||
|
||||
// IP会自动递增
|
||||
if len(subUser.StaticIp) > 5 {
|
||||
parts := strings.Split(subUser.StaticIp, ".")
|
||||
lastPart := parts[3]
|
||||
lastNum, _ := strconv.Atoi(lastPart)
|
||||
lastNum += i
|
||||
newLastPart := strconv.Itoa(lastNum)
|
||||
parts[3] = newLastPart
|
||||
newIP := strings.Join(parts, ".")
|
||||
subUser.StaticIp = newIP
|
||||
}
|
||||
|
||||
subUser.EpsDat = fmt.Sprintf("%s,%s,%s,%s,%s,%s,2,%s,%s", subUser.EpsFlag, subUser.EpsOdb, subUser.HplmnOdb, subUser.Ard, subUser.Epstpl, subUser.ContextId, subUser.ApnContext, subUser.StaticIp)
|
||||
|
||||
arr = append(arr, subUser)
|
||||
}
|
||||
|
||||
return r.repoSunUser.Inserts(arr)
|
||||
}
|
||||
|
||||
// InsertCSV UDM签约用户-批量添加
|
||||
func (r *ServiceUdmSubUser) InsertCSV(neID string, data []map[string]string) int64 {
|
||||
var arr []model.UdmSubUser
|
||||
for _, v := range data {
|
||||
var subUser model.UdmSubUser
|
||||
subUser.NeID = neID
|
||||
if s, ok := v["imsi"]; ok {
|
||||
subUser.Imsi = s
|
||||
}
|
||||
if s, ok := v["msisdn"]; ok {
|
||||
subUser.Msisdn = s
|
||||
}
|
||||
if s, ok := v["ambr"]; ok {
|
||||
subUser.Ambr = s
|
||||
}
|
||||
if s, ok := v["nssai"]; ok {
|
||||
subUser.Nssai = s
|
||||
}
|
||||
if s, ok := v["arfb"]; ok {
|
||||
subUser.Arfb = s
|
||||
}
|
||||
if s, ok := v["sar"]; ok {
|
||||
subUser.Sar = s
|
||||
}
|
||||
if s, ok := v["rat"]; ok {
|
||||
subUser.Rat = s
|
||||
}
|
||||
if s, ok := v["cn"]; ok {
|
||||
subUser.Cn = s
|
||||
}
|
||||
if s, ok := v["smf_sel"]; ok {
|
||||
subUser.SmfSel = s
|
||||
}
|
||||
if s, ok := v["sm_dat"]; ok {
|
||||
subUser.SmData = s
|
||||
}
|
||||
if s, ok := v["eps_dat"]; ok {
|
||||
subUser.EpsDat = s
|
||||
arr := strings.Split(s, ",")
|
||||
if len(arr) == 8 {
|
||||
subUser.EpsFlag = arr[0]
|
||||
subUser.EpsOdb = arr[1]
|
||||
subUser.HplmnOdb = arr[2]
|
||||
subUser.Ard = arr[3]
|
||||
subUser.Epstpl = arr[4]
|
||||
subUser.ContextId = arr[5]
|
||||
subUser.ApnContext = arr[6]
|
||||
subUser.StaticIp = arr[7]
|
||||
}
|
||||
}
|
||||
|
||||
if subUser.Imsi == "" {
|
||||
continue
|
||||
}
|
||||
arr = append(arr, subUser)
|
||||
}
|
||||
return r.repoSunUser.Inserts(arr)
|
||||
}
|
||||
|
||||
// InsertTxt UDM签约用户-批量添加
|
||||
func (r *ServiceUdmSubUser) InsertTxt(neID string, data [][]string) int64 {
|
||||
var arr []model.UdmSubUser
|
||||
for _, v := range data {
|
||||
if len(v) < 10 {
|
||||
continue
|
||||
}
|
||||
var subUser model.UdmSubUser
|
||||
subUser.NeID = neID
|
||||
subUser.Imsi = v[0]
|
||||
subUser.Msisdn = v[1]
|
||||
subUser.Ambr = v[2]
|
||||
subUser.Nssai = v[3]
|
||||
subUser.Arfb = v[4]
|
||||
subUser.Sar = v[5]
|
||||
subUser.Rat = v[6]
|
||||
subUser.Cn = v[7]
|
||||
subUser.SmfSel = v[8]
|
||||
subUser.SmData = v[9]
|
||||
if len(v) > 17 {
|
||||
subUser.EpsFlag = v[10]
|
||||
subUser.EpsOdb = v[11]
|
||||
subUser.HplmnOdb = v[12]
|
||||
subUser.Ard = v[13]
|
||||
subUser.Epstpl = v[14]
|
||||
subUser.ContextId = v[15]
|
||||
subUser.ApnContext = v[16]
|
||||
subUser.StaticIp = v[17]
|
||||
subUser.EpsDat = strings.Join(v[10:], ",")
|
||||
}
|
||||
|
||||
if subUser.Imsi == "" {
|
||||
continue
|
||||
}
|
||||
arr = append(arr, subUser)
|
||||
}
|
||||
return r.repoSunUser.Inserts(arr)
|
||||
}
|
||||
|
||||
// Insert UDM签约用户-批量添加4G用户
|
||||
func (r *ServiceUdmSubUser) Insert4G(neID string, subUser model.UdmSubUser) int64 {
|
||||
return r.repoSunUser.Insert4G(neID, subUser)
|
||||
}
|
||||
|
||||
// Insert UDM签约用户-修改更新
|
||||
func (r *ServiceUdmSubUser) Update(neID string, subUser model.UdmSubUser) int64 {
|
||||
return r.repoSunUser.Update(neID, subUser)
|
||||
}
|
||||
|
||||
// Update4GIP UDM签约用户-批量修改4G IP
|
||||
func (r *ServiceUdmSubUser) Update4GIP(neID string, subUser model.UdmSubUser) int64 {
|
||||
return r.repoSunUser.Update4GIP(neID, subUser)
|
||||
}
|
||||
|
||||
// Update4GIP UDM签约用户-批量修改sm-data
|
||||
func (r *ServiceUdmSubUser) UpdateSmData(neID string, subUser model.UdmSubUser) int64 {
|
||||
return r.repoSunUser.UpdateSmData(neID, subUser)
|
||||
}
|
||||
|
||||
// Insert UDM签约用户-删除单个
|
||||
func (r *ServiceUdmSubUser) Delete(neID, imsi string) int64 {
|
||||
return r.repoSunUser.Delete(neID, imsi)
|
||||
}
|
||||
|
||||
// Insert UDM签约用户-删除范围
|
||||
func (r *ServiceUdmSubUser) Deletes(neID, imsi, num string) int64 {
|
||||
return r.repoSunUser.Deletes(neID, imsi, num)
|
||||
}
|
||||
@@ -8,12 +8,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/ctx"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/global"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/lib/services"
|
||||
"nms_cxy/omc/config"
|
||||
tokenConst "nms_cxy/src/framework/constants/token"
|
||||
neService "nms_cxy/src/modules/network_element/service"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/gorilla/mux"
|
||||
@@ -47,6 +49,7 @@ type SmfUEInfo struct {
|
||||
UpfN3IP string `json:"upfN3IP"`
|
||||
RanN3IP string `json:"ranN3IP"`
|
||||
Activetime string `json:"activeTime"`
|
||||
UpState string `json:"upState"`
|
||||
} `json:"pduSessionInfo"`
|
||||
}
|
||||
|
||||
@@ -241,66 +244,38 @@ func GetSubscriptionsFromNSSF(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Get UEInfo from NF/NFs
|
||||
func GetUEInfoFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("GetUEInfoFromNF processing... ")
|
||||
log.Debug("GetUEInfoFromNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
neId := ctx.GetQuery(r, "neId")
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
if neType == "" || neId == "" {
|
||||
log.Error("elementTypeValue/neId is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
neInfo := neService.NewNeInfoImpl.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
var response services.MapResponse
|
||||
if neInfo.NeId == neId && neInfo.NeId != "" {
|
||||
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
// SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Get system state from NF is failed:", err)
|
||||
log.Error("Failed to Get from NF:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
var response services.MapResponse
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
log.Debug("response:", response)
|
||||
}
|
||||
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
// POST User Info from NF/NFs
|
||||
|
||||
45
go.mod
45
go.mod
@@ -17,11 +17,13 @@ require (
|
||||
github.com/gosnmp/gosnmp v1.35.0
|
||||
github.com/jasonlvhit/gocron v0.0.1
|
||||
github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f
|
||||
github.com/linxGnu/gosmpp v0.2.0
|
||||
github.com/matoous/go-nanoid/v2 v2.0.0
|
||||
github.com/metaleap/go-xsd v0.0.0-20180330193350-61f7638f502f
|
||||
github.com/mojocn/base64Captcha v1.3.5
|
||||
github.com/mssola/user_agent v0.6.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/prometheus-community/pro-bing v0.4.0
|
||||
github.com/redis/go-redis/v9 v9.1.0
|
||||
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
@@ -32,8 +34,8 @@ require (
|
||||
github.com/xuri/excelize/v2 v2.7.1
|
||||
github.com/xuri/xgen v0.0.0-20230702070049-db840e1a4605
|
||||
github.com/ziutek/telnet v0.0.0-20180329124119-c3b780dc415b
|
||||
golang.org/x/crypto v0.21.0
|
||||
golang.org/x/term v0.18.0
|
||||
golang.org/x/crypto v0.24.0
|
||||
golang.org/x/term v0.21.0
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/mysql v1.5.1
|
||||
@@ -42,7 +44,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/creack/pty v1.1.9 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
@@ -50,8 +52,7 @@ require (
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/go-admin-team/go-admin-core v1.3.12-0.20221121065133-27b7dbe27a8f // indirect
|
||||
github.com/go-gsm/charset v1.0.0 // indirect
|
||||
github.com/go-gsm/ucp v0.0.1 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
@@ -60,21 +61,20 @@ require (
|
||||
github.com/jcmturner/gofork v1.7.6 // indirect
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/klauspost/compress v1.17.7 // indirect
|
||||
github.com/linxGnu/gosmpp v0.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.69 // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
github.com/prometheus-community/pro-bing v0.4.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.48.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/time v0.1.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/IBM/sarama v1.43.0
|
||||
github.com/IBM/sarama v1.43.2
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
|
||||
github.com/bsm/redislock v0.8.2 // indirect
|
||||
github.com/bytedance/go-tagexpr/v2 v2.7.12 // indirect
|
||||
@@ -83,6 +83,7 @@ require (
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chanxuehong/rand v0.0.0-20201110082127-2f19a1bdd973 // indirect
|
||||
github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd // indirect
|
||||
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
@@ -100,7 +101,7 @@ require (
|
||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||
github.com/go-redis/redis/v9 v9.0.0-rc.1 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/goccy/go-json v0.10.3
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
@@ -114,7 +115,7 @@ require (
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 // indirect
|
||||
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 // indirect
|
||||
@@ -125,6 +126,7 @@ require (
|
||||
github.com/mattn/goveralls v0.0.2 // indirect
|
||||
github.com/metaleap/go-util v0.0.0-20180330192724-a09253046f73 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.73
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
@@ -133,7 +135,9 @@ require (
|
||||
github.com/nyaruka/phonenumbers v1.0.55 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.6
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/reiver/go-oi v1.0.0 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.3 // indirect
|
||||
@@ -156,14 +160,13 @@ require (
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/image v0.5.0 // indirect
|
||||
golang.org/x/net v0.22.0
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0
|
||||
golang.org/x/tools v0.16.1 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
golang.org/x/net v0.26.0
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
golang.org/x/text v0.16.0
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.5 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
||||
110
go.sum
110
go.sum
@@ -41,8 +41,8 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0p
|
||||
gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/IBM/sarama v1.43.0 h1:YFFDn8mMI2QL0wOrG0J2sFoVIAFl7hS9JQi2YZsXtJc=
|
||||
github.com/IBM/sarama v1.43.0/go.mod h1:zlE6HEbC/SMQ9mhEYaF7nNLYOUyrs0obySKCckWP9BM=
|
||||
github.com/IBM/sarama v1.43.2 h1:HABeEqRUh32z8yzY2hGB/j8mHSzC/HA9zlEjqFNCzSw=
|
||||
github.com/IBM/sarama v1.43.2/go.mod h1:Kyo4WkF24Z+1nz7xeVUFWIuKVV8RS3wM8mkvPKMdXFQ=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
@@ -67,6 +67,7 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0=
|
||||
@@ -94,16 +95,14 @@ github.com/chanxuehong/rand v0.0.0-20201110082127-2f19a1bdd973/go.mod h1:9+sJ9zv
|
||||
github.com/chanxuehong/util v0.0.0-20200304121633-ca8141845b13/go.mod h1:XEYt99iTxMqkv+gW85JX/DdUINHUe43Sbe5AtqSaDAQ=
|
||||
github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd h1:TM3wjEWel4U31J72dlhnwCBqPC0+FA0Ejm2NCbn5a5U=
|
||||
github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd/go.mod h1:/dvhOIRCjjiZu6NV0QTTiMcc5XwoORbxfDSsRY2IfaM=
|
||||
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a h1:yTfhjWYoPomJkHVArtNHpo36FuOa6Kc2ZjTLvyyQ5Lg=
|
||||
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a/go.mod h1:lINNCb1ZH3c0uL/9ApaQ8muR4QILsi0STj8Ojt8ZmwU=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
@@ -186,10 +185,8 @@ github.com/go-forks/fsnotify v1.4.7/go.mod h1:AU8mot+GznW5+B4jRJHxKg/2EeO+jMORGR
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gsm/charset v1.0.0 h1:6k6LOKHtxgCPXE15X0unRewjOksyhmHBIp6x7qLQ6Ls=
|
||||
github.com/go-gsm/charset v1.0.0/go.mod h1:sC8+2VpAM2sZDlxv11MxWIZiuf8MipOgM/hCYsRQRps=
|
||||
github.com/go-gsm/ucp v0.0.1 h1:vM5ly5iRNGMGGiVx4K3+puF9AhpwkC76BkiV9LFv0bw=
|
||||
github.com/go-gsm/ucp v0.0.1/go.mod h1:58/PrXWFcmaQyZ5p/Dp2YiCnhlVx0HdKXFGmqiVO/mI=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
@@ -223,6 +220,8 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78
|
||||
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
@@ -285,8 +284,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@@ -305,7 +305,6 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@@ -457,20 +456,22 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@@ -537,10 +538,8 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyex
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.69 h1:l8AnsQFyY1xiwa/DaQskY4NXSLA2yrGsW5iD9nRPVS0=
|
||||
github.com/minio/minio-go/v7 v7.0.69/go.mod h1:XAvOPJQ5Xlzk5o3o/ArO2NMbhSGkimC+bpW/ngRKDmQ=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/minio/minio-go/v7 v7.0.73 h1:qr2vi96Qm7kZ4v7LLebjte+MQh621fFWnv93p12htEo=
|
||||
github.com/minio/minio-go/v7 v7.0.73/go.mod h1:qydcVzV8Hqtj1VtEocfxbmVFa2siu6HGa+LDEPogjD8=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
@@ -626,6 +625,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
@@ -637,18 +638,26 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
|
||||
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
@@ -669,8 +678,8 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
@@ -825,12 +834,15 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -875,7 +887,6 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -916,13 +927,16 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
|
||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -946,6 +960,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1009,29 +1025,31 @@ golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1040,16 +1058,17 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -1112,6 +1131,7 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
|
||||
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1216,8 +1236,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.5 h1:QoEEmn/d5BbuPIL2qvXwzJdttFFhRQFkaq+tEKb7SMI=
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.5/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
package account
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
sysMenuService "nms_cxy/features/sys_menu/service"
|
||||
sysRoleService "nms_cxy/features/sys_role/service"
|
||||
"nms_cxy/lib/core/cache"
|
||||
"nms_cxy/lib/core/vo"
|
||||
"nms_cxy/lib/dborm"
|
||||
srcConfig "nms_cxy/src/framework/config"
|
||||
)
|
||||
|
||||
// 登录缓存用户信息
|
||||
func CacheLoginUser(user *dborm.User) {
|
||||
// 过期时间
|
||||
expiresStr, err := dborm.XormGetConfigValue("Security", "sessionExpires")
|
||||
if err != nil {
|
||||
expiresStr = "18000"
|
||||
}
|
||||
expiresValue, _ := strconv.Atoi(expiresStr)
|
||||
expireTime := time.Duration(expiresValue) * time.Second
|
||||
|
||||
nowTime := time.Now().UnixMilli()
|
||||
|
||||
// 登录用户
|
||||
loginUser := vo.LoginUser{
|
||||
UserID: fmt.Sprint(user.Id),
|
||||
UserName: user.Name,
|
||||
ExpireTime: nowTime + expireTime.Milliseconds(),
|
||||
LoginTime: nowTime,
|
||||
User: *user,
|
||||
}
|
||||
|
||||
// 是否管理员
|
||||
if srcConfig.IsAdmin(loginUser.UserID) {
|
||||
loginUser.Permissions = []string{"*:*:*"}
|
||||
} else {
|
||||
// 获取权限标识
|
||||
loginUser.Permissions = sysMenuService.NewRepoSysMenu.SelectMenuPermsByUserId(loginUser.UserID)
|
||||
// 获取角色信息
|
||||
loginUser.User.Roles = sysRoleService.NewRepoSysRole.SelectRoleListByUserId(loginUser.UserID)
|
||||
}
|
||||
|
||||
// 缓存时间
|
||||
cache.SetLocalTTL(user.AccountId, loginUser, time.Duration(expireTime))
|
||||
}
|
||||
|
||||
// 清除缓存用户信息
|
||||
func ClearLoginUser(accountId string) {
|
||||
cache.DeleteLocalTTL(accountId)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package cachekey
|
||||
|
||||
// 缓存的key常量
|
||||
|
||||
// 登录用户
|
||||
const LOGIN_TOKEN_KEY = "login_tokens:"
|
||||
|
||||
// 验证码
|
||||
const CAPTCHA_CODE_KEY = "captcha_codes:"
|
||||
|
||||
// 参数管理
|
||||
const SYS_CONFIG_KEY = "sys_config:"
|
||||
|
||||
// 字典管理
|
||||
const SYS_DICT_KEY = "sys_dict:"
|
||||
|
||||
// 防重提交
|
||||
const REPEAT_SUBMIT_KEY = "repeat_submit:"
|
||||
|
||||
// 限流
|
||||
const RATE_LIMIT_KEY = "rate_limit:"
|
||||
|
||||
// 登录账户密码错误次数
|
||||
const PWD_ERR_CNT_KEY = "pwd_err_cnt:"
|
||||
@@ -10,16 +10,16 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/lib/core/vo"
|
||||
commonConstants "nms_cxy/src/framework/constants/common"
|
||||
tokenConst "nms_cxy/src/framework/constants/token"
|
||||
"nms_cxy/src/framework/constants/token"
|
||||
tokenUtils "nms_cxy/src/framework/utils/token"
|
||||
"nms_cxy/src/framework/vo"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// Param 地址栏参数{id}
|
||||
func Param(r *http.Request, key string) string {
|
||||
// GetParam 地址栏参数{id}
|
||||
func GetParam(r *http.Request, key string) string {
|
||||
vars := mux.Vars(r)
|
||||
v, ok := vars[key]
|
||||
if ok {
|
||||
@@ -48,7 +48,7 @@ func QueryMap(r *http.Request) map[string]any {
|
||||
return queryParams
|
||||
}
|
||||
|
||||
// ShouldBindQuery 查询参数读取json请求结构团体
|
||||
// ShouldBindQuery 查询参数读取json请求结构团体 &xxx
|
||||
func ShouldBindQuery(r *http.Request, args any) error {
|
||||
queryParams := QueryMap(r)
|
||||
body, err := json.Marshal(queryParams)
|
||||
@@ -58,7 +58,7 @@ func ShouldBindQuery(r *http.Request, args any) error {
|
||||
return json.Unmarshal(body, args)
|
||||
}
|
||||
|
||||
// 读取json请求结构团体
|
||||
// ShouldBindJSON 读取json请求结构团体 &xxx
|
||||
func ShouldBindJSON(r *http.Request, args any) error {
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) // 设置较大的长度,例如 1<<20 (1MB)
|
||||
if err != nil {
|
||||
@@ -123,12 +123,26 @@ func SaveUploadedFile(r *http.Request, dst string) error {
|
||||
|
||||
// Authorization 解析请求头
|
||||
func Authorization(r *http.Request) string {
|
||||
authHeader := r.Header.Get(tokenConst.HEADER_KEY)
|
||||
// Query请求查询
|
||||
if authQuery := r.URL.Query().Get(token.ACCESS_TOKEN); authQuery != "" {
|
||||
return authQuery
|
||||
}
|
||||
// Header请求头
|
||||
if authHeader := r.Header.Get(token.ACCESS_TOKEN); authHeader != "" {
|
||||
return authHeader
|
||||
}
|
||||
|
||||
// Query请求查询
|
||||
if authQuery := r.URL.Query().Get(token.RESPONSE_FIELD); authQuery != "" {
|
||||
return authQuery
|
||||
}
|
||||
// Header请求头
|
||||
authHeader := r.Header.Get(token.HEADER_KEY)
|
||||
if authHeader == "" {
|
||||
return ""
|
||||
}
|
||||
// 拆分 Authorization 请求头,提取 JWT 令牌部分
|
||||
arr := strings.Split(authHeader, tokenConst.HEADER_PREFIX)
|
||||
arr := strings.Split(authHeader, token.HEADER_PREFIX)
|
||||
if len(arr) == 2 && arr[1] == "" {
|
||||
return ""
|
||||
}
|
||||
@@ -165,12 +179,24 @@ type ContextKey string
|
||||
|
||||
// LoginUser 登录用户信息需要Authorize中间件
|
||||
func LoginUser(r *http.Request) (vo.LoginUser, error) {
|
||||
// 上下文
|
||||
v := r.Context().Value(ContextKey(commonConstants.CTX_LOGIN_USER))
|
||||
if v != nil {
|
||||
return v.(vo.LoginUser), nil
|
||||
// 获取请求头标识信息
|
||||
tokenStr := Authorization(r)
|
||||
if tokenStr == "" {
|
||||
return vo.LoginUser{}, fmt.Errorf("not token info")
|
||||
}
|
||||
return vo.LoginUser{}, fmt.Errorf("No user information")
|
||||
// 验证令牌
|
||||
claims, err := tokenUtils.Verify(tokenStr)
|
||||
if err != nil {
|
||||
return vo.LoginUser{}, fmt.Errorf("token verify fail")
|
||||
}
|
||||
|
||||
// 获取缓存的用户信息
|
||||
loginUser := tokenUtils.LoginUser(claims)
|
||||
if loginUser.UserID == "" {
|
||||
return vo.LoginUser{}, fmt.Errorf("not user info")
|
||||
}
|
||||
|
||||
return loginUser, nil
|
||||
}
|
||||
|
||||
// LoginUserToUserID 登录用户信息-用户ID
|
||||
@@ -188,5 +214,5 @@ func LoginUserToUserName(r *http.Request) string {
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return loginUser.UserName
|
||||
return loginUser.User.UserName
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package datasource
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"regexp"
|
||||
|
||||
"nms_cxy/lib/dborm"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// 获取默认数据源
|
||||
func DefaultDB() *xorm.Engine {
|
||||
return dborm.DbClient.XEngine
|
||||
}
|
||||
|
||||
// RawDB 原生查询语句
|
||||
func RawDB(source string, sql string, parameters []any) ([]map[string]any, error) {
|
||||
// 数据源
|
||||
db := DefaultDB()
|
||||
|
||||
// 使用正则表达式替换连续的空白字符为单个空格
|
||||
fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ")
|
||||
|
||||
// log.Infof("sql=> %v", fmtSql)
|
||||
// log.Infof("parameters=> %v", parameters)
|
||||
|
||||
// 查询结果
|
||||
var rows []map[string]any
|
||||
err := db.SQL(fmtSql, parameters...).Find(&rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// ExecDB 原生执行语句
|
||||
func ExecDB(source string, sql string, parameters []any) (sql.Result, error) {
|
||||
// 数据源
|
||||
db := DefaultDB()
|
||||
|
||||
// 使用正则表达式替换连续的空白字符为单个空格
|
||||
fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ")
|
||||
// 执行结果
|
||||
res, err := db.Exec(append([]any{fmtSql}, parameters...)...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
package datasource
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PageNumSize 分页页码记录数
|
||||
func PageNumSize(pageNum, pageSize any) (int, int) {
|
||||
// 记录起始索引
|
||||
pageNumStr := fmt.Sprintf("%v", pageNum)
|
||||
num := 1
|
||||
if v, err := strconv.Atoi(pageNumStr); err == nil && v > 0 {
|
||||
num = v
|
||||
}
|
||||
|
||||
// 显示记录数
|
||||
pageSizeStr := fmt.Sprintf("%v", pageSize)
|
||||
size := 10
|
||||
if v, err := strconv.Atoi(pageSizeStr); err == nil && v > 0 {
|
||||
size = v
|
||||
}
|
||||
return num - 1, size
|
||||
}
|
||||
|
||||
// SetFieldValue 判断结构体内是否存在指定字段并设置值
|
||||
func SetFieldValue(obj any, fieldName string, value any) {
|
||||
// 获取结构体的反射值
|
||||
userValue := reflect.ValueOf(obj)
|
||||
|
||||
// 获取字段的反射值
|
||||
fieldValue := userValue.Elem().FieldByName(fieldName)
|
||||
|
||||
// 检查字段是否存在
|
||||
if fieldValue.IsValid() && fieldValue.CanSet() {
|
||||
// 获取字段的类型
|
||||
fieldType := fieldValue.Type()
|
||||
|
||||
// 转换传入的值类型为字段类型
|
||||
switch fieldType.Kind() {
|
||||
case reflect.String:
|
||||
if value == nil {
|
||||
fieldValue.SetString("")
|
||||
} else {
|
||||
fieldValue.SetString(fmt.Sprintf("%v", value))
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
intValue, err := strconv.ParseInt(fmt.Sprintf("%v", value), 10, 64)
|
||||
if err != nil {
|
||||
intValue = 0
|
||||
}
|
||||
fieldValue.SetInt(intValue)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
uintValue, err := strconv.ParseUint(fmt.Sprintf("%v", value), 10, 64)
|
||||
if err != nil {
|
||||
uintValue = 0
|
||||
}
|
||||
fieldValue.SetUint(uintValue)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
floatValue, err := strconv.ParseFloat(fmt.Sprintf("%v", value), 64)
|
||||
if err != nil {
|
||||
floatValue = 0
|
||||
}
|
||||
fieldValue.SetFloat(floatValue)
|
||||
default:
|
||||
// 设置字段的值
|
||||
fieldValue.Set(reflect.ValueOf(value).Convert(fieldValue.Type()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertIdsSlice 将 []string 转换为 []any
|
||||
func ConvertIdsSlice(ids []string) []any {
|
||||
// 将 []string 转换为 []any
|
||||
arr := make([]any, len(ids))
|
||||
for i, v := range ids {
|
||||
arr[i] = v
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// 查询-参数值的占位符
|
||||
func KeyPlaceholderByQuery(sum int) string {
|
||||
placeholders := make([]string, sum)
|
||||
for i := 0; i < sum; i++ {
|
||||
placeholders[i] = "?"
|
||||
}
|
||||
return strings.Join(placeholders, ",")
|
||||
}
|
||||
|
||||
// 插入-参数映射键值占位符 keys, placeholder, values
|
||||
func KeyPlaceholderValueByInsert(params map[string]any) ([]string, string, []any) {
|
||||
// 参数映射的键
|
||||
keys := make([]string, len(params))
|
||||
// 参数映射的值
|
||||
values := make([]any, len(params))
|
||||
sum := 0
|
||||
for k, v := range params {
|
||||
keys[sum] = k
|
||||
values[sum] = v
|
||||
sum++
|
||||
}
|
||||
// 参数值的占位符
|
||||
placeholders := make([]string, sum)
|
||||
for i := 0; i < sum; i++ {
|
||||
placeholders[i] = "?"
|
||||
}
|
||||
return keys, strings.Join(placeholders, ","), values
|
||||
}
|
||||
|
||||
// 更新-参数映射键值占位符 keys, values
|
||||
func KeyValueByUpdate(params map[string]any) ([]string, []any) {
|
||||
// 参数映射的键
|
||||
keys := make([]string, len(params))
|
||||
// 参数映射的值
|
||||
values := make([]any, len(params))
|
||||
sum := 0
|
||||
for k, v := range params {
|
||||
keys[sum] = k + "=?"
|
||||
values[sum] = v
|
||||
sum++
|
||||
}
|
||||
return keys, values
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package mmlclient
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/conf"
|
||||
)
|
||||
|
||||
// 定义MMLClient结构体
|
||||
type MMLClient struct {
|
||||
awaitTime time.Duration // 等待时间
|
||||
conn net.Conn
|
||||
reader *bufio.Reader
|
||||
size int // 包含字符
|
||||
}
|
||||
|
||||
// 封装NewMMLClient函数,用于创建MMLClient实例
|
||||
// 网元UDM的IP地址 "198.51.100.1"
|
||||
func NewMMLClient(ip string) (*MMLClient, error) {
|
||||
// 创建TCP连接
|
||||
portMML := conf.Get("mml.port").(int)
|
||||
hostMML := fmt.Sprintf("%s:%d", ip, portMML)
|
||||
conn, err := net.Dial("tcp", hostMML)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 进行登录
|
||||
usernameMML := conf.Get("mml.user").(string)
|
||||
passwordMML := conf.Get("mml.password").(string)
|
||||
fmt.Fprintln(conn, usernameMML)
|
||||
fmt.Fprintln(conn, passwordMML)
|
||||
|
||||
// 发送后等待
|
||||
awaitTime := time.Duration(300) * time.Millisecond
|
||||
time.Sleep(awaitTime)
|
||||
|
||||
// 读取内容
|
||||
buf := make([]byte, 1024*1024*1)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建MMLClient实例
|
||||
client := &MMLClient{
|
||||
conn: conn,
|
||||
reader: bufio.NewReader(conn),
|
||||
awaitTime: awaitTime,
|
||||
size: n,
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// 封装Send函数,用于向TCP连接发送数据
|
||||
func (c *MMLClient) Send(msg string) error {
|
||||
_, err := fmt.Fprintln(c.conn, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(c.awaitTime)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 封装Receive函数,用于从TCP连接中接收数据
|
||||
func (c *MMLClient) Receive() (string, error) {
|
||||
buf := make([]byte, 1024*1024*1)
|
||||
n, err := c.reader.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return "", fmt.Errorf("server closed the connection")
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
c.size += n
|
||||
return string(buf[0:n]), nil
|
||||
}
|
||||
|
||||
// 封装Close函数,用于关闭TCP连接
|
||||
func (c *MMLClient) Close() error {
|
||||
return c.conn.Close()
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package mmlclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 发送MML原始消息
|
||||
// ip 网元IP地址
|
||||
// msg 指令
|
||||
func MMLSendMsg(ip, msg string) (string, error) {
|
||||
// 创建MMLClient实例
|
||||
client, err := NewMMLClient(ip)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create MMLClient instance: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 发送数据
|
||||
err = client.Send(msg)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("sending data failed: %v", err)
|
||||
}
|
||||
|
||||
// 接收数据
|
||||
data, err := client.Receive()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to receive data: %v", err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// 发送MML
|
||||
// ip 网元IP地址
|
||||
// msg 指令
|
||||
func MMLSendMsgToString(ip, msg string) (string, error) {
|
||||
// 发送获取数据
|
||||
str, err := MMLSendMsg(ip, msg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
str = strings.ToLower(str)
|
||||
|
||||
// 截断
|
||||
index := strings.Index(str, "\n")
|
||||
if index != -1 {
|
||||
str = str[:index]
|
||||
}
|
||||
|
||||
// 命令成功
|
||||
if strings.Contains(str, "ok") || strings.Contains(str, "success") {
|
||||
return str, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf(str)
|
||||
}
|
||||
|
||||
// 发送MML
|
||||
// ip 网元IP地址
|
||||
// msg 指令
|
||||
func MMLSendMsgToMap(ip, msg string) (map[string]string, error) {
|
||||
// 发送获取数据
|
||||
str, err := MMLSendMsg(ip, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 无数据
|
||||
if strings.HasPrefix(str, "No Auth Data") {
|
||||
return nil, fmt.Errorf("no auth data")
|
||||
}
|
||||
|
||||
// 初始化一个map用于存储拆分后的键值对
|
||||
m := make(map[string]string)
|
||||
|
||||
var items []string
|
||||
if strings.Contains(str, "\r\n") {
|
||||
// 按照分隔符"\r\n"进行拆分
|
||||
items = strings.Split(str, "\r\n")
|
||||
} else if strings.Contains(str, "\n") {
|
||||
// 按照分隔符"\n"进行拆分
|
||||
items = strings.Split(str, "\n")
|
||||
}
|
||||
|
||||
// 遍历拆分后的结果
|
||||
for _, item := range items {
|
||||
var pair []string
|
||||
|
||||
if strings.Contains(item, "=") {
|
||||
// 按照分隔符"="进行拆分键值对
|
||||
pair = strings.SplitN(item, "=", 2)
|
||||
} else if strings.Contains(item, ":") {
|
||||
// 按照分隔符":"进行拆分键值对
|
||||
pair = strings.SplitN(item, ":", 2)
|
||||
}
|
||||
|
||||
if len(pair) == 2 {
|
||||
// 将键值对存入map中
|
||||
m[pair[0]] = pair[1]
|
||||
}
|
||||
}
|
||||
return m, err
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package date
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/log"
|
||||
)
|
||||
|
||||
const (
|
||||
// 年 列如:2022
|
||||
YYYY = "2006"
|
||||
// 年-月 列如:2022-12
|
||||
YYYY_MM = "2006-01"
|
||||
// 年-月-日 列如:2022-12-30
|
||||
YYYY_MM_DD = "2006-01-02"
|
||||
// 年月日时分秒 列如:20221230010159
|
||||
YYYYMMDDHHMMSS = "20060102150405"
|
||||
// 年-月-日 时:分:秒 列如:2022-12-30 01:01:59
|
||||
YYYY_MM_DD_HH_MM_SS = "2006-01-02 15:04:05"
|
||||
)
|
||||
|
||||
// 格式时间字符串
|
||||
//
|
||||
// dateStr 时间字符串
|
||||
//
|
||||
// formatStr 时间格式 默认YYYY-MM-DD HH:mm:ss
|
||||
func ParseStrToDate(dateStr, formatStr string) time.Time {
|
||||
t, err := time.Parse(formatStr, dateStr)
|
||||
if err != nil {
|
||||
log.Infof("utils ParseStrToDate err %v", err)
|
||||
return time.Time{}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// 格式时间
|
||||
//
|
||||
// date 可转的Date对象
|
||||
//
|
||||
// formatStr 时间格式 默认YYYY-MM-DD HH:mm:ss
|
||||
func ParseDateToStr(date any, formatStr string) string {
|
||||
t, ok := date.(time.Time)
|
||||
if !ok {
|
||||
switch v := date.(type) {
|
||||
case int64:
|
||||
if v == 0 {
|
||||
return ""
|
||||
}
|
||||
t = time.UnixMilli(v)
|
||||
case string:
|
||||
parsedTime, err := time.Parse(formatStr, v)
|
||||
if err != nil {
|
||||
fmt.Printf("utils ParseDateToStr err %v \n", err)
|
||||
return ""
|
||||
}
|
||||
t = parsedTime
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return t.Format(formatStr)
|
||||
}
|
||||
|
||||
// 格式时间成日期路径
|
||||
//
|
||||
// 年/月 列如:2022/12
|
||||
func ParseDatePath(date time.Time) string {
|
||||
return date.Format("2006/01")
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package parse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
// Number 解析数值型
|
||||
func Number(str any) int64 {
|
||||
switch str := str.(type) {
|
||||
case string:
|
||||
if str == "" {
|
||||
return 0
|
||||
}
|
||||
num, err := strconv.ParseInt(str, 10, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return num
|
||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||||
return reflect.ValueOf(str).Int()
|
||||
case float32, float64:
|
||||
return int64(reflect.ValueOf(str).Float())
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// Boolean 解析布尔型
|
||||
func Boolean(str any) bool {
|
||||
switch str := str.(type) {
|
||||
case string:
|
||||
if str == "" || str == "false" || str == "0" {
|
||||
return false
|
||||
}
|
||||
// 尝试将字符串解析为数字
|
||||
if num, err := strconv.ParseFloat(str, 64); err == nil {
|
||||
return num != 0
|
||||
}
|
||||
return true
|
||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||||
num := reflect.ValueOf(str).Int()
|
||||
return num != 0
|
||||
case float32, float64:
|
||||
num := reflect.ValueOf(str).Float()
|
||||
return num != 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// FirstUpper 首字母转大写
|
||||
//
|
||||
// 字符串 abc_123!@# 结果 Abc_123
|
||||
func FirstUpper(str string) string {
|
||||
if len(str) == 0 {
|
||||
return str
|
||||
}
|
||||
reg := regexp.MustCompile(`[^_\w]+`)
|
||||
str = reg.ReplaceAllString(str, "")
|
||||
return strings.ToUpper(str[:1]) + str[1:]
|
||||
}
|
||||
|
||||
// Bit 比特位为单位
|
||||
func Bit(bit float64) string {
|
||||
var GB, MB, KB string
|
||||
|
||||
if bit > float64(1<<30) {
|
||||
GB = fmt.Sprintf("%0.2f", bit/(1<<30))
|
||||
}
|
||||
|
||||
if bit > float64(1<<20) && bit < (1<<30) {
|
||||
MB = fmt.Sprintf("%.2f", bit/(1<<20))
|
||||
}
|
||||
|
||||
if bit > float64(1<<10) && bit < (1<<20) {
|
||||
KB = fmt.Sprintf("%.2f", bit/(1<<10))
|
||||
}
|
||||
|
||||
if GB != "" {
|
||||
return GB + "GB"
|
||||
} else if MB != "" {
|
||||
return MB + "MB"
|
||||
} else if KB != "" {
|
||||
return KB + "KB"
|
||||
} else {
|
||||
return fmt.Sprintf("%vB", bit)
|
||||
}
|
||||
}
|
||||
|
||||
// CronExpression 解析 Cron 表达式,返回下一次执行的时间戳(毫秒)
|
||||
//
|
||||
// 【*/5 * * * * ?】 6个参数
|
||||
func CronExpression(expression string) int64 {
|
||||
specParser := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
|
||||
schedule, err := specParser.Parse(expression)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return 0
|
||||
}
|
||||
return schedule.Next(time.Now()).UnixMilli()
|
||||
}
|
||||
|
||||
// SafeContent 内容值进行安全掩码
|
||||
func SafeContent(value string) string {
|
||||
if len(value) < 3 {
|
||||
return strings.Repeat("*", len(value))
|
||||
} else if len(value) < 6 {
|
||||
return string(value[0]) + strings.Repeat("*", len(value)-1)
|
||||
} else if len(value) < 10 {
|
||||
return string(value[0]) + strings.Repeat("*", len(value)-2) + string(value[len(value)-1])
|
||||
} else if len(value) < 15 {
|
||||
return value[:2] + strings.Repeat("*", len(value)-4) + value[len(value)-2:]
|
||||
} else {
|
||||
return value[:3] + strings.Repeat("*", len(value)-6) + value[len(value)-3:]
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveDuplicates 数组内字符串去重
|
||||
func RemoveDuplicates(ids []string) []string {
|
||||
uniqueIDs := make(map[string]bool)
|
||||
uniqueIDSlice := make([]string, 0)
|
||||
|
||||
for _, id := range ids {
|
||||
_, ok := uniqueIDs[id]
|
||||
if !ok && id != "" {
|
||||
uniqueIDs[id] = true
|
||||
uniqueIDSlice = append(uniqueIDSlice, id)
|
||||
}
|
||||
}
|
||||
|
||||
return uniqueIDSlice
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package regular
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// Replace 正则替换
|
||||
func Replace(originStr, pattern, repStr string) string {
|
||||
regex := regexp.MustCompile(pattern)
|
||||
return regex.ReplaceAllString(originStr, repStr)
|
||||
}
|
||||
|
||||
// 判断是否为有效用户名格式
|
||||
//
|
||||
// 用户名不能以数字开头,可包含大写小写字母,数字,且不少于5位
|
||||
func ValidUsername(username string) bool {
|
||||
if username == "" {
|
||||
return false
|
||||
}
|
||||
pattern := `^[a-zA-Z][a-z0-9A-Z]{5,}`
|
||||
match, err := regexp.MatchString(pattern, username)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
// 判断是否为有效手机号格式,1开头的11位手机号
|
||||
func ValidMobile(mobile string) bool {
|
||||
if mobile == "" {
|
||||
return false
|
||||
}
|
||||
pattern := `^1[3|4|5|6|7|8|9][0-9]\d{8}$`
|
||||
match, err := regexp.MatchString(pattern, mobile)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
// 判断是否为http(s)://开头
|
||||
//
|
||||
// link 网络链接
|
||||
func ValidHttp(link string) bool {
|
||||
if link == "" {
|
||||
return false
|
||||
}
|
||||
pattern := `^http(s)?:\/\/+`
|
||||
match, err := regexp.MatchString(pattern, link)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return match
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func ScanPort(port int) bool {
|
||||
ln, err := net.Listen("tcp", ":"+strconv.Itoa(port))
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
defer ln.Close()
|
||||
return false
|
||||
}
|
||||
|
||||
func ScanUDPPort(port int) bool {
|
||||
ln, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: port})
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
defer ln.Close()
|
||||
return false
|
||||
}
|
||||
|
||||
func ScanPortWithProto(port int, proto string) bool {
|
||||
if proto == "udp" {
|
||||
return ScanUDPPort(port)
|
||||
}
|
||||
return ScanPort(port)
|
||||
}
|
||||
@@ -23,6 +23,4 @@ type LoginUser struct {
|
||||
|
||||
// User 用户信息
|
||||
User dborm.User `json:"user"`
|
||||
|
||||
Session dborm.Session `json:"-"`
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package vo
|
||||
|
||||
// Router 路由信息对象
|
||||
type Router struct {
|
||||
// 路由名字 英文首字母大写
|
||||
Name string `json:"name"`
|
||||
// 路由地址
|
||||
Path string `json:"path"`
|
||||
// 其他元素
|
||||
Meta RouterMeta `json:"meta"`
|
||||
// 组件地址
|
||||
Component string `json:"component"`
|
||||
// 重定向地址
|
||||
Redirect string `json:"redirect"`
|
||||
// 子路由
|
||||
Children []Router `json:"children,omitempty"`
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package vo
|
||||
|
||||
// RouterMeta 路由元信息对象
|
||||
type RouterMeta struct {
|
||||
// 设置该菜单在侧边栏和面包屑中展示的名字
|
||||
Title string `json:"title"`
|
||||
// 设置该菜单的图标
|
||||
Icon string `json:"icon"`
|
||||
// 设置为true,则不会被 <keep-alive>缓存
|
||||
Cache bool `json:"cache"`
|
||||
// 内链地址(http(s)://开头), 打开目标位置 '_blank' | '_self' | ''
|
||||
Target string `json:"target"`
|
||||
// 在菜单中隐藏子节点
|
||||
HideChildInMenu bool `json:"hideChildInMenu"`
|
||||
// 在菜单中隐藏自己和子节点
|
||||
HideInMenu bool `json:"hideInMenu"`
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package vo
|
||||
|
||||
// import sysmenu "nms_cxy/features/sys_menu"
|
||||
|
||||
// TreeSelect 树结构实体类
|
||||
type TreeSelect struct {
|
||||
// ID 节点ID
|
||||
ID string `json:"id"`
|
||||
|
||||
// Label 节点名称
|
||||
Label string `json:"label"`
|
||||
|
||||
// Title 节点名称旧版本layui
|
||||
Title string `json:"title"`
|
||||
|
||||
// Children 子节点
|
||||
Children []TreeSelect `json:"children"`
|
||||
}
|
||||
|
||||
// // SysMenuTreeSelect 使用给定的 SysMenu 对象解析为 TreeSelect 对象
|
||||
// func SysMenuTreeSelect(sysMenu sysmenu.SysMenu) TreeSelect {
|
||||
// t := TreeSelect{}
|
||||
// t.ID = sysMenu.MenuID
|
||||
// t.Label = sysMenu.MenuName
|
||||
|
||||
// if len(sysMenu.Children) > 0 {
|
||||
// for _, menu := range sysMenu.Children {
|
||||
// child := SysMenuTreeSelect(menu)
|
||||
// t.Children = append(t.Children, child)
|
||||
// }
|
||||
// } else {
|
||||
// t.Children = []TreeSelect{}
|
||||
// }
|
||||
|
||||
// return t
|
||||
// }
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
|
||||
"strings"
|
||||
|
||||
"nms_cxy/features/sys_role/model"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/lib/oauth"
|
||||
"nms_cxy/src/modules/system/model"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"xorm.io/xorm"
|
||||
@@ -45,9 +45,9 @@ type DatabaseClient struct {
|
||||
|
||||
var DbClient DatabaseClient
|
||||
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||
func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam string) error {
|
||||
DbClient.dbUrl = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName, dbParam)
|
||||
DbClient.dbType = dbType
|
||||
DbClient.dbConnMaxLifetime = 0
|
||||
DbClient.dbMaxIdleConns = 0
|
||||
@@ -55,8 +55,7 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
if log.GetLevel() == log.LOG_TRACE {
|
||||
DbClient.IsShowSQL = true
|
||||
}
|
||||
log.Debugf("dbType:%s dbUrl:%s:******@tcp(%s:%s)/%s??charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
|
||||
dbType, dbUser, dbHost, dbPort, dbName)
|
||||
log.Debugf("dbType:%s dbUrl:%s:", dbType, DbClient.dbUrl)
|
||||
|
||||
var err error
|
||||
DbClient.XEngine, err = xorm.NewEngine(DbClient.dbType, DbClient.dbUrl)
|
||||
@@ -67,9 +66,12 @@ func InitDbClient(dbType, dbUser, dbPassword, dbHost, dbPort, dbName string) err
|
||||
DbClient.XEngine.SetConnMaxLifetime(DbClient.dbConnMaxLifetime)
|
||||
DbClient.XEngine.SetMaxIdleConns(DbClient.dbMaxIdleConns)
|
||||
DbClient.XEngine.SetMaxOpenConns(DbClient.dbMaxOpenConns)
|
||||
DbClient.XEngine.DatabaseTZ = time.Local // 必须
|
||||
DbClient.XEngine.TZLocation = time.Local // 必须
|
||||
if DbClient.IsShowSQL {
|
||||
DbClient.XEngine.ShowSQL(true)
|
||||
}
|
||||
|
||||
xEngine = DbClient.XEngine
|
||||
|
||||
return nil
|
||||
@@ -193,7 +195,7 @@ type NeInfo struct {
|
||||
VendorName string `json:"vendorName" xorm:"vendor_name"` // 厂商名称
|
||||
Dn string `json:"dn" xorm:"dn"` // 网络标识
|
||||
Status int `json:"status" xorm:"status"`
|
||||
UpdateTime string `json:"-" xorm:"-"`
|
||||
UpdateTime time.Time `json:"updateTime" xorm:"<-"`
|
||||
}
|
||||
|
||||
func XormGetMySQLVersion() (string, error) {
|
||||
@@ -1400,11 +1402,11 @@ type MeasureThreshold struct {
|
||||
type NeSoftware struct {
|
||||
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
FileName string `json:"neName" xorm:"file_name"`
|
||||
Path string `json:"path"`
|
||||
Version string `json:"version"`
|
||||
Md5Sum string `json:"md5Sum" xorm:"md5_sum"`
|
||||
Comment string `json:"comment"`
|
||||
FileName string `json:"fileName" xorm:"name"`
|
||||
Path string `json:"path" xorm:"path"`
|
||||
Version string `json:"version" `
|
||||
Md5Sum string `json:"md5Sum" xorm:"-"`
|
||||
Comment string `json:"comment" xorm:"description"`
|
||||
// Status string `json:"status"`
|
||||
UpdateTime string `json:"createTime" xorm:"-" `
|
||||
}
|
||||
@@ -1413,13 +1415,13 @@ type NeVersion struct {
|
||||
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
NeId string `json:"neId" xorm:"ne_id"`
|
||||
Version string `json:"version"`
|
||||
FilePath string `json:"filePath" xorm:"file_path"`
|
||||
Version string `json:"version" `
|
||||
FilePath string `json:"filePath" xorm:"path"`
|
||||
NewVersion string `json:"newVersion" xorm:"new_version"`
|
||||
NewFile string `json:"newFile" xorm:"new_file"`
|
||||
NewFile string `json:"newFile" xorm:"new_path"`
|
||||
PreVersion string `json:"preVersion" xorm:"pre_version"`
|
||||
PreFile string `json:"preFile" xorm:"pre_file"`
|
||||
Status string `json:"status"`
|
||||
PreFile string `json:"preFile" xorm:"pre_path"`
|
||||
Status string `json:"status" xorm:"status"`
|
||||
UpdateTime string `json:"createTime" xorm:"-" `
|
||||
}
|
||||
|
||||
@@ -1451,6 +1453,15 @@ func XormDeleteDataByWhere(where, table string) (int64, error) {
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func XormDeleteDataByWhereNoSession(where, table string) (int64, error) {
|
||||
affected, err := DbClient.XEngine.Table(table).Where(where).Delete()
|
||||
if err != nil {
|
||||
log.Error("Failed to Delete:", err)
|
||||
return 0, err
|
||||
}
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func XormDeleteDataById(id int, table string) (int64, error) {
|
||||
log.Debug("XormDeleteDataByWhere processing... ")
|
||||
|
||||
@@ -1632,9 +1643,10 @@ type AlarmForwardLog struct {
|
||||
AlarmTitle string `json:"alarmTitle" xorm:"alarm_title"`
|
||||
AlarmSeq int `json:"alarmSeq" xorm:"alarm_seq"`
|
||||
EventTime string `json:"eventTime" xorm:"event_time"`
|
||||
Interface string `json:"interface" xorm:"interface"`
|
||||
ToUser string `json:"toUser" xorm:"to_user"`
|
||||
OperResult string `json:"operResult" xorm:"oper_result"`
|
||||
LogTime string `json:"-" xorm:"-"`
|
||||
LogTime string `json:"logTime" xorm:"<-"`
|
||||
}
|
||||
|
||||
func XormInsertAlarmForwardLog(logData *AlarmForwardLog) (int64, error) {
|
||||
@@ -1669,7 +1681,7 @@ func XormInsertSystemLog(logData *SystemLog) (int64, error) {
|
||||
return affected, err
|
||||
}
|
||||
|
||||
type permission struct {
|
||||
type Permission struct {
|
||||
ID int `json:"-" xorm:"pk 'id' autoincr"`
|
||||
PermissionName string `json:"permissionName"`
|
||||
Method string `json:"method"`
|
||||
@@ -1696,25 +1708,26 @@ func IsPermissionAllowed(token, method, module, dbname, tbname, pack string) (bo
|
||||
type NeLicense struct {
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
NeID string `json:"neID" xorm:"ne_id"`
|
||||
SerialNo string `json:"serialNo" xorm:"serial_no"`
|
||||
Capcity int `json:"capcity" xorm:"capcity"`
|
||||
Used int `json:"used" xorm:"used"`
|
||||
FeatureEnabled string `json:"featureEnabled" xorm:"feature_enabled"`
|
||||
ExpirationDate string `json:"expirationDate" xorm:"expiration_date"`
|
||||
SerialNo string `json:"serialNo" xorm:"serial_num"`
|
||||
Capcity int `json:"capcity" xorm:"-"`
|
||||
Used int `json:"used" xorm:"-"`
|
||||
FeatureEnabled string `json:"featureEnabled" xorm:"-"`
|
||||
ExpirationDate string `json:"expirationDate" xorm:"expiry_date"`
|
||||
Status string `json:"status" xorm:"status"`
|
||||
Path string `json:"path" xorm:"path"`
|
||||
FileName string `json:"file_name" xorm:"file_name"`
|
||||
Comment string `json:"comment" xorm:"comment"`
|
||||
Path string `json:"path" xorm:"license_path"`
|
||||
FileName string `json:"file_name" xorm:"-"`
|
||||
Comment string `json:"comment" xorm:"remark"`
|
||||
CreatedAt string `json:"createdAt" xorm:"-"`
|
||||
UpdatedAt string `json:"updatedAt" xorm:"-"`
|
||||
DeletedAt string `json:"deletedAt" xorm:"-"`
|
||||
}
|
||||
|
||||
func XormAdjustmentNeLicense(neType, neID string, value int) (int64, error) {
|
||||
return 1, nil
|
||||
//neLicense := NeLicense{NeType: neType, NeID: neID, Capability: value}
|
||||
// session.LogoutTime.Valid = true
|
||||
// session.LogoutTime.Time = time.Now()
|
||||
res, err := xEngine.Exec("update ne_license set capcity=capcity+? where IFNULL(ne_type, '')=? and IFNULL(ne_id, '')=?", value, neType, neID)
|
||||
// res, err := xEngine.Exec("update ne_license set capcity=capcity+? where IFNULL(ne_type, '')=? and IFNULL(ne_id, '')=?", value, neType, neID)
|
||||
// defer xSession.Close()
|
||||
|
||||
//affected, err := xSession.Table("ne_license").Where("ne_type=? and ne_id=?", neType, neID).Update(&neLicense)
|
||||
@@ -1722,25 +1735,26 @@ func XormAdjustmentNeLicense(neType, neID string, value int) (int64, error) {
|
||||
// //affected, err := xSession.Table("ne_license").SQL("ne_tye=? and ne_id=?", neType, neID).Update(session)
|
||||
// err := xSession.SQL("update ne_license set capability=capability+? where ne_type=? and ne_id=?", value, neType, neID)
|
||||
//xSession.Commit()
|
||||
affected, err := res.RowsAffected()
|
||||
return affected, err
|
||||
// affected, err := res.RowsAffected()
|
||||
// return affected, err
|
||||
}
|
||||
|
||||
func XormUpdateNeLicense(neType, neID string, capcity int) (int64, error) {
|
||||
var err error
|
||||
var res sql.Result
|
||||
if neType != "" && neID != "" {
|
||||
res, err = xEngine.Exec("update ne_license set capcity=? where ne_type=? and ne_id=?", capcity, neType, neID)
|
||||
} else if neType != "" && neID == "" {
|
||||
res, err = xEngine.Exec("update ne_license set capcity=? where ne_type=?", capcity, neType)
|
||||
} else if neType == "" && neID != "" {
|
||||
res, err = xEngine.Exec("update ne_license set capcity=? where ne_id=?", capcity, neID)
|
||||
} else {
|
||||
res, err = xEngine.Exec("update ne_license set capcity=?", capcity)
|
||||
}
|
||||
return 1, nil
|
||||
// var err error
|
||||
// var res sql.Result
|
||||
// if neType != "" && neID != "" {
|
||||
// res, err = xEngine.Exec("update ne_license set capcity=? where ne_type=? and ne_id=?", capcity, neType, neID)
|
||||
// } else if neType != "" && neID == "" {
|
||||
// res, err = xEngine.Exec("update ne_license set capcity=? where ne_type=?", capcity, neType)
|
||||
// } else if neType == "" && neID != "" {
|
||||
// res, err = xEngine.Exec("update ne_license set capcity=? where ne_id=?", capcity, neID)
|
||||
// } else {
|
||||
// res, err = xEngine.Exec("update ne_license set capcity=?", capcity)
|
||||
// }
|
||||
|
||||
affected, err := res.RowsAffected()
|
||||
return affected, err
|
||||
// affected, err := res.RowsAffected()
|
||||
// return affected, err
|
||||
}
|
||||
|
||||
type NorthboundCm struct {
|
||||
@@ -1765,21 +1779,21 @@ func XormGetNorthboundCm(neType string, cmResults *[]NorthboundCm) error {
|
||||
log.Info("XormGetNorthboundCm processing... ")
|
||||
|
||||
cmResult := new(NorthboundCm)
|
||||
rows, err := xEngine.Table("northbound_cm").
|
||||
rows, err := xEngine.Table("nbi_cm").
|
||||
Distinct("object_type").
|
||||
Where("`ne_type` = ?", neType).
|
||||
Desc("timestamp").
|
||||
Cols("*").
|
||||
Rows(cmResult)
|
||||
if err != nil {
|
||||
log.Error("Failed to get table northbound_cm:", err)
|
||||
log.Error("Failed to get table nbi_cm:", err)
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
err := rows.Scan(cmResult)
|
||||
if err != nil {
|
||||
log.Error("Failed to get table northbound_cm:", err)
|
||||
log.Error("Failed to get table nbi_cm:", err)
|
||||
return err
|
||||
}
|
||||
*cmResults = append(*cmResults, *cmResult)
|
||||
@@ -1791,14 +1805,14 @@ func XormGetNorthboundCmLatestObject(neType, neID, objectType string) (*Northbou
|
||||
log.Info("XormGetNorthboundCmLatestObject processing... ")
|
||||
|
||||
cmResult := new(NorthboundCm)
|
||||
_, err := xEngine.Table("northbound_cm").
|
||||
_, err := xEngine.Table("nbi_cm").
|
||||
Where("`ne_type`=? and `ne_id`=? and `object_type`=?", neType, neID, objectType).
|
||||
Desc("timestamp").
|
||||
Cols("*").
|
||||
Limit(1).
|
||||
Get(cmResult)
|
||||
if err != nil {
|
||||
log.Error("Failed to get table northbound_cm:", err)
|
||||
log.Error("Failed to get table nbi_cm:", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -696,3 +696,33 @@ func IsRpmOrDebPackage(filePath string) int {
|
||||
|
||||
return fileType
|
||||
}
|
||||
|
||||
func RecurseStructToMap(obj any) map[string]any {
|
||||
out := make(map[string]any)
|
||||
v := reflect.ValueOf(obj)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
// 递归函数,用于处理嵌套结构体
|
||||
var recurse func(reflect.Value) any
|
||||
recurse = func(value reflect.Value) any {
|
||||
if value.Kind() == reflect.Struct {
|
||||
nestedOut := make(map[string]any)
|
||||
for i := 0; i < value.NumField(); i++ {
|
||||
nestedOut[value.Type().Field(i).Name] = recurse(value.Field(i))
|
||||
}
|
||||
return nestedOut
|
||||
} else if value.Kind() == reflect.Ptr {
|
||||
return recurse(value.Elem())
|
||||
}
|
||||
return value.Interface()
|
||||
}
|
||||
|
||||
t := v.Type()
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
out[t.Field(i).Name] = recurse(f)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/services"
|
||||
)
|
||||
|
||||
// 登录策略限制登录时间和访问ip范围
|
||||
func ArrowIPAddr(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
|
||||
|
||||
// 读取配置信息 登录策略设置
|
||||
result, err := dborm.XormGetConfig("Security", "loginSecurity")
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
data := make(map[string]any)
|
||||
err = json.Unmarshal([]byte(result["value_json"].(string)), &data)
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 开关
|
||||
switchStr := data["switch"].(string)
|
||||
if switchStr == "0" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ipRange := data["ipRange"].(string)
|
||||
logintimeRange := data["logintime_range"].(string)
|
||||
|
||||
// 检查ip
|
||||
ips := strings.Split(ipRange, "/")
|
||||
hasIP := false
|
||||
for _, ip := range ips {
|
||||
if ipAddr == ip {
|
||||
hasIP = true
|
||||
}
|
||||
}
|
||||
if !hasIP {
|
||||
services.ResponseErrorWithJson(w, 502, "网关登录策略-IP限制: "+ipAddr)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查开放时间
|
||||
logintimeRangeArr := strings.Split(logintimeRange, " - ")
|
||||
|
||||
// 加载中国时区
|
||||
loc, _ := time.LoadLocation("Asia/Shanghai")
|
||||
// 获取当前时间
|
||||
currentTime := time.Now().In(loc)
|
||||
|
||||
// 获取当前日期
|
||||
currentDate := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 0, 0, 0, 0, currentTime.Location())
|
||||
ymd := currentDate.Format("2006-01-02")
|
||||
|
||||
// 定义开始时间和结束时间
|
||||
startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", ymd+" "+logintimeRangeArr[0], loc)
|
||||
endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", ymd+" "+logintimeRangeArr[1], loc)
|
||||
|
||||
// 判断当前时间是否在范围内
|
||||
if currentTime.After(startTime) && currentTime.Before(endTime) {
|
||||
next.ServeHTTP(w, r)
|
||||
} else {
|
||||
services.ResponseErrorWithJson(w, 502, "网关登录策略-不在开放时间范围内")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"nms_cxy/lib/core/cache"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/vo"
|
||||
"nms_cxy/lib/core/vo/result"
|
||||
"nms_cxy/lib/dborm"
|
||||
commonConstants "nms_cxy/src/framework/constants/common"
|
||||
tokenUtils "nms_cxy/src/framework/utils/token"
|
||||
)
|
||||
|
||||
// Authorize 用户身份授权认证校验
|
||||
//
|
||||
// 只需含有其中角色 "hasRoles": {"xxx"},
|
||||
//
|
||||
// 只需含有其中权限 "hasPerms": {"xxx"},
|
||||
//
|
||||
// 同时匹配其中角色 "matchRoles": {"xxx"},
|
||||
//
|
||||
// 同时匹配其中权限 "matchPerms": {"xxx"},
|
||||
func Authorize(options map[string][]string) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// 获取请求头标识信息
|
||||
tokenStr := ctx.Authorization(r)
|
||||
// 获取请求头标识信息-旧头
|
||||
accessToken := r.Header.Get("AccessToken")
|
||||
if tokenStr == "" && accessToken != "" {
|
||||
// 验证令牌 == 这里直接查数据库session
|
||||
if !dborm.XormExistValidToken(accessToken, 0) {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization valid error"))
|
||||
return
|
||||
}
|
||||
se, err := dborm.XormUpdateSessionShakeTime(accessToken)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization shake error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取缓存的用户信息
|
||||
data, ok := cache.GetLocalTTL(se.AccountId)
|
||||
if data == nil || !ok {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization info error"))
|
||||
return
|
||||
}
|
||||
loginUser := data.(vo.LoginUser)
|
||||
|
||||
// 登录用户角色权限校验
|
||||
if options != nil {
|
||||
var roles []string
|
||||
for _, item := range loginUser.User.Roles {
|
||||
roles = append(roles, item.RoleKey)
|
||||
}
|
||||
perms := loginUser.Permissions
|
||||
verifyOk := verifyRolePermission(roles, perms, options)
|
||||
if !verifyOk {
|
||||
msg := fmt.Sprintf("Unauthorized access %s %s", r.Method, r.RequestURI)
|
||||
ctx.JSON(w, 403, result.CodeMsg(403, msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 在请求的 Context 中存储数据
|
||||
rContext := r.Context()
|
||||
rContext = context.WithValue(rContext, ctx.ContextKey(commonConstants.CTX_LOGIN_USER), loginUser)
|
||||
// 继续处理请求
|
||||
next.ServeHTTP(w, r.WithContext(rContext))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取请求头标识信息
|
||||
if tokenStr == "" {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization token error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 验证令牌
|
||||
claims, err := tokenUtils.Verify(tokenStr)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization valid error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取缓存的用户信息
|
||||
loginUser := tokenUtils.LoginUser(claims)
|
||||
if loginUser.UserID == "" {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization shake error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查刷新有效期后存入上下文
|
||||
tokenUtils.RefreshIn(&loginUser)
|
||||
|
||||
// 登录用户角色权限校验
|
||||
if options != nil {
|
||||
var roles []string
|
||||
for _, item := range loginUser.User.Roles {
|
||||
roles = append(roles, item.RoleKey)
|
||||
}
|
||||
perms := loginUser.Permissions
|
||||
verifyOk := verifyRolePermission(roles, perms, options)
|
||||
if !verifyOk {
|
||||
msg := fmt.Sprintf("Unauthorized access %s %s", r.Method, r.RequestURI)
|
||||
ctx.JSON(w, 403, result.CodeMsg(403, msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 在请求的 Context 中存储数据
|
||||
rContext := r.Context()
|
||||
rContext = context.WithValue(rContext, ctx.ContextKey(commonConstants.CTX_LOGIN_USER), loginUser)
|
||||
// 继续处理请求
|
||||
next.ServeHTTP(w, r.WithContext(rContext))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// verifyRolePermission 校验角色权限是否满足
|
||||
//
|
||||
// roles 角色字符数组
|
||||
//
|
||||
// perms 权限字符数组
|
||||
//
|
||||
// options 参数
|
||||
func verifyRolePermission(roles, perms []string, options map[string][]string) bool {
|
||||
// 直接放行 管理员角色或任意权限
|
||||
if contains(roles, "admin") || contains(perms, "*:*:*") {
|
||||
return true
|
||||
}
|
||||
opts := make([]bool, 4)
|
||||
|
||||
// 只需含有其中角色
|
||||
hasRole := false
|
||||
if arr, ok := options["hasRoles"]; ok && len(arr) > 0 {
|
||||
hasRole = some(roles, arr)
|
||||
opts[0] = true
|
||||
}
|
||||
|
||||
// 只需含有其中权限
|
||||
hasPerms := false
|
||||
if arr, ok := options["hasPerms"]; ok && len(arr) > 0 {
|
||||
hasPerms = some(perms, arr)
|
||||
opts[1] = true
|
||||
}
|
||||
|
||||
// 同时匹配其中角色
|
||||
matchRoles := false
|
||||
if arr, ok := options["matchRoles"]; ok && len(arr) > 0 {
|
||||
matchRoles = every(roles, arr)
|
||||
opts[2] = true
|
||||
}
|
||||
|
||||
// 同时匹配其中权限
|
||||
matchPerms := false
|
||||
if arr, ok := options["matchPerms"]; ok && len(arr) > 0 {
|
||||
matchPerms = every(perms, arr)
|
||||
opts[3] = true
|
||||
}
|
||||
|
||||
// 同时判断 含有其中
|
||||
if opts[0] && opts[1] {
|
||||
return hasRole || hasPerms
|
||||
}
|
||||
// 同时判断 匹配其中
|
||||
if opts[2] && opts[3] {
|
||||
return matchRoles && matchPerms
|
||||
}
|
||||
// 同时判断 含有其中且匹配其中
|
||||
if opts[0] && opts[3] {
|
||||
return hasRole && matchPerms
|
||||
}
|
||||
if opts[1] && opts[2] {
|
||||
return hasPerms && matchRoles
|
||||
}
|
||||
|
||||
return hasRole || hasPerms || matchRoles || matchPerms
|
||||
}
|
||||
|
||||
// contains 检查字符串数组中是否包含指定的字符串
|
||||
func contains(arr []string, target string) bool {
|
||||
for _, str := range arr {
|
||||
if str == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// some 检查字符串数组中含有其中一项
|
||||
func some(origin []string, target []string) bool {
|
||||
has := false
|
||||
for _, t := range target {
|
||||
for _, o := range origin {
|
||||
if t == o {
|
||||
has = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if has {
|
||||
break
|
||||
}
|
||||
}
|
||||
return has
|
||||
}
|
||||
|
||||
// every 检查字符串数组中同时包含所有项
|
||||
func every(origin []string, target []string) bool {
|
||||
match := true
|
||||
for _, t := range target {
|
||||
found := false
|
||||
for _, o := range origin {
|
||||
if t == o {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
match = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return match
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Cors 跨域
|
||||
func Cors(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// 设置Vary头部
|
||||
w.Header().Set("Vary", "Origin")
|
||||
w.Header().Set("Keep-Alive", "timeout=5")
|
||||
|
||||
requestOrigin := r.Header.Get("Origin")
|
||||
if requestOrigin == "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
|
||||
// OPTIONS
|
||||
if r.Method == "OPTIONS" {
|
||||
requestMethod := r.Header.Get("Access-Control-Request-Method")
|
||||
if requestMethod == "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 响应最大时间值
|
||||
w.Header().Set("Access-Control-Max-Age", "31536000")
|
||||
|
||||
// 允许方法
|
||||
allowMethods := []string{
|
||||
"OPTIONS",
|
||||
"HEAD",
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"PATCH",
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Methods", strings.Join(allowMethods, ","))
|
||||
|
||||
// 允许请求头
|
||||
allowHeaders := []string{
|
||||
"Accesstoken",
|
||||
"Content-Type",
|
||||
"operationtype",
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Headers", strings.Join(allowHeaders, ","))
|
||||
|
||||
w.WriteHeader(204)
|
||||
return
|
||||
}
|
||||
|
||||
// 暴露请求头
|
||||
exposeHeaders := []string{"X-RepeatSubmit-Rest", "AccessToken"}
|
||||
w.Header().Set("Access-Control-Expose-Headers", strings.Join(exposeHeaders, ","))
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -9,11 +9,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/datasource"
|
||||
"nms_cxy/lib/core/utils/ctx"
|
||||
"nms_cxy/lib/core/utils/date"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/core/ctx"
|
||||
"nms_cxy/lib/log"
|
||||
"nms_cxy/src/framework/datasource"
|
||||
"nms_cxy/src/framework/utils/date"
|
||||
)
|
||||
|
||||
// LogMML mml操作日志搜集
|
||||
@@ -37,7 +36,7 @@ func LogMML(next http.Handler) http.Handler {
|
||||
// 收尾存入数据库的参数
|
||||
mmlCmd := bodyArgs["mml"].([]any)[0]
|
||||
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
|
||||
neType := ctx.Param(r, "elementTypeValue")
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
timeStr := date.ParseDateToStr(time.Now(), date.YYYY_MM_DD_HH_MM_SS)
|
||||
|
||||
@@ -50,19 +49,12 @@ func LogMML(next http.Handler) http.Handler {
|
||||
resultStr := fmt.Sprintf(`{"status":"%s","size":"%s","content-type":"%s"}`, status, size, contentType)
|
||||
|
||||
// 用户名
|
||||
username := "-"
|
||||
accessToken := r.Header.Get("AccessToken")
|
||||
if accessToken != "" {
|
||||
// 验证令牌 == 这里直接查数据库session
|
||||
se, _ := dborm.XormUpdateSessionShakeTime(accessToken)
|
||||
username = se.AccountId
|
||||
}
|
||||
|
||||
username := ctx.LoginUserToUserName(r)
|
||||
// 执行插入
|
||||
sql := "insert into mml_log (user,ip,ne_type,ne_id,mml,result,log_time)values(?,?,?,?,?,?,?)"
|
||||
_, sqlerr := datasource.ExecDB("", sql, []any{username, ipAddr, neType, neId, mmlCmd, resultStr, timeStr})
|
||||
if sqlerr != nil {
|
||||
log.Errorf("insert row : %v", err.Error())
|
||||
log.Errorf("insert row : %v", sqlerr.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/core/utils/parse"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/core/ctx"
|
||||
"nms_cxy/src/framework/constants/common"
|
||||
"nms_cxy/src/framework/middleware/collectlogs"
|
||||
"nms_cxy/src/framework/utils/ip2region"
|
||||
"nms_cxy/src/framework/utils/parse"
|
||||
"nms_cxy/src/modules/system/model"
|
||||
"nms_cxy/src/modules/system/service"
|
||||
)
|
||||
@@ -47,13 +47,7 @@ func LogOperate(options collectlogs.Options) func(http.Handler) http.Handler {
|
||||
funcName = funcName[lastDotIndex+1:]
|
||||
|
||||
// 用户名
|
||||
username := "-"
|
||||
accessToken := r.Header.Get("AccessToken")
|
||||
if accessToken != "" {
|
||||
// 验证令牌 == 这里直接查数据库session
|
||||
se, _ := dborm.XormUpdateSessionShakeTime(accessToken)
|
||||
username = se.AccountId
|
||||
}
|
||||
username := ctx.LoginUserToUserName(r)
|
||||
|
||||
// 解析ip地址
|
||||
ip := strings.Split(r.RemoteAddr, ":")[0]
|
||||
|
||||
@@ -9,25 +9,16 @@ import (
|
||||
"nms_cxy/features/cdr"
|
||||
"nms_cxy/features/cm"
|
||||
"nms_cxy/features/dbrest"
|
||||
"nms_cxy/features/event"
|
||||
"nms_cxy/features/file"
|
||||
"nms_cxy/features/fm"
|
||||
"nms_cxy/features/lm"
|
||||
"nms_cxy/features/mml"
|
||||
"nms_cxy/features/monitor/monitor"
|
||||
"nms_cxy/features/monitor/psnet"
|
||||
"nms_cxy/features/nbi"
|
||||
"nms_cxy/features/pm"
|
||||
"nms_cxy/features/security"
|
||||
"nms_cxy/features/sm"
|
||||
"nms_cxy/features/state"
|
||||
sysconfig "nms_cxy/features/sys_config"
|
||||
sysdictdata "nms_cxy/features/sys_dict_data"
|
||||
sysdicttype "nms_cxy/features/sys_dict_type"
|
||||
sysmenu "nms_cxy/features/sys_menu"
|
||||
sysrole "nms_cxy/features/sys_role"
|
||||
sysuser "nms_cxy/features/sys_user"
|
||||
"nms_cxy/features/trace"
|
||||
udmuser "nms_cxy/features/udm_user"
|
||||
"nms_cxy/features/ue"
|
||||
"nms_cxy/lib/midware"
|
||||
"nms_cxy/lib/services"
|
||||
@@ -174,16 +165,16 @@ func init() {
|
||||
Register("POST", mml.UriMML, mml.PostMMLToNF, midware.LogMML)
|
||||
Register("POST", mml.UriMMLDiscard, mml.PostMMLToNF, nil)
|
||||
Register("POST", mml.UriOmMmlExt, mml.PostMMLToOMC, midware.LogMML)
|
||||
Register("POST", mml.CustomUriMML, mml.PostMMLToNF, midware.LogMML)
|
||||
Register("POST", mml.CustomUriOmMmlExt, mml.PostMMLToOMC, midware.LogMML)
|
||||
Register("POST", mml.CustomUriMML, mml.PostMMLToNF, nil)
|
||||
Register("POST", mml.CustomUriOmMmlExt, mml.PostMMLToOMC, nil)
|
||||
// post mml2 (standard upf port=5002)
|
||||
Register("POST", mml.UriMML2, mml.PostMML2ToNF, midware.LogMML)
|
||||
Register("POST", mml.CustomUriMML2, mml.PostMML2ToNF, midware.LogMML)
|
||||
Register("POST", mml.CustomUriMML2, mml.PostMML2ToNF, nil)
|
||||
|
||||
// Northbound Get NRM
|
||||
Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||
// Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||
|
||||
Register("GET", nbi.CustomGetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||
// Register("GET", nbi.CustomGetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||
|
||||
// Import/Export NF CM
|
||||
Register("GET", cm.NeCmUri, cm.ExportCmFromNF, nil)
|
||||
@@ -233,16 +224,6 @@ func init() {
|
||||
Register("PUT", trace.CustomUriTraceTask, trace.PutTraceTaskToNF, nil)
|
||||
Register("DELETE", trace.CustomUriTraceTask, trace.DeleteTraceTaskToNF, nil)
|
||||
|
||||
// 网元发送执行 pcap抓包任务
|
||||
Register("POST", trace.UriTcpdumpTask, trace.TcpdumpNeTask, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||
Register("POST", trace.CustomUriTcpdumpTask, trace.TcpdumpNeTask, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||
// 网元发送执行 抓包下载pcap文件
|
||||
Register("POST", trace.UriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_EXPORT)))
|
||||
Register("POST", trace.CustomUriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_EXPORT)))
|
||||
// 网元发送执行UPF pcap抓包
|
||||
Register("POST", trace.UriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||
Register("POST", trace.CustomUriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||
|
||||
// file management
|
||||
Register("POST", file.UriFile, file.UploadFile, midware.LogOperate(collectlogs.OptionNew("File", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||
Register("GET", file.UriFile, file.DownloadFile, midware.LogOperate(collectlogs.OptionNew("File", collectlogs.BUSINESS_TYPE_OTHER)))
|
||||
@@ -280,9 +261,7 @@ func init() {
|
||||
Register("DELETE", ue.CustomUriPCFUserM, ue.DeletePCFUserInfo, nil)
|
||||
//PCF User file
|
||||
Register("GET", ue.UriPCFUserFileExport, ue.GetUEInfoFileExportNF, nil)
|
||||
Register("GET", ue.CustomUriPCFUserFileExport, ue.GetUEInfoFromNF, nil)
|
||||
Register("PUT", ue.UriPCFUserFileImport, ue.PutPCFUserInfo, nil)
|
||||
Register("PUT", ue.CustomUriPCFUserFileImport, ue.PutPCFUserInfo, nil)
|
||||
|
||||
// UE Number
|
||||
Register("GET", ue.UriUENum, ue.GetUENumFromNF, nil)
|
||||
@@ -300,23 +279,20 @@ func init() {
|
||||
Register("GET", ue.UriNSSFSubscriptions, ue.GetSubscriptionsFromNSSF, nil)
|
||||
Register("GET", ue.CustomUriNSSFSubscriptions, ue.GetSubscriptionsFromNSSF, nil)
|
||||
|
||||
Register("POST", cdr.UriCDREvent, cdr.PostCDREventFromNF, nil)
|
||||
Register("POST", cdr.CustomUriCDREvent, cdr.PostCDREventFromNF, nil)
|
||||
// ims cdr event
|
||||
Register("POST", cdr.UriIMSCDREvent, cdr.PostCDREventFromIMS, nil)
|
||||
Register("POST", cdr.CustomUriIMSCDREvent, cdr.PostCDREventFromIMS, nil)
|
||||
|
||||
// UE event
|
||||
// smf cdr event
|
||||
Register("POST", cdr.UriSMFCDREvent, cdr.PostCDREventFromSMF, nil)
|
||||
Register("POST", cdr.CustomUriSMFCDREvent, cdr.PostCDREventFromSMF, nil)
|
||||
|
||||
// UE event 上报的UE事件
|
||||
Register("POST", event.UriUEEvent, event.PostUEEvent, nil)
|
||||
|
||||
// UE event AMF上报的UE事件, 无前缀给到Gin处理
|
||||
//Register("POST", event.UriUEEvent, event.PostUEEventFromAMF, nil)
|
||||
|
||||
// 进程网络
|
||||
Register("GET", psnet.UriWs, psnet.ProcessWs, nil)
|
||||
Register("POST", psnet.UriStop, psnet.StopProcess, nil)
|
||||
Register("POST", psnet.UriPing, psnet.Ping, nil)
|
||||
|
||||
// 主机CPU内存监控
|
||||
Register("POST", monitor.UriLoad, monitor.LoadMonitor, nil)
|
||||
Register("GET", monitor.UriNetOpt, monitor.Netoptions, nil)
|
||||
Register("GET", monitor.UriIPAddr, monitor.IPAddr, nil)
|
||||
Register("GET", monitor.UriIoOpt, monitor.Iooptions, nil)
|
||||
|
||||
// 文件资源
|
||||
Register("GET", file.UriDiskList, file.DiskList, nil)
|
||||
Register("POST", file.UriListFiles, file.ListFiles, nil)
|
||||
@@ -337,56 +313,6 @@ func init() {
|
||||
Register("POST", lm.ExtBackupDataUri, lm.ExtDatabaseBackupData, nil)
|
||||
Register("POST", lm.CustomExtBackupDataUri, lm.ExtDatabaseBackupData, nil)
|
||||
|
||||
// 系统登录
|
||||
Register("POST", security.UriLogin, security.LoginOMC, nil)
|
||||
Register("POST", security.CustomUriLogin, security.LoginOMC, nil)
|
||||
|
||||
// 获取验证码
|
||||
Register("GET", security.UriCaptchaImage, security.CaptchaImage, nil)
|
||||
Register("GET", security.CustomUriCaptchaImage, security.CaptchaImage, nil)
|
||||
|
||||
// 登录用户信息
|
||||
Register("GET", security.UriUserInfo, security.UserInfo, midware.Authorize(nil))
|
||||
Register("GET", security.CustomUriUserInfo, security.UserInfo, midware.Authorize(nil))
|
||||
|
||||
// 登录用户路由信息
|
||||
Register("GET", security.UriRouters, security.Routers, midware.Authorize(nil))
|
||||
Register("GET", security.CustomUriRouters, security.Routers, midware.Authorize(nil))
|
||||
|
||||
// 参数配置信息接口添加到路由
|
||||
for _, v := range sysconfig.Routers() {
|
||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||
}
|
||||
|
||||
// 字典类型信息接口添加到路由
|
||||
for _, v := range sysdicttype.Routers() {
|
||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||
}
|
||||
|
||||
// 字典类型对应的字典数据信息接口添加到路由
|
||||
for _, v := range sysdictdata.Routers() {
|
||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||
}
|
||||
|
||||
// 菜单接口添加到路由
|
||||
for _, v := range sysmenu.Routers() {
|
||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||
}
|
||||
|
||||
// 角色接口添加到路由
|
||||
for _, v := range sysrole.Routers() {
|
||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||
}
|
||||
|
||||
// 用户接口添加到路由
|
||||
for _, v := range sysuser.Routers() {
|
||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||
}
|
||||
|
||||
// UDM 用户信息接口添加到路由
|
||||
for _, v := range udmuser.Routers() {
|
||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||
}
|
||||
}
|
||||
|
||||
// To resolv rest POST/PUT/DELETE/PATCH cross domain
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package wsinfo
|
||||
|
||||
import (
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
ID string
|
||||
Socket *websocket.Conn
|
||||
Msg chan []byte
|
||||
}
|
||||
|
||||
func NewWsClient(ID string, socket *websocket.Conn) *Client {
|
||||
return &Client{
|
||||
ID: ID,
|
||||
Socket: socket,
|
||||
Msg: make(chan []byte, 100),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Read() {
|
||||
defer func() {
|
||||
close(c.Msg)
|
||||
}()
|
||||
for {
|
||||
_, message, err := c.Socket.ReadMessage()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ProcessData(c, message)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Write() {
|
||||
defer func() {
|
||||
c.Socket.Close()
|
||||
}()
|
||||
for {
|
||||
message, ok := <-c.Msg
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
_ = c.Socket.WriteMessage(websocket.TextMessage, message)
|
||||
}
|
||||
}
|
||||
@@ -1,383 +0,0 @@
|
||||
package wsinfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"nms_cxy/lib/log"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
)
|
||||
|
||||
type WsInput struct {
|
||||
Type string `json:"type"`
|
||||
DownloadProgress
|
||||
PsProcessConfig
|
||||
SSHSessionConfig
|
||||
NetConfig
|
||||
}
|
||||
|
||||
type DownloadProgress struct {
|
||||
Keys []string `json:"keys"`
|
||||
}
|
||||
|
||||
type PsProcessConfig struct {
|
||||
Pid int32 `json:"pid"`
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type SSHSessionConfig struct {
|
||||
LoginUser string `json:"loginUser"`
|
||||
LoginIP string `json:"loginIP"`
|
||||
}
|
||||
|
||||
type NetConfig struct {
|
||||
Port uint32 `json:"port"`
|
||||
ProcessName string `json:"processName"`
|
||||
ProcessID int32 `json:"processID"`
|
||||
}
|
||||
|
||||
type PsProcessData struct {
|
||||
PID int32 `json:"PID"`
|
||||
Name string `json:"name"`
|
||||
PPID int32 `json:"PPID"`
|
||||
Username string `json:"username"`
|
||||
Status string `json:"status"`
|
||||
StartTime string `json:"startTime"`
|
||||
NumThreads int32 `json:"numThreads"`
|
||||
NumConnections int `json:"numConnections"`
|
||||
CpuPercent string `json:"cpuPercent"`
|
||||
|
||||
DiskRead string `json:"diskRead"`
|
||||
DiskWrite string `json:"diskWrite"`
|
||||
CmdLine string `json:"cmdLine"`
|
||||
|
||||
Rss string `json:"rss"`
|
||||
VMS string `json:"vms"`
|
||||
HWM string `json:"hwm"`
|
||||
Data string `json:"data"`
|
||||
Stack string `json:"stack"`
|
||||
Locked string `json:"locked"`
|
||||
Swap string `json:"swap"`
|
||||
|
||||
CpuValue float64 `json:"cpuValue"`
|
||||
RssValue uint64 `json:"rssValue"`
|
||||
|
||||
Envs []string `json:"envs"`
|
||||
|
||||
OpenFiles []process.OpenFilesStat `json:"openFiles"`
|
||||
Connects []processConnect `json:"connects"`
|
||||
}
|
||||
|
||||
type processConnect struct {
|
||||
Type string `json:"type"`
|
||||
Status string `json:"status"`
|
||||
Laddr net.Addr `json:"localaddr"`
|
||||
Raddr net.Addr `json:"remoteaddr"`
|
||||
PID int32 `json:"PID"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ProcessConnects []processConnect
|
||||
|
||||
func (p ProcessConnects) Len() int {
|
||||
return len(p)
|
||||
}
|
||||
|
||||
func (p ProcessConnects) Less(i, j int) bool {
|
||||
return p[i].PID < p[j].PID
|
||||
}
|
||||
|
||||
func (p ProcessConnects) Swap(i, j int) {
|
||||
p[i], p[j] = p[j], p[i]
|
||||
}
|
||||
|
||||
type sshSession struct {
|
||||
Username string `json:"username"`
|
||||
PID int32 `json:"PID"`
|
||||
Terminal string `json:"terminal"`
|
||||
Host string `json:"host"`
|
||||
LoginTime string `json:"loginTime"`
|
||||
}
|
||||
|
||||
func ProcessData(c *Client, inputMsg []byte) {
|
||||
wsInput := &WsInput{}
|
||||
err := json.Unmarshal(inputMsg, wsInput)
|
||||
if err != nil {
|
||||
log.Errorf("unmarshal wsInput error,err %s", err.Error())
|
||||
return
|
||||
}
|
||||
switch wsInput.Type {
|
||||
case "ps":
|
||||
res, err := getProcessData(wsInput.PsProcessConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
case "ssh":
|
||||
res, err := getSSHSessions(wsInput.SSHSessionConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
case "net":
|
||||
res, err := getNetConnections(wsInput.NetConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type Process struct {
|
||||
Total uint64 `json:"total"`
|
||||
Written uint64 `json:"written"`
|
||||
Percent float64 `json:"percent"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
const (
|
||||
b = uint64(1)
|
||||
kb = 1024 * b
|
||||
mb = 1024 * kb
|
||||
gb = 1024 * mb
|
||||
)
|
||||
|
||||
func formatBytes(bytes uint64) string {
|
||||
switch {
|
||||
case bytes < kb:
|
||||
return fmt.Sprintf("%dB", bytes)
|
||||
case bytes < mb:
|
||||
return fmt.Sprintf("%.2fKB", float64(bytes)/float64(kb))
|
||||
case bytes < gb:
|
||||
return fmt.Sprintf("%.2fMB", float64(bytes)/float64(mb))
|
||||
default:
|
||||
return fmt.Sprintf("%.2fGB", float64(bytes)/float64(gb))
|
||||
}
|
||||
}
|
||||
|
||||
func getProcessData(processConfig PsProcessConfig) (res []byte, err error) {
|
||||
var processes []*process.Process
|
||||
processes, err = process.Processes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
result []PsProcessData
|
||||
resultMutex sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
numWorkers = 4
|
||||
)
|
||||
|
||||
handleData := func(proc *process.Process) {
|
||||
procData := PsProcessData{
|
||||
PID: proc.Pid,
|
||||
}
|
||||
if processConfig.Pid > 0 && processConfig.Pid != proc.Pid {
|
||||
return
|
||||
}
|
||||
if procName, err := proc.Name(); err == nil {
|
||||
procData.Name = procName
|
||||
} else {
|
||||
procData.Name = "<UNKNOWN>"
|
||||
}
|
||||
if processConfig.Name != "" && !strings.Contains(procData.Name, processConfig.Name) {
|
||||
return
|
||||
}
|
||||
if username, err := proc.Username(); err == nil {
|
||||
procData.Username = username
|
||||
}
|
||||
if processConfig.Username != "" && !strings.Contains(procData.Username, processConfig.Username) {
|
||||
return
|
||||
}
|
||||
procData.PPID, _ = proc.Ppid()
|
||||
statusArray, _ := proc.Status()
|
||||
if len(statusArray) > 0 {
|
||||
procData.Status = strings.Join(statusArray, ",")
|
||||
}
|
||||
createTime, procErr := proc.CreateTime()
|
||||
if procErr == nil {
|
||||
t := time.Unix(createTime/1000, 0)
|
||||
procData.StartTime = t.Format("2006-1-2 15:04:05")
|
||||
}
|
||||
procData.NumThreads, _ = proc.NumThreads()
|
||||
connections, procErr := proc.Connections()
|
||||
if procErr == nil {
|
||||
procData.NumConnections = len(connections)
|
||||
for _, conn := range connections {
|
||||
if conn.Laddr.IP != "" || conn.Raddr.IP != "" {
|
||||
procData.Connects = append(procData.Connects, processConnect{
|
||||
Status: conn.Status,
|
||||
Laddr: conn.Laddr,
|
||||
Raddr: conn.Raddr,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
procData.CpuValue, _ = proc.CPUPercent()
|
||||
procData.CpuPercent = fmt.Sprintf("%.2f", procData.CpuValue) + "%"
|
||||
menInfo, procErr := proc.MemoryInfo()
|
||||
if procErr == nil {
|
||||
procData.Rss = formatBytes(menInfo.RSS)
|
||||
procData.RssValue = menInfo.RSS
|
||||
procData.Data = formatBytes(menInfo.Data)
|
||||
procData.VMS = formatBytes(menInfo.VMS)
|
||||
procData.HWM = formatBytes(menInfo.HWM)
|
||||
procData.Stack = formatBytes(menInfo.Stack)
|
||||
procData.Locked = formatBytes(menInfo.Locked)
|
||||
procData.Swap = formatBytes(menInfo.Swap)
|
||||
} else {
|
||||
procData.Rss = "--"
|
||||
procData.Data = "--"
|
||||
procData.VMS = "--"
|
||||
procData.HWM = "--"
|
||||
procData.Stack = "--"
|
||||
procData.Locked = "--"
|
||||
procData.Swap = "--"
|
||||
|
||||
procData.RssValue = 0
|
||||
}
|
||||
ioStat, procErr := proc.IOCounters()
|
||||
if procErr == nil {
|
||||
procData.DiskWrite = formatBytes(ioStat.WriteBytes)
|
||||
procData.DiskRead = formatBytes(ioStat.ReadBytes)
|
||||
} else {
|
||||
procData.DiskWrite = "--"
|
||||
procData.DiskRead = "--"
|
||||
}
|
||||
procData.CmdLine, _ = proc.Cmdline()
|
||||
procData.OpenFiles, _ = proc.OpenFiles()
|
||||
procData.Envs, _ = proc.Environ()
|
||||
|
||||
resultMutex.Lock()
|
||||
result = append(result, procData)
|
||||
resultMutex.Unlock()
|
||||
}
|
||||
|
||||
chunkSize := (len(processes) + numWorkers - 1) / numWorkers
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
wg.Add(1)
|
||||
start := i * chunkSize
|
||||
end := (i + 1) * chunkSize
|
||||
if end > len(processes) {
|
||||
end = len(processes)
|
||||
}
|
||||
|
||||
go func(start, end int) {
|
||||
defer wg.Done()
|
||||
for j := start; j < end; j++ {
|
||||
handleData(processes[j])
|
||||
}
|
||||
}(start, end)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].PID < result[j].PID
|
||||
})
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
|
||||
func getSSHSessions(config SSHSessionConfig) (res []byte, err error) {
|
||||
var (
|
||||
result []sshSession
|
||||
users []host.UserStat
|
||||
processes []*process.Process
|
||||
)
|
||||
processes, err = process.Processes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users, err = host.Users()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, proc := range processes {
|
||||
name, _ := proc.Name()
|
||||
if name != "sshd" || proc.Pid == 0 {
|
||||
continue
|
||||
}
|
||||
connections, _ := proc.Connections()
|
||||
for _, conn := range connections {
|
||||
for _, user := range users {
|
||||
if user.Host == "" {
|
||||
continue
|
||||
}
|
||||
if conn.Raddr.IP == user.Host {
|
||||
if config.LoginUser != "" && !strings.Contains(user.User, config.LoginUser) {
|
||||
continue
|
||||
}
|
||||
if config.LoginIP != "" && !strings.Contains(user.Host, config.LoginIP) {
|
||||
continue
|
||||
}
|
||||
if terminal, err := proc.Cmdline(); err == nil {
|
||||
if strings.Contains(terminal, user.Terminal) {
|
||||
session := sshSession{
|
||||
Username: user.User,
|
||||
Host: user.Host,
|
||||
Terminal: user.Terminal,
|
||||
PID: proc.Pid,
|
||||
}
|
||||
t := time.Unix(int64(user.Started), 0)
|
||||
session.LoginTime = t.Format("2006-1-2 15:04:05")
|
||||
result = append(result, session)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
|
||||
var netTypes = [...]string{"tcp", "udp"}
|
||||
|
||||
func getNetConnections(config NetConfig) (res []byte, err error) {
|
||||
var (
|
||||
result []processConnect
|
||||
proc *process.Process
|
||||
)
|
||||
for _, netType := range netTypes {
|
||||
connections, _ := net.Connections(netType)
|
||||
if err == nil {
|
||||
for _, conn := range connections {
|
||||
if config.ProcessID > 0 && config.ProcessID != conn.Pid {
|
||||
continue
|
||||
}
|
||||
proc, err = process.NewProcess(conn.Pid)
|
||||
if err == nil {
|
||||
name, _ := proc.Name()
|
||||
if name != "" && config.ProcessName != "" && !strings.Contains(name, config.ProcessName) {
|
||||
continue
|
||||
}
|
||||
if config.Port > 0 && config.Port != conn.Laddr.Port && config.Port != conn.Raddr.Port {
|
||||
continue
|
||||
}
|
||||
result = append(result, processConnect{
|
||||
Type: netType,
|
||||
Status: conn.Status,
|
||||
Laddr: conn.Laddr,
|
||||
Raddr: conn.Raddr,
|
||||
PID: conn.Pid,
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
@@ -2,24 +2,15 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"nms_cxy/lib/global"
|
||||
"nms_cxy/lib/log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"nms_cxy/lib/global"
|
||||
"nms_cxy/lib/log"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type DbConfig struct {
|
||||
Type string `yaml:"type"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
Host string `yaml:"host"`
|
||||
Port string `yaml:"port"`
|
||||
Name string `yaml:"name"`
|
||||
Backup string `yaml:"backup"`
|
||||
}
|
||||
|
||||
// Yaml struct of config
|
||||
type YamlConfig struct {
|
||||
Logger struct {
|
||||
@@ -29,16 +20,23 @@ type YamlConfig struct {
|
||||
Count int `yaml:"count"`
|
||||
} `yaml:"logger"`
|
||||
|
||||
Rest []struct {
|
||||
IPv4 string `yaml:"ipv4"`
|
||||
IPv6 string `yaml:"ipv6"`
|
||||
Port uint16 `yaml:"port"`
|
||||
Scheme string `yaml:"scheme"`
|
||||
ClientAuthType int `yaml:"clientAuthType"`
|
||||
CaFile string `yaml:"caFile"`
|
||||
CertFile string `yaml:"certFile"`
|
||||
KeyFile string `yaml:"keyFile"`
|
||||
} `yaml:"rest"`
|
||||
Pprof struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Addr string `yaml:"addr"`
|
||||
} `yaml:"pprof"`
|
||||
|
||||
// Rest []struct {
|
||||
// IPv4 string `yaml:"ipv4"`
|
||||
// IPv6 string `yaml:"ipv6"`
|
||||
// Port uint16 `yaml:"port"`
|
||||
// Scheme string `yaml:"scheme"`
|
||||
// ClientAuthType int `yaml:"clientAuthType"`
|
||||
// CaFile string `yaml:"caFile"`
|
||||
// CertFile string `yaml:"certFile"`
|
||||
// KeyFile string `yaml:"keyFile"`
|
||||
// } `yaml:"rest"`
|
||||
|
||||
Rest []RestParam
|
||||
|
||||
WebServer struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
@@ -83,39 +81,9 @@ type YamlConfig struct {
|
||||
CmdTimeout int `yaml:"cmdTimeout"`
|
||||
} `yaml:"omc"`
|
||||
|
||||
Alarm struct {
|
||||
ForwardAlarm bool `yaml:"forwardAlarm"`
|
||||
Email struct {
|
||||
Smtp string `yaml:"smtp"`
|
||||
Port uint16 `yaml:"port"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
TlsSkipVerify bool `yaml:"tlsSkipVerify"`
|
||||
} `yaml:"email"`
|
||||
SMS struct {
|
||||
ApiURL string `yaml:"apiURL"`
|
||||
AccessKeyID string `yaml:"AccessKeyID"`
|
||||
AccessKeySecret string `yaml:"accessKeySecret"`
|
||||
SignName string `yaml:"signName"`
|
||||
TemplateCode string `yaml:"templateCode"`
|
||||
} `yaml:"sms"`
|
||||
SMSC struct {
|
||||
Addr string `yaml:"addr"`
|
||||
UserName string `yaml:"userName"`
|
||||
Password string `yaml:"password"`
|
||||
} `yaml:"smsc"`
|
||||
} `yaml:"alarm"`
|
||||
Alarm AlarmConfig `yaml:"alarm"`
|
||||
|
||||
MML struct {
|
||||
Port int `yaml:"port"`
|
||||
Port2 int `yaml:"port2"`
|
||||
Sleep int64 `yaml:"sleep"`
|
||||
DeadLine int64 `yaml:"deadLine"`
|
||||
User string `yaml:"user"`
|
||||
Password string `ymal:"password"`
|
||||
MmlHome string `yaml:"mmlHome"`
|
||||
Upload string `yaml:"upload"`
|
||||
} `yaml:"mml"`
|
||||
MML MMLParam `yaml:"mml"`
|
||||
|
||||
NE struct {
|
||||
Addr string `yaml:"addr"`
|
||||
@@ -156,6 +124,67 @@ type YamlConfig struct {
|
||||
} `yaml:"testConfig"`
|
||||
}
|
||||
|
||||
type RestParam struct {
|
||||
IPv4 string `yaml:"ipv4"`
|
||||
IPv6 string `yaml:"ipv6"`
|
||||
Port uint16 `yaml:"port"`
|
||||
Scheme string `yaml:"scheme,omitempty" default:"http"`
|
||||
ClientAuthType int `yaml:"clientAuthType"`
|
||||
CaFile string `yaml:"caFile"`
|
||||
CertFile string `yaml:"certFile"`
|
||||
KeyFile string `yaml:"keyFile"`
|
||||
}
|
||||
|
||||
type DbConfig struct {
|
||||
Type string `yaml:"type"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
Host string `yaml:"host"`
|
||||
Port string `yaml:"port"`
|
||||
Name string `yaml:"name"`
|
||||
ConnParam string `yaml:"connParam,omitempty"`
|
||||
Backup string `yaml:"backup"`
|
||||
}
|
||||
|
||||
type AlarmConfig struct {
|
||||
SplitEventAlarm bool `yaml:"splitEventAlarm"`
|
||||
ForwardAlarm bool `yaml:"forwardAlarm"`
|
||||
SMProxy string `yaml:"smProxy"`
|
||||
Email struct {
|
||||
Smtp string `yaml:"smtp"`
|
||||
Port uint16 `yaml:"port"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
TlsSkipVerify bool `yaml:"tlsSkipVerify"`
|
||||
} `yaml:"email"`
|
||||
SMS struct {
|
||||
ApiURL string `yaml:"apiURL"`
|
||||
AccessKeyID string `yaml:"AccessKeyID"`
|
||||
AccessKeySecret string `yaml:"accessKeySecret"`
|
||||
SignName string `yaml:"signName"`
|
||||
TemplateCode string `yaml:"templateCode"`
|
||||
} `yaml:"sms"`
|
||||
SMSC struct {
|
||||
Addr string `yaml:"addr"`
|
||||
SystemID string `yaml:"systemID"`
|
||||
Password string `yaml:"password"`
|
||||
SystemType string `yaml:"systemType"`
|
||||
} `yaml:"smsc"`
|
||||
}
|
||||
|
||||
type MMLParam struct {
|
||||
Port int `yaml:"port"`
|
||||
Port2 int `yaml:"port2"`
|
||||
Sleep int64 `yaml:"sleep"`
|
||||
DeadLine int64 `yaml:"deadLine"`
|
||||
SizeRow int16 `yaml:"sizeRow"`
|
||||
SizeCol int16 `yaml:"sizeCol"`
|
||||
BufferSize int `yaml:"bufferSize"`
|
||||
User string `yaml:"user"`
|
||||
Password string `ymal:"password"`
|
||||
MmlHome string `yaml:"mmlHome"`
|
||||
}
|
||||
|
||||
type TestDatas struct {
|
||||
UDM struct {
|
||||
CapUsed uint32 `yaml:"capUsed"`
|
||||
@@ -187,7 +216,25 @@ type TestDataMap struct {
|
||||
NeTestDatas []map[string]NeTestData
|
||||
}
|
||||
|
||||
var yamlConfig YamlConfig
|
||||
var yamlConfig YamlConfig = NewYamlConfig()
|
||||
|
||||
// set default value for yaml config
|
||||
func NewYamlConfig() YamlConfig {
|
||||
return YamlConfig{
|
||||
Database: DbConfig{
|
||||
Type: "mysql",
|
||||
ConnParam: "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True",
|
||||
},
|
||||
MML: MMLParam{
|
||||
SizeRow: 200,
|
||||
SizeCol: 120,
|
||||
BufferSize: 65535,
|
||||
},
|
||||
Alarm: AlarmConfig{
|
||||
SplitEventAlarm: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ReadConfig(configFile string) {
|
||||
yamlFile, err := os.ReadFile(configFile)
|
||||
@@ -323,10 +370,27 @@ func ReadTestConfigYaml(pfile string) (ret error) {
|
||||
}
|
||||
|
||||
func GetDefaultUserAgent() string {
|
||||
return "OMC/" + global.Version
|
||||
return "OMC-restagent/" + global.Version
|
||||
}
|
||||
|
||||
// const defaultConfigFile = "./etc/omc.yaml"
|
||||
func GetOMCHostUrl() string {
|
||||
var omcip string = "127.0.0.1"
|
||||
var rest RestParam = yamlConfig.Rest[0]
|
||||
var port uint16 = rest.Port
|
||||
if rest.IPv4 != "0.0.0.0" && rest.IPv4 != "" {
|
||||
omcip = rest.IPv4
|
||||
} else if rest.IPv6 != "::" && rest.IPv6 != "" {
|
||||
omcip = "[" + rest.IPv6 + "]"
|
||||
}
|
||||
var scheme string = "http"
|
||||
if rest.Scheme != "" {
|
||||
scheme = rest.Scheme
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s://%s:%d", scheme, omcip, port)
|
||||
}
|
||||
|
||||
// const defaultConfigFile = "./etc/restconf.yaml"
|
||||
|
||||
// func init() {
|
||||
// cfile := flag.String("c", defaultConfigFile, "config file")
|
||||
@@ -337,7 +401,7 @@ func GetDefaultUserAgent() string {
|
||||
// //global.GoVer = "go version go1.15.7 linux/arm64"
|
||||
// flag.Parse()
|
||||
// if *pv {
|
||||
// fmt.Printf("OMC version: %s\n%s\n%s\n\n", global.Version, global.BuildTime, global.GoVer)
|
||||
// fmt.Printf("OMC restagent version: %s\n%s\n%s\n\n", global.Version, global.BuildTime, global.GoVer)
|
||||
// os.Exit(0)
|
||||
// }
|
||||
// if *ph {
|
||||
|
||||
@@ -2,12 +2,17 @@
|
||||
# level: /trace/debug/info/warn/error/fatal, default: debug
|
||||
# duration: rotation time with xx hours, example: 1/12/24 hours
|
||||
# count: rotation count of log, default is 30 rotation
|
||||
# pprof: false(default)/true to disable/enable pprof
|
||||
logger:
|
||||
file: d:/local.git/nms_cxy/omc/log/omc.log
|
||||
file: ./etc/omc/log/omc.log
|
||||
level: trace
|
||||
duration: 24
|
||||
count: 2
|
||||
|
||||
pprof:
|
||||
enabled: true
|
||||
addr: :36060
|
||||
|
||||
# rest agent listen ipv4/v6 and port, support multiple routines
|
||||
# ip: 0.0.0.0 or ::0, support IPv4/v6
|
||||
# clientAuthType: 0:NoClientCert (default), 1:RequestClientCert, 2:RequireAnyClientCert,
|
||||
@@ -19,7 +24,7 @@ rest:
|
||||
|
||||
webServer:
|
||||
enabled: false
|
||||
rootDir: d:/local.git/fe.ems.vue3/dist
|
||||
rootDir: ./etc/omc/dist
|
||||
listen:
|
||||
- addr: :80
|
||||
schema: http
|
||||
@@ -34,10 +39,11 @@ database:
|
||||
type: mysql
|
||||
user: root
|
||||
password: "root@1234"
|
||||
host: "192.168.5.59"
|
||||
host: "192.168.8.58"
|
||||
port: 3306
|
||||
name: omc_db_nms_cxy
|
||||
backup: d:/local.git/be.ems/omc/database
|
||||
name: "omc_db_nms_cxy"
|
||||
connParam: charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True
|
||||
backup: ./etc/omc/database
|
||||
|
||||
# Redis 缓存数据,数据源声明全小写
|
||||
redis:
|
||||
@@ -45,14 +51,14 @@ redis:
|
||||
# OMC系统使用库
|
||||
default:
|
||||
port: 6379 # Redis port
|
||||
host: "192.168.5.59" # Redis host
|
||||
host: "192.168.8.58" # Redis host
|
||||
password: "redis@1234"
|
||||
db: 10 # Redis db_num
|
||||
# UDM网元用户库
|
||||
udmuser:
|
||||
port: 6379 # Redis port
|
||||
host: "192.168.13.140"
|
||||
password: ""
|
||||
port: 36379 # Redis port
|
||||
host: "192.168.8.58"
|
||||
password: "helloearth"
|
||||
db: 0 # Redis db_num
|
||||
# 多个数据源时可以用这个指定默认的数据源
|
||||
defaultDataSourceName: "default"
|
||||
@@ -64,22 +70,24 @@ mml:
|
||||
port2: 5002
|
||||
sleep: 200
|
||||
deadLine: 10
|
||||
sizeRow: 600
|
||||
sizeCol: 128
|
||||
bufferSize: 65535
|
||||
user: admin
|
||||
password: admin
|
||||
mmlHome: ./mmlhome
|
||||
upload: /home/agtuser
|
||||
|
||||
# NE config
|
||||
ne:
|
||||
user: agtuser
|
||||
user: omcuser
|
||||
etcdir: /usr/local/etc
|
||||
bindir: /usr/local/bin
|
||||
omcdir: /usr/local/omc
|
||||
scpdir: /tmp
|
||||
licensedir: /usr/local/etc/{neType}/license
|
||||
# backup etc list of IMS,no space
|
||||
etcListIMS: "{*.yaml,mmtel,vars.cfg}"
|
||||
etcListDefault: "{*.yaml,*.conf,*.cfg}"
|
||||
etcListIMS: '{*.yaml,mmtel,vars.cfg}'
|
||||
etcListDefault: '{*.yaml,*.conf,*.cfg}'
|
||||
# true/false to overwrite config file when dpkg ne software
|
||||
dpkgOverwrite: false
|
||||
# dpkg timeout (second)
|
||||
@@ -100,12 +108,12 @@ omc:
|
||||
checksign: false
|
||||
rootDir: ./
|
||||
binDir: ./bin
|
||||
backup: ./backup
|
||||
upload: ./upload
|
||||
frontUpload: d:/local.git/fe.ems/upload
|
||||
frontTraceDir: d:/local.git/fe.ems/trace
|
||||
software: ./software
|
||||
license: ./license
|
||||
backup: ./etc/omc/backup
|
||||
upload: ./etc/omc/upload
|
||||
frontUpload: ./etc/omc/upload
|
||||
frontTraceDir: ./etc/omc/trace
|
||||
software: ./etc/omc/software
|
||||
license: ./etc/omc/license
|
||||
gtpUri: gtp:192.168.2.219:2152
|
||||
checkContentType: false
|
||||
testMode: false
|
||||
@@ -116,8 +124,9 @@ omc:
|
||||
# Alarm module setting
|
||||
# Forward interface:
|
||||
# email/sms
|
||||
# smProxy: sms(Short Message Service)/smsc(SMS Centre)
|
||||
alarm:
|
||||
forwardAlarm: true
|
||||
forwardAlarm: false
|
||||
email:
|
||||
smtp: mail.agrandtech.com
|
||||
port: 25
|
||||
@@ -125,16 +134,18 @@ alarm:
|
||||
password: "1000smtp@omc!"
|
||||
# TLS skip verify: true/false
|
||||
tlsSkipVerify: true
|
||||
smProxy: smsc
|
||||
sms:
|
||||
apiURL: http://smsc.xxx.com.cn/
|
||||
apiURL: http://smsc.xxx.com/
|
||||
accessKeyID: xxxx
|
||||
accessKeySecret: xxxx
|
||||
signName: xxx SMSC
|
||||
templateCode: 1000
|
||||
smsc:
|
||||
addr: "192.168.14.211:2775"
|
||||
userName: OMC
|
||||
password: "123456"
|
||||
addr: "192.168.13.114:2775"
|
||||
systemID: "omc"
|
||||
password: "omc123"
|
||||
systemType: "UTRAN"
|
||||
|
||||
#User authorized information
|
||||
# crypt: mysql/md5/bcrypt
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
# file: log file name
|
||||
# level: /trace/debug/info/warn/error/fatal, default: debug
|
||||
# duration: rotation time with xx hours, example: 1/12/24 hours
|
||||
# count: rotation count of log, default is 30 rotation
|
||||
logger:
|
||||
file: d:/local.git/nms_cxy/omc/log/omc-t.log
|
||||
level: trace
|
||||
duration: 24
|
||||
count: 2
|
||||
|
||||
# rest agent listen ipv4/v6 and port, support multiple routines
|
||||
# ip: 0.0.0.0 or ::0, support IPv4/v6
|
||||
rest:
|
||||
- ipv4: 0.0.0.0
|
||||
ipv6:
|
||||
port: 33030
|
||||
- ipv4: 0.0.0.0
|
||||
ipv6:
|
||||
port: 36060
|
||||
|
||||
database:
|
||||
type: mysql
|
||||
user: root
|
||||
password: 1000omc@kp!
|
||||
host: 127.0.0.1
|
||||
port: 33066
|
||||
name: omc_db
|
||||
backup: d:/local.git/nms_cxy/omc/database
|
||||
|
||||
# Redis 缓存数据,数据源声明全小写
|
||||
redis:
|
||||
dataSource:
|
||||
# OMC系统使用库
|
||||
default:
|
||||
port: 6379 # Redis port
|
||||
host: "192.168.2.166" # Redis host
|
||||
password: ""
|
||||
db: 10 # Redis db_num
|
||||
# UDM网元用户库
|
||||
udmuser:
|
||||
port: 6379 # Redis port
|
||||
host: "192.168.2.166"
|
||||
password: ""
|
||||
db: 0 # Redis db_num
|
||||
# 多个数据源时可以用这个指定默认的数据源
|
||||
defaultDataSourceName: "default"
|
||||
|
||||
mml:
|
||||
port: 4100
|
||||
sleep: 200
|
||||
user: admin
|
||||
password: admin
|
||||
mmlHome: ./mmlhome
|
||||
|
||||
ne:
|
||||
user: root
|
||||
etcdir: /usr/local/etc
|
||||
bindir: /usr/local/bin
|
||||
omcdir: /usr/local/omc
|
||||
scpdir: /tmp
|
||||
licensedir: /usr/local/etc/{neType}/license
|
||||
|
||||
# chk2ne: true/false, if put OmcNeConfig parameters to NE
|
||||
omc:
|
||||
uriPrefix: "/omc/rest"
|
||||
neType: OMC
|
||||
neId: 001
|
||||
rmUID: 4400HX101
|
||||
neName: OMC
|
||||
province: GD
|
||||
vendor: ""
|
||||
dn: 4600
|
||||
chk2ne: false
|
||||
sn: 13750650
|
||||
checksign: false
|
||||
backup: ./backup
|
||||
upload: ./upload
|
||||
frontUpload: d:/local.git/fe.ems/upload
|
||||
frontTraceDir: d:/local.git/fe.ems/trace
|
||||
software: ./software
|
||||
license: ./license
|
||||
gtpUri: gtp:192.168.2.119:2152
|
||||
checkContentType: false
|
||||
testMode: false
|
||||
rbacMode: true
|
||||
runDir:
|
||||
|
||||
# Alarm module setting
|
||||
# Forward interface:
|
||||
# email/sms
|
||||
alarm:
|
||||
forwardAlarm: true
|
||||
email:
|
||||
smtp: smtp@xxx.com.cn
|
||||
port: 25
|
||||
user: smtpuser
|
||||
password: smtpuser@omc
|
||||
sms:
|
||||
apiURL: http://smsc.xxx.com.cn/
|
||||
accessKeyID: xxxx
|
||||
accessKeySecret: xxxx
|
||||
signName: xxx SMSC
|
||||
templateCode: 1000
|
||||
|
||||
#User authorized information
|
||||
# crypt: mysql/md5/bcrypt
|
||||
# token: true/false to check accessToken
|
||||
# expires for session, unit: second
|
||||
# Support single/multiple session of user
|
||||
auth:
|
||||
crypt: bcrypt
|
||||
token: true
|
||||
expires: 1800
|
||||
session: multiple
|
||||
publicKey: ./etc/certs/omc_pub.key
|
||||
privateKey: ./etc/certs/omc_pri.key
|
||||
|
||||
# Parameter for limit number
|
||||
# rmuid_maxnum: the max number of rmUID, default: 50
|
||||
# alarmid_maxnum: the max number of AlarmID, default: 50
|
||||
# pmid_maxnum: the max number of pmID, default: 50
|
||||
# subid_maxnum: the max number of subscription ID, default: 20
|
||||
# uri_maxlen: the max length of uri, default: 8192
|
||||
# rmuid_regexp: regexp pattern of rmUID
|
||||
params:
|
||||
rmuidmaxnum: 50
|
||||
alarmidmaxnum: 50
|
||||
pmidmaxnum: 50
|
||||
subidmaxnum: 20
|
||||
urimaxlen: 2100000
|
||||
rmuidregexp: "[0-9]{4}[A-Z]{2}[A-Z]{2}[0-9A-Z]{1}[0-9A-Z]{3}[0-9A-Z]{1,16}"
|
||||
testConfig:
|
||||
enabled: true
|
||||
file: ./etc/testconfig.yaml
|
||||
@@ -1,13 +1,13 @@
|
||||
# Makefile for rest agent project
|
||||
|
||||
PROJECT = OMC
|
||||
VERSION = 2.2403.3
|
||||
VERSION = 2.2407.1
|
||||
LIBDIR = nms_cxy/lib
|
||||
BINNAME = omc
|
||||
|
||||
.PHONY: build $(BINNAME)
|
||||
build $(BINNAME):
|
||||
go build -o $(BINNAME) -v -ldflags "-X '$(LIBDIR)/global.Version=$(VERSION)' \
|
||||
go build -o $(BINNAME) -v -ldflags "-s -w -X '$(LIBDIR)/global.Version=$(VERSION)' \
|
||||
-X '$(LIBDIR)/global.BuildTime=`date`' \
|
||||
-X '$(LIBDIR)/global.GoVer=`go version`'"
|
||||
|
||||
|
||||
34
omc/omc.go
34
omc/omc.go
@@ -9,10 +9,13 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
_ "net/http/pprof"
|
||||
|
||||
"nms_cxy/features/dbrest"
|
||||
"nms_cxy/features/event"
|
||||
"nms_cxy/features/fm"
|
||||
"nms_cxy/features/lm"
|
||||
"nms_cxy/features/mml"
|
||||
"nms_cxy/features/pm"
|
||||
"nms_cxy/lib/dborm"
|
||||
"nms_cxy/lib/global"
|
||||
@@ -21,7 +24,6 @@ import (
|
||||
"nms_cxy/omc/config"
|
||||
"nms_cxy/src"
|
||||
"nms_cxy/src/framework/middleware"
|
||||
libSession "nms_cxy/src/lib_features/session"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/net/http2"
|
||||
@@ -138,61 +140,69 @@ func HttpListenWebServer(addr string) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// src 配置中心初始加载
|
||||
src.ConfigurationInit()
|
||||
app := src.AppEngine()
|
||||
|
||||
conf := config.GetYamlConfig()
|
||||
|
||||
log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc", config.GetLogLevel())
|
||||
fmt.Printf("OMC version: %s\n", global.Version)
|
||||
if conf.Pprof.Enabled {
|
||||
// 启用pprof HTTP服务
|
||||
go func() {
|
||||
fmt.Println(http.ListenAndServe(conf.Pprof.Addr, nil))
|
||||
}()
|
||||
}
|
||||
|
||||
log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc:", config.GetLogLevel())
|
||||
fmt.Printf("OMC restagent version: %s\n", global.Version)
|
||||
log.Infof("========================= OMC startup =========================")
|
||||
log.Infof("OMC version: %s %s %s", global.Version, global.BuildTime, global.GoVer)
|
||||
log.Infof("OMC restagent version: %s %s %s", global.Version, global.BuildTime, global.GoVer)
|
||||
|
||||
err := dborm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name, conf.Database.ConnParam)
|
||||
if err != nil {
|
||||
fmt.Println("dborm.initDbClient err:", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
err = fm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name, conf.Database.ConnParam)
|
||||
if err != nil {
|
||||
fmt.Println("dborm.initDbClient err:", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
err = pm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name, conf.Database.ConnParam)
|
||||
if err != nil {
|
||||
fmt.Println("dborm.initDbClient err:", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
err = dbrest.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name, conf.Database.ConnParam)
|
||||
if err != nil {
|
||||
fmt.Println("dbrest.initDbClient err:", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
err = lm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
||||
conf.Database.Host, conf.Database.Port, conf.Database.Name, conf.Database.ConnParam)
|
||||
if err != nil {
|
||||
fmt.Println("lm.initDbClient err:", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
|
||||
mml.InitMML()
|
||||
|
||||
// 将 mux.Router 注册到 gin.Engine
|
||||
|
||||
// 默认路由组
|
||||
defaultUriGroup := app.Group(config.DefaultUriPrefix)
|
||||
defaultUriGroup.Use(middleware.PreAuthorize(nil))
|
||||
defaultUriGroup.Use(libSession.SessionHeader())
|
||||
defaultUriGroup.Any("/*any", gin.WrapH(routes.NewRouter()))
|
||||
// 可配置前缀路由组
|
||||
uriGroup := app.Group(config.UriPrefix)
|
||||
uriGroup.Use(libSession.SessionHeader())
|
||||
uriGroup.Any("/*any", gin.WrapH(routes.NewRouter()))
|
||||
// AMF上报的UE事件, 无前缀,暂时特殊处理
|
||||
app.POST(event.UriUEEvent, event.PostUEEventFromAMF)
|
||||
app.POST(event.UriUEEventAMF, event.PostUEEventFromAMF)
|
||||
|
||||
for _, rest := range conf.Rest {
|
||||
// ipv4 goroutines
|
||||
|
||||
18
src/app.go
18
src/app.go
@@ -8,18 +8,20 @@ import (
|
||||
"nms_cxy/src/framework/errorcatch"
|
||||
"nms_cxy/src/framework/middleware"
|
||||
"nms_cxy/src/framework/middleware/security"
|
||||
"nms_cxy/src/framework/utils/machine"
|
||||
"nms_cxy/src/modules/chart"
|
||||
"nms_cxy/src/modules/common"
|
||||
"nms_cxy/src/modules/crontask"
|
||||
"nms_cxy/src/modules/monitor"
|
||||
networkdata "nms_cxy/src/modules/network_data"
|
||||
networkelement "nms_cxy/src/modules/network_element"
|
||||
nmscxy "nms_cxy/src/modules/nms_cxy"
|
||||
"nms_cxy/src/modules/system"
|
||||
"nms_cxy/src/modules/trace"
|
||||
"nms_cxy/src/modules/ws"
|
||||
|
||||
"github.com/chenjiandongx/ginprom"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
//go:embed assets/*
|
||||
@@ -29,6 +31,13 @@ var assetsDir embed.FS
|
||||
func AppEngine() *gin.Engine {
|
||||
app := initAppEngine()
|
||||
|
||||
// TODO 不建议在主分支中加入
|
||||
// 性能分析监控
|
||||
if promEnabled := config.Get("pprof.enabled"); promEnabled != nil && promEnabled.(bool) {
|
||||
app.Use(ginprom.PromMiddleware(nil))
|
||||
app.GET("/metrics", ginprom.PromHandler(promhttp.Handler()))
|
||||
}
|
||||
|
||||
// 初始全局默认
|
||||
initDefeat(app)
|
||||
|
||||
@@ -38,6 +47,9 @@ func AppEngine() *gin.Engine {
|
||||
// 设置程序内全局资源访问
|
||||
config.SetAssetsDirFS(assetsDir)
|
||||
|
||||
// 首次安装启动记录
|
||||
machine.Launch()
|
||||
|
||||
// 读取服务配置
|
||||
app.ForwardedByClientIP = config.Get("server.proxy").(bool)
|
||||
return app
|
||||
@@ -109,7 +121,7 @@ func initDefeat(app *gin.Engine) {
|
||||
app.NoRoute(func(c *gin.Context) {
|
||||
c.JSON(404, gin.H{
|
||||
"code": 404,
|
||||
"msg": fmt.Sprintf("%s Not Found", c.Request.RequestURI),
|
||||
"msg": fmt.Sprintf("Not Found %s", c.Request.RequestURI),
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -124,8 +136,6 @@ func initModulesRoute(app *gin.Engine) {
|
||||
networkelement.Setup(app)
|
||||
// 网元数据模块
|
||||
networkdata.Setup(app)
|
||||
// 北向模块 - 中国星网
|
||||
nmscxy.Setup(app)
|
||||
// 跟踪模块
|
||||
trace.Setup(app)
|
||||
// 图表模块
|
||||
|
||||
@@ -27,9 +27,9 @@ func InitConfig() {
|
||||
func initFlag() {
|
||||
// --env prod
|
||||
pflag.String("env", "prod", "Specify Run Environment Configuration local or prod")
|
||||
// --c /etc/omc.yaml
|
||||
// -c /etc/omc.yaml
|
||||
pConfig := pflag.StringP("config", "c", "./etc/omc.yaml", "Specify Configuration File")
|
||||
// --c /etc/restconf.yaml
|
||||
// -c /etc/restconf.yaml
|
||||
pConfig := pflag.StringP("config", "c", "./etc/restconf.yaml", "Specify Configuration File")
|
||||
// --version
|
||||
// -V
|
||||
pVersion := pflag.BoolP("version", "V", false, "Output program version")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 项目信息
|
||||
framework:
|
||||
name: "CN EMS"
|
||||
version: "2.2403.3"
|
||||
version: "2.2407.1"
|
||||
|
||||
# 应用服务配置
|
||||
server:
|
||||
@@ -15,7 +15,7 @@ logger:
|
||||
fileDir: "/var/log"
|
||||
fileName: "omc.log"
|
||||
level: 2 # 日志记录的等级 0:silent<1:info<2:warn<3:error
|
||||
maxDay: 180 # 日志会保留 180 天
|
||||
maxDay: 7 # 日志会保留 180 天
|
||||
maxSize: 10 # 调整按 10MB 大小的切割
|
||||
|
||||
# 静态文件配置, 相对项目根路径或填绝对路径
|
||||
@@ -68,6 +68,8 @@ upload:
|
||||
# 软件包
|
||||
- ".deb"
|
||||
- ".rpm"
|
||||
# 验证文件
|
||||
- ".ini"
|
||||
|
||||
# cors 跨域
|
||||
cors:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package admin
|
||||
|
||||
// 管理员常量信息
|
||||
// 系统管理员常量信息
|
||||
|
||||
// 管理员-系统指定角色ID
|
||||
// 系统管理员-系统指定角色ID
|
||||
const ROLE_ID = "1"
|
||||
|
||||
// 管理员-系统指定角色KEY
|
||||
const ROLE_KEY = "admin"
|
||||
// 系统管理员-系统指定角色KEY
|
||||
const ROLE_KEY = "system"
|
||||
|
||||
// 管理员-系统指定权限
|
||||
// 系统管理员-系统指定权限
|
||||
const PERMISSION = "*:*:*"
|
||||
|
||||
@@ -19,3 +19,6 @@ const STATUS_NO = "0"
|
||||
|
||||
// 上下文信息-登录用户
|
||||
const CTX_LOGIN_USER = "loginuser"
|
||||
|
||||
// 启动-引导系统初始
|
||||
const LAUNCH_BOOTLOADER = "bootloader"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user