0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-31 22:51:25 -05:00

feat(core): sign in logs (#139)

* fix(core): add log result type

* fix: comments in sql

* feat(core): sign in log

* refactor: insert error log in middleware

* fix: pr fix

* feat: userLog middleware

* refactor: auto capture log

* fix: pr fix

* fix: pr fix
This commit is contained in:
Wang Sijie 2021-12-08 15:56:57 +08:00 committed by GitHub
parent 7ce706ccbe
commit 1fc73030e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 2 deletions

View file

@ -8,11 +8,14 @@ import { port } from '@/env/consts';
import koaErrorHandler from '@/middleware/koa-error-handler';
import koaI18next from '@/middleware/koa-i18next';
import koaUIProxy from '@/middleware/koa-ui-proxy';
import koaUserLog from '@/middleware/koa-user-log';
import initOidc from '@/oidc/init';
import initRouter from '@/routes/init';
export default async function initApp(app: Koa): Promise<void> {
app.use(koaErrorHandler());
// TODO move to specific router (LOG-454)
app.use(koaUserLog());
app.use(koaLogger());
app.use(koaI18next());

View file

@ -0,0 +1,56 @@
import { UserLogPayload, UserLogResult, UserLogType } from '@logto/schemas';
import { Context, MiddlewareType } from 'koa';
import { nanoid } from 'nanoid';
import { insertUserLog } from '@/queries/user-log';
export type WithUserLogContext<ContextT> = ContextT & {
userLog: LogContext;
};
export interface LogContext {
type?: UserLogType;
userId?: string;
payload: UserLogPayload;
createdAt: number;
}
const insertLog = async (ctx: WithUserLogContext<Context>, result: UserLogResult) => {
// Insert log if log context is set properly.
if (ctx.userLog.userId && ctx.userLog.type) {
try {
await insertUserLog({
id: nanoid(),
userId: ctx.userLog.userId,
type: ctx.userLog.type,
result,
payload: ctx.userLog.payload,
});
} catch (error: unknown) {
console.error('An error occured while inserting user log');
console.error(error);
}
}
};
export default function koaUserLog<StateT, ContextT, ResponseBodyT>(): MiddlewareType<
StateT,
WithUserLogContext<ContextT>,
ResponseBodyT
> {
return async (ctx, next) => {
ctx.userLog = {
createdAt: Date.now(),
payload: {},
};
try {
await next();
await insertLog(ctx, UserLogResult.Success);
return;
} catch (error: unknown) {
await insertLog(ctx, UserLogResult.Failed);
throw error;
}
};
}

View file

@ -0,0 +1,18 @@
import { UserLogDBEntry, UserLogs } from '@logto/schemas';
import { sql } from 'slonik';
import { buildInsertInto } from '@/database/insert-into';
import pool from '@/database/pool';
import { convertToIdentifiers } from '@/database/utils';
const { table, fields } = convertToIdentifiers(UserLogs);
export const insertUserLog = buildInsertInto<UserLogDBEntry>(pool, UserLogs);
export const findLogsByUserId = async (userId: string) =>
pool.many<UserLogDBEntry>(sql`
select ${sql.join(Object.values(fields), sql`,`)}
from ${table}
where ${fields.userId}=${userId}
order by created_at desc
`);

View file

@ -1,4 +1,5 @@
import { LogtoErrorCode } from '@logto/phrases';
import { UserLogType } from '@logto/schemas';
import { conditional } from '@silverhand/essentials';
import { Provider } from 'oidc-provider';
import { object, string } from 'zod';
@ -30,10 +31,14 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
const { id, passwordEncrypted, passwordEncryptionMethod, passwordEncryptionSalt } =
await findUserByUsername(username);
ctx.userLog.userId = id;
ctx.userLog.type = UserLogType.SignInUsernameAndPassword;
assertThat(
passwordEncrypted && passwordEncryptionMethod && passwordEncryptionSalt,
'session.invalid_sign_in_method'
);
assertThat(
encryptPassword(id, password, passwordEncryptionSalt, passwordEncryptionMethod) ===
passwordEncrypted,

View file

@ -3,6 +3,10 @@ import Router from 'koa-router';
import { WithAuthContext } from '@/middleware/koa-auth';
import { WithI18nContext } from '@/middleware/koa-i18next';
import { WithUserInfoContext } from '@/middleware/koa-user-info';
import { WithUserLogContext } from '@/middleware/koa-user-log';
export type AnonymousRouter = Router<unknown, WithI18nContext>;
export type AuthedRouter = Router<unknown, WithUserInfoContext<WithAuthContext<WithI18nContext>>>;
export type AnonymousRouter = Router<unknown, WithUserLogContext<WithI18nContext>>;
export type AuthedRouter = Router<
unknown,
WithUserInfoContext<WithAuthContext<WithUserLogContext<WithI18nContext>>>
>;