mirror of https://github.com/status-im/codimd.git
commit
fdbfb71d97
1
app.js
1
app.js
|
@ -180,6 +180,7 @@ app.locals.serverURL = config.serverURL
|
||||||
app.locals.sourceURL = config.sourceURL
|
app.locals.sourceURL = config.sourceURL
|
||||||
app.locals.allowAnonymous = config.allowAnonymous
|
app.locals.allowAnonymous = config.allowAnonymous
|
||||||
app.locals.allowAnonymousEdits = config.allowAnonymousEdits
|
app.locals.allowAnonymousEdits = config.allowAnonymousEdits
|
||||||
|
app.locals.permission = config.permission
|
||||||
app.locals.allowPDFExport = config.allowPDFExport
|
app.locals.allowPDFExport = config.allowPDFExport
|
||||||
app.locals.authProviders = {
|
app.locals.authProviders = {
|
||||||
facebook: config.isFacebookEnable,
|
facebook: config.isFacebookEnable,
|
||||||
|
|
|
@ -31,6 +31,7 @@ module.exports = {
|
||||||
useCDN: true,
|
useCDN: true,
|
||||||
allowAnonymous: true,
|
allowAnonymous: true,
|
||||||
allowAnonymousEdits: false,
|
allowAnonymousEdits: false,
|
||||||
|
allowAnonymousViews: true,
|
||||||
allowFreeURL: false,
|
allowFreeURL: false,
|
||||||
forbiddenNoteIDs: ['robots.txt', 'favicon.ico', 'api'],
|
forbiddenNoteIDs: ['robots.txt', 'favicon.ico', 'api'],
|
||||||
defaultPermission: 'editable',
|
defaultPermission: 'editable',
|
||||||
|
|
|
@ -27,6 +27,7 @@ module.exports = {
|
||||||
useCDN: toBooleanConfig(process.env.CMD_USECDN),
|
useCDN: toBooleanConfig(process.env.CMD_USECDN),
|
||||||
allowAnonymous: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS),
|
allowAnonymous: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS),
|
||||||
allowAnonymousEdits: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_EDITS),
|
allowAnonymousEdits: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_EDITS),
|
||||||
|
allowAnonymousViews: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_VIEWS),
|
||||||
allowFreeURL: toBooleanConfig(process.env.CMD_ALLOW_FREEURL),
|
allowFreeURL: toBooleanConfig(process.env.CMD_ALLOW_FREEURL),
|
||||||
forbiddenNoteIDs: toArrayConfig(process.env.CMD_FORBIDDEN_NOTE_IDS),
|
forbiddenNoteIDs: toArrayConfig(process.env.CMD_FORBIDDEN_NOTE_IDS),
|
||||||
defaultPermission: process.env.CMD_DEFAULT_PERMISSION,
|
defaultPermission: process.env.CMD_DEFAULT_PERMISSION,
|
||||||
|
|
|
@ -68,11 +68,17 @@ if (config.ldap.tlsca) {
|
||||||
|
|
||||||
// Permission
|
// Permission
|
||||||
config.permission = 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
|
delete config.permission.freely
|
||||||
}
|
}
|
||||||
if (!(config.defaultPermission in config.permission)) {
|
if (!(config.defaultPermission in config.permission)) {
|
||||||
config.defaultPermission = config.permission.editable
|
config.defaultPermission = defaultPermission
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache result, cannot change config in runtime!!!
|
// cache result, cannot change config in runtime!!!
|
||||||
|
|
|
@ -57,6 +57,19 @@ class RealtimeClientConnection {
|
||||||
return config.allowAnonymous || config.allowAnonymousEdits
|
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 () {
|
getCurrentUser () {
|
||||||
if (!this.socket.id) return
|
if (!this.socket.id) return
|
||||||
return this.realtime.getUserFromUserPool(this.socket.id)
|
return this.realtime.getUserFromUserPool(this.socket.id)
|
||||||
|
@ -211,7 +224,7 @@ class RealtimeClientConnection {
|
||||||
const note = this.getCurrentNote()
|
const note = this.getCurrentNote()
|
||||||
// Only owner can change permission
|
// Only owner can change permission
|
||||||
if (!this.isNoteOwner()) return
|
if (!this.isNoteOwner()) return
|
||||||
if (!this.isAnonymousEnable() && permission === 'freely') return
|
if (!(permission in this.getAvailablePermissions())) return
|
||||||
|
|
||||||
this.changeNotePermission(permission)
|
this.changeNotePermission(permission)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
|
@ -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 id="permissionLabel" class="ui-permission-label text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu" aria-labelledby="permissionLabel">
|
<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-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"><a><i class="fa fa-shield fa-fw"></i> Editable - Signed-in people 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"><a><i class="fa fa-id-card fa-fw"></i> Limited - Signed-in people can edit (forbid guests)</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"><a><i class="fa fa-lock fa-fw"></i> Locked - Only owner can edit</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"><a><i class="fa fa-umbrella fa-fw"></i> Protected - Only owner can edit (forbid guests)</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"><a><i class="fa fa-hand-stop-o fa-fw"></i> Private - Only owner can view & edit</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 & edit</a></li>
|
||||||
<li class="divider"></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>
|
<li class="ui-delete-note"><a><i class="fa fa-trash-o fa-fw"></i> Delete this note</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -56,7 +56,15 @@ describe('realtime#socket event', function () {
|
||||||
})
|
})
|
||||||
configMock = {
|
configMock = {
|
||||||
fullversion: '1.5.0',
|
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', {
|
mock('../../lib/logger', {
|
||||||
error: () => {
|
error: () => {
|
||||||
|
@ -522,9 +530,10 @@ describe('realtime#socket event', function () {
|
||||||
}, 5)
|
}, 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.allowAnonymous = true
|
||||||
configMock.allowAnonymousEdits = true
|
configMock.allowAnonymousEdits = true
|
||||||
|
configMock.allowAnonymousViews = true
|
||||||
realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]
|
realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]
|
||||||
|
|
||||||
permissionFunc('freely')
|
permissionFunc('freely')
|
||||||
|
@ -539,9 +548,10 @@ describe('realtime#socket event', function () {
|
||||||
}, 5)
|
}, 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.allowAnonymous = false
|
||||||
configMock.allowAnonymousEdits = false
|
configMock.allowAnonymousEdits = false
|
||||||
|
configMock.allowAnonymousViews = false
|
||||||
realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]
|
realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]
|
||||||
|
|
||||||
permissionFunc('freely')
|
permissionFunc('freely')
|
||||||
|
@ -556,6 +566,7 @@ describe('realtime#socket event', function () {
|
||||||
it('should change permission to freely when config allowAnonymous is true', function (done) {
|
it('should change permission to freely when config allowAnonymous is true', function (done) {
|
||||||
configMock.allowAnonymous = true
|
configMock.allowAnonymous = true
|
||||||
configMock.allowAnonymousEdits = false
|
configMock.allowAnonymousEdits = false
|
||||||
|
configMock.allowAnonymousViews = false
|
||||||
realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]
|
realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]
|
||||||
|
|
||||||
permissionFunc('freely')
|
permissionFunc('freely')
|
||||||
|
@ -570,9 +581,58 @@ describe('realtime#socket event', function () {
|
||||||
}, 5)
|
}, 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.allowAnonymous = false
|
||||||
configMock.allowAnonymousEdits = true
|
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]
|
realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]
|
||||||
|
|
||||||
permissionFunc('freely')
|
permissionFunc('freely')
|
||||||
|
@ -586,5 +646,23 @@ describe('realtime#socket event', function () {
|
||||||
done()
|
done()
|
||||||
}, 5)
|
}, 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)
|
||||||
|
assert(otherClient.disconnect.called === false)
|
||||||
|
assert(clientSocket.emit.called === false)
|
||||||
|
assert(clientSocket.disconnect.called === false)
|
||||||
|
done()
|
||||||
|
}, 5)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue