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 <hakoai64@gmail.com>
This commit is contained in:
TAKIMOTO, Atsushi 2019-02-23 13:33:37 +09:00 committed by hakoai
parent df2c0e23b6
commit c7a15ecc66
7 changed files with 113 additions and 13 deletions

1
app.js
View File

@ -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,

View File

@ -31,6 +31,7 @@ module.exports = {
useCDN: true,
allowAnonymous: true,
allowAnonymousEdits: false,
allowAnonymousViews: true,
allowFreeURL: false,
forbiddenNoteIDs: ['robots.txt', 'favicon.ico', 'api'],
defaultPermission: 'editable',

View File

@ -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,

View File

@ -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!!!

View File

@ -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(() => {

View File

@ -15,12 +15,12 @@
<a id="permissionLabel" class="ui-permission-label text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
</a>
<ul class="dropdown-menu" aria-labelledby="permissionLabel">
<li class="ui-permission-freely"<% if(!allowAnonymous && !allowAnonymousEdits) { %> style="display: none;"<% } %>><a><i class="fa fa-leaf fa-fw"></i> Freely - Anyone can edit</a></li>
<li class="ui-permission-editable"><a><i class="fa fa-shield fa-fw"></i> Editable - Signed-in people can edit</a></li>
<li class="ui-permission-limited"><a><i class="fa fa-id-card fa-fw"></i> Limited - Signed-in people can edit (forbid guests)</a></li>
<li class="ui-permission-locked"><a><i class="fa fa-lock fa-fw"></i> Locked - Only owner can edit</a></li>
<li class="ui-permission-protected"><a><i class="fa fa-umbrella fa-fw"></i> Protected - Only owner can edit (forbid guests)</a></li>
<li class="ui-permission-private"><a><i class="fa fa-hand-stop-o fa-fw"></i> Private - Only owner can view &amp; edit</a></li>
<li class="ui-permission-freely"<% if(!('freely' in permission)) { %> style="display: none;"<% } %>><a><i class="fa fa-leaf fa-fw"></i> Freely - Anyone can edit</a></li>
<li class="ui-permission-editable"<% if(!('editable' in permission)) { %> style="display: none;"<% } %>><a><i class="fa fa-shield fa-fw"></i> Editable - Signed-in people can edit</a></li>
<li class="ui-permission-limited"<% if(!('limited' in permission)) { %> style="display: none;"<% } %>><a><i class="fa fa-id-card fa-fw"></i> Limited - Signed-in people can edit (forbid guests)</a></li>
<li class="ui-permission-locked"<% if(!('locked' in permission)) { %> style="display: none;"<% } %>><a><i class="fa fa-lock fa-fw"></i> Locked - Only owner can edit</a></li>
<li class="ui-permission-protected"<% if(!('protected' in permission)) { %> style="display: none;"<% } %>><a><i class="fa fa-umbrella fa-fw"></i> Protected - Only owner can edit (forbid guests)</a></li>
<li class="ui-permission-private"<% if(!('private' in permission)) { %> style="display: none;"<% } %>><a><i class="fa fa-hand-stop-o fa-fw"></i> Private - Only owner can view &amp; edit</a></li>
<li class="divider"></li>
<li class="ui-delete-note"><a><i class="fa fa-trash-o fa-fw"></i> Delete this note</a></li>
</ul>

View File

@ -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)