mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
core: user-import: enhanced
This commit is contained in:
1 parent
27528f9a4d
commit
89fb04bfb3
4 files changed
+34
-18
No files matched your search
@@ -57,8 +57,10 @@ pager_previous: ‹ Previous
|
||||
perm_contest: Contests
|
||||
perm_discussion: Discussions
|
||||
perm_general: General
|
||||
perm_homework: Homework
|
||||
perm_problem_solution: Problem Solutions
|
||||
perm_problem: Problems
|
||||
perm_ranking: Ranking
|
||||
perm_record: Records
|
||||
perm_training: Trainings
|
||||
problem_create: Problem Create
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hydrooj",
|
||||
"version": "4.4.1",
|
||||
"version": "4.4.2",
|
||||
"bin": "bin/hydrooj.js",
|
||||
"main": "src/plugin-api",
|
||||
"module": "src/plugin-api",
|
||||
|
||||
@@ -232,6 +232,7 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler {
|
||||
@param('tid', Types.ObjectID)
|
||||
@param('ext', Types.Range(['csv', 'html', 'ghost']), true)
|
||||
async get(domainId: string, tid: ObjectID, ext = '') {
|
||||
if (!contest.canShowScoreboard.call(this, this.tdoc, true)) throw new ContestScoreboardHiddenError(tid);
|
||||
if (ext) {
|
||||
await this.exportScoreboard(domainId, tid, ext);
|
||||
return;
|
||||
@@ -248,8 +249,7 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler {
|
||||
}
|
||||
|
||||
async exportGhost(domainId: string, tid: ObjectID) {
|
||||
const tdoc = await contest.get(domainId, tid);
|
||||
if (!contest.canShowScoreboard.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid);
|
||||
const tdoc = this.tdoc;
|
||||
const [pdict, teams] = await Promise.all([
|
||||
problem.getList(domainId, tdoc.pids, true, false, undefined, true),
|
||||
contest.getMultiStatus(domainId, { docId: tid }).toArray(),
|
||||
@@ -538,8 +538,8 @@ export async function apply(ctx) {
|
||||
ctx.Route('contest_detail', '/contest/:tid', ContestDetailHandler, PERM.PERM_VIEW_CONTEST);
|
||||
ctx.Route('contest_broadcast', '/contest/:tid/broadcast', ContestBroadcastHandler);
|
||||
ctx.Route('contest_edit', '/contest/:tid/edit', ContestEditHandler, PERM.PERM_VIEW_CONTEST);
|
||||
ctx.Route('contest_scoreboard', '/contest/:tid/scoreboard', ContestScoreboardHandler, PERM.PERM_VIEW_CONTEST);
|
||||
ctx.Route('contest_scoreboard_download', '/contest/:tid/export/:ext', ContestScoreboardHandler, PERM.PERM_VIEW_CONTEST);
|
||||
ctx.Route('contest_scoreboard', '/contest/:tid/scoreboard', ContestScoreboardHandler, PERM.PERM_VIEW_CONTEST_SCOREBOARD);
|
||||
ctx.Route('contest_scoreboard_download', '/contest/:tid/export/:ext', ContestScoreboardHandler, PERM.PERM_VIEW_CONTEST_SCOREBOARD);
|
||||
ctx.Route('contest_code', '/contest/:tid/code', ContestCodeHandler, PERM.PERM_VIEW_CONTEST);
|
||||
ctx.Route('contest_files', '/contest/:tid/file', ContestFilesHandler, PERM.PERM_VIEW_CONTEST);
|
||||
ctx.Route('contest_file_download', '/contest/:tid/file/:filename', ContestFileDownloadHandler, PERM.PERM_VIEW_CONTEST);
|
||||
|
||||
@@ -209,6 +209,7 @@ class SystemConfigHandler extends SystemHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-disable no-await-in-loop */
|
||||
class SystemUserImportHandler extends SystemHandler {
|
||||
async get() {
|
||||
this.response.body.users = [];
|
||||
@@ -219,49 +220,62 @@ class SystemUserImportHandler extends SystemHandler {
|
||||
@param('draft', Types.Boolean)
|
||||
async post(domainId: string, _users: string, draft: boolean) {
|
||||
const users = _users.split('\n');
|
||||
const udocs = [];
|
||||
const udocs: { email: string, username: string, password: string, displayName?: string, payload?: any }[] = [];
|
||||
const messages = [];
|
||||
const mapping = {};
|
||||
const groups: Record<string, string[]> = {};
|
||||
for (const i in users) {
|
||||
const u = users[i];
|
||||
if (!u.trim()) continue;
|
||||
let [email, username, password, displayName] = u.split(',').map((t) => t.trim());
|
||||
if (!email || !username || !password) [email, username, password, displayName] = u.split('\t').map((t) => t.trim());
|
||||
let [email, username, password, displayName, extra] = u.split(',').map((t) => t.trim());
|
||||
if (!email || !username || !password) [email, username, password, displayName, extra] = u.split('\t').map((t) => t.trim());
|
||||
if (email && username && password) {
|
||||
if (!isEmail(email)) messages.push(`Line ${+i + 1}: Invalid email.`);
|
||||
else if (!Types.Username[1](username)) messages.push(`Line ${+i + 1}: Invalid username`);
|
||||
else if (!isPassword(password)) messages.push(`Line ${+i + 1}: Invalid password`);
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
else if (await user.getByEmail('system', email)) {
|
||||
messages.push(`Line ${+i + 1}: Email ${email} already exists.`);
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
} else if (await user.getByUname('system', username)) {
|
||||
messages.push(`Line ${+i + 1}: Username ${username} already exists.`);
|
||||
} else {
|
||||
const payload: any = {};
|
||||
try {
|
||||
const data = JSON.parse(extra);
|
||||
if (data.group) {
|
||||
if (!groups[data.group]) groups[data.group] = [];
|
||||
groups[data.group].push(email);
|
||||
}
|
||||
if (data.school) payload.school = data.school;
|
||||
} catch (e) { }
|
||||
udocs.push({
|
||||
email, username, password, displayName,
|
||||
email, username, password, displayName, payload,
|
||||
});
|
||||
}
|
||||
} else messages.push(`Line ${+i + 1}: Input invalid.`);
|
||||
}
|
||||
messages.push(`${udocs.length} users found.`);
|
||||
if (!draft) {
|
||||
for (const {
|
||||
email, username, password, displayName,
|
||||
} of udocs) {
|
||||
for (const udoc of udocs) {
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const uid = await user.create(email, username, password);
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
if (displayName) await domain.setUserInDomain(domainId, uid, { displayName });
|
||||
const uid = await user.create(udoc.email, udoc.username, udoc.password);
|
||||
mapping[udoc.email] = uid;
|
||||
if (udoc.displayName) await domain.setUserInDomain(domainId, uid, { displayName: udoc.displayName });
|
||||
if (udoc.payload?.school) await user.setById(uid, { school: udoc.payload.school });
|
||||
if (udoc.payload?.studentId) await user.setById(uid, { studentId: udoc.payload.studentId });
|
||||
} catch (e) {
|
||||
messages.push(e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const name in groups) {
|
||||
const uids = groups[name].map((i) => mapping[i]).filter((i) => i);
|
||||
if (uids.length) await user.updateGroup(domainId, name, uids);
|
||||
}
|
||||
this.response.body.users = udocs;
|
||||
this.response.body.messages = messages;
|
||||
}
|
||||
}
|
||||
/* eslint-enable no-await-in-loop */
|
||||
|
||||
const Priv = Object.fromEntries(Object.entries(PRIV).filter(
|
||||
(i) => (!i[0].endsWith('SELF') && !['PRIV_DEFAULT', 'PRIV_NEVER', 'PRIV_NONE', 'PRIV_ALL'].includes(i[0])),
|
||||
|
||||
Reference in new issue
Block a user