mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
refactor(core,console,schemas): remove logDto (#2889)
This commit is contained in:
parent
39f15acb40
commit
3ff6554c08
10 changed files with 48 additions and 338 deletions
|
@ -1,5 +1,5 @@
|
|||
import type { Log } from '@logto/schemas';
|
||||
import { LogResult } from '@logto/schemas';
|
||||
import type { LogDto } from '@logto/schemas/lib/types/log-legacy';
|
||||
import { conditional, conditionalString } from '@silverhand/essentials';
|
||||
import classNames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -45,9 +45,7 @@ const AuditLogTable = ({ userId, className }: Props) => {
|
|||
]
|
||||
.filter(Boolean)
|
||||
.join('&');
|
||||
const { data, error, mutate } = useSWR<[LogDto[], number], RequestError>(
|
||||
`/api/logs?${queryString}`
|
||||
);
|
||||
const { data, error, mutate } = useSWR<[Log[], number], RequestError>(`/api/logs?${queryString}`);
|
||||
const isLoading = !data && !error;
|
||||
const navigate = useNavigate();
|
||||
const [logs, totalCount] = data ?? [];
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import type { User } from '@logto/schemas';
|
||||
import type { LogDto } from '@logto/schemas/lib/types/log-legacy';
|
||||
import type { User, Log } from '@logto/schemas';
|
||||
import classNames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation, useParams } from 'react-router-dom';
|
||||
|
@ -31,7 +30,7 @@ const AuditLogDetails = () => {
|
|||
const { id, logId } = useParams();
|
||||
const { pathname } = useLocation();
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { data, error } = useSWR<LogDto, RequestError>(logId && `/api/logs/${logId}`);
|
||||
const { data, error } = useSWR<Log, RequestError>(logId && `/api/logs/${logId}`);
|
||||
const { data: userData } = useSWR<User, RequestError>(id && `/api/users/${id}`);
|
||||
|
||||
const isLoading = !data && !error;
|
||||
|
|
|
@ -38,7 +38,7 @@ export class LogEntry {
|
|||
}
|
||||
}
|
||||
|
||||
export type LogPayload = Partial<LogContextPayload> & Record<string, unknown>;
|
||||
export type LogPayload = Partial<LogContextPayload>;
|
||||
|
||||
export type LogContext = {
|
||||
createLog: (key: LogKey) => LogEntry;
|
||||
|
|
|
@ -5,6 +5,7 @@ import { conditional } from '@silverhand/essentials';
|
|||
import { getLogtoConnectorById } from '#src/libraries/connector.js';
|
||||
import { assignInteractionResults } from '#src/libraries/session.js';
|
||||
import { encryptUserPassword } from '#src/libraries/user.js';
|
||||
import type { LogEntry } from '#src/middleware/koa-audit-log.js';
|
||||
import type TenantContext from '#src/tenants/TenantContext.js';
|
||||
|
||||
import type { WithInteractionDetailsContext } from '../middleware/koa-interaction-details.js';
|
||||
|
@ -129,9 +130,11 @@ const parseUserProfile = async (
|
|||
export default async function submitInteraction(
|
||||
interaction: VerifiedInteractionResult,
|
||||
ctx: WithInteractionDetailsContext,
|
||||
{ provider, libraries, queries }: TenantContext
|
||||
{ provider, libraries, queries }: TenantContext,
|
||||
log?: LogEntry
|
||||
) {
|
||||
const { hasActiveUsers, findUserById, updateUserById } = queries.users;
|
||||
|
||||
const {
|
||||
users: { generateUserId, insertUser },
|
||||
} = libraries;
|
||||
|
@ -155,10 +158,13 @@ export default async function submitInteraction(
|
|||
|
||||
await assignInteractionResults(ctx, provider, { login: { accountId: id } });
|
||||
|
||||
log?.append({ userId: id });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const { accountId } = interaction;
|
||||
log?.append({ userId: accountId });
|
||||
|
||||
if (event === InteractionEvent.SignIn) {
|
||||
const user = await findUserById(accountId);
|
||||
|
|
|
@ -291,17 +291,13 @@ export default function interactionRoutes<T extends AnonymousRouter>(
|
|||
|
||||
const accountVerifiedInteraction = await verifyIdentifier(ctx, provider, interactionStorage);
|
||||
|
||||
if (event !== InteractionEvent.Register) {
|
||||
log.append({ accountId: accountVerifiedInteraction.accountId });
|
||||
}
|
||||
|
||||
const verifiedInteraction = await verifyProfile(accountVerifiedInteraction);
|
||||
|
||||
if (event !== InteractionEvent.ForgotPassword) {
|
||||
await validateMandatoryUserProfile(ctx, verifiedInteraction);
|
||||
}
|
||||
|
||||
await submitInteraction(verifiedInteraction, ctx, tenant);
|
||||
await submitInteraction(verifiedInteraction, ctx, tenant, log);
|
||||
|
||||
return next();
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { LogResult } from '@logto/schemas';
|
||||
import type { Log } from '@logto/schemas';
|
||||
import { pickDefault, createMockUtils } from '@logto/shared/esm';
|
||||
|
||||
import { createRequester } from '#src/utils/test-utils.js';
|
||||
|
@ -5,8 +7,8 @@ import { createRequester } from '#src/utils/test-utils.js';
|
|||
const { jest } = import.meta;
|
||||
const { mockEsm } = createMockUtils(jest);
|
||||
|
||||
const mockBody = { key: 'a', payload: {}, createdAt: 123 };
|
||||
const mockLog = { id: '1', ...mockBody };
|
||||
const mockBody = { key: 'a', payload: { key: 'a', result: LogResult.Success }, createdAt: 123 };
|
||||
const mockLog: Log = { id: '1', ...mockBody };
|
||||
const mockLogs = [mockLog, { id: '2', ...mockBody }];
|
||||
|
||||
const { countLogs, findLogs, findLogById } = mockEsm('#src/queries/log.js', () => ({
|
||||
|
|
|
@ -188,3 +188,33 @@ export type Translation = {
|
|||
export const translationGuard: z.ZodType<Translation> = z.lazy(() =>
|
||||
z.record(z.string().or(translationGuard))
|
||||
);
|
||||
|
||||
/**
|
||||
* Logs
|
||||
*/
|
||||
|
||||
export enum LogResult {
|
||||
Success = 'Success',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
export const logContextPayloadGuard = z
|
||||
.object({
|
||||
key: z.string(),
|
||||
result: z.nativeEnum(LogResult),
|
||||
error: z.record(z.string(), z.unknown()).or(z.string()).optional(),
|
||||
ip: z.string().optional(),
|
||||
userAgent: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
applicationId: z.string().optional(),
|
||||
sessionId: z.string().optional(),
|
||||
})
|
||||
.catchall(z.unknown());
|
||||
|
||||
/**
|
||||
* The basic log context type. It's more about a type hint instead of forcing the log shape.
|
||||
*
|
||||
* Note when setting up a log function, the type of log key in function arguments should be `LogKey`.
|
||||
* Here we use `string` to make it compatible with the Zod guard.
|
||||
**/
|
||||
export type LogContextPayload = z.infer<typeof logContextPayloadGuard>;
|
||||
|
|
|
@ -1,286 +0,0 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
import type { Log } from '../db-entries/index.js';
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export enum LogResult {
|
||||
Success = 'Success',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export const logResultGuard = z.nativeEnum(LogResult);
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export const baseLogPayloadGuard = z.object({
|
||||
result: logResultGuard.optional(),
|
||||
error: z.record(z.string(), z.unknown()).optional(),
|
||||
ip: z.string().optional(),
|
||||
userAgent: z.string().optional(),
|
||||
applicationId: z.string().optional(),
|
||||
sessionId: z.string().optional(),
|
||||
});
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export type BaseLogPayload = z.infer<typeof baseLogPayloadGuard>;
|
||||
|
||||
const arbitraryLogPayloadGuard = z.record(z.string(), z.unknown());
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export type ArbitraryLogPayload = z.infer<typeof arbitraryLogPayloadGuard>;
|
||||
|
||||
const registerUsernamePasswordLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({ userId: z.string().optional(), username: z.string().optional() })
|
||||
);
|
||||
|
||||
const registerEmailSendPasscodeLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({ email: z.string().optional(), connectorId: z.string().optional() })
|
||||
);
|
||||
|
||||
const registerEmailLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
email: z.string().optional(),
|
||||
code: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const registerSmsSendPasscodeLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
phone: z.string().optional(),
|
||||
connectorId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const registerSmsLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
phone: z.string().optional(),
|
||||
code: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const registerSocialBindLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
connectorId: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
userInfo: z.unknown().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const registerSocialLogPayloadGuard = registerSocialBindLogPayloadGuard.and(
|
||||
z.object({
|
||||
code: z.string().optional(),
|
||||
state: z.string().optional(),
|
||||
redirectUri: z.string().optional(),
|
||||
redirectTo: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const signInUsernamePasswordLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
userId: z.string().optional(),
|
||||
username: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const signInEmailPasswordLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
userId: z.string().optional(),
|
||||
email: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const signInSmsPasswordLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
userId: z.string().optional(),
|
||||
sms: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const signInEmailSendPasscodeLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
email: z.string().optional(),
|
||||
connectorId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const signInEmailLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
email: z.string().optional(),
|
||||
code: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const signInSmsSendPasscodeLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
phone: z.string().optional(),
|
||||
connectorId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const signInSmsLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
phone: z.string().optional(),
|
||||
code: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const signInSocialBindLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
connectorId: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
userInfo: z.unknown().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const signInSocialLogPayloadGuard = signInSocialBindLogPayloadGuard.and(
|
||||
z.object({
|
||||
code: z.string().optional(),
|
||||
state: z.string().optional(),
|
||||
redirectUri: z.string().optional(),
|
||||
redirectTo: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const forgotPasswordSmsSendPasscodeLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
phone: z.string().optional(),
|
||||
connectorId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const forgotPasswordSmsLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
phone: z.string().optional(),
|
||||
code: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const forgotPasswordEmailSendPasscodeLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
email: z.string().optional(),
|
||||
connectorId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const forgotPasswordEmailLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
email: z.string().optional(),
|
||||
code: z.string().optional(),
|
||||
userId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const forgotPasswordResetLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
userId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const continueEmailSendPasscodeLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
email: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const continueSmsSendPasscodeLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
phone: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const continueEmailLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
email: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const continueSmsLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
phone: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
export enum TokenType {
|
||||
AccessToken = 'AccessToken',
|
||||
RefreshToken = 'RefreshToken',
|
||||
IdToken = 'IdToken',
|
||||
}
|
||||
|
||||
export const tokenTypeGuard = z.nativeEnum(TokenType);
|
||||
|
||||
const exchangeTokenLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
userId: z.string().optional(),
|
||||
params: z.record(z.string(), z.unknown()).optional(),
|
||||
issued: tokenTypeGuard.array().optional(),
|
||||
scope: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const revokeTokenLogPayloadGuard = arbitraryLogPayloadGuard.and(
|
||||
z.object({
|
||||
userId: z.string().optional(),
|
||||
params: z.record(z.string(), z.unknown()).optional(),
|
||||
tokenType: tokenTypeGuard.optional(),
|
||||
grantId: z.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const logPayloadsGuard = z.object({
|
||||
RegisterUsernamePassword: registerUsernamePasswordLogPayloadGuard,
|
||||
RegisterEmailSendPasscode: registerEmailSendPasscodeLogPayloadGuard,
|
||||
RegisterEmail: registerEmailLogPayloadGuard,
|
||||
RegisterSmsSendPasscode: registerSmsSendPasscodeLogPayloadGuard,
|
||||
RegisterSms: registerSmsLogPayloadGuard,
|
||||
RegisterSocialBind: registerSocialBindLogPayloadGuard,
|
||||
RegisterSocial: registerSocialLogPayloadGuard,
|
||||
SignInUsernamePassword: signInUsernamePasswordLogPayloadGuard,
|
||||
SignInEmailPassword: signInEmailPasswordLogPayloadGuard,
|
||||
SignInSmsPassword: signInSmsPasswordLogPayloadGuard,
|
||||
SignInEmailSendPasscode: signInEmailSendPasscodeLogPayloadGuard,
|
||||
SignInEmail: signInEmailLogPayloadGuard,
|
||||
SignInSmsSendPasscode: signInSmsSendPasscodeLogPayloadGuard,
|
||||
SignInSms: signInSmsLogPayloadGuard,
|
||||
SignInSocialBind: signInSocialBindLogPayloadGuard,
|
||||
SignInSocial: signInSocialLogPayloadGuard,
|
||||
ForgotPasswordSmsSendPasscode: forgotPasswordSmsSendPasscodeLogPayloadGuard,
|
||||
ForgotPasswordSms: forgotPasswordSmsLogPayloadGuard,
|
||||
ForgotPasswordEmailSendPasscode: forgotPasswordEmailSendPasscodeLogPayloadGuard,
|
||||
ForgotPasswordEmail: forgotPasswordEmailLogPayloadGuard,
|
||||
ForgotPasswordReset: forgotPasswordResetLogPayloadGuard,
|
||||
ContinueEmailSendPasscode: continueEmailSendPasscodeLogPayloadGuard,
|
||||
ContinueSmsSendPasscode: continueSmsSendPasscodeLogPayloadGuard,
|
||||
ContinueEmail: continueEmailLogPayloadGuard,
|
||||
ContinueSms: continueSmsLogPayloadGuard,
|
||||
CodeExchangeToken: exchangeTokenLogPayloadGuard,
|
||||
RefreshTokenExchangeToken: exchangeTokenLogPayloadGuard,
|
||||
RevokeToken: revokeTokenLogPayloadGuard,
|
||||
});
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export type LogPayloads = z.infer<typeof logPayloadsGuard>;
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export const logTypeGuard = logPayloadsGuard.keyof();
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export type LogType = z.infer<typeof logTypeGuard>;
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export type LogPayload = LogPayloads[LogType];
|
||||
|
||||
/** @deprecated This will be removed soon. Use log types that can be directly imported from `@logto/schemas` instead. */
|
||||
export type LogDto = Omit<Log, 'payload'> & {
|
||||
payload: {
|
||||
userId?: string;
|
||||
applicationId?: string;
|
||||
result?: string;
|
||||
userAgent?: string;
|
||||
ip?: string;
|
||||
};
|
||||
};
|
|
@ -1,6 +1,3 @@
|
|||
import type { ZodType } from 'zod';
|
||||
import { z } from 'zod';
|
||||
|
||||
import type * as hook from './hook.js';
|
||||
import type * as interaction from './interaction.js';
|
||||
import type * as token from './token.js';
|
||||
|
@ -20,35 +17,3 @@ export const LogKeyUnknown = 'Unknown';
|
|||
* @see {@link token.LogKey} for token log keys.
|
||||
**/
|
||||
export type LogKey = typeof LogKeyUnknown | interaction.LogKey | token.LogKey | hook.LogKey;
|
||||
|
||||
export enum LogResult {
|
||||
Success = 'Success',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
/**
|
||||
* The basic log context type. It's more about a type hint instead of forcing the log shape.
|
||||
*
|
||||
* Note when setting up a log function, the type of log key in function arguments should be `LogKey`.
|
||||
* Here we use `string` to make it compatible with the Zod guard.
|
||||
**/
|
||||
export type LogContextPayload = {
|
||||
key: string;
|
||||
result: LogResult;
|
||||
error?: Record<string, unknown> | string;
|
||||
ip?: string;
|
||||
userAgent?: string;
|
||||
applicationId?: string;
|
||||
sessionId?: string;
|
||||
};
|
||||
|
||||
/** Type guard for {@link LogContextPayload} */
|
||||
export const logContextGuard: ZodType<LogContextPayload> = z.object({
|
||||
key: z.string(),
|
||||
result: z.nativeEnum(LogResult),
|
||||
error: z.record(z.string(), z.unknown()).or(z.string()).optional(),
|
||||
ip: z.string().optional(),
|
||||
userAgent: z.string().optional(),
|
||||
applicationId: z.string().optional(),
|
||||
sessionId: z.string().optional(),
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ create table logs
|
|||
(
|
||||
id varchar(21) not null,
|
||||
key varchar(128) not null,
|
||||
payload jsonb /* @use ArbitraryObject */ not null default '{}'::jsonb,
|
||||
payload jsonb /* @use LogContextPayload */ not null default '{}'::jsonb,
|
||||
created_at timestamptz not null default (now()),
|
||||
primary key (id)
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue