mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
recaptcha: init support
This commit is contained in:
1 parent
f58db3eeb2
commit
8d3dc160a8
11 files changed
+80
-8
No files matched your search
@@ -1,6 +1,8 @@
|
|||||||
root: true
|
root: true
|
||||||
extends:
|
extends:
|
||||||
- airbnb-typescript/base
|
- airbnb-typescript/base
|
||||||
|
env:
|
||||||
|
jquery: true
|
||||||
globals:
|
globals:
|
||||||
Atomics: readonly
|
Atomics: readonly
|
||||||
SharedArrayBuffer: readonly
|
SharedArrayBuffer: readonly
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.20.49",
|
"version": "2.20.50",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "dist/loader.js",
|
"main": "dist/loader.js",
|
||||||
"typings": "dist/loader.d.ts",
|
"typings": "dist/loader.d.ts",
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class UserLogoutHandler extends Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserRegisterHandler extends Handler {
|
export class UserRegisterHandler extends Handler {
|
||||||
async get() {
|
async get() {
|
||||||
this.response.template = 'user_register.html';
|
this.response.template = 'user_register.html';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ export const PRIV = {
|
|||||||
PRIV_REJUDGE: 1 << 13,
|
PRIV_REJUDGE: 1 << 13,
|
||||||
PRIV_VIEW_USER_SECRET: 1 << 14,
|
PRIV_VIEW_USER_SECRET: 1 << 14,
|
||||||
PRIV_VIEW_JUDGE_STATISTICS: 1 << 15,
|
PRIV_VIEW_JUDGE_STATISTICS: 1 << 15,
|
||||||
PRIV_UNLIMITED_RATE: 1 << 22,
|
PRIV_UNLIMITED_ACCESS: 1 << 22,
|
||||||
|
|
||||||
PRIV_ALL: -1,
|
PRIV_ALL: -1,
|
||||||
PRIV_DEFAULT: 0,
|
PRIV_DEFAULT: 0,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import type {
|
|||||||
import type { DomainDoc } from '../loader';
|
import type { DomainDoc } from '../loader';
|
||||||
import type { DocType } from '../model/document';
|
import type { DocType } from '../model/document';
|
||||||
import type { ProblemSolutionHandler } from '../handler/problem';
|
import type { ProblemSolutionHandler } from '../handler/problem';
|
||||||
|
import type { UserRegisterHandler } from '../handler/user';
|
||||||
|
|
||||||
const _hooks: Record<keyof any, Array<(...args: any[]) => any>> = {};
|
const _hooks: Record<keyof any, Array<(...args: any[]) => any>> = {};
|
||||||
const logger = new Logger('bus', true);
|
const logger = new Logger('bus', true);
|
||||||
@@ -23,7 +24,7 @@ function isBailed(value: any) {
|
|||||||
export type Disposable = () => void;
|
export type Disposable = () => void;
|
||||||
export type VoidReturn = Promise<any> | any;
|
export type VoidReturn = Promise<any> | any;
|
||||||
|
|
||||||
export interface EventMap {
|
export interface EventMap extends Record<string, any> {
|
||||||
'app/started': () => void
|
'app/started': () => void
|
||||||
'app/load/lib': () => VoidReturn
|
'app/load/lib': () => VoidReturn
|
||||||
'app/load/locale': () => VoidReturn
|
'app/load/locale': () => VoidReturn
|
||||||
@@ -63,6 +64,10 @@ export interface EventMap {
|
|||||||
|
|
||||||
'handler/create': (thisArg: Handler) => VoidReturn
|
'handler/create': (thisArg: Handler) => VoidReturn
|
||||||
'handler/init': (thisArg: Handler) => VoidReturn
|
'handler/init': (thisArg: Handler) => VoidReturn
|
||||||
|
'handler/before-prepare/UserRegister': (thisArg: UserRegisterHandler) => VoidReturn
|
||||||
|
'handler/before/UserRegister': (thisArg: UserRegisterHandler) => VoidReturn
|
||||||
|
'handler/after/UserRegister': (thisArg: UserRegisterHandler) => VoidReturn
|
||||||
|
'handler/finish/UserRegister': (thisArg: UserRegisterHandler) => VoidReturn
|
||||||
'handler/solution/get': (thisArg: ProblemSolutionHandler) => VoidReturn
|
'handler/solution/get': (thisArg: ProblemSolutionHandler) => VoidReturn
|
||||||
|
|
||||||
'discussion/before-add': (
|
'discussion/before-add': (
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ export class HandlerCommon {
|
|||||||
extraTitleContent?: string;
|
extraTitleContent?: string;
|
||||||
|
|
||||||
async limitRate(op: string, periodSecs: number, maxOperations: number) {
|
async limitRate(op: string, periodSecs: number, maxOperations: number) {
|
||||||
if (this.user && this.user.hasPriv(PRIV.PRIV_UNLIMITED_RATE)) return;
|
if (this.user && this.user.hasPriv(PRIV.PRIV_UNLIMITED_ACCESS)) return;
|
||||||
await opcount.inc(op, this.request.ip, periodSecs, maxOperations);
|
await opcount.inc(op, this.request.ip, periodSecs, maxOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,6 +352,7 @@ export class Handler extends HandlerCommon {
|
|||||||
ctx: Koa.Context;
|
ctx: Koa.Context;
|
||||||
|
|
||||||
request: {
|
request: {
|
||||||
|
method: string,
|
||||||
host: string,
|
host: string,
|
||||||
hostname: string,
|
hostname: string,
|
||||||
ip: string,
|
ip: string,
|
||||||
@@ -384,6 +385,7 @@ export class Handler extends HandlerCommon {
|
|||||||
super();
|
super();
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.request = {
|
this.request = {
|
||||||
|
method: ctx.request.method.toLowerCase(),
|
||||||
host: ctx.request.host,
|
host: ctx.request.host,
|
||||||
hostname: ctx.request.hostname,
|
hostname: ctx.request.hostname,
|
||||||
ip: ctx.request.ip,
|
ip: ctx.request.ip,
|
||||||
@@ -634,15 +636,16 @@ async function handle(ctx, HandlerClass, checker) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await bus.serial('handler/init', h);
|
await bus.serial('handler/init', h);
|
||||||
|
await bus.serial(`handler/before-prepare/${HandlerClass.name.replace(/Handler$/, '')}`, h);
|
||||||
if (h._prepare) await h._prepare(args);
|
if (h._prepare) await h._prepare(args);
|
||||||
if (h.prepare) await h.prepare(args);
|
if (h.prepare) await h.prepare(args);
|
||||||
|
await bus.serial(`handler/before/${HandlerClass.name.replace(/Handler$/, '')}`, h);
|
||||||
if (h[method]) await h[method](args);
|
if (h[method]) await h[method](args);
|
||||||
if (operation) await h[`post${operation}`](args);
|
if (operation) await h[`post${operation}`](args);
|
||||||
|
await bus.serial(`handler/after/${HandlerClass.name.replace(/Handler$/, '')}`, h);
|
||||||
if (h.cleanup) await h.cleanup(args);
|
if (h.cleanup) await h.cleanup(args);
|
||||||
if (h.finish) await h.finish(args);
|
if (h.finish) await h.finish(args);
|
||||||
|
await bus.serial(`handler/finish/${HandlerClass.name.replace(/Handler$/, '')}`, h);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
try {
|
try {
|
||||||
await h.onerror(e);
|
await h.onerror(e);
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ const scripts: UpgradeScript[] = [
|
|||||||
const _FRESH_INSTALL_IGNORE = 1;
|
const _FRESH_INSTALL_IGNORE = 1;
|
||||||
await db.collection('domain.user').deleteMany({ uid: null });
|
await db.collection('domain.user').deleteMany({ uid: null });
|
||||||
await db.collection('domain.user').deleteMany({ uid: 0 });
|
await db.collection('domain.user').deleteMany({ uid: 0 });
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
async function _15_16() {
|
async function _15_16() {
|
||||||
const _FRESH_INSTALL_IGNORE = 1;
|
const _FRESH_INSTALL_IGNORE = 1;
|
||||||
@@ -242,6 +243,7 @@ const scripts: UpgradeScript[] = [
|
|||||||
if (JSON.stringify(af) !== JSON.stringify(pdoc.additional_file)) $set.additional_file = af;
|
if (JSON.stringify(af) !== JSON.stringify(pdoc.additional_file)) $set.additional_file = af;
|
||||||
if (Object.keys($set).length) await problem.edit(pdoc.domainId, pdoc.docId, $set);
|
if (Object.keys($set).length) await problem.edit(pdoc.domainId, pdoc.docId, $set);
|
||||||
});
|
});
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import superagent from 'superagent';
|
||||||
|
import { ValidationError } from 'hydrooj/dist/error';
|
||||||
|
import { PRIV } from 'hydrooj/dist/model/builtin';
|
||||||
|
import * as system from 'hydrooj/dist/model/system';
|
||||||
|
import * as bus from 'hydrooj/dist/service/bus';
|
||||||
|
|
||||||
|
bus.on('handler/before/UserRegister', async (thisArg) => {
|
||||||
|
if (thisArg.request.method !== 'post') {
|
||||||
|
thisArg.UiContext.recaptchaKey = system.get('recaptcha.key');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (thisArg.user.hasPriv(PRIV.PRIV_UNLIMITED_ACCESS)) return;
|
||||||
|
if (!thisArg.args.captcha) throw new ValidationError('captcha');
|
||||||
|
const response = await superagent.post('https://recaptcha.net/recaptcha/api/siteverify')
|
||||||
|
.field('secret', system.get('recaptcha.secret'))
|
||||||
|
.field('response', thisArg.args.captcha)
|
||||||
|
.field('remoteip', thisArg.request.ip);
|
||||||
|
if (!response.body.success) throw new ValidationError('captcha fail');
|
||||||
|
});
|
||||||
|
|
||||||
|
bus.on('handler/after/UserRegister', async (thisArg) => {
|
||||||
|
thisArg.response.body.captcha = `\
|
||||||
|
<script src="https://recaptcha.net/recaptcha/api.js?render=${system.get('recaptcha.key')}"></script>
|
||||||
|
<input type="text" name="captcha" id="_captcha" style="display:none">
|
||||||
|
<input type="submit" id="_submit" style="display:none">`;
|
||||||
|
});
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "@hydrooj/recaptcha",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Google reCAPTCHA",
|
||||||
|
"main": "package.json",
|
||||||
|
"repository": "https://github.com/hydro-dev/Hydro.git",
|
||||||
|
"author": "undefined",
|
||||||
|
"license": "AGPL-3.0-only",
|
||||||
|
"dependencies": {
|
||||||
|
"superagent": "^6.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
(() => {
|
||||||
|
const { AutoloadPage } = window.Hydro;
|
||||||
|
|
||||||
|
const page = new AutoloadPage('recaptcha', () => {
|
||||||
|
function captcha(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
grecaptcha.ready(function () {
|
||||||
|
grecaptcha.execute(UiContext.recaptchaKey, { action: 'submit' }).then(function (token) {
|
||||||
|
document.getElementById('_captcha').value = token;
|
||||||
|
document.getElementById('_submit').click();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
document.getElementById('submit').onclick = captcha;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.Hydro.extraPages.push(page);
|
||||||
|
})();
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
key:
|
||||||
|
type: text
|
||||||
|
secret:
|
||||||
|
type: text
|
||||||
Reference in new issue
Block a user