From b1f90ab5a1a4dca20f7950abbb18f6e533ac4eab Mon Sep 17 00:00:00 2001 From: undefined Date: Wed, 9 Feb 2022 18:44:41 +0800 Subject: [PATCH] core: oauth: enhancement --- package.json | 4 ++-- packages/hydrooj/package.json | 6 +++--- packages/hydrooj/src/handler/user.ts | 22 +++++++++++++++++----- packages/hydrooj/src/interface.ts | 9 +++++++++ packages/login-with-github/lib.ts | 23 +++++++++++++---------- packages/login-with-github/package.json | 4 ++-- packages/login-with-github/setting.yaml | 7 ++++++- packages/login-with-google/package.json | 2 +- packages/login-with-osu/package.json | 2 +- packages/login-with-qq/package.json | 2 +- 10 files changed, 55 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 81df7562..eb8b45eb 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,8 @@ "@types/cross-spawn": "^6.0.2", "@types/node": "^16.11.22", "@types/semver": "^7.3.9", - "@typescript-eslint/eslint-plugin": "5.10.2", - "@typescript-eslint/parser": "5.10.2", + "@typescript-eslint/eslint-plugin": "5.11.0", + "@typescript-eslint/parser": "5.11.0", "cac": "^6.7.12", "cross-env": "^7.0.3", "cross-spawn": "^7.0.3", diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 2608d8ce..e75eda91 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "3.4.9", + "version": "3.4.10", "bin": "bin/hydrooj.js", "main": "src/loader", "module": "src/loader", @@ -15,7 +15,7 @@ "@graphql-tools/schema": "^8.3.1", "@hydrooj/utils": "workspace:*", "adm-zip": "0.5.5", - "ajv": "^8.9.0", + "ajv": "^8.10.0", "ansi_up": "^5.1.0", "cac": "^6.7.12", "cookies": "^0.8.0", @@ -34,7 +34,7 @@ "koa-router": "^10.1.1", "koa-static-cache": "^5.1.4", "lodash": "^4.17.21", - "lru-cache": "^6.0.0", + "lru-cache": "^7.3.0", "mime-types": "^2.1.34", "minio": "7.0.25", "moment-timezone": "^0.5.34", diff --git a/packages/hydrooj/src/handler/user.ts b/packages/hydrooj/src/handler/user.ts index 25129635..698428a2 100644 --- a/packages/hydrooj/src/handler/user.ts +++ b/packages/hydrooj/src/handler/user.ts @@ -6,7 +6,7 @@ import { SystemError, UserAlreadyExistError, UserFacingError, UserNotFoundError, ValidationError, VerifyPasswordError, } from '../error'; -import { User } from '../interface'; +import { OAuthUserResponse, Udoc, User } from '../interface'; import avatar from '../lib/avatar'; import { sendMail } from '../lib/mail'; import { isEmail, isPassword, isUname } from '../lib/validator'; @@ -360,14 +360,23 @@ class OauthCallbackHandler extends Handler { noCheckPermView = true; async get(args: any) { - let r; - if (global.Hydro.lib[`oauth_${args.type}`]) r = await global.Hydro.lib[`oauth_${args.type}`].callback.call(this, args); - else throw new UserFacingError('Oauth type'); + if (!global.Hydro.lib[`oauth_${args.type}`]) throw new UserFacingError('Oauth type'); + const r = await global.Hydro.lib[`oauth_${args.type}`].callback.call(this, args) as OAuthUserResponse; const uid = await oauth.get(r._id); if (uid) { + await user.setById(uid, { loginat: new Date(), loginip: this.request.ip }); this.session.uid = uid; this.session.scope = PERM.PERM_ALL.toString(); } 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); let username = ''; r.uname = r.uname || []; @@ -384,11 +393,14 @@ class OauthCallbackHandler extends Handler { r.email, username, String.random(32), undefined, this.request.ip, ); - const $set: any = { + const $set: Partial = { oauth: args.type, + loginat: new Date(), + loginip: this.request.ip, }; if (r.bio) $set.bio = r.bio; if (r.viewLang) $set.viewLang = r.viewLang; + if (r.avatar) $set.avatar = r.avatar; await Promise.all([ user.setById(_id, $set), oauth.set(r.email, _id), diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 12ba025d..90d35ee6 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -55,6 +55,15 @@ export interface Setting { flag: number, } +export interface OAuthUserResponse { + _id: string; + avatar?: string; + email?: string; + bio?: string; + uname?: string[]; + viewLang?: string; +} + export interface Udoc extends Dictionary { _id: number; mail: string; diff --git a/packages/login-with-github/lib.ts b/packages/login-with-github/lib.ts index 8eb47ebe..142c771c 100644 --- a/packages/login-with-github/lib.ts +++ b/packages/login-with-github/lib.ts @@ -1,38 +1,40 @@ import 'hydrooj'; -import * as superagent from 'superagent'; +import superagent from 'superagent'; declare module 'hydrooj' { interface SystemKeys { - 'login-with-github.id': string, - 'login-with-github.secret': string, + 'login-with-github.id': string; + 'login-with-github.secret': string; + 'login-with-github.endpoint': string; } interface Lib { - oauth_github: typeof import('./lib'), + oauth_github: typeof import('./lib'); } } async function get() { const { system, token } = global.Hydro.model; - const [appid, [state]] = await Promise.all([ - system.get('login-with-github.id'), + const [[appid, endpoint = 'https://github.com'], [state]] = await Promise.all([ + system.getMany(['login-with-github.id', 'login-with-github.endpoint']), 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 }) { const { system, token } = global.Hydro.model; const { UserFacingError } = global.Hydro.error; - const [[appid, secret, url], s] = await Promise.all([ + const [[appid, secret, endpoint, url], s] = await Promise.all([ system.getMany([ 'login-with-github.id', 'login-with-github.secret', + 'login-with-github.endpoint', 'server.url', ]), 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({ client_id: appid, client_secret: secret, @@ -47,7 +49,7 @@ async function callback({ state, code }) { ); } 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('Authorization', `token ${t}`); const ret = { @@ -55,6 +57,7 @@ async function callback({ state, code }) { email: userInfo.body.email, bio: userInfo.body.bio, uname: [userInfo.body.name, userInfo.body.login], + avatar: `github:${userInfo.body.login}`, }; this.response.redirect = s.redirect; await token.del(s._id, token.TYPE_OAUTH); diff --git a/packages/login-with-github/package.json b/packages/login-with-github/package.json index fa2344ce..364f3c27 100644 --- a/packages/login-with-github/package.json +++ b/packages/login-with-github/package.json @@ -1,13 +1,13 @@ { "name": "@hydrooj/login-with-github", - "version": "0.1.0", + "version": "0.1.1", "main": "package.json", "repository": "git@github.com:hydro-dev/Hydro.git", "author": "undefined ", "license": "AGPL-3.0-or-later", "preferUnplugged": true, "devDependencies": { - "@types/superagent": "^4.1.14" + "@types/superagent": "^4.1.15" }, "peerDependencies": { "hydrooj": "*" diff --git a/packages/login-with-github/setting.yaml b/packages/login-with-github/setting.yaml index 61dbcb79..6980123c 100644 --- a/packages/login-with-github/setting.yaml +++ b/packages/login-with-github/setting.yaml @@ -7,4 +7,9 @@ secret: type: text category: system desc: Github OAuth Secret - name: secret \ No newline at end of file + name: secret +endpoint: + type: text + category: system + desc: Github Api Endpoint + name: endpoint \ No newline at end of file diff --git a/packages/login-with-google/package.json b/packages/login-with-google/package.json index 878784ce..5c39dc01 100644 --- a/packages/login-with-google/package.json +++ b/packages/login-with-google/package.json @@ -7,7 +7,7 @@ "license": "AGPL-3.0-or-later", "preferUnplugged": true, "devDependencies": { - "@types/superagent": "^4.1.14" + "@types/superagent": "^4.1.15" }, "peerDependencies": { "hydrooj": "*" diff --git a/packages/login-with-osu/package.json b/packages/login-with-osu/package.json index 66b1d428..89e40222 100644 --- a/packages/login-with-osu/package.json +++ b/packages/login-with-osu/package.json @@ -7,7 +7,7 @@ "license": "AGPL-3.0-or-later", "preferUnplugged": true, "devDependencies": { - "@types/superagent": "^4.1.14" + "@types/superagent": "^4.1.15" }, "peerDependencies": { "hydrooj": "*" diff --git a/packages/login-with-qq/package.json b/packages/login-with-qq/package.json index 97ca730f..e2023fdc 100644 --- a/packages/login-with-qq/package.json +++ b/packages/login-with-qq/package.json @@ -7,7 +7,7 @@ "license": "AGPL-3.0-or-later", "preferUnplugged": true, "dependencies": { - "ws": "^8.4.0" + "ws": "^8.5.0" }, "devDependencies": { "@types/ws": "^8.2.2"