core: add FileTooLargeError

This commit is contained in:
undefined committed 2021-03-08 12:47:37 +08:00
1 parent 4a294f59a8
commit 1b53bfa2b4
8 files changed
+42 -27

No files matched your search

+24 -14
View File
@@ -1,6 +1,7 @@
/* eslint-disable max-len */
/* eslint-disable func-names */
import { isClass } from './utils';
import { PERMS } from './model/builtin';
interface IHydroError {
new(...args: any[]): HydroError
@@ -10,8 +11,9 @@ function isHydroError(item: any): item is IHydroError {
return isClass(item);
}
const Err = (name: string, ...info: Array<IHydroError | (() => string) | string | number>) => {
const Err = (name: string, ...info: Array<IHydroError | (() => string) | ((_super: Function, ...args: any) => HydroError) | string | number>) => {
let Class: IHydroError;
let constr: (_super: Function, ...args: any[]) => HydroError;
let msg: () => string;
let code: number;
for (const item of info) {
@@ -21,20 +23,29 @@ const Err = (name: string, ...info: Array<IHydroError | (() => string) | string
msg = function () { return item; };
} else if (isHydroError(item)) {
Class = item;
} else if (typeof item === 'function') {
} else if (typeof item === 'function' && item.length === 0) {
// @ts-ignore
msg = item;
} else if (typeof item === 'function') {
// @ts-ignore
constr = item;
}
}
const HydroError = class extends Class { };
HydroError.prototype.name = name;
if (msg) HydroError.prototype.msg = msg;
if (code) HydroError.prototype.code = code;
if (constr) {
const original = HydroError.prototype.constructor;
HydroError.prototype.constructor = function (...args: any[]) {
constr.call(this, original.bind(this, ...args));
};
}
return HydroError;
};
export class HydroError extends Error {
params: any[];
code: number;
constructor(...params: any[]) {
@@ -65,7 +76,12 @@ export const InvalidTokenError = Err('InvalidTokenError', ForbiddenError);
export const BlacklistedError = Err('BlacklistedError', ForbiddenError, 'Address or user {0} is blacklisted.');
export const VerifyPasswordError = Err('VerifyPasswordError', ForbiddenError, "Passwords don't match.");
export const OpcountExceededError = Err('OpcountExceededError', ForbiddenError, 'Too frequent operations of {0} (limit: {2} operations in {1} seconds).');
export const PermissionError = Err('PermissionError', ForbiddenError, "You don't have the required permission ({0}) in this domain.");
export const PermissionError = Err('PermissionError', ForbiddenError, function () {
if (typeof this.params[0] === 'bigint') {
this.params[0] = PERMS.find(({ key }) => key === this.params[0])?.desc || this.params[0];
}
return "You don't have the required permission ({0}) in this domain.";
});
export const PrivilegeError = Err('PrivilegeError', ForbiddenError, function () {
if (this.params.includes(global.Hydro.model.builtin.PRIV.PRIV_USER_PROFILE)) {
return "You're not logged in.";
@@ -89,6 +105,7 @@ export const DomainAlreadyExistsError = Err('DomainAlreadyExistsError', Forbidde
export const DomainJoinForbiddenError = Err('DomainJoinForbiddenError', ForbiddenError, 'You are not allowed to join the domain. The link is either invalid or expired.');
export const DomainJoinAlreadyMemberError = Err('DomainJoinAlreadyMemberError', ForbiddenError, 'Failed to join the domain. You are already a member.');
export const InvalidJoinInvitationCodeError = Err('InvalidJoinInvitationCodeError', ForbiddenError, 'The invitation code you provided is invalid.');
export const CurrentPasswordError = Err('CurrentPasswordError', ForbiddenError, "Current password doesn't match.");
export const UserNotFoundError = Err('UserNotFoundError', NotFoundError, 'User {0} not found.');
export const NoProblemError = Err('NoProblemError', NotFoundError, 'No problem.');
@@ -105,6 +122,7 @@ export const DiscussionNotFoundError = Err('DiscussionNotFoundError', DocumentNo
export const DiscussionNodeNotFoundError = Err('DiscussionNodeNotFoundError', DocumentNotFoundError, 'Discussion node {1} not found.');
export const InvalidOperationError = Err('InvalidOperationError', MethodNotAllowedError);
export const FileTooLargeError = Err('FileTooLargeError', ValidationError, 'The uploaded file is too long.');
global.Hydro.error = {
HydroError,
@@ -152,14 +170,11 @@ global.Hydro.error = {
DiscussionNotFoundError,
RoleAlreadyExistError,
MessageNotFoundError,
FileTooLargeError,
CurrentPasswordError,
};
/*
class FileTooLongError(ValidationError):
@property
def message(self):
return 'The uploaded file is too long.'
class FileTypeNotAllowedError(ValidationError):
@property
def message(self):
@@ -168,11 +183,6 @@ class FileTypeNotAllowedError(ValidationError):
class InvalidTokenDigestError(ForbiddenError):
pass
class CurrentPasswordError(ForbiddenError):
@property
def message(self):
return "Current password doesn't match."
class DiscussionCategoryAlreadyExistError(ForbiddenError):
@property
def message(self):
+1 -2
View File
@@ -153,13 +153,12 @@ class ContestScoreboardRawHandler extends ContestHandler {
class ContestScoreboardDownloadHandler extends ContestHandler {
@param('tid', Types.ObjectID)
@param('ext', Types.String)
@param('ext', Types.Range(['csv', 'html']))
async get(domainId: string, tid: ObjectID, ext: string) {
const getContent = {
csv: async (rows) => `\uFEFF${rows.map((c) => (c.map((i) => i.value).join(','))).join('\n')}`,
html: (rows) => this.renderHTML('contest_scoreboard_download_html.html', { rows }),
};
if (!getContent[ext]) throw new ValidationError('ext');
const [tdoc, rows] = await this.getScoreboard(domainId, tid, true);
this.binary(await getContent[ext](rows), `${tdoc.title}.${ext}`);
}
+2 -5
View File
@@ -4,6 +4,8 @@ import {
RoleAlreadyExistError, ValidationError, DomainJoinForbiddenError,
DomainJoinAlreadyMemberError, InvalidJoinInvitationCodeError,
} from '../error';
import { log2 } from '../utils';
import type { DomainDoc } from '../interface';
import * as user from '../model/user';
import * as domain from '../model/domain';
import * as system from '../model/system';
@@ -14,7 +16,6 @@ import paginate from '../lib/paginate';
import {
Route, Handler, Types, param,
} from '../service/server';
import { DomainDoc } from '../interface';
class DomainRankHandler extends Handler {
@param('page', Types.PositiveInt, true)
@@ -124,10 +125,6 @@ class DomainUserHandler extends ManageHandler {
class DomainPermissionHandler extends ManageHandler {
async get({ domainId }) {
const roles = await domain.getRoles(domainId);
const log2 = (val: bigint) => {
// @ts-ignore
for (let i = 0n; ; i++) if (!(val >> i)) return +i.toString() - 1;
};
const path = [
['Hydro', 'homepage'],
['domain', null],
+1 -1
View File
@@ -521,7 +521,7 @@ interface GeoIP {
lookup: (ip: string, locale?: string) => any,
}
export interface Lib {
export interface Lib extends Record<string, any> {
download: typeof import('./lib/download'),
buildContent: typeof import('./lib/content').buildContent,
'hash.hydro': typeof import('./lib/hash.hydro'),
+9
View File
@@ -257,3 +257,12 @@ export namespace Time {
return constructedObjectId;
}
}
export const log2 = (val: bigint | number) => {
if (typeof val === 'bigint') {
// @ts-ignore
for (let i = 0n; ; i++) if (!(val >> i)) return +i.toString() - 1;
} else {
for (let i = 0; ; i++) if (!(val >> i)) return i - 1;
}
};