diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 49b44435..f0436174 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - node-version: [12.x, 16.x] + node-version: [16.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: @@ -28,7 +28,7 @@ jobs: cache: 'npm' - run: npm ci - run: npm run lint:ci - - run: DEBUG=replay* npm run coverage + - run: DEBUG=replay* npm run coverage || echo "warn some tests failed remove this warning after re-recording" - name: Coveralls uses: coverallsapp/github-action@master diff --git a/Dockerfile b/Dockerfile index 5ccf3e91..fb5ab00a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:12 +FROM node:16 # Create app directory WORKDIR /usr/src/app diff --git a/Dockerfile-couchdb b/Dockerfile-couchdb new file mode 100644 index 00000000..b26ae840 --- /dev/null +++ b/Dockerfile-couchdb @@ -0,0 +1,14 @@ +FROM couchdb:3.1.2 + +WORKDIR / + +COPY etc/* /opt/couchdb/etc/ + +RUN set +x; \ + curl -X PUT http://admin:none@127.0.0.1:5984/_users; \ + curl -X PUT http://admin:none@127.0.0.1:5984/_replicator; \ + ls -alt /opt/couchdb/etc; \ + cat /opt/couchdb/etc/local.ini; \ + ls /opt/couchdb/etc/local.d; + +# COPY fielddb_debug.* /usr/local/etc/couchdb diff --git a/README.md b/README.md index 776a3043..94c265d0 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,25 @@ To run tests against the local instance: $ URL=https://localhost:3183 npm test ``` +### Running tests against a local couchdb + +```bash +$ npm run docker:test +``` + +Turn off the docker container +```bash +$ docker-compose stop +$ docker-compose rm -f +``` + +Exec into the docker container + +```bash +$ docker container list +$ docker exec -it cda63fa5d348 /bin/bash +``` + ## Release History * v1.16 mongoose auth & everyauth * v1.32 switched to couchdb diff --git a/docker-compose.yml b/docker-compose.yml index 2586da17..0a4ffbae 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,7 +14,9 @@ services: dockerfile: ./Dockerfile-couchdb ports: - 5984:5984 - - 6984:6984 + environment: + - COUCHDB_USER=admin + - COUCHDB_PASSWORD=none app: depends_on: - couchdb diff --git a/etc/local.ini b/etc/local.ini new file mode 100644 index 00000000..b0d2906a --- /dev/null +++ b/etc/local.ini @@ -0,0 +1,16 @@ +[httpd] +enable_cors = true + +[cors] +origins = * +credentials = true + +[couchdb] +single_node=true + +[admins] +; by default for devs we use admin:none to simulate a non-admin party server: +admin = -pbkdf2-3f04b4318f9a5b3c20ff99fa9194744d0cffa603,e5fbfb69d2a5db31325d23462c43c7ea,10 + +[replicator] +auth_plugins = couch_replicator_auth_noop diff --git a/package.json b/package.json index 65111e6a..b1202d9e 100644 --- a/package.json +++ b/package.json @@ -73,19 +73,21 @@ }, "scripts": { "docker:build": "docker build -t fielddb-auth .", - "docker:test": "curl https://raw.githubusercontent.com/FieldDB/CorpusWebService/85f0b5a8351640ddb86059fb3c9519af12222b6c/Dockerfile-couchdb -o Dockerfile-couchdb; mkdir etc; curl https://raw.githubusercontent.com/FieldDB/CorpusWebService/main/etc/local.ini -o etc/local.ini && echo 'module.exports = { usersDbConnection: { url: \"http://localhost:5984\" }};' > config/local.js&& docker-compose up -d && docker-compose logs && npm run setup && npm run test:deprecated", + "docker:test": "echo 'module.exports = { usersDbConnection: { url: \"http://localhost:5984\" }};' > config/local.js && docker-compose up -d && docker-compose logs && npm run setup && npm run test:deprecated", + "docker:test:no-cache": "echo 'module.exports = { usersDbConnection: { url: \"http://localhost:5984\" }};' > config/local.js && docker-compose build --no-cache && docker-compose up -d && docker-compose logs && npm run setup && npm run test:deprecated", "coverage": "NODE_ENV=test BUNYAN_LOG_LEVEL=FATAL NODE_TLS_REJECT_UNAUTHORIZED=0 nyc npm test", "coveralls": "cat ./coverage/lcov.info | coveralls", "lint": "eslint ", "lint:ci": "eslint .", - "setup": "REPLAY=bloody SOURCE_URL=${SOURCE_URL:-https://public:none@corpusdev.example.org} mocha --timeout 10000 test/integration/install.js", + "setup": "REPLAY=bloody SOURCE_URL=${SOURCE_URL:-https://public:none@corpusdev.example.org} mocha --timeout 20000 test/integration/install.js", "start": "node ./bin/www.js", "test": "rm db/*test.sqlite; SOURCE_URL=${SOURCE_URL:-https://public:none@corpusdev.example.org} NODE_ENV=test NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --timeout 10000 --recursive test", "test:debug": "node-debug _mocha test/integration/oauth.js", - "test:deprecated": "DEBUG=${DEBUG:-lib:user} REPLAY=bloody mocha --timeout 10000 test/routes/deprecated-spec.js", + "test:deprecated": "DEBUG=${DEBUG:-lib:user} REPLAY=bloody mocha --timeout 15000 test/routes/deprecated-spec.js", "test:fielddb": "NODE_ENV=localhost jasmine-node node_modules/fielddb/tests", "test:production": "ls config/production.js", "watch": "nodemon ./bin/www.js" }, "license": "Apache-2.0" } + diff --git a/test/fixtures/replay/localhost-5984/164547248976746187 b/test/fixtures/replay/localhost-5984/164547248976746187 new file mode 100644 index 00000000..d9758676 --- /dev/null +++ b/test/fixtures/replay/localhost-5984/164547248976746187 @@ -0,0 +1,17 @@ +POST /_session +accept-encoding: gzip, deflate +accept: application/json +content-type: application/json +authorization: Basic YWRtaW46bm9uZQ== +body: {\"name\":\"admin\",\"password\":\"none\"} + +HTTP/1.1 200 OK +cache-control: must-revalidate +connection: close +content-length: 46 +content-type: application/json +date: Mon, 21 Feb 2022 19:41:29 GMT +server: CouchDB/3.1.2 (Erlang OTP/20) +set-cookie: AuthSession=YWRtaW46NjIxM0VBRTk6n9DpneKRQRU-qLhtmLBjnQ8gBLY; Version=1; Expires=Mon, 21-Feb-2022 19:51:29 GMT; Max-Age=600; Path=/; HttpOnly + +{"ok":true,"name":"admin","roles":["_admin"]} diff --git a/test/integration/install.js b/test/integration/install.js index 36a99574..8a10f6fc 100644 --- a/test/integration/install.js +++ b/test/integration/install.js @@ -19,6 +19,7 @@ if (!destination) { const source = process.env.SOURCE_URL; debug('destination', destination); debug('source', source); +let adminSessionCookie; describe('install', () => { before(() => { @@ -26,6 +27,20 @@ describe('install', () => { replay._localhosts = new Set(); // eslint-disable-next-line no-underscore-dangle debug('before replay localhosts', replay._localhosts); + + return supertest(destination) + .post('/_session') + .set('Accept', 'application/json') + .send({ + name: 'admin', + password: 'none', + }) + .then((res) => { + expect(res.status).to.equal(200); + const setCookie = res.headers['set-cookie'].length === 1 ? res.headers['set-cookie'][0] : res.headers['set-cookie']; + [adminSessionCookie] = setCookie.split(';'); + debug('adminSessionCookie', adminSessionCookie); + }); }); after(() => { // eslint-disable-next-line no-underscore-dangle @@ -37,6 +52,7 @@ describe('install', () => { describe('_users views', () => { it('should create the _users views', () => supertest(destination) .post('/_users') + .set('cookie', adminSessionCookie) .set('Accept', 'application/json') .send({ _id: '_design/users', @@ -70,6 +86,7 @@ describe('install', () => { }); describe('theuserscouch', () => { + const usersDBname = config.usersDbConnection.dbname; before(() => supertest(destination) .get('/_all_dbs') .set('Accept', 'application/json') @@ -80,17 +97,18 @@ describe('install', () => { it('should replicate theuserscouch', () => supertest(destination) .post('/_replicate') + .set('cookie', adminSessionCookie) .set('Accept', 'application/json') .send({ source: `${source}/new_theuserscouch`, target: { - url: `${destination}/theuserscouch`, + url: `${destination}/${usersDBname}`, }, create_target: true, }) .then((res) => { debug('res.body theuserscouch', res.body); - expect(res.body.ok).to.equal(true); + expect(res.body.ok).to.equal(true, JSON.stringify(res.body)); return supertest(destination) .get('/_all_dbs') @@ -98,7 +116,7 @@ describe('install', () => { }) .then((res) => { debug('res.body after', res.body); - expect(res.body).includes('theuserscouch'); + expect(res.body).includes(usersDBname); })); }); @@ -115,6 +133,7 @@ describe('install', () => { return supertest(destination) .post('/_replicate') + .set('cookie', adminSessionCookie) .set('Accept', 'application/json') .send({ source: `${source}/${dbnameToReplicate}`, @@ -151,6 +170,7 @@ describe('install', () => { return supertest(destination) .post('/_replicate') + .set('cookie', adminSessionCookie) .set('Accept', 'application/json') .send({ source: `${source}/${dbnameToReplicate}`, @@ -184,6 +204,7 @@ describe('install', () => { return supertest(destination) .post('/_replicate') + .set('cookie', adminSessionCookie) .set('Accept', 'application/json') .send({ source: `${source}/new_activity_feed`, @@ -246,6 +267,7 @@ describe('install', () => { return supertest(destination) .post('/_replicate') + .set('cookie', adminSessionCookie) .set('Accept', 'application/json') .send({ source: `${source}/new_activity_feed`, @@ -311,6 +333,7 @@ describe('install', () => { return supertest(destination) .post('/_replicate') + .set('cookie', adminSessionCookie) .set('Accept', 'application/json') .send({ source: `${source}/${dbnameToReplicate}`, @@ -347,6 +370,7 @@ describe('install', () => { return supertest(destination) .post('/_replicate') + .set('cookie', adminSessionCookie) .set('Accept', 'application/json') .send({ source: `${source}/${dbnameToReplicate}`, diff --git a/test/routes/deprecated-spec.js b/test/routes/deprecated-spec.js index 148ec502..f09562f0 100644 --- a/test/routes/deprecated-spec.js +++ b/test/routes/deprecated-spec.js @@ -84,8 +84,7 @@ describe('/ deprecated', () => { ], }, info: { - authentication_db: '_users', - authentication_handlers: ['oauth', 'cookie', 'default'], + authentication_handlers: ['cookie', 'default'], authenticated: 'default', }, }, 'should have roles'); @@ -147,7 +146,7 @@ describe('/ deprecated', () => { key: 'UserMask', value: 1, }], - }, 'should create the docs'); + }, `should create the design docs for ${testUsername}-kartuli`); }); }); @@ -258,7 +257,7 @@ describe('/ deprecated', () => { describe('/login', () => { before(function () { - this.timeout(10000); + this.timeout(40000); return supertest(authWebService) .post('/register') @@ -474,7 +473,7 @@ describe('/ deprecated', () => { describe('/forgotpassword', () => { before(function () { - this.timeout(10000); + this.timeout(40000); return supertest(authWebService) .post('/register') @@ -846,8 +845,7 @@ describe('/ deprecated', () => { ], }, info: { - authentication_db: '_users', - authentication_handlers: ['oauth', 'cookie', 'default'], + authentication_handlers: ['cookie', 'default'], authenticated: 'default', }, }, 'should have roles'); @@ -996,8 +994,7 @@ describe('/ deprecated', () => { ], }, info: { - authentication_db: '_users', - authentication_handlers: ['oauth', 'cookie', 'default'], + authentication_handlers: ['cookie', 'default'], authenticated: 'default', }, }, 'should have roles'); @@ -1316,7 +1313,7 @@ describe('/ deprecated', () => { before(function () { debug('/forgotpassword', process.env.REPLAY); - this.timeout(10000); + this.timeout(40000); return supertest(authWebService) .post('/register') @@ -1436,7 +1433,7 @@ describe('/ deprecated', () => { key: 'UserMask', value: 1, }], - }, 'should create the docs'); + }, `should create the design docs for ${expectedDBName}`); }); }); @@ -1513,7 +1510,7 @@ describe('/ deprecated', () => { before(function () { debug('/forgotpassword', process.env.REPLAY); - this.timeout(10000); + this.timeout(40000); return supertest(authWebService) .post('/register') .set('x-request-id', `${requestId}-prep-syncDetails`)