mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 09:46:28 +08:00
core: simple vuser
This commit is contained in:
1 parent
4d6f6dcdb2
commit
79138861a6
4 files changed
+63
-20
No files matched your search
@@ -9,7 +9,7 @@
|
|||||||
"@hydrooj/utils": "workspace:*",
|
"@hydrooj/utils": "workspace:*",
|
||||||
"axios": "^0.21.4",
|
"axios": "^0.21.4",
|
||||||
"cac": "^6.7.3",
|
"cac": "^6.7.3",
|
||||||
"esbuild": "^0.12.28",
|
"esbuild": "^0.12.29",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/fs-extra": "^9.0.12",
|
"@types/fs-extra": "^9.0.13",
|
||||||
"@types/js-yaml": "^4.0.3",
|
"@types/js-yaml": "^4.0.3",
|
||||||
"@types/lodash": "^4.14.173",
|
"@types/lodash": "^4.14.173",
|
||||||
"@types/shell-quote": "^1.7.1",
|
"@types/shell-quote": "^1.7.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.37.8",
|
"version": "2.38.0",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "src/loader",
|
"main": "src/loader",
|
||||||
"module": "src/loader",
|
"module": "src/loader",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"cac": "^6.7.3",
|
"cac": "^6.7.3",
|
||||||
"cookies": "^0.8.0",
|
"cookies": "^0.8.0",
|
||||||
"detect-browser": "^5.2.1",
|
"detect-browser": "^5.2.1",
|
||||||
"esbuild": "^0.12.28",
|
"esbuild": "^0.12.29",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
"graphql": "^15.6.0",
|
"graphql": "^15.6.0",
|
||||||
"graphql-scalars": "^1.10.1",
|
"graphql-scalars": "^1.10.1",
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/adm-zip": "^0.4.34",
|
"@types/adm-zip": "^0.4.34",
|
||||||
"@types/fs-extra": "^9.0.12",
|
"@types/fs-extra": "^9.0.13",
|
||||||
"@types/js-yaml": "^4.0.3",
|
"@types/js-yaml": "^4.0.3",
|
||||||
"@types/koa": "^2.13.4",
|
"@types/koa": "^2.13.4",
|
||||||
"@types/koa-compress": "^4.0.3",
|
"@types/koa-compress": "^4.0.3",
|
||||||
|
|||||||
@@ -73,6 +73,22 @@ export interface Udoc extends Dictionary<any> {
|
|||||||
loginip: string;
|
loginip: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VUdoc {
|
||||||
|
_id: number;
|
||||||
|
mail: string;
|
||||||
|
mailLower: string;
|
||||||
|
uname: string;
|
||||||
|
unameLower: string;
|
||||||
|
salt: '';
|
||||||
|
hash: '';
|
||||||
|
hashType: 'hydro';
|
||||||
|
priv: 0;
|
||||||
|
regat: Date;
|
||||||
|
loginat: Date;
|
||||||
|
ip: ['127.0.0.1'];
|
||||||
|
loginip: '127.0.0.1';
|
||||||
|
}
|
||||||
|
|
||||||
export type ownerInfo = { owner: number, maintainer?: number[] };
|
export type ownerInfo = { owner: number, maintainer?: number[] };
|
||||||
|
|
||||||
export interface User extends Record<string, any> {
|
export interface User extends Record<string, any> {
|
||||||
@@ -539,6 +555,14 @@ export interface EventDoc {
|
|||||||
expire: Date;
|
expire: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface OpCountDoc {
|
||||||
|
_id: ObjectID;
|
||||||
|
op: string;
|
||||||
|
ident: string;
|
||||||
|
expireAt: Date;
|
||||||
|
opcount: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Collections {
|
export interface Collections {
|
||||||
'blacklist': BlacklistDoc;
|
'blacklist': BlacklistDoc;
|
||||||
'contest': Tdoc;
|
'contest': Tdoc;
|
||||||
@@ -547,8 +571,10 @@ export interface Collections {
|
|||||||
'domain.union': DomainUnion;
|
'domain.union': DomainUnion;
|
||||||
'record': RecordDoc;
|
'record': RecordDoc;
|
||||||
'document': any;
|
'document': any;
|
||||||
|
'document.status': any;
|
||||||
'problem': ProblemDoc;
|
'problem': ProblemDoc;
|
||||||
'user': Udoc;
|
'user': Udoc;
|
||||||
|
'vuser': VUdoc;
|
||||||
'check': any;
|
'check': any;
|
||||||
'message': MessageDoc;
|
'message': MessageDoc;
|
||||||
'token': TokenDoc;
|
'token': TokenDoc;
|
||||||
@@ -559,10 +585,9 @@ export interface Collections {
|
|||||||
'storage': FileNode;
|
'storage': FileNode;
|
||||||
'oplog': OplogDoc;
|
'oplog': OplogDoc;
|
||||||
'event': EventDoc;
|
'event': EventDoc;
|
||||||
'opcount': any;
|
'opcount': OpCountDoc;
|
||||||
'fs.chunks': any;
|
'fs.chunks': any;
|
||||||
'fs.files': any;
|
'fs.files': any;
|
||||||
'document.status': any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Model {
|
export interface Model {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Collection } from 'mongodb';
|
|||||||
import { LoginError, UserAlreadyExistError, UserNotFoundError } from '../error';
|
import { LoginError, UserAlreadyExistError, UserNotFoundError } from '../error';
|
||||||
import {
|
import {
|
||||||
FileInfo, Udict, Udoc,
|
FileInfo, Udict, Udoc,
|
||||||
User as _User,
|
User as _User, VUdoc,
|
||||||
} from '../interface';
|
} from '../interface';
|
||||||
import pwhash from '../lib/hash.hydro';
|
import pwhash from '../lib/hash.hydro';
|
||||||
import { Logger } from '../logger';
|
import { Logger } from '../logger';
|
||||||
@@ -19,6 +19,8 @@ import * as system from './system';
|
|||||||
import token from './token';
|
import token from './token';
|
||||||
|
|
||||||
const coll: Collection<Udoc> = db.collection('user');
|
const coll: Collection<Udoc> = db.collection('user');
|
||||||
|
// Virtual user, only for display in contest.
|
||||||
|
const collV: Collection<VUdoc> = db.collection('vuser');
|
||||||
const logger = new Logger('model/user');
|
const logger = new Logger('model/user');
|
||||||
const cache = new LRU<string, User>({ max: 500, maxAge: 300 * 1000 });
|
const cache = new LRU<string, User>({ max: 500, maxAge: 300 * 1000 });
|
||||||
|
|
||||||
@@ -154,7 +156,7 @@ class UserModel {
|
|||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async getById(domainId: string, _id: number, scope: bigint | string = PERM.PERM_ALL): Promise<User | null> {
|
static async getById(domainId: string, _id: number, scope: bigint | string = PERM.PERM_ALL): Promise<User | null> {
|
||||||
if (cache.has(`id/${_id}/${domainId}`)) return cache.get(`id/${_id}/${domainId}`) || null;
|
if (cache.has(`id/${_id}/${domainId}`)) return cache.get(`id/${_id}/${domainId}`) || null;
|
||||||
const udoc = await coll.findOne({ _id });
|
const udoc = await (_id < -999 ? collV : coll).findOne({ _id });
|
||||||
if (!udoc) return null;
|
if (!udoc) return null;
|
||||||
const dudoc = await domain.getDomainUser(domainId, udoc);
|
const dudoc = await domain.getDomainUser(domainId, udoc);
|
||||||
if (typeof scope === 'string') scope = BigInt(scope);
|
if (typeof scope === 'string') scope = BigInt(scope);
|
||||||
@@ -177,7 +179,8 @@ class UserModel {
|
|||||||
static async getByUname(domainId: string, uname: string): Promise<User | null> {
|
static async getByUname(domainId: string, uname: string): Promise<User | null> {
|
||||||
const unameLower = uname.trim().toLowerCase();
|
const unameLower = uname.trim().toLowerCase();
|
||||||
if (cache.has(`name/${unameLower}/${domainId}`)) return cache.get(`name/${unameLower}/${domainId}`) || null;
|
if (cache.has(`name/${unameLower}/${domainId}`)) return cache.get(`name/${unameLower}/${domainId}`) || null;
|
||||||
const udoc = await coll.findOne({ unameLower });
|
let udoc = await coll.findOne({ unameLower });
|
||||||
|
if (!udoc) udoc = await collV.findOne({ unameLower });
|
||||||
if (!udoc) return null;
|
if (!udoc) return null;
|
||||||
const dudoc = await domain.getDomainUser(domainId, udoc);
|
const dudoc = await domain.getDomainUser(domainId, udoc);
|
||||||
const res = await new UserModel.User(udoc, dudoc).init();
|
const res = await new UserModel.User(udoc, dudoc).init();
|
||||||
@@ -203,6 +206,7 @@ class UserModel {
|
|||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async setById(uid: number, $set?: Partial<Udoc>, $unset?: Value<Partial<Udoc>, ''>) {
|
static async setById(uid: number, $set?: Partial<Udoc>, $unset?: Value<Partial<Udoc>, ''>) {
|
||||||
|
if (uid < 1000) return null;
|
||||||
const op: any = {};
|
const op: any = {};
|
||||||
if ($set && Object.keys($set).length) op.$set = $set;
|
if ($set && Object.keys($set).length) op.$set = $set;
|
||||||
if ($unset && Object.keys($unset).length) op.$unset = $unset;
|
if ($unset && Object.keys($unset).length) op.$unset = $unset;
|
||||||
@@ -236,6 +240,7 @@ class UserModel {
|
|||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async inc(_id: number, field: string, n: number = 1) {
|
static async inc(_id: number, field: string, n: number = 1) {
|
||||||
|
if (_id < -999) return null;
|
||||||
const udoc = await coll.findOne({ _id });
|
const udoc = await coll.findOne({ _id });
|
||||||
if (!udoc) throw new UserNotFoundError(_id);
|
if (!udoc) throw new UserNotFoundError(_id);
|
||||||
udoc[field] = udoc[field] + n || n;
|
udoc[field] = udoc[field] + n || n;
|
||||||
@@ -279,16 +284,29 @@ class UserModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async changeUsername(uid: number, uname: string) {
|
static async ensureVuser(uname: string) {
|
||||||
const udoc = await coll.findOne({ _id: uid });
|
const [[min], current] = await Promise.all([
|
||||||
deleteUserCache(udoc);
|
collV.find({}).sort({ _id: -1 }).limit(1).toArray(),
|
||||||
const res = await coll.findOneAndUpdate(
|
collV.findOne({ unameLower: uname.toLowerCase() }),
|
||||||
{ _id: uid },
|
]);
|
||||||
{ $set: { uname, unameLower: uname.trim().toLowerCase() } },
|
if (current) return current._id;
|
||||||
{ returnDocument: 'after' },
|
const uid = min?._id ? min._id - 1 : -1000;
|
||||||
);
|
await collV.insertOne({
|
||||||
deleteUserCache(res.value);
|
_id: uid,
|
||||||
return res.value;
|
mail: `${-uid}@vuser.local`,
|
||||||
|
mailLower: `${-uid}@vuser.local`,
|
||||||
|
uname,
|
||||||
|
unameLower: uname.trim().toLowerCase(),
|
||||||
|
hash: '',
|
||||||
|
salt: '',
|
||||||
|
hashType: 'hydro',
|
||||||
|
regat: new Date(),
|
||||||
|
ip: ['127.0.0.1'],
|
||||||
|
loginat: new Date(),
|
||||||
|
loginip: '127.0.0.1',
|
||||||
|
priv: 0,
|
||||||
|
});
|
||||||
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getMulti(params: any = {}) {
|
static getMulti(params: any = {}) {
|
||||||
|
|||||||
Reference in new issue
Block a user