From 0a8fc6e8c5b09ba70e0cc1901865ac236246a45e Mon Sep 17 00:00:00 2001 From: Meisam <39205857+MFTabriz@users.noreply.github.com> Date: Wed, 30 Nov 2022 00:49:08 +0100 Subject: [PATCH] validate Nodeinfo response by schema (#2390) * rm stable: 'false' from actions/setup-go@v3 * adapt tests from #2369 * set undefined as defaultStreamKey pass adminpass to sendConfigChangeRequest() * mv getAdminConfig to api/lib/config.js * npm install --quiet for automated tests * refactor tests separate default values from new ones * test adminpass change fix defaultStreamKeys test * fix defaultStreamKeys * use getAdminStatus * mv test/automated/lib/config.js to admin.js * check default hideViewerCount cleanup * test more default options in api erverName SServerSummary yp.instanceUrl FederationConfig.username * more testing of default config params * update reference values for api test --- .github/workflows/hls-tests.yml | 1 - test/automated/api/configmanagement.test.js | 395 ++++++++++++++------ test/automated/api/federation.test.js | 134 +++++++ test/automated/api/lib/admin.js | 52 +++ test/automated/api/package.json | 6 +- test/automated/api/run.sh | 2 +- test/automated/api/schema/nodeinfo_2.0.json | 180 +++++++++ test/automated/browser/run.sh | 2 +- 8 files changed, 653 insertions(+), 119 deletions(-) create mode 100644 test/automated/api/federation.test.js create mode 100644 test/automated/api/lib/admin.js create mode 100644 test/automated/api/schema/nodeinfo_2.0.json diff --git a/.github/workflows/hls-tests.yml b/.github/workflows/hls-tests.yml index 2e003ac50..2decef2de 100644 --- a/.github/workflows/hls-tests.yml +++ b/.github/workflows/hls-tests.yml @@ -27,7 +27,6 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - stable: 'false' go-version: '1.17.2' - name: Run HLS tests run: cd test/automated/hls && ./run.sh diff --git a/test/automated/api/configmanagement.test.js b/test/automated/api/configmanagement.test.js index 43a3abfc1..81f5404b0 100644 --- a/test/automated/api/configmanagement.test.js +++ b/test/automated/api/configmanagement.test.js @@ -1,19 +1,87 @@ var request = require('supertest'); + +const Random = require('crypto-random'); + +const sendConfigChangeRequest = require('./lib/admin').sendConfigChangeRequest; +const getAdminConfig = require('./lib/admin').getAdminConfig; +const getAdminStatus = require('./lib/admin').getAdminStatus; + request = request('http://127.0.0.1:8080'); -const serverName = randomString(); -const streamTitle = randomString(); -const serverSummary = randomString(); -const offlineMessage = randomString(); -const pageContent = `

${randomString()}

`; -const tags = [randomString(), randomString(), randomString()]; -const streamKeys = [ - { key: randomString(), comment: 'test key 1' }, - { key: randomString(), comment: 'test key 1' }, - { key: randomString(), comment: 'test key 1' }, -]; -const latencyLevel = Math.floor(Math.random() * 4); +// initial configuration of server +const defaultServerName = 'New Owncast Server'; +const defaultStreamTitle = undefined; +const defaultLogo = '/logo'; +const defaultOfflineMessage = ''; +const defaultServerSummary = 'This is a new live video streaming server powered by Owncast.'; +const defaultAdminPassword = 'abc123'; +const defaultStreamKeys = [{ key: defaultAdminPassword, comment: 'Default stream key' }]; +const defaultTags = ["owncast", "streaming"]; +const defaultYPConfig = { + enabled: false, + instanceUrl: "" +}; +const defaultS3Config = { + enabled: false, + forcePathStyle: false +}; +const defaultFederationConfig = { + enabled: false, + isPrivate: false, + showEngagement: true, + goLiveMessage: "I've gone live!", + username: "streamer", + blockedDomains: [] +}; +const defaultHideViewerCount = false; +const defaultSocialHandles = [{ + "icon": "/img/platformlogos/github.svg", + "platform": "github", + "url": "https://github.com/owncast/owncast" +}]; +const defaultSocialHandlesAdmin = [{ + "platform": "github", + "url": "https://github.com/owncast/owncast" +}]; +const defaultForbiddenUsernames = [ + "owncast", + "operator", + "admin", + "system", +]; +const defaultPageContent = `

Welcome to Owncast!

+ +
+`; + +// new configuration for testing +const newServerName = randomString(); +const newStreamTitle = randomString(); +const newServerSummary = randomString(); +const newOfflineMessage = randomString(); +const newPageContent = `

${randomString()}

`; +const newTags = [randomString(), randomString(), randomString()]; +const newStreamKeys = [ + { key: randomString(), comment: 'test key 1' }, + { key: randomString(), comment: 'test key 2' }, + { key: randomString(), comment: 'test key 3' }, +]; +const newAdminPassword = randomString(); + +const latencyLevel = Random.range(0, 4); const appearanceValues = { variable1: randomString(), variable2: randomString(), @@ -27,52 +95,113 @@ const streamOutputVariants = { scaledHeight: randomNumber() * 100, scaledWidth: randomNumber() * 100, }; -const socialHandles = [ +const newSocialHandles = [ { url: 'http://facebook.org/' + randomString(), platform: randomString(), }, ]; -const s3Config = { - enabled: true, - endpoint: 'http://' + randomString(), +const newS3Config = { + enabled: !defaultS3Config.enabled, + endpoint: 'http://' + randomString() + ".tld", accessKey: randomString(), secret: randomString(), bucket: randomString(), region: randomString(), - forcePathStyle: true, + forcePathStyle: !defaultS3Config.forcePathStyle, }; -const forbiddenUsernames = [randomString(), randomString(), randomString()]; +const newForbiddenUsernames = [randomString(), randomString(), randomString()]; + +const newYPConfig = { + enabled: !defaultYPConfig.enabled, + instanceUrl: 'http://' + randomString() + ".tld" +}; + +const newFederationConfig = { + enabled: !defaultFederationConfig.enabled, + isPrivate: !defaultFederationConfig.isPrivate, + username: randomString(), + goLiveMessage: randomString(), + showEngagement: !defaultFederationConfig.showEngagement, + blockedDomains: [randomString() + ".tld", randomString() + ".tld"], +}; + +const newHideViewerCount = !defaultHideViewerCount; + + +test('verify default config values', async (done) => { + const res = await request.get('/api/config'); + expect(res.body.name).toBe(defaultServerName); + expect(res.body.streamTitle).toBe(defaultStreamTitle); + expect(res.body.summary).toBe(`${defaultServerSummary}`); + expect(res.body.extraPageContent).toBe(defaultPageContent); + expect(res.body.offlineMessage).toBe(defaultOfflineMessage); + expect(res.body.logo).toBe(defaultLogo); + expect(res.body.socialHandles).toStrictEqual(defaultSocialHandles); + done(); +}); + +test('verify default admin configuration', async (done) => { + const res = await getAdminConfig(); + + expect(res.body.instanceDetails.name).toBe(defaultServerName); + expect(res.body.instanceDetails.summary).toBe(defaultServerSummary); + expect(res.body.instanceDetails.offlineMessage).toBe(defaultOfflineMessage); + expect(res.body.instanceDetails.tags).toStrictEqual(defaultTags); + expect(res.body.instanceDetails.socialHandles).toStrictEqual( + defaultSocialHandlesAdmin + ); + expect(res.body.forbiddenUsernames).toStrictEqual(defaultForbiddenUsernames); + expect(res.body.streamKeys).toStrictEqual(defaultStreamKeys); + + expect(res.body.yp.enabled).toBe(defaultYPConfig.enabled); + expect(res.body.yp.instanceUrl).toBe(defaultYPConfig.instanceUrl); + + expect(res.body.adminPassword).toBe(defaultAdminPassword); + + expect(res.body.s3.enabled).toBe(defaultS3Config.enabled); + expect(res.body.s3.forcePathStyle).toBe(defaultS3Config.forcePathStyle); + expect(res.body.hideViewerCount).toBe(defaultHideViewerCount); + + expect(res.body.federation.enabled).toBe(defaultFederationConfig.enabled); + expect(res.body.federation.username).toBe(defaultFederationConfig.username); + expect(res.body.federation.isPrivate).toBe(defaultFederationConfig.isPrivate); + expect(res.body.federation.showEngagement).toBe(defaultFederationConfig.showEngagement); + expect(res.body.federation.goLiveMessage).toBe(defaultFederationConfig.goLiveMessage); + expect(res.body.federation.blockedDomains).toStrictEqual(defaultFederationConfig.blockedDomains); + done(); + +}); test('set server name', async (done) => { - const res = await sendConfigChangeRequest('name', serverName); + const res = await sendConfigChangeRequest('name', newServerName); done(); }); test('set stream title', async (done) => { - const res = await sendConfigChangeRequest('streamtitle', streamTitle); + const res = await sendConfigChangeRequest('streamtitle', newStreamTitle); done(); }); test('set server summary', async (done) => { - const res = await sendConfigChangeRequest('serversummary', serverSummary); + const res = await sendConfigChangeRequest('serversummary', newServerSummary); done(); }); test('set extra page content', async (done) => { - const res = await sendConfigChangeRequest('pagecontent', pageContent); + const res = await sendConfigChangeRequest('pagecontent', newPageContent); done(); }); test('set tags', async (done) => { - const res = await sendConfigChangeRequest('tags', tags); + const res = await sendConfigChangeRequest('tags', newTags); done(); }); test('set stream keys', async (done) => { - const res = await sendConfigChangeRequest('streamkeys', streamKeys); + const res = await sendConfigChangeRequest('streamkeys', newStreamKeys); done(); }); @@ -92,30 +221,61 @@ test('set video stream output variants', async (done) => { }); test('set social handles', async (done) => { - const res = await sendConfigChangeRequest('socialhandles', socialHandles); + const res = await sendConfigChangeRequest('socialhandles', newSocialHandles); done(); }); test('set s3 configuration', async (done) => { - const res = await sendConfigChangeRequest('s3', s3Config); + const res = await sendConfigChangeRequest('s3', newS3Config); done(); }); test('set forbidden usernames', async (done) => { const res = await sendConfigChangeRequest( 'chat/forbiddenusernames', - forbiddenUsernames + newForbiddenUsernames ); done(); }); -test('set hide viewer count', async (done) => { - const res = await sendConfigChangeRequest('hideviewercount', true); +test('set server url', async (done) => { + const res = await sendConfigChangeRequest('serverurl', newYPConfig.instanceUrl); done(); }); +test('set federation username', async (done) => { + const res = await sendConfigChangeRequest('federation/username', newFederationConfig.username); + done(); +}); + +test('set federation goLiveMessage', async (done) => { + const res = await sendConfigChangeRequest('federation/livemessage', newFederationConfig.goLiveMessage); + done(); +}); + +test('toggle private federation mode', async (done) => { + const res = await sendConfigChangeRequest('federation/private', newFederationConfig.isPrivate); + done(); +}); + +test('toggle federation engagement', async (done) => { + const res = await sendConfigChangeRequest('federation/showengagement', newFederationConfig.showEngagement); + done(); +}); + +test('set federation blocked domains', async (done) => { + const res = await sendConfigChangeRequest('federation/blockdomains', newFederationConfig.blockedDomains); + done(); +}); + + test('set offline message', async (done) => { - const res = await sendConfigChangeRequest('offlinemessage', offlineMessage); + const res = await sendConfigChangeRequest('offlinemessage', newOfflineMessage); + done(); +}); + +test('set hide viewer count', async (done) => { + const res = await sendConfigChangeRequest('hideviewercount', newHideViewerCount); done(); }); @@ -124,88 +284,117 @@ test('set custom style values', async (done) => { done(); }); +test('enable directory', async (done) => { + const res = await sendConfigChangeRequest('directoryenabled', true); + done(); +}); + +test('enable federation', async (done) => { + const res = await sendConfigChangeRequest('federation/enable', newFederationConfig.enabled); + done(); +}); + +test('change admin password', async (done) => { + const res = await sendConfigChangeRequest('adminpass', newAdminPassword); + done(); +}); + +test('verify admin password change', async (done) => { + const res = await getAdminConfig(adminPassword = newAdminPassword); + + expect(res.body.adminPassword).toBe(newAdminPassword); + done(); +}); + +test('reset admin password', async (done) => { + const res = await sendConfigChangeRequest('adminpass', defaultAdminPassword, adminPassword = newAdminPassword); + done(); +}); + test('verify updated config values', async (done) => { const res = await request.get('/api/config'); - expect(res.body.name).toBe(serverName); - expect(res.body.streamTitle).toBe(streamTitle); - expect(res.body.summary).toBe(`${serverSummary}`); - expect(res.body.extraPageContent).toBe(pageContent); - expect(res.body.offlineMessage).toBe(offlineMessage); + expect(res.body.name).toBe(newServerName); + expect(res.body.streamTitle).toBe(newStreamTitle); + expect(res.body.summary).toBe(`${newServerSummary}`); + expect(res.body.extraPageContent).toBe(newPageContent); + expect(res.body.offlineMessage).toBe(newOfflineMessage); expect(res.body.logo).toBe('/logo'); - expect(res.body.socialHandles).toStrictEqual(socialHandles); + expect(res.body.socialHandles).toStrictEqual(newSocialHandles); done(); }); // Test that the raw video details being broadcasted are coming through -test('admin stream details are correct', (done) => { - request - .get('/api/admin/status') - .auth('admin', 'abc123') - .expect(200) - .then((res) => { - expect(res.body.broadcaster.streamDetails.width).toBe(320); - expect(res.body.broadcaster.streamDetails.height).toBe(180); - expect(res.body.broadcaster.streamDetails.framerate).toBe(24); - expect(res.body.broadcaster.streamDetails.videoBitrate).toBe(1269); - expect(res.body.broadcaster.streamDetails.videoCodec).toBe('H.264'); - expect(res.body.broadcaster.streamDetails.audioCodec).toBe('AAC'); - expect(res.body.online).toBe(true); - done(); - }); +test('verify admin stream details', async (done) => { + const res = await getAdminStatus(); + + expect(res.body.broadcaster.streamDetails.width).toBe(320); + expect(res.body.broadcaster.streamDetails.height).toBe(180); + expect(res.body.broadcaster.streamDetails.framerate).toBe(24); + expect(res.body.broadcaster.streamDetails.videoBitrate).toBe(1269); + expect(res.body.broadcaster.streamDetails.videoCodec).toBe('H.264'); + expect(res.body.broadcaster.streamDetails.audioCodec).toBe('AAC'); + expect(res.body.online).toBe(true); + done(); }); -test('admin configuration is correct', (done) => { - request - .get('/api/admin/serverconfig') - .auth('admin', 'abc123') - .expect(200) - .then((res) => { - expect(res.body.instanceDetails.name).toBe(serverName); - expect(res.body.instanceDetails.summary).toBe(serverSummary); - expect(res.body.instanceDetails.offlineMessage).toBe(offlineMessage); - expect(res.body.instanceDetails.tags).toStrictEqual(tags); - expect(res.body.instanceDetails.socialHandles).toStrictEqual( - socialHandles - ); - expect(res.body.forbiddenUsernames).toStrictEqual(forbiddenUsernames); - expect(res.body.streamKeys).toStrictEqual(streamKeys); +test('verify updated admin configuration', async (done) => { + const res = await getAdminConfig(); - expect(res.body.videoSettings.latencyLevel).toBe(latencyLevel); - expect(res.body.videoSettings.videoQualityVariants[0].framerate).toBe( - streamOutputVariants.framerate - ); - expect(res.body.videoSettings.videoQualityVariants[0].cpuUsageLevel).toBe( - streamOutputVariants.cpuUsageLevel - ); + expect(res.body.instanceDetails.name).toBe(newServerName); + expect(res.body.instanceDetails.summary).toBe(newServerSummary); + expect(res.body.instanceDetails.offlineMessage).toBe(newOfflineMessage); + expect(res.body.instanceDetails.tags).toStrictEqual(newTags); + expect(res.body.instanceDetails.socialHandles).toStrictEqual( + newSocialHandles + ); + expect(res.body.forbiddenUsernames).toStrictEqual(newForbiddenUsernames); + expect(res.body.streamKeys).toStrictEqual(newStreamKeys); - expect(res.body.yp.enabled).toBe(false); - expect(res.body.adminPassword).toBe('abc123'); + expect(res.body.videoSettings.latencyLevel).toBe(latencyLevel); + expect(res.body.videoSettings.videoQualityVariants[0].framerate).toBe( + streamOutputVariants.framerate + ); + expect(res.body.videoSettings.videoQualityVariants[0].cpuUsageLevel).toBe( + streamOutputVariants.cpuUsageLevel + ); + + expect(res.body.yp.enabled).toBe(newYPConfig.enabled); + expect(res.body.yp.instanceUrl).toBe(newYPConfig.instanceUrl); + + expect(res.body.adminPassword).toBe(defaultAdminPassword); + + expect(res.body.s3.enabled).toBe(newS3Config.enabled); + expect(res.body.s3.endpoint).toBe(newS3Config.endpoint); + expect(res.body.s3.accessKey).toBe(newS3Config.accessKey); + expect(res.body.s3.secret).toBe(newS3Config.secret); + expect(res.body.s3.bucket).toBe(newS3Config.bucket); + expect(res.body.s3.region).toBe(newS3Config.region); + expect(res.body.s3.forcePathStyle).toBe(newS3Config.forcePathStyle); + expect(res.body.hideViewerCount).toBe(newHideViewerCount); + + expect(res.body.federation.enabled).toBe(newFederationConfig.enabled); + expect(res.body.federation.isPrivate).toBe(newFederationConfig.isPrivate); + expect(res.body.federation.username).toBe(newFederationConfig.username); + expect(res.body.federation.goLiveMessage).toBe(newFederationConfig.goLiveMessage); + expect(res.body.federation.showEngagement).toBe(newFederationConfig.showEngagement); + expect(res.body.federation.blockedDomains).toStrictEqual(newFederationConfig.blockedDomains); + done(); - expect(res.body.s3.enabled).toBe(s3Config.enabled); - expect(res.body.s3.endpoint).toBe(s3Config.endpoint); - expect(res.body.s3.accessKey).toBe(s3Config.accessKey); - expect(res.body.s3.secret).toBe(s3Config.secret); - expect(res.body.s3.bucket).toBe(s3Config.bucket); - expect(res.body.s3.region).toBe(s3Config.region); - expect(res.body.s3.forcePathStyle).toBe(true); - expect(res.body.hideViewerCount).toBe(true); - done(); - }); }); -test('frontend configuration is correct', (done) => { +test('verify updated frontend configuration', (done) => { request .get('/api/config') .expect(200) .then((res) => { - expect(res.body.name).toBe(serverName); + expect(res.body.name).toBe(newServerName); expect(res.body.logo).toBe('/logo'); - expect(res.body.socialHandles).toStrictEqual(socialHandles); + expect(res.body.socialHandles).toStrictEqual(newSocialHandles); done(); }); }); -test('frontend status is correct', (done) => { +test('verify frontend status', (done) => { request .get('/api/status') .expect(200) @@ -215,35 +404,11 @@ test('frontend status is correct', (done) => { }); }); -async function sendConfigChangeRequest(endpoint, value) { - const url = '/api/admin/config/' + endpoint; - const res = await request - .post(url) - .auth('admin', 'abc123') - .send({ value: value }) - .expect(200); - - expect(res.body.success).toBe(true); - return res; -} - -async function sendConfigChangePayload(endpoint, payload) { - const url = '/api/admin/config/' + endpoint; - const res = await request - .post(url) - .auth('admin', 'abc123') - .send(payload) - .expect(200); - - expect(res.body.success).toBe(true); - - return res; -} function randomString(length = 20) { - return Math.random().toString(16).substr(2, length); + return Random.value().toString(16).substr(2, length); } function randomNumber() { - return Math.floor(Math.random() * 5); + return Random.range(0, 5); } diff --git a/test/automated/api/federation.test.js b/test/automated/api/federation.test.js new file mode 100644 index 000000000..b1d9395f3 --- /dev/null +++ b/test/automated/api/federation.test.js @@ -0,0 +1,134 @@ +var request = require('supertest') +const jsonfile = require('jsonfile') +const Ajv = require("ajv-draft-04") +const sendConfigChangeRequest = require('./lib/admin').sendConfigChangeRequest; + +request = request('http://127.0.0.1:8080'); + +var ajv = new Ajv(); +var nodeInfoSchema = jsonfile.readFileSync('schema/nodeinfo_2.0.json'); + +test('disable federation', async (done) => { + const res = await sendConfigChangeRequest('federation/enable', false); + done(); +}); + +test('verify responses of /.well-known/webfinger when federation is disabled', async (done) => { + const res = request + .get('/.well-known/webfinger') + .expect(405); + done(); +}); + +test('verify responses of /.well-known/host-meta when federation is disabled', async (done) => { + const res = request + .get('/.well-known/host-meta') + .expect(405); + done(); +}); + +test('verify responses of /.well-known/nodeinfo when federation is disabled', async (done) => { + const res = request + .get('/.well-known/nodeinfo') + .expect(405); + done(); +}); + +test('verify responses of /.well-known/x-nodeinfo2 when federation is disabled', async (done) => { + const res = request + .get('/.well-known/x-nodeinfo2') + .expect(405); + done(); +}); + +test('verify responses of /nodeinfo/2.0 when federation is disabled', async (done) => { + const res = request + .get('/nodeinfo/2.0') + .expect(405); + done(); +}); + +test('verify responses of /api/v1/instance when federation is disabled', async (done) => { + const res = request + .get('/api/v1/instance') + .expect(405); + done(); +}); + +test('verify responses of /federation/user/ when federation is disabled', async (done) => { + const res = request + .get('/federation/user/') + .expect(405); + done(); +}); + +test('verify responses of /federation/ when federation is disabled', async (done) => { + const res = request + .get('/federation/') + .expect(405); + done(); +}); + +test('enable federation', async (done) => { + const res = await sendConfigChangeRequest('federation/enable', true); + done(); +}); + +test('verify responses of /.well-known/webfinger when federation is enabled', async (done) => { + const res = request + .get('/.well-known/webfinger') + .expect(200); + done(); +}); + +test('verify responses of /.well-known/host-meta when federation is enabled', async (done) => { + const res = request + .get('/.well-known/host-meta') + .expect(200); + done(); +}); + +test('verify responses of /.well-known/nodeinfo when federation is enabled', async (done) => { + const res = request + .get('/.well-known/nodeinfo') + .expect(200); + done(); +}); + +test('verify responses of /.well-known/x-nodeinfo2 when federation is enabled', async (done) => { + const res = request + .get('/.well-known/x-nodeinfo2') + .expect(200); + done(); +}); + +test('verify responses of /nodeinfo/2.0 when federation is enabled', async (done) => { + const res = request + .get('/nodeinfo/2.0') + .expect(200) + .then((res) => { + expect(ajv.validate(nodeInfoSchema, res.body)).toBe(true); + done(); + }); +}); + +test('verify responses of /api/v1/instance when federation is enabled', async (done) => { + const res = request + .get('/api/v1/instance') + .expect(200); + done(); +}); + +test('verify responses of /federation/user/ when federation is enabled', async (done) => { + const res = request + .get('/federation/user/') + .expect(200); + done(); +}); + +test('verify responses of /federation/ when federation is enabled', async (done) => { + const res = request + .get('/federation/') + .expect(200); + done(); +}); diff --git a/test/automated/api/lib/admin.js b/test/automated/api/lib/admin.js new file mode 100644 index 000000000..0841b16e6 --- /dev/null +++ b/test/automated/api/lib/admin.js @@ -0,0 +1,52 @@ +var request = require('supertest'); +request = request('http://127.0.0.1:8080'); + +const defaultAdminPassword = 'abc123'; + +async function getAdminConfig(adminPassword = defaultAdminPassword) { + const res = request + .get('/api/admin/serverconfig') + .auth('admin', adminPassword) + .expect(200); + + return res; +} + +async function getAdminStatus(adminPassword = defaultAdminPassword) { + const res = request + .get('/api/admin/status') + .auth('admin', adminPassword) + .expect(200); + + return res; +} + +async function sendConfigChangeRequest(endpoint, value, adminPassword = defaultAdminPassword) { + const url = '/api/admin/config/' + endpoint; + const res = await request + .post(url) + .auth('admin', adminPassword) + .send({ value: value }) + .expect(200); + + expect(res.body.success).toBe(true); + return res; +} + +async function sendConfigChangePayload(endpoint, payload, adminPassword = defaultAdminPassword) { + const url = '/api/admin/config/' + endpoint; + const res = await request + .post(url) + .auth('admin', adminPassword) + .send(payload) + .expect(200); + + expect(res.body.success).toBe(true); + + return res; +} + +module.exports.getAdminConfig = getAdminConfig; +module.exports.getAdminStatus = getAdminStatus; +module.exports.sendConfigChangeRequest = sendConfigChangeRequest; +module.exports.sendConfigChangePayload = sendConfigChangePayload; diff --git a/test/automated/api/package.json b/test/automated/api/package.json index dcd0066b2..3e4d402d0 100644 --- a/test/automated/api/package.json +++ b/test/automated/api/package.json @@ -10,7 +10,11 @@ "license": "ISC", "dependencies": { "supertest": "^6.0.1", - "websocket": "^1.0.32" + "websocket": "^1.0.32", + "ajv": "^8.11.0", + "ajv-draft-04" : "^1.0.0", + "jsonfile": "^6.1.0", + "crypto-random": "^2.0.1" }, "devDependencies": { "jest": "^26.6.3" diff --git a/test/automated/api/run.sh b/test/automated/api/run.sh index 22c4d3a8a..dde360cf9 100755 --- a/test/automated/api/run.sh +++ b/test/automated/api/run.sh @@ -3,7 +3,7 @@ TEMP_DB=$(mktemp) # Install the node test framework -npm install #--silent >/dev/null +npm install --quiet --no-progress # Download a specific version of ffmpeg if [ ! -d "ffmpeg" ]; then diff --git a/test/automated/api/schema/nodeinfo_2.0.json b/test/automated/api/schema/nodeinfo_2.0.json new file mode 100644 index 000000000..da56bed13 --- /dev/null +++ b/test/automated/api/schema/nodeinfo_2.0.json @@ -0,0 +1,180 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "http://nodeinfo.diaspora.software/ns/schema/2.0#", + "description": "NodeInfo schema version 2.0.", + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "software", + "protocols", + "services", + "openRegistrations", + "usage", + "metadata" + ], + "properties": { + "version": { + "description": "The schema version, must be 2.0.", + "enum": [ + "2.0" + ] + }, + "software": { + "description": "Metadata about server software in use.", + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "description": "The canonical name of this server software.", + "type": "string", + "pattern": "^[a-z0-9-]+$" + }, + "version": { + "description": "The version of this server software.", + "type": "string" + } + } + }, + "protocols": { + "description": "The protocols supported on this server.", + "type": "array", + "minItems": 1, + "items": { + "enum": [ + "activitypub", + "buddycloud", + "dfrn", + "diaspora", + "libertree", + "ostatus", + "pumpio", + "tent", + "xmpp", + "zot" + ] + } + }, + "services": { + "description": "The third party sites this server can connect to via their application API.", + "type": "object", + "additionalProperties": false, + "required": [ + "inbound", + "outbound" + ], + "properties": { + "inbound": { + "description": "The third party sites this server can retrieve messages from for combined display with regular traffic.", + "type": "array", + "minItems": 0, + "items": { + "enum": [ + "atom1.0", + "gnusocial", + "imap", + "pnut", + "pop3", + "pumpio", + "rss2.0", + "twitter" + ] + } + }, + "outbound": { + "description": "The third party sites this server can publish messages to on the behalf of a user.", + "type": "array", + "minItems": 0, + "items": { + "enum": [ + "atom1.0", + "blogger", + "buddycloud", + "diaspora", + "dreamwidth", + "drupal", + "facebook", + "friendica", + "gnusocial", + "google", + "insanejournal", + "libertree", + "linkedin", + "livejournal", + "mediagoblin", + "myspace", + "pinterest", + "pnut", + "posterous", + "pumpio", + "redmatrix", + "rss2.0", + "smtp", + "tent", + "tumblr", + "twitter", + "wordpress", + "xmpp" + ] + } + } + } + }, + "openRegistrations": { + "description": "Whether this server allows open self-registration.", + "type": "boolean" + }, + "usage": { + "description": "Usage statistics for this server.", + "type": "object", + "additionalProperties": false, + "required": [ + "users" + ], + "properties": { + "users": { + "description": "statistics about the users of this server.", + "type": "object", + "additionalProperties": false, + "properties": { + "total": { + "description": "The total amount of on this server registered users.", + "type": "integer", + "minimum": 0 + }, + "activeHalfyear": { + "description": "The amount of users that signed in at least once in the last 180 days.", + "type": "integer", + "minimum": 0 + }, + "activeMonth": { + "description": "The amount of users that signed in at least once in the last 30 days.", + "type": "integer", + "minimum": 0 + } + } + }, + "localPosts": { + "description": "The amount of posts that were made by users that are registered on this server.", + "type": "integer", + "minimum": 0 + }, + "localComments": { + "description": "The amount of comments that were made by users that are registered on this server.", + "type": "integer", + "minimum": 0 + } + } + }, + "metadata": { + "description": "Free form key value pairs for software specific values. Clients should not rely on any specific key present.", + "type": "object", + "minProperties": 0, + "additionalProperties": true + } + } +} diff --git a/test/automated/browser/run.sh b/test/automated/browser/run.sh index 84d2781d4..fe7e48673 100755 --- a/test/automated/browser/run.sh +++ b/test/automated/browser/run.sh @@ -17,7 +17,7 @@ echo "Bundling web code into server..." # Install the web test framework echo "Installing test dependencies..." pushd test/automated/browser -npm install --silent >/dev/null +npm install --quiet --no-progress popd