mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-22 08:18:41 +00:00
feat(web): disable register & add user manager
This commit is contained in:
parent
3964f64c14
commit
a6e18b25bd
@ -13,6 +13,10 @@
|
||||
return "无效表单";
|
||||
}
|
||||
|
||||
if (DB::selectCount("SELECT COUNT(*) FROM user_info")) {
|
||||
return "只有首位用户可以注册。";
|
||||
}
|
||||
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
$email = $_POST['email'];
|
||||
|
@ -1,4 +1,7 @@
|
||||
<?php
|
||||
$REQUIRE_LIB['md5'] = '';
|
||||
$REQUIRE_LIB['jquery.query'] = '';
|
||||
|
||||
requirePHPLib('form');
|
||||
requirePHPLib('judger');
|
||||
|
||||
@ -6,6 +9,74 @@
|
||||
become403Page();
|
||||
}
|
||||
|
||||
$register_form = new UOJForm('register');
|
||||
$register_form->submit_button_config['align'] = 'compressed';
|
||||
$register_form->addInput('new_username', 'text', '用户名', '',
|
||||
function ($new_username) {
|
||||
if (!validateUsername($new_username)) {
|
||||
return '用户名不合法';
|
||||
}
|
||||
if (queryUser($new_username)) {
|
||||
return '该用户已存在';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$register_form->addInput('new_password', 'password', '密码', '',
|
||||
function ($new_password) {
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$register_form->addInput('new_realname', 'text', '真实姓名', '',
|
||||
function ($new_realname) {
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$register_form->handle = function() {
|
||||
$new_username = $_POST['new_username'];
|
||||
$new_password = $_POST['new_password'];
|
||||
$new_realname = $_POST['new_realname'];
|
||||
$new_password = hash_hmac('md5', $new_password, getPasswordClientSalt());
|
||||
$new_password = getPasswordToStore($new_password, $new_username);
|
||||
$svn_pw = uojRandString(10);
|
||||
|
||||
DB::query("insert into user_info (username, realname, password, svn_password, register_time, usergroup) values ('$new_username', '$new_realname', '$new_password', '$svn_pw', now(), 'U')");
|
||||
};
|
||||
$register_form->runAtServer();
|
||||
|
||||
$change_password_form = new UOJForm('change_password');
|
||||
$change_password_form->submit_button_config['align'] = 'compressed';
|
||||
$change_password_form->addInput('p_username', 'text', '用户名', '',
|
||||
function ($p_username) {
|
||||
if (!validateUsername($p_username)) {
|
||||
return '用户名不合法';
|
||||
}
|
||||
if (!queryUser($p_username)) {
|
||||
return '用户不存在';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$change_password_form->addInput('p_password', 'password', '密码', '',
|
||||
function ($p_password) {
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$change_password_form->handle = function() {
|
||||
$p_username = $_POST['p_username'];
|
||||
$p_password = $_POST['p_password'];
|
||||
$p_password = hash_hmac('md5', $p_password, getPasswordClientSalt());
|
||||
$p_password = getPasswordToStore($p_password, $p_username);
|
||||
|
||||
DB::query("update user_info set password = '$p_password' where username = '$p_username'");
|
||||
};
|
||||
$change_password_form->runAtServer();
|
||||
|
||||
$change_realname_form = new UOJForm('change_realname');
|
||||
$change_realname_form->submit_button_config['align'] = 'compressed';
|
||||
$change_realname_form->addInput('r_username', 'text', '用户名', '',
|
||||
@ -53,12 +124,12 @@
|
||||
'normaluser' => '设为普通用户',
|
||||
'superuser' => '设为超级用户'
|
||||
);
|
||||
$user_form->addSelect('op-type', $options, '操作类型', '');
|
||||
$user_form->addSelect('op_type', $options, '操作类型', '');
|
||||
$user_form->handle = function() {
|
||||
global $user_form;
|
||||
|
||||
$username = $_POST['username'];
|
||||
switch ($_POST['op-type']) {
|
||||
switch ($_POST['op_type']) {
|
||||
case 'banneduser':
|
||||
DB::update("update user_info set usergroup = 'B' where username = '{$username}'");
|
||||
break;
|
||||
@ -327,27 +398,48 @@ EOD;
|
||||
EOD;
|
||||
};
|
||||
|
||||
$banlist_cols = array('username', 'usergroup');
|
||||
$banlist_config = array();
|
||||
$banlist_header_row = <<<EOD
|
||||
$userlist_cols = array('username', 'usergroup', 'register_time');
|
||||
$userlist_config = array('page_len' => 20,
|
||||
'table_classes' => array('table', 'table-bordered', 'table-hover', 'table-striped'));
|
||||
$userlist_header_row = <<<EOD
|
||||
<tr>
|
||||
<th>用户名</th>
|
||||
<th style="width: 6em">用户类别</th>
|
||||
<th style="width: 12em">注册时间</th>
|
||||
</tr>
|
||||
EOD;
|
||||
$banlist_print_row = function($row) {
|
||||
|
||||
$cur_tab = isset($_GET['tab']) ? $_GET['tab'] : 'users';
|
||||
|
||||
$user_list_cond = array();
|
||||
if ($cur_tab === 'users') {
|
||||
if (isset($_GET['username']) && $_GET['username'] != "") {
|
||||
$user_list_cond[] = "username like '%" . DB::escape($_GET['username']) . "%'";
|
||||
}
|
||||
if (isset($_GET['usergroup']) && $_GET['usergroup'] != "") {
|
||||
$user_list_cond[] = "usergroup = '" . DB::escape($_GET['usergroup']) . "'";
|
||||
}
|
||||
}
|
||||
if ($user_list_cond) {
|
||||
$user_list_cond = join($user_list_cond, ' and ');
|
||||
} else {
|
||||
$user_list_cond = '1';
|
||||
}
|
||||
|
||||
$userlist_print_row = function($row) {
|
||||
$hislink = getUserLink($row['username']);
|
||||
echo <<<EOD
|
||||
<tr>
|
||||
<td>${hislink}</td>
|
||||
<td>{$row['usergroup']}</td>
|
||||
<td>{$row['register_time']}</td>
|
||||
</tr>
|
||||
EOD;
|
||||
};
|
||||
|
||||
$cur_tab = isset($_GET['tab']) ? $_GET['tab'] : 'users';
|
||||
|
||||
$tabs_info = array(
|
||||
'users' => array(
|
||||
'name' => '用户操作',
|
||||
'name' => '用户管理',
|
||||
'url' => "/super-manage/users"
|
||||
),
|
||||
'blogs' => array(
|
||||
@ -362,20 +454,12 @@ EOD;
|
||||
'name' => '自定义测试',
|
||||
'url' => '/super-manage/custom-test'
|
||||
),
|
||||
'click-zan' => array(
|
||||
'name' => '点赞管理',
|
||||
'url' => '/super-manage/click-zan'
|
||||
),
|
||||
'search' => array(
|
||||
'name' => '搜索管理',
|
||||
'url' => '/super-manage/search'
|
||||
),
|
||||
'judger' => array(
|
||||
'name' => '评测机管理',
|
||||
'url' => '/super-manage/judger'
|
||||
),
|
||||
'paste' => array(
|
||||
'name' => 'Paste管理',
|
||||
'name' => '剪贴板管理',
|
||||
'url' => '/super-manage/paste'
|
||||
)
|
||||
);
|
||||
@ -396,11 +480,37 @@ EOD;
|
||||
|
||||
<div class="col-sm-9">
|
||||
<?php if ($cur_tab === 'users'): ?>
|
||||
<h3>添加新用户</h3>
|
||||
<?php $register_form->printHTML(); ?>
|
||||
<h3>修改用户密码</h3>
|
||||
<?php $change_password_form->printHTML(); ?>
|
||||
<h3>用户类别设置</h3>
|
||||
<?php $user_form->printHTML(); ?>
|
||||
<h3>修改用户真实姓名</h3>
|
||||
<?php $change_realname_form->printHTML(); ?>
|
||||
<h3>封禁名单</h3>
|
||||
<?php echoLongTable($banlist_cols, 'user_info', "usergroup='B'", '', $banlist_header_row, $banlist_print_row, $banlist_config) ?>
|
||||
<h3>用户名单</h3>
|
||||
<div id="user-query">
|
||||
<form class="form-horizontal uoj-form-compressed" target="_self" method="GET">
|
||||
<div class="form-group">
|
||||
<label for="username" class="col-sm-2 control-label">用户名</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="text" class="form-control" name="username" id="user-query-username" value="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="usergroup" class="col-sm-2 control-label">用户类别</label>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="user-query-usergroup" name="usergroup">
|
||||
<option value="">*: 所有用户</option>
|
||||
<option value="B">B: 封禁用户</option>
|
||||
<option value="U">U: 普通用户</option>
|
||||
<option value="S">S: 超级用户</option>
|
||||
</select>
|
||||
</div>
|
||||
</div><div class="text-center"><button type="submit" id="user-query-submit" class="mt-2 btn btn-secondary">查询</button></div>
|
||||
</form>
|
||||
</div>
|
||||
<?php echoLongTable($userlist_cols, 'user_info', $user_list_cond, 'order by username asc', $userlist_header_row, $userlist_print_row, $userlist_config) ?>
|
||||
<?php elseif ($cur_tab === 'blogs'): ?>
|
||||
<div>
|
||||
<h4>添加到比赛链接</h4>
|
||||
@ -455,49 +565,6 @@ EOD;
|
||||
}
|
||||
?>
|
||||
<?= $submissions_pag->pagination() ?>
|
||||
<?php elseif ($cur_tab === 'click-zan'): ?>
|
||||
没写好QAQ
|
||||
<?php elseif ($cur_tab === 'search'): ?>
|
||||
<h2 class="text-center">一周搜索情况</h2>
|
||||
<div id="search-distribution-chart-week" style="height: 250px;"></div>
|
||||
<script type="text/javascript">
|
||||
new Morris.Line({
|
||||
element: 'search-distribution-chart-week',
|
||||
data: <?= json_encode(DB::selectAll("select DATE_FORMAT(created_at, '%Y-%m-%d %h:00'), count(*) from search_requests where created_at > now() - interval 1 week group by DATE_FORMAT(created_at, '%Y-%m-%d %h:00')")) ?>,
|
||||
xkey: "DATE_FORMAT(created_at, '%Y-%m-%d %h:00')",
|
||||
ykeys: ["count(*)"],
|
||||
labels: ['number'],
|
||||
resize: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<h2 class="text-center">一月搜索情况</h2>
|
||||
<div id="search-distribution-chart-month" style="height: 250px;"></div>
|
||||
<script type="text/javascript">
|
||||
new Morris.Line({
|
||||
element: 'search-distribution-chart-month',
|
||||
data: <?= json_encode(DB::selectAll("select DATE_FORMAT(created_at, '%Y-%m-%d'), count(*) from search_requests where created_at > now() - interval 1 week group by DATE_FORMAT(created_at, '%Y-%m-%d')")) ?>,
|
||||
xkey: "DATE_FORMAT(created_at, '%Y-%m-%d')",
|
||||
ykeys: ["count(*)"],
|
||||
labels: ['number'],
|
||||
resize: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php echoLongTable(array('*'), 'search_requests', "1", 'order by id desc',
|
||||
'<tr><th>id</th><th>created_at</th><th>remote_addr</th><th>type</th><th>q</th><tr>',
|
||||
function($row) {
|
||||
echo '<tr>';
|
||||
echo '<td>', $row['id'], '</td>';
|
||||
echo '<td>', $row['created_at'], '</td>';
|
||||
echo '<td>', $row['remote_addr'], '</td>';
|
||||
echo '<td>', $row['type'], '</td>';
|
||||
echo '<td>', HTML::escape($row['q']), '</td>';
|
||||
echo '</tr>';
|
||||
}, array(
|
||||
'page_len' => 1000
|
||||
))
|
||||
?>
|
||||
<?php elseif ($cur_tab === 'judger'): ?>
|
||||
<div>
|
||||
<h4>添加评测机</h4>
|
||||
|
@ -166,6 +166,11 @@
|
||||
<?= HTML::js_src('/js/jquery.hotkeys.js') ?>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (isset($REQUIRE_LIB['jquery.query'])): ?>
|
||||
<!-- ckeditor -->
|
||||
<?= HTML::js_src('/js/jquery.query-object.js') ?>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (isset($REQUIRE_LIB['colorhelpers'])): ?>
|
||||
<!-- colorhelpers -->
|
||||
<?= HTML::js_src('/js/jquery.colorhelpers.min.js') ?>
|
||||
@ -246,8 +251,10 @@
|
||||
<li class="nav-item" role="presentation"><a class="nav-link" href="<?= HTML::url('/logout?_token='.crsf_token()) ?>"><?= UOJLocale::get('logout') ?></a></li>
|
||||
<?php else: ?>
|
||||
<li class="nav-item" role="presentation"><a class="nav-link" href="<?= HTML::url('/login') ?>"><?= UOJLocale::get('login') ?></a></li>
|
||||
<?php if (!DB::selectCount("SELECT COUNT(*) FROM user_info")): ?>
|
||||
<li class="nav-item" role="presentation"><a class="nav-link" href="<?= HTML::url('/register') ?>"><?= UOJLocale::get('register') ?></a></li>
|
||||
<?php endif ?>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
<h1 class="d-none d-sm-block" style="position: relative; top: 4px; width: 15em">
|
||||
<a href="<?= HTML::url('/') ?>">
|
||||
|
247
web/js/jquery.query-object.js
Normal file
247
web/js/jquery.query-object.js
Normal file
@ -0,0 +1,247 @@
|
||||
/**
|
||||
* jQuery.query - Query String Modification and Creation for jQuery
|
||||
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
|
||||
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
|
||||
* Date: 2009/8/13
|
||||
*
|
||||
* @author Blair Mitchelmore
|
||||
* @version 2.2.3
|
||||
*
|
||||
**/
|
||||
new function(settings) {
|
||||
// Various Settings
|
||||
var $separator = settings.separator || '&';
|
||||
var $spaces = settings.spaces === false ? false : true;
|
||||
var $suffix = settings.suffix === false ? '' : '[]';
|
||||
var $prefix = settings.prefix === false ? false : true;
|
||||
var $hash = $prefix ? settings.hash === true ? "#" : "?" : "";
|
||||
var $numbers = settings.numbers === false ? false : true;
|
||||
|
||||
jQuery.query = new function() {
|
||||
var is = function(o, t) {
|
||||
return o != undefined && o !== null && (!!t ? o.constructor == t : true);
|
||||
};
|
||||
var parse = function(path) {
|
||||
var m, rx = /\[([^[]*)\]/g, match = /^([^[]+)(\[.*\])?$/.exec(path), base = match[1], tokens = [];
|
||||
while (m = rx.exec(match[2])) tokens.push(m[1]);
|
||||
return [base, tokens];
|
||||
};
|
||||
var set = function(target, tokens, value) {
|
||||
var o, token = tokens.shift();
|
||||
if (typeof target != 'object') target = null;
|
||||
if (token === "") {
|
||||
if (!target) target = [];
|
||||
if (is(target, Array)) {
|
||||
target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value));
|
||||
} else if (is(target, Object)) {
|
||||
var i = 0;
|
||||
while (target[i++] != null);
|
||||
target[--i] = tokens.length == 0 ? value : set(target[i], tokens.slice(0), value);
|
||||
} else {
|
||||
target = [];
|
||||
target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value));
|
||||
}
|
||||
} else if (token && token.match(/^\s*[0-9]+\s*$/)) {
|
||||
var index = parseInt(token, 10);
|
||||
if (!target) target = [];
|
||||
target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value);
|
||||
} else if (token) {
|
||||
var index = token.replace(/^\s*|\s*$/g, "");
|
||||
if (!target) target = {};
|
||||
if (is(target, Array)) {
|
||||
var temp = {};
|
||||
for (var i = 0; i < target.length; ++i) {
|
||||
temp[i] = target[i];
|
||||
}
|
||||
target = temp;
|
||||
}
|
||||
target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
var queryObject = function(a) {
|
||||
var self = this;
|
||||
self.keys = {};
|
||||
|
||||
if (a.queryObject) {
|
||||
jQuery.each(a.get(), function(key, val) {
|
||||
self.SET(key, val);
|
||||
});
|
||||
} else {
|
||||
self.parseNew.apply(self, arguments);
|
||||
}
|
||||
return self;
|
||||
};
|
||||
|
||||
queryObject.prototype = {
|
||||
queryObject: true,
|
||||
parseNew: function(){
|
||||
var self = this;
|
||||
self.keys = {};
|
||||
jQuery.each(arguments, function() {
|
||||
var q = "" + this;
|
||||
q = q.replace(/^[?#]/,''); // remove any leading ? || #
|
||||
q = q.replace(/[;&]$/,''); // remove any trailing & || ;
|
||||
if ($spaces) q = q.replace(/[+]/g,' '); // replace +'s with spaces
|
||||
|
||||
jQuery.each(q.split(/[&;]/), function(){
|
||||
var key = decodeURIComponent(this.split('=')[0] || "");
|
||||
var val = decodeURIComponent(this.split('=')[1] || "");
|
||||
|
||||
if (!key) return;
|
||||
|
||||
if ($numbers) {
|
||||
if (/^[+-]?[0-9]+\.[0-9]*$/.test(val)) // simple float regex
|
||||
val = parseFloat(val);
|
||||
else if (/^[+-]?[1-9][0-9]*$/.test(val)) // simple int regex
|
||||
val = parseInt(val, 10);
|
||||
}
|
||||
|
||||
val = (!val && val !== 0) ? true : val;
|
||||
|
||||
self.SET(key, val);
|
||||
});
|
||||
});
|
||||
return self;
|
||||
},
|
||||
has: function(key, type) {
|
||||
var value = this.get(key);
|
||||
return is(value, type);
|
||||
},
|
||||
GET: function(key) {
|
||||
if (!is(key)) return this.keys;
|
||||
var parsed = parse(key), base = parsed[0], tokens = parsed[1];
|
||||
var target = this.keys[base];
|
||||
while (target != null && tokens.length != 0) {
|
||||
target = target[tokens.shift()];
|
||||
}
|
||||
return typeof target == 'number' ? target : target || "";
|
||||
},
|
||||
get: function(key) {
|
||||
var target = this.GET(key);
|
||||
if (is(target, Object))
|
||||
return jQuery.extend(true, {}, target);
|
||||
else if (is(target, Array))
|
||||
return target.slice(0);
|
||||
return target;
|
||||
},
|
||||
SET: function(key, val) {
|
||||
if(!key.includes("__proto__")){
|
||||
var value = !is(val) ? null : val;
|
||||
var parsed = parse(key), base = parsed[0], tokens = parsed[1];
|
||||
var target = this.keys[base];
|
||||
this.keys[base] = set(target, tokens.slice(0), value);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
set: function(key, val) {
|
||||
return this.copy().SET(key, val);
|
||||
},
|
||||
REMOVE: function(key, val) {
|
||||
if (val) {
|
||||
var target = this.GET(key);
|
||||
if (is(target, Array)) {
|
||||
for (tval in target) {
|
||||
target[tval] = target[tval].toString();
|
||||
}
|
||||
var index = $.inArray(val, target);
|
||||
if (index >= 0) {
|
||||
key = target.splice(index, 1);
|
||||
key = key[index];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (val != target) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return this.SET(key, null).COMPACT();
|
||||
},
|
||||
remove: function(key, val) {
|
||||
return this.copy().REMOVE(key, val);
|
||||
},
|
||||
EMPTY: function() {
|
||||
var self = this;
|
||||
jQuery.each(self.keys, function(key, value) {
|
||||
delete self.keys[key];
|
||||
});
|
||||
return self;
|
||||
},
|
||||
load: function(url) {
|
||||
var hash = url.replace(/^.*?[#](.+?)(?:\?.+)?$/, "$1");
|
||||
var search = url.replace(/^.*?[?](.+?)(?:#.+)?$/, "$1");
|
||||
return new queryObject(url.length == search.length ? '' : search, url.length == hash.length ? '' : hash);
|
||||
},
|
||||
empty: function() {
|
||||
return this.copy().EMPTY();
|
||||
},
|
||||
copy: function() {
|
||||
return new queryObject(this);
|
||||
},
|
||||
COMPACT: function() {
|
||||
function build(orig) {
|
||||
var obj = typeof orig == "object" ? is(orig, Array) ? [] : {} : orig;
|
||||
if (typeof orig == 'object') {
|
||||
function add(o, key, value) {
|
||||
if (is(o, Array))
|
||||
o.push(value);
|
||||
else
|
||||
o[key] = value;
|
||||
}
|
||||
jQuery.each(orig, function(key, value) {
|
||||
if (!is(value)) return true;
|
||||
add(obj, key, build(value));
|
||||
});
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
this.keys = build(this.keys);
|
||||
return this;
|
||||
},
|
||||
compact: function() {
|
||||
return this.copy().COMPACT();
|
||||
},
|
||||
toString: function() {
|
||||
var i = 0, queryString = [], chunks = [], self = this;
|
||||
var encode = function(str) {
|
||||
str = str + "";
|
||||
str = encodeURIComponent(str);
|
||||
if ($spaces) str = str.replace(/%20/g, "+");
|
||||
return str;
|
||||
};
|
||||
var addFields = function(arr, key, value) {
|
||||
if (!is(value) || value === false) return;
|
||||
var o = [encode(key)];
|
||||
if (value !== true) {
|
||||
o.push("=");
|
||||
o.push(encode(value));
|
||||
}
|
||||
arr.push(o.join(""));
|
||||
};
|
||||
var build = function(obj, base) {
|
||||
var newKey = function(key) {
|
||||
return !base || base == "" ? [key].join("") : [base, "[", key, "]"].join("");
|
||||
};
|
||||
jQuery.each(obj, function(key, value) {
|
||||
if (typeof value == 'object')
|
||||
build(value, newKey(key));
|
||||
else
|
||||
addFields(chunks, newKey(key), value);
|
||||
});
|
||||
};
|
||||
|
||||
build(this.keys);
|
||||
|
||||
if (chunks.length > 0) queryString.push($hash);
|
||||
queryString.push(chunks.join($separator));
|
||||
|
||||
return queryString.join("");
|
||||
}
|
||||
};
|
||||
|
||||
return new queryObject(location.search, location.hash);
|
||||
};
|
||||
}(jQuery.query || {}); // Pass in jQuery.query as settings object
|
Loading…
Reference in New Issue
Block a user