增加登录日志

This commit is contained in:
hanhh
2021-09-07 01:40:25 +08:00
parent 0cbfca979e
commit eb196bd40d
11 changed files with 233 additions and 12 deletions
+15
View File
@@ -167,4 +167,19 @@ export default (app: Router) => {
}
},
);
route.get(
'/user/login-log',
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const authService = Container.get(AuthService);
const data = await authService.getLoginLog();
res.send({ code: 200, data });
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
};
+2
View File
@@ -24,6 +24,7 @@ const dbPath = path.join(rootPath, 'db/');
const cronDbFile = path.join(rootPath, 'db/crontab.db');
const envDbFile = path.join(rootPath, 'db/env.db');
const appDbFile = path.join(rootPath, 'db/app.db');
const authDbFile = path.join(rootPath, 'db/auth.db');
const configFound = dotenv.config({ path: confFile });
@@ -60,6 +61,7 @@ export default {
cronDbFile,
envDbFile,
appDbFile,
authDbFile,
configPath,
scriptPath,
samplePath,
+3 -2
View File
@@ -158,11 +158,12 @@ export async function getNetIp(req: any) {
}
try {
const baiduApi = got
.get(`https://www.cip.cc/${ip}`, { timeout: 100000 })
.get(`https://www.cip.cc/${ip}`, { timeout: 10000, retry: 0 })
.text();
const ipApi = got
.get(`https://whois.pconline.com.cn/ipJson.jsp?ip=${ip}&json=true`, {
timeout: 100000,
timeout: 10000,
retry: 0,
})
.buffer();
const [data, ipApiBody] = await await Promise.all<any>([baiduApi, ipApi]);
+20
View File
@@ -0,0 +1,20 @@
export class AuthInfo {
ip?: string;
type: AuthInfoType;
info?: any;
_id?: string;
constructor(options: AuthInfo) {
this.ip = options.ip;
this.info = options.info;
this.type = options.type;
this._id = options._id;
}
}
export enum LoginStatus {
'success',
'fail',
}
export type AuthInfoType = 'loginLog' | 'authToken';
+61 -1
View File
@@ -6,10 +6,20 @@ import * as fs from 'fs';
import _ from 'lodash';
import jwt from 'jsonwebtoken';
import { authenticator } from '@otplib/preset-default';
import { exec } from 'child_process';
import DataStore from 'nedb';
import { AuthInfo, LoginStatus } from '../data/auth';
@Service()
export default class AuthService {
constructor(@Inject('logger') private logger: winston.Logger) {}
private authDb = new DataStore({ filename: config.authDbFile });
constructor(@Inject('logger') private logger: winston.Logger) {
this.authDb.loadDatabase((err) => {
if (err) throw err;
});
this.authDb.persistence.setAutocompactionInterval(30000);
}
public async login(
payloads: {
@@ -84,6 +94,16 @@ export default class AuthService {
lastaddr: address,
isTwoFactorChecking: false,
});
exec(
`notify 登陆通知 你于${new Date(
timestamp,
).toLocaleString()}${address}登陆成功,ip地址${ip}`,
);
await this.getLoginLog();
await this.insertDb({
type: 'loginLog',
info: { timestamp, address, ip, status: LoginStatus.success },
});
return {
code: 200,
data: { token, lastip, lastaddr, lastlogon, retries },
@@ -95,6 +115,16 @@ export default class AuthService {
lastip: ip,
lastaddr: address,
});
exec(
`notify 登陆通知 你于${new Date(
timestamp,
).toLocaleString()}${address}登陆失败,ip地址${ip}`,
);
await this.getLoginLog();
await this.insertDb({
type: 'loginLog',
info: { timestamp, address, ip, status: LoginStatus.fail },
});
return { code: 400, message: config.authError };
}
} else {
@@ -102,6 +132,36 @@ export default class AuthService {
}
}
public async getLoginLog(): Promise<AuthInfo[]> {
return new Promise((resolve) => {
this.authDb.find({ type: 'loginLog' }).exec((err, docs) => {
if (err || docs.length === 0) {
resolve(docs);
} else {
const result = docs.sort(
(a, b) => b.info.timestamp - a.info.timestamp,
);
if (result.length > 100) {
this.authDb.remove({ _id: result[result.length - 1]._id });
}
resolve(result.map((x) => x.info));
}
});
});
}
private async insertDb(payload: AuthInfo): Promise<AuthInfo> {
return new Promise((resolve) => {
this.authDb.insert(payload, (err, doc) => {
if (err) {
this.logger.error(err);
} else {
resolve(doc);
}
});
});
}
private initAuthInfo() {
const newPassword = createRandomString(16, 22);
fs.writeFileSync(