From 10deaf5aec16b329996f2445bdca596bd277529f Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Tue, 27 Jul 2021 09:45:17 +0100 Subject: [PATCH] Merge pull request #4332 from overleaf/sk-import-server-pro-acceptance-tests Migrate server-pro acceptance tests to modules GitOrigin-RevId: 7caf5719d21bbd7fb30901f3e52225fe4cbc9832 --- .../web/app/src/infrastructure/Features.js | 4 +- services/web/docker-compose.ci.yml | 32 ++++---- services/web/docker-compose.common.env | 36 +++++++++ services/web/docker-compose.yml | 35 ++++----- .../test/acceptance/config/settings.test.js | 8 ++ .../launchpad/test/acceptance/src/Init.js | 1 + .../test/acceptance/src/LaunchpadTests.js | 73 +++++++++++++++++++ .../config/settings.test.defaults.js | 4 +- .../unit/src/infrastructure/FeaturesTests.js | 4 +- 9 files changed, 159 insertions(+), 38 deletions(-) create mode 100644 services/web/docker-compose.common.env create mode 100644 services/web/modules/launchpad/test/acceptance/config/settings.test.js create mode 100644 services/web/modules/launchpad/test/acceptance/src/Init.js create mode 100644 services/web/modules/launchpad/test/acceptance/src/LaunchpadTests.js diff --git a/services/web/app/src/infrastructure/Features.js b/services/web/app/src/infrastructure/Features.js index a4d9d016b9..3d28029890 100644 --- a/services/web/app/src/infrastructure/Features.js +++ b/services/web/app/src/infrastructure/Features.js @@ -39,8 +39,8 @@ const Features = { */ externalAuthenticationSystemUsed() { return ( - Boolean(Settings.ldap) || - Boolean(Settings.saml) || + (Boolean(Settings.ldap) && Boolean(Settings.ldap.enable)) || + (Boolean(Settings.saml) && Boolean(Settings.saml.enable)) || Boolean(_.get(Settings, ['overleaf', 'oauth'])) ) }, diff --git a/services/web/docker-compose.ci.yml b/services/web/docker-compose.ci.yml index 18b0b0bc01..c0fb7f58db 100644 --- a/services/web/docker-compose.ci.yml +++ b/services/web/docker-compose.ci.yml @@ -1,4 +1,4 @@ -version: "2" +version: "2.3" volumes: data: @@ -19,24 +19,10 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER working_dir: /app + env_file: docker-compose.common.env environment: - BCRYPT_ROUNDS: 1 - REDIS_HOST: redis - QUEUES_REDIS_HOST: redis - MONGO_URL: "mongodb://mongo/sharelatex" - SHARELATEX_ALLOW_PUBLIC_ACCESS: 'true' - PROJECT_HISTORY_ENABLED: 'true' - ENABLED_LINKED_FILE_TYPES: 'url,project_file,project_output_file,mendeley,zotero' - LINKED_URL_PROXY: 'http://localhost:6543' - LOCK_MANAGER_MAX_LOCK_WAIT_TIME: 30000 - NODE_ENV: test - NODE_OPTIONS: "--unhandled-rejections=strict" BASE_CONFIG: SHARELATEX_CONFIG: - COOKIE_DOMAIN: .overleaf.test - PUBLIC_URL: 'http://www.overleaf.test:3000' - HTTP_TEST_HOST: www.overleaf.test - OT_JWT_AUTH_KEY: "very secret key" extra_hosts: - 'www.overleaf.test:127.0.0.1' command: npm run test:acceptance:app @@ -44,6 +30,8 @@ services: depends_on: - redis - mongo + - saml + - ldap test_karma: build: @@ -79,3 +67,15 @@ services: mongo: image: mongo:4.0.19 + + ldap: + restart: always + image: rroemhild/test-openldap:1.1 + + saml: + restart: always + image: gcr.io/overleaf-ops/saml-test + environment: + SAML_BASE_URL_PATH: 'http://saml/simplesaml/' + SAML_TEST_SP_ENTITY_ID: 'sharelatex-test-saml' + SAML_TEST_SP_LOCATION: 'http://www.overleaf.test:3000/saml/callback' diff --git a/services/web/docker-compose.common.env b/services/web/docker-compose.common.env new file mode 100644 index 0000000000..5281dee83a --- /dev/null +++ b/services/web/docker-compose.common.env @@ -0,0 +1,36 @@ +BCRYPT_ROUNDS=1 +REDIS_HOST=redis +QUEUES_REDIS_HOST=redis +MONGO_URL=mongodb://mongo/sharelatex +SHARELATEX_ALLOW_PUBLIC_ACCESS=true +PROJECT_HISTORY_ENABLED=true +LINKED_URL_PROXY=http://localhost:6543 +ENABLED_LINKED_FILE_TYPES=url,project_file,project_output_file,mendeley,zotero +NODE_ENV=test +NODE_OPTIONS=--unhandled-rejections=strict +LOCK_MANAGER_MAX_LOCK_WAIT_TIME=30000 +COOKIE_DOMAIN=.overleaf.test +PUBLIC_URL=http://www.overleaf.test:3000 +HTTP_TEST_HOST=www.overleaf.test +OT_JWT_AUTH_KEY=very secret key +# Server-Pro LDAP +SHARELATEX_LDAP_URL=ldap://ldap:389 +SHARELATEX_LDAP_SEARCH_BASE=ou=people,dc=planetexpress,dc=com +SHARELATEX_LDAP_SEARCH_FILTER=(uid={{username}}) +SHARELATEX_LDAP_BIND_DN=cn=admin,dc=planetexpress,dc=com +SHARELATEX_LDAP_BIND_CREDENTIALS=GoodNewsEveryone +SHARELATEX_LDAP_EMAIL_ATT=mail +SHARELATEX_LDAP_NAME_ATT=cn +SHARELATEX_LDAP_LAST_NAME_ATT=sn +SHARELATEX_LDAP_UPDATE_USER_DETAILS_ON_LOGIN=true +# Server-Pro SAML +SHARELATEX_SAML_ENTRYPOINT=http://saml/simplesaml/saml2/idp/SSOService.php +SHARELATEX_SAML_CALLBACK_URL=http://saml/saml/callback +SHARELATEX_SAML_ISSUER=sharelatex-test-saml +SHARELATEX_SAML_IDENTITY_SERVICE_NAME=SAML Test Server +SHARELATEX_SAML_EMAIL_FIELD=email +SHARELATEX_SAML_FIRST_NAME_FIELD=givenName +SHARELATEX_SAML_LAST_NAME_FIELD=sn +SHARELATEX_SAML_UPDATE_USER_DETAILS_ON_LOGIN=true +# simplesaml cert from https://github.com/overleaf/google-ops/tree/master/docker-images/saml-test/var-simplesamlphp/cert +SHARELATEX_SAML_CERT=MIIDXTCCAkWgAwIBAgIJAOvOeQ4xFTzsMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTYxMTE1MTQxMjU5WhcNMjYxMTE1MTQxMjU5WjBFMQswCQYDVQQGEwJHQjETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCT6MBe5G9VoLU8MfztOEbUhnwLp17ak8eFUqxqeXkkqtWB0b/cmIBU3xoQoO3dIF8PBzfqehqfYVhrNt/TFgcmDfmJnPJRL1RJWMW3VmiP5odJ3LwlkKbZpkeT3wZ8HEJIR1+zbpxiBNkbd2GbdR1iumcsHzMYX1A2CBj+ZMV5VijC+K4P0e9c05VsDEUtLmfeAasJAiumQoVVgAe/BpiXjICGGewa6EPFI7mKkifIRKOGxdRESwZZjxP30bI31oDN0cgKqIgSJtJ9nfCn9jgBMBkQHu42WMuaWD4jrGd7+vYdX+oIfArs9aKgAH5kUGhGdew2R9SpBefrhbNxG8QIDAQABo1AwTjAdBgNVHQ4EFgQU+aSojSyyLChP/IpZcafvSdhj7KkwHwYDVR0jBBgwFoAU+aSojSyyLChP/IpZcafvSdhj7KkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABl3+OOVLBWMKs6PjA8lPuloWDNzSr3v76oUcHqAb+cfbucjXrOVsS9RJ0X9yxvCQyfM9FfY43DbspnN3izYhdvbJD8kKLNf0LA5st+ZxLfy0ACyL2iyAwICaqndqxAjQYplFAHmpUiu1DiHckyBPekokDJd+ze95urHMOsaGS5RWPoKJVE0bkaAeZCmEu0NNpXRSBiuxXSTeSAJfv6kyE/rkdhzUKyUl/cGQFrsVYfAFQVA+W6CKOh74ErSEzSHQQYndl7nD33snD/YqdU1ROxV6aJzLKCg+sdj+wRXSP2u/UHnM4jW9TGJfhO42jzL6WVuEvr9q4l7zWzUQKKKhtQ== diff --git a/services/web/docker-compose.yml b/services/web/docker-compose.yml index be20926444..95a6242e96 100644 --- a/services/web/docker-compose.yml +++ b/services/web/docker-compose.yml @@ -25,33 +25,22 @@ services: volumes: - .:/app working_dir: /app + env_file: docker-compose.common.env environment: - BCRYPT_ROUNDS: 1 - REDIS_HOST: redis - QUEUES_REDIS_HOST: redis - MONGO_URL: "mongodb://mongo/sharelatex" - SHARELATEX_ALLOW_PUBLIC_ACCESS: 'true' - PROJECT_HISTORY_ENABLED: 'true' - LINKED_URL_PROXY: 'http://localhost:6543' - ENABLED_LINKED_FILE_TYPES: 'url,project_file,project_output_file,mendeley,zotero' + BASE_CONFIG: + SHARELATEX_CONFIG: MOCHA_GREP: ${MOCHA_GREP} - NODE_ENV: test - NODE_OPTIONS: "--unhandled-rejections=strict" - LOCK_MANAGER_MAX_LOCK_WAIT_TIME: 30000 MONGO_SERVER_SELECTION_TIMEOUT: 600000 MONGO_SOCKET_TIMEOUT: 300000 # SHARELATEX_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: 'true' - BASE_CONFIG: - SHARELATEX_CONFIG: - COOKIE_DOMAIN: .overleaf.test - PUBLIC_URL: 'http://www.overleaf.test:3000' - HTTP_TEST_HOST: www.overleaf.test - OT_JWT_AUTH_KEY: "very secret key" + extra_hosts: - 'www.overleaf.test:127.0.0.1' depends_on: - redis - mongo + - saml + - ldap command: npm run --silent test:acceptance:app test_karma: @@ -83,3 +72,15 @@ services: mongo: image: mongo:4.0.19 + + ldap: + restart: always + image: rroemhild/test-openldap:1.1 + + saml: + restart: always + image: gcr.io/overleaf-ops/saml-test + environment: + SAML_BASE_URL_PATH: 'http://saml/simplesaml/' + SAML_TEST_SP_ENTITY_ID: 'sharelatex-test-saml' + SAML_TEST_SP_LOCATION: 'http://www.overleaf.test:3000/saml/callback' diff --git a/services/web/modules/launchpad/test/acceptance/config/settings.test.js b/services/web/modules/launchpad/test/acceptance/config/settings.test.js new file mode 100644 index 0000000000..63baaed806 --- /dev/null +++ b/services/web/modules/launchpad/test/acceptance/config/settings.test.js @@ -0,0 +1,8 @@ +const base = require(process.env.BASE_CONFIG) + +module.exports = base.mergeWith({ + enableLegacyLogin: true, + test: { + counterInit: 210000, + }, +}) diff --git a/services/web/modules/launchpad/test/acceptance/src/Init.js b/services/web/modules/launchpad/test/acceptance/src/Init.js new file mode 100644 index 0000000000..3757f183ac --- /dev/null +++ b/services/web/modules/launchpad/test/acceptance/src/Init.js @@ -0,0 +1 @@ +require('../../../../../test/acceptance/src/helpers/InitApp') diff --git a/services/web/modules/launchpad/test/acceptance/src/LaunchpadTests.js b/services/web/modules/launchpad/test/acceptance/src/LaunchpadTests.js new file mode 100644 index 0000000000..7145add869 --- /dev/null +++ b/services/web/modules/launchpad/test/acceptance/src/LaunchpadTests.js @@ -0,0 +1,73 @@ +const { expect } = require('chai') +const cheerio = require('cheerio') +const WEB_PATH = '../../../../..' +const UserHelper = require(`${WEB_PATH}/test/acceptance/src/helpers/UserHelper`) + +describe('Launchpad', function () { + const adminEmail = 'admin@example.com' + const adminPassword = 'adreadfulsecret' + const user = new UserHelper() + + it('should show the launchpad page', async function () { + const response = await user.request.get('/launchpad') + expect(response.statusCode).to.equal(200) + const $ = cheerio.load(response.body) + expect($('h2').first().text()).to.equal('Create the first Admin account') + expect($('form[name="email"]').first()).to.exist + expect($('form[name="password"]').first()).to.exist + }) + + it('should allow for creation of the first admin user', async function () { + // Load the launchpad page + const initialPageResponse = await user.request.get('/launchpad') + expect(initialPageResponse.statusCode).to.equal(200) + const $ = cheerio.load(initialPageResponse.body) + expect($('h2').first().text()).to.equal('Create the first Admin account') + expect($('form[name="email"]').first()).to.exist + expect($('form[name="password"]').first()).to.exist + + // Submit the form + let csrfToken = await user.getCsrfToken() + const postResponse = await user.request.post({ + url: '/launchpad/register_admin', + json: { + _csrf: csrfToken, + email: adminEmail, + password: adminPassword, + }, + }) + expect(postResponse.statusCode).to.equal(200) + expect(postResponse.body.redir).to.equal('') + expect(postResponse.body.email).to.equal(adminEmail) + expect(postResponse.body.id).to.exist + + // Try to load the page again + const secondPageResponse = await user.request.get('/launchpad', { + simple: false, + }) + expect(secondPageResponse.statusCode).to.equal(302) + expect(secondPageResponse.headers.location).to.equal('/login') + + // Forbid submitting the form again + csrfToken = await user.getCsrfToken() + const badPostResponse = await user.request.post({ + url: '/launchpad/register_admin', + json: { + _csrf: csrfToken, + email: adminEmail + '1', + password: adminPassword + '1', + }, + simple: false, + }) + expect(badPostResponse.statusCode).to.equal(403) + + // Log in as this new admin user + const adminUser = await UserHelper.loginUser({ + email: adminEmail, + password: adminPassword, + }) + // Check we are actually admin + expect(await adminUser.isLoggedIn()).to.equal(true) + expect(adminUser.user.isAdmin).to.equal(true) + }) +}) diff --git a/services/web/test/acceptance/config/settings.test.defaults.js b/services/web/test/acceptance/config/settings.test.defaults.js index a375b1b179..17a7a1df69 100644 --- a/services/web/test/acceptance/config/settings.test.defaults.js +++ b/services/web/test/acceptance/config/settings.test.defaults.js @@ -18,7 +18,9 @@ module.exports = { security: { sessionSecret: 'static-secret-for-tests', }, - adminDomains: ['example.com'], + adminDomains: process.env.ADMIN_DOMAINS + ? JSON.parse(process.env.ADMIN_DOMAINS) + : ['example.com'], statusPageUrl: 'status.example.com', diff --git a/services/web/test/unit/src/infrastructure/FeaturesTests.js b/services/web/test/unit/src/infrastructure/FeaturesTests.js index be64d5907c..494bc66777 100644 --- a/services/web/test/unit/src/infrastructure/FeaturesTests.js +++ b/services/web/test/unit/src/infrastructure/FeaturesTests.js @@ -20,7 +20,7 @@ describe('Features', function () { }) describe('with ldap setting', function () { beforeEach(function () { - this.settings.ldap = true + this.settings.ldap = { enable: true } }) it('should return true', function () { expect(this.Features.externalAuthenticationSystemUsed()).to.be.true @@ -28,7 +28,7 @@ describe('Features', function () { }) describe('with saml setting', function () { beforeEach(function () { - this.settings.saml = true + this.settings.saml = { enable: true } }) it('should return true', function () { expect(this.Features.externalAuthenticationSystemUsed()).to.be.true