| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- import type { IPage } from '@growi/core';
- import mongoose from 'mongoose';
- import {
- IActivity, SupportedActionType, AllSupportedActions, ActionGroupSize,
- AllEssentialActions, AllSmallGroupActions, AllMediumGroupActions, AllLargeGroupActions,
- } from '~/interfaces/activity';
- import Activity, { ActivityDocument } from '~/server/models/activity';
- import loggerFactory from '../../utils/logger';
- import Crowi from '../crowi';
- import type { GeneratePreNotify, GetAdditionalTargetUsers } from './pre-notify';
- const logger = loggerFactory('growi:service:ActivityService');
- const parseActionString = (actionsString: string): SupportedActionType[] => {
- if (actionsString == null) {
- return [];
- }
- const actions = actionsString.split(',').map(value => value.trim());
- return actions.filter(action => (AllSupportedActions as string[]).includes(action)) as SupportedActionType[];
- };
- class ActivityService {
- crowi!: Crowi;
- activityEvent: any;
- constructor(crowi: Crowi) {
- this.crowi = crowi;
- this.activityEvent = crowi.event('activity');
- this.getAvailableActions = this.getAvailableActions.bind(this);
- this.shoudUpdateActivity = this.shoudUpdateActivity.bind(this);
- this.initActivityEventListeners();
- }
- initActivityEventListeners(): void {
- this.activityEvent.on('update', async(
- activityId: string, parameters, target: IPage, generatePreNotify?: GeneratePreNotify, getAdditionalTargetUsers?: GetAdditionalTargetUsers,
- ) => {
- let activity: ActivityDocument;
- const shoudUpdate = this.shoudUpdateActivity(parameters.action);
- if (shoudUpdate) {
- try {
- activity = await Activity.updateByParameters(activityId, parameters);
- }
- catch (err) {
- logger.error('Update activity failed', err);
- return;
- }
- if (generatePreNotify != null) {
- const preNotify = generatePreNotify(activity, getAdditionalTargetUsers);
- this.activityEvent.emit('updated', activity, target, preNotify);
- return;
- }
- this.activityEvent.emit('updated', activity, target);
- }
- });
- }
- getAvailableActions = function(isIncludeEssentialActions = true): SupportedActionType[] {
- const auditLogEnabled = this.crowi.configManager.getConfig('crowi', 'app:auditLogEnabled') || false;
- const auditLogActionGroupSize = this.crowi.configManager.getConfig('crowi', 'app:auditLogActionGroupSize') || ActionGroupSize.Small;
- const auditLogAdditionalActions = this.crowi.configManager.getConfig('crowi', 'app:auditLogAdditionalActions');
- const auditLogExcludeActions = this.crowi.configManager.getConfig('crowi', 'app:auditLogExcludeActions');
- if (!auditLogEnabled) {
- return AllEssentialActions;
- }
- const availableActionsSet = new Set<SupportedActionType>();
- // Set base action group
- switch (auditLogActionGroupSize) {
- case ActionGroupSize.Small:
- AllSmallGroupActions.forEach(action => availableActionsSet.add(action));
- break;
- case ActionGroupSize.Medium:
- AllMediumGroupActions.forEach(action => availableActionsSet.add(action));
- break;
- case ActionGroupSize.Large:
- AllLargeGroupActions.forEach(action => availableActionsSet.add(action));
- break;
- }
- // Add additionalActions
- const additionalActions = parseActionString(auditLogAdditionalActions);
- additionalActions.forEach(action => availableActionsSet.add(action));
- // Delete excludeActions
- const excludeActions = parseActionString(auditLogExcludeActions);
- excludeActions.forEach(action => availableActionsSet.delete(action));
- // Add essentialActions
- if (isIncludeEssentialActions) {
- AllEssentialActions.forEach(action => availableActionsSet.add(action));
- }
- return Array.from(availableActionsSet);
- };
- shoudUpdateActivity = function(action: SupportedActionType): boolean {
- return this.getAvailableActions().includes(action);
- };
- // for GET request
- createActivity = async function(parameters): Promise<IActivity | null> {
- const shoudCreateActivity = this.crowi.activityService.shoudUpdateActivity(parameters.action);
- if (shoudCreateActivity) {
- let activity: IActivity;
- try {
- activity = await Activity.createByParameters(parameters);
- return activity;
- }
- catch (err) {
- logger.error('Create activity failed', err);
- }
- }
- return null;
- };
- createTtlIndex = async function() {
- const configManager = this.crowi.configManager;
- const activityExpirationSeconds = configManager != null ? configManager.getConfig('crowi', 'app:activityExpirationSeconds') : 2592000;
- const collection = mongoose.connection.collection('activities');
- try {
- const targetField = 'createdAt_1';
- const indexes = await collection.indexes();
- const foundCreatedAt = indexes.find(i => i.name === targetField);
- const isNotSpec = foundCreatedAt?.expireAfterSeconds == null || foundCreatedAt?.expireAfterSeconds !== activityExpirationSeconds;
- const shoudDropIndex = foundCreatedAt != null && isNotSpec;
- const shoudCreateIndex = foundCreatedAt == null || shoudDropIndex;
- if (shoudDropIndex) {
- await collection.dropIndex(targetField);
- }
- if (shoudCreateIndex) {
- await collection.createIndex({ createdAt: 1 }, { expireAfterSeconds: activityExpirationSeconds });
- }
- }
- catch (err) {
- logger.error('Failed to create TTL Index', err);
- throw err;
- }
- };
- }
- module.exports = ActivityService;
|