mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: oauth: enhancement
This commit is contained in:
1 parent
04ec44dab9
commit
b1f90ab5a1
10 files changed
+55
-26
No files matched your search
+2
-2
@@ -30,8 +30,8 @@
|
|||||||
"@types/cross-spawn": "^6.0.2",
|
"@types/cross-spawn": "^6.0.2",
|
||||||
"@types/node": "^16.11.22",
|
"@types/node": "^16.11.22",
|
||||||
"@types/semver": "^7.3.9",
|
"@types/semver": "^7.3.9",
|
||||||
"@typescript-eslint/eslint-plugin": "5.10.2",
|
"@typescript-eslint/eslint-plugin": "5.11.0",
|
||||||
"@typescript-eslint/parser": "5.10.2",
|
"@typescript-eslint/parser": "5.11.0",
|
||||||
"cac": "^6.7.12",
|
"cac": "^6.7.12",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"cross-spawn": "^7.0.3",
|
"cross-spawn": "^7.0.3",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "3.4.9",
|
"version": "3.4.10",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "src/loader",
|
"main": "src/loader",
|
||||||
"module": "src/loader",
|
"module": "src/loader",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"@graphql-tools/schema": "^8.3.1",
|
"@graphql-tools/schema": "^8.3.1",
|
||||||
"@hydrooj/utils": "workspace:*",
|
"@hydrooj/utils": "workspace:*",
|
||||||
"adm-zip": "0.5.5",
|
"adm-zip": "0.5.5",
|
||||||
"ajv": "^8.9.0",
|
"ajv": "^8.10.0",
|
||||||
"ansi_up": "^5.1.0",
|
"ansi_up": "^5.1.0",
|
||||||
"cac": "^6.7.12",
|
"cac": "^6.7.12",
|
||||||
"cookies": "^0.8.0",
|
"cookies": "^0.8.0",
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
"koa-router": "^10.1.1",
|
"koa-router": "^10.1.1",
|
||||||
"koa-static-cache": "^5.1.4",
|
"koa-static-cache": "^5.1.4",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lru-cache": "^6.0.0",
|
"lru-cache": "^7.3.0",
|
||||||
"mime-types": "^2.1.34",
|
"mime-types": "^2.1.34",
|
||||||
"minio": "7.0.25",
|
"minio": "7.0.25",
|
||||||
"moment-timezone": "^0.5.34",
|
"moment-timezone": "^0.5.34",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
SystemError, UserAlreadyExistError, UserFacingError,
|
SystemError, UserAlreadyExistError, UserFacingError,
|
||||||
UserNotFoundError, ValidationError, VerifyPasswordError,
|
UserNotFoundError, ValidationError, VerifyPasswordError,
|
||||||
} from '../error';
|
} from '../error';
|
||||||
import { User } from '../interface';
|
import { OAuthUserResponse, Udoc, User } from '../interface';
|
||||||
import avatar from '../lib/avatar';
|
import avatar from '../lib/avatar';
|
||||||
import { sendMail } from '../lib/mail';
|
import { sendMail } from '../lib/mail';
|
||||||
import { isEmail, isPassword, isUname } from '../lib/validator';
|
import { isEmail, isPassword, isUname } from '../lib/validator';
|
||||||
@@ -360,14 +360,23 @@ class OauthCallbackHandler extends Handler {
|
|||||||
noCheckPermView = true;
|
noCheckPermView = true;
|
||||||
|
|
||||||
async get(args: any) {
|
async get(args: any) {
|
||||||
let r;
|
if (!global.Hydro.lib[`oauth_${args.type}`]) throw new UserFacingError('Oauth type');
|
||||||
if (global.Hydro.lib[`oauth_${args.type}`]) r = await global.Hydro.lib[`oauth_${args.type}`].callback.call(this, args);
|
const r = await global.Hydro.lib[`oauth_${args.type}`].callback.call(this, args) as OAuthUserResponse;
|
||||||
else throw new UserFacingError('Oauth type');
|
|
||||||
const uid = await oauth.get(r._id);
|
const uid = await oauth.get(r._id);
|
||||||
if (uid) {
|
if (uid) {
|
||||||
|
await user.setById(uid, { loginat: new Date(), loginip: this.request.ip });
|
||||||
this.session.uid = uid;
|
this.session.uid = uid;
|
||||||
this.session.scope = PERM.PERM_ALL.toString();
|
this.session.scope = PERM.PERM_ALL.toString();
|
||||||
} else {
|
} else {
|
||||||
|
if (r.email) {
|
||||||
|
const udoc = await user.getByEmail('system', r.email);
|
||||||
|
if (udoc) {
|
||||||
|
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
|
||||||
|
this.session.uid = udoc._id;
|
||||||
|
this.session.scpoe = PERM.PERM_ALL.toString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
this.checkPriv(PRIV.PRIV_REGISTER_USER);
|
this.checkPriv(PRIV.PRIV_REGISTER_USER);
|
||||||
let username = '';
|
let username = '';
|
||||||
r.uname = r.uname || [];
|
r.uname = r.uname || [];
|
||||||
@@ -384,11 +393,14 @@ class OauthCallbackHandler extends Handler {
|
|||||||
r.email, username, String.random(32),
|
r.email, username, String.random(32),
|
||||||
undefined, this.request.ip,
|
undefined, this.request.ip,
|
||||||
);
|
);
|
||||||
const $set: any = {
|
const $set: Partial<Udoc> = {
|
||||||
oauth: args.type,
|
oauth: args.type,
|
||||||
|
loginat: new Date(),
|
||||||
|
loginip: this.request.ip,
|
||||||
};
|
};
|
||||||
if (r.bio) $set.bio = r.bio;
|
if (r.bio) $set.bio = r.bio;
|
||||||
if (r.viewLang) $set.viewLang = r.viewLang;
|
if (r.viewLang) $set.viewLang = r.viewLang;
|
||||||
|
if (r.avatar) $set.avatar = r.avatar;
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
user.setById(_id, $set),
|
user.setById(_id, $set),
|
||||||
oauth.set(r.email, _id),
|
oauth.set(r.email, _id),
|
||||||
|
|||||||
@@ -55,6 +55,15 @@ export interface Setting {
|
|||||||
flag: number,
|
flag: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface OAuthUserResponse {
|
||||||
|
_id: string;
|
||||||
|
avatar?: string;
|
||||||
|
email?: string;
|
||||||
|
bio?: string;
|
||||||
|
uname?: string[];
|
||||||
|
viewLang?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Udoc extends Dictionary<any> {
|
export interface Udoc extends Dictionary<any> {
|
||||||
_id: number;
|
_id: number;
|
||||||
mail: string;
|
mail: string;
|
||||||
|
|||||||
@@ -1,38 +1,40 @@
|
|||||||
import 'hydrooj';
|
import 'hydrooj';
|
||||||
|
|
||||||
import * as superagent from 'superagent';
|
import superagent from 'superagent';
|
||||||
|
|
||||||
declare module 'hydrooj' {
|
declare module 'hydrooj' {
|
||||||
interface SystemKeys {
|
interface SystemKeys {
|
||||||
'login-with-github.id': string,
|
'login-with-github.id': string;
|
||||||
'login-with-github.secret': string,
|
'login-with-github.secret': string;
|
||||||
|
'login-with-github.endpoint': string;
|
||||||
}
|
}
|
||||||
interface Lib {
|
interface Lib {
|
||||||
oauth_github: typeof import('./lib'),
|
oauth_github: typeof import('./lib');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
const { system, token } = global.Hydro.model;
|
const { system, token } = global.Hydro.model;
|
||||||
const [appid, [state]] = await Promise.all([
|
const [[appid, endpoint = 'https://github.com'], [state]] = await Promise.all([
|
||||||
system.get('login-with-github.id'),
|
system.getMany(['login-with-github.id', 'login-with-github.endpoint']),
|
||||||
token.add(token.TYPE_OAUTH, 600, { redirect: this.request.referer }),
|
token.add(token.TYPE_OAUTH, 600, { redirect: this.request.referer }),
|
||||||
]);
|
]);
|
||||||
this.response.redirect = `https://github.com/login/oauth/authorize?client_id=${appid}&state=${state}`;
|
this.response.redirect = `${endpoint}/login/oauth/authorize?client_id=${appid}&state=${state}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function callback({ state, code }) {
|
async function callback({ state, code }) {
|
||||||
const { system, token } = global.Hydro.model;
|
const { system, token } = global.Hydro.model;
|
||||||
const { UserFacingError } = global.Hydro.error;
|
const { UserFacingError } = global.Hydro.error;
|
||||||
const [[appid, secret, url], s] = await Promise.all([
|
const [[appid, secret, endpoint, url], s] = await Promise.all([
|
||||||
system.getMany([
|
system.getMany([
|
||||||
'login-with-github.id',
|
'login-with-github.id',
|
||||||
'login-with-github.secret',
|
'login-with-github.secret',
|
||||||
|
'login-with-github.endpoint',
|
||||||
'server.url',
|
'server.url',
|
||||||
]),
|
]),
|
||||||
token.get(state, token.TYPE_OAUTH),
|
token.get(state, token.TYPE_OAUTH),
|
||||||
]);
|
]);
|
||||||
const res = await superagent.post('https://github.com/login/oauth/access_token')
|
const res = await superagent.post(`${endpoint || 'https://github.com'}/login/oauth/access_token`)
|
||||||
.send({
|
.send({
|
||||||
client_id: appid,
|
client_id: appid,
|
||||||
client_secret: secret,
|
client_secret: secret,
|
||||||
@@ -47,7 +49,7 @@ async function callback({ state, code }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const t = res.body.access_token;
|
const t = res.body.access_token;
|
||||||
const userInfo = await superagent.get('https://api.github.com/user')
|
const userInfo = await superagent.get(`${endpoint || 'https://api.github.com'}/user`)
|
||||||
.set('User-Agent', 'Hydro-OAuth')
|
.set('User-Agent', 'Hydro-OAuth')
|
||||||
.set('Authorization', `token ${t}`);
|
.set('Authorization', `token ${t}`);
|
||||||
const ret = {
|
const ret = {
|
||||||
@@ -55,6 +57,7 @@ async function callback({ state, code }) {
|
|||||||
email: userInfo.body.email,
|
email: userInfo.body.email,
|
||||||
bio: userInfo.body.bio,
|
bio: userInfo.body.bio,
|
||||||
uname: [userInfo.body.name, userInfo.body.login],
|
uname: [userInfo.body.name, userInfo.body.login],
|
||||||
|
avatar: `github:${userInfo.body.login}`,
|
||||||
};
|
};
|
||||||
this.response.redirect = s.redirect;
|
this.response.redirect = s.redirect;
|
||||||
await token.del(s._id, token.TYPE_OAUTH);
|
await token.del(s._id, token.TYPE_OAUTH);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/login-with-github",
|
"name": "@hydrooj/login-with-github",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"main": "package.json",
|
"main": "package.json",
|
||||||
"repository": "git@github.com:hydro-dev/Hydro.git",
|
"repository": "git@github.com:hydro-dev/Hydro.git",
|
||||||
"author": "undefined <i@undefined.moe>",
|
"author": "undefined <i@undefined.moe>",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/superagent": "^4.1.14"
|
"@types/superagent": "^4.1.15"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"hydrooj": "*"
|
"hydrooj": "*"
|
||||||
|
|||||||
@@ -7,4 +7,9 @@ secret:
|
|||||||
type: text
|
type: text
|
||||||
category: system
|
category: system
|
||||||
desc: Github OAuth Secret
|
desc: Github OAuth Secret
|
||||||
name: secret
|
name: secret
|
||||||
|
endpoint:
|
||||||
|
type: text
|
||||||
|
category: system
|
||||||
|
desc: Github Api Endpoint
|
||||||
|
name: endpoint
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/superagent": "^4.1.14"
|
"@types/superagent": "^4.1.15"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"hydrooj": "*"
|
"hydrooj": "*"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/superagent": "^4.1.14"
|
"@types/superagent": "^4.1.15"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"hydrooj": "*"
|
"hydrooj": "*"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ws": "^8.4.0"
|
"ws": "^8.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/ws": "^8.2.2"
|
"@types/ws": "^8.2.2"
|
||||||
|
|||||||
Reference in new issue
Block a user