@ -13,19 +13,130 @@ const utils = require('../../utils');
const usersController = module . exports ;
const userFields = [ 'uid' , 'username' , 'userslug' , 'email' , 'postcount' , 'joindate' , 'banned' ,
'reputation' , 'picture' , 'flags' , 'lastonline' , 'email:confirmed' ] ;
const userFields = [
'uid' , 'username' , 'userslug' , 'email' , 'postcount' , 'joindate' , 'banned' ,
'reputation' , 'picture' , 'flags' , 'lastonline' , 'email:confirmed' ,
] ;
usersController . index = async function ( req , res ) {
if ( req . query . query ) {
await usersController . search ( req , res ) ;
} else {
await getUsers ( req , res ) ;
}
} ;
async function getUsers ( req , res ) {
const sortDirection = req . query . sortDirection || 'desc' ;
const reverse = sortDirection === 'desc' ;
const page = parseInt ( req . query . page , 10 ) || 1 ;
let resultsPerPage = parseInt ( req . query . resultsPerPage , 10 ) || 50 ;
if ( ! [ 50 , 100 , 250 , 500 ] . includes ( resultsPerPage ) ) {
resultsPerPage = 50 ;
}
let sortBy = validator . escape ( req . query . sortBy || '' ) ;
const filterBy = Array . isArray ( req . query . filters || [ ] ) ? ( req . query . filters || [ ] ) : [ req . query . filters ] ;
const start = Math . max ( 0 , page - 1 ) * resultsPerPage ;
const stop = start + resultsPerPage - 1 ;
function buildSet ( ) {
const sortToSet = {
postcount : 'users:postcount' ,
reputation : 'users:reputation' ,
joindate : 'users:joindate' ,
online : 'users:online' ,
flags : 'users:flags' ,
} ;
const set = [ ] ;
if ( sortBy ) {
set . push ( sortToSet [ sortBy ] ) ;
}
if ( filterBy . includes ( 'unverified' ) ) {
set . push ( 'group:unverified-users:members' ) ;
}
if ( filterBy . includes ( 'verified' ) ) {
set . push ( 'group:verified-users:members' ) ;
}
if ( filterBy . includes ( 'banned' ) ) {
set . push ( 'users:banned' ) ;
}
if ( ! set . length ) {
set . push ( 'users:online' ) ;
sortBy = 'online' ;
}
return set . length > 1 ? set : set [ 0 ] ;
}
async function getCount ( set ) {
if ( Array . isArray ( set ) ) {
return await db . sortedSetIntersectCard ( set ) ;
}
return await db . sortedSetCard ( set ) ;
}
async function getUids ( set ) {
let uids = [ ] ;
if ( Array . isArray ( set ) ) {
const weights = set . map ( ( s , index ) => ( index ? 0 : 1 ) ) ;
uids = await db [ reverse ? 'getSortedSetRevIntersect' : 'getSortedSetIntersect' ] ( {
sets : set ,
start : start ,
stop : stop ,
weights : weights ,
} ) ;
} else {
uids = await db [ reverse ? 'getSortedSetRevRange' : 'getSortedSetRange' ] ( set , start , stop ) ;
}
return uids ;
}
async function getUsersWithFields ( set ) {
const uids = await getUids ( set ) ;
const [ isAdmin , userData ] = await Promise . all ( [
user . isAdministrator ( uids ) ,
user . getUsersWithFields ( uids , userFields , req . uid ) ,
] ) ;
userData . forEach ( ( user , index ) => {
if ( user ) {
user . administrator = isAdmin [ index ] ;
}
} ) ;
return userData ;
}
const set = buildSet ( ) ;
const [ count , users ] = await Promise . all ( [
getCount ( set ) ,
getUsersWithFields ( set ) ,
] ) ;
render ( req , res , {
users : users . filter ( user => user && parseInt ( user . uid , 10 ) ) ,
page : page ,
pageCount : Math . max ( 1 , Math . ceil ( count / resultsPerPage ) ) ,
resultsPerPage : resultsPerPage ,
reverse : reverse ,
sortBy : sortBy ,
} ) ;
}
usersController . search = async function ( req , res ) {
const sortDirection = req . query . sortDirection || 'desc' ;
const reverse = sortDirection === 'desc' ;
const page = parseInt ( req . query . page , 10 ) || 1 ;
let resultsPerPage = parseInt ( req . query . resultsPerPage , 10 ) || 50 ;
if ( ! [ 50 , 100 , 250 , 500 ] . includes ( resultsPerPage ) ) {
resultsPerPage = 50 ;
}
const searchData = await user . search ( {
uid : req . uid ,
query : req . query . query ,
searchBy : req . query . searchBy ,
sortBy : req . query . sortBy ,
sortDirection : sortDirection ,
filters : req . query . filters ,
page : page ,
resultsPerPage : resultsPerPage ,
findUids : async function ( query , searchBy , hardCap ) {
@ -58,48 +169,10 @@ usersController.search = async function (req, res) {
}
} ) ;
searchData . query = validator . escape ( String ( req . query . query || '' ) ) ;
searchData . uidQuery = req . query . searchBy === 'uid' ? searchData . query : '' ;
searchData . usernameQuery = req . query . searchBy === 'username' ? searchData . query : '' ;
searchData . emailQuery = req . query . searchBy === 'email' ? searchData . query : '' ;
searchData . ipQuery = req . query . searchBy === 'uid' ? searchData . query : '' ;
searchData . resultsPerPage = resultsPerPage ;
searchData . pagination = pagination . create ( page , searchData . pageCount , req . query ) ;
searchData . search _display = '' ;
res . render ( 'admin/manage/users' , searchData ) ;
} ;
usersController . sortByJoinDate = async function ( req , res ) {
await getUsers ( 'users:joindate' , 'latest' , undefined , undefined , req , res ) ;
} ;
usersController . notValidated = async function ( req , res ) {
await getUsers ( 'users:notvalidated' , 'notvalidated' , undefined , undefined , req , res ) ;
} ;
usersController . noPosts = async function ( req , res ) {
await getUsers ( 'users:postcount' , 'noposts' , '-inf' , 0 , req , res ) ;
} ;
usersController . topPosters = async function ( req , res ) {
await getUsers ( 'users:postcount' , 'topposts' , 0 , '+inf' , req , res ) ;
} ;
usersController . mostReputaion = async function ( req , res ) {
await getUsers ( 'users:reputation' , 'mostreputation' , 0 , '+inf' , req , res ) ;
} ;
usersController . flagged = async function ( req , res ) {
await getUsers ( 'users:flags' , 'mostflags' , 1 , '+inf' , req , res ) ;
} ;
usersController . inactive = async function ( req , res ) {
const timeRange = 1000 * 60 * 60 * 24 * 30 * ( parseInt ( req . query . months , 10 ) || 3 ) ;
const cutoff = Date . now ( ) - timeRange ;
await getUsers ( 'users:online' , 'inactive' , '-inf' , cutoff , req , res ) ;
} ;
usersController . banned = async function ( req , res ) {
await getUsers ( 'users:banned' , 'banned' , undefined , undefined , req , res ) ;
searchData . sortBy = req . query . sortBy ;
searchData . reverse = reverse ;
render ( req , res , searchData ) ;
} ;
usersController . registrationQueue = async function ( req , res ) {
@ -149,69 +222,21 @@ async function getInvites() {
return invitations ;
}
async function getUsers ( set , section , min , max , req , res ) {
const page = parseInt ( req . query . page , 10 ) || 1 ;
let resultsPerPage = parseInt ( req . query . resultsPerPage , 10 ) || 50 ;
if ( ! [ 50 , 100 , 250 , 500 ] . includes ( resultsPerPage ) ) {
resultsPerPage = 50 ;
}
const start = Math . max ( 0 , page - 1 ) * resultsPerPage ;
const stop = start + resultsPerPage - 1 ;
const byScore = min !== undefined && max !== undefined ;
async function getCount ( ) {
if ( byScore ) {
return await db . sortedSetCount ( set , min , max ) ;
} else if ( set === 'users:banned' || set === 'users:notvalidated' ) {
return await db . sortedSetCard ( set ) ;
}
return await db . getObjectField ( 'global' , 'userCount' ) ;
}
async function getUsersWithFields ( ) {
let uids ;
if ( byScore ) {
uids = await db . getSortedSetRevRangeByScore ( set , start , resultsPerPage , max , min ) ;
} else {
uids = await user . getUidsFromSet ( set , start , stop ) ;
}
const [ isAdmin , userData ] = await Promise . all ( [
user . isAdministrator ( uids ) ,
user . getUsersWithFields ( uids , userFields , req . uid ) ,
] ) ;
userData . forEach ( ( user , index ) => {
if ( user ) {
user . administrator = isAdmin [ index ] ;
}
} ) ;
return userData ;
}
const [ count , users ] = await Promise . all ( [
getCount ( ) ,
getUsersWithFields ( ) ,
] ) ;
const data = {
users : users . filter ( user => user && parseInt ( user . uid , 10 ) ) ,
page : page ,
pageCount : Math . max ( 1 , Math . ceil ( count / resultsPerPage ) ) ,
resultsPerPage : resultsPerPage ,
} ;
data [ section ] = true ;
render ( req , res , data ) ;
}
function render ( req , res , data ) {
data . search _display = 'hidden' ;
data . pagination = pagination . create ( data . page , data . pageCount , req . query ) ;
data . requireEmailConfirmation = meta . config . requireEmailConfirmation ;
var registrationType = meta . config . registrationType ;
const registrationType = meta . config . registrationType ;
data . inviteOnly = registrationType === 'invite-only' || registrationType === 'admin-invite-only' ;
data . adminInviteOnly = registrationType === 'admin-invite-only' ;
data [ 'sort_' + data . sortBy ] = true ;
if ( req . query . searchBy ) {
data [ 'searchBy_' + validator . escape ( String ( req . query . searchBy ) ) ] = true ;
}
const filterBy = Array . isArray ( req . query . filters || [ ] ) ? ( req . query . filters || [ ] ) : [ req . query . filters ] ;
filterBy . forEach ( function ( filter ) {
data [ 'filterBy_' + validator . escape ( String ( filter ) ) ] = true ;
} ) ;
res . render ( 'admin/manage/users' , data ) ;
}