From 5611c5acb6a75bb0fcec243fb8d61b2bf3d0b45e Mon Sep 17 00:00:00 2001 From: zicla Date: Mon, 3 Dec 2018 21:21:37 +0800 Subject: [PATCH] Add the frame for installation. --- build/db/dashboard.sql | 21 +++ build/db/db.sql | 162 ++++++++++++++++++++++++ build/db/download_token.sql | 14 ++ build/db/footprint.sql | 17 +++ build/db/image_cache.sql | 16 +++ build/db/matter.sql | 21 +++ build/db/preference.sql | 15 +++ build/db/session.sql | 12 ++ build/db/upload_token.sql | 17 +++ build/db/user.sql | 21 +++ build/doc/db.sql | 153 ---------------------- main.go | 7 +- rest/base_controller.go | 7 +- rest/bean.go | 8 ++ rest/config.go | 246 +++++++----------------------------- rest/context.go | 20 ++- rest/dashboard_service.go | 6 +- rest/footprint_service.go | 36 ++++-- rest/install.go | 41 ------ rest/install_controller.go | 104 +++++++++++++++ rest/logger.go | 2 +- rest/router.go | 88 ++++++++----- rest/util_string.go | 10 ++ rest/web_result.go | 1 + 24 files changed, 593 insertions(+), 452 deletions(-) create mode 100644 build/db/dashboard.sql create mode 100644 build/db/db.sql create mode 100644 build/db/download_token.sql create mode 100644 build/db/footprint.sql create mode 100644 build/db/image_cache.sql create mode 100644 build/db/matter.sql create mode 100644 build/db/preference.sql create mode 100644 build/db/session.sql create mode 100644 build/db/upload_token.sql create mode 100644 build/db/user.sql delete mode 100644 build/doc/db.sql create mode 100644 rest/install_controller.go diff --git a/build/db/dashboard.sql b/build/db/dashboard.sql new file mode 100644 index 0000000..6d4e65e --- /dev/null +++ b/build/db/dashboard.sql @@ -0,0 +1,21 @@ +CREATE TABLE `tank20_dashboard` +( + `uuid` char(36) NOT NULL, + `invoke_num` bigint(20) NOT NULL DEFAULT '0' COMMENT '当日访问量', + `total_invoke_num` bigint(20) NOT NULL DEFAULT '0' COMMENT '截至目前总访问量', + `uv` bigint(20) NOT NULL DEFAULT '0' COMMENT '当日UV', + `total_uv` bigint(20) NOT NULL DEFAULT '0' COMMENT '截至目前总UV', + `matter_num` bigint(20) NOT NULL DEFAULT '0' COMMENT '文件数量', + `total_matter_num` bigint(20) NOT NULL DEFAULT '0' COMMENT '截至目前文件数量', + `file_size` bigint(20) NOT NULL DEFAULT '0' COMMENT '当日文件大小', + `total_file_size` bigint(20) NOT NULL DEFAULT '0' COMMENT '截至目前文件总大小', + `avg_cost` bigint(20) NOT NULL DEFAULT '0' COMMENT '请求平均耗时 ms', + `dt` varchar(45) NOT NULL COMMENT '日期', + `sort` bigint(20) NOT NULL DEFAULT '0', + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + UNIQUE KEY `uq_dt` (`dt`), + KEY `idx_dt` (`dt`), + KEY `idx_ct` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='汇总表,离线统计'; \ No newline at end of file diff --git a/build/db/db.sql b/build/db/db.sql new file mode 100644 index 0000000..27c6d3d --- /dev/null +++ b/build/db/db.sql @@ -0,0 +1,162 @@ +CREATE TABLE `tank20_dashboard` +( + `uuid` char(36) NOT NULL, + `invoke_num` bigint(20) NOT NULL DEFAULT '0' COMMENT '当日访问量', + `total_invoke_num` bigint(20) NOT NULL DEFAULT '0' COMMENT '截至目前总访问量', + `uv` bigint(20) NOT NULL DEFAULT '0' COMMENT '当日UV', + `total_uv` bigint(20) NOT NULL DEFAULT '0' COMMENT '截至目前总UV', + `matter_num` bigint(20) NOT NULL DEFAULT '0' COMMENT '文件数量', + `total_matter_num` bigint(20) NOT NULL DEFAULT '0' COMMENT '截至目前文件数量', + `file_size` bigint(20) NOT NULL DEFAULT '0' COMMENT '当日文件大小', + `total_file_size` bigint(20) NOT NULL DEFAULT '0' COMMENT '截至目前文件总大小', + `avg_cost` bigint(20) NOT NULL DEFAULT '0' COMMENT '请求平均耗时 ms', + `dt` varchar(45) NOT NULL COMMENT '日期', + `sort` bigint(20) NOT NULL DEFAULT '0', + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + UNIQUE KEY `uq_dt` (`dt`), + KEY `idx_dt` (`dt`), + KEY `idx_ct` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='汇总表,离线统计'; + +CREATE TABLE `tank20_download_token` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid', + `matter_uuid` char(36) DEFAULT NULL COMMENT '文件标识', + `expire_time` timestamp NULL DEFAULT NULL COMMENT '授权访问的次数', + `ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip', + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`), + KEY `id_mu` (`matter_uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='下载的token表'; + +CREATE TABLE `tank20_footprint` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL, + `ip` varchar(45) DEFAULT NULL, + `host` varchar(45) DEFAULT NULL, + `uri` varchar(255) DEFAULT NULL, + `params` text, + `cost` int(11) DEFAULT '0' COMMENT '耗时 ms', + `success` tinyint(1) DEFAULT '1', + `sort` bigint(20) NOT NULL DEFAULT '0', + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + KEY `idx_ct` (`create_time`), + KEY `dix_ip` (`ip`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='访问记录表'; + +CREATE TABLE `tank20_image_cache` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL COMMENT '上传的用户id', + `matter_uuid` char(36) DEFAULT NULL, + `mode` varchar(512) DEFAULT NULL COMMENT '请求的uri', + `md5` varchar(45) DEFAULT NULL COMMENT '文件的md5值', + `size` bigint(20) DEFAULT '0' COMMENT '文件大小', + `path` varchar(255) DEFAULT NULL, + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`), + KEY `idx_mu` (`matter_uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='图片缓存表'; + +CREATE TABLE `tank20_matter` +( + `uuid` char(36) NOT NULL, + `puuid` varchar(45) DEFAULT NULL COMMENT '上一级的uuid', + `user_uuid` char(36) DEFAULT NULL COMMENT '上传的用户id', + `dir` tinyint(1) DEFAULT '0' COMMENT '是否是文件夹', + `alien` tinyint(1) DEFAULT '0', + `name` varchar(255) DEFAULT NULL COMMENT '文件名称', + `md5` varchar(45) DEFAULT NULL COMMENT '文件的md5值', + `size` bigint(20) DEFAULT '0' COMMENT '文件大小', + `privacy` tinyint(1) DEFAULT '0' COMMENT '文件是否是公有的', + `path` varchar(255) DEFAULT NULL, + `times` bigint(20) DEFAULT '0' COMMENT '下载次数', + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`), + KEY `idx_uu` (`user_uuid`), + KEY `idx_ct` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='file表'; + +CREATE TABLE `tank20_preference` +( + `uuid` char(36) NOT NULL, + `name` varchar(45) DEFAULT NULL COMMENT '网站名称', + `logo_url` varchar(255) DEFAULT NULL, + `favicon_url` varchar(255) DEFAULT NULL, + `footer_line1` varchar(1024) DEFAULT NULL, + `footer_line2` varchar(1024) DEFAULT NULL, + `version` varchar(45) DEFAULT NULL, + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='网站偏好设置表'; + +CREATE TABLE `tank20_session` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid', + `ip` varchar(45) DEFAULT NULL COMMENT '用户的ip地址', + `expire_time` timestamp NULL DEFAULT NULL, + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='session表'; + +CREATE TABLE `tank20_upload_token` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid', + `folder_uuid` char(36) DEFAULT NULL, + `matter_uuid` char(36) DEFAULT NULL, + `filename` varchar(255) DEFAULT NULL COMMENT '文件后缀名的过滤,可以只允许用户上传特定格式的文件。', + `privacy` tinyint(1) DEFAULT '1', + `size` bigint(20) DEFAULT '0', + `expire_time` timestamp NULL DEFAULT NULL, + `ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip', + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='上传的token表'; + +CREATE TABLE `tank20_user` +( + `uuid` char(36) NOT NULL, + `role` varchar(45) DEFAULT 'USER', + `username` varchar(255) DEFAULT NULL COMMENT '昵称', + `password` varchar(255) DEFAULT NULL COMMENT '密码', + `email` varchar(45) DEFAULT NULL COMMENT '邮箱', + `phone` varchar(45) DEFAULT NULL COMMENT '电话', + `gender` varchar(45) DEFAULT 'UNKNOWN' COMMENT '性别,默认未知', + `city` varchar(45) DEFAULT NULL COMMENT '城市', + `avatar_url` varchar(255) DEFAULT NULL COMMENT '头像链接', + `last_time` datetime DEFAULT NULL COMMENT '上次登录使劲按', + `last_ip` varchar(45) DEFAULT NULL, + `size_limit` int(11) DEFAULT '-1' COMMENT '该账号上传文件的大小限制,单位byte。<0 表示不设限制', + `status` varchar(45) DEFAULT 'OK', + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表描述'; diff --git a/build/db/download_token.sql b/build/db/download_token.sql new file mode 100644 index 0000000..0335a6e --- /dev/null +++ b/build/db/download_token.sql @@ -0,0 +1,14 @@ +CREATE TABLE `tank20_download_token` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid', + `matter_uuid` char(36) DEFAULT NULL COMMENT '文件标识', + `expire_time` timestamp NULL DEFAULT NULL COMMENT '授权访问的次数', + `ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip', + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`), + KEY `id_mu` (`matter_uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='下载的token表'; \ No newline at end of file diff --git a/build/db/footprint.sql b/build/db/footprint.sql new file mode 100644 index 0000000..c25104e --- /dev/null +++ b/build/db/footprint.sql @@ -0,0 +1,17 @@ +CREATE TABLE `tank20_footprint` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL, + `ip` varchar(45) DEFAULT NULL, + `host` varchar(45) DEFAULT NULL, + `uri` varchar(255) DEFAULT NULL, + `params` text, + `cost` int(11) DEFAULT '0' COMMENT '耗时 ms', + `success` tinyint(1) DEFAULT '1', + `sort` bigint(20) NOT NULL DEFAULT '0', + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + KEY `idx_ct` (`create_time`), + KEY `dix_ip` (`ip`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='访问记录表'; \ No newline at end of file diff --git a/build/db/image_cache.sql b/build/db/image_cache.sql new file mode 100644 index 0000000..dfd47a8 --- /dev/null +++ b/build/db/image_cache.sql @@ -0,0 +1,16 @@ +CREATE TABLE `tank20_image_cache` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL COMMENT '上传的用户id', + `matter_uuid` char(36) DEFAULT NULL, + `mode` varchar(512) DEFAULT NULL COMMENT '请求的uri', + `md5` varchar(45) DEFAULT NULL COMMENT '文件的md5值', + `size` bigint(20) DEFAULT '0' COMMENT '文件大小', + `path` varchar(255) DEFAULT NULL, + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`), + KEY `idx_mu` (`matter_uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='图片缓存表'; \ No newline at end of file diff --git a/build/db/matter.sql b/build/db/matter.sql new file mode 100644 index 0000000..e8f29e1 --- /dev/null +++ b/build/db/matter.sql @@ -0,0 +1,21 @@ +CREATE TABLE `tank20_matter` +( + `uuid` char(36) NOT NULL, + `puuid` varchar(45) DEFAULT NULL COMMENT '上一级的uuid', + `user_uuid` char(36) DEFAULT NULL COMMENT '上传的用户id', + `dir` tinyint(1) DEFAULT '0' COMMENT '是否是文件夹', + `alien` tinyint(1) DEFAULT '0', + `name` varchar(255) DEFAULT NULL COMMENT '文件名称', + `md5` varchar(45) DEFAULT NULL COMMENT '文件的md5值', + `size` bigint(20) DEFAULT '0' COMMENT '文件大小', + `privacy` tinyint(1) DEFAULT '0' COMMENT '文件是否是公有的', + `path` varchar(255) DEFAULT NULL, + `times` bigint(20) DEFAULT '0' COMMENT '下载次数', + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`), + KEY `idx_uu` (`user_uuid`), + KEY `idx_ct` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='file表'; \ No newline at end of file diff --git a/build/db/preference.sql b/build/db/preference.sql new file mode 100644 index 0000000..2428c5c --- /dev/null +++ b/build/db/preference.sql @@ -0,0 +1,15 @@ +CREATE TABLE `tank20_preference` +( + `uuid` char(36) NOT NULL, + `name` varchar(45) DEFAULT NULL COMMENT '网站名称', + `logo_url` varchar(255) DEFAULT NULL, + `favicon_url` varchar(255) DEFAULT NULL, + `footer_line1` varchar(1024) DEFAULT NULL, + `footer_line2` varchar(1024) DEFAULT NULL, + `version` varchar(45) DEFAULT NULL, + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='网站偏好设置表'; \ No newline at end of file diff --git a/build/db/session.sql b/build/db/session.sql new file mode 100644 index 0000000..9a2a4c7 --- /dev/null +++ b/build/db/session.sql @@ -0,0 +1,12 @@ +CREATE TABLE `tank20_session` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid', + `ip` varchar(45) DEFAULT NULL COMMENT '用户的ip地址', + `expire_time` timestamp NULL DEFAULT NULL, + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='session表'; \ No newline at end of file diff --git a/build/db/upload_token.sql b/build/db/upload_token.sql new file mode 100644 index 0000000..eaa77be --- /dev/null +++ b/build/db/upload_token.sql @@ -0,0 +1,17 @@ +CREATE TABLE `tank20_upload_token` +( + `uuid` char(36) NOT NULL, + `user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid', + `folder_uuid` char(36) DEFAULT NULL, + `matter_uuid` char(36) DEFAULT NULL, + `filename` varchar(255) DEFAULT NULL COMMENT '文件后缀名的过滤,可以只允许用户上传特定格式的文件。', + `privacy` tinyint(1) DEFAULT '1', + `size` bigint(20) DEFAULT '0', + `expire_time` timestamp NULL DEFAULT NULL, + `ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip', + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='上传的token表'; \ No newline at end of file diff --git a/build/db/user.sql b/build/db/user.sql new file mode 100644 index 0000000..8c8e9fe --- /dev/null +++ b/build/db/user.sql @@ -0,0 +1,21 @@ +CREATE TABLE `tank20_user` +( + `uuid` char(36) NOT NULL, + `role` varchar(45) DEFAULT 'USER', + `username` varchar(255) DEFAULT NULL COMMENT '昵称', + `password` varchar(255) DEFAULT NULL COMMENT '密码', + `email` varchar(45) DEFAULT NULL COMMENT '邮箱', + `phone` varchar(45) DEFAULT NULL COMMENT '电话', + `gender` varchar(45) DEFAULT 'UNKNOWN' COMMENT '性别,默认未知', + `city` varchar(45) DEFAULT NULL COMMENT '城市', + `avatar_url` varchar(255) DEFAULT NULL COMMENT '头像链接', + `last_time` datetime DEFAULT NULL COMMENT '上次登录使劲按', + `last_ip` varchar(45) DEFAULT NULL, + `size_limit` int(11) DEFAULT '-1' COMMENT '该账号上传文件的大小限制,单位byte。<0 表示不设限制', + `status` varchar(45) DEFAULT 'OK', + `sort` bigint(20) DEFAULT NULL, + `update_time` timestamp NULL DEFAULT NULL, + `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`uuid`), + UNIQUE KEY `id_UNIQUE` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表描述'; \ No newline at end of file diff --git a/build/doc/db.sql b/build/doc/db.sql deleted file mode 100644 index d34fd4c..0000000 --- a/build/doc/db.sql +++ /dev/null @@ -1,153 +0,0 @@ -CREATE TABLE `tank20_dashboard` ( - `uuid` char(36) NOT NULL, - `invoke_num` int(11) NOT NULL DEFAULT '0' COMMENT '当日访问量', - `total_invoke_num` int(11) NOT NULL DEFAULT '0' COMMENT '截至目前总访问量', - `uv` int(11) NOT NULL DEFAULT '0' COMMENT '当日UV', - `total_uv` int(11) NOT NULL DEFAULT '0' COMMENT '截至目前总UV', - `matter_num` int(11) NOT NULL DEFAULT '0' COMMENT '文件数量', - `total_matter_num` int(11) NOT NULL DEFAULT '0' COMMENT '截至目前文件数量', - `file_size` int(11) NOT NULL DEFAULT '0' COMMENT '当日文件大小', - `total_file_size` int(11) NOT NULL DEFAULT '0' COMMENT '截至目前文件总大小', - `avg_cost` int(11) NOT NULL DEFAULT '0' COMMENT '请求平均耗时 ms', - `dt` varchar(45) NOT NULL COMMENT '日期', - `sort` bigint(20) NOT NULL DEFAULT '0', - `update_time` timestamp NULL DEFAULT NULL, - `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`uuid`), - UNIQUE KEY `uq_dt` (`dt`), - KEY `idx_dt` (`dt`), - KEY `idx_ct` (`create_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='汇总表,离线统计'; - -CREATE TABLE `tank20_download_token` ( - `uuid` char(36) NOT NULL, - `user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid', - `matter_uuid` char(36) DEFAULT NULL COMMENT '文件标识', - `expire_time` timestamp NULL DEFAULT NULL COMMENT '授权访问的次数', - `ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip', - `sort` bigint(20) DEFAULT NULL, - `update_time` timestamp NULL DEFAULT NULL, - `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`uuid`), - UNIQUE KEY `id_UNIQUE` (`uuid`), - KEY `id_mu` (`matter_uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='下载的token表'; - -CREATE TABLE `tank20_footprint` ( - `uuid` char(36) NOT NULL, - `user_uuid` char(36) DEFAULT NULL, - `ip` varchar(45) DEFAULT NULL, - `host` varchar(45) DEFAULT NULL, - `uri` varchar(255) DEFAULT NULL, - `params` text, - `cost` int(11) DEFAULT '0' COMMENT '耗时 ms', - `success` tinyint(1) DEFAULT '1', - `sort` bigint(20) NOT NULL DEFAULT '0', - `update_time` timestamp NULL DEFAULT NULL, - `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`uuid`), - KEY `idx_ct` (`create_time`), - KEY `dix_ip` (`ip`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='访问记录表'; - -CREATE TABLE `tank20_image_cache` ( - `uuid` char(36) NOT NULL, - `user_uuid` char(36) DEFAULT NULL COMMENT '上传的用户id', - `matter_uuid` char(36) DEFAULT NULL, - `mode` varchar(512) DEFAULT NULL COMMENT '请求的uri', - `md5` varchar(45) DEFAULT NULL COMMENT '文件的md5值', - `size` bigint(20) DEFAULT '0' COMMENT '文件大小', - `path` varchar(255) DEFAULT NULL, - `sort` bigint(20) DEFAULT NULL, - `update_time` timestamp NULL DEFAULT NULL, - `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`uuid`), - UNIQUE KEY `id_UNIQUE` (`uuid`), - KEY `idx_mu` (`matter_uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='图片缓存表'; - -CREATE TABLE `tank20_matter` ( - `uuid` char(36) NOT NULL, - `puuid` varchar(45) DEFAULT NULL COMMENT '上一级的uuid', - `user_uuid` char(36) DEFAULT NULL COMMENT '上传的用户id', - `dir` tinyint(1) DEFAULT '0' COMMENT '是否是文件夹', - `alien` tinyint(1) DEFAULT '0', - `name` varchar(255) DEFAULT NULL COMMENT '文件名称', - `md5` varchar(45) DEFAULT NULL COMMENT '文件的md5值', - `size` bigint(20) DEFAULT '0' COMMENT '文件大小', - `privacy` tinyint(1) DEFAULT '0' COMMENT '文件是否是公有的', - `path` varchar(255) DEFAULT NULL, - `times` bigint(20) DEFAULT '0' COMMENT '下载次数', - `sort` bigint(20) DEFAULT NULL, - `update_time` timestamp NULL DEFAULT NULL, - `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`uuid`), - UNIQUE KEY `id_UNIQUE` (`uuid`), - KEY `idx_uu` (`user_uuid`), - KEY `idx_ct` (`create_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='file表'; - -CREATE TABLE `tank20_preference` ( - `uuid` char(36) NOT NULL, - `name` varchar(45) DEFAULT NULL COMMENT '网站名称', - `logo_url` varchar(255) DEFAULT NULL, - `favicon_url` varchar(255) DEFAULT NULL, - `footer_line1` varchar(1024) DEFAULT NULL, - `footer_line2` varchar(1024) DEFAULT NULL, - `version` varchar(45) DEFAULT NULL, - `sort` bigint(20) DEFAULT NULL, - `update_time` timestamp NULL DEFAULT NULL, - `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`uuid`), - UNIQUE KEY `id_UNIQUE` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='网站偏好设置表'; - -CREATE TABLE `tank20_session` ( - `uuid` char(36) NOT NULL, - `user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid', - `ip` varchar(45) DEFAULT NULL COMMENT '用户的ip地址', - `expire_time` timestamp NULL DEFAULT NULL, - `sort` bigint(20) DEFAULT NULL, - `update_time` timestamp NULL DEFAULT NULL, - `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`uuid`), - UNIQUE KEY `id_UNIQUE` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='session表'; - -CREATE TABLE `tank20_upload_token` ( - `uuid` char(36) NOT NULL, - `user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid', - `folder_uuid` char(36) DEFAULT NULL, - `matter_uuid` char(36) DEFAULT NULL, - `filename` varchar(255) DEFAULT NULL COMMENT '文件后缀名的过滤,可以只允许用户上传特定格式的文件。', - `privacy` tinyint(1) DEFAULT '1', - `size` bigint(20) DEFAULT '0', - `expire_time` timestamp NULL DEFAULT NULL, - `ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip', - `sort` bigint(20) DEFAULT NULL, - `update_time` timestamp NULL DEFAULT NULL, - `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`uuid`), - UNIQUE KEY `id_UNIQUE` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='上传的token表'; - -CREATE TABLE `tank20_user` ( - `uuid` char(36) NOT NULL, - `role` varchar(45) DEFAULT 'USER', - `username` varchar(255) DEFAULT NULL COMMENT '昵称', - `password` varchar(255) DEFAULT NULL COMMENT '密码', - `email` varchar(45) DEFAULT NULL COMMENT '邮箱', - `phone` varchar(45) DEFAULT NULL COMMENT '电话', - `gender` varchar(45) DEFAULT 'UNKNOWN' COMMENT '性别,默认未知', - `city` varchar(45) DEFAULT NULL COMMENT '城市', - `avatar_url` varchar(255) DEFAULT NULL COMMENT '头像链接', - `last_time` datetime DEFAULT NULL COMMENT '上次登录使劲按', - `last_ip` varchar(45) DEFAULT NULL, - `size_limit` int(11) DEFAULT '-1' COMMENT '该账号上传文件的大小限制,单位byte。<0 表示不设限制', - `status` varchar(45) DEFAULT 'OK', - `sort` bigint(20) DEFAULT NULL, - `update_time` timestamp NULL DEFAULT NULL, - `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`uuid`), - UNIQUE KEY `id_UNIQUE` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表描述'; diff --git a/main.go b/main.go index a1cca34..ff35708 100644 --- a/main.go +++ b/main.go @@ -14,13 +14,16 @@ func main() { rest.LOGGER.Init() defer rest.LOGGER.Destroy() - //将运行时参数装填到config中去。 - rest.PrepareConfigs() + + //装载配置文件,这个决定了是否需要执行安装过程 + rest.CONFIG.Init() + //全局运行的上下文 rest.CONTEXT.Init() defer rest.CONTEXT.Destroy() + http.Handle("/", rest.CONTEXT.Router) rest.LOGGER.Info("App started at http://localhost:%v", rest.CONFIG.ServerPort) diff --git a/rest/base_controller.go b/rest/base_controller.go index 1591a17..5afe763 100644 --- a/rest/base_controller.go +++ b/rest/base_controller.go @@ -82,14 +82,14 @@ func (this *BaseController) Wrap(f func(writer http.ResponseWriter, request *htt writer.Header().Set("Content-Type", "application/json;charset=UTF-8") //用json的方式输出返回值。 - var json = jsoniter.ConfigCompatibleWithStandardLibrary - b, err := json.Marshal(webResult) + b, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(webResult) this.PanicError(err) writer.WriteHeader(FetchHttpStatus(webResult.Code)) - fmt.Fprintf(writer, string(b)) + _, err = fmt.Fprintf(writer, string(b)) + this.PanicError(err) } else { //输出的内容是二进制的。 @@ -117,7 +117,6 @@ func (this *BaseController) Success(data interface{}) *WebResult { return webResult } - //允许跨域请求 func (this *BaseController) allowCORS(writer http.ResponseWriter) { writer.Header().Add("Access-Control-Allow-Origin", "*") diff --git a/rest/bean.go b/rest/bean.go index 8ef6b24..bd9cd6c 100644 --- a/rest/bean.go +++ b/rest/bean.go @@ -5,7 +5,11 @@ import ( ) type IBean interface { + //初始化方法 Init() + //所有配置都加载完成后调用的方法,包括数据库加载完毕 + ConfigPost() + //快速的Panic方法 PanicError(err error) } @@ -17,6 +21,10 @@ func (this *Bean) Init() { this.logger = LOGGER } +func (this *Bean) ConfigPost() { + +} + //处理错误的统一方法 可以省去if err!=nil 这段代码 func (this *Bean) PanicError(err error) { if err != nil { diff --git a/rest/config.go b/rest/config.go index 312772c..4139fc2 100644 --- a/rest/config.go +++ b/rest/config.go @@ -2,12 +2,8 @@ package rest import ( "encoding/json" - "flag" - "fmt" "github.com/json-iterator/go" "io/ioutil" - "os" - "strconv" "time" "unsafe" ) @@ -29,47 +25,28 @@ create database tank; grant all privileges on tank.* to tank identified by 'tank123'; flush privileges; */ -/* - 你也可以在运行时的参数中临时修改一些配置项: --MysqlHost=127.0.0.1 -MysqlPort=3306 -MysqlSchema=tank -MysqlUsername=tank -MysqlPassword=tank123 -*/ -var ( - CONFIG = &Config{ - //以下内容是默认配置项。 - - //默认监听端口号 - ServerPort: 6010, - //上传的文件路径,如果没有指定,默认在根目录下的matter文件夹中 - MatterPath: "", - //mysql相关配置。 - //数据库端口 - MysqlPort: 3306, - //数据库Host - MysqlHost: "127.0.0.1", - //数据库名字 - MysqlSchema: "tank", - //用户名 - MysqlUsername: "tank", - //密码 - MysqlPassword: "tank123", - //数据库连接信息。这一项是上面几项组合而得,不可直接配置。 - MysqlUrl: "%MysqlUsername:%MysqlPassword@tcp(%MysqlHost:%MysqlPort)/%MysqlSchema?charset=utf8&parseTime=True&loc=Local", - //超级管理员用户名,只能包含英文和数字 - AdminUsername: "admin", - //超级管理员邮箱 - AdminEmail: "admin@tank.eyeblue.cn", - //超级管理员密码 - AdminPassword: "123456", - } -) +var CONFIG = &Config{} //依赖外部定义的变量。 type Config struct { //默认监听端口号 ServerPort int + //数据库是否配置完备 + DBConfigured bool //上传的文件路径,要求不以/结尾。如果没有指定,默认在根目录下的matter文件夹中。eg: /var/www/matter MatterPath string + //数据库连接信息。 + MysqlUrl string + //配置文件中的项 + Item *ConfigItem +} +//和tank.json文件中的键值一一对应。 +type ConfigItem struct { + //默认监听端口号 + ServerPort int + //上传的文件路径,要求不以/结尾。如果没有指定,默认在根目录下的matter文件夹中。eg: /var/www/matter + MatterPath string //mysql相关配置。 //数据库端口 MysqlPort int @@ -81,52 +58,49 @@ type Config struct { MysqlUsername string //密码 MysqlPassword string - //数据库连接信息。 - MysqlUrl string - - //超级管理员用户名,只能包含英文和数字 - AdminUsername string - //超级管理员邮箱 - AdminEmail string - //超级管理员密码 - AdminPassword string } //验证配置文件的正确性。 -func (this *Config) validate() { +func (this *ConfigItem) validate() bool { if this.ServerPort == 0 { LOGGER.Error("ServerPort 未配置") + return false } if this.MysqlUsername == "" { LOGGER.Error("MysqlUsername 未配置") + return false } if this.MysqlPassword == "" { LOGGER.Error("MysqlPassword 未配置") + return false } if this.MysqlHost == "" { LOGGER.Error("MysqlHost 未配置") + return false } if this.MysqlPort == 0 { LOGGER.Error("MysqlPort 未配置") + return false } if this.MysqlSchema == "" { LOGGER.Error("MysqlSchema 未配置") + return false } - this.MysqlUrl = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", this.MysqlUsername, this.MysqlPassword, this.MysqlHost, this.MysqlPort, this.MysqlSchema) + return true } -//init方法只要这个包被引入了就一定会执行。 -func init() { +//验证配置文件是否完好 +func (this *Config) Init() { - //json中需要去特殊处理时间。 + //JSON初始化 jsoniter.RegisterTypeDecoderFunc("time.Time", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) { //如果使用time.UTC,那么时间会相差8小时 t, err := time.ParseInLocation("2006-01-02 15:04:05", iter.ReadString(), time.Local) @@ -142,171 +116,39 @@ func init() { //如果使用time.UTC,那么时间会相差8小时 stream.WriteString(t.Local().Format("2006-01-02 15:04:05")) }, nil) -} -//第一级. 从配置文件conf/tank.json中读取配置项 -func LoadConfigFromFile() { + //默认从6010端口启动 + CONFIG.ServerPort = 6010 + //读取配置文件 filePath := GetConfPath() + "/tank.json" content, err := ioutil.ReadFile(filePath) if err != nil { - LOGGER.Warn("无法找到配置文件:%s 将使用config.go中的默认配置项。", filePath) + LOGGER.Warn("即将进入安装过程,无法找到配置文件:%s", filePath) + this.DBConfigured = false } else { // 用 json.Unmarshal - err := json.Unmarshal(content, CONFIG) + err := json.Unmarshal(content, this.Item) if err != nil { - LOGGER.Panic("配置文件格式错误!") + LOGGER.Error("配置文件格式错误!") + this.DBConfigured = false + return } - } -} - -//第二级. 从环境变量中读取配置项 -func LoadConfigFromEnvironment() { - - tmpServerPort := os.Getenv("TANK_SERVER_PORT") - if tmpServerPort != "" { - i, e := strconv.Atoi(tmpServerPort) - if e == nil { - CONFIG.ServerPort = i - } else { - LOGGER.Panic("环境变量TANK_SERVER_PORT必须为整数!%v", tmpServerPort) + //验证项是否齐全 + itemValidate := this.Item.validate() + if !itemValidate { + this.DBConfigured = false + return } - } - tmpMatterPath := os.Getenv("TANK_MATTER_PATH") - if tmpMatterPath != "" { - CONFIG.MatterPath = tmpMatterPath - } - - tmpMysqlPort := os.Getenv("TANK_MYSQL_PORT") - if tmpMysqlPort != "" { - i, e := strconv.Atoi(tmpMysqlPort) - if e == nil { - CONFIG.MysqlPort = i - } else { - LOGGER.Panic("环境变量TANK_MYSQL_PORT必须为整数!%v", tmpMysqlPort) + if this.Item.MatterPath == "" { + CONFIG.MatterPath = GetHomePath() + "/matter" } - } + MakeDirAll(CONFIG.MatterPath) - tmpMysqlHost := os.Getenv("TANK_MYSQL_HOST") - if tmpMysqlHost != "" { - CONFIG.MysqlHost = tmpMysqlHost - } - tmpMysqlSchema := os.Getenv("TANK_MYSQL_SCHEMA") - if tmpMysqlSchema != "" { - CONFIG.MysqlSchema = tmpMysqlSchema - } - tmpMysqlUsername := os.Getenv("TANK_MYSQL_USERNAME") - if tmpMysqlUsername != "" { - CONFIG.MysqlUsername = tmpMysqlUsername - } - tmpMysqlPassword := os.Getenv("TANK_MYSQL_PASSWORD") - if tmpMysqlPassword != "" { - CONFIG.MysqlPassword = tmpMysqlPassword - } - tmpAdminUsername := os.Getenv("TANK_ADMIN_USERNAME") - if tmpAdminUsername != "" { - CONFIG.AdminUsername = tmpAdminUsername - } - tmpAdminEmail := os.Getenv("TANK_ADMIN_EMAIL") - if tmpAdminEmail != "" { - CONFIG.AdminEmail = tmpAdminEmail - } - tmpAdminPassword := os.Getenv("TANK_ADMIN_PASSWORD") - if tmpAdminPassword != "" { - CONFIG.AdminPassword = tmpAdminPassword + this.MysqlUrl = GetMysqlUrl(this.Item.MysqlPort, this.Item.MysqlHost, this.Item.MysqlSchema, this.Item.MysqlUsername, this.Item.MysqlPassword) + this.DBConfigured = true } } - -//第三级. 从程序参数中读取配置项 -func LoadConfigFromArguments() { - - //从运行时参数中读取,运行时参数具有更高优先级。 - //系统端口号 - ServerPortPtr := flag.Int("ServerPort", CONFIG.ServerPort, "server port") - - //日志和上传文件的路径 - MatterPathPtr := flag.String("MatterPath", CONFIG.MatterPath, "matter path") - - //mysql相关配置。 - MysqlPortPtr := flag.Int("MysqlPort", CONFIG.MysqlPort, "mysql port") - MysqlHostPtr := flag.String("MysqlHost", CONFIG.MysqlHost, "mysql host") - MysqlSchemaPtr := flag.String("MysqlSchema", CONFIG.MysqlSchema, "mysql schema") - MysqlUsernamePtr := flag.String("MysqlUsername", CONFIG.MysqlUsername, "mysql username") - MysqlPasswordPtr := flag.String("MysqlPassword", CONFIG.MysqlPassword, "mysql password") - - //超级管理员信息 - AdminUsernamePtr := flag.String("AdminUsername", CONFIG.AdminUsername, "administrator username") - AdminEmailPtr := flag.String("AdminEmail", CONFIG.AdminEmail, "administrator email") - AdminPasswordPtr := flag.String("AdminPassword", CONFIG.AdminPassword, "administrator password") - - //flag.Parse()方法必须要在使用之前调用。 - flag.Parse() - - if *ServerPortPtr != CONFIG.ServerPort { - CONFIG.ServerPort = *ServerPortPtr - } - - if *MatterPathPtr != CONFIG.MatterPath { - CONFIG.MatterPath = *MatterPathPtr - } - - if *MysqlPortPtr != CONFIG.MysqlPort { - CONFIG.MysqlPort = *MysqlPortPtr - } - - if *MysqlHostPtr != CONFIG.MysqlHost { - CONFIG.MysqlHost = *MysqlHostPtr - } - - if *MysqlSchemaPtr != CONFIG.MysqlSchema { - CONFIG.MysqlSchema = *MysqlSchemaPtr - } - - if *MysqlUsernamePtr != CONFIG.MysqlUsername { - CONFIG.MysqlUsername = *MysqlUsernamePtr - } - - if *MysqlPasswordPtr != CONFIG.MysqlPassword { - CONFIG.MysqlPassword = *MysqlPasswordPtr - } - - if *AdminUsernamePtr != CONFIG.AdminUsername { - CONFIG.AdminUsername = *AdminUsernamePtr - } - - if *AdminEmailPtr != CONFIG.AdminEmail { - CONFIG.AdminEmail = *AdminEmailPtr - } - - if *AdminPasswordPtr != CONFIG.AdminPassword { - CONFIG.AdminPassword = *AdminPasswordPtr - } - -} - -//三种方式指定配置项,后面的策略会覆盖前面的策略。 -func PrepareConfigs() { - - //第一级. 从配置文件conf/tank.json中读取配置项 - LoadConfigFromFile() - - //第二级. 从环境变量中读取配置项 - LoadConfigFromEnvironment() - - //第三级. 从程序参数中读取配置项 - LoadConfigFromArguments() - - if CONFIG.MatterPath == "" { - CONFIG.MatterPath = GetHomePath() + "/matter" - } - MakeDirAll(CONFIG.MatterPath) - - //验证配置项的正确性 - CONFIG.validate() - - //TODO:安装程序开始导入初始表和初始数据。 做成可视化安装。 - //InstallDatabase() -} diff --git a/rest/context.go b/rest/context.go index 6fde9d2..1eb850d 100644 --- a/rest/context.go +++ b/rest/context.go @@ -26,9 +26,6 @@ type Context struct { //初始化上下文 func (this *Context) Init() { - //处理数据库连接的开关。 - this.OpenDb() - //创建一个用于存储session的缓存。 this.SessionCache = NewCacheTable() @@ -44,6 +41,13 @@ func (this *Context) Init() { //初始化Router. 这个方法要在Bean注册好了之后才能。 this.Router = NewRouter() + + //如果数据库信息配置好了,就直接打开数据库连接 同时执行Bean的ConfigPost方法 + if CONFIG.DBConfigured { + this.OpenDb() + this.configPostBeans() + } + } func (this *Context) OpenDb() { @@ -116,6 +120,9 @@ func (this *Context) registerBeans() { this.registerBean(new(ImageCacheDao)) this.registerBean(new(ImageCacheService)) + //install + this.registerBean(new(InstallController)) + //matter this.registerBean(new(MatterController)) this.registerBean(new(MatterDao)) @@ -164,7 +171,14 @@ func (this *Context) initBeans() { for _, bean := range this.BeanMap { bean.Init() } +} +//所有配置项完备后执行的方法 +func (this *Context) configPostBeans() { + + for _, bean := range this.BeanMap { + bean.ConfigPost() + } } //销毁的方法 diff --git a/rest/dashboard_service.go b/rest/dashboard_service.go index 7f61fb2..07ff30b 100644 --- a/rest/dashboard_service.go +++ b/rest/dashboard_service.go @@ -46,9 +46,13 @@ func (this *DashboardService) Init() { this.userDao = b } +} + +//系统启动,数据库配置完毕后会调用该方法 +func (this *DashboardService) ConfigPost() { + //立即执行数据清洗任务 go SafeMethod(this.maintain) - } //每日清洗离线数据表。 diff --git a/rest/footprint_service.go b/rest/footprint_service.go index f406dd8..779bda0 100644 --- a/rest/footprint_service.go +++ b/rest/footprint_service.go @@ -2,6 +2,7 @@ package rest import ( "encoding/json" + "github.com/json-iterator/go" "net/http" "time" ) @@ -61,23 +62,30 @@ func (this *FootprintService) Trace(writer http.ResponseWriter, request *http.Re paramsString = string(paramsData) } - user := this.findUser(writer, request) - userUuid := "" - if user != nil { - userUuid = user.Uuid - } - //将文件信息存入数据库中。 footprint := &Footprint{ - UserUuid: userUuid, - Ip: GetIpAddress(request), - Host: request.Host, - Uri: request.URL.Path, - Params: paramsString, - Cost: int64(duration / time.Millisecond), - Success: success, + Ip: GetIpAddress(request), + Host: request.Host, + Uri: request.URL.Path, + Params: paramsString, + Cost: int64(duration / time.Millisecond), + Success: success, } - footprint = this.footprintDao.Create(footprint) + //有可能DB尚且没有配置 直接打印出内容,并且退出 + if CONFIG.DBConfigured { + user := this.findUser(writer, request) + userUuid := "" + if user != nil { + userUuid = user.Uuid + } + footprint.UserUuid = userUuid + footprint = this.footprintDao.Create(footprint) + } else { + //用json的方式输出返回值。 + b, _ := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(footprint) + + this.logger.Info("%s", string(b)) + } } diff --git a/rest/install.go b/rest/install.go index ce85427..01322b1 100644 --- a/rest/install.go +++ b/rest/install.go @@ -3,9 +3,6 @@ package rest import ( "fmt" "github.com/jinzhu/gorm" - "github.com/nu7hatch/gouuid" - "regexp" - "time" ) //首次运行的时候,将自动安装数据库等内容。 @@ -85,44 +82,6 @@ func InstallDatabase() { hasTable = db.HasTable(user) if !hasTable { - //验证超级管理员的信息 - if m, _ := regexp.MatchString(`^[0-9a-zA-Z_]+$`, CONFIG.AdminUsername); !m { - LOGGER.Panic(`超级管理员用户名必填,且只能包含字母,数字和'_''`) - } - - if len(CONFIG.AdminPassword) < 6 { - LOGGER.Panic(`超级管理员密码长度至少为6位`) - } - - if CONFIG.AdminEmail == "" { - LOGGER.Panic("超级管理员邮箱必填!") - } - - createUser := "CREATE TABLE `tank20_user` (`uuid` char(36) NOT NULL,`role` varchar(45) DEFAULT 'USER',`username` varchar(255) DEFAULT NULL COMMENT '昵称',`password` varchar(255) DEFAULT NULL COMMENT '密码',`email` varchar(45) DEFAULT NULL COMMENT '邮箱',`phone` varchar(45) DEFAULT NULL COMMENT '电话',`gender` varchar(45) DEFAULT 'UNKNOWN' COMMENT '性别,默认未知',`city` varchar(45) DEFAULT NULL COMMENT '城市',`avatar_url` varchar(255) DEFAULT NULL COMMENT '头像链接',`last_time` datetime DEFAULT NULL COMMENT '上次登录使劲按',`last_ip` varchar(45) DEFAULT NULL,`size_limit` int(11) DEFAULT '-1' COMMENT '该账号上传文件的大小限制,单位byte。<0 表示不设限制',`status` varchar(45) DEFAULT 'OK',`sort` bigint(20) DEFAULT NULL,`modify_time` timestamp NULL DEFAULT NULL,`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',PRIMARY KEY (`uuid`),UNIQUE KEY `id_UNIQUE` (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表描述';" - db = db.Exec(createUser) - if db.Error != nil { - LOGGER.Panic(db.Error.Error()) - } - LOGGER.Info("创建User表") - - user := &User{} - timeUUID, _ := uuid.NewV4() - user.Uuid = string(timeUUID.String()) - user.CreateTime = time.Now() - user.UpdateTime = time.Now() - user.LastTime = time.Now() - user.Sort = time.Now().UnixNano() / 1e6 - user.Role = USER_ROLE_ADMINISTRATOR - user.Username = CONFIG.AdminUsername - user.Password = GetBcrypt(CONFIG.AdminPassword) - user.Email = CONFIG.AdminEmail - user.Phone = "" - user.Gender = USER_GENDER_UNKNOWN - user.SizeLimit = -1 - user.Status = USER_STATUS_OK - - db.Create(user) - } } diff --git a/rest/install_controller.go b/rest/install_controller.go new file mode 100644 index 0000000..31ec57a --- /dev/null +++ b/rest/install_controller.go @@ -0,0 +1,104 @@ +package rest + +import ( + "github.com/jinzhu/gorm" + "net/http" + "strconv" +) + +type InstallController struct { + BaseController + uploadTokenDao *UploadTokenDao + downloadTokenDao *DownloadTokenDao + matterDao *MatterDao + matterService *MatterService + imageCacheDao *ImageCacheDao + imageCacheService *ImageCacheService +} + +//初始化方法 +func (this *InstallController) Init() { + this.BaseController.Init() + + //手动装填本实例的Bean. + b := CONTEXT.GetBean(this.uploadTokenDao) + if c, ok := b.(*UploadTokenDao); ok { + this.uploadTokenDao = c + } + + b = CONTEXT.GetBean(this.downloadTokenDao) + if c, ok := b.(*DownloadTokenDao); ok { + this.downloadTokenDao = c + } + + b = CONTEXT.GetBean(this.matterDao) + if c, ok := b.(*MatterDao); ok { + this.matterDao = c + } + + b = CONTEXT.GetBean(this.matterService) + if c, ok := b.(*MatterService); ok { + this.matterService = c + } + + b = CONTEXT.GetBean(this.imageCacheDao) + if c, ok := b.(*ImageCacheDao); ok { + this.imageCacheDao = c + } + + b = CONTEXT.GetBean(this.imageCacheService) + if c, ok := b.(*ImageCacheService); ok { + this.imageCacheService = c + } + +} + +//注册自己的路由。 +func (this *InstallController) RegisterRoutes() map[string]func(writer http.ResponseWriter, request *http.Request) { + + routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request)) + + //每个Controller需要主动注册自己的路由。 + routeMap["/api/install/verify"] = this.Wrap(this.Verify, USER_ROLE_GUEST) + routeMap["/api/install/table/dashboard"] = this.Wrap(this.InstallTableDashboard, USER_ROLE_GUEST) + + return routeMap +} + +//验证数据库连接 +func (this *InstallController) Verify(writer http.ResponseWriter, request *http.Request) *WebResult { + + mysqlPortStr := request.FormValue("mysqlPort") + mysqlHost := request.FormValue("mysqlHost") + mysqlSchema := request.FormValue("mysqlSchema") + mysqlUsername := request.FormValue("mysqlUsername") + mysqlPassword := request.FormValue("mysqlPassword") + + var mysqlPort int + if mysqlPortStr != "" { + tmp, err := strconv.Atoi(mysqlPortStr) + this.PanicError(err) + mysqlPort = tmp + } + + mysqlUrl := GetMysqlUrl(mysqlPort, mysqlHost, mysqlSchema, mysqlUsername, mysqlPassword) + this.logger.Info("验证MySQL连接性 %s", mysqlUrl) + + var err error = nil + db, err := gorm.Open("mysql", mysqlUrl) + this.PanicError(err) + + this.logger.Info("Ping一下数据库") + err = db.DB().Ping() + this.PanicError(err) + + return this.Success("OK") + +} + +//安装dashboard表 +func (this *InstallController) InstallTableDashboard(writer http.ResponseWriter, request *http.Request) *WebResult { + + return this.Success("") + +} diff --git a/rest/logger.go b/rest/logger.go index 70f52b9..97bfbe6 100644 --- a/rest/logger.go +++ b/rest/logger.go @@ -104,7 +104,7 @@ func (this *Logger) maintain() { now := time.Now() nextTime := FirstSecondOfDay(Tomorrow()) duration := nextTime.Sub(now) - this.Info("%vs 后将进行下一次日志维护 下次时间维护时间:%v ", int64(duration/time.Second), nextTime) + this.Info("下次维护时间:%v ", int64(duration/time.Second), nextTime) this.maintainTimer = time.AfterFunc(duration, func() { go SafeMethod(this.maintain) }) diff --git a/rest/router.go b/rest/router.go index 900fa1e..e5681b2 100644 --- a/rest/router.go +++ b/rest/router.go @@ -12,19 +12,28 @@ import ( //用于处理所有前来的请求 type Router struct { - footprintService *FootprintService - userService *UserService - routeMap map[string]func(writer http.ResponseWriter, request *http.Request) + installController *InstallController + footprintService *FootprintService + userService *UserService + routeMap map[string]func(writer http.ResponseWriter, request *http.Request) + installRouteMap map[string]func(writer http.ResponseWriter, request *http.Request) } //构造方法 func NewRouter() *Router { router := &Router{ - routeMap: make(map[string]func(writer http.ResponseWriter, request *http.Request)), + routeMap: make(map[string]func(writer http.ResponseWriter, request *http.Request)), + installRouteMap: make(map[string]func(writer http.ResponseWriter, request *http.Request)), + } + + //installController. + b := CONTEXT.GetBean(router.installController) + if b, ok := b.(*InstallController); ok { + router.installController = b } //装载userService. - b := CONTEXT.GetBean(router.userService) + b = CONTEXT.GetBean(router.userService) if b, ok := b.(*UserService); ok { router.userService = b } @@ -35,12 +44,21 @@ func NewRouter() *Router { router.footprintService = b } - //将Controller中的路由规则装载机进来 + //将Controller中的路由规则装载进来,InstallController中的除外 for _, controller := range CONTEXT.ControllerMap { - routes := controller.RegisterRoutes() - for k, v := range routes { - router.routeMap[k] = v + + if controller == router.installController { + routes := controller.RegisterRoutes() + for k, v := range routes { + router.installRouteMap[k] = v + } + } else { + routes := controller.RegisterRoutes() + for k, v := range routes { + router.routeMap[k] = v + } } + } return router @@ -77,8 +95,7 @@ func (this *Router) GlobalPanicHandler(writer http.ResponseWriter, request *http writer.Header().Set("Content-Type", "application/json;charset=UTF-8") //用json的方式输出返回值。 - var json = jsoniter.ConfigCompatibleWithStandardLibrary - b, _ := json.Marshal(webResult) + b, _ := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(webResult) //写到输出流中 _, err := fmt.Fprintf(writer, string(b)) @@ -105,35 +122,44 @@ func (this *Router) ServeHTTP(writer http.ResponseWriter, request *http.Request) path := request.URL.Path if strings.HasPrefix(path, "/api") { - //统一处理用户的身份信息。 - this.userService.bootstrap(writer, request) + if CONFIG.DBConfigured { + //已安装的模式 - if handler, ok := this.routeMap[path]; ok { + //统一处理用户的身份信息。 + this.userService.bootstrap(writer, request) - handler(writer, request) + if handler, ok := this.routeMap[path]; ok { + handler(writer, request) + } else { + //直接将请求扔给每个controller,看看他们能不能处理,如果都不能处理,那就抛出找不到的错误 + canHandle := false + for _, controller := range CONTEXT.ControllerMap { + if handler, exist := controller.HandleRoutes(writer, request); exist { + canHandle = true + handler(writer, request) + break + } + } - } else { - //直接将请求扔给每个controller,看看他们能不能处理,如果都不能处理,那就抛出找不到的错误 - canHandle := false - for _, controller := range CONTEXT.ControllerMap { - if handler, exist := controller.HandleRoutes(writer, request); exist { - canHandle = true - - handler(writer, request) - break + if !canHandle { + panic(CustomWebResult(CODE_WRAPPER_NOT_FOUND, fmt.Sprintf("没有找到能够处理%s的方法", path))) } } - if !canHandle { - panic(CustomWebResult(CODE_WRAPPER_NOT_FOUND, fmt.Sprintf("没有找到能够处理%s的方法", path))) - } + //正常的访问记录会落到这里。 + go SafeMethod(func() { + this.footprintService.Trace(writer, request, time.Now().Sub(startTime), true) + }) + } else { + //未安装模式 + if handler, ok := this.installRouteMap[path]; ok { + handler(writer, request) + } else { + panic(ConstWebResult(CODE_WRAPPER_NOT_INSTALLED)) + } } - //正常的访问记录会落到这里。 - go SafeMethod(func() { - this.footprintService.Trace(writer, request, time.Now().Sub(startTime), true) - }) } else { //当作静态资源处理。默认从当前文件下面的static文件夹中取东西。 dir := GetHtmlPath() diff --git a/rest/util_string.go b/rest/util_string.go index ac49eed..3353a5a 100644 --- a/rest/util_string.go +++ b/rest/util_string.go @@ -30,3 +30,13 @@ func HumanFileSize(bytes int64) string { return fmt.Sprintf("%s%s", numStr, units[u]) } + +//获取MySQL的URL +func GetMysqlUrl( + mysqlPort int, + mysqlHost string, + mysqlSchema string, + mysqlUsername string, + mysqlPassword string) string { + return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", mysqlUsername, mysqlPassword, mysqlHost, mysqlPort, mysqlSchema) +} diff --git a/rest/web_result.go b/rest/web_result.go index de8f7bd..33e916a 100644 --- a/rest/web_result.go +++ b/rest/web_result.go @@ -31,6 +31,7 @@ var ( CODE_WRAPPER_UNAUTHORIZED = &CodeWrapper{Code: "UNAUTHORIZED", HttpStatus: http.StatusUnauthorized, Description: "没有权限,禁止访问"} CODE_WRAPPER_NOT_FOUND = &CodeWrapper{Code: "NOT_FOUND", HttpStatus: http.StatusNotFound, Description: "内容不存在"} CODE_WRAPPER_RANGE_NOT_SATISFIABLE = &CodeWrapper{Code: "RANGE_NOT_SATISFIABLE", HttpStatus: http.StatusRequestedRangeNotSatisfiable, Description: "文件范围读取错误"} + CODE_WRAPPER_NOT_INSTALLED = &CodeWrapper{Code: "NOT_INSTALLED", HttpStatus: http.StatusInternalServerError, Description: "系统尚未安装"} CODE_WRAPPER_UNKNOWN = &CodeWrapper{Code: "UNKNOWN", HttpStatus: http.StatusInternalServerError, Description: "服务器未知错误"} )