mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #19946 from overleaf/ac-remove-ol-int-imports-from-tests
[web] Remove overleaf-integration imports from tests GitOrigin-RevId: 96a3afaab386c486c948d35999f2acf4cedc77cf
This commit is contained in:
parent
0e43a18bc6
commit
a6c97cd506
2 changed files with 265 additions and 0 deletions
219
services/web/test/acceptance/src/helpers/groupSSO.js
Normal file
219
services/web/test/acceptance/src/helpers/groupSSO.js
Normal file
|
@ -0,0 +1,219 @@
|
|||
const fs = require('fs')
|
||||
const Path = require('path')
|
||||
const User = require('./User').promises
|
||||
const Subscription = require('./Subscription').promises
|
||||
const { SSOConfig } = require('../../../../app/src/models/SSOConfig')
|
||||
const UserHelper = require('./UserHelper')
|
||||
const SAMLHelper = require('./SAMLHelper')
|
||||
const Settings = require('@overleaf/settings')
|
||||
const {
|
||||
getProviderId,
|
||||
} = require('../../../../app/src/Features/Subscription/GroupUtils')
|
||||
const UserGetter = require('../../../../app/src/Features/User/UserGetter')
|
||||
const {
|
||||
Subscription: SubscriptionModel,
|
||||
} = require('../../../../app/src/models/Subscription')
|
||||
|
||||
const SAML_TEST_CERT = fs
|
||||
.readFileSync(Path.resolve(__dirname, '../../files/saml-cert.crt'), 'utf8')
|
||||
.replace(/-----BEGIN CERTIFICATE-----/, '')
|
||||
.replace(/-----END CERTIFICATE-----/, '')
|
||||
.replace(/\n/g, '')
|
||||
|
||||
function getEnrollmentUrl(groupId) {
|
||||
return `/subscription/${groupId}/sso_enrollment`
|
||||
}
|
||||
|
||||
const userIdAttribute = 'nameID'
|
||||
|
||||
const baseSsoConfig = {
|
||||
entryPoint: 'http://example-sso.com/saml',
|
||||
certificates: [SAML_TEST_CERT],
|
||||
signatureAlgorithm: 'sha256',
|
||||
userIdAttribute,
|
||||
} // the database also sets enabled and validated, but we cannot set that in the POST request for /manage/groups/:ID/settings/sso
|
||||
|
||||
async function createGroupSSO() {
|
||||
const nonSSOMemberHelper = await UserHelper.createUser()
|
||||
const nonSSOMember = nonSSOMemberHelper.user
|
||||
|
||||
const groupAdminUser = new User()
|
||||
const memberUser = new User()
|
||||
|
||||
await groupAdminUser.ensureUserExists()
|
||||
await memberUser.ensureUserExists()
|
||||
|
||||
const ssoConfig = new SSOConfig({
|
||||
...baseSsoConfig,
|
||||
enabled: true,
|
||||
validated: true,
|
||||
})
|
||||
|
||||
await ssoConfig.save()
|
||||
|
||||
const subscription = new Subscription({
|
||||
adminId: groupAdminUser._id,
|
||||
memberIds: [memberUser._id, nonSSOMember._id, groupAdminUser._id],
|
||||
groupPlan: true,
|
||||
planCode: 'group_professional_10_enterprise',
|
||||
features: {
|
||||
groupSSO: true,
|
||||
},
|
||||
ssoConfig: ssoConfig._id,
|
||||
membersLimit: 10,
|
||||
})
|
||||
await subscription.ensureExists()
|
||||
const subscriptionId = subscription._id.toString()
|
||||
const enrollmentUrl = getEnrollmentUrl(subscriptionId)
|
||||
const internalProviderId = getProviderId(subscriptionId)
|
||||
|
||||
await linkGroupMember(
|
||||
memberUser.email,
|
||||
memberUser.password,
|
||||
subscriptionId,
|
||||
'mock@email.com'
|
||||
)
|
||||
|
||||
const userHelper = new UserHelper()
|
||||
|
||||
return {
|
||||
ssoConfig,
|
||||
internalProviderId,
|
||||
userIdAttribute,
|
||||
subscription,
|
||||
subscriptionId,
|
||||
groupAdminUser,
|
||||
memberUser,
|
||||
nonSSOMemberHelper,
|
||||
nonSSOMember,
|
||||
userHelper,
|
||||
enrollmentUrl,
|
||||
}
|
||||
}
|
||||
|
||||
async function linkGroupMember(
|
||||
userEmail,
|
||||
userPassword,
|
||||
groupId,
|
||||
externalUserId
|
||||
) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const subscription = await SubscriptionModel.findById(groupId)
|
||||
.populate('ssoConfig')
|
||||
.exec()
|
||||
const userIdAttribute = subscription?.ssoConfig?.userIdAttribute
|
||||
|
||||
const internalProviderId = getProviderId(groupId)
|
||||
const enrollmentUrl = getEnrollmentUrl(groupId)
|
||||
const userHelper = await UserHelper.loginUser(
|
||||
{
|
||||
email: userEmail,
|
||||
password: userPassword,
|
||||
},
|
||||
`/subscription/${groupId}/sso_enrollment`
|
||||
)
|
||||
|
||||
const { headers } = await userHelper.fetch(enrollmentUrl, {
|
||||
method: 'POST',
|
||||
})
|
||||
if (
|
||||
!headers.get('location') ||
|
||||
!headers.get('location').includes(Settings.saml.groupSSO.initPath)
|
||||
) {
|
||||
throw new Error('invalid redirect when linking to group SSO')
|
||||
}
|
||||
|
||||
const redirectTo = new URL(headers.get('location'))
|
||||
|
||||
const initSSOResponse = await userHelper.fetch(redirectTo)
|
||||
|
||||
// redirect to IdP
|
||||
const idpEntryPointUrl = new URL(initSSOResponse.headers.get('location'))
|
||||
const requestId = await SAMLHelper.getRequestId(idpEntryPointUrl)
|
||||
const response = await userHelper.fetch(Settings.saml.groupSSO.path, {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({
|
||||
SAMLResponse: SAMLHelper.createMockSamlResponse({
|
||||
requestId,
|
||||
userIdAttribute,
|
||||
uniqueId: externalUserId,
|
||||
issuer: 'https://www.overleaf.test/saml/group-sso/meta',
|
||||
}),
|
||||
}),
|
||||
})
|
||||
if (response.status !== 302) {
|
||||
throw new Error('failed to link group SSO')
|
||||
}
|
||||
|
||||
// ensure user linked
|
||||
const user = await UserGetter.promises.getUser(
|
||||
{ email: userEmail },
|
||||
{ samlIdentifiers: 1, enrollment: 1 }
|
||||
)
|
||||
|
||||
const { enrollment, samlIdentifiers } = user
|
||||
const linkedToGroupSSO = samlIdentifiers.some(
|
||||
identifier => identifier.providerId === internalProviderId
|
||||
)
|
||||
const userIsEnrolledInSSO = enrollment.sso.some(
|
||||
sso => sso.groupId.toString() === groupId.toString()
|
||||
)
|
||||
if (!linkedToGroupSSO || !userIsEnrolledInSSO) {
|
||||
throw new Error('error setting up test user with group SSO linked')
|
||||
}
|
||||
|
||||
return userHelper
|
||||
}
|
||||
|
||||
async function setConfigAndEnableSSO(
|
||||
subscriptionHelper,
|
||||
adminEmailPassword,
|
||||
config
|
||||
) {
|
||||
config = config || {
|
||||
entryPoint: 'http://idp.example.com/entry_point',
|
||||
certificates: [SAML_TEST_CERT],
|
||||
userIdAttribute: 'email',
|
||||
userLastNameAttribute: 'lastName',
|
||||
}
|
||||
|
||||
const { email, password } = adminEmailPassword
|
||||
const userHelper = await UserHelper.loginUser({
|
||||
email,
|
||||
password,
|
||||
})
|
||||
|
||||
const createResponse = await userHelper.fetch(
|
||||
`/manage/groups/${subscriptionHelper._id}/settings/sso`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(config),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
)
|
||||
if (createResponse.status !== 201) {
|
||||
throw new Error(
|
||||
`failed to set SSO config. Status = ${createResponse.status}`
|
||||
)
|
||||
}
|
||||
|
||||
await subscriptionHelper.setValidatedSSO()
|
||||
|
||||
const enableResponse = await userHelper.fetch(
|
||||
`/manage/groups/${subscriptionHelper._id}/settings/enableSSO`,
|
||||
{ method: 'POST' }
|
||||
)
|
||||
|
||||
if (enableResponse.status !== 200) {
|
||||
throw new Error(`failed to enable SSO. Status = ${enableResponse.status}`)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createGroupSSO,
|
||||
linkGroupMember,
|
||||
baseSsoConfig,
|
||||
setConfigAndEnableSSO,
|
||||
}
|
46
services/web/test/acceptance/src/mocks/MockGoogleOauthApi.js
Normal file
46
services/web/test/acceptance/src/mocks/MockGoogleOauthApi.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
const AbstractMockApi = require('./AbstractMockApi')
|
||||
|
||||
class MockGoogleOauthApi extends AbstractMockApi {
|
||||
reset() {
|
||||
this.profiles = {}
|
||||
this.tokens = {}
|
||||
}
|
||||
|
||||
addProfile(profile, token, authorizationCode) {
|
||||
this.profiles[token] = {
|
||||
picture: 'https://example.com/picture.jpg',
|
||||
email_verified: true,
|
||||
locale: 'en-GB',
|
||||
...profile,
|
||||
}
|
||||
this.tokens[authorizationCode] = token
|
||||
}
|
||||
|
||||
applyRoutes() {
|
||||
this.app.post('/oauth/token', (req, res, next) => {
|
||||
if (!this.tokens[req.body.code]) {
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
res.json({
|
||||
access_token: this.tokens[req.body.code],
|
||||
})
|
||||
})
|
||||
|
||||
this.app.get('/oauth2/v3/userinfo', (req, res, next) => {
|
||||
if (!this.profiles[req.query.access_token]) {
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
res.json(this.profiles[req.query.access_token])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MockGoogleOauthApi
|
||||
|
||||
// type hint for the inherited `instance` method
|
||||
/**
|
||||
* @function instance
|
||||
* @memberOf MockGoogleOauthApi
|
||||
* @static
|
||||
* @returns {MockGoogleOauthApi}
|
||||
*/
|
Loading…
Reference in a new issue