mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
Merge pull request #26366 from overleaf/jel-group-csv
[web] Include in group members CSV if user is managed and/or linked to the group's SSO GitOrigin-RevId: 449974917d98cf121ea46eaa58be4b3666d88268
This commit is contained in:
@@ -13,6 +13,7 @@ import { Parser as CSVParser } from 'json2csv'
|
||||
import { expressify } from '@overleaf/promise-utils'
|
||||
import PlansLocator from '../Subscription/PlansLocator.js'
|
||||
import RecurlyClient from '../Subscription/RecurlyClient.js'
|
||||
import Modules from '../../infrastructure/Modules.js'
|
||||
|
||||
async function manageGroupMembers(req, res, next) {
|
||||
const { entity: subscription, entityConfig } = req
|
||||
@@ -121,6 +122,56 @@ async function _renderManagersPage(req, res, next, template) {
|
||||
})
|
||||
}
|
||||
|
||||
async function exportCsv(req, res) {
|
||||
let ssoEnabled
|
||||
const { entity, entityConfig } = req
|
||||
const fields = ['email', 'last_logged_in_at', 'last_active_at']
|
||||
|
||||
const { managedUsersEnabled } = entity
|
||||
|
||||
let users = await UserMembershipHandler.promises.getUsers(
|
||||
entity,
|
||||
entityConfig
|
||||
)
|
||||
|
||||
if (entity.ssoConfig) {
|
||||
const ssoEnabledResult = await Modules.promises.hooks.fire(
|
||||
'hasGroupSSOEnabled',
|
||||
entity
|
||||
)
|
||||
ssoEnabled = ssoEnabledResult?.[0]
|
||||
}
|
||||
|
||||
if (managedUsersEnabled) {
|
||||
fields.push('managed')
|
||||
}
|
||||
|
||||
if (ssoEnabled) {
|
||||
fields.push('sso')
|
||||
}
|
||||
|
||||
if (managedUsersEnabled || ssoEnabled) {
|
||||
users = users.map(user => {
|
||||
if (managedUsersEnabled) {
|
||||
user.managed =
|
||||
user.enrollment?.managedBy?.toString() === entity._id.toString()
|
||||
}
|
||||
|
||||
if (ssoEnabled) {
|
||||
user.sso = !!user.enrollment?.sso?.some(
|
||||
groupLinked =>
|
||||
groupLinked.groupId.toString() === entity._id.toString()
|
||||
)
|
||||
}
|
||||
return user
|
||||
})
|
||||
}
|
||||
|
||||
const csvParser = new CSVParser({ fields })
|
||||
|
||||
csvAttachment(res, csvParser.parse(users), 'Group.csv')
|
||||
}
|
||||
|
||||
export default {
|
||||
manageGroupMembers: expressify(manageGroupMembers),
|
||||
manageGroupManagers: expressify(manageGroupManagers),
|
||||
@@ -208,22 +259,7 @@ export default {
|
||||
}
|
||||
)
|
||||
},
|
||||
exportCsv(req, res, next) {
|
||||
const { entity, entityConfig } = req
|
||||
const fields = ['email', 'last_logged_in_at', 'last_active_at']
|
||||
|
||||
UserMembershipHandler.getUsers(
|
||||
entity,
|
||||
entityConfig,
|
||||
function (error, users) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
const csvParser = new CSVParser({ fields })
|
||||
csvAttachment(res, csvParser.parse(users), 'Group.csv')
|
||||
}
|
||||
)
|
||||
},
|
||||
exportCsv: expressify(exportCsv),
|
||||
new(req, res, next) {
|
||||
res.render('user_membership/new', {
|
||||
entityName: req.params.name,
|
||||
|
||||
@@ -59,6 +59,48 @@ describe('UserMembershipController', function () {
|
||||
last_logged_in_at: '2020-05-20T10:41:11.407Z',
|
||||
last_active_at: '2021-05-20T10:41:11.407Z',
|
||||
},
|
||||
{
|
||||
_id: 'mock-member-id-3',
|
||||
email: 'mock-email-3@foo.com',
|
||||
last_logged_in_at: '2021-08-10T10:41:11.407Z',
|
||||
last_active_at: '2021-08-20T10:41:11.407Z',
|
||||
enrollment: {
|
||||
managedBy: 'some-other-subscription-id',
|
||||
enrolledAt: '2021-05-20T10:41:11.407Z',
|
||||
sso: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
_id: 'mock-member-id-4',
|
||||
email: 'mock-email-4@foo.com',
|
||||
last_logged_in_at: '2021-01-01T10:41:11.407Z',
|
||||
last_active_at: '2021-01-02T10:41:11.407Z',
|
||||
enrollment: {
|
||||
managedBy: 'mock-subscription-id',
|
||||
enrolledAt: '2021-01-02T10:41:11.407Z',
|
||||
sso: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
_id: 'mock-member-id-5',
|
||||
email: 'mock-email-5@foo.com',
|
||||
last_logged_in_at: '2023-01-01T10:41:11.407Z',
|
||||
last_active_at: '2023-01-02T10:41:11.407Z',
|
||||
enrollment: {
|
||||
sso: [{ groupId: ctx.subscription._id }],
|
||||
},
|
||||
},
|
||||
{
|
||||
_id: 'mock-member-id-6',
|
||||
email: 'mock-email-6@foo.com',
|
||||
last_logged_in_at: '2024-01-01T10:41:11.407Z',
|
||||
last_active_at: '2024-01-02T10:41:11.407Z',
|
||||
enrollment: {
|
||||
managedBy: 'mock-subscription-id',
|
||||
enrolledAt: '2024-01-02T10:41:11.407Z',
|
||||
sso: [{ groupId: ctx.subscription._id }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
ctx.Settings = {
|
||||
@@ -143,6 +185,17 @@ describe('UserMembershipController', function () {
|
||||
SSOConfig: ctx.SSOConfig,
|
||||
}))
|
||||
|
||||
ctx.Modules = {
|
||||
promises: {
|
||||
hooks: {
|
||||
fire: sinon.stub(),
|
||||
},
|
||||
},
|
||||
}
|
||||
vi.doMock('../../../../app/src/infrastructure/Modules.js', () => ({
|
||||
default: ctx.Modules,
|
||||
}))
|
||||
|
||||
ctx.UserMembershipController = (await import(modulePath)).default
|
||||
})
|
||||
|
||||
@@ -377,7 +430,7 @@ describe('UserMembershipController', function () {
|
||||
|
||||
it('get users', function (ctx) {
|
||||
sinon.assert.calledWithMatch(
|
||||
ctx.UserMembershipHandler.getUsers,
|
||||
ctx.UserMembershipHandler.promises.getUsers,
|
||||
ctx.subscription,
|
||||
{ modelName: 'Subscription' }
|
||||
)
|
||||
@@ -398,7 +451,67 @@ describe('UserMembershipController', function () {
|
||||
it('should export the correct csv', function (ctx) {
|
||||
assertCalledWith(
|
||||
ctx.res.send,
|
||||
'"email","last_logged_in_at","last_active_at"\n"mock-email-1@foo.com","2020-08-09T12:43:11.467Z","2021-08-09T12:43:11.467Z"\n"mock-email-2@foo.com","2020-05-20T10:41:11.407Z","2021-05-20T10:41:11.407Z"'
|
||||
'"email","last_logged_in_at","last_active_at"\n"mock-email-1@foo.com","2020-08-09T12:43:11.467Z","2021-08-09T12:43:11.467Z"\n"mock-email-2@foo.com","2020-05-20T10:41:11.407Z","2021-05-20T10:41:11.407Z"\n"mock-email-3@foo.com","2021-08-10T10:41:11.407Z","2021-08-20T10:41:11.407Z"\n"mock-email-4@foo.com","2021-01-01T10:41:11.407Z","2021-01-02T10:41:11.407Z"\n"mock-email-5@foo.com","2023-01-01T10:41:11.407Z","2023-01-02T10:41:11.407Z"\n"mock-email-6@foo.com","2024-01-01T10:41:11.407Z","2024-01-02T10:41:11.407Z"'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('exportCsv when group is managed', function () {
|
||||
beforeEach(function (ctx) {
|
||||
ctx.req.entity = Object.assign(
|
||||
{ managedUsersEnabled: true },
|
||||
ctx.subscription
|
||||
)
|
||||
ctx.req.entityConfig = EntityConfigs.groupManagers
|
||||
ctx.res = new MockResponse()
|
||||
ctx.UserMembershipController.exportCsv(ctx.req, ctx.res)
|
||||
})
|
||||
|
||||
it('should export the correct csv', function (ctx) {
|
||||
assertCalledWith(
|
||||
ctx.res.send,
|
||||
'"email","last_logged_in_at","last_active_at","managed"\n"mock-email-1@foo.com","2020-08-09T12:43:11.467Z","2021-08-09T12:43:11.467Z",false\n"mock-email-2@foo.com","2020-05-20T10:41:11.407Z","2021-05-20T10:41:11.407Z",false\n"mock-email-3@foo.com","2021-08-10T10:41:11.407Z","2021-08-20T10:41:11.407Z",false\n"mock-email-4@foo.com","2021-01-01T10:41:11.407Z","2021-01-02T10:41:11.407Z",true\n"mock-email-5@foo.com","2023-01-01T10:41:11.407Z","2023-01-02T10:41:11.407Z",false\n"mock-email-6@foo.com","2024-01-01T10:41:11.407Z","2024-01-02T10:41:11.407Z",true'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('exportCsv when group has SSO', function () {
|
||||
beforeEach(function (ctx) {
|
||||
ctx.req.entity = Object.assign(
|
||||
{ ssoConfig: 'sso-config-id' },
|
||||
ctx.subscription
|
||||
)
|
||||
ctx.req.entityConfig = EntityConfigs.groupManagers
|
||||
ctx.Modules.promises.hooks.fire.resolves([true])
|
||||
ctx.res = new MockResponse()
|
||||
ctx.UserMembershipController.exportCsv(ctx.req, ctx.res)
|
||||
})
|
||||
|
||||
it('should export the correct csv', function (ctx) {
|
||||
assertCalledWith(
|
||||
ctx.res.send,
|
||||
'"email","last_logged_in_at","last_active_at","sso"\n"mock-email-1@foo.com","2020-08-09T12:43:11.467Z","2021-08-09T12:43:11.467Z",false\n"mock-email-2@foo.com","2020-05-20T10:41:11.407Z","2021-05-20T10:41:11.407Z",false\n"mock-email-3@foo.com","2021-08-10T10:41:11.407Z","2021-08-20T10:41:11.407Z",false\n"mock-email-4@foo.com","2021-01-01T10:41:11.407Z","2021-01-02T10:41:11.407Z",false\n"mock-email-5@foo.com","2023-01-01T10:41:11.407Z","2023-01-02T10:41:11.407Z",true\n"mock-email-6@foo.com","2024-01-01T10:41:11.407Z","2024-01-02T10:41:11.407Z",true'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('exportCsv when group has SSO and managed users enabled', function () {
|
||||
beforeEach(function (ctx) {
|
||||
ctx.req.entity = Object.assign(
|
||||
{ managedUsersEnabled: true },
|
||||
{ ssoConfig: 'sso-config-id' },
|
||||
ctx.subscription
|
||||
)
|
||||
ctx.req.entityConfig = EntityConfigs.groupManagers
|
||||
ctx.Modules.promises.hooks.fire.resolves([true])
|
||||
ctx.res = new MockResponse()
|
||||
ctx.UserMembershipController.exportCsv(ctx.req, ctx.res)
|
||||
})
|
||||
|
||||
it('should export the correct csv', function (ctx) {
|
||||
assertCalledWith(
|
||||
ctx.res.send,
|
||||
'"email","last_logged_in_at","last_active_at","managed","sso"\n"mock-email-1@foo.com","2020-08-09T12:43:11.467Z","2021-08-09T12:43:11.467Z",false,false\n"mock-email-2@foo.com","2020-05-20T10:41:11.407Z","2021-05-20T10:41:11.407Z",false,false\n"mock-email-3@foo.com","2021-08-10T10:41:11.407Z","2021-08-20T10:41:11.407Z",false,false\n"mock-email-4@foo.com","2021-01-01T10:41:11.407Z","2021-01-02T10:41:11.407Z",true,false\n"mock-email-5@foo.com","2023-01-01T10:41:11.407Z","2023-01-02T10:41:11.407Z",false,true\n"mock-email-6@foo.com","2024-01-01T10:41:11.407Z","2024-01-02T10:41:11.407Z",true,true'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user