mirror of
https://github.com/logto-io/logto.git
synced 2025-01-20 21:32:31 -05:00
Merge pull request #2681 from logto-io/gao-refactor-log-types-2
refactor: log types 2
This commit is contained in:
commit
caa75422ad
22 changed files with 88 additions and 44 deletions
|
@ -8,13 +8,13 @@ import { logEventTitle } from '@/consts/logs';
|
||||||
import * as styles from './index.module.scss';
|
import * as styles from './index.module.scss';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
type: string;
|
eventKey: string;
|
||||||
isSuccess: boolean;
|
isSuccess: boolean;
|
||||||
to?: string;
|
to?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const EventName = ({ type, isSuccess, to }: Props) => {
|
const EventName = ({ eventKey, isSuccess, to }: Props) => {
|
||||||
const title = logEventTitle[type] ?? type;
|
const title = logEventTitle[eventKey] ?? eventKey;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.eventName}>
|
<div className={styles.eventName}>
|
||||||
|
|
|
@ -115,7 +115,7 @@ const AuditLogTable = ({ userId }: Props) => {
|
||||||
)}
|
)}
|
||||||
{isLoading && <TableLoading columns={tableColumnCount} />}
|
{isLoading && <TableLoading columns={tableColumnCount} />}
|
||||||
{logs?.length === 0 && <TableEmpty columns={tableColumnCount} />}
|
{logs?.length === 0 && <TableEmpty columns={tableColumnCount} />}
|
||||||
{logs?.map(({ type, payload, createdAt, id }) => (
|
{logs?.map(({ key, payload, createdAt, id }) => (
|
||||||
<tr
|
<tr
|
||||||
key={id}
|
key={id}
|
||||||
className={tableStyles.clickable}
|
className={tableStyles.clickable}
|
||||||
|
@ -124,7 +124,7 @@ const AuditLogTable = ({ userId }: Props) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<td>
|
<td>
|
||||||
<EventName type={type} isSuccess={payload.result === LogResult.Success} />
|
<EventName eventKey={key} isSuccess={payload.result === LogResult.Success} />
|
||||||
</td>
|
</td>
|
||||||
{showUserColumn && (
|
{showUserColumn && (
|
||||||
<td>{payload.userId ? <UserName userId={payload.userId} /> : '-'}</td>
|
<td>{payload.userId ? <UserName userId={payload.userId} /> : '-'}</td>
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
import type { LogKey } from '@logto/schemas';
|
||||||
|
|
||||||
type LogEventTitle = Record<string, string>;
|
type LogEventTitle = Record<string, string>;
|
||||||
|
|
||||||
export const logEventTitle: LogEventTitle = Object.freeze({
|
/** @deprecated Don't use or update. */
|
||||||
|
const logEventTitleLegacy: LogEventTitle = Object.freeze({
|
||||||
RegisterUsernamePassword: 'Register with username and password',
|
RegisterUsernamePassword: 'Register with username and password',
|
||||||
RegisterEmailSendPasscode: 'Register with email (send passcode)',
|
RegisterEmailSendPasscode: 'Register with email (send passcode)',
|
||||||
RegisterEmail: 'Register with email',
|
RegisterEmail: 'Register with email',
|
||||||
|
@ -19,3 +22,12 @@ export const logEventTitle: LogEventTitle = Object.freeze({
|
||||||
RefreshTokenExchangeToken: 'Exchange token by refresh token',
|
RefreshTokenExchangeToken: 'Exchange token by refresh token',
|
||||||
RevokeToken: 'Revoke token',
|
RevokeToken: 'Revoke token',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const logEventTitle: Record<string, string | undefined> & Partial<Record<LogKey, string>> =
|
||||||
|
Object.freeze({
|
||||||
|
...logEventTitleLegacy,
|
||||||
|
'ExchangeTokenBy.AuthorizationCode': 'Exchange token by auth code',
|
||||||
|
'ExchangeTokenBy.RefreshToken': 'Exchange token by refresh token',
|
||||||
|
'Interaction.Create': 'Interaction started',
|
||||||
|
'Interaction.End': 'Interaction ended',
|
||||||
|
});
|
||||||
|
|
|
@ -57,11 +57,11 @@ const AuditLogDetails = () => {
|
||||||
<Card className={styles.header}>
|
<Card className={styles.header}>
|
||||||
<EventIcon isSuccess={data.payload.result === 'Success'} />
|
<EventIcon isSuccess={data.payload.result === 'Success'} />
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<div className={styles.eventName}>{logEventTitle[data.type]}</div>
|
<div className={styles.eventName}>{logEventTitle[data.key]}</div>
|
||||||
<div className={styles.basicInfo}>
|
<div className={styles.basicInfo}>
|
||||||
<div className={styles.infoItem}>
|
<div className={styles.infoItem}>
|
||||||
<div className={styles.label}>{t('log_details.event_type')}</div>
|
<div className={styles.label}>{t('log_details.event_key')}</div>
|
||||||
<div>{data.type}</div>
|
<div>{data.key}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.infoItem}>
|
<div className={styles.infoItem}>
|
||||||
<div className={styles.label}>{t('log_details.application')}</div>
|
<div className={styles.label}>{t('log_details.application')}</div>
|
||||||
|
|
|
@ -58,7 +58,7 @@ describe('koaLog middleware', () => {
|
||||||
|
|
||||||
expect(insertLog).toBeCalledWith({
|
expect(insertLog).toBeCalledWith({
|
||||||
id: nanoIdMock,
|
id: nanoIdMock,
|
||||||
type,
|
key: type,
|
||||||
payload: {
|
payload: {
|
||||||
...mockPayload,
|
...mockPayload,
|
||||||
...additionalMockPayload,
|
...additionalMockPayload,
|
||||||
|
@ -105,7 +105,7 @@ describe('koaLog middleware', () => {
|
||||||
|
|
||||||
expect(insertLog).toBeCalledWith({
|
expect(insertLog).toBeCalledWith({
|
||||||
id: nanoIdMock,
|
id: nanoIdMock,
|
||||||
type,
|
key: type,
|
||||||
payload: {
|
payload: {
|
||||||
...mockPayload,
|
...mockPayload,
|
||||||
result: LogResult.Error,
|
result: LogResult.Error,
|
||||||
|
@ -139,7 +139,7 @@ describe('koaLog middleware', () => {
|
||||||
|
|
||||||
expect(insertLog).toBeCalledWith({
|
expect(insertLog).toBeCalledWith({
|
||||||
id: nanoIdMock,
|
id: nanoIdMock,
|
||||||
type,
|
key: type,
|
||||||
payload: {
|
payload: {
|
||||||
...mockPayload,
|
...mockPayload,
|
||||||
result: LogResult.Error,
|
result: LogResult.Error,
|
||||||
|
|
|
@ -71,7 +71,7 @@ const initLogger = (basePayload?: Readonly<BaseLogPayload>) => {
|
||||||
|
|
||||||
await insertLog({
|
await insertLog({
|
||||||
id: nanoid(),
|
id: nanoid(),
|
||||||
type: logger.type,
|
key: logger.type,
|
||||||
payload: {
|
payload: {
|
||||||
...logger.basePayload,
|
...logger.basePayload,
|
||||||
...logger.payload,
|
...logger.payload,
|
||||||
|
|
|
@ -54,7 +54,7 @@ describe('koaAuditLog middleware', () => {
|
||||||
|
|
||||||
expect(insertLog).toBeCalledWith({
|
expect(insertLog).toBeCalledWith({
|
||||||
id: nanoIdMock,
|
id: nanoIdMock,
|
||||||
type: logKey,
|
key: logKey,
|
||||||
payload: {
|
payload: {
|
||||||
...mockPayload,
|
...mockPayload,
|
||||||
...additionalMockPayload,
|
...additionalMockPayload,
|
||||||
|
@ -93,12 +93,12 @@ describe('koaAuditLog middleware', () => {
|
||||||
|
|
||||||
expect(insertLog).toHaveBeenCalledWith({
|
expect(insertLog).toHaveBeenCalledWith({
|
||||||
id: nanoIdMock,
|
id: nanoIdMock,
|
||||||
type: logKey,
|
key: logKey,
|
||||||
payload: basePayload,
|
payload: basePayload,
|
||||||
});
|
});
|
||||||
expect(insertLog).toHaveBeenCalledWith({
|
expect(insertLog).toHaveBeenCalledWith({
|
||||||
id: nanoIdMock,
|
id: nanoIdMock,
|
||||||
type: logKey,
|
key: logKey,
|
||||||
payload: {
|
payload: {
|
||||||
...basePayload,
|
...basePayload,
|
||||||
...additionalMockPayload,
|
...additionalMockPayload,
|
||||||
|
@ -139,7 +139,7 @@ describe('koaAuditLog middleware', () => {
|
||||||
|
|
||||||
expect(insertLog).toBeCalledWith({
|
expect(insertLog).toBeCalledWith({
|
||||||
id: nanoIdMock,
|
id: nanoIdMock,
|
||||||
type: logKey,
|
key: logKey,
|
||||||
payload: {
|
payload: {
|
||||||
...mockPayload,
|
...mockPayload,
|
||||||
key: logKey,
|
key: logKey,
|
||||||
|
@ -176,7 +176,7 @@ describe('koaAuditLog middleware', () => {
|
||||||
expect(insertLog).toHaveBeenCalledTimes(2);
|
expect(insertLog).toHaveBeenCalledTimes(2);
|
||||||
expect(insertLog).toBeCalledWith({
|
expect(insertLog).toBeCalledWith({
|
||||||
id: nanoIdMock,
|
id: nanoIdMock,
|
||||||
type: logKey,
|
key: logKey,
|
||||||
payload: {
|
payload: {
|
||||||
...mockPayload,
|
...mockPayload,
|
||||||
key: logKey,
|
key: logKey,
|
||||||
|
|
|
@ -139,7 +139,7 @@ export default function koaAuditLog<
|
||||||
entries.map(async ({ payload }) => {
|
entries.map(async ({ payload }) => {
|
||||||
return insertLog({
|
return insertLog({
|
||||||
id: nanoid(),
|
id: nanoid(),
|
||||||
type: payload.key,
|
key: payload.key,
|
||||||
payload: { ip, userAgent, ...payload },
|
payload: { ip, userAgent, ...payload },
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,15 +12,15 @@ const { table, fields } = convertToIdentifiers(Logs);
|
||||||
export const insertLog = buildInsertInto<CreateLog>(Logs);
|
export const insertLog = buildInsertInto<CreateLog>(Logs);
|
||||||
|
|
||||||
export type LogCondition = {
|
export type LogCondition = {
|
||||||
logType?: string;
|
logKey?: string;
|
||||||
applicationId?: string;
|
applicationId?: string;
|
||||||
userId?: string;
|
userId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildLogConditionSql = (logCondition: LogCondition) =>
|
const buildLogConditionSql = (logCondition: LogCondition) =>
|
||||||
conditionalSql(logCondition, ({ logType, applicationId, userId }) => {
|
conditionalSql(logCondition, ({ logKey, applicationId, userId }) => {
|
||||||
const subConditions = [
|
const subConditions = [
|
||||||
conditionalSql(logType, (logType) => sql`${fields.type}=${logType}`),
|
conditionalSql(logKey, (logKey) => sql`${fields.key}=${logKey}`),
|
||||||
conditionalSql(userId, (userId) => sql`${fields.payload}->>'userId'=${userId}`),
|
conditionalSql(userId, (userId) => sql`${fields.payload}->>'userId'=${userId}`),
|
||||||
conditionalSql(
|
conditionalSql(
|
||||||
applicationId,
|
applicationId,
|
||||||
|
@ -59,7 +59,7 @@ export const getDailyActiveUserCountsByTimeInterval = async (
|
||||||
from ${table}
|
from ${table}
|
||||||
where ${fields.createdAt} > to_timestamp(${startTimeExclusive}::double precision / 1000)
|
where ${fields.createdAt} > to_timestamp(${startTimeExclusive}::double precision / 1000)
|
||||||
and ${fields.createdAt} <= to_timestamp(${endTimeInclusive}::double precision / 1000)
|
and ${fields.createdAt} <= to_timestamp(${endTimeInclusive}::double precision / 1000)
|
||||||
and ${fields.type} like ${`${token.Flow.ExchangeTokenBy}.%`}
|
and ${fields.key} like ${`${token.Flow.ExchangeTokenBy}.%`}
|
||||||
and ${fields.payload}->>'result' = 'Success'
|
and ${fields.payload}->>'result' = 'Success'
|
||||||
group by date(${fields.createdAt})
|
group by date(${fields.createdAt})
|
||||||
`);
|
`);
|
||||||
|
@ -73,6 +73,6 @@ export const countActiveUsersByTimeInterval = async (
|
||||||
from ${table}
|
from ${table}
|
||||||
where ${fields.createdAt} > to_timestamp(${startTimeExclusive}::double precision / 1000)
|
where ${fields.createdAt} > to_timestamp(${startTimeExclusive}::double precision / 1000)
|
||||||
and ${fields.createdAt} <= to_timestamp(${endTimeInclusive}::double precision / 1000)
|
and ${fields.createdAt} <= to_timestamp(${endTimeInclusive}::double precision / 1000)
|
||||||
and ${fields.type} like ${`${token.Flow.ExchangeTokenBy}.%`}
|
and ${fields.key} like ${`${token.Flow.ExchangeTokenBy}.%`}
|
||||||
and ${fields.payload}->>'result' = 'Success'
|
and ${fields.payload}->>'result' = 'Success'
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { createRequester } from '#src/utils/test-utils.js';
|
||||||
|
|
||||||
const { jest } = import.meta;
|
const { jest } = import.meta;
|
||||||
|
|
||||||
const mockBody = { type: 'a', payload: {}, createdAt: 123 };
|
const mockBody = { key: 'a', payload: {}, createdAt: 123 };
|
||||||
const mockLog = { id: '1', ...mockBody };
|
const mockLog = { id: '1', ...mockBody };
|
||||||
const mockLogs = [mockLog, { id: '2', ...mockBody }];
|
const mockLogs = [mockLog, { id: '2', ...mockBody }];
|
||||||
|
|
||||||
|
@ -28,15 +28,15 @@ describe('logRoutes', () => {
|
||||||
it('should call countLogs and findLogs with correct parameters', async () => {
|
it('should call countLogs and findLogs with correct parameters', async () => {
|
||||||
const userId = 'userIdValue';
|
const userId = 'userIdValue';
|
||||||
const applicationId = 'foo';
|
const applicationId = 'foo';
|
||||||
const logType = 'SignInUsernamePassword';
|
const logKey = 'SignInUsernamePassword';
|
||||||
const page = 1;
|
const page = 1;
|
||||||
const pageSize = 5;
|
const pageSize = 5;
|
||||||
|
|
||||||
await logRequest.get(
|
await logRequest.get(
|
||||||
`/logs?userId=${userId}&applicationId=${applicationId}&logType=${logType}&page=${page}&page_size=${pageSize}`
|
`/logs?userId=${userId}&applicationId=${applicationId}&logKey=${logKey}&page=${page}&page_size=${pageSize}`
|
||||||
);
|
);
|
||||||
expect(countLogs).toHaveBeenCalledWith({ userId, applicationId, logType });
|
expect(countLogs).toHaveBeenCalledWith({ userId, applicationId, logKey });
|
||||||
expect(findLogs).toHaveBeenCalledWith(5, 0, { userId, applicationId, logType });
|
expect(findLogs).toHaveBeenCalledWith(5, 0, { userId, applicationId, logKey });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return correct response', async () => {
|
it('should return correct response', async () => {
|
||||||
|
|
|
@ -15,19 +15,19 @@ export default function logRoutes<T extends AuthedRouter>(router: T) {
|
||||||
query: object({
|
query: object({
|
||||||
userId: string().optional(),
|
userId: string().optional(),
|
||||||
applicationId: string().optional(),
|
applicationId: string().optional(),
|
||||||
logType: string().optional(),
|
logKey: string().optional(),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
async (ctx, next) => {
|
async (ctx, next) => {
|
||||||
const { limit, offset } = ctx.pagination;
|
const { limit, offset } = ctx.pagination;
|
||||||
const {
|
const {
|
||||||
query: { userId, applicationId, logType },
|
query: { userId, applicationId, logKey },
|
||||||
} = ctx.guard;
|
} = ctx.guard;
|
||||||
|
|
||||||
// TODO: @Gao refactor like user search
|
// TODO: @Gao refactor like user search
|
||||||
const [{ count }, logs] = await Promise.all([
|
const [{ count }, logs] = await Promise.all([
|
||||||
countLogs({ logType, applicationId, userId }),
|
countLogs({ logKey, applicationId, userId }),
|
||||||
findLogs(limit, offset, { logType, userId, applicationId }),
|
findLogs(limit, offset, { logKey, userId, applicationId }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return totalCount to pagination middleware
|
// Return totalCount to pagination middleware
|
||||||
|
|
|
@ -20,7 +20,7 @@ describe('admin console logs (legacy)', () => {
|
||||||
const logs = await getLogs();
|
const logs = await getLogs();
|
||||||
|
|
||||||
const registerLog = logs.filter(
|
const registerLog = logs.filter(
|
||||||
({ type, payload }) => type === 'RegisterUsernamePassword' && payload.username === username
|
({ key, payload }) => key === 'RegisterUsernamePassword' && payload.username === username
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(registerLog.length).toBeGreaterThan(0);
|
expect(registerLog.length).toBeGreaterThan(0);
|
||||||
|
|
|
@ -3,7 +3,7 @@ const log_details = {
|
||||||
back_to_user: 'Zurück zu {{name}}',
|
back_to_user: 'Zurück zu {{name}}',
|
||||||
success: 'Erfolgreich',
|
success: 'Erfolgreich',
|
||||||
failed: 'Fehlgeschlagen',
|
failed: 'Fehlgeschlagen',
|
||||||
event_type: 'Event Typ',
|
event_key: 'Event Key', // UNTRANSLATED
|
||||||
application: 'Anwendung',
|
application: 'Anwendung',
|
||||||
ip_address: 'IP Adresse',
|
ip_address: 'IP Adresse',
|
||||||
user: 'Benutzer',
|
user: 'Benutzer',
|
||||||
|
|
|
@ -3,7 +3,7 @@ const log_details = {
|
||||||
back_to_user: 'Back to {{name}}',
|
back_to_user: 'Back to {{name}}',
|
||||||
success: 'Success',
|
success: 'Success',
|
||||||
failed: 'Failed',
|
failed: 'Failed',
|
||||||
event_type: 'Event type',
|
event_key: 'Event Key',
|
||||||
application: 'Application',
|
application: 'Application',
|
||||||
ip_address: 'IP address',
|
ip_address: 'IP address',
|
||||||
user: 'User',
|
user: 'User',
|
||||||
|
|
|
@ -3,7 +3,7 @@ const log_details = {
|
||||||
back_to_user: 'Retour à {{name}}',
|
back_to_user: 'Retour à {{name}}',
|
||||||
success: 'Succès',
|
success: 'Succès',
|
||||||
failed: 'Échoué',
|
failed: 'Échoué',
|
||||||
event_type: "Type d'événement",
|
event_key: 'Event Key', // UNTRANSLATED
|
||||||
application: 'Application',
|
application: 'Application',
|
||||||
ip_address: 'Addresse IP',
|
ip_address: 'Addresse IP',
|
||||||
user: 'Utilisateur',
|
user: 'Utilisateur',
|
||||||
|
|
|
@ -3,7 +3,7 @@ const log_details = {
|
||||||
back_to_user: '{{name}}으로 돌아가기',
|
back_to_user: '{{name}}으로 돌아가기',
|
||||||
success: '성공',
|
success: '성공',
|
||||||
failed: '실패',
|
failed: '실패',
|
||||||
event_type: '활동 종류',
|
event_key: 'Event Key', // UNTRANSLATED
|
||||||
application: '어플리케이션',
|
application: '어플리케이션',
|
||||||
ip_address: 'IP 주소',
|
ip_address: 'IP 주소',
|
||||||
user: '사용자',
|
user: '사용자',
|
||||||
|
|
|
@ -3,7 +3,7 @@ const log_details = {
|
||||||
back_to_user: 'Voltar para {{name}}',
|
back_to_user: 'Voltar para {{name}}',
|
||||||
success: 'Sucesso',
|
success: 'Sucesso',
|
||||||
failed: 'Falhou',
|
failed: 'Falhou',
|
||||||
event_type: 'Tipo de evento',
|
event_key: 'Event Key', // UNTRANSLATED
|
||||||
application: 'Aplicativo',
|
application: 'Aplicativo',
|
||||||
ip_address: 'Endereço de IP',
|
ip_address: 'Endereço de IP',
|
||||||
user: 'Usuário',
|
user: 'Usuário',
|
||||||
|
|
|
@ -3,7 +3,7 @@ const log_details = {
|
||||||
back_to_user: 'De volta a {{name}}',
|
back_to_user: 'De volta a {{name}}',
|
||||||
success: 'Sucesso',
|
success: 'Sucesso',
|
||||||
failed: 'Falha',
|
failed: 'Falha',
|
||||||
event_type: 'Tipo de evento',
|
event_key: 'Event Key', // UNTRANSLATED
|
||||||
application: 'Aplicação',
|
application: 'Aplicação',
|
||||||
ip_address: 'Endereço IP',
|
ip_address: 'Endereço IP',
|
||||||
user: 'Utilizador',
|
user: 'Utilizador',
|
||||||
|
|
|
@ -3,7 +3,7 @@ const log_details = {
|
||||||
back_to_user: '{{name}}e geri dön',
|
back_to_user: '{{name}}e geri dön',
|
||||||
success: 'Başarılı',
|
success: 'Başarılı',
|
||||||
failed: 'Başarısız',
|
failed: 'Başarısız',
|
||||||
event_type: 'Etkinlik tipi',
|
event_key: 'Event Key', // UNTRANSLATED
|
||||||
application: 'Uygulama',
|
application: 'Uygulama',
|
||||||
ip_address: 'IP adresi',
|
ip_address: 'IP adresi',
|
||||||
user: 'Kullanıcı',
|
user: 'Kullanıcı',
|
||||||
|
|
|
@ -3,7 +3,7 @@ const log_details = {
|
||||||
back_to_user: '返回 {{name}}',
|
back_to_user: '返回 {{name}}',
|
||||||
success: '成功',
|
success: '成功',
|
||||||
failed: '失败',
|
failed: '失败',
|
||||||
event_type: '事件类型',
|
event_key: 'Event Key', // UNTRANSLATED
|
||||||
application: '应用',
|
application: '应用',
|
||||||
ip_address: 'IP 地址',
|
ip_address: 'IP 地址',
|
||||||
user: '用户',
|
user: '用户',
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { sql } from 'slonik';
|
||||||
|
|
||||||
|
import type { AlterationScript } from '../lib/types/alteration.js';
|
||||||
|
|
||||||
|
const alteration: AlterationScript = {
|
||||||
|
up: async (pool) => {
|
||||||
|
await pool.query(sql`
|
||||||
|
-- Update metadata
|
||||||
|
alter table logs rename column type to key;
|
||||||
|
alter table logs alter column key type varchar(128);
|
||||||
|
alter index logs__type rename to logs__key;
|
||||||
|
|
||||||
|
-- Update token exchange keys
|
||||||
|
update logs set "key" = 'ExchangeTokenBy.AuthorizationCode' where "key" = 'CodeExchangeToken';
|
||||||
|
update logs set "key" = 'ExchangeTokenBy.RefreshToken' where "key" = 'RefreshTokenExchangeToken';
|
||||||
|
`);
|
||||||
|
},
|
||||||
|
down: async (pool) => {
|
||||||
|
await pool.query(sql`
|
||||||
|
-- Update token exchange keys
|
||||||
|
update logs set "key" = 'CodeExchangeToken' where "key" = 'ExchangeTokenBy.AuthorizationCode';
|
||||||
|
update logs set "key" = 'RefreshTokenExchangeToken' where "key" = 'ExchangeTokenBy.RefreshToken';
|
||||||
|
|
||||||
|
-- Update metadata
|
||||||
|
alter table logs alter column key type varchar(64);
|
||||||
|
alter table logs rename column key to type;
|
||||||
|
alter index logs__key rename to logs__type;
|
||||||
|
`);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default alteration;
|
|
@ -1,13 +1,13 @@
|
||||||
create table logs
|
create table logs
|
||||||
(
|
(
|
||||||
id varchar(21) not null,
|
id varchar(21) not null,
|
||||||
type varchar(64) not null,
|
key varchar(128) not null,
|
||||||
payload jsonb /* @use ArbitraryObject */ not null default '{}'::jsonb,
|
payload jsonb /* @use ArbitraryObject */ not null default '{}'::jsonb,
|
||||||
created_at timestamptz not null default (now()),
|
created_at timestamptz not null default (now()),
|
||||||
primary key (id)
|
primary key (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
create index logs__type on logs (type);
|
create index logs__key on logs (key);
|
||||||
create index logs__created_at on logs (created_at);
|
create index logs__created_at on logs (created_at);
|
||||||
create index logs__user_id on logs ((payload->>'user_id') nulls last);
|
create index logs__user_id on logs ((payload->>'user_id') nulls last);
|
||||||
create index logs__application_id on logs ((payload->>'application_id') nulls last);
|
create index logs__application_id on logs ((payload->>'application_id') nulls last);
|
||||||
|
|
Loading…
Add table
Reference in a new issue