@ -16,39 +16,49 @@ module.exports = function (privileges) {
privileges . posts . get = function ( pids , uid , callback ) {
if ( ! Array . isArray ( pids ) || ! pids . length ) {
return callback( null , [ ] ) ;
return setImmediate( callback , null , [ ] ) ;
}
let uniqueCids ;
let cids ;
async . waterfall ( [
function ( next ) {
posts . getCidsByPids ( pids , next ) ;
} ,
function ( cids , next ) {
function ( _cids , next ) {
cids = _cids ;
uniqueCids = _ . uniq ( cids ) ;
async . parallel ( {
isAdmin : async . apply ( user . isAdministrator , uid ) ,
isModerator : async . apply ( user . isModerator , uid , c ids) ,
isModerator : async . apply ( user . isModerator , uid , uniqueC ids) ,
isOwner : async . apply ( posts . isOwner , pids , uid ) ,
'topics:read' : async . apply ( helpers . isUserAllowedTo , 'topics:read' , uid , c ids) ,
read : async . apply ( helpers . isUserAllowedTo , 'read' , uid , c ids) ,
'posts:edit' : async . apply ( helpers . isUserAllowedTo , 'posts:edit' , uid , c ids) ,
'posts:history' : async . apply ( helpers . isUserAllowedTo , 'posts:history' , uid , c ids) ,
'posts:view_deleted' : async . apply ( helpers . isUserAllowedTo , 'posts:view_deleted' , uid , c ids) ,
'topics:read' : async . apply ( helpers . isUserAllowedTo , 'topics:read' , uid , uniqueC ids) ,
read : async . apply ( helpers . isUserAllowedTo , 'read' , uid , uniqueC ids) ,
'posts:edit' : async . apply ( helpers . isUserAllowedTo , 'posts:edit' , uid , uniqueC ids) ,
'posts:history' : async . apply ( helpers . isUserAllowedTo , 'posts:history' , uid , uniqueC ids) ,
'posts:view_deleted' : async . apply ( helpers . isUserAllowedTo , 'posts:view_deleted' , uid , uniqueC ids) ,
} , next ) ;
} ,
function ( results , next ) {
var privileges = pids . map ( function ( pid , i ) {
var isAdminOrMod = results . isAdmin || results . isModerator [ i ] ;
var editable = isAdminOrMod || ( results . isOwner [ i ] && results [ 'posts:edit' ] [ i ] ) ;
var viewDeletedPosts = isAdminOrMod || results . isOwner [ i ] || results [ 'posts:view_deleted' ] [ i ] ;
var viewHistory = isAdminOrMod || results . isOwner [ i ] || results [ 'posts:history' ] [ i ] ;
const isModerator = _ . zipObject ( uniqueCids , results . isModerator ) ;
const privData = { } ;
privData [ 'topics:read' ] = _ . zipObject ( uniqueCids , results [ 'topics:read' ] ) ;
privData . read = _ . zipObject ( uniqueCids , results . read ) ;
privData [ 'posts:edit' ] = _ . zipObject ( uniqueCids , results [ 'posts:edit' ] ) ;
privData [ 'posts:history' ] = _ . zipObject ( uniqueCids , results [ 'posts:history' ] ) ;
privData [ 'posts:view_deleted' ] = _ . zipObject ( uniqueCids , results [ 'posts:view_deleted' ] ) ;
var privileges = cids . map ( function ( cid , i ) {
var isAdminOrMod = results . isAdmin || isModerator [ cid ] ;
var editable = ( privData [ 'posts:edit' ] [ cid ] && ( results . isOwner [ i ] || results . isModerator ) ) || results . isAdmin ;
var viewDeletedPosts = results . isOwner [ i ] || privData [ 'posts:view_deleted' ] [ cid ] || results . isAdmin ;
var viewHistory = results . isOwner [ i ] || privData [ 'posts:history' ] [ cid ] || results . isAdmin ;
return {
editable : editable ,
view _deleted : editable ,
move : isAdminOrMod ,
isAdminOrMod : isAdminOrMod ,
'topics:read' : results [ 'topics:read' ] [ i ] || isAdminOrMod ,
read : results . read [ i ] || isAdminOrMod ,
'topics:read' : privData [ 'topics:read' ] [ c id ] || results. isAdmin,
read : privData. read [ cid ] || results . isAdmin ,
'posts:history' : viewHistory ,
'posts:view_deleted' : viewDeletedPosts ,
} ;
@ -72,7 +82,7 @@ module.exports = function (privileges) {
privileges . posts . filter = function ( privilege , pids , uid , callback ) {
if ( ! Array . isArray ( pids ) || ! pids . length ) {
return callback( null , [ ] ) ;
return setImmediate( callback , null , [ ] ) ;
}
var cids ;
var postData ;
@ -112,18 +122,16 @@ module.exports = function (privileges) {
privileges . categories . getBase ( privilege , cids , uid , next ) ;
} ,
function ( results , next ) {
var isModOf = { } ;
cids = cids . filter ( function ( cid , index ) {
isModOf [ cid ] = results . isModerators [ index ] ;
return ! results . categories [ index ] . disabled &&
( results . allowedTo [ index ] || results . isAdmin || results . isModerators [ index ] ) ;
( results . allowedTo [ index ] || results . isAdmin ) ;
} ) ;
const cidsSet = new Set ( cids ) ;
pids = postData . filter ( function ( post ) {
return post . topic && cidsSet . has ( post . topic . cid ) &&
( ( ! post . topic . deleted && ! post . deleted ) || results . isAdmin || isModOf [ post . cid ] ) ;
( ( ! post . topic . deleted && ! post . deleted ) || results . isAdmin ) ;
} ) . map ( post => post . pid ) ;
plugins . fireHook ( 'filter:privileges.posts.filter' , {
@ -138,19 +146,41 @@ module.exports = function (privileges) {
} ;
privileges . posts . canEdit = function ( pid , uid , callback ) {
let results ;
async . waterfall ( [
function ( next ) {
async . parallel ( {
isEditable : async . apply ( isPostEditable , pid , uid ) ,
isAdminOrMod : async . apply ( isAdminOrMod , pid , uid ) ,
isAdmin : async . apply ( privileges . users . isAdministrator , uid ) ,
isMod : async . apply ( posts . isModerator , [ pid ] , uid ) ,
owner : async . apply ( posts . isOwner , pid , uid ) ,
edit : async . apply ( privileges . posts . can , 'posts:edit' , pid , uid ) ,
postData : async . apply ( posts . getPostFields , pid , [ 'tid' , 'timestamp' ] ) ,
} , next ) ;
} ,
function ( results , next ) {
if ( results . isAdminOrMod ) {
return next ( null , { flag : true } ) ;
function ( _results , next ) {
results = _results ;
results . isMod = results . isMod [ 0 ] ;
if ( results . isAdmin ) {
return callback ( null , { flag : true } ) ;
}
if ( ! results . isMod && meta . config . postEditDuration && ( Date . now ( ) - results . postData . timestamp > meta . config . postEditDuration * 1000 ) ) {
return callback ( null , { flag : false , message : '[[error:post-edit-duration-expired, ' + meta . config . postEditDuration + ']]' } ) ;
}
topics . isLocked ( results . postData . tid , next ) ;
} ,
function ( isLocked , next ) {
if ( ! results . isMod && isLocked ) {
return callback ( null , { flag : false , message : '[[error:topic-locked]]' } ) ;
}
next ( null , results . isEditable ) ;
results . pid = parseInt ( pid , 10 ) ;
results . uid = uid ;
plugins . fireHook ( 'filter:privileges.posts.edit' , results , next ) ;
} ,
function ( result , next ) {
next ( null , { flag : result . edit && ( result . owner || result . isMod ) , message : '[[error:no-privileges]]' } ) ;
} ,
] , callback ) ;
} ;
@ -164,31 +194,29 @@ module.exports = function (privileges) {
function ( _postData , next ) {
postData = _postData ;
async . parallel ( {
isAdminOrMod : async . apply ( isAdminOrMod , pid , uid ) ,
isAdmin : async . apply ( privileges . users . isAdministrator , uid ) ,
isMod : async . apply ( posts . isModerator , [ pid ] , uid ) ,
isLocked : async . apply ( topics . isLocked , postData . tid ) ,
isOwner : async . apply ( posts . isOwner , pid , uid ) ,
'posts:delete' : async . apply ( privileges . posts . can , 'posts:delete' , pid , uid ) ,
} , next ) ;
} ,
function ( results , next ) {
if ( results . isAdminOrMod ) {
results . isMod = results . isMod [ 0 ] ;
if ( results . isAdmin ) {
return next ( null , { flag : true } ) ;
}
if ( results . isLocked ) {
if ( ! results . isMod && results . isLocked ) {
return next ( null , { flag : false , message : '[[error:topic-locked]]' } ) ;
}
if ( ! results [ 'posts:delete' ] ) {
return next ( null , { flag : false , message : '[[error:no-privileges]]' } ) ;
}
var postDeleteDuration = meta . config . postDeleteDuration ;
if ( postDeleteDuration && ( Date . now ( ) - postData . timestamp > postDeleteDuration * 1000 ) ) {
if ( ! results . isMod && postDeleteDuration && ( Date . now ( ) - postData . timestamp > postDeleteDuration * 1000 ) ) {
return next ( null , { flag : false , message : '[[error:post-delete-duration-expired, ' + meta . config . postDeleteDuration + ']]' } ) ;
}
var deleterUid = postData . deleterUid ;
var flag = results .isOwner && ( deleterUid === 0 || deleterUid === postData . ui d) ;
var flag = results ['posts:delete' ] && ( ( results .isOwner && ( deleterUid === 0 || deleterUid === postData . ui d) ) || results . isMo d) ;
next ( null , { flag : flag , message : '[[error:no-privileges]]' } ) ;
} ,
] , callback ) ;
@ -233,51 +261,16 @@ module.exports = function (privileges) {
async . parallel ( {
purge : async . apply ( privileges . categories . isUserAllowedTo , 'purge' , cid , uid ) ,
owner : async . apply ( posts . isOwner , pid , uid ) ,
isAdminOrMod : async . apply ( privileges . categories . isAdminOrMod , cid , uid ) ,
isAdmin : async . apply ( privileges . users . isAdministrator , uid ) ,
isModerator : async . apply ( privileges . users . isModerator , uid , cid ) ,
} , next ) ;
} ,
function ( results , next ) {
next ( null , results . isAdminOrMod || ( results . purge && results . owner ) ) ;
next ( null , ( results . purge && ( results . owner || results . isModerator ) ) || results . isAdmin ) ;
} ,
] , callback ) ;
} ;
function isPostEditable ( pid , uid , callback ) {
async . waterfall ( [
function ( next ) {
posts . getPostFields ( pid , [ 'tid' , 'timestamp' ] , next ) ;
} ,
function ( postData , next ) {
var postEditDuration = meta . config . postEditDuration ;
if ( postEditDuration && ( Date . now ( ) - postData . timestamp > postEditDuration * 1000 ) ) {
return callback ( null , { flag : false , message : '[[error:post-edit-duration-expired, ' + meta . config . postEditDuration + ']]' } ) ;
}
topics . isLocked ( postData . tid , next ) ;
} ,
function ( isLocked , next ) {
if ( isLocked ) {
return callback ( null , { flag : false , message : '[[error:topic-locked]]' } ) ;
}
async . parallel ( {
owner : async . apply ( posts . isOwner , pid , uid ) ,
edit : async . apply ( privileges . posts . can , 'posts:edit' , pid , uid ) ,
} , next ) ;
} ,
( result , next ) => {
Object . assign ( result , {
pid : parseInt ( pid , 10 ) ,
uid : uid ,
} ) ;
plugins . fireHook ( 'filter:privileges.posts.edit' , result , next ) ;
} ,
function ( result , next ) {
next ( null , { flag : result . owner && result . edit , message : '[[error:no-privileges]]' } ) ;
} ,
] , callback ) ;
}
function isAdminOrMod ( pid , uid , callback ) {
helpers . some ( [
function ( next ) {