diff --git a/src/appstore.js b/src/appstore.js index b43482b81..da384134f 100644 --- a/src/appstore.js +++ b/src/appstore.js @@ -20,7 +20,10 @@ exports = module.exports = { getAppUpdate, getBoxUpdate, - createTicket + createTicket, + + // exported for tests + _unregister: unregister }; const apps = require('./apps.js'), @@ -341,6 +344,12 @@ async function registerWithLoginCredentials(options) { await registerCloudron({ domain: settings.dashboardDomain(), accessToken: result.accessToken, version: constants.VERSION }); } +async function unregister() { + await settings.setCloudronId(''); + await settings.setAppstoreApiToken(''); + await settings.setAppstoreWebToken(''); +} + async function createTicket(info, auditSource) { assert.strictEqual(typeof info, 'object'); assert.strictEqual(typeof info.email, 'string'); diff --git a/src/routes/test/appstore-test.js b/src/routes/test/appstore-test.js index d2464cf77..38df6d4e1 100644 --- a/src/routes/test/appstore-test.js +++ b/src/routes/test/appstore-test.js @@ -5,55 +5,43 @@ 'use strict'; -const common = require('./common.js'), +const appstore = require('../../appstore.js'), + common = require('./common.js'), constants = require('../../constants.js'), expect = require('expect.js'), nock = require('nock'), settings = require('../../settings.js'), superagent = require('superagent'); -const { setup, cleanup, serverUrl, owner } = common; +const { setup, cleanup, serverUrl, owner, appstoreToken } = common; describe('Appstore Apps API', function () { before(setup); after(cleanup); - it('cannot list apps without subscription', async function () { + it('cannot list apps when appstore is down', async function () { const response = await superagent.get(`${serverUrl}/api/v1/appstore/apps`) .query({ access_token: owner.token }) .ok(() => true); - expect(response.statusCode).to.be(402); + expect(response.statusCode).to.be(424); }); - it('cannot get app without subscription', async function () { + it('cannot get app with bad token', async function () { + const scope1 = nock(settings.apiServerOrigin()) + .get(`/api/v1/apps/org.wordpress.cloudronapp?accessToken=${appstoreToken}`) + .reply(402, {}); + const response = await superagent.get(`${serverUrl}/api/v1/appstore/apps/org.wordpress.cloudronapp`) .query({ access_token: owner.token }) .ok(() => true); expect(response.statusCode).to.be(402); - }); - - it('register cloudron', async function () { - const scope1 = nock(settings.apiServerOrigin()) - .post('/api/v1/login', (body) => body.email && body.password) - .reply(200, { userId: 'userId', accessToken: 'SECRET_TOKEN' }); - - const scope2 = nock(settings.apiServerOrigin()) - .post('/api/v1/register_cloudron', (body) => !!body.domain && body.accessToken === 'SECRET_TOKEN') - .reply(201, { cloudronId: 'cid', cloudronToken: 'CLOUDRON_TOKEN' }); - - const response = await superagent.post(`${serverUrl}/api/v1/appstore/register_cloudron`) - .send({ email: 'test@cloudron.io', password: 'secret', signup: false }) - .query({ access_token: owner.token }); - - expect(response.statusCode).to.equal(201); expect(scope1.isDone()).to.be.ok(); - expect(scope2.isDone()).to.be.ok(); }); it('can list apps', async function () { const scope1 = nock(settings.apiServerOrigin()) - .get(`/api/v1/apps?accessToken=CLOUDRON_TOKEN&boxVersion=${constants.VERSION}&unstable=true`, () => true) + .get(`/api/v1/apps?accessToken=${appstoreToken}&boxVersion=${constants.VERSION}&unstable=true`, () => true) .reply(200, { apps: [] }); const response = await superagent.get(`${serverUrl}/api/v1/appstore/apps`) @@ -65,7 +53,7 @@ describe('Appstore Apps API', function () { it('can get app', async function () { const scope1 = nock(settings.apiServerOrigin()) - .get('/api/v1/apps/org.wordpress.cloudronapp?accessToken=CLOUDRON_TOKEN', () => true) + .get(`/api/v1/apps/org.wordpress.cloudronapp?accessToken=${appstoreToken}`, () => true) .reply(200, { apps: [] }); const response = await superagent.get(`${serverUrl}/api/v1/appstore/apps/org.wordpress.cloudronapp`) @@ -77,7 +65,7 @@ describe('Appstore Apps API', function () { it('can get app version', async function () { var scope1 = nock(settings.apiServerOrigin()) - .get('/api/v1/apps/org.wordpress.cloudronapp/versions/3.4.2?accessToken=CLOUDRON_TOKEN', () => true) + .get(`/api/v1/apps/org.wordpress.cloudronapp/versions/3.4.2?accessToken=${appstoreToken}`, () => true) .reply(200, { apps: [] }); const response = await superagent.get(`${serverUrl}/api/v1/appstore/apps/org.wordpress.cloudronapp/versions/3.4.2`) @@ -88,16 +76,23 @@ describe('Appstore Apps API', function () { }); }); -describe('Subscription API - no signup', function () { - before(setup); +describe('Appstore Cloudron Registration API - existing user', function () { + before(async function () { + await setup(); + await appstore._unregister(); + }); after(cleanup); it('can setup subscription', async function () { const scope1 = nock(settings.apiServerOrigin()) + .post('/api/v1/register_user', (body) => body.email && body.password) + .reply(201, {}); + + const scope2 = nock(settings.apiServerOrigin()) .post('/api/v1/login', (body) => body.email && body.password) .reply(200, { userId: 'userId', accessToken: 'SECRET_TOKEN' }); - const scope2 = nock(settings.apiServerOrigin()) + const scope3 = nock(settings.apiServerOrigin()) .post('/api/v1/register_cloudron', (body) => !!body.domain && body.accessToken === 'SECRET_TOKEN') .reply(201, { cloudronId: 'cid', cloudronToken: 'CLOUDRON_TOKEN' }); @@ -106,11 +101,15 @@ describe('Subscription API - no signup', function () { .query({ access_token: owner.token }); expect(response.statusCode).to.equal(201); - expect(scope1.isDone()).to.be.ok(); + expect(scope1.isDone()).to.not.be.ok(); // should not have called register_user since signup is false expect(scope2.isDone()).to.be.ok(); + expect(scope3.isDone()).to.be.ok(); + expect(await settings.getAppstoreApiToken()).to.be('CLOUDRON_TOKEN'); + expect(await settings.getAppstoreWebToken()).to.be('SECRET_TOKEN'); + nock.cleanAll(); }); - it('cannot re-setup subscription - already registered', async function () { + it('cannot re-register - already registered', async function () { const response = await superagent.post(`${serverUrl}/api/v1/appstore/register_cloudron`) .send({ email: 'test@cloudron.io', password: 'secret', signup: false }) .query({ access_token: owner.token }) @@ -118,16 +117,33 @@ describe('Subscription API - no signup', function () { expect(response.statusCode).to.equal(409); }); + + it('can get subscription', async function () { + const scope1 = nock(settings.apiServerOrigin()) + .get('/api/v1/subscription?accessToken=CLOUDRON_TOKEN', () => true) + .reply(200, { subscription: { plan: { id: 'free' } }, email: 'test@cloudron.io' }); + + const response = await superagent.get(`${serverUrl}/api/v1/appstore/subscription`) + .query({ access_token: owner.token }); + + expect(response.statusCode).to.equal(200); + expect(response.body.email).to.be('test@cloudron.io'); + expect(response.body.subscription).to.be.an('object'); + expect(scope1.isDone()).to.be.ok(); + }); }); -describe('Subscription API - signup', function () { - before(setup); +describe('Appstore Cloudron Registration API - new user signup', function () { + before(async function () { + await setup(); + await appstore._unregister(); + }); after(cleanup); it('can setup subscription', async function () { const scope1 = nock(settings.apiServerOrigin()) .post('/api/v1/register_user', (body) => body.email && body.password) - .reply(201, { }); + .reply(201, {}); const scope2 = nock(settings.apiServerOrigin()) .post('/api/v1/login', (body) => body.email && body.password) @@ -145,6 +161,17 @@ describe('Subscription API - signup', function () { expect(scope1.isDone()).to.be.ok(); expect(scope2.isDone()).to.be.ok(); expect(scope3.isDone()).to.be.ok(); + expect(await settings.getAppstoreApiToken()).to.be('CLOUDRON_TOKEN'); + expect(await settings.getAppstoreWebToken()).to.be('SECRET_TOKEN'); + }); + + it('cannot re-register - already registered', async function () { + const response = await superagent.post(`${serverUrl}/api/v1/appstore/register_cloudron`) + .send({ email: 'test@cloudron.io', password: 'secret', signup: false }) + .query({ access_token: owner.token }) + .ok(() => true); + + expect(response.statusCode).to.equal(409); }); it('can get subscription', async function () {