mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #15672 from overleaf/mj-group-subscription-audit-revival
[web] Add audit logs when user joins or leaves group subscription GitOrigin-RevId: d64425f5a2434c60c89c297c9a51acae3b96c31e
This commit is contained in:
parent
7c8014d791
commit
6e74a65758
8 changed files with 341 additions and 23 deletions
|
@ -3,27 +3,44 @@ const OError = require('@overleaf/o-error')
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
const SubscriptionLocator = require('./SubscriptionLocator')
|
const SubscriptionLocator = require('./SubscriptionLocator')
|
||||||
const SessionManager = require('../Authentication/SessionManager')
|
const SessionManager = require('../Authentication/SessionManager')
|
||||||
|
const UserAuditLogHandler = require('../User/UserAuditLogHandler')
|
||||||
|
|
||||||
function removeUserFromGroup(req, res, next) {
|
function removeUserFromGroup(req, res, next) {
|
||||||
const subscription = req.entity
|
const subscription = req.entity
|
||||||
const userToRemoveId = req.params.user_id
|
const userToRemoveId = req.params.user_id
|
||||||
|
const loggedInUserId = SessionManager.getLoggedInUserId(req.session)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ subscriptionId: subscription._id, userToRemoveId },
|
{ subscriptionId: subscription._id, userToRemoveId },
|
||||||
'removing user from group subscription'
|
'removing user from group subscription'
|
||||||
)
|
)
|
||||||
SubscriptionGroupHandler.removeUserFromGroup(
|
UserAuditLogHandler.addEntry(
|
||||||
subscription._id,
|
|
||||||
userToRemoveId,
|
userToRemoveId,
|
||||||
function (error) {
|
'remove-from-group-subscription',
|
||||||
if (error) {
|
loggedInUserId,
|
||||||
OError.tag(error, 'error removing user from group', {
|
req.ip,
|
||||||
|
{ subscriptionId: subscription._id },
|
||||||
|
function (auditLogError) {
|
||||||
|
if (auditLogError) {
|
||||||
|
OError.tag(auditLogError, 'error adding audit log entry', {
|
||||||
|
userToRemoveId,
|
||||||
subscriptionId: subscription._id,
|
subscriptionId: subscription._id,
|
||||||
userToRemove_id: userToRemoveId,
|
|
||||||
})
|
})
|
||||||
return next(error)
|
return next(auditLogError)
|
||||||
}
|
}
|
||||||
|
SubscriptionGroupHandler.removeUserFromGroup(
|
||||||
res.sendStatus(200)
|
subscription._id,
|
||||||
|
userToRemoveId,
|
||||||
|
function (error) {
|
||||||
|
if (error) {
|
||||||
|
OError.tag(error, 'error removing user from group', {
|
||||||
|
subscriptionId: subscription._id,
|
||||||
|
userToRemove_id: userToRemoveId,
|
||||||
|
})
|
||||||
|
return next(error)
|
||||||
|
}
|
||||||
|
res.sendStatus(200)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -38,18 +55,34 @@ function removeSelfFromGroup(req, res, next) {
|
||||||
return next(error)
|
return next(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
SubscriptionGroupHandler.removeUserFromGroup(
|
UserAuditLogHandler.addEntry(
|
||||||
subscription._id,
|
|
||||||
userToRemoveId,
|
userToRemoveId,
|
||||||
function (error) {
|
'remove-from-group-subscription',
|
||||||
if (error) {
|
userToRemoveId,
|
||||||
logger.err(
|
req.ip,
|
||||||
{ err: error, userToRemoveId, subscriptionId },
|
{ subscriptionId: subscription._id },
|
||||||
'error removing self from group'
|
function (auditLogError) {
|
||||||
)
|
if (auditLogError) {
|
||||||
return res.sendStatus(500)
|
OError.tag(auditLogError, 'error adding audit log entry', {
|
||||||
|
userToRemoveId,
|
||||||
|
subscriptionId,
|
||||||
|
})
|
||||||
|
return next(auditLogError)
|
||||||
}
|
}
|
||||||
res.sendStatus(200)
|
SubscriptionGroupHandler.removeUserFromGroup(
|
||||||
|
subscription._id,
|
||||||
|
userToRemoveId,
|
||||||
|
function (error) {
|
||||||
|
if (error) {
|
||||||
|
logger.err(
|
||||||
|
{ err: error, userToRemoveId, subscriptionId },
|
||||||
|
'error removing self from group'
|
||||||
|
)
|
||||||
|
return res.sendStatus(500)
|
||||||
|
}
|
||||||
|
res.sendStatus(200)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ const AnalyticsManager = require('../Analytics/AnalyticsManager')
|
||||||
const { DeletedSubscription } = require('../../models/DeletedSubscription')
|
const { DeletedSubscription } = require('../../models/DeletedSubscription')
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
const Features = require('../../infrastructure/Features')
|
const Features = require('../../infrastructure/Features')
|
||||||
|
const UserAuditLogHandler = require('../User/UserAuditLogHandler')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the admin of the given subscription.
|
* Change the admin of the given subscription.
|
||||||
|
@ -59,6 +60,13 @@ async function syncSubscription(
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addUserToGroup(subscriptionId, userId) {
|
async function addUserToGroup(subscriptionId, userId) {
|
||||||
|
await UserAuditLogHandler.promises.addEntry(
|
||||||
|
userId,
|
||||||
|
'join-group-subscription',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{ subscriptionId }
|
||||||
|
)
|
||||||
await Subscription.updateOne(
|
await Subscription.updateOne(
|
||||||
{ _id: subscriptionId },
|
{ _id: subscriptionId },
|
||||||
{ $addToSet: { member_ids: userId } }
|
{ $addToSet: { member_ids: userId } }
|
||||||
|
@ -73,6 +81,13 @@ async function addUserToGroup(subscriptionId, userId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function removeUserFromGroup(subscriptionId, userId) {
|
async function removeUserFromGroup(subscriptionId, userId) {
|
||||||
|
await UserAuditLogHandler.promises.addEntry(
|
||||||
|
userId,
|
||||||
|
'leave-group-subscription',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{ subscriptionId }
|
||||||
|
)
|
||||||
await Subscription.updateOne(
|
await Subscription.updateOne(
|
||||||
{ _id: subscriptionId },
|
{ _id: subscriptionId },
|
||||||
{ $pull: { member_ids: userId } }
|
{ $pull: { member_ids: userId } }
|
||||||
|
@ -97,6 +112,17 @@ async function removeUserFromAllGroups(userId) {
|
||||||
}
|
}
|
||||||
const subscriptionIds = subscriptions.map(sub => sub._id)
|
const subscriptionIds = subscriptions.map(sub => sub._id)
|
||||||
const removeOperation = { $pull: { member_ids: userId } }
|
const removeOperation = { $pull: { member_ids: userId } }
|
||||||
|
|
||||||
|
for (const subscriptionId of subscriptionIds) {
|
||||||
|
await UserAuditLogHandler.promises.addEntry(
|
||||||
|
userId,
|
||||||
|
'leave-group-subscription',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{ subscriptionId }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Subscription.updateMany(
|
await Subscription.updateMany(
|
||||||
{ _id: subscriptionIds },
|
{ _id: subscriptionIds },
|
||||||
removeOperation
|
removeOperation
|
||||||
|
|
|
@ -13,6 +13,7 @@ const PermissionsManager = require('../Authorization/PermissionsManager')
|
||||||
const EmailHandler = require('../Email/EmailHandler')
|
const EmailHandler = require('../Email/EmailHandler')
|
||||||
const { RateLimiter } = require('../../infrastructure/RateLimiter')
|
const { RateLimiter } = require('../../infrastructure/RateLimiter')
|
||||||
const Modules = require('../../infrastructure/Modules')
|
const Modules = require('../../infrastructure/Modules')
|
||||||
|
const UserAuditLogHandler = require('../User/UserAuditLogHandler')
|
||||||
|
|
||||||
const rateLimiters = {
|
const rateLimiters = {
|
||||||
resendGroupInvite: new RateLimiter('resend-group-invite', {
|
resendGroupInvite: new RateLimiter('resend-group-invite', {
|
||||||
|
@ -198,6 +199,21 @@ async function acceptInvite(req, res, next) {
|
||||||
await Modules.promises.hooks.fire('hasGroupSSOEnabled', subscription)
|
await Modules.promises.hooks.fire('hasGroupSSOEnabled', subscription)
|
||||||
)?.[0]
|
)?.[0]
|
||||||
|
|
||||||
|
try {
|
||||||
|
await UserAuditLogHandler.promises.addEntry(
|
||||||
|
userId,
|
||||||
|
'accept-group-invitation',
|
||||||
|
userId,
|
||||||
|
req.ip,
|
||||||
|
{ subscriptionId: subscription._id }
|
||||||
|
)
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(
|
||||||
|
{ err: e, userId, subscriptionId: subscription._id },
|
||||||
|
'error adding audit log entry'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
res.json({ groupSSOActive })
|
res.json({ groupSSOActive })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,20 @@ const OError = require('@overleaf/o-error')
|
||||||
const { UserAuditLogEntry } = require('../../models/UserAuditLogEntry')
|
const { UserAuditLogEntry } = require('../../models/UserAuditLogEntry')
|
||||||
const { callbackify } = require('util')
|
const { callbackify } = require('util')
|
||||||
|
|
||||||
|
function _canHaveNoIpAddressId(operation) {
|
||||||
|
if (operation === 'join-group-subscription') return true
|
||||||
|
if (operation === 'leave-group-subscription') return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
function _canHaveNoInitiatorId(operation, info) {
|
function _canHaveNoInitiatorId(operation, info) {
|
||||||
if (operation === 'reset-password') return true
|
if (operation === 'reset-password') return true
|
||||||
if (operation === 'unlink-sso' && info.providerId === 'collabratec')
|
if (operation === 'unlink-sso' && info.providerId === 'collabratec')
|
||||||
return true
|
return true
|
||||||
if (operation === 'unlink-institution-sso-not-migrated') return true
|
if (operation === 'unlink-institution-sso-not-migrated') return true
|
||||||
if (operation === 'remove-email' && info.script) return true
|
if (operation === 'remove-email' && info.script) return true
|
||||||
|
if (operation === 'join-group-subscription') return true
|
||||||
|
if (operation === 'leave-group-subscription') return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,12 +30,19 @@ function _canHaveNoInitiatorId(operation, info) {
|
||||||
* - info: an object detailing what happened
|
* - info: an object detailing what happened
|
||||||
*/
|
*/
|
||||||
async function addEntry(userId, operation, initiatorId, ipAddress, info = {}) {
|
async function addEntry(userId, operation, initiatorId, ipAddress, info = {}) {
|
||||||
if (!operation || !ipAddress)
|
if (!operation) {
|
||||||
throw new OError('missing required audit log data', {
|
throw new OError('missing operation for audit log', {
|
||||||
operation,
|
|
||||||
initiatorId,
|
initiatorId,
|
||||||
ipAddress,
|
ipAddress,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ipAddress && !_canHaveNoIpAddressId(operation, info)) {
|
||||||
|
throw new OError('missing ipAddress for audit log', {
|
||||||
|
operation,
|
||||||
|
initiatorId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (!initiatorId && !_canHaveNoInitiatorId(operation, info)) {
|
if (!initiatorId && !_canHaveNoInitiatorId(operation, info)) {
|
||||||
throw new OError('missing initiatorId for audit log', {
|
throw new OError('missing initiatorId for audit log', {
|
||||||
|
|
|
@ -41,11 +41,16 @@ describe('SubscriptionGroupController', function () {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.UserAuditLogHandler = {
|
||||||
|
addEntry: sinon.stub().callsArgWith(5),
|
||||||
|
}
|
||||||
|
|
||||||
this.Controller = SandboxedModule.require(modulePath, {
|
this.Controller = SandboxedModule.require(modulePath, {
|
||||||
requires: {
|
requires: {
|
||||||
'./SubscriptionGroupHandler': this.GroupHandler,
|
'./SubscriptionGroupHandler': this.GroupHandler,
|
||||||
'./SubscriptionLocator': this.SubscriptionLocator,
|
'./SubscriptionLocator': this.SubscriptionLocator,
|
||||||
'../Authentication/SessionManager': this.SessionManager,
|
'../Authentication/SessionManager': this.SessionManager,
|
||||||
|
'../User/UserAuditLogHandler': this.UserAuditLogHandler,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -66,6 +71,27 @@ describe('SubscriptionGroupController', function () {
|
||||||
}
|
}
|
||||||
this.Controller.removeUserFromGroup(this.req, res)
|
this.Controller.removeUserFromGroup(this.req, res)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should log that the user has been removed', function (done) {
|
||||||
|
const userIdToRemove = '31231'
|
||||||
|
this.req.params = { user_id: userIdToRemove }
|
||||||
|
this.req.entity = this.subscription
|
||||||
|
|
||||||
|
const res = {
|
||||||
|
sendStatus: () => {
|
||||||
|
sinon.assert.calledWith(
|
||||||
|
this.UserAuditLogHandler.addEntry,
|
||||||
|
userIdToRemove,
|
||||||
|
'remove-from-group-subscription',
|
||||||
|
this.adminUserId,
|
||||||
|
this.req.ip,
|
||||||
|
{ subscriptionId: this.subscriptionId }
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
this.Controller.removeUserFromGroup(this.req, res)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('removeSelfFromGroup', function () {
|
describe('removeSelfFromGroup', function () {
|
||||||
|
@ -90,5 +116,26 @@ describe('SubscriptionGroupController', function () {
|
||||||
}
|
}
|
||||||
this.Controller.removeSelfFromGroup(this.req, res)
|
this.Controller.removeSelfFromGroup(this.req, res)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should log that the user has left the subscription', function (done) {
|
||||||
|
this.req.query = { subscriptionId: this.subscriptionId }
|
||||||
|
const memberUserIdToremove = 123456789
|
||||||
|
this.req.session.user._id = memberUserIdToremove
|
||||||
|
|
||||||
|
const res = {
|
||||||
|
sendStatus: () => {
|
||||||
|
sinon.assert.calledWith(
|
||||||
|
this.UserAuditLogHandler.addEntry,
|
||||||
|
memberUserIdToremove,
|
||||||
|
'remove-from-group-subscription',
|
||||||
|
memberUserIdToremove,
|
||||||
|
this.req.ip,
|
||||||
|
{ subscriptionId: this.subscriptionId }
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
this.Controller.removeSelfFromGroup(this.req, res)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -147,6 +147,12 @@ describe('SubscriptionUpdater', function () {
|
||||||
hasFeature: sinon.stub().returns(false),
|
hasFeature: sinon.stub().returns(false),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.UserAuditLogHandler = {
|
||||||
|
promises: {
|
||||||
|
addEntry: sinon.stub().resolves(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
this.SubscriptionUpdater = SandboxedModule.require(modulePath, {
|
this.SubscriptionUpdater = SandboxedModule.require(modulePath, {
|
||||||
requires: {
|
requires: {
|
||||||
'../../models/Subscription': {
|
'../../models/Subscription': {
|
||||||
|
@ -162,6 +168,7 @@ describe('SubscriptionUpdater', function () {
|
||||||
},
|
},
|
||||||
'../Analytics/AnalyticsManager': this.AnalyticsManager,
|
'../Analytics/AnalyticsManager': this.AnalyticsManager,
|
||||||
'../../infrastructure/Features': this.Features,
|
'../../infrastructure/Features': this.Features,
|
||||||
|
'../User/UserAuditLogHandler': this.UserAuditLogHandler,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -487,6 +494,23 @@ describe('SubscriptionUpdater', function () {
|
||||||
'better_group_subscription'
|
'better_group_subscription'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should add an entry to the user audit log when joining a group', async function () {
|
||||||
|
await this.SubscriptionUpdater.promises.addUserToGroup(
|
||||||
|
this.subscription._id,
|
||||||
|
this.otherUserId
|
||||||
|
)
|
||||||
|
sinon.assert.calledWith(
|
||||||
|
this.UserAuditLogHandler.promises.addEntry,
|
||||||
|
this.otherUserId,
|
||||||
|
'join-group-subscription',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
subscriptionId: this.subscription._id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('removeUserFromGroup', function () {
|
describe('removeUserFromGroup', function () {
|
||||||
|
@ -554,6 +578,23 @@ describe('SubscriptionUpdater', function () {
|
||||||
.calledWith(this.otherUserId)
|
.calledWith(this.otherUserId)
|
||||||
.should.equal(true)
|
.should.equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should add an audit log when a user leaves a group', async function () {
|
||||||
|
await this.SubscriptionUpdater.promises.removeUserFromGroup(
|
||||||
|
this.subscription._id,
|
||||||
|
this.otherUserId
|
||||||
|
)
|
||||||
|
sinon.assert.calledWith(
|
||||||
|
this.UserAuditLogHandler.promises.addEntry,
|
||||||
|
this.otherUserId,
|
||||||
|
'leave-group-subscription',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
subscriptionId: this.subscription._id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('removeUserFromAllGroups', function () {
|
describe('removeUserFromAllGroups', function () {
|
||||||
|
@ -638,6 +679,32 @@ describe('SubscriptionUpdater', function () {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should add an audit log entry for each group the user leaves', async function () {
|
||||||
|
await this.SubscriptionUpdater.promises.removeUserFromAllGroups(
|
||||||
|
this.otherUserId
|
||||||
|
)
|
||||||
|
sinon.assert.calledWith(
|
||||||
|
this.UserAuditLogHandler.promises.addEntry,
|
||||||
|
this.otherUserId,
|
||||||
|
'leave-group-subscription',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
subscriptionId: 'fake-id-1',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
sinon.assert.calledWith(
|
||||||
|
this.UserAuditLogHandler.promises.addEntry,
|
||||||
|
this.otherUserId,
|
||||||
|
'leave-group-subscription',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
subscriptionId: 'fake-id-2',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('deleteSubscription', function () {
|
describe('deleteSubscription', function () {
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
const SandboxedModule = require('sandboxed-module')
|
||||||
|
const sinon = require('sinon')
|
||||||
|
const modulePath =
|
||||||
|
'../../../../app/src/Features/Subscription/TeamInvitesController'
|
||||||
|
|
||||||
|
describe('TeamInvitesController', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
this.user = { _id: '!@312431', email: 'user@email.com' }
|
||||||
|
this.adminUserId = '123jlkj'
|
||||||
|
this.subscriptionId = '123434325412'
|
||||||
|
this.user_email = 'bob@gmail.com'
|
||||||
|
this.req = {
|
||||||
|
session: {
|
||||||
|
user: {
|
||||||
|
_id: this.adminUserId,
|
||||||
|
email: this.user_email,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: {},
|
||||||
|
query: {},
|
||||||
|
ip: '0.0.0.0',
|
||||||
|
}
|
||||||
|
|
||||||
|
this.subscription = {
|
||||||
|
_id: this.subscriptionId,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.TeamInvitesHandler = {
|
||||||
|
promises: { acceptInvite: sinon.stub().resolves(this.subscription) },
|
||||||
|
}
|
||||||
|
|
||||||
|
this.SubscriptionLocator = {
|
||||||
|
promises: {
|
||||||
|
hasSSOEnabled: sinon.stub().resolves(true),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
this.ErrorController = { notFound: sinon.stub() }
|
||||||
|
|
||||||
|
this.SessionManager = {
|
||||||
|
getLoggedInUserId(session) {
|
||||||
|
return session.user._id
|
||||||
|
},
|
||||||
|
getSessionUser(session) {
|
||||||
|
return session.user
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
this.UserAuditLogHandler = {
|
||||||
|
promises: {
|
||||||
|
addEntry: sinon.stub().resolves(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
this.UserGetter = {
|
||||||
|
promises: {
|
||||||
|
getUser: sinon.stub().resolves(this.user),
|
||||||
|
getUserByMainEmail: sinon.stub().resolves(this.user),
|
||||||
|
getUserByAnyEmail: sinon.stub().resolves(this.user),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
this.EmailHandler = {
|
||||||
|
sendDeferredEmail: sinon.stub().resolves(),
|
||||||
|
}
|
||||||
|
|
||||||
|
this.RateLimiter = {
|
||||||
|
RateLimiter: class {},
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Controller = SandboxedModule.require(modulePath, {
|
||||||
|
requires: {
|
||||||
|
'./TeamInvitesHandler': this.TeamInvitesHandler,
|
||||||
|
'../Authentication/SessionManager': this.SessionManager,
|
||||||
|
'./SubscriptionLocator': this.SubscriptionLocator,
|
||||||
|
'../User/UserAuditLogHandler': this.UserAuditLogHandler,
|
||||||
|
'../Errors/ErrorController': this.ErrorController,
|
||||||
|
'../User/UserGetter': this.UserGetter,
|
||||||
|
'../Email/EmailHandler': this.EmailHandler,
|
||||||
|
'../../infrastructure/RateLimiter': this.RateLimiter,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('acceptInvite', function () {
|
||||||
|
it('should add an audit log entry', function (done) {
|
||||||
|
this.req.params.token = 'foo'
|
||||||
|
this.req.session.user = this.user
|
||||||
|
const res = {
|
||||||
|
json: () => {
|
||||||
|
sinon.assert.calledWith(
|
||||||
|
this.UserAuditLogHandler.promises.addEntry,
|
||||||
|
this.user._id,
|
||||||
|
'accept-group-invitation',
|
||||||
|
this.user._id,
|
||||||
|
this.req.ip,
|
||||||
|
{ subscriptionId: this.subscriptionId }
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
this.Controller.acceptInvite(this.req, res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -81,6 +81,18 @@ describe('UserAuditLogHandler', function () {
|
||||||
)
|
)
|
||||||
this.UserAuditLogEntryMock.verify()
|
this.UserAuditLogEntryMock.verify()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('updates the log when no ip address or initiatorId is specified for a group join event', async function () {
|
||||||
|
this.UserAuditLogHandler.promises.addEntry(
|
||||||
|
this.userId,
|
||||||
|
'join-group-subscription',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
subscriptionId: 'foo',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('errors', function () {
|
describe('errors', function () {
|
||||||
|
@ -97,7 +109,7 @@ describe('UserAuditLogHandler', function () {
|
||||||
).to.be.rejected
|
).to.be.rejected
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws an error when no IP', async function () {
|
it('throws an error when no IP and not excempt', async function () {
|
||||||
await expect(
|
await expect(
|
||||||
this.UserAuditLogHandler.promises.addEntry(
|
this.UserAuditLogHandler.promises.addEntry(
|
||||||
this.userId,
|
this.userId,
|
||||||
|
|
Loading…
Reference in a new issue