From 881d73263a75cf245bda1aa8e858fc0d365917dd Mon Sep 17 00:00:00 2001 From: printempw Date: Thu, 28 Jul 2016 15:10:08 +0800 Subject: [PATCH] add installation pages --- README.md | 6 +- app/Services/Boot.php | 10 +- app/Services/Config.php | 13 +- app/Services/Migration.php | 57 ++++++ assets/src/sass/install.scss | 319 ++++++++++++++++++++++++++++++ config/services.php | 3 +- db.sql | 120 ----------- index.php | 7 +- resources/views/setup/locked.tpl | 10 + resources/views/setup/master.tpl | 19 ++ resources/views/setup/steps/1.tpl | 12 ++ resources/views/setup/steps/2.tpl | 55 ++++++ resources/views/setup/steps/3.tpl | 21 ++ setup/index.php | 117 +++++++++++ 14 files changed, 638 insertions(+), 131 deletions(-) create mode 100644 app/Services/Migration.php create mode 100644 assets/src/sass/install.scss delete mode 100644 db.sql create mode 100644 resources/views/setup/locked.tpl create mode 100644 resources/views/setup/master.tpl create mode 100644 resources/views/setup/steps/1.tpl create mode 100644 resources/views/setup/steps/2.tpl create mode 100644 resources/views/setup/steps/3.tpl create mode 100644 setup/index.php diff --git a/README.md b/README.md index 5c6c69c1..bb6e0316 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ 快速使用: ----------- 1. 下载发布的打包版源码,重命名 `.env.example` 为 `.env` 并配置你的数据库连接信息(如果是 windows 就重命名为 `.env.`,后面那个点会自动去掉的) -2. 导入根目录下的 `db.sql` 到你的数据库 +2. 访问 `/setup/index.php` 进行安装 3. 如果你是用的是 Nginx,请配置你的 `nginx.conf` 并加入重写规则 -4. 访问你的站点,注册一个新账户 -5. (在数据库的 `users` 表中将你的用户 permission 字段设置为 `1` 即可获取管理员权限) +4. 访问你的站点,注册一个新账户或者使用 `安装时所配置的账户` 登录 +5. (在数据库的 `users` 表中将你的用户 permission 字段设置为 `1` 即可获取管理员权限, 设置为 `2` 即为超级管理员) 6. 在角色管理面板使用你的 Minecraft 角色名添加一个新角色 7. 在皮肤库上传你的皮肤 & 披风(可设为私有)并添加至衣柜 8. 应用皮肤 & 披风到你的角色 diff --git a/app/Services/Boot.php b/app/Services/Boot.php index fe2fdfb4..296c567a 100644 --- a/app/Services/Boot.php +++ b/app/Services/Boot.php @@ -7,14 +7,20 @@ use \Pecee\SimpleRouter\SimpleRouter as Router; class Boot { - public static function loadDotEnv() + public static function loadDotEnv($dir) { if (Config::checkDotEnvExist()) { - $dotenv = new \Dotenv\Dotenv(BASE_DIR); + $dotenv = new \Dotenv\Dotenv($dir); $dotenv->load(); } } + public static function checkRuntimeEnv() + { + Config::checkPHPVersion(); + Config::checkFolderExist(); + } + public static function loadServices() { // Set Aliases for App\Services diff --git a/app/Services/Config.php b/app/Services/Config.php index 57c063a4..f1c02af0 100644 --- a/app/Services/Config.php +++ b/app/Services/Config.php @@ -18,6 +18,12 @@ class Config return require BASE_DIR."/config/view.php"; } + public static function checkPHPVersion() + { + if (strnatcasecmp(phpversion(), '5.5.9') < 0) + throw new E('Blessing Skin Server v3 要求 PHP 版本不低于 5.5.9,当前版本为 '.phpversion(), -1, true); + } + /** * Check database config * @@ -46,6 +52,7 @@ class Config return false; } } + return true; } @@ -56,8 +63,10 @@ class Config $view_config = self::getViewConfig(); - if (!is_dir($view_config['cache_path'])) - mkdir($view_config['cache_path']); + if (!is_dir($view_config['cache_path'])) { + if (!mkdir($view_config['cache_path'])) + throw new E('缓存文件夹创建失败,请确认目录权限是否正确', -1); + } return true; } diff --git a/app/Services/Migration.php b/app/Services/Migration.php new file mode 100644 index 00000000..85e2662f --- /dev/null +++ b/app/Services/Migration.php @@ -0,0 +1,57 @@ +increments('uid'); + $table->string('email', 100); + $table->string('nickname', 50); + $table->integer('score'); + $table->integer('avatar'); + $table->string('password', 255); + $table->string('ip', 32); + $table->integer('permission')->default('0'); + $table->dateTime('last_sign_at'); + $table->dateTime('register_at'); + }); + + Schema::create($prefix.'closets', function($table) { + $table->increments('uid'); + $table->longText('textures'); + }); + + Schema::create($prefix.'players', function($table) { + $table->increments('pid'); + $table->integer('uid'); + $table->string('player_name', 50); + $table->string('preference', 10); + $table->integer('tid_steve'); + $table->integer('tid_alex'); + $table->integer('tid_cape'); + $table->dateTime('last_modified'); + }); + + Schema::create($prefix.'textures', function($table) { + $table->increments('tid'); + $table->string('name', 50); + $table->string('type', 10); + $table->integer('likes'); + $table->string('hash', 64); + $table->integer('size'); + $table->integer('uploader'); + $table->integer('public'); + $table->dateTime('last_modified'); + }); + + Schema::create($prefix.'options', function($table) { + $table->increments('id'); + $table->string('option_name', 50); + $table->longText('option_value'); + }); + + } +} diff --git a/assets/src/sass/install.scss b/assets/src/sass/install.scss new file mode 100644 index 00000000..c03fdf27 --- /dev/null +++ b/assets/src/sass/install.scss @@ -0,0 +1,319 @@ +/* +* @Author: printempw +* @Date: 2016-07-28 13:15:18 +* @Last Modified by: printempw +* @Last Modified time: 2016-07-28 14:09:59 +*/ + +@import "style.scss"; + +html { + background: #f1f1f1; + margin: 0 20px; + font-weight: 400; +} +body { + background: #FFF none repeat scroll 0% 0%; + color: #444; + font-family: Ubuntu, 'Microsoft Yahei', 'Microsoft Jhenghei', sans-serif; + margin: 140px auto 25px; + padding: 20px 20px 10px; + max-width: 700px; + box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.13); +} +h1, h2 { + border-bottom: 1px solid #DEDEDE; + clear: both; + color: #666; + font-size: 24px; +} +#logo a, p, h1, h2 { + font-weight: 400; +} +#logo, h1, h2 { + padding: 0px 0px 7px; +} +p { + padding-bottom: 2px; + font-size: 14px; + line-height: 1.5; +} +#logo a { + font-family: Minecraft, sans-serif; + transition: all .2s ease-in-out; + font-size: 50px; + color: #666; + height: 84px; + line-height: 1.3em; + margin: -130px auto 25px; + padding: 0; + outline: 0; + text-decoration: none; + overflow: hidden; + display: block; +} +#logo a:hover { + color: #42a5f5; +} +/* Mobile phone */ +@media (max-width: 48em) { + #logo a { + font-size: 40px; + } +} +@media (max-width: 35.5em) { + #logo a { + font-size: 30px; + } +} +#logo { + margin: 6px 0 14px; + border-bottom: none; + text-align: center; +} +.step { + margin: 20px 0 15px; + text-align: left; + padding: 0; +} +.step>input { + font-family: Ubuntu, 'Microsoft Yahei', 'Microsoft Jhenghei', sans-serif; +} +fieldset { + padding: 0; + margin: 0 +} + +label { + cursor: pointer +} + +.step { + margin: 20px 0 15px +} + +.step,th { + text-align: left; + padding: 0 +} + +.language-chooser.wp-core-ui .step .button.button-large { + height: 36px; + vertical-align: middle; + font-size: 14px +} + +.form-table td,.form-table th { + padding: 10px 20px 10px 0; + vertical-align: top; + font-size: 14px +} + +td > input { + font-family: Ubuntu, 'Microsoft Yahei', 'Microsoft Jhenghei', sans-serif; +} + +textarea { + border: 1px solid #dfdfdf; + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +.form-table { + border-collapse: collapse; + margin-top: 1em; + width: 100% +} + +.form-table td { + margin-bottom: 9px +} + +.form-table th { + text-align: left; + width: 140px +} + +.form-table code { + line-height: 18px; + font-size: 14px +} + +.form-table p { + margin: 4px 0 0; + font-size: 11px +} + +.form-table input { + line-height: 20px; + font-size: 15px; + padding: 3px 5px; + border: 1px solid #ddd; + -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.07); + box-shadow: inset 0 1px 2px rgba(0,0,0,.07) +} + +.form-table input[type=email],.form-table input[type=password],.form-table input[type=text],.form-table input[type=url] { + width: 206px +} + +.form-table.install-success td,.form-table.install-success th { + vertical-align: middle; + padding: 16px 20px 16px 0 +} + +.form-table.install-success td p { + margin: 0; + font-size: 14px +} + +.form-table.install-success td code { + margin: 0; + font-size: 18px +} +.container .button,.container .button-primary,.container .button-secondary { + display:inline-block; + text-decoration:none; + font-size:13px; + line-height:26px; + height:28px; + margin:0; + padding:0 10px 1px; + cursor:pointer; + border-width:1px; + border-style:solid; + -webkit-appearance:none; + -webkit-border-radius:3px; + border-radius:3px; + white-space:nowrap; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box +} +.container button::-moz-focus-inner,.container input[type=reset]::-moz-focus-inner,.container input[type=button]::-moz-focus-inner,.container input[type=submit]::-moz-focus-inner { + border-width:0; + border-style:none; + padding:0 +} +.container .button-group.button-large .button,.container .button.button-large { + height:30px; + line-height:28px; + padding:0 12px 2px +} +.container .button-group.button-small .button,.container .button.button-small { + height:24px; + line-height:22px; + padding:0 8px 1px; + font-size:11px +} +.container .button-group.button-hero .button,.container .button.button-hero { + font-size:14px; + height:46px; + line-height:44px; + padding:0 36px +} +.container .button:active,.container .button:focus { + outline:0 +} +.container .button.hidden { + display:none +} +.container input[type=reset],.container input[type=reset]:active,.container input[type=reset]:focus,.container input[type=reset]:hover { + background:0 0; + border:none; + -webkit-box-shadow:none; + box-shadow:none; + padding:0 2px 1px; + width:auto +} +.container .button,.container .button-secondary { + color:#555; + border-color:#ccc; + background:#f7f7f7; + -webkit-box-shadow:0 1px 0 #ccc; + box-shadow:0 1px 0 #ccc; + vertical-align:top +} +.container p .button { + vertical-align:baseline +} +.container .button-secondary:focus,.container .button-secondary:hover,.container .button.focus,.container .button.hover,.container .button:focus,.container .button:hover { + background:#fafafa; + border-color:#999; + color:#23282d +} +.container .button-link:focus,.container .button-secondary:focus,.container .button.focus,.container .button:focus { + border-color:#5b9dd9; + -webkit-box-shadow:0 0 3px rgba(0,115,170,.8); + box-shadow:0 0 3px rgba(0,115,170,.8) +} +.container .button-secondary:active,.container .button.active,.container .button.active:hover,.container .button:active { + background:#eee; + border-color:#999; + -webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5); + box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5); + -webkit-transform:translateY(1px); + -ms-transform:translateY(1px); + transform:translateY(1px) +} +.container .button.active:focus { + border-color:#5b9dd9; + -webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5),0 0 3px rgba(0,115,170,.8); + box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5),0 0 3px rgba(0,115,170,.8) +} +.container .button-disabled,.container .button-secondary.disabled,.container .button-secondary:disabled,.container .button-secondary[disabled],.container .button.disabled,.container .button:disabled,.container .button[disabled] { + color:#a0a5aa!important; + border-color:#ddd!important; + background:#f7f7f7!important; + -webkit-box-shadow:none!important; + box-shadow:none!important; + text-shadow:0 1px 0 #fff!important; + cursor:default; + -webkit-transform:none!important; + -ms-transform:none!important; + transform:none!important +} +.container .button-link { + margin:0; + padding:0; + -webkit-box-shadow:none; + box-shadow:none; + border:0; + -webkit-border-radius:0; + border-radius:0; + background:0 0; + outline:0; + cursor:pointer +} +.container .button-primary { + background:#0085ba; + border-color:#0073aa #006799 #006799; + -webkit-box-shadow:0 1px 0 #006799; + box-shadow:0 1px 0 #006799; + color:#fff; + text-decoration:none; + text-shadow:0 -1px 1px #006799,1px 0 1px #006799,0 1px 1px #006799,-1px 0 1px #006799 +} +.container .button-primary.focus,.container .button-primary.hover,.container .button-primary:focus,.container .button-primary:hover { + background:#008ec2; + border-color:#006799; + color:#fff +} +.container .button-primary.focus,.container .button-primary:focus { + -webkit-box-shadow:0 1px 0 #0073aa,0 0 2px 1px #33b3db; + box-shadow:0 1px 0 #0073aa,0 0 2px 1px #33b3db +} +.alert { + padding: 15px; + margin-top: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} diff --git a/config/services.php b/config/services.php index c0bfd0db..2db1ec1c 100644 --- a/config/services.php +++ b/config/services.php @@ -22,5 +22,6 @@ return [ 'Updater' => 'App\Services\Updater', 'Config' => 'App\Services\Config', 'Schema' => 'App\Services\Schema', - 'Boot' => 'App\Services\Boot' + 'Boot' => 'App\Services\Boot', + 'Migration' => 'App\Services\Migration' ]; diff --git a/db.sql b/db.sql deleted file mode 100644 index c2e9189e..00000000 --- a/db.sql +++ /dev/null @@ -1,120 +0,0 @@ -/* - * @Author: printempw - * @Date: 2016-07-24 13:37:40 - * @Last Modified by: printempw - * @Last Modified time: 2016-07-24 14:49:24 - */ - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -SET time_zone = "+00:00"; -SET NAMES utf8mb4; - --- --- Database: `skin-v3` --- - --- -------------------------------------------------------- - --- --- 表的结构 `users` --- - -CREATE TABLE IF NOT EXISTS `users` ( - `uid` int(11) NOT NULL AUTO_INCREMENT, - `email` varchar(100) NOT NULL, - `nickname` varchar(50) NOT NULL DEFAULT '', - `score` int(11) NOT NULL, - `avatar` int(11) NOT NULL, - `password` varchar(255) NOT NULL, - `ip` varchar(32) NOT NULL, - `permission` int(11) NOT NULL DEFAULT '0', - `last_sign_at` datetime NOT NULL, - `register_at` datetime NOT NULL, - PRIMARY KEY (`uid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- 表的结构 `closets` --- - -CREATE TABLE IF NOT EXISTS `closets` ( - `uid` int(11) NOT NULL AUTO_INCREMENT, - `textures` longtext NOT NULL, - PRIMARY KEY (`uid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- 表的结构 `players` --- - -CREATE TABLE IF NOT EXISTS `players` ( - `pid` int(11) NOT NULL AUTO_INCREMENT, - `uid` int(11) NOT NULL, - `player_name` varchar(50) NOT NULL, - `preference` varchar(10) NOT NULL, - `tid_steve` int(11) NOT NULL, - `tid_alex` int(11) NOT NULL, - `tid_cape` int(11) NOT NULL, - `last_modified` datetime NOT NULL, - PRIMARY KEY (`pid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- 表的结构 `textures` --- - -CREATE TABLE IF NOT EXISTS `textures` ( - `tid` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(50) NOT NULL, - `type` varchar(10) NOT NULL, - `likes` int(11) NOT NULL, - `hash` varchar(64) NOT NULL, - `size` int(11) NOT NULL, - `uploader` int(11) NOT NULL, - `public` int(11) NOT NULL, - `upload_at` datetime NOT NULL, - PRIMARY KEY (`tid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- 表的结构 `options` --- - -CREATE TABLE IF NOT EXISTS `options` ( - `id` int(20) unsigned NOT NULL AUTO_INCREMENT, - `option_name` varchar(50) NOT NULL, - `option_value` longtext NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- --- 转存表中的数据 `options` --- - -INSERT INTO `options` (`id`, `option_name`, `option_value`) VALUES -(1, 'site_url', ''), -(2, 'site_name', 'Blessing Skin'), -(3, 'site_description', '开源的 PHP Minecraft 皮肤站'), -(4, 'user_can_register', '1'), -(5, 'regs_per_ip', '3'), -(6, 'api_type', '0'), -(7, 'announcement', '欢迎使用 Blessing Skin Server 3.0!'), -(8, 'color_scheme', 'skin-blue'), -(9, 'home_pic_url', './assets/images/bg.jpg'), -(10, 'current_version', '3.0-beta'), -(11, 'custom_css', ''), -(12, 'custom_js', ''), -(13, 'update_url', 'https://work.prinzeugen.net/update.json'), -(14, 'allow_chinese_playername', '1'), -(15, 'show_footer_copyright', '1'), -(16, 'comment_script', ''), -(17, 'user_initial_score', '1000'), -(18, 'sign_gap_time', '24'); diff --git a/index.php b/index.php index 392f355d..ddca28a1 100755 --- a/index.php +++ b/index.php @@ -12,8 +12,11 @@ require BASE_DIR.'/vendor/autoload.php'; // Load Aliases App\Services\Boot::loadServices(); +// Check Runtime Environment +Boot::checkRuntimeEnv(); + // Load dotenv Configuration -Boot::loadDotEnv(); +Boot::loadDotEnv(BASE_DIR); // Register Error Handler Boot::registerErrorHandler(); @@ -30,8 +33,6 @@ if (!Config::checkTableExist($db_config)) { Http::redirect('../setup/index.php'); } -Config::checkFolderExist(); - // Start Session Boot::startSession(); diff --git a/resources/views/setup/locked.tpl b/resources/views/setup/locked.tpl new file mode 100644 index 00000000..796d8895 --- /dev/null +++ b/resources/views/setup/locked.tpl @@ -0,0 +1,10 @@ +@extends('setup.master') + +@section('content') +

已安装过

+ +

Blessing Skin Server 看起来已经安装妥当。如果想重新安装,请删除数据库中的旧数据表,或者换一个数据表前缀。

+

+ 返回首页 +

+@endsection diff --git a/resources/views/setup/master.tpl b/resources/views/setup/master.tpl new file mode 100644 index 00000000..3879e6d7 --- /dev/null +++ b/resources/views/setup/master.tpl @@ -0,0 +1,19 @@ + + + + + + + Blessing Skin Server 安装程序 + + + + + + + +@yield('content') + + + + diff --git a/resources/views/setup/steps/1.tpl b/resources/views/setup/steps/1.tpl new file mode 100644 index 00000000..abee0e02 --- /dev/null +++ b/resources/views/setup/steps/1.tpl @@ -0,0 +1,12 @@ +@extends('setup.master') + +@section('content') +

欢迎

+ +

欢迎使用 Blessing Skin Server V3!

+

成功连接至 MySQL 服务器 {{ $server }},点击下一步以开始安装。

+ +

+ 下一步 +

+@endsection diff --git a/resources/views/setup/steps/2.tpl b/resources/views/setup/steps/2.tpl new file mode 100644 index 00000000..5983125f --- /dev/null +++ b/resources/views/setup/steps/2.tpl @@ -0,0 +1,55 @@ +@extends('setup.master') + +@section('content') +

填写信息

+

您需要填写一些基本信息。无需担心填错,这些信息以后可以再次修改。

+ +
+ + + + + + + + + + + + + + + + + +
+ +

这是唯一的超级管理员账号,可 添加/取消 其他管理员。

+
+ +

+ + 重要:您将需要此密码来登录管理皮肤站,请将其保存在安全的位置。 + +

+
+ +
+ +

+ + 将会显示在首页以及标题栏,最好用纯英文(字体原因) + +

+
+ +@if (isset($_SESSION['msg'])) + + +@endif + +

+ +

+
+@endsection diff --git a/resources/views/setup/steps/3.tpl b/resources/views/setup/steps/3.tpl new file mode 100644 index 00000000..e019325d --- /dev/null +++ b/resources/views/setup/steps/3.tpl @@ -0,0 +1,21 @@ +@extends('setup.master') + +@section('content') +

成功!

+ +

Blessing Skin Server 安装完成。您是否还沉浸在愉悦的安装过程中?很遗憾,一切皆已完成! :)

+ + + + + + + + + +
邮箱{{ $email }}
密码

{{ $password }}

+ +

+ 首页 +

+@endsection diff --git a/setup/index.php b/setup/index.php new file mode 100644 index 00000000..16f96f20 --- /dev/null +++ b/setup/index.php @@ -0,0 +1,117 @@ +with('server', $server); + break; + + case 2: + echo View::make('setup.steps.2'); + break; + + case 3: + // check post + if (isset($_POST['email']) && isset($_POST['password']) && isset($_POST['confirm-pwd'])) + { + if ($_POST['password'] != $_POST['confirm-pwd']) + Http::redirect('index.php?step=2', '确认密码不一致'); + + $email = $_POST['email']; + $password = $_POST['password']; + $sitename = isset($_POST['sitename']) ? $_POST['sitename'] : "Blessing Skin Server"; + + if (Validate::checkValidEmail($email)) { + if (strlen($password) > 16 || strlen($password) < 8) { + Http::redirect('index.php?step=2', '无效的密码。密码长度应该大于 8 并小于 16。'); + + } else if (Utils::convertString($password) != $password) { + Http::redirect('index.php?step=2', '无效的密码。密码中包含了奇怪的字符。'); + } + } else { + Http::redirect('index.php?step=2', '邮箱格式不正确。'); + } + } else { + Http::redirect('index.php?step=2', '表单信息不完整。'); + } + + Migration::creatTables($db_config['prefix']); + + $options = [ + 'site_url' => Http::getBaseUrl(), + 'site_name' => $_POST['sitename'], + 'site_description' => '开源的 PHP Minecraft 皮肤站', + 'user_can_register' => '1', + 'regs_per_ip' => '3', + 'api_type' => '0', + 'announcement' => '欢迎使用 Blessing Skin Server 3.0!', + 'color_scheme' => 'skin-blue', + 'home_pic_url' => './assets/images/bg.jpg', + 'current_version' => '3.0-beta', + 'custom_css' => '', + 'custom_js' => '', + 'update_url' => 'https://work.prinzeugen.net/update.json', + 'allow_chinese_playername' => '1', + 'show_footer_copyright' => '1', + 'comment_script' => '', + 'user_initial_score' => '1000', + 'sign_gap_time' => '24' + ]; + + foreach ($options as $key => $value) { + Option::add($key, $value); + } + + $user = new App\Models\User($_POST['email']); + $user->register($_POST['password'], Http::getRealIP()); + + if (!is_dir(BASE_DIR.'/textures/')) { + if (!mkdir(BASE_DIR.'/textures/')) + throw new E('textures 文件夹创建失败,请确认目录权限是否正确,或者手动放置一个。', -1); + } + + echo View::make('setup.steps.3')->with('email', $_POST['email'])->with('password', $_POST['password']); + + break; +}