mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
some bug fix
This commit is contained in:
1 parent
57f711ed4f
commit
fb5c29226b
11 files changed
+57
-44
No files matched your search
+1
-1
@@ -2,4 +2,4 @@ FROM mhart/alpine-node:slim-10
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY .build /app
|
COPY .build /app
|
||||||
EXPOSE 8888
|
EXPOSE 8888
|
||||||
CMD ["node", ".build/development.js"]
|
CMD ["node", ".build/app.js"]
|
||||||
+2
-2
@@ -6,11 +6,11 @@ services:
|
|||||||
links:
|
links:
|
||||||
- mongo
|
- mongo
|
||||||
volumes:
|
volumes:
|
||||||
- ./config.yaml:/config/config.yaml
|
- ./data/config:/config
|
||||||
ports:
|
ports:
|
||||||
- 8888:8888
|
- 8888:8888
|
||||||
mongo:
|
mongo:
|
||||||
image: mongo:latest
|
image: mongo:latest
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./db:/data/db
|
- ./data/db:/data/db
|
||||||
+10
-10
@@ -33,11 +33,11 @@ class HydroError extends Error {
|
|||||||
const UserFacingError = Err('UserFacingError', HydroError, 'UserFacingError', 400);
|
const UserFacingError = Err('UserFacingError', HydroError, 'UserFacingError', 400);
|
||||||
const SystemError = Err('SystemError', HydroError, 'SystemError', 500);
|
const SystemError = Err('SystemError', HydroError, 'SystemError', 500);
|
||||||
|
|
||||||
const BadRequestError = Err('BadRequestError', UserFacingError, 400);
|
const BadRequestError = Err('BadRequestError', UserFacingError, 'BadRequestError', 400);
|
||||||
const ForbiddenError = Err('ForbiddenError', UserFacingError, 403);
|
const ForbiddenError = Err('ForbiddenError', UserFacingError, 'ForbiddenError', 403);
|
||||||
const NotFoundError = Err('NotFoundError', UserFacingError, 404);
|
const NotFoundError = Err('NotFoundError', UserFacingError, 'NotFoundError', 404);
|
||||||
const MethodNotAllowedError = Err('MethodNotAllowedError', UserFacingError, 405);
|
const MethodNotAllowedError = Err('MethodNotAllowedError', UserFacingError, 'MethodNotAllowedError', 405);
|
||||||
const RemoteOnlineJudgeError = Err('RemoteOnlineJudgeError', UserFacingError, 500);
|
const RemoteOnlineJudgeError = Err('RemoteOnlineJudgeError', UserFacingError, 'RemoteOnlineJudgeError', 500);
|
||||||
|
|
||||||
const AlreadyVotedError = Err('AlreadyVotedError', ForbiddenError, "You've already voted.");
|
const AlreadyVotedError = Err('AlreadyVotedError', ForbiddenError, "You've already voted.");
|
||||||
const LoginError = Err('LoginError', ForbiddenError, 'Invalid password for user {0}.');
|
const LoginError = Err('LoginError', ForbiddenError, 'Invalid password for user {0}.');
|
||||||
@@ -63,7 +63,7 @@ const ContestNotLiveError = Err('ContestNotLiveError', ForbiddenError, 'This con
|
|||||||
const ContestScoreboardHiddenError = Err('ContestScoreboardHiddenError', ForbiddenError, 'Contest scoreboard is not visible.');
|
const ContestScoreboardHiddenError = Err('ContestScoreboardHiddenError', ForbiddenError, 'Contest scoreboard is not visible.');
|
||||||
const TrainingAlreadyEnrollError = Err('TrainingAlreadyEnrollError', ForbiddenError, "You've already enrolled this training.");
|
const TrainingAlreadyEnrollError = Err('TrainingAlreadyEnrollError', ForbiddenError, "You've already enrolled this training.");
|
||||||
const RoleAlreadyExistError = Err('RoleAlreadyExistError', ForbiddenError, 'This role already exists.');
|
const RoleAlreadyExistError = Err('RoleAlreadyExistError', ForbiddenError, 'This role already exists.');
|
||||||
const CsrfTokenError = Err('CsrfTokenError', ForbiddenError);
|
const CsrfTokenError = Err('CsrfTokenError', ForbiddenError, 'CsrfTokenError');
|
||||||
|
|
||||||
const UserNotFoundError = Err('UserNotFoundError', NotFoundError, 'User {0} not found.');
|
const UserNotFoundError = Err('UserNotFoundError', NotFoundError, 'User {0} not found.');
|
||||||
const NoProblemError = Err('NoProblemError', NotFoundError, 'No problem.');
|
const NoProblemError = Err('NoProblemError', NotFoundError, 'No problem.');
|
||||||
@@ -72,10 +72,10 @@ const ProblemDataNotFoundError = Err('ProblemDataNotFoundError', NotFoundError,
|
|||||||
const MessageNotFoundError = Err('MessageNotFoundError', NotFoundError, 'Message {0} not found.');
|
const MessageNotFoundError = Err('MessageNotFoundError', NotFoundError, 'Message {0} not found.');
|
||||||
const DocumentNotFoundError = Err('DocumentNotFoundError', NotFoundError, 'Document {2} not found.');
|
const DocumentNotFoundError = Err('DocumentNotFoundError', NotFoundError, 'Document {2} not found.');
|
||||||
|
|
||||||
const ProblemNotFoundError = Err('ProblemNotFountError', DocumentNotFoundError, 'Problem {1} not found.');
|
const ProblemNotFoundError = Err('ProblemNotFountError', DocumentNotFoundError, 'Problem {0} not found.');
|
||||||
const SolutionNotFoundError = Err('SolutionNotFoundError', DocumentNotFoundError);
|
const SolutionNotFoundError = Err('SolutionNotFoundError', DocumentNotFoundError, 'Solution {0} not found.');
|
||||||
const TrainingNotFoundError = Err('TrainingNotFoundError', DocumentNotFoundError);
|
const TrainingNotFoundError = Err('TrainingNotFoundError', DocumentNotFoundError, 'Training {0} not found.');
|
||||||
const ContestNotFoundError = Err('ContestNotFoundError', DocumentNotFoundError);
|
const ContestNotFoundError = Err('ContestNotFoundError', DocumentNotFoundError, 'Contest {0} not found.');
|
||||||
const DiscussionNotFoundError = Err('DiscussionNotFoundError', DocumentNotFoundError, 'Discussion {0} not found.');
|
const DiscussionNotFoundError = Err('DiscussionNotFoundError', DocumentNotFoundError, 'Discussion {0} not found.');
|
||||||
const DiscussionNodeNotFoundError = Err('DiscussionNodeNotFoundError', DocumentNotFoundError, 'Discussion node {1} not found.');
|
const DiscussionNodeNotFoundError = Err('DiscussionNodeNotFoundError', DocumentNotFoundError, 'Discussion node {1} not found.');
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class UserLoginHandler extends Handler {
|
|||||||
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
|
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
|
||||||
if (udoc.priv === PRIV_NONE) throw new BlacklistedError(uname);
|
if (udoc.priv === PRIV_NONE) throw new BlacklistedError(uname);
|
||||||
this.session.uid = udoc._id;
|
this.session.uid = udoc._id;
|
||||||
this.session.rememberme = rememberme;
|
this.session.save = rememberme;
|
||||||
this.response.redirect = this.request.referer.endsWith('/login') ? '/' : this.request.referer;
|
this.response.redirect = this.request.referer.endsWith('/login') ? '/' : this.request.referer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ async function add(tokenType, expireSeconds, data) {
|
|||||||
updateAt: now,
|
updateAt: now,
|
||||||
expireAt: new Date(now.getTime() + expireSeconds * 1000),
|
expireAt: new Date(now.getTime() + expireSeconds * 1000),
|
||||||
});
|
});
|
||||||
return [str, res.ops];
|
return [str, res.ops[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,7 +109,7 @@ global.Hydro.model.token = module.exports = {
|
|||||||
get,
|
get,
|
||||||
update,
|
update,
|
||||||
del,
|
del,
|
||||||
deleteByUid(uid) {
|
delByUid(uid) {
|
||||||
return coll.deleteMany({ uid });
|
return coll.deleteMany({ uid });
|
||||||
},
|
},
|
||||||
getMostRecentSessionByUid(uid) {
|
getMostRecentSessionByUid(uid) {
|
||||||
|
|||||||
+36
-28
@@ -234,7 +234,6 @@ const Handler = HandlerMixin(class {
|
|||||||
cdn_prefix: '/',
|
cdn_prefix: '/',
|
||||||
url_prefix: '/',
|
url_prefix: '/',
|
||||||
};
|
};
|
||||||
this._handler = {};
|
|
||||||
this.session = {};
|
this.session = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,34 +254,37 @@ const Handler = HandlerMixin(class {
|
|||||||
this.response.disposition = `attachment; filename="${name}"`;
|
this.response.disposition = `attachment; filename="${name}"`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async init({ domainId }) {
|
async getSession() {
|
||||||
this.response.body = {};
|
const sid = this.request.cookies.get('sid');
|
||||||
this.now = new Date();
|
this.session = await token.get(sid, token.TYPE_SESSION, false);
|
||||||
this._handler.sid = this.request.cookies.get('sid');
|
|
||||||
this._handler.save = this.request.cookies.get('save');
|
|
||||||
if (this._handler.save) this._handler.expireSeconds = await system.get('session.saved_expire_seconds');
|
|
||||||
else this._handler.expireSeconds = await system.get('session.unsaved_expire_seconds');
|
|
||||||
this.session = this._handler.sid
|
|
||||||
? await token.update(
|
|
||||||
this._handler.sid,
|
|
||||||
token.TYPE_SESSION,
|
|
||||||
this._handler.expireSeconds,
|
|
||||||
{
|
|
||||||
updateIp: this.request.ip,
|
|
||||||
updateUa: this.request.headers['user-agent'] || '',
|
|
||||||
},
|
|
||||||
) : { uid: 1 };
|
|
||||||
if (!this.session) this.session = { uid: 0 };
|
if (!this.session) this.session = { uid: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
async getBdoc() {
|
||||||
const bdoc = await blacklist.get(this.request.ip);
|
const bdoc = await blacklist.get(this.request.ip);
|
||||||
if (bdoc) throw new BlacklistedError(this.request.ip);
|
if (bdoc) throw new BlacklistedError(this.request.ip);
|
||||||
this.user = await user.getById(domainId, this.session.uid);
|
}
|
||||||
if (!this.user) throw new UserNotFoundError(this.session.uid);
|
|
||||||
|
async getCsrfToken() {
|
||||||
this.csrfToken = await token.createOrUpdate(token.TYPE_CSRF_TOKEN, 600, {
|
this.csrfToken = await token.createOrUpdate(token.TYPE_CSRF_TOKEN, 600, {
|
||||||
path: this.request.path,
|
path: this.request.path,
|
||||||
uid: this.session.uid,
|
uid: this.session.uid,
|
||||||
});
|
});
|
||||||
this.UIContext.csrfToken = this.csrfToken;
|
this.UIContext.csrfToken = this.csrfToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
async init({ domainId }) {
|
||||||
|
this.response.body = {};
|
||||||
|
this.now = new Date();
|
||||||
this.preferJson = (this.request.headers.accept || '').includes('application/json');
|
this.preferJson = (this.request.headers.accept || '').includes('application/json');
|
||||||
|
await Promise.all([
|
||||||
|
this.getSession(),
|
||||||
|
this.getBdoc(),
|
||||||
|
]);
|
||||||
|
[this.user] = await Promise.all([
|
||||||
|
user.getById(domainId, this.session.uid, true),
|
||||||
|
this.getCsrfToken(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkCsrfToken(csrfToken) {
|
async checkCsrfToken(csrfToken) {
|
||||||
@@ -339,31 +341,37 @@ const Handler = HandlerMixin(class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async saveCookie() {
|
async saveCookie() {
|
||||||
|
const expireSeconds = this.session.save
|
||||||
|
? await system.get('session.expire_seconds')
|
||||||
|
: await system.get('session.unsaved_expire_seconds');
|
||||||
if (this.session._id) {
|
if (this.session._id) {
|
||||||
await token.update(
|
await token.update(
|
||||||
this.session._id,
|
this.session._id,
|
||||||
token.TYPE_SESSION,
|
token.TYPE_SESSION,
|
||||||
this._handler.expireSeconds,
|
expireSeconds,
|
||||||
this.session,
|
{
|
||||||
|
...this.session,
|
||||||
|
updateIp: this.request.ip,
|
||||||
|
updateUa: this.request.headers['user-agent'] || '',
|
||||||
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
[this.session._id] = await token.add(
|
[, this.session] = await token.add(
|
||||||
token.TYPE_SESSION,
|
token.TYPE_SESSION,
|
||||||
this._handler.expireSeconds,
|
expireSeconds,
|
||||||
{
|
{
|
||||||
|
...this.session,
|
||||||
createIp: this.request.ip,
|
createIp: this.request.ip,
|
||||||
createUa: this.request.headers['user-agent'] || '',
|
createUa: this.request.headers['user-agent'] || '',
|
||||||
updateIp: this.request.ip,
|
updateIp: this.request.ip,
|
||||||
updateUa: this.request.headers['user-agent'] || '',
|
updateUa: this.request.headers['user-agent'] || '',
|
||||||
...this.session,
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const cookie = { secure: await system.get('session.secure') };
|
const cookie = { secure: await system.get('session.secure') };
|
||||||
if (this._handler.save) {
|
if (this.session.save) {
|
||||||
cookie.expires = this.session.expireAt;
|
cookie.expires = this.session.expireAt;
|
||||||
cookie.maxAge = this._handler.expireSeconds;
|
cookie.maxAge = expireSeconds;
|
||||||
this.ctx.cookies.set('save', 'true', cookie);
|
|
||||||
}
|
}
|
||||||
this.ctx.cookies.set('sid', this.session._id, cookie);
|
this.ctx.cookies.set('sid', this.session._id, cookie);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="row"><div class="columns">
|
<div class="row"><div class="columns">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||||
<input type="submit" value="{{ _('Login') }}" class="inverse expanded rounded primary button">
|
<input type="submit" value="{{ _('Login') }}" class="inverse expanded rounded primary button">
|
||||||
</div>
|
</div>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
</div></div>
|
</div></div>
|
||||||
<div class="row"><div class="columns">
|
<div class="row"><div class="columns">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||||
<input type="submit" value="{{ _('Send Password Reset Email') }}" class="inverse rounded primary button">
|
<input type="submit" value="{{ _('Send Password Reset Email') }}" class="inverse rounded primary button">
|
||||||
</div>
|
</div>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||||
<input type="submit" value="{{ _('Reset Password') }}" class="inverse rounded primary button">
|
<input type="submit" value="{{ _('Reset Password') }}" class="inverse rounded primary button">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
</div></div>
|
</div></div>
|
||||||
<div class="row"><div class="columns">
|
<div class="row"><div class="columns">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||||
<input type="submit" value="{{ _('Send Verification Email') }}" class="inverse expanded rounded primary button">
|
<input type="submit" value="{{ _('Send Verification Email') }}" class="inverse expanded rounded primary button">
|
||||||
</div>
|
</div>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||||
<input type="submit" value="{{ _('user_register') }}" class="inverse expanded rounded primary button">
|
<input type="submit" value="{{ _('user_register') }}" class="inverse expanded rounded primary button">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Reference in new issue
Block a user