feat: support ims user, voip auth data and backup UE data
This commit is contained in:
@@ -703,10 +703,11 @@ INSERT INTO `sys_dict_data` VALUES (2192, 2192, 'menu.dashboard.overview.gnbBase
|
||||
INSERT INTO `sys_dict_data` VALUES (2193, 2193, 'menu.dashboard.overview.enbBase', '展示4G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (2194, 2194, 'menu.ueUser.imsUDM', 'IMS签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (2195, 2195, 'menu.ueUser.imsUDMRemark', 'IMS签约用户菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (2196, 2196, 'menu.ueUser.voipUDM', 'VoIP签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (2197, 2197, 'menu.ueUser.voipUDMRemark', 'VoIP签约用户菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (2196, 2196, 'menu.ueUser.voipUDM', 'VoIP鉴权数据', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (2197, 2197, 'menu.ueUser.voipUDMRemark', 'VoIP鉴权数据菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (2198, 2198, 'menu.ueUser.exportFile', '导出文件管理', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (2199, 2199, 'menu.ueUser.exportFileRemark', '导出文件管理菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (2200, 2200, 'job.backup.ue.data', '定期从UE用户和数据表导出文件至指定目录', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
|
||||
-- multi-tenancy
|
||||
INSERT INTO `sys_dict_data` VALUES (11000, 11000, 'menu.security.tenant', '租户管理', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
|
||||
|
||||
@@ -703,10 +703,11 @@ INSERT INTO `sys_dict_data` VALUES (4192, 4192, 'menu.dashboard.overview.gnbBase
|
||||
INSERT INTO `sys_dict_data` VALUES (4193, 4193, 'menu.dashboard.overview.enbBase', 'Display 4G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (4194, 4194, 'menu.ueUser.imsUDM', 'IMS Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (4195, 4195, 'menu.ueUser.imsUDMRemark', 'IMS Subscribers Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (4196, 4196, 'menu.ueUser.voipUDM', 'VoIP Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (4197, 4197, 'menu.ueUser.voipUDMRemark', 'VoIP Subscribers Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (4196, 4196, 'menu.ueUser.voipUDM', 'VoIP Authentication', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (4197, 4197, 'menu.ueUser.voipUDMRemark', 'VoIP Authentication Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (4198, 4198, 'menu.ueUser.exportFile', 'Exported File Management', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (4199, 4199, 'menu.ueUser.exportFileRemark', 'Exported File Management Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
INSERT INTO `sys_dict_data` VALUES (4200, 4200, 'job.backup.ue.data', 'Regularly export files from UE users and data tables to a specified directory', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
|
||||
-- 多租户
|
||||
INSERT INTO `sys_dict_data` VALUES (14000, 14000, 'menu.security.tenant', 'Tenant Management', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
|
||||
|
||||
@@ -42,7 +42,8 @@ INSERT INTO `sys_job` VALUES (11, 'job.exportOperateLog', 'SYSTEM', 'exportTable
|
||||
INSERT INTO `sys_job` VALUES (12, 'job.exportIMSCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_ims\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callType\')) as call_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callerParty\')) as caller_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.calledParty\')) as called_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callDuration\')) as call_duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.serviceResult\')) as service_result,DATE_FORMAT(FROM_UNIXTIME(timestamp), \'%Y-%m-%d %H:%i:%s\') AS timestamp\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/ims_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1722224659251, '');
|
||||
INSERT INTO `sys_job` VALUES (13, 'job.exportSMFCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_smf\",\"columns\":\"id,ne_type,ne_name,rm_uid,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) AS record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.chargingID\')) AS charging_id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDType\')) AS subscriber_id_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDData\')) AS subscriber_id_data,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.duration\')) AS duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.invocationTimestamp\')) as invocationTimestamp,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeUplink\')) AS data_volume_uplink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeDownlink\')) AS data_volume_downlink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataTotalVolume\')) AS data_total_volume,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.pDUSessionChargingInformation.pDUAddress.pDUIPv4Address\')) AS pdu_ipv4_address,timestamp\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/smf_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, '');
|
||||
INSERT INTO `sys_job` VALUES (14, 'job.exportSMSCCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_smsc\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.serviceType\')) as service_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callerParty\')) as caller_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.calledParty\')) as called_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.result\')) as result,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.updateTime\')) as update_time\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/smsc_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, '');
|
||||
INSERT INTO `sys_job` VALUES (15, 'job.removeExportedFiles', 'SYSTEM', 'removeFile', '[{\"filePath\":\"/usr/local/omc/backup/operate_log\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/ims_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smf_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smsc_cdr\",\"maxDays\":30}]', '0 10 0 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1728634085631, '');
|
||||
INSERT INTO `sys_job` VALUES (15, 'job.removeExportedFiles', 'SYSTEM', 'removeFile', '[{\"filePath\":\"/usr/local/omc/backup/operate_log\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/ims_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smf_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smsc_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/u_auth_user\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/u_sub_user\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/u_voip_auth\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/u_ims_user\",\"maxDays\":30}]', '0 10 0 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1728634085631, '');
|
||||
INSERT INTO `sys_job` VALUES (16, 'job.exportSGWCCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_sgwc\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as recordType,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.accessPointNameNI\')) as accessPointNameNI,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.servedIMSI\')) as IMSI,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.servedMSISDN\')) as MSISDN,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.servedPDPPDNAddress\')) as PdpAddress,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.duration\')) as duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordOpeningTime\')) as recordOpeningTime,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.chargingID\')) as chargingID,JSON_UNQUOTE(JSON_EXTRACT(cdr_json, \'$.listOfTrafficVolumes[0].dataVolumeGPRSDownlink\')) AS dataVolumeGPRSDownlink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json, \'$.listOfTrafficVolumes[0].dataVolumeGPRsUplink\')) as dataVolumeGPRsUplink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.userLocationInformation.tai.tac\')) as tac,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.userLocationInformation.ecgi.eutraCellId\')) as cellID\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/sgwc_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, '');
|
||||
INSERT INTO `sys_job` VALUES (17, 'job.backup.ue.data', 'SYSTEM', 'exportUEData', '[{\"tableName\":\"u_auth_user\",\"columns\":\"imsi,ki,algo,amf,opc\",\"extras\":\"\",\"serviceName\":\"UDMAuthUser\",\"orderBy\":\"imsi\",\"orderType\":\"desc\", \"fileType\":\"txt\",\"filePath\":\"/usr/local/omc/backup/u_auth_user\"},{\"tableName\":\"u_sub_user\",\"columns\":\"imsi,msisdn,ambr,nssai,arfb,sar,rat,cn_type,smf_sel,sm_data,eps_flag,eps_odb,hplmn_odb,ard,epstpl,context_id,apn_context,static_ip\",\"extras\":\"\",\"serviceName\":\"UDMSubUser\",\"orderBy\":\"imsi\",\"orderType\":\"desc\", \"fileType\":\"txt\",\"filePath\":\"/usr/local/omc/backup/u_sub_user\"},{\"tableName\":\"u_voip_auth\",\"columns\":\"user_name,password\",\"extras\":\"\",\"serviceName\":\"UDMVoIPAuth\",\"orderBy\":\"user_name\",\"orderType\":\"desc\", \"fileType\":\"txt\",\"filePath\":\"/usr/local/omc/backup/u_voip_auth\"},{\"tableName\":\"u_ims_user\",\"columns\":\"imsi,msisdn,volte,vni\",\"extras\":\"\",\"serviceName\":\"UDMIMSUser\",\"orderBy\":\"imsi\",\"orderType\":\"desc\", \"fileType\":\"txt\",\"filePath\":\"/usr/local/omc/backup/u_ims_user\"}]', '0 35 0 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1743479268652, '');
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
@@ -129,8 +129,8 @@ INSERT INTO `sys_menu` VALUES (1055, 'menu.common.edit', 116, 5, '#', NULL, '1',
|
||||
INSERT INTO `sys_menu` VALUES (1056, 'menu.common.export', 116, 6, '#', NULL, '1', '1', 'B', '1', '1', 'monitor:job:export', '#', 'supervisor', 1700000000000, NULL, 0, NULL);
|
||||
INSERT INTO `sys_menu` VALUES (2009, 'menu.ueUser.authUDM', 5, 1, 'auth', 'neUser/auth/index', '1', '1', 'M', '1', '1', 'neUser:auth:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.authUDMRemark');
|
||||
INSERT INTO `sys_menu` VALUES (2010, 'menu.ueUser.subUDM', 5, 2, 'sub', 'neUser/sub/index', '1', '1', 'M', '1', '1', 'neUser:sub:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.subUDMRemark');
|
||||
INSERT INTO `sys_menu` VALUES (2011, 'menu.ueUser.imsUDM', 5, 3, 'imsUDM', 'neUser/imsUDM/index', '1', '1', 'M', '1', '1', 'neUser:imsUDM:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.imsUDMRemark');
|
||||
INSERT INTO `sys_menu` VALUES (2012, 'menu.ueUser.voipUDM', 5, 4, 'voip', 'neUser/voip/index', '1', '1', 'M', '1', '1', 'neUser:voip:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.voipUDMRemark');
|
||||
INSERT INTO `sys_menu` VALUES (2011, 'menu.ueUser.voipUDM', 5, 3, 'voip', 'neUser/voip/index', '1', '1', 'M', '1', '1', 'neUser:voip:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.voipUDMRemark');
|
||||
INSERT INTO `sys_menu` VALUES (2012, 'menu.ueUser.imsUDM', 5, 4, 'imsUDM', 'neUser/imsUDM/index', '1', '1', 'M', '1', '1', 'neUser:imsUDM:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.imsUDMRemark');
|
||||
INSERT INTO `sys_menu` VALUES (2079, 'menu.ueUser.exportFile', 5, 20, 'exportFile', 'neUser/exportFile/index', '1', '1', 'M', '1', '1', 'neUser:exportFile:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.exportFileRemark');
|
||||
-- INSERT INTO `sys_menu` VALUES (2075, 'menu.config.neManage', 4, 1, 'neManage', 'configManage/neManage/index', '1', '0', 'M', '1', '0', 'configManage:neManage:index', 'icon-biaoqing', 'supervisor', 1700000000000, NULL, 0, 'menu.config.neManageRemark');
|
||||
-- INSERT INTO `sys_menu` VALUES (2078, 'menu.config.backupManage', 4, 100, 'backupManage', 'configManage/backupManage/index', '1', '0', 'M', '1', '0', 'configManage:backupManage:index', 'icon-soutubiao', 'supervisor', 1700000000000, NULL, 0, 'menu.config.backupManageRemark');
|
||||
|
||||
36
database/install/u_ims_user.sql
Executable file
36
database/install/u_ims_user.sql
Executable file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : omc@192.168.2.211
|
||||
Source Server Type : MariaDB
|
||||
Source Server Version : 100621 (10.6.21-MariaDB-0ubuntu0.22.04.2)
|
||||
Source Host : 192.168.2.211:33066
|
||||
Source Schema : tenants_db
|
||||
|
||||
Target Server Type : MariaDB
|
||||
Target Server Version : 100621 (10.6.21-MariaDB-0ubuntu0.22.04.2)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 09/04/2025 09:22:00
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for u_ims_user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `u_ims_user`;
|
||||
CREATE TABLE `u_ims_user` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ne_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`imsi` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'SIM/USIMID',
|
||||
`msisdn` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
|
||||
`volte` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
|
||||
`vni` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
|
||||
`tenant_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'multi-tenancy refer to sys_tenant.tenant_id',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uk_imsi_ne`(`imsi`, `ne_id`) USING BTREE COMMENT 'imsi_neid'
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'UDM' ROW_FORMAT = Dynamic;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
34
database/install/u_voip_auth.sql
Executable file
34
database/install/u_voip_auth.sql
Executable file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : omc@192.168.2.211
|
||||
Source Server Type : MariaDB
|
||||
Source Server Version : 100621 (10.6.21-MariaDB-0ubuntu0.22.04.2)
|
||||
Source Host : 192.168.2.211:33066
|
||||
Source Schema : tenants_db
|
||||
|
||||
Target Server Type : MariaDB
|
||||
Target Server Version : 100621 (10.6.21-MariaDB-0ubuntu0.22.04.2)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 09/04/2025 09:26:02
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for u_voip_auth
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `u_voip_auth`;
|
||||
CREATE TABLE `u_voip_auth` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ne_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
|
||||
`tenant_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'multi-tenancy refer to sys_tenant.tenant_id',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_user_name`(`user_name`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'UDM' ROW_FORMAT = Dynamic;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -710,10 +710,11 @@ REPLACE INTO `sys_dict_data` VALUES (2192, 2192, 'menu.dashboard.overview.gnbBas
|
||||
REPLACE INTO `sys_dict_data` VALUES (2193, 2193, 'menu.dashboard.overview.enbBase', '展示4G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (2194, 2194, 'menu.ueUser.imsUDM', 'IMS签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (2195, 2195, 'menu.ueUser.imsUDMRemark', 'IMS签约用户菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (2196, 2196, 'menu.ueUser.voipUDM', 'VoIP签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (2197, 2197, 'menu.ueUser.voipUDMRemark', 'VoIP签约用户菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (2196, 2196, 'menu.ueUser.voipUDM', 'VoIP鉴权数据', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (2197, 2197, 'menu.ueUser.voipUDMRemark', 'VoIP鉴权数据菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (2198, 2198, 'menu.ueUser.exportFile', '导出文件管理', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (2199, 2199, 'menu.ueUser.exportFileRemark', '导出文件管理菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (2200, 2200, 'job.backup.ue.data', '定期备份UE用户和数据表', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
|
||||
-- multi-tenancy
|
||||
REPLACE INTO `sys_dict_data` VALUES (11000, 11000, 'menu.security.tenant', '租户管理', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
|
||||
|
||||
@@ -709,10 +709,11 @@ REPLACE INTO `sys_dict_data` VALUES (4192, 4192, 'menu.dashboard.overview.gnbBas
|
||||
REPLACE INTO `sys_dict_data` VALUES (4193, 4193, 'menu.dashboard.overview.enbBase', 'Display 4G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (4194, 4194, 'menu.ueUser.imsUDM', 'IMS Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (4195, 4195, 'menu.ueUser.imsUDMRemark', 'IMS Subscribers Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (4196, 4196, 'menu.ueUser.voipUDM', 'VoIP Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (4197, 4197, 'menu.ueUser.voipUDMRemark', 'VoIP Subscribers Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (4196, 4196, 'menu.ueUser.voipUDM', 'VoIP Authentication', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (4197, 4197, 'menu.ueUser.voipUDMRemark', 'VoIP Authentication Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (4198, 4198, 'menu.ueUser.exportFile', 'Exported File Management', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (4199, 4199, 'menu.ueUser.exportFileRemark', 'Exported File Management Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
REPLACE INTO `sys_dict_data` VALUES (4200, 4200, 'job.backup.ue.data', 'Backup regularly UE users and data', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
|
||||
|
||||
-- 多租户
|
||||
REPLACE INTO `sys_dict_data` VALUES (14000, 14000, 'menu.security.tenant', 'Tenant Management', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
|
||||
|
||||
@@ -46,7 +46,8 @@ REPLACE INTO `sys_job` VALUES (11, 'job.exportOperateLog', 'SYSTEM', 'exportTabl
|
||||
REPLACE INTO `sys_job` VALUES (12, 'job.exportIMSCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_ims\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callType\')) as call_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callerParty\')) as caller_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.calledParty\')) as called_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callDuration\')) as call_duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.serviceResult\')) as service_result,DATE_FORMAT(FROM_UNIXTIME(timestamp), \'%Y-%m-%d %H:%i:%s\') AS timestamp\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/ims_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1722224659251, '');
|
||||
REPLACE INTO `sys_job` VALUES (13, 'job.exportSMFCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_smf\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) AS record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.chargingID\')) AS charging_id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDType\')) AS subscriber_id_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.subscriberIdentifier.subscriptionIDData\')) AS subscriber_id_data,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.duration\')) AS duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.invocationTimestamp\')) as invocationTimestamp,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeUplink\')) AS data_volume_uplink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeDownlink\')) AS data_volume_downlink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataTotalVolume\')) AS data_total_volume,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.pDUSessionChargingInformation.pDUAddress.pDUIPv4Address\')) AS pdu_ipv4_address,timestamp\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/smf_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, '');
|
||||
REPLACE INTO `sys_job` VALUES (14, 'job.exportSMSCCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_smsc\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as record_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.serviceType\')) as service_type,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.callerParty\')) as caller_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.calledParty\')) as called_party,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.result\')) as result,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.updateTime\')) as update_time\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/smsc_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, '');
|
||||
REPLACE INTO `sys_job` VALUES (15, 'job.removeExportedFiles', 'SYSTEM', 'removeFile', '[{\"filePath\":\"/usr/local/omc/backup/operate_log\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/ims_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smf_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smsc_cdr\",\"maxDays\":30}]', '0 10 0 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1728634085631, '');
|
||||
REPLACE INTO `sys_job` VALUES (15, 'job.removeExportedFiles', 'SYSTEM', 'removeFile', '[{\"filePath\":\"/usr/local/omc/backup/operate_log\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/ims_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smf_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/smsc_cdr\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/u_auth_user\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/u_sub_user\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/u_voip_auth\",\"maxDays\":30},{\"filePath\":\"/usr/local/omc/backup/u_ims_user\",\"maxDays\":30}]', '0 10 0 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1728634085631, '');
|
||||
REPLACE INTO `sys_job` VALUES (16, 'job.exportSGWCCDR', 'SYSTEM', 'exportTable', '{\"duration\":1,\"tableName\":\"cdr_event_sgwc\",\"columns\":\"id,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordType\')) as recordType,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.accessPointNameNI\')) as accessPointNameNI,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.servedIMSI\')) as IMSI,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.servedMSISDN\')) as MSISDN,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.servedPDPPDNAddress\')) as PdpAddress,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.duration\')) as duration,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.recordOpeningTime\')) as recordOpeningTime,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.chargingID\')) as chargingID,JSON_UNQUOTE(JSON_EXTRACT(cdr_json, \'$.listOfTrafficVolumes[0].dataVolumeGPRSDownlink\')) AS dataVolumeGPRSDownlink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json, \'$.listOfTrafficVolumes[0].dataVolumeGPRsUplink\')) as dataVolumeGPRsUplink,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.userLocationInformation.tai.tac\')) as tac,JSON_UNQUOTE(JSON_EXTRACT(cdr_json,\'$.userLocationInformation.ecgi.eutraCellId\')) as cellID\",\"timeCol\":\"timestamp\",\"timeUnit\":\"second\",\"extras\":\"\",\"filePath\":\"/usr/local/omc/backup/sgwc_cdr\"}', '0 0 0/1 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1724309047797, '');
|
||||
REPLACE INTO `sys_job` VALUES (17, 'job.backup.ue.data', 'SYSTEM', 'exportUEData', '[{\"tableName\":\"u_auth_user\",\"columns\":\"imsi,ki,algo,amf,opc\",\"extras\":\"\",\"serviceName\":\"UDMAuthUser\",\"orderBy\":\"imsi\",\"orderType\":\"desc\", \"fileType\":\"txt\",\"filePath\":\"/usr/local/omc/backup/u_auth_user\"},{\"tableName\":\"u_sub_user\",\"columns\":\"imsi,msisdn,ambr,nssai,arfb,sar,rat,cn_type,smf_sel,sm_data,eps_flag,eps_odb,hplmn_odb,ard,epstpl,context_id,apn_context,static_ip\",\"extras\":\"\",\"serviceName\":\"UDMSubUser\",\"orderBy\":\"imsi\",\"orderType\":\"desc\", \"fileType\":\"txt\",\"filePath\":\"/usr/local/omc/backup/u_sub_user\"},{\"tableName\":\"u_voip_auth\",\"columns\":\"user_name,password\",\"extras\":\"\",\"serviceName\":\"UDMVoIPAuth\",\"orderBy\":\"user_name\",\"orderType\":\"desc\", \"fileType\":\"txt\",\"filePath\":\"/usr/local/omc/backup/u_voip_auth\"},{\"tableName\":\"u_ims_user\",\"columns\":\"imsi,msisdn,volte,vni\",\"extras\":\"\",\"serviceName\":\"UDMIMSUser\",\"orderBy\":\"imsi\",\"orderType\":\"desc\", \"fileType\":\"txt\",\"filePath\":\"/usr/local/omc/backup/u_ims_user\"}]', '0 35 0 * * ?', '3', '0', '1', '1', 'supervisor', 1698478134842, 'admin', 1743479268652, '');
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -112,8 +112,8 @@ REPLACE INTO `sys_menu` VALUES (1055, 'menu.common.edit', 116, 5, '#', NULL, '1'
|
||||
REPLACE INTO `sys_menu` VALUES (1056, 'menu.common.export', 116, 6, '#', NULL, '1', '1', 'B', '1', '1', 'monitor:job:export', '#', 'supervisor', 1700000000000, NULL, 0, NULL);
|
||||
REPLACE INTO `sys_menu` VALUES (2009, 'menu.ueUser.authUDM', 5, 1, 'auth', 'neUser/auth/index', '1', '1', 'M', '1', '1', 'neUser:auth:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.authUDMRemark');
|
||||
REPLACE INTO `sys_menu` VALUES (2010, 'menu.ueUser.subUDM', 5, 2, 'sub', 'neUser/sub/index', '1', '1', 'M', '1', '1', 'neUser:sub:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.subUDMRemark');
|
||||
REPLACE INTO `sys_menu` VALUES (2011, 'menu.ueUser.imsUDM', 5, 3, 'imsUDM', 'neUser/imsUDM/index', '1', '1', 'M', '1', '1', 'neUser:imsUDM:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.imsUDMRemark');
|
||||
REPLACE INTO `sys_menu` VALUES (2012, 'menu.ueUser.voipUDM', 5, 4, 'voip', 'neUser/voip/index', '1', '1', 'M', '1', '1', 'neUser:voip:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.voipUDMRemark');
|
||||
REPLACE INTO `sys_menu` VALUES (2011, 'menu.ueUser.voipUDM', 5, 3, 'voip', 'neUser/voip/index', '1', '1', 'M', '1', '1', 'neUser:voip:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.voipUDMRemark');
|
||||
REPLACE INTO `sys_menu` VALUES (2012, 'menu.ueUser.imsUDM', 5, 4, 'imsUDM', 'neUser/imsUDM/index', '1', '1', 'M', '1', '1', 'neUser:imsUDM:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.imsUDMRemark');
|
||||
REPLACE INTO `sys_menu` VALUES (2079, 'menu.ueUser.exportFile', 5, 20, 'exportFile', 'neUser/exportFile/index', '1', '1', 'M', '1', '1', 'neUser:exportFile:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.exportFileRemark');
|
||||
-- REPLACE INTO `sys_menu` VALUES (2075, 'menu.config.neManage', 4, 1, 'neManage', 'configManage/neManage/index', '1', '0', 'M', '1', '0', 'configManage:neManage:index', 'icon-biaoqing', 'supervisor', 1700000000000, NULL, 0, 'menu.config.neManageRemark');
|
||||
-- REPLACE INTO `sys_menu` VALUES (2078, 'menu.config.backupManage', 4, 100, 'backupManage', 'configManage/backupManage/index', '1', '0', 'M', '1', '0', 'configManage:backupManage:index', 'icon-soutubiao', 'supervisor', 1700000000000, NULL, 0, 'menu.config.backupManageRemark');
|
||||
|
||||
35
database/upgrade/upg_u_ims_user.sql
Executable file
35
database/upgrade/upg_u_ims_user.sql
Executable file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : omc@192.168.2.211
|
||||
Source Server Type : MariaDB
|
||||
Source Server Version : 100621 (10.6.21-MariaDB-0ubuntu0.22.04.2)
|
||||
Source Host : 192.168.2.211:33066
|
||||
Source Schema : tenants_db
|
||||
|
||||
Target Server Type : MariaDB
|
||||
Target Server Version : 100621 (10.6.21-MariaDB-0ubuntu0.22.04.2)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 09/04/2025 09:22:00
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for u_ims_user
|
||||
-- ----------------------------
|
||||
CREATE TABLE IF NOT EXISTS `u_ims_user` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ne_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`imsi` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'SIM/USIMID',
|
||||
`msisdn` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
|
||||
`volte` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
|
||||
`vni` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
|
||||
`tenant_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'multi-tenancy refer to sys_tenant.tenant_id',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uk_imsi_ne`(`imsi`, `ne_id`) USING BTREE COMMENT 'imsi_neid'
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'UDM' ROW_FORMAT = Dynamic;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
33
database/upgrade/upg_u_voip_auth.sql
Executable file
33
database/upgrade/upg_u_voip_auth.sql
Executable file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : omc@192.168.2.211
|
||||
Source Server Type : MariaDB
|
||||
Source Server Version : 100621 (10.6.21-MariaDB-0ubuntu0.22.04.2)
|
||||
Source Host : 192.168.2.211:33066
|
||||
Source Schema : tenants_db
|
||||
|
||||
Target Server Type : MariaDB
|
||||
Target Server Version : 100621 (10.6.21-MariaDB-0ubuntu0.22.04.2)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 09/04/2025 09:26:56
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for u_voip_auth
|
||||
-- ----------------------------
|
||||
CREATE TABLE IF NOT EXISTS `u_voip_auth` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ne_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
|
||||
`tenant_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'multi-tenancy refer to sys_tenant.tenant_id',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_user_name`(`user_name`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 19570 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'UDM' ROW_FORMAT = Dynamic;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
25
features/ue/api.go
Normal file
25
features/ue/api.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// log management package
|
||||
|
||||
package ue
|
||||
|
||||
import (
|
||||
// "be.ems/features/ue/file_export"
|
||||
// "be.ems/features/ue/ims_user"
|
||||
"be.ems/features/ue/api"
|
||||
"be.ems/lib/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitSubServiceRoute(r *gin.Engine) {
|
||||
log.Info("======init UE management group gin.Engine")
|
||||
|
||||
ueGroup := r.Group("/ue")
|
||||
// register sub modules routes
|
||||
// file_export.Register(ueGroup)
|
||||
// ims_user.Register(ueGroup)
|
||||
api.UDMIMSUserRegister(ueGroup)
|
||||
api.FileExportRegister(ueGroup)
|
||||
api.VoIPAuthRegister(ueGroup)
|
||||
// register other sub modules routes
|
||||
}
|
||||
|
||||
40
features/ue/api/file_export.go
Normal file
40
features/ue/api/file_export.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/middleware"
|
||||
"be.ems/features/ue/controller"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Register Routes for file_export
|
||||
func FileExportRegister(r *gin.RouterGroup) {
|
||||
|
||||
ueTable := r.Group("/table")
|
||||
{
|
||||
var m *controller.FileSource
|
||||
ueTable.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
m.GetFileExportTable,
|
||||
)
|
||||
}
|
||||
ueFile := r.Group("/file")
|
||||
{
|
||||
var f *controller.FileExport
|
||||
ueFile.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.GetFileList,
|
||||
)
|
||||
ueFile.GET("/total",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.Total,
|
||||
)
|
||||
ueFile.GET("/:fileName",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.DownloadHandler,
|
||||
)
|
||||
ueFile.DELETE("/:fileName",
|
||||
middleware.PreAuthorize(nil),
|
||||
f.Delete,
|
||||
)
|
||||
}
|
||||
}
|
||||
68
features/ue/api/ims_user.go
Normal file
68
features/ue/api/ims_user.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/middleware"
|
||||
"be.ems/src/framework/middleware/collectlogs"
|
||||
"be.ems/src/framework/middleware/repeat"
|
||||
"be.ems/features/ue/controller"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Description Register Routes for ims_user
|
||||
func UDMIMSUserRegister(r *gin.RouterGroup) {
|
||||
|
||||
udmIMSUserGroup := r.Group("/udm/imsuser")
|
||||
{
|
||||
udmIMSUserGroup.PUT("/resetData/:neId",
|
||||
repeat.RepeatSubmit(5),
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmIMSUser", collectlogs.BUSINESS_TYPE_CLEAN)),
|
||||
controller.NewIMSUserController.ResetData,
|
||||
)
|
||||
udmIMSUserGroup.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewIMSUserController.List,
|
||||
)
|
||||
udmIMSUserGroup.GET("/:neId/:imsi",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewIMSUserController.Info,
|
||||
)
|
||||
udmIMSUserGroup.POST("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmIMSUser", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
controller.NewIMSUserController.Add,
|
||||
)
|
||||
udmIMSUserGroup.POST("/:neId/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmIMSUser", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
controller.NewIMSUserController.Adds,
|
||||
)
|
||||
udmIMSUserGroup.PUT("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmIMSUser", collectlogs.BUSINESS_TYPE_UPDATE)),
|
||||
controller.NewIMSUserController.Edit,
|
||||
)
|
||||
udmIMSUserGroup.DELETE("/:neId/:imsi",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmIMSUser", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewIMSUserController.Remove,
|
||||
)
|
||||
udmIMSUserGroup.DELETE("/:neId/:imsi/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmIMSUser", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewIMSUserController.Removes,
|
||||
)
|
||||
udmIMSUserGroup.POST("/export",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmIMSUser", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewIMSUserController.Export,
|
||||
)
|
||||
udmIMSUserGroup.POST("/import",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmIMSUser", collectlogs.BUSINESS_TYPE_IMPORT)),
|
||||
controller.NewIMSUserController.Import,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
68
features/ue/api/voip_auth.go
Normal file
68
features/ue/api/voip_auth.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/middleware"
|
||||
"be.ems/src/framework/middleware/collectlogs"
|
||||
"be.ems/src/framework/middleware/repeat"
|
||||
"be.ems/features/ue/controller"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Description Register Routes for ims_user
|
||||
func VoIPAuthRegister(r *gin.RouterGroup) {
|
||||
|
||||
voipAuthGroup := r.Group("/udm/voipauth")
|
||||
{
|
||||
voipAuthGroup.PUT("/resetData/:neId",
|
||||
repeat.RepeatSubmit(5),
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.voipAuth", collectlogs.BUSINESS_TYPE_CLEAN)),
|
||||
controller.NewVoIPAuthController.ResetData,
|
||||
)
|
||||
voipAuthGroup.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewVoIPAuthController.List,
|
||||
)
|
||||
voipAuthGroup.GET("/:neId/:userName",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewVoIPAuthController.Info,
|
||||
)
|
||||
voipAuthGroup.POST("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.voipAuth", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
controller.NewVoIPAuthController.Add,
|
||||
)
|
||||
voipAuthGroup.POST("/:neId/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.voipAuth", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
controller.NewVoIPAuthController.Adds,
|
||||
)
|
||||
voipAuthGroup.PUT("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.voipAuth", collectlogs.BUSINESS_TYPE_UPDATE)),
|
||||
controller.NewVoIPAuthController.Edit,
|
||||
)
|
||||
voipAuthGroup.DELETE("/:neId/:userName",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.voipAuth", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewVoIPAuthController.Remove,
|
||||
)
|
||||
voipAuthGroup.DELETE("/:neId/:userName/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.voipAuth", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewVoIPAuthController.Removes,
|
||||
)
|
||||
voipAuthGroup.POST("/export",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.voipAuth", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewVoIPAuthController.Export,
|
||||
)
|
||||
voipAuthGroup.POST("/import",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.voipAuth", collectlogs.BUSINESS_TYPE_IMPORT)),
|
||||
controller.NewVoIPAuthController.Import,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
95
features/ue/controller/file_export.go
Normal file
95
features/ue/controller/file_export.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"be.ems/lib/file"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/features/ue/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type FileExport struct {
|
||||
file.FileInfo
|
||||
}
|
||||
|
||||
func (m *FileExport) GetFileList(c *gin.Context) {
|
||||
var querys model.FileExportQuery
|
||||
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
files, err := file.GetFileInfo(querys.Path, querys.Suffix)
|
||||
if err != nil {
|
||||
log.Error("failed to GetFileInfo:", err)
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// split files list
|
||||
lenNum := int64(len(files))
|
||||
start := (querys.PageNum - 1) * querys.PageSize
|
||||
end := start + querys.PageSize
|
||||
var splitList []file.FileInfo
|
||||
if start >= lenNum {
|
||||
splitList = []file.FileInfo{}
|
||||
} else if end >= lenNum {
|
||||
splitList = files[start:]
|
||||
} else {
|
||||
splitList = files[start:end]
|
||||
}
|
||||
total := len(files)
|
||||
c.JSON(http.StatusOK, services.TotalDataResp(splitList, total))
|
||||
}
|
||||
|
||||
func (m *FileExport) Total(c *gin.Context) {
|
||||
dir := c.Query("path")
|
||||
|
||||
fileCount, dirCount, err := file.GetFileAndDirCount(dir)
|
||||
if err != nil {
|
||||
log.Error("failed to GetFileAndDirCount:", err)
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
total := fileCount + dirCount
|
||||
c.JSON(http.StatusOK, services.TotalResp(int64(total)))
|
||||
}
|
||||
|
||||
func (m *FileExport) DownloadHandler(c *gin.Context) {
|
||||
dir := c.Query("path")
|
||||
fileName := c.Param("fileName")
|
||||
filePath := filepath.Join(dir, fileName)
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Disposition", "attachment; filename="+fileName)
|
||||
c.Header("Content-Type", "application/octet-stream")
|
||||
c.File(filePath)
|
||||
}
|
||||
|
||||
func (m *FileExport) Delete(c *gin.Context) {
|
||||
fileName := c.Param("fileName")
|
||||
dir := c.Query("path")
|
||||
filePath := filepath.Join(dir, fileName)
|
||||
|
||||
if err := os.Remove(filePath); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusNoContent, nil) // 204 No Content
|
||||
}
|
||||
57
features/ue/controller/file_source.go
Normal file
57
features/ue/controller/file_source.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"be.ems/lib/services"
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/modules/crontask/processor/exportUEData"
|
||||
"be.ems/features/ue/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type FileSource struct {
|
||||
SysJob model.SysJob
|
||||
TableName string `json:"tableName"`
|
||||
TableDisplay string `json:"tableDisplay"`
|
||||
FilePath string `json:"filePath"`
|
||||
}
|
||||
|
||||
// GetFileExportTable 获取文件导出任务列表
|
||||
func (m *FileSource) GetFileExportTable(c *gin.Context) {
|
||||
var results []model.SysJob
|
||||
|
||||
err := datasource.DefaultDB().Table(m.SysJob.TableName()).
|
||||
Where("invoke_target=? and status=1", model.INVOKE_FILE_EXPORT).
|
||||
Find(&results).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var response []FileSource
|
||||
for _, job := range results {
|
||||
params := make([]exportUEData.BarParams, 0)
|
||||
if err := json.Unmarshal([]byte(job.TargetParams), ¶ms); err != nil {
|
||||
c.JSON(http.StatusOK, services.ErrResp(err.Error()))
|
||||
return
|
||||
}
|
||||
for _, param := range params {
|
||||
TableDisplay := i18n.TKey(language, "table."+param.TableName)
|
||||
if TableDisplay == "" {
|
||||
TableDisplay = param.TableName
|
||||
}
|
||||
response = append(response, FileSource{
|
||||
SysJob: job,
|
||||
TableName: param.TableName,
|
||||
TableDisplay: TableDisplay,
|
||||
FilePath: param.FilePath,
|
||||
})
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, services.DataResp(response))
|
||||
}
|
||||
|
||||
488
features/ue/controller/ims_user.go
Normal file
488
features/ue/controller/ims_user.go
Normal file
@@ -0,0 +1,488 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/constants/uploadsubpath"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/telnet"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/vo/result"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"be.ems/features/ue/service"
|
||||
"be.ems/features/ue/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
)
|
||||
|
||||
// 实例化控制层 IMSUserController 结构体
|
||||
var NewIMSUserController = &IMSUserController{
|
||||
imsUserService: service.NewIMSUserService,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
}
|
||||
|
||||
// IMS用户信息 控制层处理
|
||||
//
|
||||
// @Description IMS用户信息 控制层处理
|
||||
type IMSUserController struct {
|
||||
imsUserService *service.IMSUserService // IMS User信息服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
}
|
||||
|
||||
func (s *IMSUserController) ResetData(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
data := s.imsUserService.ResetData(neId)
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
|
||||
func (s *IMSUserController) List(c *gin.Context) {
|
||||
querys := ctx.QueryMap(c)
|
||||
// querys["userName"] = ctx.LoginUserToUserName(c)
|
||||
// 判断租户角色
|
||||
loginUser, _ := ctx.LoginUser(c)
|
||||
if len(loginUser.User.Roles) > 0 {
|
||||
for _, v := range loginUser.User.Roles {
|
||||
if v.RoleKey == "tenant" {
|
||||
querys["tenantName"] = loginUser.User.UserName
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
data := s.imsUserService.SelectPage(querys)
|
||||
c.JSON(200, result.Ok(data))
|
||||
}
|
||||
|
||||
func (s *IMSUserController) Info(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
imsi := c.Param("imsi")
|
||||
if neId == "" || imsi == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("dsp imsuser:imsi=%s", imsi)
|
||||
data, err := telnet.ConvertToMap(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if len(data) == 0 {
|
||||
c.JSON(200, result.ErrMsg("Not found IMS User data"))
|
||||
return
|
||||
}
|
||||
|
||||
// 解析返回的数据
|
||||
u := s.imsUserService.ParseInfo(imsi, neId, data)
|
||||
s.imsUserService.Insert(neId, u)
|
||||
c.JSON(200, result.OkData(u))
|
||||
}
|
||||
|
||||
func (s *IMSUserController) Add(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
var body model.IMSUser
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || len(body.IMSI) < model.IMSI_MAX_LENGTH {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("add imsuser:imsi=%s,", body.IMSI)
|
||||
cmd += s.imsUserService.ParseCommandParams(body)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
body.NeId = neId
|
||||
s.imsUserService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *IMSUserController) Adds(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
num := c.Param("num")
|
||||
if neId == "" || num == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
var body model.IMSUser
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || len(body.IMSI) < model.IMSI_MAX_LENGTH {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("baa imsuser:start_imsi=%s,start_msisdn=%s,sub_num=%s,", body.IMSI, body.MSISDN, num)
|
||||
cmd += s.imsUserService.ParseCommandParams(body)
|
||||
// 去除msisdn参数,避免重复
|
||||
omemsisdn := fmt.Sprintf(",msisdn=%s,", body.MSISDN)
|
||||
cmd = strings.Replace(cmd, omemsisdn, ",", 1)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *IMSUserController) Edit(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
var body model.IMSUser
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || len(body.IMSI) < model.IMSI_MAX_LENGTH {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("mod imsuser:imsi=%s,", body.IMSI)
|
||||
cmd += s.imsUserService.ParseCommandParams(body)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
body.NeId = neId
|
||||
s.imsUserService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *IMSUserController) Remove(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
imsi := c.Param("imsi")
|
||||
if neId == "" || len(imsi) < model.IMSI_MAX_LENGTH {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 处理字符转id数组后去重
|
||||
imsiArr := strings.Split(imsi, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(imsiArr)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
c.JSON(200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
resultData := map[string]string{}
|
||||
for _, imsi := range uniqueIDs {
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("del imsuser:imsi=%s", imsi)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
resultData[imsi] = err.Error()
|
||||
continue
|
||||
}
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
s.imsUserService.Delete(neId, imsi)
|
||||
}
|
||||
resultData[imsi] = data
|
||||
}
|
||||
|
||||
c.JSON(200, result.OkData(resultData))
|
||||
}
|
||||
|
||||
func (s *IMSUserController) Removes(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
imsi := c.Param("imsi")
|
||||
num := c.Param("num")
|
||||
if neId == "" || len(imsi) < model.IMSI_MAX_LENGTH || num == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("bde imsuser:start_imsi=%s,sub_num=%s", imsi, num)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
s.imsUserService.LoadData(neId, imsi, num)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *IMSUserController) Export(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
querys := ctx.BodyJSONMap(c)
|
||||
neId := querys["neId"].(string)
|
||||
fileType := querys["type"].(string)
|
||||
if neId == "" || fileType == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
if !(fileType == "csv" || fileType == "txt") {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断租户角色
|
||||
loginUser, _ := ctx.LoginUser(c)
|
||||
if len(loginUser.User.Roles) > 0 {
|
||||
for _, v := range loginUser.User.Roles {
|
||||
if v.RoleKey == "tenant" {
|
||||
querys["tenantName"] = loginUser.User.UserName
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
querys["pageNum"] = 1
|
||||
querys["pageSize"] = 10000
|
||||
data := s.imsUserService.SelectPage(querys)
|
||||
if parse.Number(data["total"]) == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
rows := data["rows"].([]model.IMSUser)
|
||||
|
||||
// rows := s.imsUserService.SelectList(model.IMSUser{NeId: neId})
|
||||
if len(rows) <= 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
|
||||
// 文件名
|
||||
fileName := fmt.Sprintf("udm_volte_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), fileType)
|
||||
filePath := filepath.Join(file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
|
||||
|
||||
if fileType == "csv" {
|
||||
// 转换数据
|
||||
data := [][]string{}
|
||||
data = append(data, []string{"IMSI", "MSISDN", "VoLTE", "VNI"})
|
||||
for _, v := range rows {
|
||||
data = append(data, []string{v.IMSI, v.MSISDN, v.VoLTE, v.VNI})
|
||||
}
|
||||
// 输出到文件
|
||||
if err := file.WriterFileCSV(data, filePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if fileType == "txt" {
|
||||
// 转换数据
|
||||
data := [][]string{}
|
||||
for _, v := range rows {
|
||||
data = append(data, []string{v.IMSI, v.MSISDN, v.VoLTE, v.VNI})
|
||||
}
|
||||
// 输出到文件
|
||||
if err := file.WriterFileTXT(data, ",", filePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.FileAttachment(filePath, fileName)
|
||||
}
|
||||
|
||||
func (s *IMSUserController) Import(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var body struct {
|
||||
NeId string `json:"neId" binding:"required"`
|
||||
UploadPath string `json:"uploadPath" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断文件名
|
||||
if !(strings.HasSuffix(body.UploadPath, ".csv") || strings.HasSuffix(body.UploadPath, ".txt")) {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", body.NeId)
|
||||
if neInfo.NeId != body.NeId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元主机的SSH客户端
|
||||
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sshClient.Close()
|
||||
// 网元主机的SSH客户端进行文件传输
|
||||
sftpClient, err := sshClient.NewClientSFTP()
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sftpClient.Close()
|
||||
|
||||
// 本地文件
|
||||
localFilePath := file.ParseUploadFilePath(body.UploadPath)
|
||||
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
|
||||
// 复制到远程
|
||||
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg("error uploading file"))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("import imsuser:path=%s", neFilePath)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
if strings.HasSuffix(body.UploadPath, ".csv") {
|
||||
data := file.ReadFileCSV(localFilePath)
|
||||
go s.imsUserService.InsertData(neInfo.NeId, "csv", data)
|
||||
}
|
||||
if strings.HasSuffix(body.UploadPath, ".txt") {
|
||||
data := file.ReadFileTXT(",", localFilePath)
|
||||
go s.imsUserService.InsertData(neInfo.NeId, "txt", data)
|
||||
}
|
||||
}
|
||||
c.JSON(200, result.OkMsg(data))
|
||||
}
|
||||
486
features/ue/controller/voip_auth.go
Normal file
486
features/ue/controller/voip_auth.go
Normal file
@@ -0,0 +1,486 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/constants/uploadsubpath"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/telnet"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/vo/result"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"be.ems/features/ue/service"
|
||||
"be.ems/features/ue/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
)
|
||||
|
||||
// 实例化控制层 VoIPAuthController 结构体
|
||||
var NewVoIPAuthController = &VoIPAuthController{
|
||||
voipAuthService: service.NewVoIPAuthService,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
}
|
||||
|
||||
// IMS用户信息 控制层处理
|
||||
//
|
||||
// @Description IMS用户信息 控制层处理
|
||||
type VoIPAuthController struct {
|
||||
voipAuthService *service.VoIPAuthService // VoIP Auth信息服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
}
|
||||
|
||||
func (s *VoIPAuthController) ResetData(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
data := s.voipAuthService.ResetData(neId)
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
|
||||
func (s *VoIPAuthController) List(c *gin.Context) {
|
||||
querys := ctx.QueryMap(c)
|
||||
// querys["userName"] = ctx.LoginUserToUserName(c)
|
||||
// 判断租户角色
|
||||
loginUser, _ := ctx.LoginUser(c)
|
||||
if len(loginUser.User.Roles) > 0 {
|
||||
for _, v := range loginUser.User.Roles {
|
||||
if v.RoleKey == "tenant" {
|
||||
querys["tenantName"] = loginUser.User.UserName
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
data := s.voipAuthService.SelectPage(querys)
|
||||
c.JSON(200, result.Ok(data))
|
||||
}
|
||||
|
||||
func (s *VoIPAuthController) Info(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
userName := c.Param("userName")
|
||||
if neId == "" || userName == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("dsp voip:username=%s", userName)
|
||||
data, err := telnet.ConvertToMap(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if len(data) == 0 {
|
||||
c.JSON(200, result.ErrMsg("Not found VoIP Auth data"))
|
||||
return
|
||||
}
|
||||
|
||||
// 解析返回的数据
|
||||
u := s.voipAuthService.ParseInfo(userName, neId, data)
|
||||
s.voipAuthService.Insert(neId, u)
|
||||
c.JSON(200, result.OkData(u))
|
||||
}
|
||||
|
||||
func (s *VoIPAuthController) Add(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
var body model.VoIPAuth
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("add voip:username=%s,", body.UserName)
|
||||
cmd += s.voipAuthService.ParseCommandParams(body)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
body.NeId = neId
|
||||
s.voipAuthService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *VoIPAuthController) Adds(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
num := c.Param("num")
|
||||
if neId == "" || num == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
var body model.VoIPAuth
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("baa voip:start_username=%s,password=%s,sub_num=%s,",
|
||||
body.UserName, body.Password, num)
|
||||
cmd += s.voipAuthService.ParseCommandParams(body)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *VoIPAuthController) Edit(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
var body model.VoIPAuth
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("mod voip:username=%s,", body.UserName)
|
||||
cmd += s.voipAuthService.ParseCommandParams(body)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
body.NeId = neId
|
||||
s.voipAuthService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *VoIPAuthController) Remove(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
userName := c.Param("userName")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 处理字符转id数组后去重
|
||||
userNameArr := strings.Split(userName, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(userNameArr)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
c.JSON(200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
resultData := map[string]string{}
|
||||
for _, userName := range uniqueIDs {
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("del voip:username=%s", userName)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
resultData[userName] = err.Error()
|
||||
continue
|
||||
}
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
s.voipAuthService.Delete(neId, userName)
|
||||
}
|
||||
resultData[userName] = data
|
||||
}
|
||||
|
||||
c.JSON(200, result.OkData(resultData))
|
||||
}
|
||||
|
||||
func (s *VoIPAuthController) Removes(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
userName := c.Param("userName")
|
||||
num := c.Param("num")
|
||||
if neId == "" || num == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("bde voip:start_username=%s,sub_num=%s", userName, num)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
s.voipAuthService.LoadData(neId, userName, num)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *VoIPAuthController) Export(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
querys := ctx.BodyJSONMap(c)
|
||||
neId := querys["neId"].(string)
|
||||
fileType := querys["type"].(string)
|
||||
if neId == "" || fileType == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
if !(fileType == "csv" || fileType == "txt") {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断租户角色
|
||||
loginUser, _ := ctx.LoginUser(c)
|
||||
if len(loginUser.User.Roles) > 0 {
|
||||
for _, v := range loginUser.User.Roles {
|
||||
if v.RoleKey == "tenant" {
|
||||
querys["tenantName"] = loginUser.User.UserName
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
querys["pageNum"] = 1
|
||||
querys["pageSize"] = 10000
|
||||
data := s.voipAuthService.SelectPage(querys)
|
||||
if parse.Number(data["total"]) == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
rows := data["rows"].([]model.VoIPAuth)
|
||||
|
||||
// rows := s.voipAuthService.SelectList(model.VoIPAuth{NeId: neId})
|
||||
if len(rows) <= 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
|
||||
// 文件名
|
||||
fileName := fmt.Sprintf("u_voip_auth_export_%s_%d.%s", neId, time.Now().UnixMilli(), fileType)
|
||||
filePath := filepath.Join(file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
|
||||
|
||||
if fileType == "csv" {
|
||||
// 转换数据
|
||||
data := [][]string{}
|
||||
data = append(data, []string{"UserName", "Password"})
|
||||
for _, v := range rows {
|
||||
data = append(data, []string{v.UserName, v.Password})
|
||||
}
|
||||
// 输出到文件
|
||||
if err := file.WriterFileCSV(data, filePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if fileType == "txt" {
|
||||
// 转换数据
|
||||
data := [][]string{}
|
||||
for _, v := range rows {
|
||||
data = append(data, []string{v.UserName, v.Password})
|
||||
}
|
||||
// 输出到文件
|
||||
if err := file.WriterFileTXT(data, ",", filePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.FileAttachment(filePath, fileName)
|
||||
}
|
||||
|
||||
func (s *VoIPAuthController) Import(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var body struct {
|
||||
NeId string `json:"neId" binding:"required"`
|
||||
UploadPath string `json:"uploadPath" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断文件名
|
||||
if !(strings.HasSuffix(body.UploadPath, ".csv") || strings.HasSuffix(body.UploadPath, ".txt")) {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", body.NeId)
|
||||
if neInfo.NeId != body.NeId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元主机的SSH客户端
|
||||
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sshClient.Close()
|
||||
// 网元主机的SSH客户端进行文件传输
|
||||
sftpClient, err := sshClient.NewClientSFTP()
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sftpClient.Close()
|
||||
|
||||
// 本地文件
|
||||
localFilePath := file.ParseUploadFilePath(body.UploadPath)
|
||||
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
|
||||
// 复制到远程
|
||||
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg("error uploading file"))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("import voip:path=%s", neFilePath)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
if strings.HasSuffix(body.UploadPath, ".csv") {
|
||||
data := file.ReadFileCSV(localFilePath)
|
||||
go s.voipAuthService.InsertData(neInfo.NeId, "csv", data)
|
||||
}
|
||||
if strings.HasSuffix(body.UploadPath, ".txt") {
|
||||
data := file.ReadFileTXT(",", localFilePath)
|
||||
go s.voipAuthService.InsertData(neInfo.NeId, "txt", data)
|
||||
}
|
||||
}
|
||||
c.JSON(200, result.OkMsg(data))
|
||||
}
|
||||
486
features/ue/ims_user/controller.go
Normal file
486
features/ue/ims_user/controller.go
Normal file
@@ -0,0 +1,486 @@
|
||||
package ims_user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/constants/uploadsubpath"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/telnet"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/vo/result"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
)
|
||||
|
||||
// 实例化控制层 Controller 结构体
|
||||
var NewController = &Controller{
|
||||
volteUserService: NewVoLTEService,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
}
|
||||
|
||||
// IMS用户信息 控制层处理
|
||||
//
|
||||
// @Description IMS用户信息 控制层处理
|
||||
type Controller struct {
|
||||
volteUserService *Service // IMS User信息服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
}
|
||||
|
||||
func (s *Controller) ResetData(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
data := s.volteUserService.ResetData(neId)
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
|
||||
func (s *Controller) List(c *gin.Context) {
|
||||
querys := ctx.QueryMap(c)
|
||||
// querys["userName"] = ctx.LoginUserToUserName(c)
|
||||
// 判断租户角色
|
||||
loginUser, _ := ctx.LoginUser(c)
|
||||
if len(loginUser.User.Roles) > 0 {
|
||||
for _, v := range loginUser.User.Roles {
|
||||
if v.RoleKey == "tenant" {
|
||||
querys["tenantName"] = loginUser.User.UserName
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
data := s.volteUserService.SelectPage(querys)
|
||||
c.JSON(200, result.Ok(data))
|
||||
}
|
||||
|
||||
func (s *Controller) Info(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
imsi := c.Param("imsi")
|
||||
if neId == "" || imsi == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("dsp imsuser:imsi=%s", imsi)
|
||||
data, err := telnet.ConvertToMap(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if len(data) == 0 {
|
||||
c.JSON(200, result.ErrMsg("Not found VoLTE user data"))
|
||||
return
|
||||
}
|
||||
|
||||
// 解析返回的数据
|
||||
u := s.volteUserService.ParseInfo(imsi, neId, data)
|
||||
s.volteUserService.Insert(neId, u)
|
||||
c.JSON(200, result.OkData(u))
|
||||
}
|
||||
|
||||
func (s *Controller) Add(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
var body VoLTEUser
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || len(body.IMSI) < IMSI_MAX_LENGTH {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("add imsuser:imsi=%s,", body.IMSI)
|
||||
cmd += s.volteUserService.ParseCommandParams(body)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
body.NeId = neId
|
||||
s.volteUserService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *Controller) Adds(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
num := c.Param("num")
|
||||
if neId == "" || num == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
var body VoLTEUser
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || len(body.IMSI) < IMSI_MAX_LENGTH {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("baa imsuser:start_imsi=%s,start_msisdn=%s,sub_num=%s,", body.IMSI, body.MSISDN, num)
|
||||
cmd += s.volteUserService.ParseCommandParams(body)
|
||||
// 去除msisdn参数,避免重复
|
||||
omemsisdn := fmt.Sprintf(",msisdn=%s,", body.MSISDN)
|
||||
cmd = strings.Replace(cmd, omemsisdn, ",", 1)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *Controller) Edit(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
var body VoLTEUser
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || len(body.IMSI) < IMSI_MAX_LENGTH {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("mod imsuser:imsi=%s,", body.IMSI)
|
||||
cmd += s.volteUserService.ParseCommandParams(body)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
body.NeId = neId
|
||||
s.volteUserService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *Controller) Remove(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
imsi := c.Param("imsi")
|
||||
if neId == "" || len(imsi) < IMSI_MAX_LENGTH {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 处理字符转id数组后去重
|
||||
imsiArr := strings.Split(imsi, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(imsiArr)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
c.JSON(200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
resultData := map[string]string{}
|
||||
for _, imsi := range uniqueIDs {
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("del imsuser:imsi=%s", imsi)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
resultData[imsi] = err.Error()
|
||||
continue
|
||||
}
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
s.volteUserService.Delete(neId, imsi)
|
||||
}
|
||||
resultData[imsi] = data
|
||||
}
|
||||
|
||||
c.JSON(200, result.OkData(resultData))
|
||||
}
|
||||
|
||||
func (s *Controller) Removes(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.Param("neId")
|
||||
imsi := c.Param("imsi")
|
||||
num := c.Param("num")
|
||||
if neId == "" || len(imsi) < IMSI_MAX_LENGTH || num == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("bde imsuser:start_imsi=%s,sub_num=%s", imsi, num)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
s.volteUserService.LoadData(neId, imsi, num)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
func (s *Controller) Export(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
querys := ctx.BodyJSONMap(c)
|
||||
neId := querys["neId"].(string)
|
||||
fileType := querys["type"].(string)
|
||||
if neId == "" || fileType == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
if !(fileType == "csv" || fileType == "txt") {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断租户角色
|
||||
loginUser, _ := ctx.LoginUser(c)
|
||||
if len(loginUser.User.Roles) > 0 {
|
||||
for _, v := range loginUser.User.Roles {
|
||||
if v.RoleKey == "tenant" {
|
||||
querys["tenantName"] = loginUser.User.UserName
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
querys["pageNum"] = 1
|
||||
querys["pageSize"] = 10000
|
||||
data := s.volteUserService.SelectPage(querys)
|
||||
if parse.Number(data["total"]) == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
rows := data["rows"].([]VoLTEUser)
|
||||
|
||||
// rows := s.volteUserService.SelectList(VoLTEUser{NeId: neId})
|
||||
if len(rows) <= 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
|
||||
// 文件名
|
||||
fileName := fmt.Sprintf("udm_volte_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), fileType)
|
||||
filePath := filepath.Join(file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
|
||||
|
||||
if fileType == "csv" {
|
||||
// 转换数据
|
||||
data := [][]string{}
|
||||
data = append(data, []string{"IMSI", "MSISDN", "VoLTE", "VNI"})
|
||||
for _, v := range rows {
|
||||
data = append(data, []string{v.IMSI, v.MSISDN, v.VoLTE, v.VNI})
|
||||
}
|
||||
// 输出到文件
|
||||
if err := file.WriterFileCSV(data, filePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if fileType == "txt" {
|
||||
// 转换数据
|
||||
data := [][]string{}
|
||||
for _, v := range rows {
|
||||
data = append(data, []string{v.IMSI, v.MSISDN, v.VoLTE, v.VNI})
|
||||
}
|
||||
// 输出到文件
|
||||
if err := file.WriterFileTXT(data, ",", filePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.FileAttachment(filePath, fileName)
|
||||
}
|
||||
|
||||
func (s *Controller) Import(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var body struct {
|
||||
NeId string `json:"neId" binding:"required"`
|
||||
UploadPath string `json:"uploadPath" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 判断文件名
|
||||
if !(strings.HasSuffix(body.UploadPath, ".csv") || strings.HasSuffix(body.UploadPath, ".txt")) {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", body.NeId)
|
||||
if neInfo.NeId != body.NeId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元主机的SSH客户端
|
||||
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sshClient.Close()
|
||||
// 网元主机的SSH客户端进行文件传输
|
||||
sftpClient, err := sshClient.NewClientSFTP()
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sftpClient.Close()
|
||||
|
||||
// 本地文件
|
||||
localFilePath := file.ParseUploadFilePath(body.UploadPath)
|
||||
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
|
||||
// 复制到远程
|
||||
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg("error uploading file"))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
cmd := fmt.Sprintf("import imsuser:path=%s", neFilePath)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
if strings.HasSuffix(body.UploadPath, ".csv") {
|
||||
data := file.ReadFileCSV(localFilePath)
|
||||
go s.volteUserService.InsertData(neInfo.NeId, "csv", data)
|
||||
}
|
||||
if strings.HasSuffix(body.UploadPath, ".txt") {
|
||||
data := file.ReadFileTXT(",", localFilePath)
|
||||
go s.volteUserService.InsertData(neInfo.NeId, "txt", data)
|
||||
}
|
||||
}
|
||||
c.JSON(200, result.OkMsg(data))
|
||||
}
|
||||
26
features/ue/ims_user/model.go
Normal file
26
features/ue/ims_user/model.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package ims_user
|
||||
|
||||
const (
|
||||
// IMSI 号码长度
|
||||
IMSI_MAX_LENGTH = 15
|
||||
// MSISDN 号码长度
|
||||
MSISDN_MAX_LENGTH = 15
|
||||
)
|
||||
|
||||
// @Description VoLTE用户信息
|
||||
type VoLTEUser struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
|
||||
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识
|
||||
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
|
||||
MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户电话号码
|
||||
VoLTE string `json:"volte" gorm:"column:volte"` // VoLTE
|
||||
VNI string `json:"vni" gorm:"column:vni"` // VNI
|
||||
|
||||
TenantID string `json:"tenantID" gorm:"column:tenant_id"`
|
||||
TenantName string `json:"tenantName" gorm:"-"`
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*VoLTEUser) TableName() string {
|
||||
return "u_ims_user"
|
||||
}
|
||||
272
features/ue/ims_user/repository.go
Normal file
272
features/ue/ims_user/repository.go
Normal file
@@ -0,0 +1,272 @@
|
||||
package ims_user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
dborm "be.ems/lib/core/datasource"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
)
|
||||
|
||||
// 实例化数据层 Repository 结构体
|
||||
var NewVoLTERepository = &Repository{
|
||||
selectSql: `select
|
||||
s.id, s.ne_id, s.imsi, s.msisdn, s.volte, s.vni,
|
||||
t.tenant_id, t.tenant_name
|
||||
from u_ims_user s
|
||||
left join sys_tenant t on t.tenant_id = s.tenant_id and t.status = 1`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"ne_id": "NeId",
|
||||
"imsi": "IMSI",
|
||||
"msisdn": "MSISDN",
|
||||
"volte": "VoLTE",
|
||||
"vni": "VNI",
|
||||
|
||||
"tenant_id": "TenantID",
|
||||
"tenant_name": "TenantName", // Tenant name for multi-tenancy
|
||||
},
|
||||
}
|
||||
|
||||
// Repository UDM签约信息表 数据层处理
|
||||
type Repository struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *Repository) convertResultRows(rows []map[string]any) []VoLTEUser {
|
||||
arr := make([]VoLTEUser, 0)
|
||||
for _, row := range rows {
|
||||
item := VoLTEUser{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
repo.SetFieldValue(&item, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, item)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// ClearAndInsert 清空ne_id后新增实体
|
||||
func (r *Repository) ClearAndInsert(neId string, u []VoLTEUser) int64 {
|
||||
// 不指定neID时,用 TRUNCATE 清空表快
|
||||
// _, err := datasource.ExecDB("", "TRUNCATE TABLE u_ims_user", nil)
|
||||
_, err := datasource.ExecDB("", "DELETE FROM u_ims_user WHERE ne_id = ?", []any{neId})
|
||||
if err != nil {
|
||||
logger.Errorf("TRUNCATE err => %v", err)
|
||||
}
|
||||
|
||||
return r.Inserts(u)
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询字典类型
|
||||
func (r *Repository) 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, strings.Trim(v.(string), " "))
|
||||
}
|
||||
if v, ok := query["msisdn"]; ok && v != "" {
|
||||
conditions = append(conditions, "msisdn like concat(concat('%', ?), '%')")
|
||||
params = append(params, strings.Trim(v.(string), " "))
|
||||
}
|
||||
if v, ok := query["imsis"]; ok && v != "" {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(v.([]any)))
|
||||
conditions = append(conditions, fmt.Sprintf("imsi in (%s)", placeholder))
|
||||
for _, v := range v.([]any) {
|
||||
params = append(params, v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
// for multi-tenancy solution
|
||||
if v, ok := query["tenantName"]; ok && v != "" {
|
||||
var tenantID []string
|
||||
err := dborm.DefaultDB().Table("sys_tenant").
|
||||
Where("tenant_name=? and status=1", v).Cols("tenant_id").Distinct().Find(&tenantID)
|
||||
if err != nil {
|
||||
log.Errorf("Find tenant_id from sys_user err => %v", err)
|
||||
}
|
||||
log.Tracef("userName=%v, tenantID=%v", v, tenantID)
|
||||
if len(tenantID) > 0 {
|
||||
conditions = append(conditions, "s.tenant_id = ?")
|
||||
params = append(params, tenantID[0])
|
||||
}
|
||||
} else if v, ok := query["userName"]; ok && v != "" {
|
||||
var tenantID string
|
||||
_, err := dborm.DefaultDB().Table("sys_user").
|
||||
Where("user_name=?", v).Cols("tenant_id").Distinct().Get(&tenantID)
|
||||
if err != nil {
|
||||
log.Errorf("Find tenant_id from sys_user err => %v", err)
|
||||
}
|
||||
log.Tracef("userName=%v, tenantID=%v", v, tenantID)
|
||||
if tenantID != "" {
|
||||
conditions = append(conditions, "s.tenant_id = ?")
|
||||
params = append(params, tenantID)
|
||||
query["neId"] = ""
|
||||
}
|
||||
}
|
||||
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": []VoLTEUser{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from u_ims_user s"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
orderSql := ""
|
||||
if v, ok := query["sortField"]; ok && v != "" {
|
||||
sortSql := v.(string)
|
||||
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
|
||||
if o == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return result
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectList 根据实体查询
|
||||
func (r *Repository) SelectList(u VoLTEUser) []VoLTEUser {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if u.IMSI != "" {
|
||||
conditions = append(conditions, "imsi = ?")
|
||||
params = append(params, u.IMSI)
|
||||
}
|
||||
if u.NeId != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, u.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 {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectByIMSIAndNeID 通过imsi和ne_id查询
|
||||
func (r *Repository) SelectByIMSIAndNeID(imsi, neId string) VoLTEUser {
|
||||
querySql := r.selectSql + " where imsi = ? and ne_id = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{imsi, neId})
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return VoLTEUser{}
|
||||
}
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
if len(rows) > 0 {
|
||||
return rows[0]
|
||||
}
|
||||
return VoLTEUser{}
|
||||
}
|
||||
|
||||
// Insert 批量添加
|
||||
func (r *Repository) Inserts(uArr []VoLTEUser) int64 {
|
||||
// multi-tenancy
|
||||
r.SetTenantID(&uArr)
|
||||
|
||||
tx := datasource.DefaultDB().CreateInBatches(uArr, 2000)
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("CreateInBatches err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// Delete 删除实体
|
||||
func (r *Repository) Delete(imsi, neId string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neId).Delete(&Repository{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("Delete err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// DeletePrefixByIMSI 删除前缀匹配的实体
|
||||
func (r *Repository) DeletePrefixByIMSI(imsiPrefix, neId string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsiPrefix, neId).Delete(&Repository{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("DeletePrefixByIMSI err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
func (r *Repository) SetTenantID(subArr *[]VoLTEUser) {
|
||||
for s := 0; s < len(*subArr); s++ {
|
||||
var tenantID []string
|
||||
err := dborm.DefaultDB().Table("sys_tenant").
|
||||
Where("status='1' and tenancy_type='IMSI' and ? like tenancy_key", (*subArr)[s].IMSI).
|
||||
Cols("parent_id").Distinct().Find(&tenantID)
|
||||
if err != nil {
|
||||
logger.Errorf("Find tenant_id err => %v", err)
|
||||
continue
|
||||
}
|
||||
if len(tenantID) > 0 {
|
||||
(*subArr)[s].TenantID = tenantID[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
67
features/ue/ims_user/router.go
Normal file
67
features/ue/ims_user/router.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package ims_user
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/middleware"
|
||||
"be.ems/src/framework/middleware/collectlogs"
|
||||
"be.ems/src/framework/middleware/repeat"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Description Register Routes for ims_user
|
||||
func Register(r *gin.RouterGroup) {
|
||||
|
||||
volteUserGroup := r.Group("/volte/user")
|
||||
{
|
||||
volteUserGroup.PUT("/resetData/:neId",
|
||||
repeat.RepeatSubmit(5),
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.volteUser", collectlogs.BUSINESS_TYPE_CLEAN)),
|
||||
NewController.ResetData,
|
||||
)
|
||||
volteUserGroup.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
NewController.List,
|
||||
)
|
||||
volteUserGroup.GET("/:neId/:imsi",
|
||||
middleware.PreAuthorize(nil),
|
||||
NewController.Info,
|
||||
)
|
||||
volteUserGroup.POST("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.volteUser", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
NewController.Add,
|
||||
)
|
||||
volteUserGroup.POST("/:neId/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.volteUser", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
NewController.Adds,
|
||||
)
|
||||
volteUserGroup.PUT("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.volteUser", collectlogs.BUSINESS_TYPE_UPDATE)),
|
||||
NewController.Edit,
|
||||
)
|
||||
volteUserGroup.DELETE("/:neId/:imsi",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.volteUser", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
NewController.Remove,
|
||||
)
|
||||
volteUserGroup.DELETE("/:neId/:imsi/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.volteUser", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
NewController.Removes,
|
||||
)
|
||||
volteUserGroup.POST("/export",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.volteUser", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
NewController.Export,
|
||||
)
|
||||
volteUserGroup.POST("/import",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.volteUser", collectlogs.BUSINESS_TYPE_IMPORT)),
|
||||
NewController.Import,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
209
features/ue/ims_user/service.go
Normal file
209
features/ue/ims_user/service.go
Normal file
@@ -0,0 +1,209 @@
|
||||
package ims_user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/redis"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
)
|
||||
|
||||
// 实例化服务层 Service 结构体
|
||||
var NewVoLTEService = &Service{
|
||||
volteRepository: NewVoLTERepository,
|
||||
}
|
||||
|
||||
// VoLTE用户信息 服务层处理
|
||||
type Service struct {
|
||||
volteRepository *Repository // VoLTE用户信息数据信息
|
||||
}
|
||||
|
||||
// dataByRedis UDM签约用户 db:0 中 volte:*
|
||||
func (r *Service) dataByRedis(imsi, neId string) []VoLTEUser {
|
||||
arr := []VoLTEUser{}
|
||||
key := fmt.Sprintf("volte:%s", imsi)
|
||||
source := fmt.Sprintf("UDM_%s", neId)
|
||||
|
||||
// 网元主机的Redis客户端
|
||||
redisClient, err := neService.NewNeInfo.NeRunRedisClient("UDM", neId)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
defer func() {
|
||||
redisClient.Close()
|
||||
redis.ConnectPush(source, nil)
|
||||
}()
|
||||
redis.ConnectPush(source, redisClient.Client)
|
||||
|
||||
udmsdArr, err := redis.GetKeys(source, key)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
mkv, err := redis.GetHashBatch(source, udmsdArr)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
|
||||
for k, m := range mkv {
|
||||
var imsi, msisdn string
|
||||
KeyParts := strings.Split(k, ":")
|
||||
switch len(KeyParts) {
|
||||
case 0, 1:
|
||||
// 处理单个部分的情况
|
||||
continue
|
||||
case 2:
|
||||
// 处理两个部分的情况
|
||||
imsi = KeyParts[1]
|
||||
msisdn = "-"
|
||||
case 3:
|
||||
// 处理三个部分的情况
|
||||
imsi = KeyParts[1]
|
||||
msisdn = KeyParts[2]
|
||||
default:
|
||||
// 处理更多部分的情况
|
||||
imsi = KeyParts[1]
|
||||
msisdn = KeyParts[2]
|
||||
}
|
||||
|
||||
var vni string = "-"
|
||||
impiParts := strings.Split(m["impi"], "@")
|
||||
if len(impiParts) > 1 {
|
||||
vni = impiParts[1] // 输出: ims.mnc001.mcc110.3gppnetwork.org
|
||||
}
|
||||
a := VoLTEUser{
|
||||
NeId: neId,
|
||||
IMSI: imsi, // volte:360000100000130:8612300000130
|
||||
MSISDN: msisdn, // 8612300000130
|
||||
VoLTE: m["tag"], // volte = tag
|
||||
VNI: vni, // ims.mnc001.mcc110.3gppnetwork.org
|
||||
}
|
||||
arr = append(arr, a)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// ResetData 重置鉴权用户数据,清空数据库重新同步Redis数据
|
||||
func (r *Service) ResetData(neId string) int64 {
|
||||
subArr := r.dataByRedis("*", neId)
|
||||
// 数据清空后添加
|
||||
go r.volteRepository.ClearAndInsert(neId, subArr)
|
||||
return int64(len(subArr))
|
||||
}
|
||||
|
||||
// ParseInfo 解析单个用户imsi签约信息 data从命令MML得到的结果
|
||||
func (r *Service) ParseInfo(imsi, neId string, data map[string]string) VoLTEUser {
|
||||
u := r.volteRepository.SelectByIMSIAndNeID(imsi, neId)
|
||||
|
||||
msisdn := data["MSISDN"]
|
||||
if imsMsisdnLen := strings.Index(msisdn, ","); imsMsisdnLen != -1 {
|
||||
msisdn = msisdn[:imsMsisdnLen]
|
||||
}
|
||||
|
||||
// 用于更新
|
||||
u.NeId = neId
|
||||
u.IMSI = imsi
|
||||
u.MSISDN = msisdn
|
||||
u.VoLTE = data["VoLTE"]
|
||||
u.VNI = data["VNI"]
|
||||
return u
|
||||
}
|
||||
|
||||
// SelectPage 分页查询数据库
|
||||
func (r *Service) SelectPage(query map[string]any) map[string]any {
|
||||
return r.volteRepository.SelectPage(query)
|
||||
}
|
||||
|
||||
// SelectList 查询数据库
|
||||
func (r *Service) SelectList(u VoLTEUser) []VoLTEUser {
|
||||
return r.volteRepository.SelectList(u)
|
||||
}
|
||||
|
||||
// Insert 从数据中读取后删除imsi再存入数据库
|
||||
// imsi长度15,ki长度32,opc长度0或者32
|
||||
func (r *Service) Insert(neId string, u VoLTEUser) int64 {
|
||||
uArr := r.dataByRedis(u.IMSI, neId)
|
||||
if len(uArr) > 0 {
|
||||
r.volteRepository.Delete(u.IMSI, neId)
|
||||
return r.volteRepository.Inserts(uArr)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InsertData 导入文件数据 dataType目前两种:txt/csv
|
||||
func (r *Service) InsertData(neId, dataType string, data any) int64 {
|
||||
// imsi截取前缀,重新获取部分数据
|
||||
prefixes := make(map[string]struct{})
|
||||
|
||||
if dataType == "csv" {
|
||||
for _, v := range data.([]map[string]string) {
|
||||
imsi := v["imsi"]
|
||||
if len(imsi) < 6 {
|
||||
continue
|
||||
}
|
||||
prefix := imsi[:len(imsi)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
if dataType == "txt" {
|
||||
for _, v := range data.([][]string) {
|
||||
imsi := v[0]
|
||||
if len(imsi) < 6 {
|
||||
continue
|
||||
}
|
||||
prefix := imsi[:len(imsi)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据前缀重新加载插入
|
||||
var num int64 = 0
|
||||
for prefix := range prefixes {
|
||||
// keys volte:4600001000004*
|
||||
arr := r.dataByRedis(prefix+"*", neId)
|
||||
if len(arr) > 0 {
|
||||
r.volteRepository.DeletePrefixByIMSI(prefix, neId)
|
||||
num += r.volteRepository.Inserts(arr)
|
||||
}
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// Delete 删除单个不重新加载
|
||||
func (r *Service) Delete(neId, imsi string) int64 {
|
||||
return r.volteRepository.Delete(imsi, neId)
|
||||
}
|
||||
|
||||
// LoadData 重新加载从imsi开始num的数据
|
||||
func (r *Service) LoadData(neId, imsi, num string) {
|
||||
startIMSI, _ := strconv.ParseInt(imsi, 10, 64)
|
||||
subNum, _ := strconv.ParseInt(num, 10, 64)
|
||||
var i int64
|
||||
for i = 0; i < subNum; i++ {
|
||||
keyIMSI := fmt.Sprintf("%015d", startIMSI+i)
|
||||
// 删除原数据
|
||||
r.volteRepository.Delete(keyIMSI, neId)
|
||||
arr := r.dataByRedis(keyIMSI, neId)
|
||||
if len(arr) < 1 {
|
||||
continue
|
||||
}
|
||||
r.volteRepository.Inserts(arr)
|
||||
}
|
||||
}
|
||||
|
||||
// ParseCommandParams 解析数据组成命令参数 msisdn=xx,xx=xx,...
|
||||
func (r *Service) ParseCommandParams(item VoLTEUser) string {
|
||||
var conditions []string
|
||||
if item.MSISDN != "" {
|
||||
conditions = append(conditions, fmt.Sprintf("msisdn=%s", item.MSISDN))
|
||||
}
|
||||
|
||||
if item.VoLTE != "" {
|
||||
conditions = append(conditions, fmt.Sprintf("volte=%s", item.VoLTE))
|
||||
}
|
||||
if item.VNI != "" {
|
||||
conditions = append(conditions, fmt.Sprintf("vni=%s", item.VNI))
|
||||
}
|
||||
|
||||
return strings.Join(conditions, ",")
|
||||
}
|
||||
26
features/ue/model/file_export.go
Normal file
26
features/ue/model/file_export.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
|
||||
)
|
||||
|
||||
const (
|
||||
INVOKE_FILE_EXPORT = "exportUEData" // 调用目标字符串
|
||||
)
|
||||
|
||||
type SysJob struct {
|
||||
JobID int64 `gorm:"column:job_id;primary_key;auto_increment" json:"job_id"` //任务ID
|
||||
InvokeTarget string `gorm:"column:invoke_target" json:"invoke_target"` //调用目标字符串
|
||||
TargetParams string `gorm:"column:target_params;type:json" json:"target_params,omitempty"` //调用目标传入参数
|
||||
}
|
||||
|
||||
func (m *SysJob) TableName() string {
|
||||
return "sys_job"
|
||||
}
|
||||
|
||||
type FileExportQuery struct {
|
||||
Path string `form:"path" binding:"required"`
|
||||
Suffix string `form:"suffix"`
|
||||
PageNum int64 `form:"pageNum" binding:"required"`
|
||||
PageSize int64 `form:"pageSize" binding:"required"`
|
||||
}
|
||||
26
features/ue/model/ims_user.go
Normal file
26
features/ue/model/ims_user.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package model
|
||||
|
||||
const (
|
||||
// IMSI 号码长度
|
||||
IMSI_MAX_LENGTH = 15
|
||||
// MSISDN 号码长度
|
||||
MSISDN_MAX_LENGTH = 15
|
||||
)
|
||||
|
||||
// @Description VoLTE用户信息
|
||||
type IMSUser struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
|
||||
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识
|
||||
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
|
||||
MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户电话号码
|
||||
VoLTE string `json:"volte" gorm:"column:volte"` // VoLTE
|
||||
VNI string `json:"vni" gorm:"column:vni"` // VNI
|
||||
|
||||
TenantID string `json:"tenantID" gorm:"column:tenant_id"`
|
||||
TenantName string `json:"tenantName" gorm:"-"`
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*IMSUser) TableName() string {
|
||||
return "u_ims_user"
|
||||
}
|
||||
17
features/ue/model/voip_auth.go
Normal file
17
features/ue/model/voip_auth.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package model
|
||||
|
||||
// @Description VoLTE用户信息
|
||||
type VoIPAuth struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
|
||||
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识
|
||||
UserName string `json:"userName" gorm:"column:user_name"` // SIM卡/USIM卡ID
|
||||
Password string `json:"password" gorm:"column:password"` // 用户电话号码
|
||||
|
||||
TenantID string `json:"tenantID" gorm:"column:tenant_id"`
|
||||
TenantName string `json:"tenantName" gorm:"-"`
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*VoIPAuth) TableName() string {
|
||||
return "u_voip_auth"
|
||||
}
|
||||
273
features/ue/repository/ims_user.go
Normal file
273
features/ue/repository/ims_user.go
Normal file
@@ -0,0 +1,273 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
dborm "be.ems/lib/core/datasource"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
"be.ems/features/ue/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 IMSUserRepository 结构体
|
||||
var NewIMSUserRepository = &IMSUserRepository{
|
||||
selectSql: `select
|
||||
s.id, s.ne_id, s.imsi, s.msisdn, s.volte, s.vni,
|
||||
t.tenant_id, t.tenant_name
|
||||
from u_ims_user s
|
||||
left join sys_tenant t on t.tenant_id = s.tenant_id and t.status = 1`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"ne_id": "NeId",
|
||||
"imsi": "IMSI",
|
||||
"msisdn": "MSISDN",
|
||||
"volte": "VoLTE",
|
||||
"vni": "VNI",
|
||||
|
||||
"tenant_id": "TenantID",
|
||||
"tenant_name": "TenantName", // Tenant name for multi-tenancy
|
||||
},
|
||||
}
|
||||
|
||||
// IMSUserRepository UDM签约信息表 数据层处理
|
||||
type IMSUserRepository struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *IMSUserRepository) convertResultRows(rows []map[string]any) []model.IMSUser {
|
||||
arr := make([]model.IMSUser, 0)
|
||||
for _, row := range rows {
|
||||
item := model.IMSUser{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
repo.SetFieldValue(&item, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, item)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// ClearAndInsert 清空ne_id后新增实体
|
||||
func (r *IMSUserRepository) ClearAndInsert(neId string, u []model.IMSUser) int64 {
|
||||
// 不指定neID时,用 TRUNCATE 清空表快
|
||||
// _, err := datasource.ExecDB("", "TRUNCATE TABLE u_ims_user", nil)
|
||||
_, err := datasource.ExecDB("", "DELETE FROM u_ims_user WHERE ne_id = ?", []any{neId})
|
||||
if err != nil {
|
||||
logger.Errorf("TRUNCATE err => %v", err)
|
||||
}
|
||||
|
||||
return r.Inserts(u)
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询字典类型
|
||||
func (r *IMSUserRepository) 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, strings.Trim(v.(string), " "))
|
||||
}
|
||||
if v, ok := query["msisdn"]; ok && v != "" {
|
||||
conditions = append(conditions, "msisdn like concat(concat('%', ?), '%')")
|
||||
params = append(params, strings.Trim(v.(string), " "))
|
||||
}
|
||||
if v, ok := query["imsis"]; ok && v != "" {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(v.([]any)))
|
||||
conditions = append(conditions, fmt.Sprintf("imsi in (%s)", placeholder))
|
||||
for _, v := range v.([]any) {
|
||||
params = append(params, v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
// for multi-tenancy solution
|
||||
if v, ok := query["tenantName"]; ok && v != "" {
|
||||
var tenantID []string
|
||||
err := dborm.DefaultDB().Table("sys_tenant").
|
||||
Where("tenant_name=? and status=1", v).Cols("tenant_id").Distinct().Find(&tenantID)
|
||||
if err != nil {
|
||||
log.Errorf("Find tenant_id from sys_user err => %v", err)
|
||||
}
|
||||
log.Tracef("userName=%v, tenantID=%v", v, tenantID)
|
||||
if len(tenantID) > 0 {
|
||||
conditions = append(conditions, "s.tenant_id = ?")
|
||||
params = append(params, tenantID[0])
|
||||
}
|
||||
} else if v, ok := query["userName"]; ok && v != "" {
|
||||
var tenantID string
|
||||
_, err := dborm.DefaultDB().Table("sys_user").
|
||||
Where("user_name=?", v).Cols("tenant_id").Distinct().Get(&tenantID)
|
||||
if err != nil {
|
||||
log.Errorf("Find tenant_id from sys_user err => %v", err)
|
||||
}
|
||||
log.Tracef("userName=%v, tenantID=%v", v, tenantID)
|
||||
if tenantID != "" {
|
||||
conditions = append(conditions, "s.tenant_id = ?")
|
||||
params = append(params, tenantID)
|
||||
query["neId"] = ""
|
||||
}
|
||||
}
|
||||
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.IMSUser{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from u_ims_user s"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
orderSql := ""
|
||||
if v, ok := query["sortField"]; ok && v != "" {
|
||||
sortSql := v.(string)
|
||||
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
|
||||
if o == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return result
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectList 根据实体查询
|
||||
func (r *IMSUserRepository) SelectList(u model.IMSUser) []model.IMSUser {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if u.IMSI != "" {
|
||||
conditions = append(conditions, "imsi = ?")
|
||||
params = append(params, u.IMSI)
|
||||
}
|
||||
if u.NeId != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, u.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 {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectByIMSIAndNeID 通过imsi和ne_id查询
|
||||
func (r *IMSUserRepository) SelectByIMSIAndNeID(imsi, neId string) model.IMSUser {
|
||||
querySql := r.selectSql + " where imsi = ? and ne_id = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{imsi, neId})
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return model.IMSUser{}
|
||||
}
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
if len(rows) > 0 {
|
||||
return rows[0]
|
||||
}
|
||||
return model.IMSUser{}
|
||||
}
|
||||
|
||||
// Insert 批量添加
|
||||
func (r *IMSUserRepository) Inserts(uArr []model.IMSUser) int64 {
|
||||
// multi-tenancy
|
||||
r.SetTenantID(&uArr)
|
||||
|
||||
tx := datasource.DefaultDB().CreateInBatches(uArr, 2000)
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("CreateInBatches err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// Delete 删除实体
|
||||
func (r *IMSUserRepository) Delete(imsi, neId string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neId).Delete(&IMSUserRepository{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("Delete err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// DeletePrefixByIMSI 删除前缀匹配的实体
|
||||
func (r *IMSUserRepository) DeletePrefixByIMSI(imsiPrefix, neId string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsiPrefix, neId).Delete(&IMSUserRepository{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("DeletePrefixByIMSI err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
func (r *IMSUserRepository) SetTenantID(subArr *[]model.IMSUser) {
|
||||
for s := 0; s < len(*subArr); s++ {
|
||||
var tenantID []string
|
||||
err := dborm.DefaultDB().Table("sys_tenant").
|
||||
Where("status='1' and tenancy_type='IMSI' and ? like tenancy_key", (*subArr)[s].IMSI).
|
||||
Cols("parent_id").Distinct().Find(&tenantID)
|
||||
if err != nil {
|
||||
logger.Errorf("Find tenant_id err => %v", err)
|
||||
continue
|
||||
}
|
||||
if len(tenantID) > 0 {
|
||||
(*subArr)[s].TenantID = tenantID[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
268
features/ue/repository/voip_auth.go
Normal file
268
features/ue/repository/voip_auth.go
Normal file
@@ -0,0 +1,268 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
dborm "be.ems/lib/core/datasource"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
"be.ems/features/ue/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 VoIPAuthRepository 结构体
|
||||
var NewVoIPAuthRepository = &VoIPAuthRepository{
|
||||
selectSql: `select
|
||||
s.id, s.ne_id, s.user_name, s.password,
|
||||
t.tenant_id, t.tenant_name
|
||||
from u_voip_auth s
|
||||
left join sys_tenant t on t.tenant_id = s.tenant_id and t.status = 1`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"ne_id": "NeId",
|
||||
"user_name": "UserName",
|
||||
"password": "Password",
|
||||
|
||||
|
||||
"tenant_id": "TenantID",
|
||||
"tenant_name": "TenantName", // Tenant name for multi-tenancy
|
||||
},
|
||||
}
|
||||
|
||||
// VoIPAuthRepository UDM签约信息表 数据层处理
|
||||
type VoIPAuthRepository struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *VoIPAuthRepository) convertResultRows(rows []map[string]any) []model.VoIPAuth {
|
||||
arr := make([]model.VoIPAuth, 0)
|
||||
for _, row := range rows {
|
||||
item := model.VoIPAuth{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
repo.SetFieldValue(&item, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, item)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// ClearAndInsert 清空ne_id后新增实体
|
||||
func (r *VoIPAuthRepository) ClearAndInsert(neId string, u []model.VoIPAuth) int64 {
|
||||
// 不指定neID时,用 TRUNCATE 清空表快
|
||||
// _, err := datasource.ExecDB("", "TRUNCATE TABLE u_voip_auth", nil)
|
||||
_, err := datasource.ExecDB("", "DELETE FROM u_voip_auth WHERE ne_id = ?", []any{neId})
|
||||
if err != nil {
|
||||
logger.Errorf("TRUNCATE err => %v", err)
|
||||
}
|
||||
|
||||
return r.Inserts(u)
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询字典类型
|
||||
func (r *VoIPAuthRepository) SelectPage(query map[string]any) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if v, ok := query["userName"]; ok && v != "" {
|
||||
conditions = append(conditions, "user_name like concat(concat('%', ?), '%')")
|
||||
params = append(params, strings.Trim(v.(string), " "))
|
||||
}
|
||||
if v, ok := query["userNames"]; ok && v != "" {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(v.([]any)))
|
||||
conditions = append(conditions, fmt.Sprintf("user_name in (%s)", placeholder))
|
||||
for _, v := range v.([]any) {
|
||||
params = append(params, v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
// for multi-tenancy solution
|
||||
if v, ok := query["tenantName"]; ok && v != "" {
|
||||
var tenantID []string
|
||||
err := dborm.DefaultDB().Table("sys_tenant").
|
||||
Where("tenant_name=? and status=1", v).Cols("tenant_id").Distinct().Find(&tenantID)
|
||||
if err != nil {
|
||||
log.Errorf("Find tenant_id from sys_user err => %v", err)
|
||||
}
|
||||
log.Tracef("userName=%v, tenantID=%v", v, tenantID)
|
||||
if len(tenantID) > 0 {
|
||||
conditions = append(conditions, "s.tenant_id = ?")
|
||||
params = append(params, tenantID[0])
|
||||
}
|
||||
} else if v, ok := query["userName"]; ok && v != "" {
|
||||
var tenantID string
|
||||
_, err := dborm.DefaultDB().Table("sys_user").
|
||||
Where("user_name=?", v).Cols("tenant_id").Distinct().Get(&tenantID)
|
||||
if err != nil {
|
||||
log.Errorf("Find tenant_id from sys_user err => %v", err)
|
||||
}
|
||||
log.Tracef("userName=%v, tenantID=%v", v, tenantID)
|
||||
if tenantID != "" {
|
||||
conditions = append(conditions, "s.tenant_id = ?")
|
||||
params = append(params, tenantID)
|
||||
query["neId"] = ""
|
||||
}
|
||||
}
|
||||
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.VoIPAuth{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from u_voip_auth s"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
orderSql := ""
|
||||
if v, ok := query["sortField"]; ok && v != "" {
|
||||
sortSql := v.(string)
|
||||
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
|
||||
if o == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return result
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectList 根据实体查询
|
||||
func (r *VoIPAuthRepository) SelectList(u model.VoIPAuth) []model.VoIPAuth {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if u.UserName != "" {
|
||||
conditions = append(conditions, "user_name = ?")
|
||||
params = append(params, u.UserName)
|
||||
}
|
||||
if u.NeId != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, u.NeId)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + " order by user_name asc "
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// SelectByUserNameAndNeID 根据用户名和网元ID查询
|
||||
func (r *VoIPAuthRepository) SelectByUserNameAndNeID(userName, neId string) model.VoIPAuth {
|
||||
querySql := r.selectSql + " where user_name = ? and ne_id = ?"
|
||||
results, err := datasource.RawDB("", querySql, []any{userName, neId})
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return model.VoIPAuth{}
|
||||
}
|
||||
// 转换实体
|
||||
rows := r.convertResultRows(results)
|
||||
if len(rows) > 0 {
|
||||
return rows[0]
|
||||
}
|
||||
return model.VoIPAuth{}
|
||||
}
|
||||
|
||||
// Insert 批量添加
|
||||
func (r *VoIPAuthRepository) Inserts(uArr []model.VoIPAuth) int64 {
|
||||
// multi-tenancy
|
||||
r.SetTenantID(&uArr)
|
||||
|
||||
tx := datasource.DefaultDB().CreateInBatches(uArr, 2000)
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("CreateInBatches err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// Delete 删除实体
|
||||
func (r *VoIPAuthRepository) Delete(userName, neId string) int64 {
|
||||
tx := datasource.DefaultDB().Where("user_name = ? and ne_id = ?", userName, neId).Delete(&VoIPAuthRepository{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("Delete err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// DeletePrefixByUserName 删除以指定前缀的用户名
|
||||
func (r *VoIPAuthRepository) DeletePrefixByUserName(userNamePrefix, neId string) int64 {
|
||||
tx := datasource.DefaultDB().Where("user_name like concat(?, '%') and ne_id = ?", userNamePrefix, neId).Delete(&VoIPAuthRepository{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("DeletePrefixByUserName err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
func (r *VoIPAuthRepository) SetTenantID(subArr *[]model.VoIPAuth) {
|
||||
for s := 0; s < len(*subArr); s++ {
|
||||
var tenantID []string
|
||||
err := dborm.DefaultDB().Table("sys_tenant").
|
||||
Where("status='1' and tenancy_type='MSISDN' and ? like tenancy_key", (*subArr)[s].UserName).
|
||||
Cols("parent_id").Distinct().Find(&tenantID)
|
||||
if err != nil {
|
||||
logger.Errorf("Find tenant_id err => %v", err)
|
||||
continue
|
||||
}
|
||||
if len(tenantID) > 0 {
|
||||
(*subArr)[s].TenantID = tenantID[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// log management package
|
||||
|
||||
package ue
|
||||
|
||||
import (
|
||||
"be.ems/features/ue/file_export"
|
||||
"be.ems/lib/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitSubServiceRoute(r *gin.Engine) {
|
||||
log.Info("======init UE management group gin.Engine")
|
||||
|
||||
ueGroup := r.Group("/ue")
|
||||
// register sub modules routes
|
||||
file_export.Register(ueGroup)
|
||||
}
|
||||
211
features/ue/service/ims_user.go
Normal file
211
features/ue/service/ims_user.go
Normal file
@@ -0,0 +1,211 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/redis"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"be.ems/features/ue/model"
|
||||
"be.ems/features/ue/repository"
|
||||
)
|
||||
|
||||
// 实例化服务层 IMSUserService 结构体
|
||||
var NewIMSUserService = &IMSUserService{
|
||||
imsUserRepository: repository.NewIMSUserRepository,
|
||||
}
|
||||
|
||||
// VoLTE用户信息 服务层处理
|
||||
type IMSUserService struct {
|
||||
imsUserRepository *repository.IMSUserRepository // VoLTE用户信息数据信息
|
||||
}
|
||||
|
||||
// dataByRedis UDM签约用户 db:0 中 volte:*
|
||||
func (r *IMSUserService) dataByRedis(imsi, neId string) []model.IMSUser {
|
||||
arr := []model.IMSUser{}
|
||||
key := fmt.Sprintf("volte:%s", imsi)
|
||||
source := fmt.Sprintf("UDM_%s", neId)
|
||||
|
||||
// 网元主机的Redis客户端
|
||||
redisClient, err := neService.NewNeInfo.NeRunRedisClient("UDM", neId)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
defer func() {
|
||||
redisClient.Close()
|
||||
redis.ConnectPush(source, nil)
|
||||
}()
|
||||
redis.ConnectPush(source, redisClient.Client)
|
||||
|
||||
udmsdArr, err := redis.GetKeys(source, key)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
mkv, err := redis.GetHashBatch(source, udmsdArr)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
|
||||
for k, m := range mkv {
|
||||
var imsi, msisdn string
|
||||
KeyParts := strings.Split(k, ":")
|
||||
switch len(KeyParts) {
|
||||
case 0, 1:
|
||||
// 处理单个部分的情况
|
||||
continue
|
||||
case 2:
|
||||
// 处理两个部分的情况
|
||||
imsi = KeyParts[1]
|
||||
msisdn = "-"
|
||||
case 3:
|
||||
// 处理三个部分的情况
|
||||
imsi = KeyParts[1]
|
||||
msisdn = KeyParts[2]
|
||||
default:
|
||||
// 处理更多部分的情况
|
||||
imsi = KeyParts[1]
|
||||
msisdn = KeyParts[2]
|
||||
}
|
||||
|
||||
var vni string = "-"
|
||||
impiParts := strings.Split(m["impi"], "@")
|
||||
if len(impiParts) > 1 {
|
||||
vni = impiParts[1] // 输出: ims.mnc001.mcc110.3gppnetwork.org
|
||||
}
|
||||
a := model.IMSUser{
|
||||
NeId: neId,
|
||||
IMSI: imsi, // volte:360000100000130:8612300000130
|
||||
MSISDN: msisdn, // 8612300000130
|
||||
VoLTE: m["tag"], // volte = tag
|
||||
VNI: vni, // ims.mnc001.mcc110.3gppnetwork.org
|
||||
}
|
||||
arr = append(arr, a)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// ResetData 重置鉴权用户数据,清空数据库重新同步Redis数据
|
||||
func (r *IMSUserService) ResetData(neId string) int64 {
|
||||
subArr := r.dataByRedis("*", neId)
|
||||
// 数据清空后添加
|
||||
go r.imsUserRepository.ClearAndInsert(neId, subArr)
|
||||
return int64(len(subArr))
|
||||
}
|
||||
|
||||
// ParseInfo 解析单个用户imsi签约信息 data从命令MML得到的结果
|
||||
func (r *IMSUserService) ParseInfo(imsi, neId string, data map[string]string) model.IMSUser {
|
||||
u := r.imsUserRepository.SelectByIMSIAndNeID(imsi, neId)
|
||||
|
||||
msisdn := data["MSISDN"]
|
||||
if imsMsisdnLen := strings.Index(msisdn, ","); imsMsisdnLen != -1 {
|
||||
msisdn = msisdn[:imsMsisdnLen]
|
||||
}
|
||||
|
||||
// 用于更新
|
||||
u.NeId = neId
|
||||
u.IMSI = imsi
|
||||
u.MSISDN = msisdn
|
||||
u.VoLTE = data["VoLTE"]
|
||||
u.VNI = data["VNI"]
|
||||
return u
|
||||
}
|
||||
|
||||
// SelectPage 分页查询数据库
|
||||
func (r *IMSUserService) SelectPage(query map[string]any) map[string]any {
|
||||
return r.imsUserRepository.SelectPage(query)
|
||||
}
|
||||
|
||||
// SelectList 查询数据库
|
||||
func (r *IMSUserService) SelectList(u model.IMSUser) []model.IMSUser {
|
||||
return r.imsUserRepository.SelectList(u)
|
||||
}
|
||||
|
||||
// Insert 从数据中读取后删除imsi再存入数据库
|
||||
// imsi长度15,ki长度32,opc长度0或者32
|
||||
func (r *IMSUserService) Insert(neId string, u model.IMSUser) int64 {
|
||||
uArr := r.dataByRedis(u.IMSI, neId)
|
||||
if len(uArr) > 0 {
|
||||
r.imsUserRepository.Delete(u.IMSI, neId)
|
||||
return r.imsUserRepository.Inserts(uArr)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InsertData 导入文件数据 dataType目前两种:txt/csv
|
||||
func (r *IMSUserService) InsertData(neId, dataType string, data any) int64 {
|
||||
// imsi截取前缀,重新获取部分数据
|
||||
prefixes := make(map[string]struct{})
|
||||
|
||||
if dataType == "csv" {
|
||||
for _, v := range data.([]map[string]string) {
|
||||
imsi := v["imsi"]
|
||||
if len(imsi) < 6 {
|
||||
continue
|
||||
}
|
||||
prefix := imsi[:len(imsi)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
if dataType == "txt" {
|
||||
for _, v := range data.([][]string) {
|
||||
imsi := v[0]
|
||||
if len(imsi) < 6 {
|
||||
continue
|
||||
}
|
||||
prefix := imsi[:len(imsi)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据前缀重新加载插入
|
||||
var num int64 = 0
|
||||
for prefix := range prefixes {
|
||||
// keys volte:4600001000004*
|
||||
arr := r.dataByRedis(prefix+"*", neId)
|
||||
if len(arr) > 0 {
|
||||
r.imsUserRepository.DeletePrefixByIMSI(prefix, neId)
|
||||
num += r.imsUserRepository.Inserts(arr)
|
||||
}
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// Delete 删除单个不重新加载
|
||||
func (r *IMSUserService) Delete(neId, imsi string) int64 {
|
||||
return r.imsUserRepository.Delete(imsi, neId)
|
||||
}
|
||||
|
||||
// LoadData 重新加载从imsi开始num的数据
|
||||
func (r *IMSUserService) LoadData(neId, imsi, num string) {
|
||||
startIMSI, _ := strconv.ParseInt(imsi, 10, 64)
|
||||
subNum, _ := strconv.ParseInt(num, 10, 64)
|
||||
var i int64
|
||||
for i = 0; i < subNum; i++ {
|
||||
keyIMSI := fmt.Sprintf("%015d", startIMSI+i)
|
||||
// 删除原数据
|
||||
r.imsUserRepository.Delete(keyIMSI, neId)
|
||||
arr := r.dataByRedis(keyIMSI, neId)
|
||||
if len(arr) < 1 {
|
||||
continue
|
||||
}
|
||||
r.imsUserRepository.Inserts(arr)
|
||||
}
|
||||
}
|
||||
|
||||
// ParseCommandParams 解析数据组成命令参数 msisdn=xx,xx=xx,...
|
||||
func (r *IMSUserService) ParseCommandParams(item model.IMSUser) string {
|
||||
var conditions []string
|
||||
if item.MSISDN != "" {
|
||||
conditions = append(conditions, fmt.Sprintf("msisdn=%s", item.MSISDN))
|
||||
}
|
||||
|
||||
if item.VoLTE != "" {
|
||||
conditions = append(conditions, fmt.Sprintf("volte=%s", item.VoLTE))
|
||||
}
|
||||
if item.VNI != "" {
|
||||
conditions = append(conditions, fmt.Sprintf("vni=%s", item.VNI))
|
||||
}
|
||||
|
||||
return strings.Join(conditions, ",")
|
||||
}
|
||||
170
features/ue/service/voip_auth.go
Normal file
170
features/ue/service/voip_auth.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/redis"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"be.ems/features/ue/model"
|
||||
"be.ems/features/ue/repository"
|
||||
)
|
||||
|
||||
// 实例化服务层 VoIPAuthService 结构体
|
||||
var NewVoIPAuthService = &VoIPAuthService{
|
||||
voipAuthRepository: repository.NewVoIPAuthRepository,
|
||||
}
|
||||
|
||||
// VoLTE用户信息 服务层处理
|
||||
type VoIPAuthService struct {
|
||||
voipAuthRepository *repository.VoIPAuthRepository // VoLTE用户信息数据信息
|
||||
}
|
||||
|
||||
// dataByRedis UDM签约用户 db:0 中 volte:*
|
||||
func (r *VoIPAuthService) dataByRedis(userName, neId string) []model.VoIPAuth {
|
||||
arr := []model.VoIPAuth{}
|
||||
key := fmt.Sprintf("voip:%s", userName)
|
||||
source := fmt.Sprintf("UDM_%s", neId)
|
||||
|
||||
// 网元主机的Redis客户端
|
||||
redisClient, err := neService.NewNeInfo.NeRunRedisClient("UDM", neId)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
defer func() {
|
||||
redisClient.Close()
|
||||
redis.ConnectPush(source, nil)
|
||||
}()
|
||||
redis.ConnectPush(source, redisClient.Client)
|
||||
|
||||
udmsdArr, err := redis.GetKeys(source, key)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
mkv, err := redis.GetHashBatch(source, udmsdArr)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
|
||||
for k, m := range mkv {
|
||||
var userName string
|
||||
KeyParts := strings.Split(k, ":")
|
||||
if len(KeyParts) > 1 {
|
||||
userName = KeyParts[1]
|
||||
}
|
||||
|
||||
a := model.VoIPAuth{
|
||||
NeId: neId,
|
||||
UserName: userName, // userName
|
||||
Password: m["password"], //
|
||||
}
|
||||
arr = append(arr, a)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// ResetData 重置鉴权用户数据,清空数据库重新同步Redis数据
|
||||
func (r *VoIPAuthService) ResetData(neId string) int64 {
|
||||
subArr := r.dataByRedis("*", neId)
|
||||
// 数据清空后添加
|
||||
go r.voipAuthRepository.ClearAndInsert(neId, subArr)
|
||||
return int64(len(subArr))
|
||||
}
|
||||
|
||||
// ParseInfo 解析单个用户userName信息 data从命令MML得到的结果
|
||||
func (r *VoIPAuthService) ParseInfo(userName, neId string, data map[string]string) model.VoIPAuth {
|
||||
u := r.voipAuthRepository.SelectByUserNameAndNeID(userName, neId)
|
||||
password := data["password"]
|
||||
|
||||
// 用于更新
|
||||
u.NeId = neId
|
||||
u.UserName = userName
|
||||
u.Password = password
|
||||
return u
|
||||
}
|
||||
|
||||
// SelectPage 分页查询数据库
|
||||
func (r *VoIPAuthService) SelectPage(query map[string]any) map[string]any {
|
||||
return r.voipAuthRepository.SelectPage(query)
|
||||
}
|
||||
|
||||
// SelectList 查询数据库
|
||||
func (r *VoIPAuthService) SelectList(u model.VoIPAuth) []model.VoIPAuth {
|
||||
return r.voipAuthRepository.SelectList(u)
|
||||
}
|
||||
|
||||
// Insert 从数据中读取后删除userName再存入数据库
|
||||
func (r *VoIPAuthService) Insert(neId string, u model.VoIPAuth) int64 {
|
||||
uArr := r.dataByRedis(u.UserName, neId)
|
||||
if len(uArr) > 0 {
|
||||
r.voipAuthRepository.Delete(u.UserName, neId)
|
||||
return r.voipAuthRepository.Inserts(uArr)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InsertData 导入文件数据 dataType目前两种:txt/csv
|
||||
func (r *VoIPAuthService) InsertData(neId, dataType string, data any) int64 {
|
||||
// userName截取前缀,重新获取部分数据
|
||||
prefixes := make(map[string]struct{})
|
||||
|
||||
if dataType == "csv" {
|
||||
for _, v := range data.([]map[string]string) {
|
||||
userName := v["userName"]
|
||||
prefix := userName[:len(userName)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
if dataType == "txt" {
|
||||
for _, v := range data.([][]string) {
|
||||
userName := v[0]
|
||||
prefix := userName[:len(userName)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据前缀重新加载插入
|
||||
var num int64 = 0
|
||||
for prefix := range prefixes {
|
||||
// keys volte:4600001000004*
|
||||
arr := r.dataByRedis(prefix+"*", neId)
|
||||
if len(arr) > 0 {
|
||||
r.voipAuthRepository.DeletePrefixByUserName(prefix, neId)
|
||||
num += r.voipAuthRepository.Inserts(arr)
|
||||
}
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// Delete 删除单个不重新加载
|
||||
func (r *VoIPAuthService) Delete(neId, userName string) int64 {
|
||||
return r.voipAuthRepository.Delete(userName, neId)
|
||||
}
|
||||
|
||||
// LoadData 重新加载从userName开始num的数据
|
||||
func (r *VoIPAuthService) LoadData(neId, userName, num string) {
|
||||
startUserName, _ := strconv.ParseInt(userName, 10, 64)
|
||||
subNum, _ := strconv.ParseInt(num, 10, 64)
|
||||
var i int64
|
||||
for i = 0; i < subNum; i++ {
|
||||
keyUserName := fmt.Sprintf("%d", startUserName+i)
|
||||
// 删除原数据
|
||||
r.voipAuthRepository.Delete(keyUserName, neId)
|
||||
arr := r.dataByRedis(keyUserName, neId)
|
||||
if len(arr) < 1 {
|
||||
continue
|
||||
}
|
||||
r.voipAuthRepository.Inserts(arr)
|
||||
}
|
||||
}
|
||||
|
||||
// ParseCommandParams 解析数据组成命令参数 msisdn=xx,xx=xx,...
|
||||
func (r *VoIPAuthService) ParseCommandParams(item model.VoIPAuth) string {
|
||||
var conditions []string
|
||||
if item.Password != "" {
|
||||
conditions = append(conditions, fmt.Sprintf("password=%s", item.Password))
|
||||
}
|
||||
|
||||
return strings.Join(conditions, ",")
|
||||
}
|
||||
@@ -13,7 +13,8 @@ import (
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/src/framework/cron"
|
||||
networkdata "be.ems/src/modules/network_data"
|
||||
ueService "be.ems/features/ue/service"
|
||||
neService "be.ems/src/modules/network_data/service"
|
||||
)
|
||||
|
||||
var NewProcessor = &BarProcessor{
|
||||
@@ -103,7 +104,7 @@ func (s *BarProcessor) exportUEData(param BarParams) (map[string]any, error) {
|
||||
for _, neID := range neIDs {
|
||||
log.Trace("ne_id:", neID)
|
||||
// 1. 加载最新数据, 如果数据服务存在,则重新加载数据
|
||||
dataService, err := networkdata.GetService(param.ServiceName)
|
||||
dataService, err := GetService(param.ServiceName)
|
||||
if err != nil {
|
||||
log.Warn("failed to get data service:", err)
|
||||
} else if dataService != nil {
|
||||
@@ -224,3 +225,33 @@ func (s *BarProcessor) exportData(query, filePath string, fileType string) (int6
|
||||
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
// ResettableService 接口定义
|
||||
type ResettableService interface {
|
||||
ResetData(neID string) int64
|
||||
}
|
||||
|
||||
// 服务注册表
|
||||
var serviceRegistry = make(map[string]ResettableService)
|
||||
func RegisterService(name string, service ResettableService) {
|
||||
serviceRegistry[name] = service
|
||||
}
|
||||
|
||||
// 获取服务
|
||||
func GetService(name string) (ResettableService, error) {
|
||||
service, exists := serviceRegistry[name]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("service %s not found", name)
|
||||
}
|
||||
return service, nil
|
||||
}
|
||||
|
||||
// 初始化注册表
|
||||
func init() {
|
||||
RegisterService("UDMAuthUser", neService.NewUDMAuthUser)
|
||||
RegisterService("UDMSubUser", neService.NewUDMAuthUser)
|
||||
RegisterService("UDMVoIPAuth", ueService.NewVoIPAuthService)
|
||||
RegisterService("UDMIMSUser", ueService.NewIMSUserService)
|
||||
|
||||
// 这里注册更多服务
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"be.ems/src/modules/network_data/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 模块路由注册
|
||||
@@ -324,34 +323,6 @@ func Setup(router *gin.Engine) {
|
||||
}
|
||||
}
|
||||
|
||||
// ResettableService 接口定义
|
||||
type ResettableService interface {
|
||||
ResetData(neID string) int64
|
||||
}
|
||||
|
||||
// 服务注册表
|
||||
var serviceRegistry = make(map[string]ResettableService)
|
||||
func RegisterService(name string, service ResettableService) {
|
||||
serviceRegistry[name] = service
|
||||
}
|
||||
|
||||
// 获取服务
|
||||
func GetService(name string) (ResettableService, error) {
|
||||
service, exists := serviceRegistry[name]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("service %s not found", name)
|
||||
}
|
||||
return service, nil
|
||||
}
|
||||
|
||||
// 初始化注册表
|
||||
func init() {
|
||||
RegisterService("UDMAuthUser", service.NewUDMAuthUser)
|
||||
RegisterService("UDMSubUser", service.NewUDMSubUser)
|
||||
|
||||
// 这里注册更多服务
|
||||
}
|
||||
|
||||
// InitLoad 初始参数
|
||||
func InitLoad() {
|
||||
// 启动时,加载UPF上下行流量
|
||||
|
||||
Reference in New Issue
Block a user