| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- const OError = require('@overleaf/o-error')
- const logger = require('@overleaf/logger')
- const { UserAuditLogEntry } = require('../../models/UserAuditLogEntry')
- const { callbackify } = require('util')
- const SubscriptionLocator = require('../Subscription/SubscriptionLocator')
- function _canHaveNoIpAddressId(operation, info) {
- if (operation === 'join-group-subscription') return true
- if (operation === 'leave-group-subscription') return true
- if (operation === 'must-reset-password-set') return true
- if (operation === 'remove-email' && info.script) return true
- if (operation === 'release-managed-user' && info.script) return true
- if (operation === 'unlink-dropbox' && info.batch) return true
- return false
- }
- function _canHaveNoInitiatorId(operation, info) {
- if (operation === 'reset-password') return true
- if (operation === 'unlink-sso' && info.providerId === 'collabratec')
- return true
- if (operation === 'unlink-sso' && info.script === true) return true
- if (operation === 'unlink-institution-sso-not-migrated') return true
- if (operation === 'remove-email' && info.script) return true
- if (operation === 'join-group-subscription') return true
- if (operation === 'leave-group-subscription') return true
- if (operation === 'must-reset-password-set') return true
- if (operation === 'must-reset-password-unset') return true
- if (operation === 'account-suspension' && info.script) return true
- if (operation === 'release-managed-user' && info.script) return true
- }
- // events that are visible to managed user admins in Group Audit Logs view
- const MANAGED_GROUP_USER_EVENTS = ['login', 'reset-password', 'update-password']
- /**
- * Add an audit log entry
- *
- * The entry should include at least the following fields:
- *
- * - userId: the user on behalf of whom the operation was performed
- * - operation: a string identifying the type of operation
- * - initiatorId: who performed the operation
- * - ipAddress: the IP address of the initiator
- * - info: an object detailing what happened
- */
- async function addEntry(userId, operation, initiatorId, ipAddress, info = {}) {
- if (!operation) {
- throw new OError('missing operation for audit log', {
- initiatorId,
- ipAddress,
- })
- }
- if (!ipAddress && !_canHaveNoIpAddressId(operation, info)) {
- throw new OError('missing ipAddress for audit log', {
- operation,
- initiatorId,
- })
- }
- if (!initiatorId && !_canHaveNoInitiatorId(operation, info)) {
- throw new OError('missing initiatorId for audit log', {
- operation,
- ipAddress,
- })
- }
- const entry = {
- userId,
- operation,
- initiatorId,
- info,
- ipAddress,
- }
- if (MANAGED_GROUP_USER_EVENTS.includes(operation)) {
- try {
- const managedSubscription =
- await SubscriptionLocator.promises.getUniqueManagedSubscriptionMemberOf(
- userId
- )
- if (managedSubscription) {
- entry.managedSubscriptionId = managedSubscription._id
- }
- } catch (err) {
- logger.error({ err, userId }, 'failed to lookup managed subscription')
- }
- }
- await UserAuditLogEntry.create(entry)
- }
- const UserAuditLogHandler = {
- MANAGED_GROUP_USER_EVENTS,
- addEntry: callbackify(addEntry),
- promises: {
- addEntry,
- },
- }
- module.exports = UserAuditLogHandler
|