From d4e849a13304079c29b41780627f797a58b53846 Mon Sep 17 00:00:00 2001 From: undefined Date: Tue, 14 Jul 2020 17:17:49 +0800 Subject: [PATCH] update interface.ts --- TODO | 2 +- hydro/interface.ts | 61 +++++++++++++++++++++++++++------------- hydro/model/blacklist.ts | 12 ++++++-- hydro/model/domain.ts | 11 ++++---- hydro/model/file.ts | 20 +++++++++---- hydro/model/message.ts | 26 ++++++++--------- hydro/model/setting.ts | 35 +++++++++-------------- hydro/model/system.ts | 3 +- 8 files changed, 99 insertions(+), 71 deletions(-) diff --git a/TODO b/TODO index a46d2ed72..4a925a4a1 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,5 @@ @requireCsrfToken -消息提醒 +为model.system添加缓存 bug修复 使用BigInt管理权限 修复discussion前端权限节点显示异常 diff --git a/hydro/interface.ts b/hydro/interface.ts index ae8257068..682b2f258 100644 --- a/hydro/interface.ts +++ b/hydro/interface.ts @@ -1,13 +1,12 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars import { ObjectID, GridFSBucket } from 'mongodb'; import fs from 'fs'; - -export type Dict = { [key: string]: T }; +import { Dictionary, NumericDictionary } from 'lodash'; export interface Setting { family: string, key: string, - range: Array<[string, string]> | Dict, + range: Array<[string, string]> | Dictionary, value: any, type: string, name: string, @@ -15,7 +14,7 @@ export interface Setting { flag: number, } -export interface Udoc { +export interface Udoc extends Dictionary { udoc: () => any, dudoc: () => any, _id: number, @@ -34,12 +33,9 @@ export interface Udoc { hasPerm: (perm: string) => boolean, hasPriv: (priv: number) => boolean, checkPassword: (password: string) => void, - [key: string]: any, } -export interface Udict { - [key: number]: Udoc, -} +export type Udict = NumericDictionary; export interface Pdoc { _id: ObjectID, @@ -59,9 +55,7 @@ export interface Pdoc { config: string, } -export interface Pdict { - [key: string]: Pdoc, -} +export type Pdict = Dictionary; export interface TestCase { time: number, @@ -102,9 +96,7 @@ export interface ScoreboardNode { raw?: any, } -export interface PenaltyRules { - [key: string]: number, -} +export type PenaltyRules = Dictionary; export interface Tdoc { _id: ObjectID, @@ -128,9 +120,40 @@ export interface Tdoc { dag: any } -interface ContestStat { +export interface DomainDoc extends Dictionary { + _id: string, + owner: number, + roles: Dictionary, + gravatar: string, + bulletin: string, +} + +// Message +export interface Mdoc { + _id: ObjectID, + from: number, + to: number, + content: string, + unread: boolean, +} + +// Userfile +export interface Ufdoc { + _id: ObjectID, + secret: string, + md5: string, + owner: number, + size: number, +} + +// Blacklist +export interface Bdoc { + _id: string, // ip + expireAt: Date, +} + +interface ContestStat extends Dictionary { detail: any, - [key: string]: any, } export interface ContestRule { @@ -147,9 +170,7 @@ export interface ContestRule { rank: (tsdocs: any[]) => any[] | Generator, } -export interface ContestRules { - [key: string]: ContestRule, -} +export type ContestRules = Dictionary; export type ProblemImporter = (url: string, handler: any) => Promise<[Pdoc, fs.ReadStream?]> | [Pdoc, fs.ReadStream?]; @@ -224,7 +245,7 @@ declare global { template: { [key: string]: string }, ui: any, error: typeof import('./error'), - locales: { [id: string]: { [key: string]: string } }, + locales: Dict>, postInit: Function[], }, nodeModules: any, diff --git a/hydro/model/blacklist.ts b/hydro/model/blacklist.ts index 42e5d8ec7..6ef24b7bc 100644 --- a/hydro/model/blacklist.ts +++ b/hydro/model/blacklist.ts @@ -1,13 +1,19 @@ import * as db from '../service/db'; +import { Bdoc } from '../interface'; const coll = db.collection('blacklist'); -export async function add(ip: string) { +export async function add(ip: string): Promise { const expireAt = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000); - return coll.findOneAndUpdate({ _id: ip }, { $set: { expireAt } }, { upsert: true }); + const res = await coll.findOneAndUpdate( + { _id: ip }, + { $set: { expireAt } }, + { upsert: true, returnOriginal: false }, + ); + return res.value; } -export function get(ip: string) { +export function get(ip: string): Promise { return coll.findOne({ _id: ip }); } diff --git a/hydro/model/domain.ts b/hydro/model/domain.ts index 1ec7f2b49..327c09ec1 100644 --- a/hydro/model/domain.ts +++ b/hydro/model/domain.ts @@ -1,5 +1,6 @@ +import { Dictionary } from 'lodash'; import { BUILTIN_ROLES, PRIV } from './builtin'; -import { Udoc } from '../interface'; +import { Udoc, DomainDoc } from '../interface'; import * as db from '../service/db'; const coll = db.collection('domain'); @@ -12,11 +13,11 @@ export async function add(domainId: string, owner: number, name: string, bulleti return domainId; } -export function get(domainId: string) { +export function get(domainId: string): Promise { return coll.findOne({ _id: domainId }); } -export function getMany(query: any, sort: any, page: number, limit: number) { +export function getMany(query: any, sort: any, page: number, limit: number): Promise { return coll.find(query).sort(sort).skip((page - 1) * limit).limit(limit) .toArray(); } @@ -29,7 +30,7 @@ export function edit(domainId: string, $set: any) { return coll.updateOne({ _id: domainId }, { $set }); } -export async function inc(domainId: string, field: string, n: number) { +export async function inc(domainId: string, field: string, n: number): Promise { const res = await coll.findOneAndUpdate( { _id: domainId }, { $inc: { [field]: n } }, @@ -38,7 +39,7 @@ export async function inc(domainId: string, field: string, n: number) { return res.value; } -export async function getList(domainIds: string[]) { +export async function getList(domainIds: string[]): Promise> { const r = {}; // eslint-disable-next-line no-await-in-loop for (const domainId of domainIds) r[domainId] = await get(domainId); diff --git a/hydro/model/file.ts b/hydro/model/file.ts index 3dd26fe82..e267821f7 100644 --- a/hydro/model/file.ts +++ b/hydro/model/file.ts @@ -1,9 +1,11 @@ import { ObjectID } from 'mongodb'; import * as fs from 'fs'; +import { Dictionary } from 'lodash'; import { ForbiddenError, NotFoundError } from '../error'; import * as db from '../service/db'; import gridfs from '../service/gridfs'; import hash from '../lib/hash.hydro'; +import { Ufdoc } from '../interface'; const coll = db.collection('file'); const collFile = db.collection('fs.files'); @@ -22,7 +24,12 @@ export async function add( else stream = streamOrPath; const w = gridfs.openUploadStream(filename); await coll.insertOne({ - ...meta, _id: w.id, secret: String.random(32), owner, filename, + ...meta, + _id: w.id, + secret: String.random(32), + owner, + filename, + count: 1, }); await new Promise((resolve, reject) => { w.on('error', reject); @@ -42,21 +49,22 @@ export function del(_id: ObjectID) { ]); } -export async function inc(_id: ObjectID) { +export async function inc(_id: ObjectID): Promise { const doc = await coll.findOneAndUpdate( { _id }, { $inc: { count: 1 } }, { returnOriginal: false }, ); - return (doc.value || {}).count; + return doc.value?.count; } -export async function dec(_id: ObjectID) { +export async function dec(_id: ObjectID): Promise { const file = await coll.findOneAndUpdate( { _id }, { $inc: { count: -1 } }, { returnOriginal: false }, ); + if (!file.value) return 0; if (!file.value.count) await del(_id); return file.value.count; } @@ -79,11 +87,11 @@ export async function get(_id: ObjectID) { return gridfs.openDownloadStream(_id); } -export function getMeta(_id: ObjectID) { +export function getMeta(_id: ObjectID): Promise { return coll.findOne({ _id }); } -export async function getMetaDict(ufids: ObjectID[]) { +export async function getMetaDict(ufids: ObjectID[]): Promise> { const r = {}; ufids = Array.from(new Set(ufids)); const ufdocs = await coll.find({ _id: { $in: ufids } }).toArray(); diff --git a/hydro/model/message.ts b/hydro/model/message.ts index 93686d0ee..c879ad6c7 100644 --- a/hydro/model/message.ts +++ b/hydro/model/message.ts @@ -1,10 +1,10 @@ -import { ObjectID, QuerySelector } from 'mongodb'; -import { MessageNotFoundError } from '../error'; +import { ObjectID } from 'mongodb'; +import { Mdoc } from '../interface'; import * as db from '../service/db'; const coll = db.collection('message'); -export async function send(from: number, to: number, content: string) { +export async function send(from: number, to: number, content: string): Promise { const res = await coll.insertOne({ from, to, content, unread: true, }); @@ -13,27 +13,25 @@ export async function send(from: number, to: number, content: string) { }; } -export async function get(_id: ObjectID) { - const doc = await coll.findOne({ _id }); - if (!doc) throw new MessageNotFoundError(_id); - return doc; +export async function get(_id: ObjectID): Promise { + return await coll.findOne({ _id }); } -export function getByUser(uid: number) { - return coll.find({ $or: [{ from: uid }, { to: uid }] }).sort('_id', 1).toArray(); +export async function getByUser(uid: number): Promise { + return await coll.find({ $or: [{ from: uid }, { to: uid }] }).sort('_id', 1).toArray(); } -export function getMany(query: QuerySelector, sort, page: number, limit: number) { - return coll.find(query).sort(sort) +export async function getMany(query: any, sort: any, page: number, limit: number): Promise { + return await coll.find(query).sort(sort) .skip((page - 1) * limit).limit(limit) .toArray(); } -export function del(_id: ObjectID) { - return coll.deleteOne({ _id }); +export async function del(_id: ObjectID) { + return await coll.deleteOne({ _id }); } -export function count(query: QuerySelector) { +export function count(query: any) { return coll.find(query).count(); } diff --git a/hydro/model/setting.ts b/hydro/model/setting.ts index cc0621100..467ebb298 100644 --- a/hydro/model/setting.ts +++ b/hydro/model/setting.ts @@ -1,9 +1,10 @@ /* eslint-disable no-await-in-loop */ import moment from 'moment-timezone'; +import { Dictionary } from 'lodash'; import * as builtin from './builtin'; -import { Setting as _Setting, Dict } from '../interface'; +import { Setting as _Setting } from '../interface'; -type SettingDict = Dict<_Setting>; +type SettingDict = Dictionary<_Setting>; const countries = moment.tz.countries(); const tzs: Set = new Set(); @@ -11,8 +12,8 @@ for (const country of countries) { const tz = moment.tz.zonesForCountry(country); for (const t of tz) tzs.add(t); } -const timezones = Array.from(tzs).sort().map((tz) => [tz, tz]); -const langRange: Dict = {}; +const timezones = Array.from(tzs).sort().map((tz) => [tz, tz]) as [string, string][]; +const langRange: Dictionary = {}; for (const lang in global.Hydro.locales) { langRange[lang] = global.Hydro.locales[lang].__langname; @@ -34,7 +35,7 @@ export const DOMAIN_SETTINGS_BY_KEY: SettingDict = {}; export const SYSTEM_SETTINGS_BY_KEY: SettingDict = {}; export const Setting = ( - family: string, key: string, range: Array<[string, string]> | Dict = null, + family: string, key: string, range: Array<[string, string]> | Dictionary = null, value: any = null, type = 'text', name = '', desc = '', flag = 0, ): _Setting => ({ @@ -75,27 +76,19 @@ export const SystemSetting = (...settings: _Setting[]) => { }; PreferenceSetting( - Setting('setting_display', 'viewLang', langRange, - 'zh_CN', 'select', 'UI Language'), - Setting('setting_display', 'timeZone', timezones as [string, string][], - 'Asia/Shanghai', 'select', 'Timezone'), - Setting('setting_usage', 'codeLang', builtin.LANG_TEXTS, - null, 'select', 'Default Code Language'), - Setting('setting_usage', 'codeTemplate', null, - null, 'textarea', 'Default Code Template', + Setting('setting_display', 'viewLang', langRange, 'zh_CN', 'select', 'UI Language'), + Setting('setting_display', 'timeZone', timezones, 'Asia/Shanghai', 'select', 'Timezone'), + Setting('setting_usage', 'codeLang', builtin.LANG_TEXTS, null, 'select', 'Default Code Language'), + Setting('setting_usage', 'codeTemplate', null, null, 'textarea', 'Default Code Template', 'If left blank, the built-in template of the corresponding language will be used.'), ); AccountSetting( - Setting('setting_info', 'gravatar', null, - null, 'text', 'Gravatar Email', + Setting('setting_info', 'gravatar', null, null, 'text', 'Gravatar Email', 'We use Gravatar to present your avatar icon.'), - Setting('setting_info', 'qq', null, - null, 'text', 'QQ'), - Setting('setting_info', 'gender', builtin.USER_GENDER_RANGE, - null, 'select', 'Gender'), - Setting('setting_info', 'bio', null, - null, 'markdown', 'Bio'), + Setting('setting_info', 'qq', null, null, 'text', 'QQ'), + Setting('setting_info', 'gender', builtin.USER_GENDER_RANGE, null, 'select', 'Gender'), + Setting('setting_info', 'bio', null, null, 'markdown', 'Bio'), Setting('setting_customize', 'backgroundImage', null, '/components/profile/backgrounds/1.jpg', 'text', 'Profile Background Image', 'Choose the background image in your profile page.'), diff --git a/hydro/model/system.ts b/hydro/model/system.ts index d2a97fa71..c528200e0 100644 --- a/hydro/model/system.ts +++ b/hydro/model/system.ts @@ -1,4 +1,5 @@ import { FindOneAndUpdateOption } from 'mongodb'; +import { Dictionary } from 'lodash'; import * as db from '../service/db'; const coll = db.collection('system'); @@ -9,7 +10,7 @@ export async function get(_id: string) { return null; } -export async function getMany(keys: string[]) { +export async function getMany(keys: string[]): Promise> { const docs = await coll.find({ _id: { $in: keys } }).toArray(); const dict = {}; const res = [];