0
Fork 0
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:
Wang Sijie 2021-11-29 15:47:43 +08:00 committed by GitHub
parent 61edd16798
commit acdbc5db56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 84 additions and 3 deletions

View file

@ -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',
}

View file

@ -3,4 +3,5 @@
export * from './custom-types';
export * from './application';
export * from './oidc-model-instance';
export * from './user-log';
export * from './user';

View 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,
});

View file

@ -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>;

View file

@ -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 ${

View file

@ -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;

View 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)
);