Skip to content

Commit

Permalink
社会化登陆封装
Browse files Browse the repository at this point in the history
  • Loading branch information
陈泉 committed Nov 22, 2022
1 parent 61ffa36 commit c214996
Show file tree
Hide file tree
Showing 12 changed files with 220 additions and 255 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"postinstall": "prisma generate"
},
"devDependencies": {
"@stringke/prisma-generator-tsrpc": "^1.0.7",
"@stringke/prisma-generator-tsrpc": "^1.0.10",
"@types/ali-oss": "^6.16.6",
"@types/content-type": "^1.1.5",
"@types/fs-extra": "^9.0.13",
Expand Down Expand Up @@ -46,6 +46,7 @@
"@tnwx/miniprogram": "^2.5.6",
"@tnwx/wxmp": "^2.5.6",
"ali-oss": "^6.17.1",
"axios": "^1.1.3",
"bullmq": "^3.2.2",
"casbin": "^5.19.2",
"casbin-redis-adapter": "^1.0.3",
Expand All @@ -54,7 +55,6 @@
"dayjs": "^1.11.6",
"dotenv": "^16.0.3",
"fs-extra": "^10.1.0",
"got": "^12.5.3",
"hash-wasm": "^4.9.0",
"ioredis": "^5.2.4",
"lodash": "^4.17.21",
Expand Down
33 changes: 28 additions & 5 deletions src/api/auth/ApiSocial.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
import { ApiCall } from "tsrpc";
import { ReqSocial, ResSocial } from "../../shared/protocols/auth/PtlSocial";
import { ApiCall, TsrpcError, TsrpcErrorType } from 'tsrpc'
import { ReqSocial, ResSocial } from '../../shared/protocols/auth/PtlSocial'
import authManager, { QQProvider } from '../../kernel/auth'
import redis from '../../kernel/redis'

export default async function (call: ApiCall<ReqSocial, ResSocial>) {
// TODO
call.error('API Not Implemented');
}
const qqProvider = authManager.getInstance<QQProvider>('test-qq')
if (!qqProvider) {
return call.error(
new TsrpcError({
message: 'No provider found',
code: 'NO_PROVIDER',
type: TsrpcErrorType.ApiError,
}),
)
}

let qqUrl = await redis.getCacheKey(`auth:${call.req.id}`)
if (!qqUrl) {
qqUrl = await qqProvider.getAuthorizationUrl({
srp: call.req.srp,
erp: call.req.erp,
})
await redis.setCacheKey(`auth:${call.req.id}`, qqUrl, 60)
}

return call.succ({
qq: qqUrl,
})
}
2 changes: 1 addition & 1 deletion src/kernel/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class AuthManager {
init<T extends OAuthProvider>(
driver: string,
name: string,
options: T['options'],
options: Omit<T['options'], 'name'>,
) {
const driveClass = AuthManager.getDrive(driver)
const instance = new driveClass({
Expand Down
57 changes: 41 additions & 16 deletions src/kernel/auth/providers/qq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
OAuthProvider,
OAuthProviderBaseOptions,
} from '../abstract-provider'
import got from 'got'
import axios from 'axios'

export declare type QQProviderOptions = OAuthProviderBaseOptions & {
clientId: string
Expand Down Expand Up @@ -35,12 +35,21 @@ export interface QQProfileBase {
gender: string
}

export interface QQApiError {
error: string
error_description: string
}

export interface QQProfile extends QQProfileBase {
unionId?: string
openId: string
raw: any
}

function isQQApiError(data: any): data is QQApiError {
return data && data.error
}

export class QQProvider extends OAuthProvider {
providerName = 'qq'
options: QQProviderOptions
Expand Down Expand Up @@ -92,15 +101,24 @@ export class QQProvider extends OAuthProvider {
url.searchParams.set('fmt', 'json')

return new Promise<QQAccessTokenInfo>((resolve, reject) => {
got<QQAccessTokenInfo>(url.toString(), {
responseType: 'json',
})
axios
.get<
| QQAccessTokenInfo
| {
error: string
error_description: string
}
>(url.toString(), {
headers: {
'Content-Type': 'application/json',
},
})
.then((response) => {
const data = response.body
if (data.error) {
const data = response.data
if (isQQApiError(data)) {
return reject(new Error(data.error_description))
}
resolve(data)
return resolve(data)
})
.catch((error) => {
reject(error)
Expand All @@ -117,12 +135,13 @@ export class QQProvider extends OAuthProvider {
}

return new Promise<QQOpenInfo>((resolve, reject) => {
got<QQOpenInfo>(url.toString(), {
responseType: 'json',
})
axios
.get<QQOpenInfo>(url.toString(), {
responseType: 'json',
})
.then((response) => {
const data = response.body
if (data.error) {
const data = response.data
if (isQQApiError(data)) {
return reject(new Error(data.error_description))
}
resolve(data)
Expand All @@ -142,18 +161,24 @@ export class QQProvider extends OAuthProvider {
url.searchParams.set('openid', openInfo.openid)

return new Promise<QQProfile>((resolve, reject) => {
got<QQProfileBase>(url.toString(), {
responseType: 'json',
})
axios
.get<QQProfileBase>(url.toString(), {
responseType: 'json',
})
.then((response) => {
const data = response.body
const data = response.data
if (data.ret !== 0) {
return reject(new Error(data.msg))
}
resolve({
...data,
openId: openInfo.openid,
unionId: openInfo.unionid,
raw: {
...data,
...openInfo,
params,
},
})
})
.catch((error) => {
Expand Down
10 changes: 9 additions & 1 deletion src/kernel/redis.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import Redis, { RedisOptions } from 'ioredis'

class RedisHelper extends Redis {}
class RedisHelper extends Redis {
async setCacheKey(key: string, value: string, ttl = 60 * 10) {
await this.set(key, value, 'EX', ttl)
}

async getCacheKey(key: string): Promise<string | null> {
return this.get(key)
}
}

export const redisOptions: RedisOptions = {
host: '127.0.0.1',
Expand Down
46 changes: 20 additions & 26 deletions src/shared/db/index.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,33 @@
// Generated by prisma-generator-tsrpc v1.0.9
// Generated by prisma-generator-tsrpc v1.0.10

/* Enum 消费类型 */
export const UserFileConsumeType: {
MEMBER: "MEMBER";
RESOURCE_PACKAGE: "RESOURCE_PACKAGE";
OTHER: "OTHER";
};

export type UserFileConsumeType = (typeof UserFileConsumeType)[keyof typeof UserFileConsumeType];
export enum UserFileConsumeType {
MEMBER = "MEMBER",
RESOURCE_PACKAGE = "RESOURCE_PACKAGE",
OTHER = "OTHER"
}



/* Enum 用户记录来源 */
export const UserRecordSource: {
Promoter: "Promoter";
Order: "Order";
System: "System";
Activity: "Activity";
Other: "Other";
};

export type UserRecordSource = (typeof UserRecordSource)[keyof typeof UserRecordSource];
export enum UserRecordSource {
Promoter = "Promoter",
Order = "Order",
System = "System",
Activity = "Activity",
Other = "Other"
}



/* Enum 用户记录类型 */
export const UserRecordType: {
Alliance: "Alliance";
Withdraw: "Withdraw";
ResourcePackage: "ResourcePackage";
Member: "Member";
Other: "Other";
};

export type UserRecordType = (typeof UserRecordType)[keyof typeof UserRecordType];
export enum UserRecordType {
Alliance = "Alliance",
Withdraw = "Withdraw",
ResourcePackage = "ResourcePackage",
Member = "Member",
Other = "Other"
}



Expand Down
6 changes: 5 additions & 1 deletion src/shared/protocols/auth/PtlSocial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import { BaseRequest, BaseResponse, BaseConf } from '../base'

export interface ReqSocial extends BaseRequest {
id: number
erp?: string
srp?: string
}

export interface ResSocial extends BaseResponse {}
export interface ResSocial extends BaseResponse {
qq: string
}

export const conf: BaseConf = {}
2 changes: 2 additions & 0 deletions src/shared/protocols/base.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { UserRecordSource } from '../db'

export interface SessionData {
[key: string]: [number | null | undefined, any] | any
}
Expand Down
27 changes: 26 additions & 1 deletion src/shared/protocols/serviceProto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface ServiceType {
}

export const serviceProto: ServiceProto<ServiceType> = {
"version": 10,
"version": 11,
"services": [
{
"id": 3,
Expand Down Expand Up @@ -69,6 +69,22 @@ export const serviceProto: ServiceProto<ServiceType> = {
"type": {
"type": "Number"
}
},
{
"id": 1,
"name": "erp",
"type": {
"type": "String"
},
"optional": true
},
{
"id": 2,
"name": "srp",
"type": {
"type": "String"
},
"optional": true
}
]
},
Expand Down Expand Up @@ -170,6 +186,15 @@ export const serviceProto: ServiceProto<ServiceType> = {
"target": "base/BaseResponse"
}
}
],
"properties": [
{
"id": 0,
"name": "qq",
"type": {
"type": "String"
}
}
]
},
"base/BaseResponse": {
Expand Down
5 changes: 1 addition & 4 deletions src/utils/auth.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { authManager, QQProvider } from '../kernel/auth'

export const testQQProvider = new QQProvider({
authManager.init<QQProvider>('qq', 'test-qq', {
clientId: '102018312',
clientSecret: 'AC1cz83mIbhZEfsr',
canGetUnionId: true,
name: 'test-qq',
})

authManager.registerProvider(testQQProvider)
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"ESNext"
],
"module": "commonjs",
"target": "es2018",
"target": "ESNext",
"outDir": "dist",
"strict": true,
"esModuleInterop": true,
Expand Down
Loading

0 comments on commit c214996

Please sign in to comment.