mirror of
https://github.com/logto-io/logto.git
synced 2025-01-27 21:39:16 -05:00
feat(schema): user logs (#137)
* feat(schema): user logs * fix(core): use z.object * fix(core): add log result type * fix: comments in sql * fix: user_log_type and user_log_result
This commit is contained in:
parent
61edd16798
commit
acdbc5db56
7 changed files with 84 additions and 3 deletions
|
@ -5,6 +5,14 @@ export enum ApplicationType {
|
|||
SPA = 'SPA',
|
||||
Traditional = 'Traditional',
|
||||
}
|
||||
export enum UserLogType {
|
||||
SignInUsernameAndPassword = 'SignInUsernameAndPassword',
|
||||
ExchangeAccessToken = 'ExchangeAccessToken',
|
||||
}
|
||||
export enum UserLogResult {
|
||||
Success = 'Success',
|
||||
Failed = 'Failed',
|
||||
}
|
||||
export enum PasswordEncryptionMethod {
|
||||
SaltAndPepper = 'SaltAndPepper',
|
||||
}
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
export * from './custom-types';
|
||||
export * from './application';
|
||||
export * from './oidc-model-instance';
|
||||
export * from './user-log';
|
||||
export * from './user';
|
||||
|
|
39
packages/schemas/src/db-entries/user-log.ts
Normal file
39
packages/schemas/src/db-entries/user-log.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
|
||||
import { z } from 'zod';
|
||||
|
||||
import { UserLogPayload, userLogPayloadGuard, GeneratedSchema, Guard } from '../foundations';
|
||||
import { UserLogType, UserLogResult } from './custom-types';
|
||||
|
||||
export type UserLogDBEntry = {
|
||||
id: string;
|
||||
userId: string;
|
||||
type: UserLogType;
|
||||
result: UserLogResult;
|
||||
payload: UserLogPayload;
|
||||
createdAt: number;
|
||||
};
|
||||
|
||||
const guard: Guard<UserLogDBEntry> = z.object({
|
||||
id: z.string(),
|
||||
userId: z.string(),
|
||||
type: z.nativeEnum(UserLogType),
|
||||
result: z.nativeEnum(UserLogResult),
|
||||
payload: userLogPayloadGuard,
|
||||
createdAt: z.number(),
|
||||
});
|
||||
|
||||
export const UserLogs: GeneratedSchema<UserLogDBEntry> = Object.freeze({
|
||||
table: 'user_logs',
|
||||
tableSingular: 'user_log',
|
||||
fields: {
|
||||
id: 'id',
|
||||
userId: 'user_id',
|
||||
type: 'type',
|
||||
result: 'result',
|
||||
payload: 'payload',
|
||||
createdAt: 'created_at',
|
||||
},
|
||||
fieldKeys: ['id', 'userId', 'type', 'result', 'payload', 'createdAt'],
|
||||
guard,
|
||||
});
|
|
@ -21,3 +21,13 @@ export const oidcClientMetadataGuard = z.object({
|
|||
});
|
||||
|
||||
export type OidcClientMetadata = z.infer<typeof oidcClientMetadataGuard>;
|
||||
|
||||
export const userLogPayloadGuard = z.object({
|
||||
ip: z.string().optional(),
|
||||
userAgent: z.string().optional(),
|
||||
applicationId: z.string().optional(),
|
||||
applicationName: z.string().optional(),
|
||||
details: z.object({}).optional(), // NOT intend to be parsed
|
||||
});
|
||||
|
||||
export type UserLogPayload = z.infer<typeof userLogPayloadGuard>;
|
||||
|
|
|
@ -11,7 +11,13 @@ import pluralize from 'pluralize';
|
|||
|
||||
import { generateSchema } from './schema';
|
||||
import { FileData, Table, Field, Type, GeneratedType, TableWithType } from './types';
|
||||
import { findFirstParentheses, getType, normalizeWhitespaces, removeParentheses } from './utils';
|
||||
import {
|
||||
findFirstParentheses,
|
||||
getType,
|
||||
normalizeWhitespaces,
|
||||
removeParentheses,
|
||||
removeUnrecognizedComments,
|
||||
} from './utils';
|
||||
|
||||
const directory = 'tables';
|
||||
|
||||
|
@ -25,7 +31,8 @@ const generate = async () => {
|
|||
.map<Promise<[string, FileData]>>(async (file) => {
|
||||
const statements = (await fs.readFile(path.join(directory, file), { encoding: 'utf-8' }))
|
||||
.split(';')
|
||||
.map((value) => normalizeWhitespaces(value));
|
||||
.map((value) => normalizeWhitespaces(value))
|
||||
.map((value) => removeUnrecognizedComments(value));
|
||||
const tables = statements
|
||||
.filter((value) => value.toLowerCase().startsWith('create table'))
|
||||
.map((value) => findFirstParentheses(value))
|
||||
|
@ -55,7 +62,6 @@ const generate = async () => {
|
|||
const required = restLowercased.includes('not null');
|
||||
const primitiveType = getType(type);
|
||||
const tsType = /\/\* @use (.*) \*\//.exec(restJoined)?.[1];
|
||||
|
||||
assert(
|
||||
!(!primitiveType && tsType),
|
||||
`TS type can only be applied on primitive types, found ${
|
||||
|
|
|
@ -2,6 +2,10 @@ import { Optional } from '@silverhand/essentials';
|
|||
|
||||
export const normalizeWhitespaces = (string: string): string => string.replace(/\s+/g, ' ').trim();
|
||||
|
||||
// Remove all comments not start with @
|
||||
export const removeUnrecognizedComments = (string: string): string =>
|
||||
string.replace(/\/\*(?!\s@)[^*]+\*\//g, '');
|
||||
|
||||
const getCountDelta = (value: string): number => {
|
||||
if (value === '(') {
|
||||
return 1;
|
||||
|
|
13
packages/schemas/tables/user_logs.sql
Normal file
13
packages/schemas/tables/user_logs.sql
Normal file
|
@ -0,0 +1,13 @@
|
|||
create type user_log_type as enum ('SignInUsernameAndPassword', 'ExchangeAccessToken');
|
||||
|
||||
create type user_log_result as enum ('Success', 'Failed');
|
||||
|
||||
create table user_logs (
|
||||
id varchar(24) not null,
|
||||
user_id varchar(24) not null,
|
||||
type user_log_type not null,
|
||||
result user_log_result not null, /* not using boolean, may have more result types in the future */
|
||||
payload jsonb /* @use UserLogPayload */ not null,
|
||||
created_at timestamptz not null default(now()),
|
||||
primary key (id)
|
||||
);
|
Loading…
Add table
Reference in a new issue