作者 Karson

新增会员注册短信验证码

新增后台菜单栏hook
优化后台修改管理员密码脚本
优化安装脚本,默认禁用admin模块
优化插件列表参数和分页显示
@@ -74,6 +74,9 @@ class Install extends Command @@ -74,6 +74,9 @@ class Install extends Command
74 74
75 file_put_contents($installLockFile, 1); 75 file_put_contents($installLockFile, 1);
76 76
  77 + //后台入口文件
  78 + $adminFile = ROOT_PATH . 'public' . DS . 'admin.php';
  79 +
77 $dbConfigFile = APP_PATH . 'database.php'; 80 $dbConfigFile = APP_PATH . 'database.php';
78 $config = @file_get_contents($dbConfigFile); 81 $config = @file_get_contents($dbConfigFile);
79 $callback = function ($matches) use ($hostname, $hostport, $username, $password, $database, $prefix) { 82 $callback = function ($matches) use ($hostname, $hostport, $username, $password, $database, $prefix) {
@@ -88,6 +91,16 @@ class Install extends Command @@ -88,6 +91,16 @@ class Install extends Command
88 // 写入数据库配置 91 // 写入数据库配置
89 file_put_contents($dbConfigFile, $config); 92 file_put_contents($dbConfigFile, $config);
90 93
  94 + // 修改后台入口
  95 + if (is_file($adminFile)) {
  96 + $x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  97 + $adminName = substr(str_shuffle(str_repeat($x, ceil(10 / strlen($x)))), 1, 10) . '.php';
  98 + rename($adminFile, ROOT_PATH . 'public' . DS . $adminName);
  99 + $output->highlight("Admin url:http://www.yoursite.com/{$adminName}");
  100 + }
  101 + $output->highlight("Admin username:admin");
  102 + $output->highlight("Admin password:123456");
  103 +
91 \think\Cache::rm('__menu__'); 104 \think\Cache::rm('__menu__');
92 105
93 $output->info("Install Successed!"); 106 $output->info("Install Successed!");
@@ -6,6 +6,7 @@ use app\admin\model\Admin; @@ -6,6 +6,7 @@ use app\admin\model\Admin;
6 use app\common\controller\Backend; 6 use app\common\controller\Backend;
7 use fast\Random; 7 use fast\Random;
8 use think\Session; 8 use think\Session;
  9 +use think\Validate;
9 10
10 /** 11 /**
11 * 个人配置 12 * 个人配置
@@ -59,10 +60,20 @@ class Profile extends Backend @@ -59,10 +60,20 @@ class Profile extends Backend
59 array_flip(array('email', 'nickname', 'password', 'avatar')) 60 array_flip(array('email', 'nickname', 'password', 'avatar'))
60 )); 61 ));
61 unset($v); 62 unset($v);
  63 + if (!Validate::is($params['email'], "email")) {
  64 + $this->error(__("Please input correct email"));
  65 + }
62 if (isset($params['password'])) { 66 if (isset($params['password'])) {
  67 + if (!Validate::is($params['password'], "/^[\S]{6,16}$/")) {
  68 + $this->error(__("Please input correct password"));
  69 + }
63 $params['salt'] = Random::alnum(); 70 $params['salt'] = Random::alnum();
64 $params['password'] = md5(md5($params['password']) . $params['salt']); 71 $params['password'] = md5(md5($params['password']) . $params['salt']);
65 } 72 }
  73 + $exist = Admin::where('email', $params['email'])->where('id', '<>', $this->auth->id)->find();
  74 + if ($exist) {
  75 + $this->error(__("Email already exists"));
  76 + }
66 if ($params) { 77 if ($params) {
67 $admin = Admin::get($this->auth->id); 78 $admin = Admin::get($this->auth->id);
68 $admin->save($params); 79 $admin->save($params);
@@ -53,6 +53,7 @@ return [ @@ -53,6 +53,7 @@ return [
53 'Mail vertify type' => 'SMTP验证方式', 53 'Mail vertify type' => 'SMTP验证方式',
54 'Mail from' => '发件人邮箱', 54 'Mail from' => '发件人邮箱',
55 'Name already exist' => '变量名称已经存在', 55 'Name already exist' => '变量名称已经存在',
  56 + 'Add new config' => '点击添加新的配置',
56 'Send a test message' => '发送测试邮件', 57 'Send a test message' => '发送测试邮件',
57 'This is a test mail content' => '这是一封来自FastAdmin校验邮件,用于校验邮件配置是否正常!', 58 'This is a test mail content' => '这是一封来自FastAdmin校验邮件,用于校验邮件配置是否正常!',
58 'This is a test mail' => '这是一封来自FastAdmin的邮件', 59 'This is a test mail' => '这是一封来自FastAdmin的邮件',
@@ -7,4 +7,7 @@ return [ @@ -7,4 +7,7 @@ return [
7 'Click to edit' => '点击编辑', 7 'Click to edit' => '点击编辑',
8 'Admin log' => '操作日志', 8 'Admin log' => '操作日志',
9 'Leave password blank if dont want to change' => '不修改密码请留空', 9 'Leave password blank if dont want to change' => '不修改密码请留空',
  10 + 'Please input correct email' => '请输入正确的Email地址',
  11 + 'Please input correct password' => '密码长度不正确',
  12 + 'Email already exists' => '邮箱已经存在',
10 ]; 13 ];
@@ -7,6 +7,7 @@ use fast\Random; @@ -7,6 +7,7 @@ use fast\Random;
7 use fast\Tree; 7 use fast\Tree;
8 use think\Config; 8 use think\Config;
9 use think\Cookie; 9 use think\Cookie;
  10 +use think\Hook;
10 use think\Request; 11 use think\Request;
11 use think\Session; 12 use think\Session;
12 13
@@ -361,6 +362,8 @@ class Auth extends \fast\Auth @@ -361,6 +362,8 @@ class Auth extends \fast\Auth
361 */ 362 */
362 public function getSidebar($params = [], $fixedPage = 'dashboard') 363 public function getSidebar($params = [], $fixedPage = 'dashboard')
363 { 364 {
  365 + // 边栏开始
  366 + Hook::listen("admin_sidebar_begin", $params);
364 $colorArr = ['red', 'green', 'yellow', 'blue', 'teal', 'orange', 'purple']; 367 $colorArr = ['red', 'green', 'yellow', 'blue', 'teal', 'orange', 'purple'];
365 $colorNums = count($colorArr); 368 $colorNums = count($colorArr);
366 $badgeList = []; 369 $badgeList = [];
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 <li class="{$vo.active?'active':''}"><a href="#{$vo.name}" data-toggle="tab">{:__($vo.title)}</a></li> 23 <li class="{$vo.active?'active':''}"><a href="#{$vo.name}" data-toggle="tab">{:__($vo.title)}</a></li>
24 {/foreach} 24 {/foreach}
25 <li> 25 <li>
26 - <a href="#addcfg" data-toggle="tab"><i class="fa fa-plus"></i></a> 26 + <a href="#addcfg" data-toggle="tab" title="{:__('Add new config')}"><i class="fa fa-plus"></i></a>
27 </li> 27 </li>
28 </ul> 28 </ul>
29 </div> 29 </div>
@@ -5,6 +5,7 @@ namespace app\api\controller; @@ -5,6 +5,7 @@ namespace app\api\controller;
5 use app\common\controller\Api; 5 use app\common\controller\Api;
6 use app\common\library\Sms as Smslib; 6 use app\common\library\Sms as Smslib;
7 use app\common\model\User; 7 use app\common\model\User;
  8 +use think\Hook;
8 9
9 /** 10 /**
10 * 手机短信接口 11 * 手机短信接口
@@ -50,11 +51,14 @@ class Sms extends Api @@ -50,11 +51,14 @@ class Sms extends Api
50 $this->error(__('未注册')); 51 $this->error(__('未注册'));
51 } 52 }
52 } 53 }
  54 + if (!Hook::get('sms_send')) {
  55 + $this->error(__('请在后台插件管理安装短信验证插件'));
  56 + }
53 $ret = Smslib::send($mobile, null, $event); 57 $ret = Smslib::send($mobile, null, $event);
54 if ($ret) { 58 if ($ret) {
55 $this->success(__('发送成功')); 59 $this->success(__('发送成功'));
56 } else { 60 } else {
57 - $this->error(__('发送失败')); 61 + $this->error(__('发送失败,请检查短信配置是否正确'));
58 } 62 }
59 } 63 }
60 64
@@ -96,6 +96,7 @@ class User extends Api @@ -96,6 +96,7 @@ class User extends Api
96 * @param string $password 密码 96 * @param string $password 密码
97 * @param string $email 邮箱 97 * @param string $email 邮箱
98 * @param string $mobile 手机号 98 * @param string $mobile 手机号
  99 + * @param string $code 验证码
99 */ 100 */
100 public function register() 101 public function register()
101 { 102 {
@@ -103,6 +104,7 @@ class User extends Api @@ -103,6 +104,7 @@ class User extends Api
103 $password = $this->request->request('password'); 104 $password = $this->request->request('password');
104 $email = $this->request->request('email'); 105 $email = $this->request->request('email');
105 $mobile = $this->request->request('mobile'); 106 $mobile = $this->request->request('mobile');
  107 + $code = $this->request->request('code');
106 if (!$username || !$password) { 108 if (!$username || !$password) {
107 $this->error(__('Invalid parameters')); 109 $this->error(__('Invalid parameters'));
108 } 110 }
@@ -112,6 +114,10 @@ class User extends Api @@ -112,6 +114,10 @@ class User extends Api
112 if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) { 114 if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {
113 $this->error(__('Mobile is incorrect')); 115 $this->error(__('Mobile is incorrect'));
114 } 116 }
  117 + $ret = Sms::check($mobile, $code, 'register');
  118 + if (!$ret) {
  119 + $this->error(__('Captcha is incorrect'));
  120 + }
115 $ret = $this->auth->register($username, $password, $email, $mobile, []); 121 $ret = $this->auth->register($username, $password, $email, $mobile, []);
116 if ($ret) { 122 if ($ret) {
117 $data = ['userinfo' => $this->auth->getUserinfo()]; 123 $data = ['userinfo' => $this->auth->getUserinfo()];
@@ -57,7 +57,7 @@ return [ @@ -57,7 +57,7 @@ return [
57 // 默认模块名 57 // 默认模块名
58 'default_module' => 'index', 58 'default_module' => 'index',
59 // 禁止访问模块 59 // 禁止访问模块
60 - 'deny_module_list' => ['common'], 60 + 'deny_module_list' => ['common', 'admin'],
61 // 默认控制器名 61 // 默认控制器名
62 'default_controller' => 'Index', 62 'default_controller' => 'Index',
63 // 默认操作名 63 // 默认操作名
@@ -272,7 +272,7 @@ return [ @@ -272,7 +272,7 @@ return [
272 //自动检测更新 272 //自动检测更新
273 'checkupdate' => false, 273 'checkupdate' => false,
274 //版本号 274 //版本号
275 - 'version' => '1.0.0.20190705_beta', 275 + 'version' => '1.0.0.20190930_beta',
276 //API接口地址 276 //API接口地址
277 'api_url' => 'https://api.fastadmin.net', 277 'api_url' => 'https://api.fastadmin.net',
278 ], 278 ],
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 namespace app\index\controller; 3 namespace app\index\controller;
4 4
5 use app\common\controller\Frontend; 5 use app\common\controller\Frontend;
  6 +use app\common\library\Sms;
6 use think\Config; 7 use think\Config;
7 use think\Cookie; 8 use think\Cookie;
8 use think\Hook; 9 use think\Hook;
@@ -85,13 +86,13 @@ class User extends Frontend @@ -85,13 +86,13 @@ class User extends Frontend
85 $email = $this->request->post('email'); 86 $email = $this->request->post('email');
86 $mobile = $this->request->post('mobile', ''); 87 $mobile = $this->request->post('mobile', '');
87 $captcha = $this->request->post('captcha'); 88 $captcha = $this->request->post('captcha');
  89 + $code = $this->request->post('code');
88 $token = $this->request->post('__token__'); 90 $token = $this->request->post('__token__');
89 $rule = [ 91 $rule = [
90 'username' => 'require|length:3,30', 92 'username' => 'require|length:3,30',
91 'password' => 'require|length:6,30', 93 'password' => 'require|length:6,30',
92 'email' => 'require|email', 94 'email' => 'require|email',
93 'mobile' => 'regex:/^1\d{10}$/', 95 'mobile' => 'regex:/^1\d{10}$/',
94 - 'captcha' => 'require|captcha',  
95 '__token__' => 'require|token', 96 '__token__' => 'require|token',
96 ]; 97 ];
97 98
@@ -100,8 +101,8 @@ class User extends Frontend @@ -100,8 +101,8 @@ class User extends Frontend
100 'username.length' => 'Username must be 3 to 30 characters', 101 'username.length' => 'Username must be 3 to 30 characters',
101 'password.require' => 'Password can not be empty', 102 'password.require' => 'Password can not be empty',
102 'password.length' => 'Password must be 6 to 30 characters', 103 'password.length' => 'Password must be 6 to 30 characters',
103 - 'captcha.require' => 'Captcha can not be empty',  
104 - 'captcha.captcha' => 'Captcha is incorrect', 104 + //'captcha.require' => 'Captcha can not be empty',
  105 + //'captcha.captcha' => 'Captcha is incorrect',
105 'email' => 'Email is incorrect', 106 'email' => 'Email is incorrect',
106 'mobile' => 'Mobile is incorrect', 107 'mobile' => 'Mobile is incorrect',
107 ]; 108 ];
@@ -110,9 +111,13 @@ class User extends Frontend @@ -110,9 +111,13 @@ class User extends Frontend
110 'password' => $password, 111 'password' => $password,
111 'email' => $email, 112 'email' => $email,
112 'mobile' => $mobile, 113 'mobile' => $mobile,
113 - 'captcha' => $captcha, 114 + //'captcha' => $captcha,
114 '__token__' => $token, 115 '__token__' => $token,
115 ]; 116 ];
  117 + $ret = Sms::check($mobile, $code, 'register');
  118 + if (!$ret) {
  119 + $this->error(__('Captcha is incorrect'));
  120 + }
116 $validate = new Validate($rule, $msg); 121 $validate = new Validate($rule, $msg);
117 $result = $validate->check($data); 122 $result = $validate->check($data);
118 if (!$result) { 123 if (!$result) {
@@ -2,12 +2,13 @@ @@ -2,12 +2,13 @@
2 2
3 return [ 3 return [
4 'Title' => '标题', 4 'Title' => '标题',
  5 + 'CRUD' => '一键CRUD',
5 'Auth tips' => '基于完善的Auth权限控制管理、无限父子级权限分组、可自由分配子级权限、一个管理员可同时属于多个组别', 6 'Auth tips' => '基于完善的Auth权限控制管理、无限父子级权限分组、可自由分配子级权限、一个管理员可同时属于多个组别',
6 'Responsive tips' => '基于Bootstrap和AdminLTE进行二次开发,手机、平板、PC均自动适配,无需要担心兼容性问题', 7 'Responsive tips' => '基于Bootstrap和AdminLTE进行二次开发,手机、平板、PC均自动适配,无需要担心兼容性问题',
7 'Languages tips' => '不仅仅后台开发支持多语言,同时视图部分和JS部分仍然共享同一个语言包,语法相同且自动加载', 8 'Languages tips' => '不仅仅后台开发支持多语言,同时视图部分和JS部分仍然共享同一个语言包,语法相同且自动加载',
8 'Module tips' => '控制器、模型、视图、JS一一对应,使用RequireJS进行JS模块化管理,采用Bower进行前端包组件管理', 9 'Module tips' => '控制器、模型、视图、JS一一对应,使用RequireJS进行JS模块化管理,采用Bower进行前端包组件管理',
9 - 'CRUD tips' => '控制台进行一键生成控制器、模型、视图和JS文件,一键生成API文档,一键生成后台权限节点和菜单栏',  
10 - 'Extension tips' => 'FastAdmin提供强大的扩展中心,可直接在线安装和卸载插件,同时支持命令行一键操作', 10 + 'CRUD tips' => '可使用命令行一键生成控制器、模型、视图和JS文件,一键生成API文档,一键生成回收站,一键生成后台权限节点和菜单栏',
  11 + 'Extension tips' => 'FastAdmin提供强大丰富的应用(插件)市场,可直接在线安装和卸载用户(插件),同时支持命令行一键操作',
11 'Do not hesitate' => '不要犹豫', 12 'Do not hesitate' => '不要犹豫',
12 'Start to act' => '开始行动', 13 'Start to act' => '开始行动',
13 ]; 14 ];
@@ -63,7 +63,6 @@ @@ -63,7 +63,6 @@
63 <div class="header-content-inner"> 63 <div class="header-content-inner">
64 <h1>FastAdmin</h1> 64 <h1>FastAdmin</h1>
65 <h3>{:__('The fastest framework based on ThinkPHP5 and Bootstrap')}</h3> 65 <h3>{:__('The fastest framework based on ThinkPHP5 and Bootstrap')}</h3>
66 - <a href="{:url('admin/index/login')}" class="btn btn-warning btn-xl page-scroll">{:__('Go to Dashboard')}</a>  
67 <a href="{:url('index/user/index')}" class="btn btn-outline btn-xl page-scroll">{:__('Go to Member center')}</a> 66 <a href="{:url('index/user/index')}" class="btn btn-outline btn-xl page-scroll">{:__('Go to Member center')}</a>
68 </div> 67 </div>
69 </div> 68 </div>
@@ -147,7 +146,7 @@ @@ -147,7 +146,7 @@
147 <footer> 146 <footer>
148 <div class="container"> 147 <div class="container">
149 <!-- FastAdmin是开源程序,建议在您的网站底部保留一个FastAdmin的链接 --> 148 <!-- FastAdmin是开源程序,建议在您的网站底部保留一个FastAdmin的链接 -->
150 - <p>&copy; 2017-2018 <a href="https://www.fastadmin.net" target="_blank">FastAdmin</a>. All Rights Reserved.</p> 149 + <p>&copy; 2017-2019 <a href="https://www.fastadmin.net" target="_blank">FastAdmin</a>. All Rights Reserved.</p>
151 <ul class="list-inline"> 150 <ul class="list-inline">
152 <li> 151 <li>
153 <a href="https://gitee.com/karson/fastadmin">{:__('Gitee')}</a> 152 <a href="https://gitee.com/karson/fastadmin">{:__('Gitee')}</a>
@@ -61,7 +61,7 @@ @@ -61,7 +61,7 @@
61 61
62 <footer class="footer" style="clear:both"> 62 <footer class="footer" style="clear:both">
63 <!-- FastAdmin是开源程序,建议在您的网站底部保留一个FastAdmin的链接 --> 63 <!-- FastAdmin是开源程序,建议在您的网站底部保留一个FastAdmin的链接 -->
64 - <p class="copyright">Copyright&nbsp;©&nbsp;2017-2019 Powered by <a href="https://www.fastadmin.net" target="_blank">FastAdmin</a> All Rights Reserved {$site.name|htmlentities} {:__('Copyrights')} <a href="http://www.miibeian.gov.cn" target="_blank">{$site.beian|htmlentities}</a></p> 64 + <p class="copyright">Copyright&nbsp;©&nbsp;2017-2019 Powered by <a href="https://www.fastadmin.net" target="_blank">FastAdmin</a> All Rights Reserved <a href="http://www.beian.miit.gov.cn" target="_blank">{$site.beian|htmlentities}</a></p>
65 </footer> 65 </footer>
66 66
67 {include file="common/script" /} 67 {include file="common/script" /}
@@ -37,10 +37,10 @@ @@ -37,10 +37,10 @@
37 <div class="form-group"> 37 <div class="form-group">
38 <label class="control-label">{:__('Captcha')}</label> 38 <label class="control-label">{:__('Captcha')}</label>
39 <div class="controls"> 39 <div class="controls">
40 - <div class="input-group input-group-lg">  
41 - <input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="required;length(4)" style="border-radius: 0;" />  
42 - <span class="input-group-addon" style="padding:0;border:none;">  
43 - <img src="{:captcha_src()}" width="140" height="42" onclick="this.src = '{:captcha_src()}?r=' + Math.random();"/> 40 + <div class="input-group">
  41 + <input type="text" name="code" class="form-control input-lg" data-rule="required;length(4);integer[+];remote({:url('api/validate/check_sms_correct')}, event=register, mobile:#mobile)" />
  42 + <span class="input-group-btn" style="padding:0;border:none;">
  43 + <a href="javascript:;" class="btn btn-info btn-captcha btn-lg" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="register">发送验证码</a>
44 </span> 44 </span>
45 </div> 45 </div>
46 <p class="help-block"></p> 46 <p class="help-block"></p>
@@ -62,6 +62,15 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -62,6 +62,15 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
62 // 初始化表格 62 // 初始化表格
63 table.bootstrapTable({ 63 table.bootstrapTable({
64 url: $.fn.bootstrapTable.defaults.extend.index_url, 64 url: $.fn.bootstrapTable.defaults.extend.index_url,
  65 + queryParams: function (params) {
  66 + var userinfo = Controller.api.userinfo.get();
  67 + $.extend(params, {
  68 + uid: userinfo ? userinfo.id : '',
  69 + token: userinfo ? userinfo.token : '',
  70 + version: Config.fastadmin.version
  71 + });
  72 + return params;
  73 + },
65 columns: [ 74 columns: [
66 [ 75 [
67 {field: 'id', title: 'ID', operate: false, visible: false}, 76 {field: 'id', title: 'ID', operate: false, visible: false},
@@ -144,8 +153,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function @@ -144,8 +153,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
144 commonSearch: true, 153 commonSearch: true,
145 searchFormVisible: true, 154 searchFormVisible: true,
146 searchFormTemplate: 'searchformtpl', 155 searchFormTemplate: 'searchformtpl',
147 - pageSize: 12,  
148 - pagination: false, 156 + pageSize: 30,
149 }); 157 });
150 158
151 // 为表格绑定事件 159 // 为表格绑定事件
@@ -23,15 +23,15 @@ define('INSTALL_PATH', APP_PATH . 'admin' . DS . 'command' . DS . 'Install' . DS @@ -23,15 +23,15 @@ define('INSTALL_PATH', APP_PATH . 'admin' . DS . 'command' . DS . 'Install' . DS
23 // 判断文件或目录是否有写的权限 23 // 判断文件或目录是否有写的权限
24 function is_really_writable($file) 24 function is_really_writable($file)
25 { 25 {
26 - if (DIRECTORY_SEPARATOR == '/' AND @ ini_get("safe_mode") == FALSE) { 26 + if (DIRECTORY_SEPARATOR == '/' AND @ ini_get("safe_mode") == false) {
27 return is_writable($file); 27 return is_writable($file);
28 } 28 }
29 - if (!is_file($file) OR ($fp = @fopen($file, "r+")) === FALSE) {  
30 - return FALSE; 29 + if (!is_file($file) OR ($fp = @fopen($file, "r+")) === false) {
  30 + return false;
31 } 31 }
32 32
33 fclose($fp); 33 fclose($fp);
34 - return TRUE; 34 + return true;
35 } 35 }
36 36
37 $sitename = "FastAdmin"; 37 $sitename = "FastAdmin";
@@ -59,31 +59,40 @@ $errInfo = ''; @@ -59,31 +59,40 @@ $errInfo = '';
59 //数据库配置文件 59 //数据库配置文件
60 $dbConfigFile = APP_PATH . 'database.php'; 60 $dbConfigFile = APP_PATH . 'database.php';
61 61
  62 +//后台入口文件
  63 +$adminFile = ROOT_PATH . 'public' . DS . 'admin.php';
  64 +
62 // 锁定的文件 65 // 锁定的文件
63 $lockFile = INSTALL_PATH . 'install.lock'; 66 $lockFile = INSTALL_PATH . 'install.lock';
64 if (is_file($lockFile)) { 67 if (is_file($lockFile)) {
65 $errInfo = "当前已经安装{$sitename},如果需要重新安装,请手动移除application/admin/command/Install/install.lock文件"; 68 $errInfo = "当前已经安装{$sitename},如果需要重新安装,请手动移除application/admin/command/Install/install.lock文件";
66 -} else if (version_compare(PHP_VERSION, '5.5.0', '<')) {  
67 - $errInfo = "当前版本(" . PHP_VERSION . ")过低,请使用PHP5.5以上版本";  
68 -} else if (!extension_loaded("PDO")) {  
69 - $errInfo = "当前未开启PDO,无法进行安装";  
70 -} else if (!is_really_writable($dbConfigFile)) {  
71 - $open_basedir = ini_get('open_basedir');  
72 - if ($open_basedir) {  
73 - $dirArr = explode(PATH_SEPARATOR, $open_basedir);  
74 - if ($dirArr && in_array(__DIR__, $dirArr)) {  
75 - $errInfo = '当前服务器因配置了open_basedir,导致无法读取父目录<br><a href="https://forum.fastadmin.net/thread/1145?ref=install" target="_blank">点击查看解决办法</a>';  
76 - }  
77 - }  
78 - if (!$errInfo) {  
79 - $errInfo = '当前权限不足,无法写入配置文件application/database.php<br><a href="https://forum.fastadmin.net/thread/1145?ref=install" target="_blank">点击查看解决办法</a>';  
80 - }  
81 } else { 69 } else {
82 - $dirArr = [];  
83 - foreach ($checkDirs as $k => $v) {  
84 - if (!is_dir(ROOT_PATH . $v)) {  
85 - $errInfo = '当前代码仅包含核心代码,请前往官网下载完整包或资源包覆盖后再尝试安装,<a href="https://www.fastadmin.net/download.html?ref=install" target="_blank">立即前往下载</a>';  
86 - break; 70 + if (version_compare(PHP_VERSION, '5.5.0', '<')) {
  71 + $errInfo = "当前版本(" . PHP_VERSION . ")过低,请使用PHP5.5以上版本";
  72 + } else {
  73 + if (!extension_loaded("PDO")) {
  74 + $errInfo = "当前未开启PDO,无法进行安装";
  75 + } else {
  76 + if (!is_really_writable($dbConfigFile)) {
  77 + $open_basedir = ini_get('open_basedir');
  78 + if ($open_basedir) {
  79 + $dirArr = explode(PATH_SEPARATOR, $open_basedir);
  80 + if ($dirArr && in_array(__DIR__, $dirArr)) {
  81 + $errInfo = '当前服务器因配置了open_basedir,导致无法读取父目录<br><a href="https://forum.fastadmin.net/thread/1145?ref=install" target="_blank">点击查看解决办法</a>';
  82 + }
  83 + }
  84 + if (!$errInfo) {
  85 + $errInfo = '当前权限不足,无法写入配置文件application/database.php<br><a href="https://forum.fastadmin.net/thread/1145?ref=install" target="_blank">点击查看解决办法</a>';
  86 + }
  87 + } else {
  88 + $dirArr = [];
  89 + foreach ($checkDirs as $k => $v) {
  90 + if (!is_dir(ROOT_PATH . $v)) {
  91 + $errInfo = '当前代码仅包含核心代码,请前往官网下载完整包或资源包覆盖后再尝试安装,<a href="https://www.fastadmin.net/download.html?ref=install" target="_blank">立即前往下载</a>';
  92 + break;
  93 + }
  94 + }
  95 + }
87 } 96 }
88 } 97 }
89 } 98 }
@@ -110,22 +119,19 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { @@ -110,22 +119,19 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
110 $adminPasswordConfirmation = isset($_POST['adminPasswordConfirmation']) ? $_POST['adminPasswordConfirmation'] : '123456'; 119 $adminPasswordConfirmation = isset($_POST['adminPasswordConfirmation']) ? $_POST['adminPasswordConfirmation'] : '123456';
111 $adminEmail = isset($_POST['adminEmail']) ? $_POST['adminEmail'] : 'admin@admin.com'; 120 $adminEmail = isset($_POST['adminEmail']) ? $_POST['adminEmail'] : 'admin@admin.com';
112 121
113 - if ($adminPassword !== $adminPasswordConfirmation) {  
114 - echo "两次输入的密码不一致";  
115 - exit;  
116 - } else if (!preg_match("/^\w+$/", $adminUsername)) {  
117 - echo "用户名只能输入字母、数字、下划线"; 122 + if (!preg_match("/^\w{3,12}$/", $adminUsername)) {
  123 + echo "用户名只能由3-12位数字、字母、下划线组合";
118 exit; 124 exit;
119 - } else if (!preg_match("/^[\S]+$/", $adminPassword)) {  
120 - echo "密码不能包含空格";  
121 - exit;  
122 - } else if (strlen($adminUsername) < 3 || strlen($adminUsername) > 12) {  
123 - echo "用户名请输入3~12位字符"; 125 + }
  126 + if (!preg_match("/^[\S]{6,16}$/", $adminPassword)) {
  127 + echo "密码长度必须在6-16位之间,不能包含空格";
124 exit; 128 exit;
125 - } else if (strlen($adminPassword) < 6 || strlen($adminPassword) > 16 || stripos($adminPassword, ' ') !== false) {  
126 - echo "密码请输入6~16位字符,不能包含空格"; 129 + }
  130 + if ($adminPassword !== $adminPasswordConfirmation) {
  131 + echo "两次输入的密码不一致";
127 exit; 132 exit;
128 } 133 }
  134 +
129 try { 135 try {
130 //检测能否读取安装文件 136 //检测能否读取安装文件
131 $sql = @file_get_contents(INSTALL_PATH . 'fastadmin.sql'); 137 $sql = @file_get_contents(INSTALL_PATH . 'fastadmin.sql');
@@ -177,7 +183,14 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { @@ -177,7 +183,14 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
177 $newSalt = substr(md5(uniqid(true)), 0, 6); 183 $newSalt = substr(md5(uniqid(true)), 0, 6);
178 $newPassword = md5(md5($adminPassword) . $newSalt); 184 $newPassword = md5(md5($adminPassword) . $newSalt);
179 $pdo->query("UPDATE {$mysqlPrefix}admin SET username = '{$adminUsername}', email = '{$adminEmail}',password = '{$newPassword}', salt = '{$newSalt}' WHERE username = 'admin'"); 185 $pdo->query("UPDATE {$mysqlPrefix}admin SET username = '{$adminUsername}', email = '{$adminEmail}',password = '{$newPassword}', salt = '{$newSalt}' WHERE username = 'admin'");
180 - echo "success"; 186 +
  187 + $adminName = '';
  188 + if (is_file($adminFile)) {
  189 + $x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  190 + $adminName = substr(str_shuffle(str_repeat($x, ceil(10 / strlen($x)))), 1, 10) . '.php';
  191 + rename($adminFile, ROOT_PATH . 'public' . DS . $adminName);
  192 + }
  193 + echo "success|{$adminName}";
181 } catch (PDOException $e) { 194 } catch (PDOException $e) {
182 $err = $e->getMessage(); 195 $err = $e->getMessage();
183 } catch (Exception $e) { 196 } catch (Exception $e) {
@@ -202,16 +215,18 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { @@ -202,16 +215,18 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
202 margin: 0; 215 margin: 0;
203 padding: 0; 216 padding: 0;
204 line-height: 1.5; 217 line-height: 1.5;
  218 + -webkit-font-smoothing: antialiased;
  219 + -moz-osx-font-smoothing: grayscale;
205 } 220 }
206 221
207 body, input, button { 222 body, input, button {
208 - font-family: 'Open Sans', sans-serif;  
209 - font-size: 16px; 223 + font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, 'Microsoft Yahei', Arial, sans-serif;
  224 + font-size: 14px;
210 color: #7E96B3; 225 color: #7E96B3;
211 } 226 }
212 227
213 .container { 228 .container {
214 - max-width: 515px; 229 + max-width: 480px;
215 margin: 0 auto; 230 margin: 0 auto;
216 padding: 20px; 231 padding: 20px;
217 text-align: center; 232 text-align: center;
@@ -236,6 +251,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { @@ -236,6 +251,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
236 font-weight: normal; 251 font-weight: normal;
237 color: #3C5675; 252 color: #3C5675;
238 margin-bottom: 0; 253 margin-bottom: 0;
  254 + margin-top: 0;
239 } 255 }
240 256
241 form { 257 form {
@@ -300,7 +316,16 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { @@ -300,7 +316,16 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
300 opacity: 0.5; 316 opacity: 0.5;
301 } 317 }
302 318
303 - #error, .error, #success, .success { 319 + .form-buttons {
  320 + height: 52px;
  321 + line-height: 52px;
  322 + }
  323 +
  324 + .form-buttons .btn {
  325 + margin-right: 5px;
  326 + }
  327 +
  328 + #error, .error, #success, .success, #warmtips, .warmtips {
304 background: #D83E3E; 329 background: #D83E3E;
305 color: #fff; 330 color: #fff;
306 padding: 15px 20px; 331 padding: 15px 20px;
@@ -316,13 +341,29 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { @@ -316,13 +341,29 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
316 color: white; 341 color: white;
317 text-decoration: underline; 342 text-decoration: underline;
318 } 343 }
  344 +
  345 + #warmtips {
  346 + background: #ffcdcd;
  347 + font-size: 14px;
  348 + color: #e74c3c;
  349 + }
  350 +
  351 + #warmtips a {
  352 + background: #ffffff7a;
  353 + display: block;
  354 + height: 30px;
  355 + line-height: 30px;
  356 + margin-top: 10px;
  357 + color: #e21a1a;
  358 + border-radius: 3px;
  359 + }
319 </style> 360 </style>
320 </head> 361 </head>
321 362
322 <body> 363 <body>
323 <div class="container"> 364 <div class="container">
324 <h1> 365 <h1>
325 - <svg width="100px" height="120px" viewBox="0 0 768 830" version="1.1" xmlns="http://www.w3.org/2000/svg" 366 + <svg width="80px" height="96px" viewBox="0 0 768 830" version="1.1" xmlns="http://www.w3.org/2000/svg"
326 xmlns:xlink="http://www.w3.org/1999/xlink"> 367 xmlns:xlink="http://www.w3.org/1999/xlink">
327 <g id="logo" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> 368 <g id="logo" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
328 <path d="M64.433651,605.899968 C20.067302,536.265612 0,469.698785 0,389.731348 C0,174.488668 171.922656,0 384,0 C596.077344,0 768,174.488668 768,389.731348 C768,469.698785 747.932698,536.265612 703.566349,605.899968 C614.4,753.480595 441.6,870.4 384,870.4 C326.4,870.4 153.6,753.480595 64.433651,605.899968 L64.433651,605.899968 Z" 369 <path d="M64.433651,605.899968 C20.067302,536.265612 0,469.698785 0,389.731348 C0,174.488668 171.922656,0 384,0 C596.077344,0 768,174.488668 768,389.731348 C768,469.698785 747.932698,536.265612 703.566349,605.899968 C614.4,753.480595 441.6,870.4 384,870.4 C326.4,870.4 153.6,753.480595 64.433651,605.899968 L64.433651,605.899968 Z"
@@ -336,7 +377,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { @@ -336,7 +377,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
336 <div> 377 <div>
337 378
338 <p>若你在安装中遇到麻烦可点击 <a href="<?php echo $link['doc']; ?>" target="_blank">安装文档</a> <a 379 <p>若你在安装中遇到麻烦可点击 <a href="<?php echo $link['doc']; ?>" target="_blank">安装文档</a> <a
339 - href="<?php echo $link['forum']; ?>" target="_blank">交流社区</a> <a 380 + href="<?php echo $link['forum']; ?>" target="_blank">问答社区</a> <a
340 href="<?php echo $link['qqun']; ?>">QQ交流群</a></p> 381 href="<?php echo $link['qqun']; ?>">QQ交流群</a></p>
341 <!--<p><?php echo $sitename; ?>还支持在命令行php think install一键安装</p>--> 382 <!--<p><?php echo $sitename; ?>还支持在命令行php think install一键安装</p>-->
342 383
@@ -348,6 +389,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { @@ -348,6 +389,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
348 <?php endif; ?> 389 <?php endif; ?>
349 <div id="error" style="display:none"></div> 390 <div id="error" style="display:none"></div>
350 <div id="success" style="display:none"></div> 391 <div id="success" style="display:none"></div>
  392 + <div id="warmtips" style="display:none"></div>
351 393
352 <div class="form-group"> 394 <div class="form-group">
353 <div class="form-field"> 395 <div class="form-field">
@@ -417,18 +459,28 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { @@ -417,18 +459,28 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
417 459
418 $('form').on('submit', function (e) { 460 $('form').on('submit', function (e) {
419 e.preventDefault(); 461 e.preventDefault();
420 - 462 + var form = this;
421 var $button = $(this).find('button') 463 var $button = $(this).find('button')
422 .text('安装中...') 464 .text('安装中...')
423 .prop('disabled', true); 465 .prop('disabled', true);
424 466
425 $.post('', $(this).serialize()) 467 $.post('', $(this).serialize())
426 .done(function (ret) { 468 .done(function (ret) {
427 - if (ret === 'success') { 469 + if (ret.substr(0, 7) === 'success') {
  470 + var retArr = ret.split(/\|/);
428 $('#error').hide(); 471 $('#error').hide();
429 - $("#success").text("安装成功!开始你的<?php echo $sitename; ?>之旅吧!").show();  
430 - $('<a class="btn" href="./">访问首页</a> <a class="btn" href="./index.php/admin/index/login" style="background:#18bc9c">访问后台</a>').insertAfter($button); 472 + $(".form-group", form).remove();
431 $button.remove(); 473 $button.remove();
  474 + $("#success").text("安装成功!开始你的<?php echo $sitename; ?>之旅吧!").show();
  475 +
  476 + $buttons = $(".form-buttons", form);
  477 + $('<a class="btn" href="./">访问首页</a>').appendTo($buttons);
  478 +
  479 + if (typeof retArr[1] !== 'undefined' && retArr[1] !== '') {
  480 + var url = location.href.replace(/install\.php/, retArr[1]);
  481 + $("#warmtips").html('温馨提示:请将以下后台登录入口添加到你的收藏夹,为了你的安全,不要泄漏或发送给他人!如有泄漏请及时修改!<a href="' + url + '">' + url + '</a>').show();
  482 + $('<a class="btn" href="' + url + '" id="btn-admin" style="background:#18bc9c">访问后台</a>').appendTo($buttons);
  483 + }
432 localStorage.setItem("fastep", "installed"); 484 localStorage.setItem("fastep", "installed");
433 } else { 485 } else {
434 $('#error').show().text(ret); 486 $('#error').show().text(ret);