From 56991a0b498fc4ce1af006e9a62ca9ee5e437473 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Sun, 27 Apr 2025 11:07:34 +0800 Subject: [PATCH] feat: Implement Oauth2 login log service and repository - Added Oauth2LogLoginService for managing user authorization logs. - Implemented methods for inserting logs, cleaning logs, and exporting log data. - Created a new file for Oauth2 login log service. refactor: Remove unused open_api module - Deleted the open_api.go file as it was not utilized in the project. fix: Update error codes in SysProfileController - Changed error codes for binding errors and user authentication errors to more descriptive values. fix: Update cache handling in SysConfig and SysDictType services - Modified Redis set operations to include expiration time for cached values. refactor: Update middleware authorization checks - Replaced PreAuthorize middleware with AuthorizeUser across multiple routes in system and tool modules for consistency. chore: Clean up trace and ws modules - Updated middleware authorization in trace and ws modules to use AuthorizeUser. --- build/database/lite/install/oauth2_client.sql | 24 ++ .../lite/install/oauth2_log_login.sql | 20 ++ build/database/lite/install/sys_i18n.sql | 5 +- build/database/std/install/oauth2_client.sql | 27 +++ .../database/std/install/oauth2_log_login.sql | 23 ++ build/database/std/install/sys_i18n.sql | 8 +- features/cm/omc/route.go | 8 +- features/lm/file_export/route.go | 10 +- features/nbi/file/route.go | 6 +- features/pm/kpi_c_report/route.go | 14 +- features/pm/kpi_c_title/route.go | 12 +- lib/core/ctx/ctx.go | 55 +---- main.go | 2 +- src/app.go | 6 + src/config/config.default.yaml | 10 +- src/framework/constants/cache_key.go | 8 +- src/framework/constants/common.go | 3 + src/framework/constants/token.go | 10 +- src/framework/database/redis/redis.go | 102 ++++----- src/framework/middleware/authorize_oauth2.go | 66 ++++++ .../{pre_authorize.go => authorize_user.go} | 42 ++-- src/framework/middleware/operate_log.go | 2 +- src/framework/middleware/repeat/repeat.go | 2 +- src/framework/middleware/repeat_submit.go | 2 +- src/framework/reqctx/auth.go | 12 +- src/framework/reqctx/context.go | 8 +- src/framework/reqctx/param.go | 9 + src/framework/resp/api.go | 6 +- src/framework/token/oauth2_info.go | 14 ++ src/framework/token/oauth2_token.go | 167 ++++++++++++++ src/framework/token/token.go | 152 ------------- .../token/{token_info.go => user_info.go} | 6 +- src/framework/token/user_token.go | 173 ++++++++++++++ src/framework/utils/crypto/hash.go | 31 +++ src/modules/auth/auth.go | 34 ++- src/modules/auth/controller/account.go | 205 +++++++++++------ src/modules/auth/controller/bootloader.go | 33 ++- src/modules/auth/controller/captcha.go | 4 +- src/modules/auth/controller/register.go | 58 ++--- src/modules/auth/service/account.go | 66 ++++-- src/modules/auth/service/register.go | 47 +--- src/modules/chart/chart.go | 8 +- src/modules/common/common.go | 20 +- src/modules/common/controller/file.go | 4 +- src/modules/monitor/controller/sys_cache.go | 6 +- .../monitor/controller/sys_user_online.go | 15 +- src/modules/monitor/monitor.go | 52 ++--- .../monitor/service/sys_user_online.go | 24 +- src/modules/network_data/network_data.go | 160 ++++++------- .../network_element/network_element.go | 126 +++++------ .../network_element/service/ne_config.go | 4 +- .../network_element/service/ne_info.go | 8 +- src/modules/oauth2/controller/oauth2.go | 214 ++++++++++++++++++ .../oauth2/controller/oauth2_client.go | 152 +++++++++++++ src/modules/oauth2/model/code_query.go | 8 + src/modules/oauth2/model/oauth2_client.go | 22 ++ src/modules/oauth2/model/oauth2_log_login.go | 19 ++ src/modules/oauth2/model/token_body.go | 10 + src/modules/oauth2/oauth2.go | 83 +++++++ .../oauth2/repository/oauth2_client.go | 168 ++++++++++++++ .../oauth2/repository/oauth2_log_login.go | 117 ++++++++++ src/modules/oauth2/service/oauth2.go | 86 +++++++ src/modules/oauth2/service/oauth2_client.go | 65 ++++++ .../oauth2/service/oauth2_log_login.go | 85 +++++++ src/modules/open_api/open_api.go | 12 - src/modules/system/controller/sys_profile.go | 27 ++- src/modules/system/service/sys_config.go | 6 +- src/modules/system/service/sys_dict_type.go | 4 +- src/modules/system/system.go | 150 ++++++------ src/modules/tool/tool.go | 14 +- src/modules/trace/trace.go | 34 +-- src/modules/ws/ws.go | 12 +- 72 files changed, 2334 insertions(+), 873 deletions(-) create mode 100644 build/database/lite/install/oauth2_client.sql create mode 100644 build/database/lite/install/oauth2_log_login.sql create mode 100644 build/database/std/install/oauth2_client.sql create mode 100644 build/database/std/install/oauth2_log_login.sql create mode 100644 src/framework/middleware/authorize_oauth2.go rename src/framework/middleware/{pre_authorize.go => authorize_user.go} (82%) create mode 100644 src/framework/token/oauth2_info.go create mode 100644 src/framework/token/oauth2_token.go delete mode 100644 src/framework/token/token.go rename src/framework/token/{token_info.go => user_info.go} (85%) create mode 100644 src/framework/token/user_token.go create mode 100644 src/framework/utils/crypto/hash.go create mode 100644 src/modules/oauth2/controller/oauth2.go create mode 100644 src/modules/oauth2/controller/oauth2_client.go create mode 100644 src/modules/oauth2/model/code_query.go create mode 100644 src/modules/oauth2/model/oauth2_client.go create mode 100644 src/modules/oauth2/model/oauth2_log_login.go create mode 100644 src/modules/oauth2/model/token_body.go create mode 100644 src/modules/oauth2/oauth2.go create mode 100644 src/modules/oauth2/repository/oauth2_client.go create mode 100644 src/modules/oauth2/repository/oauth2_log_login.go create mode 100644 src/modules/oauth2/service/oauth2.go create mode 100644 src/modules/oauth2/service/oauth2_client.go create mode 100644 src/modules/oauth2/service/oauth2_log_login.go delete mode 100644 src/modules/open_api/open_api.go diff --git a/build/database/lite/install/oauth2_client.sql b/build/database/lite/install/oauth2_client.sql new file mode 100644 index 00000000..72276be1 --- /dev/null +++ b/build/database/lite/install/oauth2_client.sql @@ -0,0 +1,24 @@ +-- ---------------------------- +-- Table structure for oauth2_client +-- ---------------------------- +DROP TABLE IF EXISTS "oauth2_client"; +CREATE TABLE "oauth2_client" ( + "id" integer NOT NULL, + "client_id" text(32) NOT NULL, + "client_secret" text(64) NOT NULL, + "title" text(64), + "ip_white" text(255), + "del_flag" text(1), + "login_ip" text(128), + "login_time" integer, + "create_by" text(64), + "create_time" integer, + "update_by" text(64), + "update_time" integer, + "remark" text(200), + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- Records of oauth2_client +-- ---------------------------- diff --git a/build/database/lite/install/oauth2_log_login.sql b/build/database/lite/install/oauth2_log_login.sql new file mode 100644 index 00000000..9ea610dd --- /dev/null +++ b/build/database/lite/install/oauth2_log_login.sql @@ -0,0 +1,20 @@ +-- ---------------------------- +-- Table structure for oauth2_log_login +-- ---------------------------- +DROP TABLE IF EXISTS "oauth2_log_login"; +CREATE TABLE "oauth2_log_login" ( + "id" integer NOT NULL, + "client_id" text(32), + "login_ip" text(128), + "login_location" text(32), + "browser" text(64), + "os" text(64), + "status_flag" text(1), + "msg" text(255), + "login_time" integer, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- Records of oauth2_log_login +-- ---------------------------- diff --git a/build/database/lite/install/sys_i18n.sql b/build/database/lite/install/sys_i18n.sql index cfe88931..d394c06d 100644 --- a/build/database/lite/install/sys_i18n.sql +++ b/build/database/lite/install/sys_i18n.sql @@ -613,7 +613,7 @@ INSERT INTO "sys_i18n" VALUES (543, 'dictData.cdr_sip_code.503', '服务不可 INSERT INTO "sys_i18n" VALUES (544, 'dictData.cdr_sip_code.504', '服务器超时', 'Server Time Out'); INSERT INTO "sys_i18n" VALUES (545, 'dictData.cdr_sip_code.603', '拒绝', 'Decline'); INSERT INTO "sys_i18n" VALUES (546, 'dictData.cdr_sip_code.606', '不可接受', 'Not Acceptable'); -INSERT INTO "sys_i18n" VALUES (547, 'cache.name.user', '登录用户', 'Login User'); +INSERT INTO "sys_i18n" VALUES (547, 'cache.name.token', '用户令牌', 'User Token'); INSERT INTO "sys_i18n" VALUES (548, 'cache.name.sys_config', '参数管理', 'Parameters Management'); INSERT INTO "sys_i18n" VALUES (549, 'cache.name.sys_dict', '字典管理', 'Dictionary Management'); INSERT INTO "sys_i18n" VALUES (550, 'cache.name.captcha_codes', '验证码', 'Captcha'); @@ -708,6 +708,8 @@ View network element configuration backup records for downloading or importing c INSERT INTO "sys_i18n" VALUES (637, 'job.backup_export_table_sys_log_operate', '备份-操作日志表定期导出', 'Backup-Operation Log Table Periodic Export'); INSERT INTO "sys_i18n" VALUES (638, 'job.backup_export_table_cdr_event_ims', '备份-语音话单表定期导出', 'Backup-Regular Export of voice bill forms'); INSERT INTO "sys_i18n" VALUES (639, 'job.backup_export_table_cdr_event_smf', '备份-数据话单表定期导出', 'Backup-Regular Export of data sheet tables'); +INSERT INTO "sys_i18n" VALUES (640, 'cache.name.oauth2_codes', '客户端授权码', 'Oauth2 Client Code'); +INSERT INTO "sys_i18n" VALUES (641, 'cache.name.oauth2_devices', '客户端令牌', 'Oauth2 Token'); INSERT INTO "sys_i18n" VALUES (644, 'menu.log.exportFile', '导出文件', 'Exported File'); INSERT INTO "sys_i18n" VALUES (645, 'menu.perf.kpiCReport', '自定义指标数据', 'Custom Indicator Data'); INSERT INTO "sys_i18n" VALUES (646, 'menu.trace.taskHLR', 'HLR 跟踪任务', 'HLR Trace Task'); @@ -751,6 +753,7 @@ alertHours upcoming expiration reminder time'); INSERT INTO "sys_i18n" VALUES (674, 'config.sys.user.passwdNotAllowedHistory', '用户管理-不允许使用最近密码次数', 'User Management-Not Allowed Recent Passwords'); INSERT INTO "sys_i18n" VALUES (675, 'config.sys.user.passwdNotAllowedHistoryRemark', '创建新密码不等于之前使用的x次中的密码', 'Creating a new password that is not equal to the previously used password in x times'); INSERT INTO "sys_i18n" VALUES (676, 'login.errPasswdHistory', '不允许使用最近密码', 'Recent passwords not allowed'); +INSERT INTO "sys_i18n" VALUES (677, 'log.operate.title.oauth2client', 'Oauth2客户端授权', 'Oauth2 Client Authorization'); INSERT INTO "sys_i18n" VALUES (679, 'dictType.trace_msg_type', '跟踪消息类型', 'Trace Message Type'); INSERT INTO "sys_i18n" VALUES (680, 'dictData.trace_msg_type.0', '请求', 'Request'); INSERT INTO "sys_i18n" VALUES (681, 'dictData.trace_msg_type.1', '响应', 'Response'); diff --git a/build/database/std/install/oauth2_client.sql b/build/database/std/install/oauth2_client.sql new file mode 100644 index 00000000..195d85e2 --- /dev/null +++ b/build/database/std/install/oauth2_client.sql @@ -0,0 +1,27 @@ +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for oauth2_client +-- ---------------------------- +DROP TABLE IF EXISTS `oauth2_client`; +CREATE TABLE `oauth2_client` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '应用ID', + `client_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '应用的唯一标识', + `client_secret` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '应用的凭证秘钥', + `title` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '应用名称', + `ip_white` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'IP白名单', + `del_flag` varchar(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记(0存在 1删除)', + `login_ip` varchar(128) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '最后登录IP', + `login_time` bigint DEFAULT '0' COMMENT '最后登录时间', + `create_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者', + `create_time` bigint DEFAULT '0' COMMENT '创建时间', + `update_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者', + `update_time` bigint DEFAULT '0' COMMENT '更新时间', + `remark` varchar(200) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '备注', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='第三方_用户授权应用表'; + +SET FOREIGN_KEY_CHECKS = 1; + +-- Dump completed on 2025-04-25 15:26:56 diff --git a/build/database/std/install/oauth2_log_login.sql b/build/database/std/install/oauth2_log_login.sql new file mode 100644 index 00000000..c6f13889 --- /dev/null +++ b/build/database/std/install/oauth2_log_login.sql @@ -0,0 +1,23 @@ +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for oauth2_log_login +-- ---------------------------- +DROP TABLE IF EXISTS `oauth2_log_login`; +CREATE TABLE `oauth2_log_login` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '登录ID', + `client_id` varchar(32) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '应用的唯一标识', + `login_ip` varchar(128) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '登录IP地址', + `login_location` varchar(32) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '登录地点', + `browser` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '浏览器类型', + `os` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '操作系统', + `status_flag` varchar(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '登录状态(0失败 1成功)', + `msg` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '提示消息', + `login_time` bigint DEFAULT '0' COMMENT '登录时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='第三方_用户授权应用登录日志表'; + +SET FOREIGN_KEY_CHECKS = 1; + +-- Dump completed on 2025-04-25 15:26:56 diff --git a/build/database/std/install/sys_i18n.sql b/build/database/std/install/sys_i18n.sql index 987bf098..9aea25b9 100644 --- a/build/database/std/install/sys_i18n.sql +++ b/build/database/std/install/sys_i18n.sql @@ -561,7 +561,7 @@ INSERT INTO `sys_i18n` VALUES (543, 'dictData.cdr_sip_code.503', '服务不可 INSERT INTO `sys_i18n` VALUES (544, 'dictData.cdr_sip_code.504', '服务器超时', 'Server Time Out'); INSERT INTO `sys_i18n` VALUES (545, 'dictData.cdr_sip_code.603', '拒绝', 'Decline'); INSERT INTO `sys_i18n` VALUES (546, 'dictData.cdr_sip_code.606', '不可接受', 'Not Acceptable'); -INSERT INTO `sys_i18n` VALUES (547, 'cache.name.user', '登录用户', 'Login User'); +INSERT INTO `sys_i18n` VALUES (547, 'cache.name.token', '用户令牌', 'User Token'); INSERT INTO `sys_i18n` VALUES (548, 'cache.name.sys_config', '参数管理', 'Parameters Management'); INSERT INTO `sys_i18n` VALUES (549, 'cache.name.sys_dict', '字典管理', 'Dictionary Management'); INSERT INTO `sys_i18n` VALUES (550, 'cache.name.captcha_codes', '验证码', 'Captcha'); @@ -654,8 +654,8 @@ INSERT INTO `sys_i18n` VALUES (636, 'job.ne_config_backup_remark', '网元配置 INSERT INTO `sys_i18n` VALUES (637, 'job.backup_export_table_sys_log_operate', '备份-操作日志表定期导出', 'Backup-Operation Log Table Periodic Export'); INSERT INTO `sys_i18n` VALUES (638, 'job.backup_export_table_cdr_event_ims', '备份-语音话单表定期导出', 'Backup-Regular Export of voice bill forms'); INSERT INTO `sys_i18n` VALUES (639, 'job.backup_export_table_cdr_event_smf', '备份-数据话单表定期导出', 'Backup-Regular Export of data sheet tables'); --- INSERT INTO `sys_i18n` VALUES (640, 'table.sys_log_operate', '操作日志', 'Operation Log'); --- INSERT INTO `sys_i18n` VALUES (641, 'table.cdr_event_ims', '语音话单', 'Voice CDR'); +INSERT INTO `sys_i18n` VALUES (640, 'cache.name.oauth2_codes', '客户端授权码', 'Oauth2 Client Code'); +INSERT INTO `sys_i18n` VALUES (641, 'cache.name.oauth2_devices', '客户端令牌', 'Oauth2 Token'); -- INSERT INTO `sys_i18n` VALUES (642, 'table.cdr_event_smf', '数据话单', 'Data CDR'); -- INSERT INTO `sys_i18n` VALUES (643, 'table.cdr_event_smsc', '短信话单', 'SMS CDR'); INSERT INTO `sys_i18n` VALUES (644, 'menu.log.exportFile', '导出文件', 'Exported File'); @@ -691,7 +691,7 @@ INSERT INTO `sys_i18n` VALUES (673, 'config.sys.user.passwdExpireRemark', '数 INSERT INTO `sys_i18n` VALUES (674, 'config.sys.user.passwdNotAllowedHistory', '用户管理-不允许使用最近密码次数', 'User Management-Not Allowed Recent Passwords'); INSERT INTO `sys_i18n` VALUES (675, 'config.sys.user.passwdNotAllowedHistoryRemark', '创建新密码不等于之前使用的x次中的密码', 'Creating a new password that is not equal to the previously used password in x times'); INSERT INTO `sys_i18n` VALUES (676, 'login.errPasswdHistory', '不允许使用最近密码', 'Recent passwords not allowed'); --- INSERT INTO `sys_i18n` VALUES (677, 'config.ne.neConfigBackupFTP', '配置文件备份FTP服务', 'NE Config Backup file FTP service'); +INSERT INTO `sys_i18n` VALUES (677, 'log.operate.title.oauth2client', 'Oauth2客户端授权', 'Oauth2 Client Authorization'); -- INSERT INTO `sys_i18n` VALUES (678, 'config.ne.neConfigBackupFTPRemark', '请通过配置文件备份页面进行设置FTP信息', 'Please set the FTP information through the configuration file backup page.'); INSERT INTO `sys_i18n` VALUES (679, 'dictType.trace_msg_type', '跟踪消息类型', 'Trace Message Type'); INSERT INTO `sys_i18n` VALUES (680, 'dictData.trace_msg_type.0', '请求', 'Request'); diff --git a/features/cm/omc/route.go b/features/cm/omc/route.go index 906cb1e7..e97f7b5f 100644 --- a/features/cm/omc/route.go +++ b/features/cm/omc/route.go @@ -11,19 +11,19 @@ func Register(r *gin.RouterGroup) { { var o *ConfigOMC cmOMC.GET("/config/:paramName", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), o.Get, ) cmOMC.POST("/config/:paramName", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), o.Post, ) cmOMC.PUT("/config/:paramName", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), o.Put, ) cmOMC.DELETE("/config/:paramName", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), o.Delete, ) } diff --git a/features/lm/file_export/route.go b/features/lm/file_export/route.go index 768a09b4..de9a05e6 100644 --- a/features/lm/file_export/route.go +++ b/features/lm/file_export/route.go @@ -12,7 +12,7 @@ func Register(r *gin.RouterGroup) { { var m *SysJob lmTable.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), m.GetFileExportTable, ) } @@ -20,19 +20,19 @@ func Register(r *gin.RouterGroup) { { var f *FileExport lmFile.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), f.GetFileList, ) lmFile.GET("/total", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), f.Total, ) lmFile.GET("/:fileName", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), f.DownloadHandler, ) lmFile.DELETE("/:fileName", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), f.Delete, ) } diff --git a/features/nbi/file/route.go b/features/nbi/file/route.go index f0cb58f6..45c87e62 100644 --- a/features/nbi/file/route.go +++ b/features/nbi/file/route.go @@ -11,15 +11,15 @@ func Register(r *gin.RouterGroup) { { var f *FileNBI fileNBI.GET("/:category/:type/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), f.GetFileList, ) fileNBI.GET("/:category/:type/:dateIndex", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), f.GetSingleFileHandler, ) fileNBI.GET("/:category/:type", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), f.GetMultiFileHandler, ) } diff --git a/features/pm/kpi_c_report/route.go b/features/pm/kpi_c_report/route.go index 7e64f95b..037d936c 100644 --- a/features/pm/kpi_c_report/route.go +++ b/features/pm/kpi_c_report/route.go @@ -12,31 +12,31 @@ func Register(r *gin.RouterGroup) { { var k *KpiCReport pmKPIC.GET("/report", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.GetReport2FE, ) pmKPIC.GET("/report/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Get, ) pmKPIC.GET("/report/totalList", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Total, ) pmKPIC.GET("/report/total", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Total, ) pmKPIC.POST("/report", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Post, ) pmKPIC.PUT("/report/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Put, ) pmKPIC.DELETE("/report/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Delete, ) } diff --git a/features/pm/kpi_c_title/route.go b/features/pm/kpi_c_title/route.go index f058dbe0..485f3f93 100644 --- a/features/pm/kpi_c_title/route.go +++ b/features/pm/kpi_c_title/route.go @@ -12,27 +12,27 @@ func Register(r *gin.RouterGroup) { { var k *KpiCTitle pmKPIC.GET("/title", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Get, ) pmKPIC.GET("/title/total", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Total, ) pmKPIC.GET("/title/totalList", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.GetToalList, ) pmKPIC.POST("/title", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Post, ) pmKPIC.PUT("/title/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Put, ) pmKPIC.DELETE("/title/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), k.Delete, ) } diff --git a/lib/core/ctx/ctx.go b/lib/core/ctx/ctx.go index 0bbf3c1f..be5823a1 100644 --- a/lib/core/ctx/ctx.go +++ b/lib/core/ctx/ctx.go @@ -13,7 +13,6 @@ import ( "be.ems/src/framework/constants" "be.ems/src/framework/token" "github.com/gorilla/mux" - "golang.org/x/text/language" ) // GetParam 地址栏参数{id} @@ -147,63 +146,33 @@ func Authorization(r *http.Request) string { return arr[1] } -// AcceptLanguage 解析客户端接收语言 zh:中文 en: 英文 -func AcceptLanguage(r *http.Request) string { - preferredLanguage := language.English - - // Query请求查询 - if v := GetQuery(r, "language"); v != "" { - tags, _, _ := language.ParseAcceptLanguage(v) - if len(tags) > 0 { - preferredLanguage = tags[0] - } - } - // Header请求头 - if v := GetHeader(r, "Accept-Language"); v != "" { - tags, _, _ := language.ParseAcceptLanguage(v) - if len(tags) > 0 { - preferredLanguage = tags[0] - } - } - - // 只取前缀 - lang := preferredLanguage.String() - arr := strings.Split(lang, "-") - return arr[0] -} - // ContextKey 定义自定义类型作为键 type ContextKey string // LoginUser 登录用户信息需要Authorize中间件 -func LoginUser(r *http.Request) (token.TokenInfo, error) { +func LoginUser(r *http.Request) (token.UserInfo, error) { // 获取请求头标识信息 tokenStr := Authorization(r) if tokenStr == "" { - return token.TokenInfo{}, fmt.Errorf("not token info") + return token.UserInfo{}, fmt.Errorf("not token info") } + if tokenStr == "" { + return token.UserInfo{}, fmt.Errorf("authorization token is empty") + } + // 验证令牌 - claims, err := token.Verify(tokenStr) + claims, err := token.UserTokenVerify(tokenStr, "access") if err != nil { - return token.TokenInfo{}, fmt.Errorf("token verify fail") + return token.UserInfo{}, err } // 获取缓存的用户信息 - loginUser := token.Info(claims) - if loginUser.UserId <= 0 { - return token.TokenInfo{}, fmt.Errorf("not user info") + info := token.UserInfoGet(claims) + if info.UserId <= 0 { + return token.UserInfo{}, fmt.Errorf("invalid login user information") } - return loginUser, nil -} - -// LoginUserToUserID 登录用户信息-用户ID -func LoginUserToUserID(r *http.Request) int64 { - loginUser, err := LoginUser(r) - if err != nil { - return 0 - } - return loginUser.UserId + return info, nil } // LoginUserToUserName 登录用户信息-用户名称 diff --git a/main.go b/main.go index d35b50d5..b81c1381 100644 --- a/main.go +++ b/main.go @@ -178,7 +178,7 @@ func loadFeatures(app *gin.Engine) { // 默认路由组 defaultUriGroup := app.Group(featuresCfg.DefaultUriPrefix) - defaultUriGroup.Use(middleware.PreAuthorize(nil)) + defaultUriGroup.Use(middleware.AuthorizeUser(nil)) defaultUriGroup.Any("/*any", gin.WrapH(routes.NewRouter())) // 可配置前缀路由组 uriGroup := app.Group(featuresCfg.UriPrefix) diff --git a/src/app.go b/src/app.go index 2c905fbf..2f47f4ed 100644 --- a/src/app.go +++ b/src/app.go @@ -15,6 +15,7 @@ import ( "be.ems/src/modules/monitor" networkdata "be.ems/src/modules/network_data" networkelement "be.ems/src/modules/network_element" + "be.ems/src/modules/oauth2" "be.ems/src/modules/system" "be.ems/src/modules/tool" "be.ems/src/modules/trace" @@ -83,12 +84,16 @@ func ModulesRoute(app *gin.Engine) { system.Setup(app) // 认证模块 auth.Setup(app) + // 开放客户端模块 + oauth2.Setup(app) // 通用模块 common.Setup(app) + // 网元功能模块 networkelement.Setup(app) // 网元数据模块 networkdata.Setup(app) + // 跟踪模块 trace.Setup(app) // 图表模块 @@ -97,6 +102,7 @@ func ModulesRoute(app *gin.Engine) { tool.Setup(app) // ws 模块 ws.Setup(app) + // 调度任务模块--暂无接口 crontask.Setup(app) // 监控模块 - 含调度处理加入队列,放最后 diff --git a/src/config/config.default.yaml b/src/config/config.default.yaml index 4b379992..c98c4678 100644 --- a/src/config/config.default.yaml +++ b/src/config/config.default.yaml @@ -135,13 +135,13 @@ security: # JWT 令牌配置 jwt: # 令牌算法 HS256 HS384 HS512 - algorithm: "HS512" + algorithm: "HS256" # 令牌密钥 secret: "217a0481c7f9cfe1cb547d32ee012b0f" - # 令牌有效期(默认120分钟) - expiresIn: 120 - # 验证令牌有效期,相差不足xx分钟,自动刷新缓存 - refreshIn: 20 + # 访问令牌有效期(默认15分钟) + expiresIn: 15 + # 刷新令牌有效期(默认7*24*60分钟) + refreshIn: 10080 # DB 数据源 database: diff --git a/src/framework/constants/cache_key.go b/src/framework/constants/cache_key.go index 901aa249..58fbf785 100644 --- a/src/framework/constants/cache_key.go +++ b/src/framework/constants/cache_key.go @@ -2,8 +2,8 @@ package constants // 缓存的key常量 const ( - // CACHE_LOGIN_TOKEN 登录用户 - CACHE_LOGIN_TOKEN = "login_tokens" + // CACHE_TOKEN_DEVICE 登录用户令牌标识 + CACHE_TOKEN_DEVICE = "token_devices" // CACHE_CAPTCHA_CODE 验证码 CACHE_CAPTCHA_CODE = "captcha_codes" // CACHE_SYS_CONFIG 参数管理 @@ -16,6 +16,10 @@ const ( CACHE_RATE_LIMIT = "rate_limit" // CACHE_PWD_ERR_COUNT 登录账户密码错误次数 CACHE_PWD_ERR_COUNT = "pwd_err_count" + // CACHE_OAUTH2_DEVICE 授权客户端令牌标识 + CACHE_OAUTH2_DEVICE = "oauth2_devices" + // CACHE_OAUTH2_CODE 客户端授权码 + CACHE_OAUTH2_CODE = "oauth2_codes" // CACHE_I18N 国际化语言管理 CACHE_I18N = "i18n" // CACHE_NE_INFO 网元信息管理 diff --git a/src/framework/constants/common.go b/src/framework/constants/common.go index f14ebece..3822cbfa 100644 --- a/src/framework/constants/common.go +++ b/src/framework/constants/common.go @@ -10,5 +10,8 @@ const ( // CTX_LOGIN_USER 上下文信息-登录用户 const CTX_LOGIN_USER = "ctx:login_user" +// CTX_LOGIN_OAUTH2 上下文信息-认证客户端 +const CTX_LOGIN_OAUTH2 = "ctx:login_oauth2" + // 启动-引导系统初始 const LAUNCH_BOOTLOADER = "bootloader" diff --git a/src/framework/constants/token.go b/src/framework/constants/token.go index 70b192e3..86461080 100644 --- a/src/framework/constants/token.go +++ b/src/framework/constants/token.go @@ -3,19 +3,19 @@ package constants // 令牌常量信息 // HEADER_PREFIX 令牌-请求头标识前缀 -const HEADER_PREFIX = "Bearer " +const HEADER_PREFIX = "Bearer" // HEADER_KEY 令牌-请求头标识 const HEADER_KEY = "Authorization" -// JWT_UUID 令牌-JWT唯一标识字段 -const JWT_UUID = "uuid" +// JWT_DEVICE_ID 令牌-JWT设备标识字段 +const JWT_DEVICE_ID = "device_id" // JWT_USER_ID 令牌-JWT标识用户主键字段 const JWT_USER_ID = "user_id" -// JWT_USER_NAME 令牌-JWT标识用户登录账号字段 -const JWT_USER_NAME = "user_name" +// JWT_CLIENT_ID 令牌-JWT标识客户端ID字段 +const JWT_CLIENT_ID = "client_id" // NMS北向使用-数据响应字段和请求头授权 const ACCESS_TOKEN = "accessToken" diff --git a/src/framework/database/redis/redis.go b/src/framework/database/redis/redis.go index 077075bf..82ffccbf 100644 --- a/src/framework/database/redis/redis.go +++ b/src/framework/database/redis/redis.go @@ -16,6 +16,21 @@ import ( // Redis连接实例 var rdbMap = make(map[string]*redis.Client) +// 声明定义限流脚本命令 +var rateLimitCommand = redis.NewScript(` +local key = KEYS[1] +local time = tonumber(ARGV[1]) +local count = tonumber(ARGV[2]) +local current = redis.call('get', key); +if current and tonumber(current) >= count then + return tonumber(current); +end +current = redis.call('incr', key) +if tonumber(current) == 1 then + redis.call('expire', key, time) +end +return tonumber(current);`) + // Connect 连接Redis实例 func Connect() { ctx := context.Background() @@ -33,7 +48,7 @@ func Connect() { // 测试数据库连接 pong, err := rdb.Ping(ctx).Result() if err != nil { - logger.Fatalf("failed error redis connect: %s is %v", k, err) + logger.Fatalf("Ping redis %s is %v", k, err) } logger.Infof("redis %s %d %s connection is successful.", k, client["db"].(int), pong) rdbMap[k] = rdb @@ -139,6 +154,39 @@ func CommandStats(source string) []map[string]string { return statsObjArr } +// Has 判断是否存在 +func Has(source string, keys ...string) (int64, error) { + // 数据源 + rdb := RDB(source) + if rdb == nil { + return 0, fmt.Errorf("redis not client") + } + + ctx := context.Background() + exists, err := rdb.Exists(ctx, keys...).Result() + if err != nil { + return 0, err + } + return exists, nil +} + +// SetExpire 设置过期时间 +func SetExpire(source, key string, expiration time.Duration) error { + // 数据源 + rdb := RDB(source) + if rdb == nil { + return fmt.Errorf("redis not client") + } + + ctx := context.Background() + err := rdb.Expire(ctx, key, expiration).Err() + if err != nil { + logger.Errorf("redis Expire err %v", err) + return err + } + return nil +} + // GetExpire 获取键的剩余有效时间(秒) func GetExpire(source string, key string) (int64, error) { // 数据源 @@ -227,41 +275,8 @@ func Get(source, key string) (string, error) { return v, nil } -// Has 判断是否存在 -func Has(source string, keys ...string) (int64, error) { - // 数据源 - rdb := RDB(source) - if rdb == nil { - return 0, fmt.Errorf("redis not client") - } - - ctx := context.Background() - exists, err := rdb.Exists(ctx, keys...).Result() - if err != nil { - return 0, err - } - return exists, nil -} - // Set 设置缓存数据 -func Set(source, key string, value any) error { - // 数据源 - rdb := RDB(source) - if rdb == nil { - return fmt.Errorf("redis not client") - } - - ctx := context.Background() - err := rdb.Set(ctx, key, value, 0).Err() - if err != nil { - logger.Errorf("redis Set err %v", err) - return err - } - return nil -} - -// SetByExpire 设置缓存数据与过期时间 -func SetByExpire(source, key string, value any, expiration time.Duration) error { +func Set(source, key string, value any, expiration time.Duration) error { // 数据源 rdb := RDB(source) if rdb == nil { @@ -271,7 +286,7 @@ func SetByExpire(source, key string, value any, expiration time.Duration) error ctx := context.Background() err := rdb.Set(ctx, key, value, expiration).Err() if err != nil { - logger.Errorf("redis SetByExpire err %v", err) + logger.Errorf("redis Set err %v", err) return err } return nil @@ -329,18 +344,3 @@ func RateLimit(source, limitKey string, time, count int64) (int64, error) { } return result.(int64), err } - -// 声明定义限流脚本命令 -var rateLimitCommand = redis.NewScript(` -local key = KEYS[1] -local time = tonumber(ARGV[1]) -local count = tonumber(ARGV[2]) -local current = redis.call('get', key); -if current and tonumber(current) >= count then - return tonumber(current); -end -current = redis.call('incr', key) -if tonumber(current) == 1 then - redis.call('expire', key, time) -end -return tonumber(current);`) diff --git a/src/framework/middleware/authorize_oauth2.go b/src/framework/middleware/authorize_oauth2.go new file mode 100644 index 00000000..4705d6b7 --- /dev/null +++ b/src/framework/middleware/authorize_oauth2.go @@ -0,0 +1,66 @@ +package middleware + +import ( + "fmt" + + "github.com/gin-gonic/gin" + + "be.ems/src/framework/constants" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" + "be.ems/src/framework/token" +) + +// AuthorizeOauth2 客户端授权认证校验 +// +// scope 客户端授权范围,例如:[]string{"read","write"} +func AuthorizeOauth2(scope []string) gin.HandlerFunc { + return func(c *gin.Context) { + // 获取请求头标识信息 + tokenStr := reqctx.Authorization(c) + if tokenStr == "" { + c.JSON(401, resp.CodeMsg(401003, "authorization token is empty")) + c.Abort() // 停止执行后续的处理函数 + return + } + + // 验证令牌 + claims, err := token.Oauth2TokenVerify(tokenStr, "access") + if err != nil { + c.JSON(401, resp.CodeMsg(401001, err.Error())) + c.Abort() // 停止执行后续的处理函数 + return + } + + // 获取缓存的用户信息 + info := token.Oauth2InfoGet(claims) + if info.ClientId == "" { + c.JSON(401, resp.CodeMsg(401002, "invalid login user information")) + c.Abort() // 停止执行后续的处理函数 + return + } + c.Set(constants.CTX_LOGIN_OAUTH2, info) + + // 客户端权限校验 + if scope != nil { + var hasScope bool = false + for _, item := range info.Scope { + for _, v := range scope { + if item == v { + hasScope = true + break + } + } + } + if !hasScope { + msg := fmt.Sprintf("unauthorized access %s %s", c.Request.Method, c.Request.RequestURI) + c.JSON(403, resp.CodeMsg(403001, msg)) + c.Abort() // 停止执行后续的处理函数 + return + } + } + + // 调用下一个处理程序 + c.Next() + } +} diff --git a/src/framework/middleware/pre_authorize.go b/src/framework/middleware/authorize_user.go similarity index 82% rename from src/framework/middleware/pre_authorize.go rename to src/framework/middleware/authorize_user.go index 5d069e86..f34d487e 100644 --- a/src/framework/middleware/pre_authorize.go +++ b/src/framework/middleware/authorize_user.go @@ -1,17 +1,17 @@ package middleware import ( + "fmt" "strings" + "github.com/gin-gonic/gin" + "be.ems/src/framework/config" "be.ems/src/framework/constants" - "be.ems/src/framework/i18n" "be.ems/src/framework/reqctx" "be.ems/src/framework/resp" "be.ems/src/framework/token" "be.ems/src/framework/utils/parse" - - "github.com/gin-gonic/gin" ) /**无Token可访问白名单 */ @@ -27,7 +27,7 @@ var URL_WHITE_LIST = []string{ "/oauth/token", } -// PreAuthorize 用户身份授权认证校验 +// AuthorizeUser 用户身份授权认证校验 // // 只需含有其中角色 "hasRoles": {"xxx"}, // @@ -36,7 +36,7 @@ var URL_WHITE_LIST = []string{ // 同时匹配其中角色 "matchRoles": {"xxx"}, // // 同时匹配其中权限 "matchPerms": {"xxx"}, -func PreAuthorize(options map[string][]string) gin.HandlerFunc { +func AuthorizeUser(options map[string][]string) gin.HandlerFunc { return func(c *gin.Context) { // 登录认证,默认打开 enable := parse.Boolean(config.Get("serverLoginAuth")) @@ -51,12 +51,9 @@ func PreAuthorize(options map[string][]string) gin.HandlerFunc { return } - language := reqctx.AcceptLanguage(c) - - requestURI := c.Request.RequestURI - // 判断白名单 isWhite := false + requestURI := c.Request.RequestURI for _, w := range URL_WHITE_LIST { if strings.Contains(requestURI, w) { isWhite = true @@ -71,42 +68,39 @@ func PreAuthorize(options map[string][]string) gin.HandlerFunc { // 获取请求头标识信息 tokenStr := reqctx.Authorization(c) if tokenStr == "" { - c.JSON(401, resp.CodeMsg(401, i18n.TKey(language, "app.common.err401"))) + c.JSON(401, resp.CodeMsg(401003, "authorization token is empty")) c.Abort() // 停止执行后续的处理函数 return } // 验证令牌 - claims, err := token.Verify(tokenStr) + claims, err := token.UserTokenVerify(tokenStr, "access") if err != nil { - c.JSON(401, resp.CodeMsg(401, err.Error())) + c.JSON(401, resp.CodeMsg(401001, err.Error())) c.Abort() // 停止执行后续的处理函数 return } // 获取缓存的用户信息 - loginUser := token.Info(claims) - if loginUser.UserId <= 0 { - c.JSON(401, resp.CodeMsg(401, i18n.TKey(language, "app.common.err401"))) + info := token.UserInfoGet(claims) + if info.UserId <= 0 { + c.JSON(401, resp.CodeMsg(401002, "invalid login user information")) c.Abort() // 停止执行后续的处理函数 return } - - // 检查刷新有效期后存入上下文 - token.RefreshIn(&loginUser) - c.Set(constants.CTX_LOGIN_USER, loginUser) + c.Set(constants.CTX_LOGIN_USER, info) // 登录用户角色权限校验 if options != nil { var roles []string - for _, item := range loginUser.User.Roles { + for _, item := range info.User.Roles { roles = append(roles, item.RoleKey) } - perms := loginUser.Permissions + perms := info.Permissions verifyOk := verifyRolePermission(roles, perms, options) if !verifyOk { - msg := i18n.TTemplate(language, "app.common.err403", map[string]any{"method": c.Request.Method, "requestURI": requestURI}) - c.JSON(403, resp.CodeMsg(403, msg)) + msg := fmt.Sprintf("unauthorized access %s %s", c.Request.Method, c.Request.RequestURI) + c.JSON(403, resp.CodeMsg(403001, msg)) c.Abort() // 停止执行后续的处理函数 return } @@ -125,7 +119,7 @@ func PreAuthorize(options map[string][]string) gin.HandlerFunc { // // options 参数 func verifyRolePermission(roles, perms []string, options map[string][]string) bool { - // 直接放行 管理员角色或任意权限 + // 直接放行 系统管理员角色或任意权限 if contains(roles, constants.SYS_ROLE_SYSTEM_KEY) || contains(perms, constants.SYS_PERMISSION_SYSTEM) { return true } diff --git a/src/framework/middleware/operate_log.go b/src/framework/middleware/operate_log.go index 75542f40..f920fb70 100644 --- a/src/framework/middleware/operate_log.go +++ b/src/framework/middleware/operate_log.go @@ -134,7 +134,7 @@ func OperateLog(options Options) gin.HandlerFunc { contentDisposition := c.Writer.Header().Get("Content-Disposition") contentType := c.Writer.Header().Get("Content-Type") content := contentType + contentDisposition - msg := fmt.Sprintf(`{"status":"%d","size":"%d","content-type":"%s"}`, status, c.Writer.Size(), content) + msg := fmt.Sprintf(`{"status":"%d","size":%d,"content-type":"%s"}`, status, c.Writer.Size(), content) operaLog.OperaMsg = msg } diff --git a/src/framework/middleware/repeat/repeat.go b/src/framework/middleware/repeat/repeat.go index 78a09447..dd238852 100644 --- a/src/framework/middleware/repeat/repeat.go +++ b/src/framework/middleware/repeat/repeat.go @@ -77,7 +77,7 @@ func RepeatSubmit(interval int64) gin.HandlerFunc { logger.Errorf("RepeatSubmit rp json marshal err: %v", err) } // 保存请求时间和参数 - redis.SetByExpire("", repeatKey, string(rpJSON), time.Duration(interval)*time.Second) + redis.Set("", repeatKey, string(rpJSON), time.Duration(interval)*time.Second) // 调用下一个处理程序 c.Next() diff --git a/src/framework/middleware/repeat_submit.go b/src/framework/middleware/repeat_submit.go index 79753319..b1acff24 100644 --- a/src/framework/middleware/repeat_submit.go +++ b/src/framework/middleware/repeat_submit.go @@ -76,7 +76,7 @@ func RepeatSubmit(interval int64) gin.HandlerFunc { logger.Errorf("RepeatSubmit rp json marshal err: %v", err) } // 保存请求时间和参数 - _ = redis.SetByExpire("", repeatKey, string(rpJSON), time.Duration(interval)*time.Second) + _ = redis.Set("", repeatKey, string(rpJSON), time.Duration(interval)*time.Second) // 调用下一个处理程序 c.Next() diff --git a/src/framework/reqctx/auth.go b/src/framework/reqctx/auth.go index f88149a7..20fd5552 100644 --- a/src/framework/reqctx/auth.go +++ b/src/framework/reqctx/auth.go @@ -12,12 +12,12 @@ import ( ) // LoginUser 登录用户信息 -func LoginUser(c *gin.Context) (token.TokenInfo, error) { +func LoginUser(c *gin.Context) (token.UserInfo, error) { value, exists := c.Get(constants.CTX_LOGIN_USER) if exists && value != nil { - return value.(token.TokenInfo), nil + return value.(token.UserInfo), nil } - return token.TokenInfo{}, fmt.Errorf("invalid login user information") + return token.UserInfo{}, fmt.Errorf("invalid login user information") } // LoginUserToUserID 登录用户信息-用户ID @@ -58,14 +58,14 @@ func LoginUserByContainRoles(c *gin.Context, target string) bool { // LoginUserByContainPerms 登录用户信息-包含权限标识 func LoginUserByContainPerms(c *gin.Context, target string) bool { - loginUser, err := LoginUser(c) + info, err := LoginUser(c) if err != nil { return false } - if config.IsSystemUser(loginUser.UserId) { + if config.IsSystemUser(info.UserId) { return true } - perms := loginUser.Permissions + perms := info.Permissions for _, str := range perms { if str == target { return true diff --git a/src/framework/reqctx/context.go b/src/framework/reqctx/context.go index dc597025..85f27e3b 100644 --- a/src/framework/reqctx/context.go +++ b/src/framework/reqctx/context.go @@ -73,11 +73,11 @@ func Authorization(c *gin.Context) string { return "" } // 拆分 Authorization 请求头,提取 JWT 令牌部分 - arr := strings.SplitN(authHeader, constants.HEADER_PREFIX, 2) - if len(arr) < 2 { - return "" + tokenStr := strings.Replace(authHeader, constants.HEADER_PREFIX, "", 1) + if len(tokenStr) > 64 { + return strings.TrimSpace(tokenStr) // 去除可能存在的空格 } - return arr[1] + return "" } // AcceptLanguage 解析客户端接收语言 zh:中文 en: 英文 diff --git a/src/framework/reqctx/param.go b/src/framework/reqctx/param.go index a74390c8..400605d2 100644 --- a/src/framework/reqctx/param.go +++ b/src/framework/reqctx/param.go @@ -1,9 +1,12 @@ package reqctx import ( + "fmt" + "github.com/gin-gonic/gin" "be.ems/src/framework/ip2region" + "be.ems/src/framework/utils/crypto" "be.ems/src/framework/utils/ua" ) @@ -33,3 +36,9 @@ func UaOsBrowser(c *gin.Context) (string, string) { } return os, browser } + +// DeviceFingerprint 设备指纹信息 +func DeviceFingerprint(c *gin.Context, v any) string { + str := fmt.Sprintf("%v:%s", v, c.Request.UserAgent()) + return crypto.SHA256ToBase64(str) +} diff --git a/src/framework/resp/api.go b/src/framework/resp/api.go index eff18f28..4b6422cf 100644 --- a/src/framework/resp/api.go +++ b/src/framework/resp/api.go @@ -2,17 +2,17 @@ package resp const ( // CODE_ERROR 响应-code错误失败 - CODE_ERROR = 0 + CODE_ERROR = 400001 // MSG_ERROR 响应-msg错误失败 MSG_ERROR = "error" // CODE_SUCCESS 响应-msg正常成功 - CODE_SUCCESS = 1 + CODE_SUCCESS = 200001 // MSG_SUCCCESS 响应-code正常成功 MSG_SUCCCESS = "success" // 响应-code加密数据 - CODE_ENCRYPT = 2 + CODE_ENCRYPT = 200999 // 响应-msg加密数据 MSG_ENCRYPT = "encrypt" ) diff --git a/src/framework/token/oauth2_info.go b/src/framework/token/oauth2_info.go new file mode 100644 index 00000000..bc962ec5 --- /dev/null +++ b/src/framework/token/oauth2_info.go @@ -0,0 +1,14 @@ +package token + +// Oauth2Info 第三方客户端令牌信息对象 +type Oauth2Info struct { + DeviceId string `json:"deviceId"` // 用户设备标识 + ClientId string `json:"clientId"` // 客户端ID + LoginTime int64 `json:"loginTime"` // 登录时间时间戳 + ExpireTime int64 `json:"expireTime"` // 过期时间时间戳 + LoginIp string `json:"loginIp"` // 登录IP地址 x.x.x.x + LoginLocation string `json:"loginLocation"` // 登录地点 xx xx + Browser string `json:"browser"` // 浏览器类型 + OS string `json:"os"` // 操作系统 + Scope []string `json:"scope"` // 权限列表 +} diff --git a/src/framework/token/oauth2_token.go b/src/framework/token/oauth2_token.go new file mode 100644 index 00000000..cfac0fd5 --- /dev/null +++ b/src/framework/token/oauth2_token.go @@ -0,0 +1,167 @@ +package token + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/golang-jwt/jwt/v5" + + "be.ems/src/framework/config" + "be.ems/src/framework/constants" + "be.ems/src/framework/database/redis" + "be.ems/src/framework/logger" + "be.ems/src/framework/utils/parse" +) + +// Oauth2TokenCreate 生成令牌 +// clientId 客户端ID +// deviceFingerprint 设备指纹 SHA256 +// tokenType 令牌类型 access:访问令牌 refresh:刷新令牌 +func Oauth2TokenCreate(clientId, deviceFingerprint, tokenType string) (string, int64) { + // 令牌算法 HS256 HS384 HS512 + algorithm := config.Get("jwt.algorithm").(string) + var method *jwt.SigningMethodHMAC + switch algorithm { + case "HS512": + method = jwt.SigningMethodHS512 + case "HS384": + method = jwt.SigningMethodHS384 + default: // 包含HS256和其他所有情况 + method = jwt.SigningMethodHS256 + } + + // 生成令牌设置密钥 + secret := fmt.Sprint(config.Get("jwt.secret")) + // 设置令牌过期时间 + now := time.Now() + exp := now + if tokenType == "access" { + expiresIn := time.Duration(parse.Number(config.Get("jwt.expiresIn"))) + exp = now.Add(expiresIn * time.Minute) + secret = "Oauth2_Access:" + secret + } + if tokenType == "refresh" { + refreshIn := time.Duration(parse.Number(config.Get("jwt.refreshIn"))) + exp = now.Add(refreshIn * time.Minute) + secret = "Oauth2_Refresh:" + secret + } + + // 生成令牌负荷绑定uuid标识 + jwtToken := jwt.NewWithClaims(method, jwt.MapClaims{ + constants.JWT_DEVICE_ID: deviceFingerprint, + constants.JWT_CLIENT_ID: clientId, + "exp": exp.Unix(), // 过期时间 + "iat": now.Unix(), // 签发时间 + "nbf": now.Unix(), // 生效时间 + }) + + tokenStr, err := jwtToken.SignedString([]byte(secret)) + if err != nil { + logger.Infof("jwt sign err : %v", err) + return "", 0 + } + expSeconds := int64(exp.Sub(now).Seconds()) + return tokenStr, expSeconds +} + +// Oauth2TokenVerify 校验令牌是否有效 +// tokenType 令牌类型 access:访问令牌 refresh:刷新令牌 +func Oauth2TokenVerify(tokenStr, tokenType string) (jwt.MapClaims, error) { + jwtToken, err := jwt.Parse(tokenStr, func(jToken *jwt.Token) (any, error) { + // 判断加密算法是预期的加密算法 + if _, ok := jToken.Method.(*jwt.SigningMethodHMAC); ok { + secret := config.Get("jwt.secret").(string) + if tokenType == "access" { + secret = "Oauth2_Access:" + secret + } + if tokenType == "refresh" { + secret = "Oauth2_Refresh:" + secret + } + return []byte(secret), nil + } + return nil, jwt.ErrSignatureInvalid + }) + if err != nil { + logger.Errorf("Token Verify Err: %v", err) + return nil, fmt.Errorf("token invalid") + } + // 如果解析负荷成功并通过签名校验 + claims, ok := jwtToken.Claims.(jwt.MapClaims) + if ok && jwtToken.Valid { + return claims, nil + } + return nil, fmt.Errorf("token valid error") +} + +// Oauth2InfoRemove 清除登录第三方客户端信息 +func Oauth2InfoRemove(tokenStr string) (string, error) { + claims, err := Oauth2TokenVerify(tokenStr, "access") + if err != nil { + logger.Errorf("token verify err %v", err) + return "", err + } + deviceId, ok := claims[constants.JWT_DEVICE_ID] + if ok && deviceId != "" { + // 清除缓存KEY + tokenKey := constants.CACHE_OAUTH2_DEVICE + ":" + fmt.Sprint(deviceId) + return fmt.Sprint(claims[constants.JWT_CLIENT_ID]), redis.Del("", tokenKey) + } + return "", fmt.Errorf("token invalid") +} + +// Oauth2InfoCreate 生成访问第三方客户端信息缓存 +func Oauth2InfoCreate(info *Oauth2Info, deviceFingerprint string, ilobArr [4]string) { + info.DeviceId = deviceFingerprint + + // 设置请求登录客户端 + info.LoginIp = ilobArr[0] + info.LoginLocation = ilobArr[1] + info.OS = ilobArr[2] + info.Browser = ilobArr[3] + + expiresIn := time.Duration(parse.Number(config.Get("jwt.expiresIn"))) + now := time.Now() + exp := now.Add(expiresIn * time.Minute) + info.LoginTime = now.UnixMilli() + info.ExpireTime = exp.UnixMilli() + // 登录信息标识缓存 + tokenKey := constants.CACHE_OAUTH2_DEVICE + ":" + info.DeviceId + jsonBytes, err := json.Marshal(info) + if err != nil { + return + } + _ = redis.Set("", tokenKey, string(jsonBytes), expiresIn*time.Minute) +} + +// Oauth2InfoUpdate 更新访问第三方客户端信息缓存 +func Oauth2InfoUpdate(info Oauth2Info) { + // 登录信息标识缓存 + tokenKey := constants.CACHE_OAUTH2_DEVICE + ":" + info.DeviceId + jsonBytes, err := json.Marshal(info) + if err != nil { + return + } + expiresIn, _ := redis.GetExpire("", tokenKey) + expiration := time.Duration(expiresIn) * time.Second + _ = redis.Set("", tokenKey, string(jsonBytes), expiration) +} + +// Oauth2InfoGet 缓存的登录第三方客户端信息 +func Oauth2InfoGet(claims jwt.MapClaims) Oauth2Info { + info := Oauth2Info{} + deviceId := fmt.Sprint(claims[constants.JWT_DEVICE_ID]) + tokenKey := constants.CACHE_OAUTH2_DEVICE + ":" + deviceId + hasKey, err := redis.Has("", tokenKey) + if hasKey > 0 && err == nil { + infoStr, err := redis.Get("", tokenKey) + if infoStr == "" || err != nil { + return info + } + if err := json.Unmarshal([]byte(infoStr), &info); err != nil { + logger.Errorf("info json err : %v", err) + return info + } + } + return info +} diff --git a/src/framework/token/token.go b/src/framework/token/token.go deleted file mode 100644 index 2b7d5a69..00000000 --- a/src/framework/token/token.go +++ /dev/null @@ -1,152 +0,0 @@ -package token - -import ( - "encoding/json" - "fmt" - "time" - - "github.com/golang-jwt/jwt/v5" - - "be.ems/src/framework/config" - "be.ems/src/framework/constants" - "be.ems/src/framework/database/redis" - "be.ems/src/framework/logger" - "be.ems/src/framework/utils/generate" -) - -// Remove 清除登录用户信息UUID -func Remove(token string) string { - claims, err := Verify(token) - if err != nil { - logger.Errorf("token verify err %v", err) - return "" - } - // 清除缓存KEY - uuid := claims[constants.JWT_UUID].(string) - tokenKey := constants.CACHE_LOGIN_TOKEN + ":" + uuid - hasKey, err := redis.Has("", tokenKey) - if hasKey > 0 && err == nil { - _ = redis.Del("", tokenKey) - } - return claims[constants.JWT_USER_NAME].(string) -} - -// Create 令牌生成 -func Create(tokenInfo *TokenInfo, ilobArr [4]string) string { - // 生成用户唯一token 32位 - tokenInfo.UUID = generate.Code(32) - tokenInfo.LoginTime = time.Now().UnixMilli() - - // 设置请求用户登录客户端 - tokenInfo.LoginIp = ilobArr[0] - tokenInfo.LoginLocation = ilobArr[1] - tokenInfo.OS = ilobArr[2] - tokenInfo.Browser = ilobArr[3] - - // 设置新登录IP和登录时间 - tokenInfo.User.LoginIp = tokenInfo.LoginIp - tokenInfo.User.LoginTime = tokenInfo.LoginTime - - // 设置用户令牌有效期并存入缓存 - Cache(tokenInfo) - - // 令牌算法 HS256 HS384 HS512 - algorithm := config.Get("jwt.algorithm").(string) - var method *jwt.SigningMethodHMAC - switch algorithm { - case "HS512": - method = jwt.SigningMethodHS512 - case "HS384": - method = jwt.SigningMethodHS384 - case "HS256": - default: - method = jwt.SigningMethodHS256 - } - // 生成令牌负荷绑定uuid标识 - jwtToken := jwt.NewWithClaims(method, jwt.MapClaims{ - constants.JWT_UUID: tokenInfo.UUID, - constants.JWT_USER_ID: tokenInfo.UserId, - constants.JWT_USER_NAME: tokenInfo.User.UserName, - "ait": tokenInfo.LoginTime, - }) - - // 生成令牌设置密钥 - secret := config.Get("jwt.secret").(string) - tokenStr, err := jwtToken.SignedString([]byte(secret)) - if err != nil { - logger.Infof("jwt sign err : %v", err) - return "" - } - return tokenStr -} - -// Cache 缓存登录用户信息 -func Cache(tokenInfo *TokenInfo) { - // 计算配置的有效期 - expTime := config.Get("jwt.expiresIn").(int) - expTimestamp := time.Duration(expTime) * time.Minute - iatTimestamp := time.Now().UnixMilli() - tokenInfo.LoginTime = iatTimestamp - tokenInfo.ExpireTime = iatTimestamp + expTimestamp.Milliseconds() - tokenInfo.User.Password = "" - // 登录信息标识缓存 - tokenKey := constants.CACHE_LOGIN_TOKEN + ":" + tokenInfo.UUID - jsonBytes, err := json.Marshal(tokenInfo) - if err != nil { - return - } - _ = redis.SetByExpire("", tokenKey, string(jsonBytes), expTimestamp) -} - -// RefreshIn 验证令牌有效期,相差不足xx分钟,自动刷新缓存 -func RefreshIn(loginUser *TokenInfo) { - // 相差不足xx分钟,自动刷新缓存 - refreshTime := config.Get("jwt.refreshIn").(int) - refreshTimestamp := time.Duration(refreshTime) * time.Minute - // 过期时间 - expireTimestamp := loginUser.ExpireTime - currentTimestamp := time.Now().UnixMilli() - if expireTimestamp-currentTimestamp <= refreshTimestamp.Milliseconds() { - Cache(loginUser) - } -} - -// Verify 校验令牌是否有效 -func Verify(token string) (jwt.MapClaims, error) { - jwtToken, err := jwt.Parse(token, func(jToken *jwt.Token) (any, error) { - // 判断加密算法是预期的加密算法 - if _, ok := jToken.Method.(*jwt.SigningMethodHMAC); ok { - secret := config.Get("jwt.secret").(string) - return []byte(secret), nil - } - return nil, jwt.ErrSignatureInvalid - }) - if err != nil { - logger.Errorf("Token Verify Err: %v", err) - return nil, fmt.Errorf("token invalid") - } - // 如果解析负荷成功并通过签名校验 - if claims, ok := jwtToken.Claims.(jwt.MapClaims); ok && jwtToken.Valid { - return claims, nil - } - return nil, fmt.Errorf("token valid error") -} - -// Info 缓存的登录用户信息 -func Info(claims jwt.MapClaims) TokenInfo { - tokenInfo := TokenInfo{} - uuid := claims[constants.JWT_UUID].(string) - tokenKey := constants.CACHE_LOGIN_TOKEN + ":" + uuid - hasKey, err := redis.Has("", tokenKey) - if hasKey > 0 && err == nil { - infoStr, err := redis.Get("", tokenKey) - if infoStr == "" || err != nil { - return tokenInfo - } - if err := json.Unmarshal([]byte(infoStr), &tokenInfo); err != nil { - logger.Errorf("info json err : %v", err) - return tokenInfo - } - } - return tokenInfo -} diff --git a/src/framework/token/token_info.go b/src/framework/token/user_info.go similarity index 85% rename from src/framework/token/token_info.go rename to src/framework/token/user_info.go index 77ef68a8..918858db 100644 --- a/src/framework/token/token_info.go +++ b/src/framework/token/user_info.go @@ -2,9 +2,9 @@ package token import systemModel "be.ems/src/modules/system/model" -// TokenInfo 令牌信息对象 -type TokenInfo struct { - UUID string `json:"uuid"` // 用户唯一标识 +// UserInfo 系统用户令牌信息对象 +type UserInfo struct { + DeviceId string `json:"deviceId"` // 用户设备标识 UserId int64 `json:"userId"` // 用户ID DeptId int64 `json:"deptId"` // 部门ID LoginTime int64 `json:"loginTime"` // 登录时间时间戳 diff --git a/src/framework/token/user_token.go b/src/framework/token/user_token.go new file mode 100644 index 00000000..e068a111 --- /dev/null +++ b/src/framework/token/user_token.go @@ -0,0 +1,173 @@ +package token + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/golang-jwt/jwt/v5" + + "be.ems/src/framework/config" + "be.ems/src/framework/constants" + "be.ems/src/framework/database/redis" + "be.ems/src/framework/logger" + "be.ems/src/framework/utils/parse" +) + +// UserTokenCreate 生成令牌 +// userId 用户ID +// deviceFingerprint 设备指纹 SHA256 +// tokenType 令牌类型 access:访问令牌 refresh:刷新令牌 +func UserTokenCreate(userId int64, deviceFingerprint, tokenType string) (string, int64) { + // 令牌算法 HS256 HS384 HS512 + algorithm := config.Get("jwt.algorithm").(string) + var method *jwt.SigningMethodHMAC + switch algorithm { + case "HS512": + method = jwt.SigningMethodHS512 + case "HS384": + method = jwt.SigningMethodHS384 + default: // 包含HS256和其他所有情况 + method = jwt.SigningMethodHS256 + } + + // 生成令牌设置密钥 + secret := fmt.Sprint(config.Get("jwt.secret")) + // 设置令牌过期时间 + now := time.Now() + exp := now + if tokenType == "access" { + expiresIn := time.Duration(parse.Number(config.Get("jwt.expiresIn"))) + exp = now.Add(expiresIn * time.Minute) + secret = "User_Access:" + secret + } + if tokenType == "refresh" { + refreshIn := time.Duration(parse.Number(config.Get("jwt.refreshIn"))) + exp = now.Add(refreshIn * time.Minute) + secret = "User_Refresh:" + secret + } + + // 生成令牌负荷绑定uuid标识 + jwtToken := jwt.NewWithClaims(method, jwt.MapClaims{ + constants.JWT_DEVICE_ID: deviceFingerprint, + constants.JWT_USER_ID: userId, + "exp": exp.Unix(), // 过期时间 + "iat": now.Unix(), // 签发时间 + "nbf": now.Add(-10 * time.Second).Unix(), // 生效时间 + }) + + tokenStr, err := jwtToken.SignedString([]byte(secret)) + if err != nil { + logger.Infof("jwt sign err : %v", err) + return "", 0 + } + expSeconds := int64(exp.Sub(now).Seconds()) + return tokenStr, expSeconds +} + +// UserTokenVerify 校验令牌是否有效 +// tokenType 令牌类型 access:访问令牌 refresh:刷新令牌 +func UserTokenVerify(tokenStr string, tokenType string) (jwt.MapClaims, error) { + jwtToken, err := jwt.Parse(tokenStr, func(jToken *jwt.Token) (any, error) { + // 判断加密算法是预期的加密算法 + if _, ok := jToken.Method.(*jwt.SigningMethodHMAC); ok { + secret := config.Get("jwt.secret").(string) + if tokenType == "access" { + secret = "User_Access:" + secret + } + if tokenType == "refresh" { + secret = "User_Refresh:" + secret + } + return []byte(secret), nil + } + return nil, jwt.ErrSignatureInvalid + }) + if err != nil { + logger.Errorf("Token Verify Err: %v", err) + return nil, fmt.Errorf("token invalid") + } + // 如果解析负荷成功并通过签名校验 + claims, ok := jwtToken.Claims.(jwt.MapClaims) + if ok && jwtToken.Valid { + return claims, nil + } + return nil, fmt.Errorf("token valid error") +} + +// UserInfoRemove 清除访问用户信息缓存 +func UserInfoRemove(tokenStr string) (string, error) { + claims, err := UserTokenVerify(tokenStr, "access") + if err != nil { + logger.Errorf("token verify err %v", err) + return "", err + } + info := UserInfoGet(claims) + if info.User.UserName != "" { + // 清除缓存KEY + deviceId := fmt.Sprint(claims[constants.JWT_DEVICE_ID]) + tokenKey := constants.CACHE_TOKEN_DEVICE + ":" + deviceId + return info.User.UserName, redis.Del("", tokenKey) + } + return "", fmt.Errorf("token invalid") +} + +// UserInfoCreate 生成访问用户信息缓存 +func UserInfoCreate(info *UserInfo, deviceFingerprint string, ilobArr [4]string) { + info.DeviceId = deviceFingerprint + + // 设置请求用户登录客户端 + info.LoginIp = ilobArr[0] + info.LoginLocation = ilobArr[1] + info.OS = ilobArr[2] + info.Browser = ilobArr[3] + + expiresIn := time.Duration(parse.Number(config.Get("jwt.expiresIn"))) + now := time.Now() + exp := now.Add(expiresIn * time.Minute) + info.LoginTime = now.UnixMilli() + info.ExpireTime = exp.UnixMilli() + // 设置新登录IP和登录时间 + info.User.LoginIp = info.LoginIp + info.User.LoginTime = info.LoginTime + info.User.Password = "" + // 登录信息标识缓存 + tokenKey := constants.CACHE_TOKEN_DEVICE + ":" + info.DeviceId + jsonBytes, err := json.Marshal(info) + if err != nil { + return + } + _ = redis.Set("", tokenKey, string(jsonBytes), expiresIn*time.Minute) +} + +// UserInfoUpdate 更新访问用户信息缓存 +func UserInfoUpdate(info UserInfo) { + info.User.Password = "" + // 登录信息标识缓存 + tokenKey := constants.CACHE_TOKEN_DEVICE + ":" + info.DeviceId + jsonBytes, err := json.Marshal(info) + if err != nil { + return + } + expiresIn, _ := redis.GetExpire("", tokenKey) + expiration := time.Duration(expiresIn) * time.Second + _ = redis.Set("", tokenKey, string(jsonBytes), expiration) +} + +// UserInfoGet 缓存的访问用户信息 +func UserInfoGet(claims jwt.MapClaims) UserInfo { + info := UserInfo{} + deviceId := fmt.Sprint(claims[constants.JWT_DEVICE_ID]) + tokenKey := constants.CACHE_TOKEN_DEVICE + ":" + deviceId + hasKey, err := redis.Has("", tokenKey) + if hasKey > 0 && err == nil { + infoStr, err := redis.Get("", tokenKey) + if infoStr == "" || err != nil { + return info + } + if err := json.Unmarshal([]byte(infoStr), &info); err != nil { + logger.Errorf("info json err : %v", err) + return info + } + } + return info +} diff --git a/src/framework/utils/crypto/hash.go b/src/framework/utils/crypto/hash.go new file mode 100644 index 00000000..9cf95c84 --- /dev/null +++ b/src/framework/utils/crypto/hash.go @@ -0,0 +1,31 @@ +package crypto + +import ( + "crypto/hmac" + "crypto/md5" + "crypto/sha256" + "encoding/base64" + "encoding/hex" + "fmt" +) + +// SHA256ToBase64 编码字符串 +func SHA256ToBase64(str string) string { + hash := sha256.Sum256([]byte(str)) + return base64.URLEncoding.EncodeToString(hash[:]) +} + +// SHA256Hmac HMAC-SHA256算法 +func SHA256Hmac(key string, data string) string { + mac := hmac.New(sha256.New, []byte(key)) + mac.Write([]byte(data)) + return hex.EncodeToString(mac.Sum(nil)) +} + +// MD5 md5加密 +func MD5(str string) (md5str string) { + data := []byte(str) + has := md5.Sum(data) + md5str = fmt.Sprintf("%x", has) + return md5str +} diff --git a/src/modules/auth/auth.go b/src/modules/auth/auth.go index 704d2c2e..cf01e504 100644 --- a/src/modules/auth/auth.go +++ b/src/modules/auth/auth.go @@ -19,9 +19,9 @@ func Setup(router *gin.Engine) { guideGroup := router.Group("/bootloader") { guideGroup.POST("", controller.NewBootloader.Start) - guideGroup.PUT("", middleware.PreAuthorize(nil), controller.NewBootloader.Done) - guideGroup.DELETE("", middleware.PreAuthorize(nil), controller.NewBootloader.Reset) - guideGroup.PUT("/account", middleware.PreAuthorize(nil), controller.NewBootloader.Account) + guideGroup.PUT("", middleware.AuthorizeUser(nil), controller.NewBootloader.Done) + guideGroup.DELETE("", middleware.AuthorizeUser(nil), controller.NewBootloader.Reset) + guideGroup.PUT("/account", middleware.AuthorizeUser(nil), controller.NewBootloader.Account) } // 验证码操作 @@ -34,20 +34,17 @@ func Setup(router *gin.Engine) { controller.NewCaptcha.Image, ) - // 账号身份操作处理 + // 账号身份操作 { - router.POST("/login", + router.POST("/auth/login", middleware.RateLimit(middleware.LimitOption{ Time: 180, Count: 15, Type: middleware.LIMIT_IP, }), - middleware.CryptoApi(true, true), controller.NewAccount.Login, ) - router.GET("/me", middleware.PreAuthorize(nil), controller.NewAccount.Me) - router.GET("/router", middleware.PreAuthorize(nil), controller.NewAccount.Router) - router.POST("/logout", + router.POST("/auth/logout", middleware.RateLimit(middleware.LimitOption{ Time: 120, Count: 15, @@ -55,17 +52,32 @@ func Setup(router *gin.Engine) { }), controller.NewAccount.Logout, ) + router.POST("/auth/refresh-token", + middleware.RateLimit(middleware.LimitOption{ + Time: 60, + Count: 5, + Type: middleware.LIMIT_IP, + }), + controller.NewAccount.RefreshToken, + ) + router.GET("/me", + middleware.AuthorizeUser(nil), + controller.NewAccount.Me, + ) + router.GET("/router", + middleware.AuthorizeUser(nil), + controller.NewAccount.Router, + ) } // 账号注册操作 { - router.POST("/register", + router.POST("/auth/register", middleware.RateLimit(middleware.LimitOption{ Time: 300, Count: 10, Type: middleware.LIMIT_IP, }), - middleware.CryptoApi(true, true), controller.NewRegister.Register, ) } diff --git a/src/modules/auth/controller/account.go b/src/modules/auth/controller/account.go index eae8fe94..8592b597 100644 --- a/src/modules/auth/controller/account.go +++ b/src/modules/auth/controller/account.go @@ -2,7 +2,7 @@ package controller import ( "fmt" - "strings" + "time" "be.ems/src/framework/config" "be.ems/src/framework/constants" @@ -10,6 +10,7 @@ import ( "be.ems/src/framework/reqctx" "be.ems/src/framework/resp" "be.ems/src/framework/token" + "be.ems/src/framework/utils/parse" "be.ems/src/modules/auth/model" "be.ems/src/modules/auth/service" systemModelVO "be.ems/src/modules/system/model/vo" @@ -34,7 +35,7 @@ type AccountController struct { // Login 系统登录 // -// POST /login +// POST /auth/login // // @Tags common/authorization // @Accept json @@ -43,13 +44,13 @@ type AccountController struct { // @Success 200 {object} object "Response Results" // @Summary System Login // @Description System Login -// @Router /login [post] +// @Router /auth/login [post] func (s AccountController) Login(c *gin.Context) { language := reqctx.AcceptLanguage(c) var body model.LoginBody if err := c.ShouldBindJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) - c.JSON(422, resp.CodeMsg(40422, errMsgs)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) return } @@ -59,27 +60,31 @@ func (s AccountController) Login(c *gin.Context) { // 校验验证码 根据错误信息,创建系统访问记录 if err := s.accountService.ValidateCaptcha(body.Code, body.UUID); err != nil { - msg := fmt.Sprintf("%s code: %s", err.Error(), body.Code) + msg := fmt.Sprintf("%s code %s", err.Error(), body.Code) s.sysLogLoginService.Insert( body.Username, constants.STATUS_NO, msg, [4]string{ipaddr, location, os, browser}, ) - c.JSON(400, resp.CodeMsg(40012, i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } // 登录用户信息 - loginUser, err := s.accountService.ByUsername(body.Username, body.Password) + info, err := s.accountService.ByUsername(body.Username, body.Password) if err != nil { + s.sysLogLoginService.Insert( + body.Username, constants.STATUS_NO, err.Error(), + [4]string{ipaddr, location, os, browser}, + ) c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } data := map[string]any{} - if !config.IsSystemUser(loginUser.UserId) { + if !config.IsSystemUser(info.UserId) { // 强制改密码 - forcePasswdChange, err := s.accountService.PasswordCountOrExpireTime(loginUser.User.LoginCount, loginUser.User.PasswordUpdateTime) + forcePasswdChange, err := s.accountService.PasswordCountOrExpireTime(info.User.LoginCount, info.User.PasswordUpdateTime) if err != nil { c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return @@ -89,25 +94,132 @@ func (s AccountController) Login(c *gin.Context) { } } - // 生成令牌,创建系统访问记录 - tokenStr := token.Create(&loginUser, [4]string{ipaddr, location, os, browser}) - if tokenStr == "" { - c.JSON(200, resp.Err(nil)) + deviceFingerprint := reqctx.DeviceFingerprint(c, info.UserId) + + // 生成访问令牌 + accessToken, expiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "access") + if accessToken == "" || expiresIn == 0 { + c.JSON(200, resp.ErrMsg("token generation failed")) + return + } + // 生成刷新令牌 + refreshToken, refreshExpiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "refresh") + + // 记录令牌,创建系统访问记录 + token.UserInfoCreate(&info, deviceFingerprint, [4]string{ipaddr, location, os, browser}) + s.accountService.UpdateLoginDateAndIP(info) + s.sysLogLoginService.Insert( + body.Username, constants.STATUS_YES, "app.common.loginSuccess", + [4]string{ipaddr, location, os, browser}, + ) + + data["tokenType"] = constants.HEADER_PREFIX + data["accessToken"] = accessToken + data["expiresIn"] = expiresIn + data["refreshToken"] = refreshToken + data["refreshExpiresIn"] = refreshExpiresIn + data["userId"] = info.UserId + c.JSON(200, resp.OkData(data)) +} + +// Logout 系统登出 +// +// POST /auth/logout +func (s AccountController) Logout(c *gin.Context) { + language := reqctx.AcceptLanguage(c) + tokenStr := reqctx.Authorization(c) + if tokenStr != "" { + // 存在token时记录退出信息 + userName, err := token.UserInfoRemove(tokenStr) + if err != nil { + // 当前请求信息 + ipaddr, location := reqctx.IPAddrLocation(c) + os, browser := reqctx.UaOsBrowser(c) + // 创建系统访问记录 + s.sysLogLoginService.Insert( + userName, constants.STATUS_YES, "app.common.logoutSuccess", + [4]string{ipaddr, location, os, browser}, + ) + } + } + c.JSON(200, resp.OkMsg(i18n.TKey(language, "app.common.logoutSuccess"))) +} + +// RefreshToken 刷新Token +// +// POST /auth/refresh-token +func (s AccountController) RefreshToken(c *gin.Context) { + var body struct { + RefreshToken string `json:"refreshToken" binding:"required"` // 刷新令牌 + } + if err := c.ShouldBindJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) return - } else { - s.accountService.UpdateLoginDateAndIP(loginUser) - // 登录成功 - s.sysLogLoginService.Insert( - body.Username, constants.STATUS_YES, "app.common.loginSuccess", - [4]string{ipaddr, location, os, browser}, - ) } - data["accessToken"] = tokenStr - data["tokenType"] = strings.TrimRight(constants.HEADER_PREFIX, " ") - data["expiresIn"] = (loginUser.ExpireTime - loginUser.LoginTime) / 1000 - data["userId"] = loginUser.UserId - c.JSON(200, resp.OkData(data)) + // 验证刷新令牌是否有效 + claims, err := token.UserTokenVerify(body.RefreshToken, "refresh") + if err != nil { + c.JSON(401, resp.CodeMsg(401001, err.Error())) + return + } + userId := parse.Number(claims[constants.JWT_USER_ID]) + + // 登录用户信息 + info, err := s.accountService.ByUserId(userId) + if err != nil { + c.JSON(200, resp.ErrMsg(err.Error())) + return + } + + // 设备指纹信息是否一致 + deviceId := fmt.Sprint(claims[constants.JWT_DEVICE_ID]) + deviceFingerprint := reqctx.DeviceFingerprint(c, userId) + if deviceId != deviceFingerprint { + c.JSON(200, resp.ErrMsg("device fingerprint mismatch")) + return + } + + // 生成访问令牌 + accessToken, expiresIn := token.UserTokenCreate(userId, deviceFingerprint, "access") + if accessToken == "" || expiresIn == 0 { + c.JSON(200, resp.ErrMsg("token generation failed")) + return + } + // 生成刷新令牌 + now := time.Now() + exp, _ := claims.GetExpirationTime() + iat, _ := claims.GetIssuedAt() + refreshExpiresIn := int64(exp.Sub(now).Seconds()) + refreshToken := body.RefreshToken + + // 如果当前时间大于过期时间的一半,则生成新令牌 + halfExp := exp.Add(-(exp.Sub(iat.Time)) / 2) + if now.After(halfExp) { + refreshToken, refreshExpiresIn = token.UserTokenCreate(userId, deviceFingerprint, "refresh") + } + + // 当前请求信息 + ipaddr, location := reqctx.IPAddrLocation(c) + os, browser := reqctx.UaOsBrowser(c) + // 记录令牌,创建系统访问记录 + token.UserInfoCreate(&info, deviceFingerprint, [4]string{ipaddr, location, os, browser}) + s.accountService.UpdateLoginDateAndIP(info) + s.sysLogLoginService.Insert( + info.User.UserName, constants.STATUS_YES, "Refresh Access Token Successful", + [4]string{ipaddr, location, os, browser}, + ) + + // 返回访问令牌和刷新令牌 + c.JSON(200, resp.OkData(map[string]any{ + "tokenType": constants.HEADER_PREFIX, + "accessToken": accessToken, + "expiresIn": expiresIn, + "refreshToken": refreshToken, + "refreshExpiresIn": refreshExpiresIn, + "userId": userId, + })) } // Me 登录用户信息 @@ -126,7 +238,7 @@ func (s AccountController) Me(c *gin.Context) { language := reqctx.AcceptLanguage(c) info, err := reqctx.LoginUser(c) if err != nil { - c.JSON(401, resp.CodeMsg(40003, err.Error())) + c.JSON(401, resp.CodeMsg(401002, err.Error())) return } @@ -146,7 +258,6 @@ func (s AccountController) Me(c *gin.Context) { "roles": roles, "permissions": perms, } - if !isSystemUser { // 强制改密码 forcePasswdChange, _ := s.accountService.PasswordCountOrExpireTime(info.User.LoginCount, info.User.PasswordUpdateTime) @@ -170,12 +281,11 @@ func (s AccountController) Me(c *gin.Context) { // @Description Login User Routing Information // @Router /router [get] func (s AccountController) Router(c *gin.Context) { - userId := reqctx.LoginUserToUserID(c) + loginUserId := reqctx.LoginUserToUserID(c) // 前端路由,系统管理员拥有所有 - isSystemUser := config.IsSystemUser(userId) - buildMenus := s.accountService.RouteMenus(userId, isSystemUser) - + isSystemUser := config.IsSystemUser(loginUserId) + buildMenus := s.accountService.RouteMenus(loginUserId, isSystemUser) // 闭包函数处理多语言 language := reqctx.AcceptLanguage(c) var converI18n func(language string, arr *[]systemModelVO.Router) @@ -191,36 +301,3 @@ func (s AccountController) Router(c *gin.Context) { c.JSON(200, resp.OkData(buildMenus)) } - -// Logout 系统登出 -// -// POST /logout -// -// @Tags common/authorization -// @Accept json -// @Produce json -// @Success 200 {object} object "Response Results" -// @Security TokenAuth -// @Summary System Logout -// @Description System Logout -// @Router /logout [post] -func (s AccountController) Logout(c *gin.Context) { - language := reqctx.AcceptLanguage(c) - tokenStr := reqctx.Authorization(c) - if tokenStr != "" { - // 存在token时记录退出信息 - userName := token.Remove(tokenStr) - if userName != "" { - // 当前请求信息 - ipaddr, location := reqctx.IPAddrLocation(c) - os, browser := reqctx.UaOsBrowser(c) - // 创建系统访问记录 - s.sysLogLoginService.Insert( - userName, constants.STATUS_YES, "app.common.logoutSuccess", - [4]string{ipaddr, location, os, browser}, - ) - } - } - - c.JSON(200, resp.OkMsg(i18n.TKey(language, "app.common.logoutSuccess"))) -} diff --git a/src/modules/auth/controller/bootloader.go b/src/modules/auth/controller/bootloader.go index 038740b4..fed5d16d 100644 --- a/src/modules/auth/controller/bootloader.go +++ b/src/modules/auth/controller/bootloader.go @@ -1,8 +1,6 @@ package controller import ( - "strings" - "be.ems/src/framework/constants" "be.ems/src/framework/i18n" "be.ems/src/framework/reqctx" @@ -52,7 +50,7 @@ func (s *BootloaderController) Start(c *gin.Context) { } // 登录用户信息 - loginUser := token.TokenInfo{ + info := token.UserInfo{ UserId: sysUser.UserId, DeptId: sysUser.DeptId, User: sysUser, @@ -60,23 +58,24 @@ func (s *BootloaderController) Start(c *gin.Context) { } // 当前请求信息 - ipaddr, location := reqctx.IPAddrLocation(c) - os, browser := reqctx.UaOsBrowser(c) + deviceFingerprint := reqctx.DeviceFingerprint(c, info.UserId) - // 生成令牌,创建系统访问记录 - tokenStr := token.Create(&loginUser, [4]string{ipaddr, location, os, browser}) - if tokenStr == "" { - c.JSON(200, resp.Err(nil)) + // 生成访问令牌 + accessToken, expiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "access") + if accessToken == "" || expiresIn == 0 { + c.JSON(200, resp.ErrMsg("token generation failed")) return - } else { - s.accountService.UpdateLoginDateAndIP(loginUser) } + // 创建系统访问记录 + s.accountService.UpdateLoginDateAndIP(info) c.JSON(200, resp.OkData(map[string]any{ - "accessToken": tokenStr, - "tokenType": strings.TrimRight(constants.HEADER_PREFIX, " "), - "expiresIn": (loginUser.ExpireTime - loginUser.LoginTime) / 1000, - "userId": loginUser.UserId, + "tokenType": constants.HEADER_PREFIX, + "accessToken": accessToken, + "expiresIn": expiresIn, + "refreshToken": "", + "refreshExpiresIn": 0, + "userId": info.UserId, })) } @@ -102,7 +101,7 @@ func (s *BootloaderController) Done(c *gin.Context) { } // 清除授权信息 - token.Remove(reqctx.Authorization(c)) + token.UserInfoRemove(reqctx.Authorization(c)) c.JSON(200, resp.Ok(nil)) } @@ -127,7 +126,7 @@ func (s *BootloaderController) Reset(c *gin.Context) { } // 清除授权信息 - token.Remove(reqctx.Authorization(c)) + token.UserInfoRemove(reqctx.Authorization(c)) c.JSON(200, resp.Ok(nil)) } diff --git a/src/modules/auth/controller/captcha.go b/src/modules/auth/controller/captcha.go index 03180113..578878c4 100644 --- a/src/modules/auth/controller/captcha.go +++ b/src/modules/auth/controller/captcha.go @@ -87,7 +87,7 @@ func (s *CaptchaController) Image(c *gin.Context) { data["img"] = item.EncodeB64string() expiration := constants.CAPTCHA_EXPIRATION * time.Second verifyKey = constants.CACHE_CAPTCHA_CODE + ":" + id - redis.SetByExpire("", verifyKey, answer, expiration) + redis.Set("", verifyKey, answer, expiration) } } if captchaType == constants.CAPTCHA_TYPE_CHAR { @@ -121,7 +121,7 @@ func (s *CaptchaController) Image(c *gin.Context) { data["img"] = item.EncodeB64string() expiration := constants.CAPTCHA_EXPIRATION * time.Second verifyKey = constants.CACHE_CAPTCHA_CODE + ":" + id - redis.SetByExpire("", verifyKey, answer, expiration) + redis.Set("", verifyKey, answer, expiration) } } diff --git a/src/modules/auth/controller/register.go b/src/modules/auth/controller/register.go index b29b9480..ba436ed4 100644 --- a/src/modules/auth/controller/register.go +++ b/src/modules/auth/controller/register.go @@ -29,15 +29,32 @@ type RegisterController struct { sysLogLoginService *systemService.SysLogLogin // 系统登录访问服务 } -// 账号注册 +// Register 账号注册 // -// GET /register -func (s *RegisterController) Register(c *gin.Context) { +// POST /auth/register +func (s RegisterController) Register(c *gin.Context) { language := reqctx.AcceptLanguage(c) var body model.RegisterBody if err := c.ShouldBindJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) - c.JSON(422, resp.CodeMsg(40422, errMsgs)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) + return + } + + // 当前请求信息 + ipaddr, location := reqctx.IPAddrLocation(c) + os, browser := reqctx.UaOsBrowser(c) + + // 校验验证码 + err := s.registerService.ValidateCaptcha(body.Code, body.UUID) + // 根据错误信息,创建系统访问记录 + if err != nil { + msg := fmt.Sprintf("%s code %s", err.Error(), body.Code) + s.sysLogLoginService.Insert( + body.Username, constants.STATUS_NO, msg, + [4]string{ipaddr, location, os, browser}, + ) + c.JSON(200, resp.ErrMsg(err.Error())) return } @@ -47,15 +64,9 @@ func (s *RegisterController) Register(c *gin.Context) { c.JSON(200, resp.ErrMsg(i18n.TKey(language, "register.errUsername"))) return } - // if !regular.ValidPassword(body.Password) { - // // 登录密码至少包含大小写字母、数字、特殊符号,且不少于6位 - // c.JSON(200, resp.ErrMsg(i18n.TKey(language, "register.errPasswd"))) - // return - // } - // 检查用户密码策略强度 - ok, errMsg := s.registerService.ValidatePasswordPolicy(body.Password, language) - if !ok { - c.JSON(200, resp.ErrMsg(errMsg)) + if !regular.ValidPassword(body.Password) { + // 登录密码至少包含大小写字母、数字、特殊符号,且不少于6位 + c.JSON(200, resp.ErrMsg(i18n.TKey(language, "register.errPasswd"))) return } if body.Password != body.ConfirmPassword { @@ -64,26 +75,7 @@ func (s *RegisterController) Register(c *gin.Context) { return } - // 当前请求信息 - ipaddr, location := reqctx.IPAddrLocation(c) - os, browser := reqctx.UaOsBrowser(c) - - // 校验验证码 - err := s.registerService.ValidateCaptcha( - body.Code, - body.UUID, - ) - // 根据错误信息,创建系统访问记录 - if err != nil { - msg := err.Error() + " code: " + body.Code - s.sysLogLoginService.Insert( - body.Username, constants.STATUS_NO, msg, - [4]string{ipaddr, location, os, browser}, - ) - c.JSON(200, resp.ErrMsg(err.Error())) - return - } - + // 进行注册 userId, err := s.registerService.ByUserName(body.Username, body.Password) if err == nil { msg := i18n.TTemplate(language, "register.successMsg", map[string]any{"name": body.Username, "id": userId}) diff --git a/src/modules/auth/service/account.go b/src/modules/auth/service/account.go index e52b6622..bc8d605a 100644 --- a/src/modules/auth/service/account.go +++ b/src/modules/auth/service/account.go @@ -56,25 +56,25 @@ func (s *Account) ValidateCaptcha(code, uuid string) error { } // ByUsername 登录创建用户信息 -func (s Account) ByUsername(username, password string) (token.TokenInfo, error) { - tokenInfo := token.TokenInfo{} +func (s Account) ByUsername(username, password string) (token.UserInfo, error) { + info := token.UserInfo{} // 检查密码重试次数 retryKey, retryCount, lockTime, err := s.passwordRetryCount(username) if err != nil { - return tokenInfo, err + return info, err } // 查询用户登录账号 sysUser := s.sysUserService.FindByUserName(username) if sysUser.UserName != username { - return tokenInfo, fmt.Errorf("login.errNameOrPasswd") + return info, fmt.Errorf("login.errNameOrPasswd") } if sysUser.DelFlag == constants.STATUS_YES { - return tokenInfo, fmt.Errorf("login.errDelFlag") + return info, fmt.Errorf("login.errDelFlag") } if sysUser.StatusFlag == constants.STATUS_NO { - return tokenInfo, fmt.Errorf("login.errStatus") + return info, fmt.Errorf("login.errStatus") } // 检验用户密码 @@ -82,31 +82,61 @@ func (s Account) ByUsername(username, password string) (token.TokenInfo, error) if compareBool { s.CleanLoginRecordCache(sysUser.UserName) // 清除错误记录次数 } else { - _ = redis.SetByExpire("", retryKey, retryCount+1, lockTime) - return tokenInfo, fmt.Errorf("login.errNameOrPasswd") + _ = redis.Set("", retryKey, retryCount+1, lockTime) + return info, fmt.Errorf("login.errNameOrPasswd") } // 登录用户信息 - tokenInfo.UserId = sysUser.UserId - tokenInfo.DeptId = sysUser.DeptId - tokenInfo.User = sysUser + info.UserId = sysUser.UserId + info.DeptId = sysUser.DeptId + info.User = sysUser // 用户权限组标识 if config.IsSystemUser(sysUser.UserId) { - tokenInfo.Permissions = []string{constants.SYS_PERMISSION_SYSTEM} + info.Permissions = []string{constants.SYS_PERMISSION_SYSTEM} } else { perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId) - tokenInfo.Permissions = parse.RemoveDuplicates(perms) + info.Permissions = parse.RemoveDuplicates(perms) } - return tokenInfo, nil + return info, nil +} + +// ByUserId 用户ID刷新令牌创建用户信息 +func (s Account) ByUserId(userId int64) (token.UserInfo, error) { + info := token.UserInfo{} + + // 查询用户登录账号 + sysUser := s.sysUserService.FindById(userId) + if sysUser.UserId != userId { + return info, fmt.Errorf("user does not exist") + } + if sysUser.DelFlag == constants.STATUS_YES { + return info, fmt.Errorf("sorry, your account has been deleted. Sorry, your account has been deleted") + } + if sysUser.StatusFlag == constants.STATUS_NO { + return info, fmt.Errorf("sorry, your account has been disabled") + } + + // 登录用户信息 + info.UserId = sysUser.UserId + info.DeptId = sysUser.DeptId + info.User = sysUser + // 用户权限组标识 + if config.IsSystemUser(sysUser.UserId) { + info.Permissions = []string{constants.SYS_PERMISSION_SYSTEM} + } else { + perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId) + info.Permissions = parse.RemoveDuplicates(perms) + } + return info, nil } // UpdateLoginDateAndIP 更新登录时间和IP -func (s Account) UpdateLoginDateAndIP(tokenInfo token.TokenInfo) bool { - user := s.sysUserService.FindById(tokenInfo.UserId) +func (s Account) UpdateLoginDateAndIP(info token.UserInfo) bool { + user := s.sysUserService.FindById(info.UserId) user.Password = "" // 密码不更新 user.LoginCount += 1 - user.LoginIp = tokenInfo.LoginIp - user.LoginTime = tokenInfo.LoginTime + user.LoginIp = info.LoginIp + user.LoginTime = info.LoginTime return s.sysUserService.Update(user) > 0 } diff --git a/src/modules/auth/service/register.go b/src/modules/auth/service/register.go index b7b0afd6..39903be2 100644 --- a/src/modules/auth/service/register.go +++ b/src/modules/auth/service/register.go @@ -1,13 +1,10 @@ package service import ( - "encoding/json" "fmt" - "regexp" "be.ems/src/framework/constants" "be.ems/src/framework/database/redis" - "be.ems/src/framework/i18n" "be.ems/src/framework/utils/parse" systemModel "be.ems/src/modules/system/model" systemService "be.ems/src/modules/system/service" @@ -81,7 +78,7 @@ func (s Register) ByUserName(username, password string) (int64, error) { if insertId > 0 { return insertId, nil } - return 0, fmt.Errorf("failed to register user [%s]. Please contact the system administrator", username) + return 0, fmt.Errorf("failed to register user [%s]. Please contact the GM", username) } // registerRoleInit 注册初始角色 @@ -93,45 +90,3 @@ func (s Register) registerRoleInit() []int64 { func (s Register) registerPostInit() []int64 { return []int64{} } - -// ValidatePasswordPolicy 判断密码策略强度 -func (s Register) ValidatePasswordPolicy(password string, errLang string) (bool, string) { - passwordPolicyStr := s.sysConfigService.FindValueByKey("sys.user.passwordPolicy") - if passwordPolicyStr == "" { - // 未配置密码策略 - return false, i18n.TKey(errLang, "config.sys.user.passwordPolicyNot") - } - var policy struct { - MinLength int `json:"minLength"` - SpecialChars int `json:"specialChars"` - Uppercase int `json:"uppercase"` - Lowercase int `json:"lowercase"` - } - - err := json.Unmarshal([]byte(passwordPolicyStr), &policy) - if err != nil { - return false, err.Error() - } - - errMsg := i18n.TTemplate(errLang, "sys.user.passwordPolicyError", map[string]any{ - "minLength": policy.MinLength, - "specialChars": policy.SpecialChars, - "uppercase": policy.Uppercase, - "lowercase": policy.Lowercase, - }) - specialChars := len(regexp.MustCompile(`[!@#$%^&*(),.?":{}|<>]`).FindAllString(password, -1)) - if specialChars < policy.SpecialChars { - return false, errMsg - } - - uppercase := len(regexp.MustCompile(`[A-Z]`).FindAllString(password, -1)) - if uppercase < policy.Uppercase { - return false, errMsg - } - - lowercase := len(regexp.MustCompile(`[a-z]`).FindAllString(password, -1)) - if lowercase < policy.Lowercase { - return false, errMsg - } - return true, "" -} diff --git a/src/modules/chart/chart.go b/src/modules/chart/chart.go index 83455e2b..9f5cd577 100644 --- a/src/modules/chart/chart.go +++ b/src/modules/chart/chart.go @@ -17,20 +17,20 @@ func Setup(router *gin.Engine) { chartGraphGroup := router.Group("/chart/graph") { chartGraphGroup.GET("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewChartGraph.Load, ) chartGraphGroup.GET("/groups", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewChartGraph.GroupNames, ) chartGraphGroup.POST("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.chartGraph", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewChartGraph.Save, ) chartGraphGroup.DELETE("/:group", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.chartGraph", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewChartGraph.Delete, ) diff --git a/src/modules/common/common.go b/src/modules/common/common.go index a22d2057..7a054bc2 100644 --- a/src/modules/common/common.go +++ b/src/modules/common/common.go @@ -25,21 +25,21 @@ func Setup(router *gin.Engine) { // 通用请求 commonGroup := router.Group("/common") { - commonGroup.POST("/hash", middleware.PreAuthorize(nil), controller.NewCommon.Hash) + commonGroup.POST("/hash", middleware.AuthorizeUser(nil), controller.NewCommon.Hash) commonGroup.GET("/i18n", controller.NewCommon.I18n) } // 文件操作处理 fileGroup := router.Group("/file") { - fileGroup.POST("/upload", middleware.PreAuthorize(nil), controller.NewFile.Upload) - fileGroup.POST("/chunk-check", middleware.PreAuthorize(nil), controller.NewFile.ChunkCheck) - fileGroup.POST("/chunk-upload", middleware.PreAuthorize(nil), controller.NewFile.ChunkUpload) - fileGroup.POST("/chunk-merge", middleware.PreAuthorize(nil), controller.NewFile.ChunkMerge) - fileGroup.GET("/download/:filePath", middleware.PreAuthorize(nil), controller.NewFile.Download) - fileGroup.GET("/list", middleware.PreAuthorize(nil), controller.NewFile.List) - fileGroup.GET("", middleware.PreAuthorize(nil), controller.NewFile.File) - fileGroup.DELETE("", middleware.PreAuthorize(nil), controller.NewFile.Remove) - fileGroup.POST("/transfer-static-file", middleware.PreAuthorize(nil), controller.NewFile.TransferStaticFile) + fileGroup.POST("/upload", middleware.AuthorizeUser(nil), controller.NewFile.Upload) + fileGroup.POST("/chunk-check", middleware.AuthorizeUser(nil), controller.NewFile.ChunkCheck) + fileGroup.POST("/chunk-upload", middleware.AuthorizeUser(nil), controller.NewFile.ChunkUpload) + fileGroup.POST("/chunk-merge", middleware.AuthorizeUser(nil), controller.NewFile.ChunkMerge) + fileGroup.GET("/download/:filePath", middleware.AuthorizeUser(nil), controller.NewFile.Download) + fileGroup.GET("/list", middleware.AuthorizeUser(nil), controller.NewFile.List) + fileGroup.GET("", middleware.AuthorizeUser(nil), controller.NewFile.File) + fileGroup.DELETE("", middleware.AuthorizeUser(nil), controller.NewFile.Remove) + fileGroup.POST("/transfer-static-file", middleware.AuthorizeUser(nil), controller.NewFile.TransferStaticFile) } } diff --git a/src/modules/common/controller/file.go b/src/modules/common/controller/file.go index 1b50a3f6..271bb464 100644 --- a/src/modules/common/controller/file.go +++ b/src/modules/common/controller/file.go @@ -134,7 +134,7 @@ func (s *FileController) ChunkCheck(c *gin.Context) { Identifier string `json:"identifier" binding:"required"` // 唯一标识 FileName string `json:"fileName" binding:"required"` // 文件名 } - if err := c.ShouldBindJSON(&body); err != nil { + if err := c.ShouldBindBodyWithJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(40422, errMsgs)) return @@ -168,7 +168,7 @@ func (s *FileController) ChunkMerge(c *gin.Context) { FileName string `json:"fileName" binding:"required"` // 文件名 SubPath string `json:"subPath"` // 子路径类型 } - if err := c.ShouldBindJSON(&body); err != nil { + if err := c.ShouldBindBodyWithJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(40422, errMsgs)) return diff --git a/src/modules/monitor/controller/sys_cache.go b/src/modules/monitor/controller/sys_cache.go index f46c9a26..55c7c565 100644 --- a/src/modules/monitor/controller/sys_cache.go +++ b/src/modules/monitor/controller/sys_cache.go @@ -48,13 +48,15 @@ func (s *SysCacheController) Info(c *gin.Context) { func (s SysCacheController) Names(c *gin.Context) { language := reqctx.AcceptLanguage(c) caches := []model.SysCache{ - model.NewNames(i18n.TKey(language, "cache.name.user"), constants.CACHE_LOGIN_TOKEN), + model.NewNames(i18n.TKey(language, "cache.name.token"), constants.CACHE_TOKEN_DEVICE), model.NewNames(i18n.TKey(language, "cache.name.sys_config"), constants.CACHE_SYS_CONFIG), model.NewNames(i18n.TKey(language, "cache.name.sys_dict"), constants.CACHE_SYS_DICT), model.NewNames(i18n.TKey(language, "cache.name.captcha_codes"), constants.CACHE_CAPTCHA_CODE), model.NewNames(i18n.TKey(language, "cache.name.repeat_submit"), constants.CACHE_REPEAT_SUBMIT), model.NewNames(i18n.TKey(language, "cache.name.rate_limit"), constants.CACHE_RATE_LIMIT), model.NewNames(i18n.TKey(language, "cache.name.pwd_err_cnt"), constants.CACHE_PWD_ERR_COUNT), + model.NewNames(i18n.TKey(language, "cache.name.oauth2_codes"), constants.CACHE_OAUTH2_CODE), + model.NewNames(i18n.TKey(language, "cache.name.oauth2_devices"), constants.CACHE_OAUTH2_DEVICE), model.NewNames(i18n.TKey(language, "cache.name.i18n"), constants.CACHE_I18N), model.NewNames(i18n.TKey(language, "cache.name.ne_info"), constants.CACHE_NE_INFO), model.NewNames(i18n.TKey(language, "cache.name.ne_data"), constants.CACHE_NE_DATA), @@ -166,7 +168,7 @@ func (s SysCacheController) CleanKeys(c *gin.Context) { c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } - if constants.CACHE_LOGIN_TOKEN == query.CacheName { + if constants.CACHE_TOKEN_DEVICE == query.CacheName { c.JSON(200, resp.ErrMsg("Cannot delete user information cache")) return } diff --git a/src/modules/monitor/controller/sys_user_online.go b/src/modules/monitor/controller/sys_user_online.go index 8a8dac97..0e275d92 100644 --- a/src/modules/monitor/controller/sys_user_online.go +++ b/src/modules/monitor/controller/sys_user_online.go @@ -46,7 +46,7 @@ func (s *SysUserOnlineController) List(c *gin.Context) { userName := c.Query("userName") // 获取所有在线用户key - keys, _ := redis.GetKeys("", constants.CACHE_LOGIN_TOKEN+":*") + keys, _ := redis.GetKeys("", constants.CACHE_TOKEN_DEVICE+":*") // 分批获取 arr := make([]string, 0) @@ -69,13 +69,13 @@ func (s *SysUserOnlineController) List(c *gin.Context) { continue } - var tokenInfo token.TokenInfo - err := json.Unmarshal([]byte(str), &tokenInfo) + var info token.UserInfo + err := json.Unmarshal([]byte(str), &info) if err != nil { continue } - onlineUser := s.sysUserOnlineService.TokenInfoToUserOnline(tokenInfo) + onlineUser := s.sysUserOnlineService.UserInfoToUserOnline(info) if onlineUser.TokenID != "" { userOnlines = append(userOnlines, onlineUser) } @@ -122,15 +122,14 @@ func (s *SysUserOnlineController) List(c *gin.Context) { func (s SysUserOnlineController) Logout(c *gin.Context) { tokenIdStr := c.Param("tokenId") if tokenIdStr == "" || strings.Contains(tokenIdStr, "*") { - c.JSON(400, resp.CodeMsg(40010, "bind err: tokenId is empty")) + c.JSON(422, resp.CodeMsg(422002, "bind err: tokenId is empty")) return } // 处理字符转id数组后去重 - ids := strings.Split(tokenIdStr, ",") - uniqueIDs := parse.RemoveDuplicates(ids) + uniqueIDs := parse.RemoveDuplicatesToArray(tokenIdStr, ",") for _, v := range uniqueIDs { - key := constants.CACHE_LOGIN_TOKEN + ":" + v + key := constants.CACHE_TOKEN_DEVICE + ":" + v if err := redis.Del("", key); err != nil { c.JSON(200, resp.ErrMsg(err.Error())) return diff --git a/src/modules/monitor/monitor.go b/src/modules/monitor/monitor.go index 2188060b..b2461e47 100644 --- a/src/modules/monitor/monitor.go +++ b/src/modules/monitor/monitor.go @@ -23,15 +23,14 @@ func Setup(router *gin.Engine) { monitorGroup := router.Group("/monitor") { monitorGroup.GET("/load", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewMonitor.Load, ) } // 服务器信息 router.GET("/monitor/system", - // middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:system:info"}}), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:system:info"}}), controller.NewSystem.Info, ) @@ -39,11 +38,11 @@ func Setup(router *gin.Engine) { sysUserOnlineGroup := router.Group("/monitor/user-online") { sysUserOnlineGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:online:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:online:list"}}), controller.NewSysUserOnline.List, ) sysUserOnlineGroup.DELETE("/logout/:tokenId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:online:logout"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:online:logout"}}), controller.NewSysUserOnline.Logout, ) } @@ -52,32 +51,31 @@ func Setup(router *gin.Engine) { sysCacheGroup := router.Group("/monitor/cache") { sysCacheGroup.GET("", - // middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:cache:info"}}), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:cache:info"}}), controller.NewSysCache.Info, ) sysCacheGroup.GET("/names", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:cache:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:cache:list"}}), controller.NewSysCache.Names, ) sysCacheGroup.GET("/keys", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:cache:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:cache:list"}}), controller.NewSysCache.Keys, ) sysCacheGroup.GET("/value", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:cache:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:cache:query"}}), controller.NewSysCache.Value, ) sysCacheGroup.DELETE("/names", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:cache:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:cache:remove"}}), controller.NewSysCache.CleanNames, ) sysCacheGroup.DELETE("/keys", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:cache:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:cache:remove"}}), controller.NewSysCache.CleanKeys, ) sysCacheGroup.DELETE("/value", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:cache:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:cache:remove"}}), controller.NewSysCache.CleanValue, ) } @@ -86,26 +84,26 @@ func Setup(router *gin.Engine) { sysJobLogGroup := router.Group("/monitor/job/log") { sysJobLogGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:list"}}), controller.NewSysJobLog.List, ) sysJobLogGroup.GET("/:logId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:query"}}), controller.NewSysJobLog.Info, ) sysJobLogGroup.DELETE("/:logId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:remove"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJobLog", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewSysJobLog.Remove, ) sysJobLogGroup.DELETE("/clean", repeat.RepeatSubmit(5), - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:remove"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJobLog", collectlogs.BUSINESS_TYPE_CLEAN)), controller.NewSysJobLog.Clean, ) sysJobLogGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:export"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJobLog", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewSysJobLog.Export, ) @@ -115,47 +113,47 @@ func Setup(router *gin.Engine) { sysJobGroup := router.Group("/monitor/job") { sysJobGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:list"}}), controller.NewSysJob.List, ) sysJobGroup.GET("/:jobId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:query"}}), controller.NewSysJob.Info, ) sysJobGroup.POST("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:add"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:add"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJob", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewSysJob.Add, ) sysJobGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:edit"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJob", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewSysJob.Edit, ) sysJobGroup.DELETE("/:jobId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:remove"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJob", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewSysJob.Remove, ) sysJobGroup.PUT("/status", repeat.RepeatSubmit(5), - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:changeStatus"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:changeStatus"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJob", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewSysJob.Status, ) sysJobGroup.PUT("/run/:jobId", repeat.RepeatSubmit(10), - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:changeStatus"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:changeStatus"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJob", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewSysJob.Run, ) sysJobGroup.PUT("/reset", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:changeStatus"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:changeStatus"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJob", collectlogs.BUSINESS_TYPE_CLEAN)), controller.NewSysJob.ResetQueueJob, ) sysJobGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"monitor:job:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"monitor:job:export"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sysJob", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewSysJob.Export, ) diff --git a/src/modules/monitor/service/sys_user_online.go b/src/modules/monitor/service/sys_user_online.go index d48368b5..3ee54494 100644 --- a/src/modules/monitor/service/sys_user_online.go +++ b/src/modules/monitor/service/sys_user_online.go @@ -11,23 +11,23 @@ var NewSysUserOnline = &SysUserOnline{} // SysUserOnline 在线用户 服务层处理 type SysUserOnline struct{} -// TokenInfoToUserOnline 在线用户信息 -func (s SysUserOnline) TokenInfoToUserOnline(tokenInfo token.TokenInfo) model.SysUserOnline { - if tokenInfo.UserId <= 0 { +// UserInfoToUserOnline 在线用户信息 +func (s SysUserOnline) UserInfoToUserOnline(info token.UserInfo) model.SysUserOnline { + if info.UserId <= 0 { return model.SysUserOnline{} } sysUserOnline := model.SysUserOnline{ - TokenID: tokenInfo.UUID, - UserName: tokenInfo.User.UserName, - LoginIp: tokenInfo.LoginIp, - LoginLocation: tokenInfo.LoginLocation, - Browser: tokenInfo.Browser, - OS: tokenInfo.OS, - LoginTime: tokenInfo.LoginTime, + TokenID: info.DeviceId, + UserName: info.User.UserName, + LoginIp: info.LoginIp, + LoginLocation: info.LoginLocation, + Browser: info.Browser, + OS: info.OS, + LoginTime: info.LoginTime, } - if tokenInfo.User.DeptId > 0 { - sysUserOnline.DeptName = tokenInfo.User.Dept.DeptName + if info.User.DeptId > 0 { + sysUserOnline.DeptName = info.User.Dept.DeptName } return sysUserOnline } diff --git a/src/modules/network_data/network_data.go b/src/modules/network_data/network_data.go index 7385c57d..3c809701 100644 --- a/src/modules/network_data/network_data.go +++ b/src/modules/network_data/network_data.go @@ -24,11 +24,11 @@ func Setup(router *gin.Engine) { kpiGroup := neDataGroup.Group("/kpi") { kpiGroup.GET("/title", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewKPI.KPITitle, ) kpiGroup.GET("/data", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewKPI.KPIData, ) } @@ -37,25 +37,25 @@ func Setup(router *gin.Engine) { alarmGroup := neDataGroup.Group("/alarm") { alarmGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewAlarm.List, ) alarmGroup.DELETE("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewAlarm.Remove, ) alarmGroup.PUT("/clear", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.alarm", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewAlarm.Clear, ) alarmGroup.PUT("/ack", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.alarm", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewAlarm.Ack, ) alarmGroup.GET("/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.alarm", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewAlarm.Export, ) @@ -65,12 +65,12 @@ func Setup(router *gin.Engine) { alarmLogGroup := neDataGroup.Group("/alarm/log") { alarmLogGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewAlarmLog.List, ) alarmLogGroup.GET("/event", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewAlarmLog.Event, ) } @@ -79,7 +79,7 @@ func Setup(router *gin.Engine) { alarmForwardGroup := neDataGroup.Group("/alarm/forward") { alarmForwardGroup.GET("/log/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewAlarmForward.List, ) } @@ -88,11 +88,11 @@ func Setup(router *gin.Engine) { nbStateGroup := neDataGroup.Group("/nb-state") { nbStateGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNBState.List, ) nbStateGroup.POST("/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNBState.Export, ) } @@ -101,25 +101,25 @@ func Setup(router *gin.Engine) { imsGroup := neDataGroup.Group("/ims") { imsGroup.GET("/cdr/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewIMS.CDRList, ) imsGroup.DELETE("/cdr/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewIMS.CDRRemove, ) imsGroup.POST("/cdr/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewIMS.CDRExport, ) imsGroup.GET("/session/num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewIMS.UeSessionNum, ) imsGroup.GET("/session/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewIMS.UeSessionList, ) } @@ -128,16 +128,16 @@ func Setup(router *gin.Engine) { smscGroup := neDataGroup.Group("/smsc") { smscGroup.GET("/cdr/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewSMSC.CDRList, ) smscGroup.DELETE("/cdr/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smscCDR", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewSMSC.CDRRemove, ) smscGroup.POST("/cdr/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smscCDR", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewSMSC.CDRExport, ) @@ -147,25 +147,25 @@ func Setup(router *gin.Engine) { smfGroup := neDataGroup.Group("/smf") { smfGroup.GET("/cdr/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewSMF.CDRList, ) smfGroup.DELETE("/cdr/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewSMF.CDRRemove, ) smfGroup.POST("/cdr/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewSMF.CDRExport, ) smfGroup.GET("/sub/num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewSMF.SubUserNum, ) smfGroup.GET("/sub/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewSMF.SubUserList, ) } @@ -174,25 +174,25 @@ func Setup(router *gin.Engine) { amfGroup := neDataGroup.Group("/amf") { amfGroup.GET("/ue/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewAMF.UEList, ) amfGroup.DELETE("/ue/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewAMF.UERemove, ) amfGroup.POST("/ue/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewAMF.UEExport, ) amfGroup.GET("/nb/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewAMF.NbInfoList, ) amfGroup.GET("/nb/list-cfg", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewAMF.NbStateList, ) } @@ -201,7 +201,7 @@ func Setup(router *gin.Engine) { upfGroup := neDataGroup.Group("/upf") { upfGroup.GET("/flow-total", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewUPF.FlowTotal, ) } @@ -210,16 +210,16 @@ func Setup(router *gin.Engine) { backupGroup := neDataGroup.Group("/backup") { backupGroup.GET("/ftp", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewBackup.FTPInfo, ) backupGroup.PUT("/ftp", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.backup", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewBackup.FTPUpdate, ) backupGroup.POST("/ftp", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.backup", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewBackup.FTPPush, ) @@ -230,50 +230,50 @@ func Setup(router *gin.Engine) { { udmAuthGroup.PUT("/resetData/:neId", repeat.RepeatSubmit(5), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_CLEAN)), controller.NewUDMAuth.ResetData, ) udmAuthGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewUDMAuth.List, ) udmAuthGroup.GET("/:neId/:imsi", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewUDMAuth.Info, ) udmAuthGroup.POST("/:neId", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewUDMAuth.Add, ) udmAuthGroup.POST("/:neId/:num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewUDMAuth.Adds, ) udmAuthGroup.PUT("/:neId", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewUDMAuth.Edit, ) udmAuthGroup.DELETE("/:neId/:imsi", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewUDMAuth.Remove, ) udmAuthGroup.DELETE("/:neId/:imsi/:num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewUDMAuth.Removes, ) udmAuthGroup.GET("/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewUDMAuth.Export, ) udmAuthGroup.POST("/import", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_IMPORT)), controller.NewUDMAuth.Import, ) @@ -284,50 +284,50 @@ func Setup(router *gin.Engine) { { udmSubGroup.PUT("/resetData/:neId", repeat.RepeatSubmit(5), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_CLEAN)), controller.NewUDMSub.ResetData, ) udmSubGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewUDMSub.List, ) udmSubGroup.GET("/:neId/:imsi", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewUDMSub.Info, ) udmSubGroup.POST("/:neId", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewUDMSub.Add, ) udmSubGroup.POST("/:neId/:num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewUDMSub.Adds, ) udmSubGroup.PUT("/:neId", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewUDMSub.Edit, ) udmSubGroup.DELETE("/:neId/:imsi", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewUDMSub.Remove, ) udmSubGroup.DELETE("/:neId/:imsi/:num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewUDMSub.Removes, ) udmSubGroup.GET("/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewUDMSub.Export, ) udmSubGroup.POST("/import", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_IMPORT)), controller.NewUDMSub.Import, ) @@ -338,45 +338,45 @@ func Setup(router *gin.Engine) { { udmVOIPGroup.PUT("/resetData/:neId", repeat.RepeatSubmit(5), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVOIP", collectlogs.BUSINESS_TYPE_CLEAN)), controller.NewUDMVOIP.ResetData, ) udmVOIPGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewUDMVOIP.List, ) udmVOIPGroup.GET("/:neId/:username", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewUDMVOIP.Info, ) udmVOIPGroup.POST("/:neId", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVOIP", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewUDMVOIP.Add, ) udmVOIPGroup.POST("/:neId/:num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVOIP", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewUDMVOIP.Adds, ) udmVOIPGroup.DELETE("/:neId/:username", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVOIP", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewUDMVOIP.Remove, ) udmVOIPGroup.DELETE("/:neId/:username/:num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVOIP", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewUDMVOIP.Removes, ) udmVOIPGroup.GET("/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVOIP", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewUDMVOIP.Export, ) udmVOIPGroup.POST("/import", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVOIP", collectlogs.BUSINESS_TYPE_IMPORT)), controller.NewUDMVOIP.Import, ) @@ -387,45 +387,45 @@ func Setup(router *gin.Engine) { { udmVolteIMSGroup.PUT("/resetData/:neId", repeat.RepeatSubmit(5), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVolteIMS", collectlogs.BUSINESS_TYPE_CLEAN)), controller.NewUDMVolteIMS.ResetData, ) udmVolteIMSGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewUDMVolteIMS.List, ) udmVolteIMSGroup.GET("/:neId/:imsi", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewUDMVolteIMS.Info, ) udmVolteIMSGroup.POST("/:neId", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVolteIMS", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewUDMVolteIMS.Add, ) udmVolteIMSGroup.POST("/:neId/:num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVolteIMS", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewUDMVolteIMS.Adds, ) udmVolteIMSGroup.DELETE("/:neId/:imsi", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVolteIMS", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewUDMVolteIMS.Remove, ) udmVolteIMSGroup.DELETE("/:neId/:imsi/:num", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVolteIMS", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewUDMVolteIMS.Removes, ) udmVolteIMSGroup.GET("/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVolteIMS", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewUDMVolteIMS.Export, ) udmVolteIMSGroup.POST("/import", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmVolteIMS", collectlogs.BUSINESS_TYPE_IMPORT)), controller.NewUDMVolteIMS.Import, ) @@ -435,25 +435,25 @@ func Setup(router *gin.Engine) { mmeGroup := neDataGroup.Group("/mme") { mmeGroup.GET("/ue/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewMME.UEList, ) mmeGroup.DELETE("/ue/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewMME.UERemove, ) mmeGroup.POST("/ue/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewMME.UEExport, ) mmeGroup.GET("/nb/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewMME.NbInfoList, ) mmeGroup.GET("/nb/list-cfg", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewMME.NbStateList, ) } @@ -462,16 +462,16 @@ func Setup(router *gin.Engine) { sgwcGroup := neDataGroup.Group("/sgwc") { sgwcGroup.GET("/cdr/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewSGWC.CDRList, ) sgwcGroup.DELETE("/cdr/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sgwcCDR", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewSGWC.CDRRemove, ) sgwcGroup.POST("/cdr/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.sgwcCDR", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewSGWC.CDRExport, ) diff --git a/src/modules/network_element/network_element.go b/src/modules/network_element/network_element.go index 78a9787a..95f7685c 100644 --- a/src/modules/network_element/network_element.go +++ b/src/modules/network_element/network_element.go @@ -21,28 +21,28 @@ func Setup(router *gin.Engine) { neActionGroup := router.Group("/ne/action") { neActionGroup.GET("/files", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeAction.Files, ) neActionGroup.GET("/pullFile", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeAction.PullFile, ) neActionGroup.POST("/pushFile", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neAction", collectlogs.BUSINESS_TYPE_IMPORT)), controller.NewNeAction.PushFile, ) neActionGroup.GET("/pullDirZip", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeAction.PullDirZip, ) neActionGroup.GET("/viewFile", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeAction.ViewFile, ) neActionGroup.PUT("/service", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neAction", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeAction.Service, ) @@ -52,58 +52,58 @@ func Setup(router *gin.Engine) { neInfoGroup := router.Group("/ne/info") { neInfoGroup.GET("/state", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeInfo.State, ) neInfoGroup.GET("/byTypeAndID", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeInfo.NeTypeAndID, ) neInfoGroup.GET("/listAll", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeInfo.ListAll, ) neInfoGroup.GET("/para5GFile", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeInfo.Para5GFileRead, ) neInfoGroup.PUT("/para5GFile", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeInfo.Para5GFileWrite, ) neInfoGroup.GET("/oamFile", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeInfo.OAMFileRead, ) neInfoGroup.PUT("/oamFile", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeInfo.OAMFileWrite, ) neInfoGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeInfo.List, ) neInfoGroup.GET("/:id", middleware.CryptoApi(false, true), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeInfo.Info, ) neInfoGroup.POST("", middleware.CryptoApi(true, true), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewNeInfo.Add, ) neInfoGroup.PUT("", middleware.CryptoApi(true, true), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewNeInfo.Edit, ) neInfoGroup.DELETE(":id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neInfo", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewNeInfo.Remove, ) @@ -113,46 +113,46 @@ func Setup(router *gin.Engine) { neHostGroup := router.Group("/ne/host") { neHostGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeHost.List, ) neHostGroup.GET("/:id", middleware.CryptoApi(false, true), - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeHost.Info, ) neHostGroup.POST("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewNeHost.Add, ) neHostGroup.PUT("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewNeHost.Edit, ) neHostGroup.DELETE("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewNeHost.Remove, ) neHostGroup.POST("/test", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeHost.Test, ) neHostGroup.POST("/cmd", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeHost.Cmd, ) neHostGroup.POST("/checkBySSH", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeHost.CheckBySSH, ) neHostGroup.POST("/authorizedBySSH", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHost", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeHost.AuthorizedBySSH, ) @@ -162,25 +162,25 @@ func Setup(router *gin.Engine) { neHostCmdGroup := router.Group("/ne/hostCmd") { neHostCmdGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeHostCmd.List, ) neHostCmdGroup.GET("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeHostCmd.Info, ) neHostCmdGroup.POST("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHostCmd", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewNeHostCmd.Add, ) neHostCmdGroup.PUT("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHostCmd", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewNeHostCmd.Edit, ) neHostCmdGroup.DELETE(":id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neHostCmd", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewNeHostCmd.Remove, ) @@ -190,15 +190,15 @@ func Setup(router *gin.Engine) { neVersionGroup := router.Group("/ne/version") { neVersionGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeVersion.List, ) neVersionGroup.GET("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeVersion.Info, ) neVersionGroup.POST("/operate", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neVersion", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeVersion.Operate, ) @@ -208,30 +208,30 @@ func Setup(router *gin.Engine) { neSoftwareGroup := router.Group("/ne/software") { neSoftwareGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeSoftware.List, ) neSoftwareGroup.GET("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeSoftware.Info, ) neSoftwareGroup.POST("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewNeSoftware.Add, ) neSoftwareGroup.PUT("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewNeSoftware.Edit, ) neSoftwareGroup.DELETE(":id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewNeSoftware.Remove, ) neSoftwareGroup.POST("/newNeVersion", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neSoftware", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeSoftware.NewNeVersion, ) @@ -241,28 +241,28 @@ func Setup(router *gin.Engine) { neLicenseGroup := router.Group("/ne/license") { neLicenseGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeLicense.List, ) neLicenseGroup.GET("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeLicense.Info, ) neLicenseGroup.GET("/byTypeAndID", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeLicense.NeTypeAndID, ) neLicenseGroup.GET("/code", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeLicense.Code, ) neLicenseGroup.POST("/change", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neLicense", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewNeLicense.Change, ) neLicenseGroup.GET("/state", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeLicense.State, ) } @@ -272,49 +272,49 @@ func Setup(router *gin.Engine) { { // 网元参数配置可用属性值 neConfigGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeConfig.List, ) neConfigGroup.GET("/info/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeConfig.Info, ) neConfigGroup.POST("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewNeConfig.Add, ) neConfigGroup.PUT("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewNeConfig.Edit, ) neConfigGroup.DELETE("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewNeConfig.Remove, ) neConfigGroup.GET("/list/:neType", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeConfig.ListByNeType, ) // 网元参数配置数据 neConfigGroup.GET("/data", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeConfig.DataInfo, ) neConfigGroup.PUT("/data", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewNeConfig.DataEdit, ) neConfigGroup.POST("/data", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewNeConfig.DataAdd, ) neConfigGroup.DELETE("/data", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfig", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewNeConfig.DataRemove, ) @@ -324,30 +324,30 @@ func Setup(router *gin.Engine) { neConfigBackupGroup := router.Group("/ne/config/backup") { neConfigBackupGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeConfigBackup.List, ) neConfigBackupGroup.GET("/download", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewNeConfigBackup.Download, ) neConfigBackupGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"ne:neConfigBackup:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"ne:neConfigBackup:edit"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfigBackup", collectlogs.BUSINESS_TYPE_UPDATE)), controller.NewNeConfigBackup.Edit, ) neConfigBackupGroup.DELETE("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"ne:neConfigBackup:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"ne:neConfigBackup:remove"}}), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfigBackup", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewNeConfigBackup.Remove, ) neConfigBackupGroup.POST("/import", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfigBackup", collectlogs.BUSINESS_TYPE_IMPORT)), controller.NewNeConfigBackup.Import, ) neConfigBackupGroup.POST("/export", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.neConfigBackup", collectlogs.BUSINESS_TYPE_EXPORT)), controller.NewNeConfigBackup.Export, ) diff --git a/src/modules/network_element/service/ne_config.go b/src/modules/network_element/service/ne_config.go index f96b4fbf..f5d6430e 100644 --- a/src/modules/network_element/service/ne_config.go +++ b/src/modules/network_element/service/ne_config.go @@ -46,7 +46,7 @@ func (r *NeConfig) RefreshByNeTypeAndNeID(neType string) []model.NeConfig { v[i] = item } values, _ := json.Marshal(v) - redis.Set("", key, string(values)) + redis.Set("", key, string(values), 0) } } } @@ -66,7 +66,7 @@ func (r *NeConfig) RefreshByNeTypeAndNeID(neType string) []model.NeConfig { neConfigList[i] = v } values, _ := json.Marshal(neConfigList) - redis.Set("", key, string(values)) + redis.Set("", key, string(values), 0) } return neConfigList } diff --git a/src/modules/network_element/service/ne_info.go b/src/modules/network_element/service/ne_info.go index 104db955..49da206b 100644 --- a/src/modules/network_element/service/ne_info.go +++ b/src/modules/network_element/service/ne_info.go @@ -50,7 +50,7 @@ func (r NeInfo) FindByNeTypeAndNeID(neType, neID string) model.NeInfo { if neInfo.ID != 0 && neInfo.NeId == neID { redis.Del("", key) values, _ := json.Marshal(neInfo) - redis.Set("", key, string(values)) + redis.Set("", key, string(values), 0) } } return neInfo @@ -64,7 +64,7 @@ func (r NeInfo) RefreshByNeTypeAndNeID(neType, neID string) model.NeInfo { neInfo = r.neInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID) if neInfo.ID != 0 && neInfo.NeId == neID { values, _ := json.Marshal(neInfo) - redis.Set("", key, string(values)) + redis.Set("", key, string(values), 0) } return neInfo } @@ -103,7 +103,7 @@ func (r NeInfo) FindByNeType(neType string) []model.NeInfo { key := fmt.Sprintf("%s:%s:%s", constants.CACHE_NE_INFO, strings.ToUpper(v.NeType), v.NeId) redis.Del("", key) values, _ := json.Marshal(v) - redis.Set("", key, string(values)) + redis.Set("", key, string(values), 0) } } return neInfo @@ -131,7 +131,7 @@ func (r NeInfo) FindByRmuid(rmUid string) model.NeInfo { key := fmt.Sprintf("%s:%s:%s", constants.CACHE_NE_INFO, strings.ToUpper(v.NeType), v.NeId) redis.Del("", key) values, _ := json.Marshal(v) - redis.Set("", key, string(values)) + redis.Set("", key, string(values), 0) if v.RmUID == rmUid { neInfo = v } diff --git a/src/modules/oauth2/controller/oauth2.go b/src/modules/oauth2/controller/oauth2.go new file mode 100644 index 00000000..3c6e5530 --- /dev/null +++ b/src/modules/oauth2/controller/oauth2.go @@ -0,0 +1,214 @@ +package controller + +import ( + "fmt" + "strings" + "time" + + "github.com/gin-gonic/gin" + + "be.ems/src/framework/constants" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" + "be.ems/src/framework/token" + "be.ems/src/modules/oauth2/model" + "be.ems/src/modules/oauth2/service" +) + +// NewOauth2 实例化控制层 +var NewOauth2 = &Oauth2Controller{ + oauth2Service: service.NewOauth2Service, + oauth2ClientService: service.NewOauth2ClientService, + oauth2LogLoginService: service.NewOauth2LogLogin, +} + +// Oauth2Controller 授权第三方客户端应用认证 控制层处理 +// +// PATH /oauth2 +type Oauth2Controller struct { + oauth2Service *service.Oauth2Service // 用户授权第三方信息服务 + oauth2ClientService *service.Oauth2ClientService // 用户授权第三方应用信息服务 + oauth2LogLoginService *service.Oauth2LogLoginService // 用户授权第三方应用登录日志 +} + +// Authorize 获取登录预授权码 +// +// GET /authorize +func (s Oauth2Controller) Authorize(c *gin.Context) { + var query model.CodeQuery + if err := c.ShouldBindQuery(&query); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) + return + } + + // 是否存在clientId + info := s.oauth2ClientService.FindByClientId(query.ClientId) + if info.ClientId == "" || info.ClientId != query.ClientId { + c.JSON(422, resp.CodeMsg(422002, "clientId not exist")) + return + } + + // 判断IP白名单 + if !strings.Contains(info.IPWhite, c.ClientIP()) { + c.JSON(422, resp.CodeMsg(422002, "IP whitelist mismatch")) + return + } + + // 生成登录预授权码 + code := s.oauth2Service.CreateCode() + + redirectURL := fmt.Sprintf("%s?code=%s&state=%s", query.RedirectUrl, code, query.State) + c.Redirect(302, redirectURL) +} + +// Tooken 通过授权码获取访问令牌 +// +// POST /token +func (s Oauth2Controller) Token(c *gin.Context) { + var body model.TokenBody + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) + return + } + if body.GrantType != "authorization_code" || body.Code == "" { + c.JSON(422, resp.CodeMsg(422002, "grantType or code error")) + return + } + + // 当前请求信息 + ipaddr, location := reqctx.IPAddrLocation(c) + os, browser := reqctx.UaOsBrowser(c) + + // 校验验证码 根据错误信息,创建系统访问记录 + if err := s.oauth2Service.ValidateCode(body.Code); err != nil { + msg := fmt.Sprintf("%s code %s", err.Error(), body.Code) + s.oauth2LogLoginService.Insert( + body.ClientId, constants.STATUS_NO, msg, + [4]string{ipaddr, location, os, browser}, + ) + c.JSON(200, resp.ErrMsg(err.Error())) + return + } + + // 登录客户端信息 + info, err := s.oauth2Service.ByClient(body.ClientId, body.ClientSecret) + if err != nil { + s.oauth2LogLoginService.Insert( + body.ClientId, constants.STATUS_NO, err.Error(), + [4]string{ipaddr, location, os, browser}, + ) + c.JSON(200, resp.ErrMsg(err.Error())) + return + } + deviceFingerprint := reqctx.DeviceFingerprint(c, info.ClientId) + + // 生成访问令牌 + accessToken, expiresIn := token.Oauth2TokenCreate(info.ClientId, deviceFingerprint, "access") + if accessToken == "" || expiresIn == 0 { + c.JSON(200, resp.ErrMsg("token generation failed")) + return + } + // 生成刷新令牌 + refreshToken, refreshExpiresIn := token.Oauth2TokenCreate(info.ClientId, deviceFingerprint, "refresh") + + // 记录令牌,创建系统访问记录 + token.Oauth2InfoCreate(&info, deviceFingerprint, [4]string{ipaddr, location, os, browser}) + s.oauth2Service.UpdateLoginDateAndIP(info) + s.oauth2LogLoginService.Insert( + body.ClientId, constants.STATUS_YES, "Authorization successful", + [4]string{ipaddr, location, os, browser}, + ) + + c.JSON(200, resp.OkData(map[string]any{ + "tokenType": constants.HEADER_PREFIX, + "accessToken": accessToken, + "expiresIn": expiresIn, + "refreshToken": refreshToken, + "refreshExpiresIn": refreshExpiresIn, + })) +} + +// RefreshToken 通过刷新令牌续期访问令牌 +// +// POST /refresh-token +func (s Oauth2Controller) RefreshToken(c *gin.Context) { + var body model.TokenBody + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) + return + } + if body.GrantType != "refresh_token" || body.RefreshToken == "" { + c.JSON(422, resp.CodeMsg(422002, "grantType or refreshToken error")) + return + } + + // 验证刷新令牌是否有效 + claims, err := token.Oauth2TokenVerify(body.RefreshToken, "refresh") + if err != nil { + c.JSON(401, resp.CodeMsg(401001, err.Error())) + return + } + clientId := fmt.Sprint(claims[constants.JWT_CLIENT_ID]) + + // 客户端信息 + info, err := s.oauth2Service.ByClient(body.ClientId, body.ClientSecret) + if err != nil { + c.JSON(200, resp.ErrMsg(err.Error())) + return + } + + // 客户端ID是否一致 + if clientId != body.ClientId { + c.JSON(200, resp.ErrMsg("clientId mismatch")) + return + } + // 设备指纹信息是否一致 + deviceId := fmt.Sprint(claims[constants.JWT_DEVICE_ID]) + deviceFingerprint := reqctx.DeviceFingerprint(c, clientId) + if deviceId != deviceFingerprint { + c.JSON(200, resp.ErrMsg("device fingerprint mismatch")) + return + } + + // 生成访问令牌 + accessToken, expiresIn := token.Oauth2TokenCreate(clientId, deviceFingerprint, "access") + if accessToken == "" || expiresIn == 0 { + c.JSON(200, resp.ErrMsg("token generation failed")) + return + } + // 生成刷新令牌 + now := time.Now() + exp, _ := claims.GetExpirationTime() + iat, _ := claims.GetIssuedAt() + refreshExpiresIn := int64(exp.Sub(now).Seconds()) + refreshToken := body.RefreshToken + + // 如果当前时间大于过期时间的一半,则生成新令牌 + halfExp := exp.Add(-(exp.Sub(iat.Time)) / 2) + if now.After(halfExp) { + refreshToken, refreshExpiresIn = token.Oauth2TokenCreate(clientId, deviceFingerprint, "refresh") + } + + // 当前请求信息 + ipaddr, location := reqctx.IPAddrLocation(c) + os, browser := reqctx.UaOsBrowser(c) + // 记录令牌,创建系统访问记录 + token.Oauth2InfoCreate(&info, deviceFingerprint, [4]string{ipaddr, location, os, browser}) + s.oauth2Service.UpdateLoginDateAndIP(info) + s.oauth2LogLoginService.Insert( + info.ClientId, constants.STATUS_YES, "Refresh Access Token Succeeded", + [4]string{ipaddr, location, os, browser}, + ) + + // 返回访问令牌和刷新令牌 + c.JSON(200, resp.OkData(map[string]any{ + "tokenType": constants.HEADER_PREFIX, + "accessToken": accessToken, + "expiresIn": expiresIn, + "refreshToken": refreshToken, + "refreshExpiresIn": refreshExpiresIn, + })) +} diff --git a/src/modules/oauth2/controller/oauth2_client.go b/src/modules/oauth2/controller/oauth2_client.go new file mode 100644 index 00000000..ca7a7061 --- /dev/null +++ b/src/modules/oauth2/controller/oauth2_client.go @@ -0,0 +1,152 @@ +package controller + +import ( + "fmt" + "strings" + + "github.com/gin-gonic/gin" + + "be.ems/src/framework/i18n" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" + "be.ems/src/framework/utils/parse" + "be.ems/src/modules/oauth2/model" + "be.ems/src/modules/oauth2/service" +) + +// NewOauth2Client 实例化控制层 +var NewOauth2Client = &Oauth2ClientController{ + oauth2ClientService: service.NewOauth2ClientService, +} + +// Oauth2ClientController 客户端授权管理 控制层处理 +// +// PATH /oauth2/client +type Oauth2ClientController struct { + oauth2ClientService *service.Oauth2ClientService // 用户授权第三方应用信息服务 +} + +// List 列表 +// +// GET /list +func (s Oauth2ClientController) List(c *gin.Context) { + query := reqctx.QueryMap(c) + rows, total := s.oauth2ClientService.FindByPage(query) + c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total})) +} + +// Info 信息 +// +// GET /:clientId +func (s Oauth2ClientController) Info(c *gin.Context) { + clientId := c.Param("clientId") + if clientId == "" { + c.JSON(422, resp.CodeMsg(422002, "bind err: clientId is empty")) + return + } + + info := s.oauth2ClientService.FindByClientId(clientId) + if info.ClientId == "" || info.ClientId != clientId { + c.JSON(200, resp.ErrMsg("clientId does not exist")) + return + } + c.JSON(200, resp.OkData(info)) +} + +// Add 新增 +// +// POST / +func (s Oauth2ClientController) Add(c *gin.Context) { + var body model.Oauth2Client + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) + return + } + if body.Id > 0 { + c.JSON(422, resp.CodeMsg(422002, "bind err: id not is empty")) + return + } + + localHost := strings.Contains(body.IPWhite, "127.0.0.1") || strings.Contains(body.IPWhite, "localhost") || strings.Contains(body.IPWhite, "::1") + if localHost || strings.Contains(body.IPWhite, "::ffff:") { + c.JSON(200, resp.ErrMsg("no support local host")) + return + } + + body.CreateBy = reqctx.LoginUserToUserName(c) + insertId := s.oauth2ClientService.Insert(body) + if insertId > 0 { + c.JSON(200, resp.OkData(insertId)) + return + } + c.JSON(200, resp.Err(nil)) +} + +// Edit 更新 +// +// PUT / +func (s Oauth2ClientController) Edit(c *gin.Context) { + var body model.Oauth2Client + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) + return + } + if body.Id <= 0 { + c.JSON(422, resp.CodeMsg(422002, "bind err: id is empty")) + return + } + + localHost := strings.Contains(body.IPWhite, "127.0.0.1") || strings.Contains(body.IPWhite, "localhost") || strings.Contains(body.IPWhite, "::1") + if localHost || strings.Contains(body.IPWhite, "::ffff:") { + c.JSON(200, resp.ErrMsg("no support local host")) + return + } + + // 查询信息 + info := s.oauth2ClientService.FindById(body.Id) + if info.ClientId == "" || info.Id != body.Id { + c.JSON(200, resp.ErrMsg("modification failed, data not exist")) + return + } + + info.Title = body.Title + info.IPWhite = body.IPWhite + info.Remark = body.Remark + info.UpdateBy = reqctx.LoginUserToUserName(c) + rowsAffected := s.oauth2ClientService.Update(info) + if rowsAffected > 0 { + c.JSON(200, resp.Ok(nil)) + return + } + c.JSON(200, resp.Err(nil)) +} + +// Remove 删除 +// +// DELETE /:id +func (s Oauth2ClientController) Remove(c *gin.Context) { + language := reqctx.AcceptLanguage(c) + id := c.Param("id") + if id == "" { + c.JSON(422, resp.CodeMsg(422002, "bind err: id is empty")) + return + } + + // 处理字符转id数组后去重 + uniqueIDs := parse.RemoveDuplicatesToArray(id, ",") + // 转换成int64数组类型 + ids := make([]int64, 0) + for _, v := range uniqueIDs { + ids = append(ids, parse.Number(v)) + } + + rows, err := s.oauth2ClientService.DeleteByIds(ids) + if err != nil { + c.JSON(200, resp.ErrMsg(err.Error())) + return + } + msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows}) + c.JSON(200, resp.OkMsg(msg)) +} diff --git a/src/modules/oauth2/model/code_query.go b/src/modules/oauth2/model/code_query.go new file mode 100644 index 00000000..9c32a195 --- /dev/null +++ b/src/modules/oauth2/model/code_query.go @@ -0,0 +1,8 @@ +package model + +// CodeQuery 重定向授权码参数 +type CodeQuery struct { + RedirectUrl string `form:"redirectUrl" binding:"required"` // 授权回调地址 + ClientId string `form:"clientId" binding:"required"` // 申请得到的客户端ID + State string `form:"state" binding:"required"` // 随机字符串,认证服务器会原封不动地返回这个值 +} diff --git a/src/modules/oauth2/model/oauth2_client.go b/src/modules/oauth2/model/oauth2_client.go new file mode 100644 index 00000000..df8bc8ea --- /dev/null +++ b/src/modules/oauth2/model/oauth2_client.go @@ -0,0 +1,22 @@ +package model + +// Oauth2Client 用户授权第三方应用表 oauth2_client +type Oauth2Client struct { + Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // 应用ID + ClientId string `gorm:"column:client_id" json:"clientId"` // 应用的唯一标识 + ClientSecret string `gorm:"column:client_secret" json:"clientSecret"` // 应用的凭证秘钥 + Title string `gorm:"column:title" json:"title"` // 应用名称 + IPWhite string `gorm:"column:ip_white" json:"ipWhite"` // IP白名单 + DelFlag string `gorm:"column:del_flag" json:"delFlag"` // 删除标记(0存在 1删除) + LoginIp string `gorm:"column:login_ip" json:"loginIp"` // 最后登录IP + LoginTime int64 `gorm:"column:login_time" json:"loginTime"` // 最后登录时间 + CreateBy string `gorm:"column:create_by" json:"createBy"` // 创建者 + CreateTime int64 `gorm:"column:create_time" json:"createTime"` // 创建时间 + UpdateBy string `gorm:"column:update_by" json:"updateBy"` // 更新者 + UpdateTime int64 `gorm:"column:update_time" json:"updateTime"` // 更新时间 + Remark string `gorm:"column:remark" json:"remark"` // 备注 +} + +func (*Oauth2Client) TableName() string { + return "oauth2_client" +} diff --git a/src/modules/oauth2/model/oauth2_log_login.go b/src/modules/oauth2/model/oauth2_log_login.go new file mode 100644 index 00000000..724202ab --- /dev/null +++ b/src/modules/oauth2/model/oauth2_log_login.go @@ -0,0 +1,19 @@ +package model + +// Oauth2LogLogin 用户授权第三方应用登录日志表 +type Oauth2LogLogin struct { + ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 登录ID + ClientId string `json:"clientId" gorm:"column:client_id"` // 应用的唯一标识 + LoginIp string `json:"loginIp" gorm:"column:login_ip"` // 登录IP地址 + LoginLocation string `json:"loginLocation" gorm:"column:login_location"` // 登录地点 + Browser string `json:"browser" gorm:"column:browser"` // 浏览器类型 + OS string `json:"os" gorm:"column:os"` // 操作系统 + StatusFlag string `json:"statusFlag" gorm:"column:status_flag"` // 登录状态(0失败 1成功) + Msg string `json:"msg" gorm:"column:msg"` // 提示消息 + LoginTime int64 `json:"loginTime" gorm:"column:login_time"` // 登录时间 +} + +// TableName 表名称 +func (*Oauth2LogLogin) TableName() string { + return "oauth2_log_login" +} diff --git a/src/modules/oauth2/model/token_body.go b/src/modules/oauth2/model/token_body.go new file mode 100644 index 00000000..2f82ab8f --- /dev/null +++ b/src/modules/oauth2/model/token_body.go @@ -0,0 +1,10 @@ +package model + +// TokenBody 获取访问令牌参数 +type TokenBody struct { + ClientId string `json:"clientId" binding:"required"` // 申请应用时获得的client_id + ClientSecret string `json:"clientSecret" binding:"required"` // 申请应用时分配的secret + GrantType string `json:"grantType" binding:"required,oneof=authorization_code refresh_token"` // 请求的类型,此处的值固定为 authorization_code/refresh_token + Code string `json:"code"` // 授权拿到的code值 + RefreshToken string `json:"refreshToken"` // 刷新令牌 +} diff --git a/src/modules/oauth2/oauth2.go b/src/modules/oauth2/oauth2.go new file mode 100644 index 00000000..edf1e10a --- /dev/null +++ b/src/modules/oauth2/oauth2.go @@ -0,0 +1,83 @@ +package oauth2 + +import ( + "github.com/gin-gonic/gin" + + "be.ems/src/framework/logger" + "be.ems/src/framework/middleware" + monitorController "be.ems/src/modules/monitor/controller" + "be.ems/src/modules/oauth2/controller" +) + +// Setup 模块路由注册 +func Setup(router *gin.Engine) { + logger.Infof("开始加载 ====> oauth2 模块路由") + + // 客户端授权管理 + oauth2ClientGroup := router.Group("/oauth2/client") + { + oauth2ClientGroup.GET("/list", + middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}), + controller.NewOauth2Client.List, + ) + oauth2ClientGroup.GET("/:clientId", + middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}), + controller.NewOauth2Client.Info, + ) + oauth2ClientGroup.POST("", + middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}), + middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_INSERT)), + controller.NewOauth2Client.Add, + ) + oauth2ClientGroup.PUT("", + middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}), + middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_UPDATE)), + controller.NewOauth2Client.Edit, + ) + oauth2ClientGroup.DELETE("/:id", + middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}), + middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_DELETE)), + controller.NewOauth2Client.Remove, + ) + } + + // 授权认证 + oauth2Group := router.Group("/oauth2") + { + oauth2Group.GET("/authorize", + middleware.RateLimit(middleware.LimitOption{ + Time: 60, + Count: 30, + Type: middleware.LIMIT_IP, + }), + controller.NewOauth2.Authorize, + ) + oauth2Group.POST("/token", + middleware.RateLimit(middleware.LimitOption{ + Time: 180, + Count: 15, + Type: middleware.LIMIT_IP, + }), + controller.NewOauth2.Token, + ) + oauth2Group.POST("/refresh-token", + middleware.RateLimit(middleware.LimitOption{ + Time: 60, + Count: 5, + Type: middleware.LIMIT_IP, + }), + controller.NewOauth2.RefreshToken, + ) + } + + // ==== 开放接口 ==== + + openApiGroup := router.Group("/open-api") + { + openApiGroup.GET("/monitor/system", + middleware.AuthorizeOauth2(nil), + monitorController.NewSystem.Info, + ) + } + +} diff --git a/src/modules/oauth2/repository/oauth2_client.go b/src/modules/oauth2/repository/oauth2_client.go new file mode 100644 index 00000000..1c7253c4 --- /dev/null +++ b/src/modules/oauth2/repository/oauth2_client.go @@ -0,0 +1,168 @@ +package repository + +import ( + "fmt" + "time" + + "be.ems/src/framework/database/db" + "be.ems/src/framework/logger" + "be.ems/src/modules/oauth2/model" +) + +// NewOauth2Client 实例化数据层 +var NewOauth2Client = &Oauth2Client{} + +// Oauth2Client 用户授权第三方应用表 数据层处理 +type Oauth2Client struct{} + +// SelectByPage 分页查询集合 +func (r Oauth2Client) SelectByPage(query map[string]string) ([]model.Oauth2Client, int64) { + tx := db.DB("").Model(&model.Oauth2Client{}) + tx = tx.Where("del_flag = 0") + // 查询条件拼接 + if v, ok := query["clientId"]; ok && v != "" { + tx = tx.Where("client_id = ?", v) + } + if v, ok := query["title"]; ok && v != "" { + tx = tx.Where("title like ?", v+"%") + } + if v, ok := query["beginTime"]; ok && v != "" { + if len(v) == 10 { + v = fmt.Sprintf("%s000", v) + tx = tx.Where("login_time >= ?", v) + } else if len(v) == 13 { + tx = tx.Where("login_time >= ?", v) + } + } + if v, ok := query["endTime"]; ok && v != "" { + if len(v) == 10 { + v = fmt.Sprintf("%s999", v) + tx = tx.Where("login_time <= ?", v) + } else if len(v) == 13 { + tx = tx.Where("login_time <= ?", v) + } + } + + // 查询结果 + var total int64 = 0 + rows := []model.Oauth2Client{} + + // 查询数量为0直接返回 + if err := tx.Count(&total).Error; err != nil || total <= 0 { + return rows, total + } + + // 查询数据分页 + pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"]) + tx = tx.Limit(pageSize).Offset(pageSize * pageNum) + err := tx.Find(&rows).Error + if err != nil { + return rows, total + } + return rows, total +} + +// Select 查询集合 +func (r Oauth2Client) Select(param model.Oauth2Client) []model.Oauth2Client { + tx := db.DB("").Model(&model.Oauth2Client{}) + // 查询条件拼接 + if param.ClientId != "" { + tx = tx.Where("client_id = ?", param.ClientId) + } + if param.Title != "" { + tx = tx.Where("title like ?", param.Title+"%") + } + + // 查询数据 + rows := []model.Oauth2Client{} + if err := tx.Find(&rows).Error; err != nil { + return rows + } + return rows +} + +// SelectByIds 通过ID查询信息 +func (r Oauth2Client) SelectByIds(ids []int64) []model.Oauth2Client { + rows := []model.Oauth2Client{} + if len(ids) <= 0 { + return rows + } + tx := db.DB("").Model(&model.Oauth2Client{}) + // 构建查询条件 + tx = tx.Where("id in ? and del_flag = 0", ids) + // 查询数据 + if err := tx.Find(&rows).Error; err != nil { + logger.Errorf("query find err => %v", err.Error()) + return rows + } + return rows +} + +// Insert 新增信息 返回新增数据ID +func (r Oauth2Client) Insert(param model.Oauth2Client) int64 { + if param.CreateBy != "" { + ms := time.Now().UnixMilli() + param.UpdateBy = param.CreateBy + param.UpdateTime = ms + param.CreateTime = ms + param.DelFlag = "0" + } + // 执行插入 + if err := db.DB("").Create(¶m).Error; err != nil { + logger.Errorf("insert err => %v", err.Error()) + return 0 + } + return param.Id +} + +// Update 修改信息 返回受影响行数 +func (r Oauth2Client) Update(param model.Oauth2Client) int64 { + if param.Id <= 0 { + return 0 + } + if param.UpdateBy != "" { + param.UpdateTime = time.Now().UnixMilli() + } + tx := db.DB("").Model(&model.Oauth2Client{}) + // 构建查询条件 + tx = tx.Where("id = ?", param.Id) + tx = tx.Omit("id", "del_flag", "create_by", "create_time") + // 执行更新 + if err := tx.Updates(param).Error; err != nil { + logger.Errorf("update err => %v", err.Error()) + return 0 + } + return tx.RowsAffected +} + +// DeleteByIds 批量删除信息 返回受影响行数 +func (r Oauth2Client) DeleteByIds(ids []int64) int64 { + if len(ids) <= 0 { + return 0 + } + tx := db.DB("").Model(&model.Oauth2Client{}) + // 构建查询条件 + tx = tx.Where("id in ?", ids) + // 执行更新删除标记 + if err := tx.Update("del_flag", "1").Error; err != nil { + logger.Errorf("update err => %v", err.Error()) + return 0 + } + return tx.RowsAffected +} + +// SelectByClientId 通过clientId查询 +func (r Oauth2Client) SelectByClientId(clientId string) model.Oauth2Client { + item := model.Oauth2Client{} + if clientId == "" { + return item + } + tx := db.DB("").Model(&model.Oauth2Client{}) + // 构建查询条件 + tx = tx.Where("client_id = ? and del_flag = '0'", clientId) + // 查询数据 + if err := tx.Find(&item).Error; err != nil { + return item + } + return item +} diff --git a/src/modules/oauth2/repository/oauth2_log_login.go b/src/modules/oauth2/repository/oauth2_log_login.go new file mode 100644 index 00000000..f712b9d4 --- /dev/null +++ b/src/modules/oauth2/repository/oauth2_log_login.go @@ -0,0 +1,117 @@ +package repository + +import ( + "fmt" + "strings" + "time" + + "be.ems/src/framework/database/db" + "be.ems/src/framework/logger" + "be.ems/src/modules/oauth2/model" +) + +// NewOauth2LogLogin 实例化数据层 +var NewOauth2LogLogin = &Oauth2LogLoginRepository{} + +// Oauth2LogLoginRepository 用户授权第三方应用登录日志表 数据层处理 +type Oauth2LogLoginRepository struct{} + +// SelectByPage 分页查询集合 +func (r Oauth2LogLoginRepository) SelectByPage(query map[string]string) ([]model.Oauth2LogLogin, int64) { + tx := db.DB("").Model(&model.Oauth2LogLogin{}) + // 查询条件拼接 + if v, ok := query["loginIp"]; ok && v != "" { + tx = tx.Where("login_ip like ?", v+"%") + } + if v, ok := query["clientId"]; ok && v != "" { + tx = tx.Where("client_id = ?", v) + } + if v, ok := query["statusFlag"]; ok && v != "" { + tx = tx.Where("status_flag = ?", v) + } + if v, ok := query["beginTime"]; ok && v != "" { + if len(v) == 10 { + v = fmt.Sprintf("%s000", v) + tx = tx.Where("login_time >= ?", v) + } else if len(v) == 13 { + tx = tx.Where("login_time >= ?", v) + } + } + if v, ok := query["endTime"]; ok && v != "" { + if len(v) == 10 { + v = fmt.Sprintf("%s999", v) + tx = tx.Where("login_time <= ?", v) + } else if len(v) == 13 { + tx = tx.Where("login_time <= ?", v) + } + } + + // 查询结果 + var total int64 = 0 + rows := []model.Oauth2LogLogin{} + + // 查询数量为0直接返回 + if err := tx.Count(&total).Error; err != nil || total <= 0 { + return rows, total + } + + // 查询数据分页 + pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"]) + tx = tx.Limit(pageSize).Offset(pageSize * pageNum) + // 排序 + sortByStr, sortOk := query["sortBy"] + sortOrderStr, orderOk := query["sortOrder"] + if sortOk && sortByStr != "" && orderOk && sortOrderStr != "" { + sortByArr := strings.Split(sortByStr, ",") + sortOrderArr := strings.Split(sortOrderStr, ",") + for i := range sortByArr { + sortBy := sortByArr[i] + sortOrder := sortOrderArr[i] + // 排序字段 + sort := "id" + if sortBy == "loginIp" { + sort = "login_ip" + } else if sortBy == "createTime" { + sort = "create_time" + } + // 排序方式 + order := "ASC" + if strings.HasPrefix(sortOrder, "asc") { + order = "ASC" + } else if strings.HasPrefix(sortOrder, "desc") { + order = "DESC" + } + tx = tx.Order(fmt.Sprintf("%s %s", sort, order)) + } + } else { + tx = tx.Order("id desc") + } + // 查询数据 + err := tx.Find(&rows).Error + if err != nil { + logger.Errorf("query find err => %v", err.Error()) + return rows, total + } + return rows, total +} + +// Insert 新增信息 返回新增的数据ID +func (r Oauth2LogLoginRepository) Insert(param model.Oauth2LogLogin) int64 { + param.LoginTime = time.Now().UnixMilli() + // 执行插入 + if err := db.DB("").Create(¶m).Error; err != nil { + logger.Errorf("insert err => %v", err.Error()) + return 0 + } + return param.ID +} + +// Clean 清空信息 +func (r Oauth2LogLoginRepository) Clean() int64 { + tx := db.DB("").Delete(&model.Oauth2LogLogin{}) + if err := tx.Error; err != nil { + logger.Errorf("delete err => %v", err.Error()) + return 0 + } + return tx.RowsAffected +} diff --git a/src/modules/oauth2/service/oauth2.go b/src/modules/oauth2/service/oauth2.go new file mode 100644 index 00000000..40293622 --- /dev/null +++ b/src/modules/oauth2/service/oauth2.go @@ -0,0 +1,86 @@ +package service + +import ( + "fmt" + "strings" + "time" + + "be.ems/src/framework/constants" + "be.ems/src/framework/database/redis" + "be.ems/src/framework/token" + "be.ems/src/framework/utils/crypto" + "be.ems/src/framework/utils/generate" + "be.ems/src/modules/oauth2/model" + "be.ems/src/modules/oauth2/repository" +) + +// NewOauth2Service 实例化服务层 +var NewOauth2Service = &Oauth2Service{ + oauth2ClientRepository: repository.NewOauth2Client, +} + +// Oauth2Service 用户授权第三方应用信息 服务层处理 +type Oauth2Service struct { + oauth2ClientRepository *repository.Oauth2Client // 用户授权第三方应用表 +} + +// CreateCode 创建授权码 +func (s Oauth2Service) CreateCode() string { + code := generate.Code(8) + uuid := crypto.MD5(code) + verifyKey := constants.CACHE_OAUTH2_CODE + ":" + uuid + // 授权码有效期,单位秒 + codeExpiration := 2 * 60 * time.Second + _ = redis.Set("", verifyKey, code, codeExpiration) + return code +} + +// ValidateCode 校验授权码 +func (s Oauth2Service) ValidateCode(code string) error { + if len(code) > 16 { + return fmt.Errorf("code length error") + } + uuid := crypto.MD5(code) + verifyKey := constants.CACHE_OAUTH2_CODE + ":" + uuid + captcha, _ := redis.Get("", verifyKey) + if captcha == "" { + return fmt.Errorf("code expire") + } + _ = redis.Del("", verifyKey) + if captcha != strings.ToLower(code) { + return fmt.Errorf("code error") + } + return nil +} + +// ByClient 客户端信息 +func (s Oauth2Service) ByClient(clientId, clientSecret string) (token.Oauth2Info, error) { + info := token.Oauth2Info{} + + // 查询用户登录账号 + var item model.Oauth2Client + rows := s.oauth2ClientRepository.Select(model.Oauth2Client{ + ClientId: clientId, + ClientSecret: clientSecret, + }) + if len(rows) > 0 { + item = rows[0] + } + if item.ClientId == "" { + return info, fmt.Errorf("clientId or clientSecret is not exist") + } + + info.ClientId = clientId + // 用户权限组标识 + info.Scope = []string{} + return info, nil +} + +// UpdateLoginDateAndIP 更新登录时间和IP +func (s Oauth2Service) UpdateLoginDateAndIP(info token.Oauth2Info) bool { + item := s.oauth2ClientRepository.SelectByClientId(info.ClientId) + item.LoginIp = info.LoginIp + item.LoginTime = info.LoginTime + rows := s.oauth2ClientRepository.Update(item) + return rows > 0 +} diff --git a/src/modules/oauth2/service/oauth2_client.go b/src/modules/oauth2/service/oauth2_client.go new file mode 100644 index 00000000..6edc055f --- /dev/null +++ b/src/modules/oauth2/service/oauth2_client.go @@ -0,0 +1,65 @@ +package service + +import ( + "fmt" + + "be.ems/src/framework/utils/generate" + "be.ems/src/modules/oauth2/model" + "be.ems/src/modules/oauth2/repository" +) + +// NewOauth2ClientService 实例化服务层 +var NewOauth2ClientService = &Oauth2ClientService{ + oauth2ClientRepository: repository.NewOauth2Client, +} + +// Oauth2ClientService 用户授权第三方应用信息 服务层处理 +type Oauth2ClientService struct { + oauth2ClientRepository *repository.Oauth2Client // 用户授权第三方应用表 +} + +// FindByPage 分页查询 +func (s Oauth2ClientService) FindByPage(query map[string]string) ([]model.Oauth2Client, int64) { + return s.oauth2ClientRepository.SelectByPage(query) +} + +// FindById 查询ID +func (s Oauth2ClientService) FindById(id int64) model.Oauth2Client { + rows := s.oauth2ClientRepository.SelectByIds([]int64{id}) + if len(rows) > 0 { + return rows[0] + } + return model.Oauth2Client{} +} + +// FindByClientId 查询ClientId +func (s Oauth2ClientService) FindByClientId(clientId string) model.Oauth2Client { + return s.oauth2ClientRepository.SelectByClientId(clientId) +} + +// Insert 新增 +func (s Oauth2ClientService) Insert(param model.Oauth2Client) int64 { + param.ClientId = generate.Code(16) + param.ClientSecret = generate.Code(32) + return s.oauth2ClientRepository.Insert(param) +} + +// Update 更新 +func (s Oauth2ClientService) Update(param model.Oauth2Client) int64 { + return s.oauth2ClientRepository.Update(param) +} + +// DeleteByIds 批量删除 +func (s Oauth2ClientService) DeleteByIds(ids []int64) (int64, error) { + // 检查是否存在 + arr := s.oauth2ClientRepository.SelectByIds(ids) + if len(arr) <= 0 { + // return 0, fmt.Errorf("没有权限访问用户授权第三方应用数据!") + return 0, fmt.Errorf("No permission to access user-authorized third-party application data!") + } + if len(arr) == len(ids) { + return s.oauth2ClientRepository.DeleteByIds(ids), nil + } + // return 0, fmt.Errorf("删除用户授权第三方应用信息失败!") + return 0, fmt.Errorf("Failed to delete user-authorized third-party application information!") +} diff --git a/src/modules/oauth2/service/oauth2_log_login.go b/src/modules/oauth2/service/oauth2_log_login.go new file mode 100644 index 00000000..e400fa9c --- /dev/null +++ b/src/modules/oauth2/service/oauth2_log_login.go @@ -0,0 +1,85 @@ +package service + +import ( + "strconv" + + "be.ems/src/framework/constants" + "be.ems/src/framework/utils/date" + "be.ems/src/framework/utils/file" + "be.ems/src/modules/oauth2/model" + "be.ems/src/modules/oauth2/repository" +) + +// NewOauth2LogLogin 实例化服务层 +var NewOauth2LogLogin = &Oauth2LogLoginService{ + oauth2LogLoginRepository: repository.NewOauth2LogLogin, +} + +// Oauth2LogLogin 用户授权第三方应用登录日志 服务层处理 +type Oauth2LogLoginService struct { + oauth2LogLoginRepository *repository.Oauth2LogLoginRepository // 用户授权第三方应用登录日志信息 +} + +// FindByPage 分页查询列表数据 +func (s Oauth2LogLoginService) FindByPage(query map[string]string) ([]model.Oauth2LogLogin, int64) { + return s.oauth2LogLoginRepository.SelectByPage(query) +} + +// Insert 新增信息 +func (s Oauth2LogLoginService) Insert(clientId, status, msg string, ilobArr [4]string) int64 { + sysOauth2LogLogin := model.Oauth2LogLogin{ + LoginIp: ilobArr[0], + LoginLocation: ilobArr[1], + OS: ilobArr[2], + Browser: ilobArr[3], + ClientId: clientId, + StatusFlag: status, + Msg: msg, + } + return s.oauth2LogLoginRepository.Insert(sysOauth2LogLogin) +} + +// Clean 清空用户授权第三方应用登录日志 +func (s Oauth2LogLoginService) Clean() int64 { + return s.oauth2LogLoginRepository.Clean() +} + +// ExportData 导出数据表格 +func (s Oauth2LogLoginService) ExportData(rows []model.Oauth2LogLogin, fileName string) (string, error) { + // 第一行表头标题 + headerCells := map[string]string{ + "A1": "序号", + "B1": "应用的唯一标识", + "C1": "登录状态", + "D1": "登录地址", + "E1": "登录地点", + "F1": "浏览器", + "G1": "操作系统", + "H1": "提示消息", + "I1": "访问时间", + } + // 从第二行开始的数据 + dataCells := make([]map[string]any, 0) + for i, row := range rows { + idx := strconv.Itoa(i + 2) + // 状态 + statusValue := "失败" + if row.StatusFlag == constants.STATUS_YES { + statusValue = "成功" + } + dataCells = append(dataCells, map[string]any{ + "A" + idx: row.ID, + "B" + idx: row.ClientId, + "C" + idx: statusValue, + "D" + idx: row.LoginIp, + "E" + idx: row.LoginLocation, + "F" + idx: row.Browser, + "G" + idx: row.OS, + "H" + idx: row.Msg, + "I" + idx: date.ParseDateToStr(row.LoginTime, date.YYYY_MM_DD_HH_MM_SS), + }) + } + + // 导出数据表格 + return file.WriteSheet(headerCells, dataCells, fileName, "") +} diff --git a/src/modules/open_api/open_api.go b/src/modules/open_api/open_api.go deleted file mode 100644 index aa882097..00000000 --- a/src/modules/open_api/open_api.go +++ /dev/null @@ -1,12 +0,0 @@ -package open_api - -import ( - "be.ems/src/framework/logger" - - "github.com/gin-gonic/gin" -) - -// 模块路由注册 -func Setup(router *gin.Engine) { - logger.Infof("开始加载 ====> open_api 模块路由") -} diff --git a/src/modules/system/controller/sys_profile.go b/src/modules/system/controller/sys_profile.go index e6b1e2f3..26d6ed6e 100644 --- a/src/modules/system/controller/sys_profile.go +++ b/src/modules/system/controller/sys_profile.go @@ -104,18 +104,18 @@ func (s *SysProfileController) UpdateProfile(c *gin.Context) { } if err := c.ShouldBindBodyWithJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) - c.JSON(422, resp.CodeMsg(40422, errMsgs)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) return } // 登录用户信息 - loginUser, err := reqctx.LoginUser(c) + info, err := reqctx.LoginUser(c) if err != nil { - c.JSON(401, resp.CodeMsg(401, i18n.TKey(language, err.Error()))) + c.JSON(401, resp.CodeMsg(401002, err.Error())) return } - userId := loginUser.UserId - userName := loginUser.User.UserName + userId := info.UserId + userName := info.User.UserName // 检查手机号码格式并判断是否唯一 if body.Phone != "" { @@ -172,10 +172,9 @@ func (s *SysProfileController) UpdateProfile(c *gin.Context) { rows := s.sysUserService.Update(userInfo) if rows > 0 { // 更新缓存用户信息 - loginUser.User = userInfo - // 刷新令牌信息 - token.Cache(&loginUser) - + info.User = userInfo + // 更新信息 + token.UserInfoUpdate(info) c.JSON(200, resp.Ok(nil)) return } @@ -203,17 +202,17 @@ func (s *SysProfileController) PasswordUpdate(c *gin.Context) { } if err := c.ShouldBindBodyWithJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) - c.JSON(422, resp.CodeMsg(40422, errMsgs)) + c.JSON(422, resp.CodeMsg(422001, errMsgs)) return } // 登录用户信息 - loginUser, err := reqctx.LoginUser(c) + info, err := reqctx.LoginUser(c) if err != nil { - c.JSON(401, resp.CodeMsg(401, i18n.TKey(language, err.Error()))) + c.JSON(401, resp.CodeMsg(401002, err.Error())) return } - userId := loginUser.UserId + userId := info.UserId // 查询当前登录用户信息得到密码值 userInfo := s.sysUserService.FindById(userId) @@ -317,7 +316,7 @@ func (s *SysProfileController) PasswordForce(c *gin.Context) { // 更新缓存用户信息 userInfo.Password = "" // 移除令牌信息 - token.Remove(reqctx.Authorization(c)) + token.UserInfoRemove(reqctx.Authorization(c)) c.JSON(200, resp.Ok(nil)) return } diff --git a/src/modules/system/service/sys_config.go b/src/modules/system/service/sys_config.go index 3d06f8a5..68eca01d 100644 --- a/src/modules/system/service/sys_config.go +++ b/src/modules/system/service/sys_config.go @@ -99,7 +99,7 @@ func (s SysConfig) FindValueByKey(configKey string) string { } // 无缓存时读取数据放入缓存中 if configValue := s.sysConfigRepository.SelectValueByKey(configKey); configValue != "" { - _ = redis.Set("", cacheKey, configValue) + _ = redis.Set("", cacheKey, configValue, 0) return configValue } return "" @@ -113,7 +113,7 @@ func (s SysConfig) CacheLoad(configKey string) { for _, v := range sysConfigs { key := constants.CACHE_SYS_CONFIG + ":" + v.ConfigKey _ = redis.Del("", key) - _ = redis.Set("", key, v.ConfigValue) + _ = redis.Set("", key, v.ConfigValue, 0) } return } @@ -122,7 +122,7 @@ func (s SysConfig) CacheLoad(configKey string) { if cacheValue != "" { key := constants.CACHE_SYS_CONFIG + ":" + configKey _ = redis.Del("", key) - _ = redis.Set("", key, cacheValue) + _ = redis.Set("", key, cacheValue, 0) } } diff --git a/src/modules/system/service/sys_dict_type.go b/src/modules/system/service/sys_dict_type.go index 5dc046b3..888e6539 100644 --- a/src/modules/system/service/sys_dict_type.go +++ b/src/modules/system/service/sys_dict_type.go @@ -137,7 +137,7 @@ func (s SysDictType) FindDataByType(dictType string) []model.SysDictData { if len(data) > 0 { _ = redis.Del("", key) values, _ := json.Marshal(data) - _ = redis.Set("", key, string(values)) + _ = redis.Set("", key, string(values), 0) } } return data @@ -176,7 +176,7 @@ func (s SysDictType) CacheLoad(dictType string) { key := constants.CACHE_SYS_DICT + ":" + k _ = redis.Del("", key) values, _ := json.Marshal(v) - _ = redis.Set("", key, string(values)) + _ = redis.Set("", key, string(values), 0) } } diff --git a/src/modules/system/system.go b/src/modules/system/system.go index 3ec9b20b..d4cca368 100644 --- a/src/modules/system/system.go +++ b/src/modules/system/system.go @@ -20,31 +20,31 @@ func Setup(router *gin.Engine) { sysConfigGroup := router.Group("/system/config") { sysConfigGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:config:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:config:list"}}), controller.NewSysConfig.List, ) sysConfigGroup.GET("/:configId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:config:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:config:query"}}), controller.NewSysConfig.Info, ) sysConfigGroup.POST("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:config:add"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:config:add"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysConfig", middleware.BUSINESS_TYPE_INSERT)), controller.NewSysConfig.Add, ) sysConfigGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:config:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:config:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysConfig", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysConfig.Edit, ) sysConfigGroup.DELETE("/:configId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:config:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:config:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysConfig", middleware.BUSINESS_TYPE_DELETE)), controller.NewSysConfig.Remove, ) sysConfigGroup.PUT("/refresh", middleware.RepeatSubmit(5), - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:config:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:config:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysConfig", middleware.BUSINESS_TYPE_OTHER)), controller.NewSysConfig.Refresh, ) @@ -57,12 +57,12 @@ func Setup(router *gin.Engine) { controller.NewSysConfig.ConfigKey, ) sysConfigGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:config:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:config:export"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysConfig", middleware.BUSINESS_TYPE_EXPORT)), controller.NewSysConfig.Export, ) sysConfigGroup.PUT("/change-value", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:config:edit"}, "hasRoles": {"admin"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:config:edit"}, "hasRoles": {"admin"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysConfig", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysConfig.ConfigValue, ) @@ -72,38 +72,38 @@ func Setup(router *gin.Engine) { sysDeptGroup := router.Group("/system/dept") { sysDeptGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dept:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dept:list"}}), controller.NewSysDept.List, ) sysDeptGroup.GET("/:deptId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dept:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dept:query"}}), controller.NewSysDept.Info, ) sysDeptGroup.POST("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dept:add"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dept:add"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDept", middleware.BUSINESS_TYPE_INSERT)), controller.NewSysDept.Add, ) sysDeptGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dept:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dept:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDept", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysDept.Edit, ) sysDeptGroup.DELETE("/:deptId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dept:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dept:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDept", middleware.BUSINESS_TYPE_DELETE)), controller.NewSysDept.Remove, ) sysDeptGroup.GET("/list/exclude/:deptId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dept:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dept:list"}}), controller.NewSysDept.ExcludeChild, ) sysDeptGroup.GET("/tree", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dept:list", "system:user:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dept:list", "system:user:list"}}), controller.NewSysDept.Tree, ) sysDeptGroup.GET("/tree/role/:roleId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dept:query", "system:user:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dept:query", "system:user:edit"}}), controller.NewSysDept.TreeRole, ) } @@ -112,34 +112,34 @@ func Setup(router *gin.Engine) { sysDictDataGroup := router.Group("/system/dict/data") { sysDictDataGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:list"}}), controller.NewSysDictData.List, ) sysDictDataGroup.GET("/:dataId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:query"}}), controller.NewSysDictData.Info, ) sysDictDataGroup.POST("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:add"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:add"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDictData", middleware.BUSINESS_TYPE_INSERT)), controller.NewSysDictData.Add, ) sysDictDataGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDictData", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysDictData.Edit, ) sysDictDataGroup.DELETE("/:dataId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDictData", middleware.BUSINESS_TYPE_DELETE)), controller.NewSysDictData.Remove, ) sysDictDataGroup.GET("/type/:dictType", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewSysDictData.DictType, ) sysDictDataGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:export"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDictData", middleware.BUSINESS_TYPE_EXPORT)), controller.NewSysDictData.Export, ) @@ -149,39 +149,39 @@ func Setup(router *gin.Engine) { sysDictTypeGroup := router.Group("/system/dict/type") { sysDictTypeGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:list"}}), controller.NewSysDictType.List, ) sysDictTypeGroup.GET("/:dictId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:query"}}), controller.NewSysDictType.Info, ) sysDictTypeGroup.POST("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:add"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:add"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDictType", middleware.BUSINESS_TYPE_INSERT)), controller.NewSysDictType.Add, ) sysDictTypeGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDictType", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysDictType.Edit, ) sysDictTypeGroup.DELETE("/:dictId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDictType", middleware.BUSINESS_TYPE_DELETE)), controller.NewSysDictType.Remove, ) sysDictTypeGroup.PUT("/refresh", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDictType", middleware.BUSINESS_TYPE_OTHER)), controller.NewSysDictType.Refresh, ) sysDictTypeGroup.GET("/options", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:query"}}), controller.NewSysDictType.Options, ) sysDictTypeGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:dict:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:dict:export"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysDictType", middleware.BUSINESS_TYPE_EXPORT)), controller.NewSysDictType.Export, ) @@ -191,21 +191,21 @@ func Setup(router *gin.Engine) { sysLogLoginGroup := router.Group("/system/log/login") { sysLogLoginGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:log:login:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:log:login:list"}}), controller.NewSysLogLogin.List, ) sysLogLoginGroup.DELETE("/clean", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:log:login:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:log:login:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysLogLogin", middleware.BUSINESS_TYPE_CLEAN)), controller.NewSysLogLogin.Clean, ) sysLogLoginGroup.PUT("/unlock/:userName", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:log:login:unlock"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:log:login:unlock"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysLogLogin", middleware.BUSINESS_TYPE_OTHER)), controller.NewSysLogLogin.Unlock, ) sysLogLoginGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:log:login:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:log:login:export"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysLogLogin", middleware.BUSINESS_TYPE_EXPORT)), controller.NewSysLogLogin.Export, ) @@ -215,16 +215,16 @@ func Setup(router *gin.Engine) { sysLogOperateGroup := router.Group("/system/log/operate") { sysLogOperateGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:log:operate:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:log:operate:list"}}), controller.NewSysLogOperate.List, ) sysLogOperateGroup.DELETE("/clean", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:log:operate:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:log:operate:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysLogOper", middleware.BUSINESS_TYPE_CLEAN)), controller.NewSysLogOperate.Clean, ) sysLogOperateGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:log:operate:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:log:operate:export"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysLogOper", middleware.BUSINESS_TYPE_EXPORT)), controller.NewSysLogOperate.Export, ) @@ -234,34 +234,34 @@ func Setup(router *gin.Engine) { sysMenuGroup := router.Group("/system/menu") { sysMenuGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:menu:list"}, "hasRoles": {"admin"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:menu:list"}, "hasRoles": {"admin"}}), controller.NewSysMenu.List, ) sysMenuGroup.GET("/:menuId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:menu:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:menu:query"}}), controller.NewSysMenu.Info, ) sysMenuGroup.POST("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:menu:add"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:menu:add"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysMenu", middleware.BUSINESS_TYPE_INSERT)), controller.NewSysMenu.Add, ) sysMenuGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:menu:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:menu:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysMenu", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysMenu.Edit, ) sysMenuGroup.DELETE("/:menuId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:menu:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:menu:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysMenu", middleware.BUSINESS_TYPE_DELETE)), controller.NewSysMenu.Remove, ) sysMenuGroup.GET("/tree", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:menu:list", "system:role:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:menu:list", "system:role:query"}}), controller.NewSysMenu.Tree, ) sysMenuGroup.GET("/tree/role/:roleId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:menu:list", "system:role:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:menu:list", "system:role:query"}}), controller.NewSysMenu.TreeRole, ) } @@ -270,30 +270,30 @@ func Setup(router *gin.Engine) { sysPostGroup := router.Group("/system/post") { sysPostGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:post:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:post:list"}}), controller.NewSysPost.List, ) sysPostGroup.GET("/:postId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:post:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:post:query"}}), controller.NewSysPost.Info, ) sysPostGroup.POST("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:post:add"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:post:add"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysPost", middleware.BUSINESS_TYPE_INSERT)), controller.NewSysPost.Add, ) sysPostGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:post:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:post:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysPost", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysPost.Edit, ) sysPostGroup.DELETE("/:postId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:post:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:post:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysPost", middleware.BUSINESS_TYPE_DELETE)), controller.NewSysPost.Remove, ) sysPostGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:post:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:post:export"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysPost", middleware.BUSINESS_TYPE_EXPORT)), controller.NewSysPost.Export, ) @@ -303,21 +303,21 @@ func Setup(router *gin.Engine) { sysProfileGroup := router.Group("/system/user/profile") { sysProfileGroup.GET("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewSysProfile.Info, ) sysProfileGroup.PUT("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysProfile", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysProfile.UpdateProfile, ) sysProfileGroup.PUT("/password", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysProfile", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysProfile.PasswordUpdate, ) sysProfileGroup.PUT("/password-force", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysProfile", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysProfile.PasswordForce, ) @@ -327,51 +327,51 @@ func Setup(router *gin.Engine) { sysRoleGroup := router.Group("/system/role") { sysRoleGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:role:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:role:list"}}), controller.NewSysRole.List, ) sysRoleGroup.GET("/:roleId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:role:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:role:query"}}), controller.NewSysRole.Info, ) sysRoleGroup.POST("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:role:add"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:role:add"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysRole", middleware.BUSINESS_TYPE_INSERT)), controller.NewSysRole.Add, ) sysRoleGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:role:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:role:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysRole", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysRole.Edit, ) sysRoleGroup.DELETE("/:roleId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:role:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:role:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysRole", middleware.BUSINESS_TYPE_DELETE)), controller.NewSysRole.Remove, ) sysRoleGroup.PUT("/status", middleware.RepeatSubmit(5), - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:role:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:role:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysRole", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysRole.Status, ) sysRoleGroup.PUT("/data-scope", middleware.RepeatSubmit(5), - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysRole", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysRole.DataScope, ) sysRoleGroup.GET("/user/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:list"}}), controller.NewSysRole.UserAuthList, ) sysRoleGroup.PUT("/user/auth", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysRole", middleware.BUSINESS_TYPE_GRANT)), controller.NewSysRole.UserAuthChecked, ) sysRoleGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:export"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysRole", middleware.BUSINESS_TYPE_EXPORT)), controller.NewSysRole.Export, ) @@ -381,50 +381,50 @@ func Setup(router *gin.Engine) { sysUserGroup := router.Group("/system/user") { sysUserGroup.GET("/list", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:list"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:list"}}), controller.NewSysUser.List, ) sysUserGroup.GET("/:userId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:query"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:query"}}), controller.NewSysUser.Info, ) sysUserGroup.POST("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:add"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:add"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysUser", middleware.BUSINESS_TYPE_INSERT)), controller.NewSysUser.Add, ) sysUserGroup.PUT("", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysUser", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysUser.Edit, ) sysUserGroup.DELETE("/:userId", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:remove"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:remove"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysUser", middleware.BUSINESS_TYPE_DELETE)), controller.NewSysUser.Remove, ) sysUserGroup.PUT("/password", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:resetPwd"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:resetPwd"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysUser", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysUser.Password, ) sysUserGroup.PUT("/status", middleware.RepeatSubmit(5), - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:edit"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:edit"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysUser", middleware.BUSINESS_TYPE_UPDATE)), controller.NewSysUser.Status, ) sysUserGroup.GET("/export", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:export"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:export"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysUser", middleware.BUSINESS_TYPE_EXPORT)), controller.NewSysUser.Export, ) sysUserGroup.GET("/import/template", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:import"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:import"}}), controller.NewSysUser.Template, ) sysUserGroup.POST("/import", - middleware.PreAuthorize(map[string][]string{"hasPerms": {"system:user:import"}}), + middleware.AuthorizeUser(map[string][]string{"hasPerms": {"system:user:import"}}), middleware.OperateLog(middleware.OptionNew("log.operate.title.sysUser", middleware.BUSINESS_TYPE_IMPORT)), controller.NewSysUser.Import, ) diff --git a/src/modules/tool/tool.go b/src/modules/tool/tool.go index 70385683..ce37e8c1 100644 --- a/src/modules/tool/tool.go +++ b/src/modules/tool/tool.go @@ -17,16 +17,16 @@ func Setup(router *gin.Engine) { iperfGroup := router.Group("/tool/iperf") { iperfGroup.GET("/v", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewIPerf.Version, ) iperfGroup.POST("/i", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.iperf", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewIPerf.Install, ) iperfGroup.GET("/run", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.iperf", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewIPerf.Run, ) @@ -36,20 +36,20 @@ func Setup(router *gin.Engine) { pingGroup := router.Group("/tool/ping") { pingGroup.POST("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewPing.Statistics, ) pingGroup.GET("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.ping", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewPing.StatisticsOn, ) pingGroup.GET("/v", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewPing.Version, ) pingGroup.GET("/run", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.ping", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewPing.Run, ) diff --git a/src/modules/trace/trace.go b/src/modules/trace/trace.go index 273a2c4a..bb5dd4dc 100644 --- a/src/modules/trace/trace.go +++ b/src/modules/trace/trace.go @@ -21,17 +21,17 @@ func Setup(router *gin.Engine) { tcpdumpGroup := router.Group("/trace/tcpdump") { tcpdumpGroup.POST("/start", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.tcpdump", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewTCPdump.DumpStart, ) tcpdumpGroup.POST("/stop", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.tcpdump", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewTCPdump.DumpStop, ) tcpdumpGroup.POST("/upf", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.tcpdump", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewTCPdump.UPFTrace, ) @@ -41,30 +41,30 @@ func Setup(router *gin.Engine) { packetGroup := router.Group("/trace/packet") { packetGroup.GET("/devices", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewPacket.Devices, ) packetGroup.POST("/start", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.packet", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewPacket.Start, ) packetGroup.POST("/stop", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.packet", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewPacket.Stop, ) packetGroup.PUT("/filter", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.packet", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewPacket.Filter, ) packetGroup.PUT("/keep-alive", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewPacket.KeepAlive, ) packetGroup.GET("/filePull", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewPacket.FilePull, ) } @@ -96,25 +96,25 @@ func Setup(router *gin.Engine) { taskGroup := router.Group("/trace/task") { taskGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewTraceTask.List, ) taskGroup.GET("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewTraceTask.Info, ) taskGroup.POST("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.task", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewTraceTask.Add, ) taskGroup.DELETE("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.task", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewTraceTask.Remove, ) taskGroup.GET("/filePull", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewTraceTask.FilePull, ) } @@ -123,15 +123,15 @@ func Setup(router *gin.Engine) { taskDataGroup := router.Group("/trace/data") { taskDataGroup.GET("/list", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewTraceData.List, ) taskDataGroup.GET("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewTraceData.Info, ) taskDataGroup.DELETE("/:id", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.taskData", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewTraceData.Remove, ) diff --git a/src/modules/ws/ws.go b/src/modules/ws/ws.go index 35e63f85..af8147f4 100644 --- a/src/modules/ws/ws.go +++ b/src/modules/ws/ws.go @@ -17,31 +17,31 @@ func Setup(router *gin.Engine) { wsGroup := router.Group("/ws") { wsGroup.GET("", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.ws", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewWSController.WS, ) wsGroup.GET("/test", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), controller.NewWSController.Test, ) wsGroup.GET("/ssh", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.ws", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewWSController.SSH, ) wsGroup.GET("/telnet", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.ws", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewWSController.Telnet, ) wsGroup.GET("/redis", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.ws", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewWSController.Redis, ) wsGroup.GET("/view", - middleware.PreAuthorize(nil), + middleware.AuthorizeUser(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.ws", collectlogs.BUSINESS_TYPE_OTHER)), controller.NewWSController.ShellView, )