feat: implement activity logging for user actions and create activities table
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 44s
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 44s
This commit is contained in:
parent
6c75efbc28
commit
7e2f320b4f
12 changed files with 420 additions and 160 deletions
57
app/models/activity.ts
Normal file
57
app/models/activity.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// app/models/activity.ts
|
||||
import { DateTime } from 'luxon';
|
||||
import { belongsTo, column } from '@adonisjs/lucid/orm';
|
||||
import BaseModel from './base_model.js';
|
||||
import type { BelongsTo } from '@adonisjs/lucid/types/relations';
|
||||
import User from '#models/user';
|
||||
import { SnakeCaseNamingStrategy } from '@adonisjs/lucid/orm';
|
||||
|
||||
export default class Activity extends BaseModel {
|
||||
public static namingStrategy = new SnakeCaseNamingStrategy();
|
||||
public static primaryKey = 'id';
|
||||
public static table = 'activities';
|
||||
|
||||
@column({ isPrimary: true })
|
||||
declare id: number;
|
||||
|
||||
@column()
|
||||
declare type: string;
|
||||
|
||||
@column()
|
||||
declare userId: number | null;
|
||||
|
||||
@column()
|
||||
declare subjectType: string | null;
|
||||
|
||||
@column()
|
||||
declare subjectId: number | null;
|
||||
|
||||
@column()
|
||||
declare description: string;
|
||||
|
||||
// Manual JSON (de)serialization keeps this working on SQLite/MySQL.
|
||||
// On Postgres json/jsonb the driver already parses — drop the `consume`
|
||||
// JSON.parse there to avoid double-handling.
|
||||
// @column({
|
||||
// prepare: (value: Record<string, any> | null) => (value ? JSON.stringify(value) : null),
|
||||
// consume: (value: string | null) => (value ? JSON.parse(value) : null),
|
||||
// })
|
||||
// declare properties: Record<string, any> | null;
|
||||
|
||||
@column()
|
||||
declare properties: Record<string, any> | null;
|
||||
|
||||
@column.dateTime({ autoCreate: true })
|
||||
declare createdAt: DateTime;
|
||||
|
||||
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
||||
declare updatedAt: DateTime;
|
||||
|
||||
// @belongsTo(() => User)
|
||||
// declare user: BelongsTo<typeof User>;
|
||||
|
||||
@belongsTo(() => User, {
|
||||
foreignKey: 'userId',
|
||||
})
|
||||
declare user: BelongsTo<typeof User>;
|
||||
}
|
||||
|
|
@ -5,7 +5,10 @@ import {
|
|||
belongsTo,
|
||||
hasMany,
|
||||
computed,
|
||||
hasOne
|
||||
hasOne,
|
||||
afterCreate,
|
||||
beforeUpdate,
|
||||
afterUpdate,
|
||||
} from '@adonisjs/lucid/orm';
|
||||
import { DateTime } from 'luxon';
|
||||
import dayjs from 'dayjs';
|
||||
|
|
@ -23,10 +26,11 @@ import DatasetIdentifier from './dataset_identifier.js';
|
|||
import Project from './project.js';
|
||||
import DocumentXmlCache from './DocumentXmlCache.js';
|
||||
import DatasetExtension from '#models/traits/dataset_extension';
|
||||
import type { ManyToMany } from "@adonisjs/lucid/types/relations";
|
||||
import type { BelongsTo } from "@adonisjs/lucid/types/relations";
|
||||
import type { HasMany } from "@adonisjs/lucid/types/relations";
|
||||
import type { HasOne } from "@adonisjs/lucid/types/relations";
|
||||
import type { ManyToMany } from '@adonisjs/lucid/types/relations';
|
||||
import type { BelongsTo } from '@adonisjs/lucid/types/relations';
|
||||
import type { HasMany } from '@adonisjs/lucid/types/relations';
|
||||
import type { HasOne } from '@adonisjs/lucid/types/relations';
|
||||
import ActivityLogger from '#services/activity_logger';
|
||||
|
||||
export default class Dataset extends DatasetExtension {
|
||||
public static namingStrategy = new SnakeCaseNamingStrategy();
|
||||
|
|
@ -46,7 +50,7 @@ export default class Dataset extends DatasetExtension {
|
|||
@column({ columnName: 'creating_corporation' })
|
||||
public creating_corporation: string;
|
||||
|
||||
@column.dateTime({
|
||||
@column.dateTime({
|
||||
columnName: 'embargo_date',
|
||||
serialize: (value: Date | null) => {
|
||||
return value ? dayjs(value).format('YYYY-MM-DD') : value;
|
||||
|
|
@ -60,7 +64,7 @@ export default class Dataset extends DatasetExtension {
|
|||
@column({})
|
||||
public language: string;
|
||||
|
||||
@column({columnName: 'publish_id'})
|
||||
@column({ columnName: 'publish_id' })
|
||||
public publish_id: number | null = null;
|
||||
|
||||
@column({})
|
||||
|
|
@ -266,10 +270,12 @@ export default class Dataset extends DatasetExtension {
|
|||
return model || null;
|
||||
}
|
||||
|
||||
static async getMax (column: string) {
|
||||
let dataset = await this.query().max(column + ' as max_publish_id').firstOrFail();
|
||||
static async getMax(column: string) {
|
||||
let dataset = await this.query()
|
||||
.max(column + ' as max_publish_id')
|
||||
.firstOrFail();
|
||||
return dataset.$extras.max_publish_id;
|
||||
}
|
||||
}
|
||||
|
||||
@computed({
|
||||
serializeAs: 'remaining_time',
|
||||
|
|
@ -284,4 +290,34 @@ export default class Dataset extends DatasetExtension {
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// @afterCreate()
|
||||
// static async logUploaded(dataset: Dataset) {
|
||||
// await dataset.preload('titles');
|
||||
|
||||
// await ActivityLogger.log({
|
||||
// type: 'dataset.uploaded',
|
||||
// description: `New publication uploaded: ${dataset.mainTitle ?? 'Untitled'}`,
|
||||
// subjectType: 'Dataset',
|
||||
// subjectId: dataset.id,
|
||||
// });
|
||||
// }
|
||||
|
||||
@beforeUpdate()
|
||||
static capturePublish(dataset: Dataset) {
|
||||
// $dirty is populated here, before persistence
|
||||
(dataset as any).$becamePublished = dataset.$dirty.status !== undefined && dataset.status === 'published';
|
||||
}
|
||||
|
||||
@afterUpdate()
|
||||
static async logPublished(dataset: Dataset) {
|
||||
if ((dataset as any).$becamePublished) {
|
||||
await ActivityLogger.log({
|
||||
type: 'dataset.published',
|
||||
description: `Publication published: ${dataset.mainTitle}`,
|
||||
subjectType: 'Dataset',
|
||||
subjectId: dataset.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import type { ManyToMany } from '@adonisjs/lucid/types/relations';
|
|||
import type { HasMany } from '@adonisjs/lucid/types/relations';
|
||||
import { compose } from '@adonisjs/core/helpers';
|
||||
import BackupCode from './backup_code.js';
|
||||
import Activity from './activity.js';
|
||||
|
||||
const AuthFinder = withAuthFinder(() => hash.use('laravel'), {
|
||||
uids: ['email'],
|
||||
|
|
@ -111,6 +112,11 @@ export default class User extends compose(BaseModel, AuthFinder) {
|
|||
})
|
||||
public backupcodes: HasMany<typeof BackupCode>;
|
||||
|
||||
@hasMany(() => Activity, {
|
||||
foreignKey: 'user_id',
|
||||
})
|
||||
public activities: HasMany<typeof Activity>;
|
||||
|
||||
@computed({
|
||||
serializeAs: 'is_admin',
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue