feat: validator decorator

This commit is contained in:
undefined committed 2020-07-08 20:37:06 +08:00
1 parent ba03d7a7bf
commit 4e85b696c0
23 files changed
+313 -180

No files matched your search

-66
View File
@@ -1,66 +0,0 @@
const description = 'Add blacklist by ip, uid';
// This code format is just for fun. DO NOT DO THIS IN YOUR CODE !
/* eslint-disable */
const { ObjectID } = require('mongodb');
const document = require('../model/document');
const discussion = require('../model/discussion');
const user = require('../model/user');
const blacklist = require('../model/blacklist');
const db = require('../service/db');
async function _address(ip, bset, uset, dset, dryrun, report) {
if (bset.has(ip))
return
bset.add(ip)
report({ message: `ip ${ip}` })
const users = await db.collection('user').find({ loginip: ip }).toArray()
const tasks = []
for (const udoc of users) {
tasks.push(_user(udoc._id, bset, uset, dset, dryrun, report)) }
await Promise.all(tasks)
if (!dryrun)
await blacklist.add(ip) }
async function _discussion(domainId, did, bset, uset, dset, dryrun, report) {
if (dset.has(did))
return
dset.add(did)
const ddoc = await discussion.get(domainId, did)
if (!ddoc)
return
report({ message: `discussion ${ddoc['title']}` })
await _user(ddoc['owner'], bset, uset, dset, dryrun, report)
if (ddoc.ip)
await _address(ddoc['ip'], bset, uset, dset, dryrun, report)
if (!dryrun)
await discussion.delete(domainId, ddoc['docId']) }
async function _user(uid, bset, uset, dset, dryrun, report) {
if (uset.has(uid))
return
uset.add(uid)
const udoc = await user.getById(uid)
if (!udoc)
return
report({ message: `user ${udoc['_id']} ${udoc['uname']}` })
await _address(udoc['loginip'], bset, uset, dset, dryrun, report)
const ddocs = await db.collection('document')
.find({ docType: document.TYPE_DISCUSSION }).sort({ domainId: 1, docId: 1 }).toArray()
const tasks = []
for (const ddoc of ddocs)
tasks.push(_discussion(ddoc.domainId, ddoc.docId, bset, uset, dset, dryrun, report))
await Promise.all(tasks)
if (!dryrun)
await user.ban(uid) }
async function run({address = null, discuss = null, user = null, dryrun = true}, report) {
if (address)
await _address(address, new Set(), new Set(), new Set(), dryrun, report)
if (discuss)
await _discussion(discuss.domainId, new ObjectID(discuss.did),
new Set(), new Set(), new Set(), dryrun, report)
if (user)
await _user(user, new Set(), new Set(), new Set(), dryrun, report) }
global.Hydro.script.blacklist = module.exports = { run, description };
+86
View File
@@ -0,0 +1,86 @@
/* eslint-disable no-use-before-define */
import { ObjectID } from 'mongodb';
import * as document from '../model/document';
import * as discussion from '../model/discussion';
import * as user from '../model/user';
import * as blacklist from '../model/blacklist';
import * as db from '../service/db';
export const description = 'Add blacklist by ip, uid';
async function _address(
ip: string,
bset: Set<string>, uset: Set<number>, dset: Set<ObjectID>,
dryrun: boolean, report: Function,
) {
if (bset.has(ip)) return;
bset.add(ip);
report({ message: `ip ${ip}` });
const users = await db.collection('user').find({ loginip: ip }).toArray();
const tasks = [];
for (const udoc of users) {
tasks.push(_user(udoc._id, bset, uset, dset, dryrun, report));
}
await Promise.all(tasks);
if (!dryrun) await blacklist.add(ip);
}
async function _discussion(
domainId: string, did: ObjectID,
bset: Set<string>, uset: Set<number>, dset: Set<ObjectID>,
dryrun: boolean, report: Function,
) {
if (dset.has(did)) return;
dset.add(did);
const ddoc = await discussion.get(domainId, did);
if (!ddoc) return;
report({ message: `discussion ${ddoc.title}` });
await _user(ddoc.owner, bset, uset, dset, dryrun, report);
if (ddoc.ip) await _address(ddoc.ip, bset, uset, dset, dryrun, report);
if (!dryrun) await discussion.del(domainId, ddoc.docId);
}
async function _user(
uid: number,
bset: Set<string>, uset: Set<number>, dset: Set<ObjectID>,
dryrun: boolean, report: Function,
) {
if (uset.has(uid)) return;
uset.add(uid);
const udoc = await user.getById('system', uid);
if (!udoc) return;
report({ message: `user ${udoc._id} ${udoc.uname}` });
await _address(udoc.loginip(), bset, uset, dset, dryrun, report);
const ddocs = await db.collection('document').find({ docType: document.TYPE_DISCUSSION })
.sort({ domainId: 1, docId: 1 }).toArray();
const tasks = [];
for (const ddoc of ddocs) {
tasks.push(_discussion(ddoc.domainId, ddoc.docId, bset, uset, dset, dryrun, report));
}
await Promise.all(tasks);
if (!dryrun) await user.ban(uid);
}
export async function run({
address = null, discuss = null, user = null, dryrun = true,
}, report) {
if (address) await _address(address, new Set(), new Set(), new Set(), dryrun, report);
if (discuss) {
await _discussion(
discuss.domainId, new ObjectID(discuss.did),
new Set(), new Set(), new Set(), dryrun, report,
);
}
if (user) await _user(user, new Set(), new Set(), new Set(), dryrun, report);
}
export const validate = {
$or: {
address: 'string',
discuss: ObjectID,
user: 'number',
},
dryrun: 'boolean',
};
global.Hydro.script.blacklist = { run, description, validate };
@@ -1,12 +1,12 @@
const description = 'Delete a user';
/* eslint-disable no-await-in-loop */
const user = require('../model/user');
const document = require('../model/document');
const setting = require('../model/setting');
const db = require('../service/db');
const paginate = require('../lib/paginate');
const { STATUS, PRIV } = require('../model/builtin');
import * as user from '../model/user';
import * as document from '../model/document';
import * as setting from '../model/setting';
import * as db from '../service/db';
import paginate from '../lib/paginate';
import { STATUS, PRIV } from '../model/builtin';
export const description = 'Delete a user';
const collDocument = db.collection('document');
const collStatus = db.collection('document.status');
@@ -19,7 +19,7 @@ for (const s of setting.PREFERENCE_SETTINGS) {
$unset[s.key] = '';
}
async function deleteRecord(uid) {
async function deleteRecord(uid: number) {
const [, pcount] = await paginate(
collRecord.find(),
1,
@@ -45,7 +45,7 @@ async function deleteRecord(uid) {
await collRecord.deleteMany({ uid });
}
async function deleteDiscussion(uid) {
async function deleteDiscussion(uid: number) {
const [, pcount] = await paginate(
collDocument.find({ docType: document.TYPE_DISCUSSION, owner: uid }),
1,
@@ -70,7 +70,7 @@ async function deleteDiscussion(uid) {
// TODO delete replies
}
async function run({
export async function run({
uid,
}) {
await deleteRecord(uid);
@@ -87,4 +87,8 @@ async function run({
return uid;
}
global.Hydro.script.deleteUser = module.exports = { run, description };
export const validate = {
uid: 'number',
};
global.Hydro.script.deleteUser = { run, description, validate };
@@ -1,12 +1,12 @@
const description = 'Install';
import { PRIV } from '../model/builtin';
import * as system from '../model/system';
import * as user from '../model/user';
import * as domain from '../model/domain';
import pwhash from '../lib/hash.hydro';
const { PRIV_ALL } = require('../model/builtin').PRIV;
const system = require('../model/system');
const user = require('../model/user');
const domain = require('../model/domain');
const pwhash = require('../lib/hash.hydro');
export const description = 'Install';
async function run({ username, password } = {}) {
export async function run({ username = '', password = '' } = {}) {
const def = {
PROBLEM_PER_PAGE: 100,
RECORD_PER_PAGE: 100,
@@ -52,7 +52,7 @@ async function run({ username, password } = {}) {
uname: username,
password,
regip: '127.0.0.1',
priv: PRIV_ALL,
priv: PRIV.PRIV_ALL,
});
} else {
const salt = String.random();
@@ -60,11 +60,18 @@ async function run({ username, password } = {}) {
uname: username,
unameLower: username.trim().toLowerCase(),
salt,
hash: pwhash.default(password, salt),
hash: pwhash(password, salt),
hashType: 'hydro',
});
}
}
}
global.Hydro.script.install = module.exports = { run, description };
export const validate = {
$or: [
{ username: 'string', password: 'string' },
{ username: 'undefined', password: 'undefined' },
],
};
global.Hydro.script.install = { run, description, validate };
@@ -1,10 +1,10 @@
const description = 'Recalcuates nSubmit and nAccept in problem status.';
import * as db from '../service/db';
import { STATUS } from '../model/builtin';
import * as document from '../model/document';
const db = require('../service/db');
const { STATUS_ACCEPTED } = require('../model/builtin').STATUS;
const document = require('../model/document');
export const description = 'Recalcuates nSubmit and nAccept in problem status.';
async function run() {
export async function run() {
const pipeline = [
{
$match: { hidden: false, type: { $ne: 'run' } },
@@ -15,7 +15,7 @@ async function run() {
nSubmit: { $sum: 1 },
nAccept: {
$sum: {
$cond: [{ $eq: ['$status', STATUS_ACCEPTED] }, 1, 0],
$cond: [{ $eq: ['$status', STATUS.STATUS_ACCEPTED] }, 1, 0],
},
},
},
@@ -29,8 +29,8 @@ async function run() {
},
];
const bulk = db.collection('document').initializeUnorderedBulkOp();
db.collection('record').aggregate(pipeline).forEach(
(adoc) => bulk.find({
db.collection('record').aggregate(pipeline).each(
(err, adoc: any) => bulk.find({
domainId: adoc._id.domainId,
docType: document.TYPE_PROBLEM,
docId: adoc._id.pid,
@@ -44,4 +44,6 @@ async function run() {
await bulk.execute();
}
global.Hydro.script.problemStat = module.exports = { run, description };
export const validate = {};
global.Hydro.script.problemStat = { run, description, validate };
@@ -1,11 +1,11 @@
const description = 'Calculate the rating of a contest';
import { ObjectID } from 'mongodb';
import * as contest from '../model/contest';
import * as user from '../model/user';
import rating from '../lib/rating';
const { ObjectID } = require('mongodb');
const contest = require('../model/contest');
const user = require('../model/user');
const rating = require('../lib/rating');
export const description = 'Calculate the rating of a contest';
async function run({ domainId, contestId }) {
export async function run({ domainId, contestId }) {
contestId = new ObjectID(contestId);
const tdoc = await contest.get(domainId, contestId);
const tsdocs = await contest.getMultiStatus(domainId, { docId: contestId })
@@ -20,4 +20,9 @@ async function run({ domainId, contestId }) {
return rated;
}
global.Hydro.script.rating = module.exports = { run, description };
export const validate = {
domainId: { $type: 'string' },
contestId: { $type: ObjectID },
};
global.Hydro.script.rating = { run, description, validate };
@@ -1,13 +1,13 @@
const description = 'Calculate rating of a domain, or all domains';
/* eslint-disable no-await-in-loop */
const domain = require('../model/domain');
const contest = require('../model/contest');
const user = require('../model/user');
const rating = require('../lib/rating');
const { STATUS } = require('../model/builtin');
import * as domain from '../model/domain';
import * as contest from '../model/contest';
import * as user from '../model/user';
import rating from '../lib/rating';
import { STATUS } from '../model/builtin';
async function run({ domainId, isSub = false }, report) {
export const description = 'Calculate rating of a domain, or all domains';
export async function run({ domainId, isSub = false }, report) {
if (!domainId) {
const domains = await domain.getMulti().toArray();
await report({ message: `Found ${domains.length} domains` });
@@ -66,4 +66,11 @@ async function run({ domainId, isSub = false }, report) {
return true;
}
global.Hydro.script.recalcRating = module.exports = { run, description };
export const validate = {
$or: [
{ domainId: 'string' },
{ domainId: 'undefined' },
],
};
global.Hydro.script.recalcRating = { run, description, validate };
-18
View File
@@ -1,18 +0,0 @@
const description = 'Create a new user';
const user = require('../model/user');
const system = require('../model/system');
async function run({
uname, password, mail, uid,
}) {
if (!uid) uid = await system.inc('user');
else uid = parseInt(uid, 10);
if (Number.isNaN(uid)) throw new Error('uid');
await user.create({
uid, uname, password, mail, regip: '127.0.0.1',
});
return uid;
}
global.Hydro.script.register = module.exports = { run, description };
+24
View File
@@ -0,0 +1,24 @@
import * as user from '../model/user';
import * as system from '../model/system';
export const description = 'Create a new user';
export async function run({
uname, password, mail, uid,
}) {
if (!uid) uid = await system.inc('user');
else uid = parseInt(uid, 10);
if (Number.isNaN(uid)) throw new Error('uid');
await user.create({
uid, uname, password, mail, regip: '127.0.0.1',
});
return uid;
}
export const validate = {
uname: { $type: 'string' },
password: { $type: 'string' },
mail: { $type: 'string' },
};
global.Hydro.script.register = { run, description, validate };
-15
View File
@@ -1,15 +0,0 @@
const description = 'Set a user as superadmin.';
const user = require('../model/user');
const { PRIV_ALL } = require('../model/builtin').PRIV;
async function run({
uid,
}) {
uid = parseInt(uid, 10);
if (Number.isNaN(uid)) throw new Error('uid');
await user.setPriv(uid, PRIV_ALL);
return uid;
}
global.Hydro.script.setSuperadmin = module.exports = { run, description };
+17
View File
@@ -0,0 +1,17 @@
import * as user from '../model/user';
import { PRIV } from '../model/builtin';
export const description = 'Set a user as superadmin.';
export async function run({ uid }) {
uid = parseInt(uid, 10);
if (Number.isNaN(uid)) throw new Error('uid');
await user.setPriv(uid, PRIV.PRIV_ALL);
return uid;
}
export const validate = {
uid: { $type: 'number' },
};
global.Hydro.script.setSuperadmin = { run, description, validate };