From c7a15ecc66e656051a9390d1a0f60bffe4b9fecd Mon Sep 17 00:00:00 2001 From: "TAKIMOTO, Atsushi" Date: Sat, 23 Feb 2019 13:33:37 +0900 Subject: [PATCH] Add allowAnonymousViews option resolve #1144 set to `false` to delete `freely`, `editable` and `locked` permission when allowAnonymous is true (default is `true`) Signed-off-by: hakoai --- app.js | 1 + lib/config/default.js | 1 + lib/config/environment.js | 1 + lib/config/index.js | 10 +++- lib/realtimeClientConnection.js | 15 ++++- public/views/codimd/body.ejs | 12 ++-- test/realtime/socket-events.test.js | 86 +++++++++++++++++++++++++++-- 7 files changed, 113 insertions(+), 13 deletions(-) diff --git a/app.js b/app.js index 50dae472..4093bd3b 100644 --- a/app.js +++ b/app.js @@ -180,6 +180,7 @@ app.locals.serverURL = config.serverURL app.locals.sourceURL = config.sourceURL app.locals.allowAnonymous = config.allowAnonymous app.locals.allowAnonymousEdits = config.allowAnonymousEdits +app.locals.permission = config.permission app.locals.allowPDFExport = config.allowPDFExport app.locals.authProviders = { facebook: config.isFacebookEnable, diff --git a/lib/config/default.js b/lib/config/default.js index 3fc11fcc..93de2599 100644 --- a/lib/config/default.js +++ b/lib/config/default.js @@ -31,6 +31,7 @@ module.exports = { useCDN: true, allowAnonymous: true, allowAnonymousEdits: false, + allowAnonymousViews: true, allowFreeURL: false, forbiddenNoteIDs: ['robots.txt', 'favicon.ico', 'api'], defaultPermission: 'editable', diff --git a/lib/config/environment.js b/lib/config/environment.js index 09a27e14..de573e18 100644 --- a/lib/config/environment.js +++ b/lib/config/environment.js @@ -27,6 +27,7 @@ module.exports = { useCDN: toBooleanConfig(process.env.CMD_USECDN), allowAnonymous: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS), allowAnonymousEdits: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_EDITS), + allowAnonymousViews: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_VIEWS), allowFreeURL: toBooleanConfig(process.env.CMD_ALLOW_FREEURL), forbiddenNoteIDs: toArrayConfig(process.env.CMD_FORBIDDEN_NOTE_IDS), defaultPermission: process.env.CMD_DEFAULT_PERMISSION, diff --git a/lib/config/index.js b/lib/config/index.js index 1dd9fbe7..22e7ec47 100644 --- a/lib/config/index.js +++ b/lib/config/index.js @@ -68,11 +68,17 @@ if (config.ldap.tlsca) { // Permission config.permission = Permission -if (!config.allowAnonymous && !config.allowAnonymousEdits) { +let defaultPermission = config.permission.editable +if (!config.allowAnonymous && !config.allowAnonymousViews) { + delete config.permission.freely + delete config.permission.editable + delete config.permission.locked + defaultPermission = config.permission.limited +} else if (!config.allowAnonymous && !config.allowAnonymousEdits) { delete config.permission.freely } if (!(config.defaultPermission in config.permission)) { - config.defaultPermission = config.permission.editable + config.defaultPermission = defaultPermission } // cache result, cannot change config in runtime!!! diff --git a/lib/realtimeClientConnection.js b/lib/realtimeClientConnection.js index b8aaa054..b1490791 100644 --- a/lib/realtimeClientConnection.js +++ b/lib/realtimeClientConnection.js @@ -57,6 +57,19 @@ class RealtimeClientConnection { return config.allowAnonymous || config.allowAnonymousEdits } + getAvailablePermissions () { + // TODO: move this method to config module + const availablePermission = Object.assign({}, config.permission) + if (!config.allowAnonymous && !config.allowAnonymousViews) { + delete availablePermission.freely + delete availablePermission.editable + delete availablePermission.locked + } else if (!config.allowAnonymous && !config.allowAnonymousEdits) { + delete availablePermission.freely + } + return availablePermission + } + getCurrentUser () { if (!this.socket.id) return return this.realtime.getUserFromUserPool(this.socket.id) @@ -211,7 +224,7 @@ class RealtimeClientConnection { const note = this.getCurrentNote() // Only owner can change permission if (!this.isNoteOwner()) return - if (!this.isAnonymousEnable() && permission === 'freely') return + if (!(permission in this.getAvailablePermissions())) return this.changeNotePermission(permission) .then(() => { diff --git a/public/views/codimd/body.ejs b/public/views/codimd/body.ejs index dc111909..b7b730f2 100644 --- a/public/views/codimd/body.ejs +++ b/public/views/codimd/body.ejs @@ -15,12 +15,12 @@ diff --git a/test/realtime/socket-events.test.js b/test/realtime/socket-events.test.js index 0a6aa7af..0015d179 100644 --- a/test/realtime/socket-events.test.js +++ b/test/realtime/socket-events.test.js @@ -56,7 +56,15 @@ describe('realtime#socket event', function () { }) configMock = { fullversion: '1.5.0', - minimumCompatibleVersion: '1.0.0' + minimumCompatibleVersion: '1.0.0', + permission: { + freely: 'freely', + editable: 'editable', + limited: 'limited', + locked: 'locked', + protected: 'protected', + private: 'private' + } } mock('../../lib/logger', { error: () => { @@ -522,9 +530,10 @@ describe('realtime#socket event', function () { }, 5) }) - it('should change permission to freely when config allowAnonymous and allowAnonymousEdits are true', function (done) { + it('should change permission to freely when config allowAnonymous, allowAnonymousEdits and allowAnonymousViews are true', function (done) { configMock.allowAnonymous = true configMock.allowAnonymousEdits = true + configMock.allowAnonymousViews = true realtime.notes[noteId].socks = [clientSocket, undefined, otherClient] permissionFunc('freely') @@ -539,9 +548,10 @@ describe('realtime#socket event', function () { }, 5) }) - it('should not change permission to freely when config allowAnonymous and allowAnonymousEdits are false', function (done) { + it('should not change permission to freely when config allowAnonymous, allowAnonymousEdits and allowAnonymousViews are false', function (done) { configMock.allowAnonymous = false configMock.allowAnonymousEdits = false + configMock.allowAnonymousViews = false realtime.notes[noteId].socks = [clientSocket, undefined, otherClient] permissionFunc('freely') @@ -556,6 +566,7 @@ describe('realtime#socket event', function () { it('should change permission to freely when config allowAnonymous is true', function (done) { configMock.allowAnonymous = true configMock.allowAnonymousEdits = false + configMock.allowAnonymousViews = false realtime.notes[noteId].socks = [clientSocket, undefined, otherClient] permissionFunc('freely') @@ -570,13 +581,80 @@ describe('realtime#socket event', function () { }, 5) }) - it('should change permission to freely when config allowAnonymousEdits is true', function (done) { + it('should not change permission to freely when config allowAnonymousEdits is true', function (done) { configMock.allowAnonymous = false configMock.allowAnonymousEdits = true + configMock.allowAnonymousViews = false realtime.notes[noteId].socks = [clientSocket, undefined, otherClient] permissionFunc('freely') + setTimeout(() => { + assert(modelsMock.Note.update.called === false) + assert(checkViewPermissionSpy.called === false) + done() + }, 5) + }) + + it('should not change permission to freely when config allowAnonymousViews is true', function (done) { + configMock.allowAnonymous = false + configMock.allowAnonymousEdits = false + configMock.allowAnonymousViews = true + realtime.notes[noteId].socks = [clientSocket, undefined, otherClient] + + permissionFunc('freely') + + setTimeout(() => { + assert(modelsMock.Note.update.called === false) + assert(checkViewPermissionSpy.called === false) + done() + }, 5) + }) + + it('should change permission to editable when config allowAnonymousViews is true', function (done) { + configMock.allowAnonymous = false + configMock.allowAnonymousEdits = false + configMock.allowAnonymousViews = true + realtime.notes[noteId].socks = [clientSocket, undefined, otherClient] + + permissionFunc('editable') + + setTimeout(() => { + assert(checkViewPermissionSpy.callCount === 2) + assert(otherClient.emit.called === false) + assert(otherClient.disconnect.called === false) + assert(clientSocket.emit.called === false) + assert(clientSocket.disconnect.called === false) + done() + }, 5) + }) + + it('should change permission to freely when config allowAnonymousEdits and allowAnonymousViews are false true', function (done) { + configMock.allowAnonymous = false + configMock.allowAnonymousEdits = true + configMock.allowAnonymousViews = true + realtime.notes[noteId].socks = [clientSocket, undefined, otherClient] + + permissionFunc('freely') + + setTimeout(() => { + assert(checkViewPermissionSpy.callCount === 2) + assert(otherClient.emit.called === false) + assert(otherClient.disconnect.called === false) + assert(clientSocket.emit.called === false) + assert(clientSocket.disconnect.called === false) + done() + }, 5) + }) + + it('should change permission to editable when config allowAnonymousEdits and allowAnonymousViews are false true', function (done) { + configMock.allowAnonymous = false + configMock.allowAnonymousEdits = true + configMock.allowAnonymousViews = true + realtime.notes[noteId].socks = [clientSocket, undefined, otherClient] + + permissionFunc('editable') + setTimeout(() => { assert(checkViewPermissionSpy.callCount === 2) assert(otherClient.emit.called === false)