Browse Source

Add contest admin support.

pull/6/head
t123yh 7 years ago
parent
commit
552d684c04
  1. 26
      models/contest.js
  2. 31
      modules/api_v2.js
  3. 13
      modules/contest.js
  4. 2
      views/contest.ejs
  5. 23
      views/contest_edit.ejs

26
models/contest.js

@ -46,6 +46,7 @@ let model = db.define('contest', {
information: { type: Sequelize.TEXT },
problems: { type: Sequelize.TEXT },
admins: { type: Sequelize.TEXT },
ranklist_id: {
type: Sequelize.INTEGER,
@ -57,17 +58,17 @@ let model = db.define('contest', {
is_public: { type: Sequelize.BOOLEAN }
}, {
timestamps: false,
tableName: 'contest',
indexes: [
{
fields: ['holder_id'],
},
{
fields: ['ranklist_id'],
}
]
});
timestamps: false,
tableName: 'contest',
indexes: [
{
fields: ['holder_id'],
},
{
fields: ['ranklist_id'],
}
]
});
let Model = require('./common');
class Contest extends Model {
@ -76,6 +77,7 @@ class Contest extends Model {
title: '',
subtitle: '',
problems: '',
admins: '',
information: '',
type: 'noi',
start_time: 0,
@ -92,7 +94,7 @@ class Contest extends Model {
}
async isSupervisior(user) {
return user && (user.is_admin || this.holder_id === user.id);
return user && (user.is_admin || this.holder_id === user.id || this.admins.split('|').includes(user.id.toString()));
}
allowedSeeingOthers() {

31
modules/api_v2.js

@ -19,6 +19,37 @@
'use strict';
app.get('/api/v2/search/users/:keyword*?', async (req, res) => {
try {
let User = syzoj.model('user');
let keyword = req.params.keyword || '';
let conditions = [];
const uid = parseInt(keyword);
if (uid != null && !isNaN(uid)) {
conditions.push({ id: uid });
}
if (keyword != null && String(keyword).length >= 2) {
conditions.push({ username: { like: `%${req.params.keyword}%` } });
}
if (conditions.length === 0) {
res.send({ success: true, results: [] });
} else {
let users = await User.query(null, {
$or: conditions
}, [['username', 'asc']]);
let result = [];
result = users.map(x => ({ name: `${x.username}`, value: x.id, url: syzoj.utils.makeUrl(['user', x.id]) }));
res.send({ success: true, results: result });
}
} catch (e) {
syzoj.log(e);
res.send({ success: false });
}
});
app.get('/api/v2/search/problems/:keyword*?', async (req, res) => {
try {
let Problem = syzoj.model('problem');

13
modules/contest.js

@ -63,12 +63,14 @@ app.get('/contest/:id/edit', async (req, res) => {
contest.id = 0;
}
let problems = [];
let problems = [], admins = [];
if (contest.problems) problems = await contest.problems.split('|').mapAsync(async id => await Problem.fromID(id));
if (contest.admins) admins = await contest.admins.split('|').mapAsync(async id => await User.fromID(id));
res.render('contest_edit', {
contest: contest,
problems: problems
problems: problems,
admins: admins
});
} catch (e) {
syzoj.log(e);
@ -103,6 +105,7 @@ app.post('/contest/:id/edit', async (req, res) => {
contest.subtitle = req.body.subtitle;
if (!Array.isArray(req.body.problems)) req.body.problems = [req.body.problems];
contest.problems = req.body.problems.join('|');
contest.admins = req.body.admins.join('|');
contest.information = req.body.information;
contest.start_time = syzoj.utils.parseDate(req.body.start_time);
contest.end_time = syzoj.utils.parseDate(req.body.end_time);
@ -223,9 +226,13 @@ app.get('/contest/:id/ranklist', async (req, res) => {
try {
let contest_id = parseInt(req.params.id);
let contest = await Contest.fromID(contest_id);
const curUser = res.locals.user;
if (!contest) throw new ErrorMessage('无此比赛。');
if (!await contest.isAllowedSeeResultBy(res.locals.user)) throw new ErrorMessage('您没有权限进行此操作。');
if ([contest.allowedSeeingResult() && contest.allowedSeeingOthers(),
contest.isEnded(),
contest.isSupervisior(curUser)].every(x => !x))
throw new ErrorMessage('您没有权限进行此操作。');
await contest.loadRelationships();

2
views/contest.ejs

@ -71,7 +71,7 @@
<tr>
<td class="center aligned" style="white-space: nowrap; ">
<% if (problem.judge_id) { %>
<a href="<%= syzoj.utils.makeUrl(['submission', problem.judge_id]) %>">
<a href="<%= syzoj.utils.makeUrl(['contest', 'submission', problem.judge_id]) %>">
<% if (typeof problem.status === 'string') { %>
<span class="status <%= problem.status.toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(problem.status)] || 'remove' %> icon"></i>

23
views/contest_edit.ejs

@ -18,6 +18,14 @@
<% } %>
</select>
</div>
<div class="field">
<label>比赛管理员</label>
<select class="ui fluid search dropdown" multiple="" id="search_admins" name="admins">
<% for (let admin of admins) { %>
<option value="<%= admin.id %>" selected><%= admin.username %></option>
<% } %>
</select>
</div>
<div class="inline fields">
<label>赛制</label>
<div class="field">
@ -62,6 +70,21 @@
</form>
<script>
$(function () {
$('#search_admins')
.dropdown({
debug: true,
apiSettings: {
url: '/api/v2/search/users/{query}',
onResponse: function (response) {
var a = $('#search_admins').val().map(function (x) { return parseInt(x) });
if (response.results) {
response.results = response.results.filter(x => !a.includes(parseInt(x.value)));
}
return response;
},
cache: false
}
});
$('#search_problems')
.dropdown({
debug: true,

Loading…
Cancel
Save