Commit 2d7f04c1 authored by nanahira's avatar nanahira

auth module

parent a27d3224
......@@ -12,4 +12,9 @@ s3:
accessKeyId: zzzz
secretAccessKey: tttt
bucket: nanahira
pathPrefix: test-koishi/
\ No newline at end of file
pathPrefix: test-koishi/
jwt:
secretOrPrivateKey: 'secret'
signOptions:
expiresIn: '1d'
centerAccount: '1111111111'
\ No newline at end of file
......@@ -13,6 +13,7 @@
"@nestjs/common": "^8.0.0",
"@nestjs/config": "^1.1.5",
"@nestjs/core": "^8.0.0",
"@nestjs/jwt": "^8.0.0",
"@nestjs/platform-express": "^8.0.0",
"@nestjs/platform-ws": "^8.2.4",
"@nestjs/swagger": "^5.1.5",
......@@ -2629,6 +2630,18 @@
}
}
},
"node_modules/@nestjs/jwt": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-8.0.0.tgz",
"integrity": "sha512-fz2LQgYY2zmuD8S+8UE215anwKyXlnB/1FwJQLVR47clNfMeFMK8WCxmn6xdPhF5JKuV1crO6FVabb1qWzDxqQ==",
"dependencies": {
"@types/jsonwebtoken": "8.5.4",
"jsonwebtoken": "8.5.1"
},
"peerDependencies": {
"@nestjs/common": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/@nestjs/mapped-types": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.0.tgz",
......@@ -3185,6 +3198,14 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
"node_modules/@types/jsonwebtoken": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz",
"integrity": "sha512-4L8msWK31oXwdtC81RmRBAULd0ShnAHjBuKT9MRQpjP0piNrZdXyTRcKY9/UIfhGeKIT4PvF5amOOUbbT/9Wpg==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/keygrip": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz",
......@@ -4338,6 +4359,11 @@
"ieee754": "^1.1.13"
}
},
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
......@@ -5592,6 +5618,14 @@
"safe-buffer": "~5.1.0"
}
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
......@@ -8543,6 +8577,54 @@
"graceful-fs": "^4.1.6"
}
},
"node_modules/jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^5.6.0"
},
"engines": {
"node": ">=4",
"npm": ">=1.4.28"
}
},
"node_modules/jsonwebtoken/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"bin": {
"semver": "bin/semver"
}
},
"node_modules/jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"dependencies": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/keygrip": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
......@@ -8783,6 +8865,36 @@
"resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz",
"integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI="
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
},
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
},
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
......@@ -8794,6 +8906,11 @@
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
"node_modules/lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"node_modules/lodash.pad": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz",
......@@ -14212,6 +14329,15 @@
"uuid": "8.3.2"
}
},
"@nestjs/jwt": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-8.0.0.tgz",
"integrity": "sha512-fz2LQgYY2zmuD8S+8UE215anwKyXlnB/1FwJQLVR47clNfMeFMK8WCxmn6xdPhF5JKuV1crO6FVabb1qWzDxqQ==",
"requires": {
"@types/jsonwebtoken": "8.5.4",
"jsonwebtoken": "8.5.1"
}
},
"@nestjs/mapped-types": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.0.0.tgz",
......@@ -14640,6 +14766,14 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
"@types/jsonwebtoken": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz",
"integrity": "sha512-4L8msWK31oXwdtC81RmRBAULd0ShnAHjBuKT9MRQpjP0piNrZdXyTRcKY9/UIfhGeKIT4PvF5amOOUbbT/9Wpg==",
"requires": {
"@types/node": "*"
}
},
"@types/keygrip": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz",
......@@ -15534,6 +15668,11 @@
"ieee754": "^1.1.13"
}
},
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
......@@ -16553,6 +16692,14 @@
}
}
},
"ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
......@@ -18771,6 +18918,49 @@
"universalify": "^2.0.0"
}
},
"jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
"requires": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^5.6.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
}
}
},
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"requires": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"keygrip": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
......@@ -18972,6 +19162,36 @@
"resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz",
"integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI="
},
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
},
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
},
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
},
"lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
......@@ -18983,6 +19203,11 @@
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"lodash.pad": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz",
......
......@@ -7,6 +7,10 @@ import { Adapter } from 'koishi';
import { AdapterConfig } from './onebot-improved/utils';
import { MessageService } from './message/message.service';
import S3Assets from '@koishijs/plugin-assets-s3';
import { JwtModule, JwtModuleOptions } from '@nestjs/jwt';
import { AuthService } from './auth/auth.service';
import { BotService } from './bot/bot.service';
import { CENTER_ACCOUNT_TOKEN } from './utility/constant';
@Module({
imports: [
......@@ -17,11 +21,10 @@ import S3Assets from '@koishijs/plugin-assets-s3';
}),
KoishiModule.registerAsync({
inject: [ConfigService],
useFactory: async (configService: ConfigService) => {
const onebotConfig =
configService.get<Adapter.PluginConfig<AdapterConfig, BotConfig>>(
'onebot',
);
useFactory: (configService: ConfigService) => {
const onebotConfig = configService.get<
Adapter.PluginConfig<AdapterConfig, BotConfig>
>('onebot');
const s3Config = configService.get<S3Assets.Config>('s3');
return {
prefix: '__never_prefix',
......@@ -35,7 +38,22 @@ import S3Assets from '@koishijs/plugin-assets-s3';
};
},
}),
JwtModule.registerAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) =>
configService.get<JwtModuleOptions>('jwt'),
}),
],
providers: [
MessageService,
AuthService,
BotService,
{
provide: CENTER_ACCOUNT_TOKEN,
inject: [ConfigService],
useFactory: (configService: ConfigService) =>
configService.get<string>('centerAccount'),
},
],
providers: [MessageService],
})
export class AppModule {}
import { Test, TestingModule } from '@nestjs/testing';
import { AuthService } from './auth.service';
describe('AuthService', () => {
let service: AuthService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AuthService],
}).compile();
service = module.get<AuthService>(AuthService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
import { ConsoleLogger, Injectable } from '@nestjs/common';
import { BotService } from '../bot/bot.service';
import { JwtService } from '@nestjs/jwt';
import { BlankReturnMessageDto } from '../dto/ReturnMessage.dto';
import { InjectCenterAccount } from '../utility/constant';
@Injectable()
export class AuthService extends ConsoleLogger {
constructor(
private readonly botService: BotService,
private readonly jwt: JwtService,
@InjectCenterAccount()
private readonly centerAccount: string,
) {
super('AuthService');
}
async sendCode(selfId: string) {
const bot = this.botService.getBot(selfId);
if (!bot) {
throw new BlankReturnMessageDto(404, 'Bot not found').toException();
}
try {
const code = await this.jwt.signAsync({ sub: selfId });
await bot.sendPrivateMessage(this.centerAccount, `您的密钥是:\n${code}`);
} catch (e) {
this.error(`sendCode error for ${selfId}: ${e.message}`);
throw new BlankReturnMessageDto(500, 'Send message failed').toException();
}
}
async verify(token: string) {
try {
const { sub } = await this.jwt.verifyAsync<{ sub: string }>(token);
return sub;
} catch (e) {
throw new BlankReturnMessageDto(403, 'Invalid token').toException();
}
}
}
import { Test, TestingModule } from '@nestjs/testing';
import { BotService } from './bot.service';
describe('BotService', () => {
let service: BotService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [BotService],
}).compile();
service = module.get<BotService>(BotService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
import { Injectable } from '@nestjs/common';
import { WireContextService } from 'koishi-nestjs';
import { Bot } from 'koishi';
@Injectable()
export class BotService {
@WireContextService()
private bots: Bot[];
private botMap = new Map<string, Bot>();
getBot(id: string): Bot {
if (this.botMap.has(id)) {
return this.botMap.get(id);
}
const bot = this.bots.find((bot) => bot.selfId === id);
if (!bot) {
return;
}
this.botMap.set(id, bot);
return bot;
}
}
......@@ -6,12 +6,16 @@ import {
import { UseEvent, WireContextService } from 'koishi-nestjs';
import { Session } from 'koishi';
import S3Assets from '@koishijs/plugin-assets-s3';
import { InjectCenterAccount } from '../utility/constant';
@Injectable()
export class MessageService
extends ConsoleLogger
implements OnApplicationBootstrap {
constructor() {
constructor(
@InjectCenterAccount()
private readonly centerAccount: string,
) {
super('message');
}
......@@ -23,6 +27,9 @@ export class MessageService
@UseEvent('message')
async onMessage(session: Session) {
if (session.targetId === this.centerAccount) {
return;
}
let content = session.content;
if (this.assets) {
try {
......@@ -34,7 +41,7 @@ export class MessageService
}
// targetId, for private messages only
const fromId = session.userId;
const targetId = session.targetId || session.selfId;
const targetId = session.targetId || session.guildId;
this.log(
`Received message from ${session.username}(${fromId}) to ${targetId}: ${content}`,
);
......
......@@ -4,18 +4,28 @@ import { Adapter } from 'koishi';
import S3Assets from '@koishijs/plugin-assets-s3';
import { AdapterConfig } from '../onebot-improved/utils';
import { BotConfig } from '../onebot-improved';
import { JwtModuleOptions } from '@nestjs/jwt';
export interface Config {
host: string;
port: number;
onebot: Adapter.PluginConfig<AdapterConfig, BotConfig>;
s3?: S3Assets.Config;
jwt: JwtModuleOptions;
centerAccount: string;
}
const defaultConfig: Config = {
host: '::',
port: 3000,
onebot: { bots: [] },
jwt: {
secretOrPrivateKey: 'secret',
signOptions: {
expiresIn: '1d',
},
},
centerAccount: '1111111111',
};
export async function loadConfig(): Promise<Config> {
......
import { Inject } from '@nestjs/common';
export const CENTER_ACCOUNT_TOKEN = 'center_account_token';
export const InjectCenterAccount = () => Inject(CENTER_ACCOUNT_TOKEN);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment