activity.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { getModelSafely } from '@growi/core';
  2. import mongoose from 'mongoose';
  3. import { IActivity } from '~/interfaces/activity';
  4. import { IPage } from '~/interfaces/page';
  5. import Activity from '~/server/models/activity';
  6. import loggerFactory from '../../utils/logger';
  7. import Crowi from '../crowi';
  8. const logger = loggerFactory('growi:service:ActivityService');
  9. type UpdateActivityParameterType = Omit<IActivity, 'user' | 'createdAt' | 'ip' | 'endpoint'>
  10. class ActivityService {
  11. crowi!: Crowi;
  12. activityEvent: any;
  13. constructor(crowi: Crowi) {
  14. this.crowi = crowi;
  15. this.activityEvent = crowi.event('activity');
  16. this.updateByParameters = this.updateByParameters.bind(this);
  17. this.initActivityEventListeners();
  18. }
  19. initActivityEventListeners(): void {
  20. this.activityEvent.on('update', async(activityId: string, parameters: UpdateActivityParameterType, target?: IPage) => {
  21. // update activity
  22. let activity: IActivity;
  23. try {
  24. activity = await this.updateByParameters(activityId, parameters);
  25. }
  26. catch (err) {
  27. logger.error('Update activity failed', err);
  28. return;
  29. }
  30. this.activityEvent.emit('updated', activity, target);
  31. });
  32. }
  33. createTtlIndex = async function() {
  34. const configManager = this.crowi.configManager;
  35. const activityExpirationSeconds = configManager != null ? configManager.getConfig('crowi', 'app:activityExpirationSeconds') : 2592000;
  36. const collection = mongoose.connection.collection('activities');
  37. try {
  38. const targetField = 'createdAt_1';
  39. const indexes = await collection.indexes();
  40. const foundCreatedAt = indexes.find(i => i.name === targetField);
  41. const isNotSpec = foundCreatedAt?.expireAfterSeconds == null || foundCreatedAt?.expireAfterSeconds !== activityExpirationSeconds;
  42. const shoudDropIndex = foundCreatedAt != null && isNotSpec;
  43. const shoudCreateIndex = foundCreatedAt == null || shoudDropIndex;
  44. if (shoudDropIndex) {
  45. await collection.dropIndex(targetField);
  46. }
  47. if (shoudCreateIndex) {
  48. await collection.createIndex({ createdAt: 1 }, { expireAfterSeconds: activityExpirationSeconds });
  49. }
  50. }
  51. catch (err) {
  52. logger.error('Failed to create TTL Index', err);
  53. throw err;
  54. }
  55. };
  56. /**
  57. * @param {object} parameters
  58. * @return {Promise}
  59. */
  60. createByParameters = function(parameters) {
  61. const Activity = getModelSafely('Activity') || require('../models/activity')(this.crowi);
  62. return Activity.create(parameters);
  63. };
  64. updateByParameters = async function(activityId: string, parameters: UpdateActivityParameterType): Promise<IActivity> {
  65. const activity = await Activity.findOneAndUpdate({ _id: activityId }, parameters, { new: true }) as unknown as IActivity;
  66. return activity;
  67. };
  68. /**
  69. * @param {User} user
  70. * @return {Promise}
  71. */
  72. findByUser = function(user) {
  73. return this.find({ user }).sort({ createdAt: -1 }).exec();
  74. };
  75. }
  76. module.exports = ActivityService;