Merge remote-tracking branch 'upstream/master'

v1.18.x
Matti Leppänen 11 years ago
commit 98c4b08f15

@ -25,7 +25,6 @@
"passport-facebook": "0.1.5",
"less-middleware": "0.1.12",
"marked": "0.2.8",
"bcrypt": "0.7.5",
"async": "~0.2.8",
"node-imagemagick": "0.1.8",
"gravatar": "1.0.6",
@ -47,7 +46,8 @@
"semver": "~2.2.1",
"string": "~1.7.0",
"xregexp": "~2.0.0",
"socket.io-wildcard": "~0.1.1"
"socket.io-wildcard": "~0.1.1",
"bcryptjs": "~0.7.10"
},
"optionalDependencies": {
"redis": "0.8.3",

@ -23,6 +23,8 @@
"header.recent": "Recent",
"header.unread": "Unread",
"header.users": "Users",
"header.chats": "Chats",
"header.notifications": "Notifications",
"header.search": "Search",
"header.profile": "Profile",

@ -0,0 +1,14 @@
{
"new_topic_button": "New Topic",
"no_topics": "<strong>There are no topics in this category.</strong><br />Why don't you try posting one?",
"sidebar.recent_replies": "Recent Replies",
"sidebar.active_participants": "Active Participants",
"sidebar.moderators": "Moderators",
"posts": "posts",
"views": "views",
"posted": "posted",
"browsing": "browsing",
"no_replies": "No one has replied",
"replied": "replied",
"last_edited_by": "last edited by"
}

@ -0,0 +1,7 @@
{
"stats.online": "Online",
"stats.users": "Testers",
"stats.topics": "T&oacute;picos",
"stats.posts": "Posts",
"success": "Sucesso"
}

@ -0,0 +1,40 @@
{
"home": "Home",
"search": "Procurar",
"buttons.close": "Fechar",
"403.title": "Acesso Negado",
"403.message": "Parece que você n&atilde;o tem acesso a essa p&aacute;gina. talvez você devesse <a href='/login'>tentar logar...</a>?",
"404.title": "Not Found",
"404.message": "Essa p&aacute;gina n&atilde;o existe... volte para <a href='/'>p&aacute;gina principal</a>.",
"500.title": "Erro Interno.",
"500.message": "Oops! deu algo errado!",
"register": "Cadastrar",
"login": "Logar",
"logout": "Logout",
"logout.title": "Logout com sucesso.",
"logout.message": "Logado com Sucesso!",
"save_changes": "Salvar Altera&ccedil;&otilde;es",
"close": "Fechar",
"header.admin": "Admin",
"header.recent": "Recente",
"header.unread": "Não Lido",
"header.users": "Usu&aacute;rios",
"header.search": "Procurar",
"header.profile": "Profile",
"notifications.loading": "Carregando Notifica&ccedil;&otilde;es",
"chats.loading": "Carregando Bate-Papo",
"motd.welcome": "Welcome to NodeBB, the discussion platform of the future.",
"motd.get": "Get NodeBB",
"motd.fork": "Fork",
"motd.like": "Like",
"motd.follow": "Seguir",
"previouspage": "P&aacute;gina Anterior",
"nextpage": "Pr&oacutexima pagina;"
}

@ -0,0 +1,4 @@
{
"name": "Portugu&ecirc;s Brasileiro",
"code": "pt_br"
}

@ -0,0 +1,10 @@
{
"login": "Login",
"username": "Usu&aacute;rio",
"password": "Senha",
"remember_me": "Lembrar?",
"forgot_password": "Esqueceu a Senha?",
"alternative_logins": "Você pode logar usando tamb&eacute;m...",
"failed_login_attempt": "Falha no login, por favor tente novamente.",
"login_successful": "Você logou com sucesso!"
}

@ -0,0 +1,6 @@
{
"chat.chatting_with": "Conversar com <span id=\"chat-with-name\"></span>",
"chat.placeholder": "Digite sua mensagem aqui e pressione 'enter' para enviar",
"chat.send": "Enviar",
"chat.no_active": "Você n&atilde;o tem chats ativos."
}

@ -0,0 +1,8 @@
{
"title": "Notifica&ccedil;&otilde;es",
"back_to_home": "voltar para home",
"outgoing_link": "Link Externo",
"outgoing_link_message": "Você est&aacute; saindo do agiletesters com um link externo",
"continue_to": "Continuar para",
"return_to": "Voltar para"
}

@ -0,0 +1,5 @@
{
"day": "Dia",
"week": "Semana",
"month": "Mês"
}

@ -0,0 +1,16 @@
{
"register": "Cadastrar",
"help.email": "Por padr&atilde;o, seu email n&atilde;o ficar&aacute; visivel.",
"help.username_restrictions": "Um usu&aacute;rio único com %1 e %2 caracteres. Outros poder&atilde;o te mencionar digitando @<span id='yourUsername'>usu&aacute;rio</span>.",
"help.minimum_password_length": "Sua senha tem que ter no m&iacute;nimo %1 caracteres.",
"email_address": "Email",
"email_address_placeholder": "Digite seu Email",
"username": "Usu&aacute;rio",
"username_placeholder": "Digiter Usu&aacute;rio",
"password": "Senha",
"password_placeholder": "Digitar Senha",
"confirm_password": "Confirmar Senha",
"confirm_password_placeholder": "Confirmar Senha",
"register_now_button": "Cadastrar Agora",
"alternative_registration": "Você pode usar essas outras formas de cadastro"
}

@ -0,0 +1,13 @@
{
"reset_Senha": "Resetar Senha",
"update_Senha": "Alterar Senha",
"Senha_changed.title": "Senha Alterada",
"Senha_changed.message": "<p>Senha resetada com sucesso, por favor <a href=\"/login\">logue novamente</a>.",
"wrong_reset_code.title": "C&oacute;digo De Reset Incorreto",
"wrong_reset_code.message": "Codigo de Reset Incorreto. Tente novamente, ou <a href=\"/reset\">pe&ccedil;a um novo</a>.",
"new_Senha": "Nova Senha",
"repeat_Senha": "Confirmar Senha",
"enter_email": "Por digite seu <strong>email</strong> n&oacute;s enviaremos para você as instru&ccedil;&otilde;es de como resetar sua senha.",
"Senha_reset_sent": "Reset de Senha Enviado",
"invalid_email": "Email inv&aacute;lido!"
}

@ -0,0 +1,53 @@
{
"topic": "T&oacute;pico",
"topics": "T&oacute;picos",
"no_topics_found": "Nenhum t&oacute;pico encontrado!",
"profile": "Profile",
"posted_by": "Postado por",
"chat": "Chat",
"notify_me": "Ser notificado a cada nova resposta",
"quote": "Citar",
"reply": "Esponder",
"edit": "Editar",
"delete": "Deletar",
"move": "Mover",
"fork": "Fork",
"banned": "Banido",
"link": "Link",
"share": "Compartilho",
"tools": "Ferramentas",
"thread_tools.title": "Ferramentas da Thread",
"thread_tools.markAsUnreadForAll": "Marcar como n&atilde;o lido",
"thread_tools.pin": "Fixar Thread",
"thread_tools.lock": "Travar Thread",
"thread_tools.move": "Mover Thread",
"thread_tools.fork": "Fork Thread",
"thread_tools.delete": "Deletar Thread",
"load_categories": "Carregando Categorias",
"disabled_categories_note": "Categorias desabilitadas est&atilde;o em cinza",
"confirm_move": "Mover",
"confirm_fork": "Fork",
"favourite": "Favoritar",
"favourites": "Favoritos",
"favourites.not_logged_in.title": "N&atilde;o Logado",
"favourites.not_logged_in.message": "Por Favor logar para favoritar o t&oacute;pico",
"favourites.has_no_favourites": "Você n&atilde;o tem nenhum item favoritado!",
"posted_by": "postado por",
"loading_more_posts": "Carregando mais posts",
"move_topic": "Mover T&oacute;pico",
"move_post": "Mover Post",
"fork_topic": "Fork T&oacute;pico",
"topic_will_be_moved_to": "Este t&oacute;pico ser&aacute; movido para categoria",
"fork_topic_instruction": "Clique nos postas que você fazer o fork",
"fork_no_pids": "Nenhum T&oacute;pico selecionado",
"fork_success": "Fork realizado com sucesso!",
"reputation": "Reputa&ccedil;&atilde;o",
"posts": "Posts"
}

@ -0,0 +1,5 @@
{
"no_unread_topics": "Todos os topicos lidos.",
"mark_all_read": "Marcar como Lido",
"load_more": "Carregar"
}

@ -0,0 +1,41 @@
{
"banned": "Banido",
"offline": "Offline",
"username": "Usu&aacute;rio",
"email": "Email",
"fullname": "Nome Completo",
"website": "Website",
"location": "Localiza&ccedil;&atilde;o",
"age": "Idade",
"joined": "Cadastrou",
"lastonline": "Visto &aacute;",
"profile_views": "Visualiza&ccedil;&otilde;es de Profile",
"reputation": "Reputa&ccedil;&atilde;o",
"posts": "Posts",
"followers": "Seguidores",
"following": "Seguindo",
"signature": "Assinatura",
"gravatar": "Gravatar",
"birthday": "Anivers&aacute;rio",
"change_picture": "Alterar Foto",
"edit": "Editar",
"uploaded_picture": "Foto Carregada",
"upload_new_picture": "Carregar novo Foto",
"change_password": "Alterar Senha",
"confirm_password": "Confirmar Senha",
"password": "Senha",
"upload_picture": "Carregar Foto",
"upload_a_picture": "Carregar Foto",
"image_spec": "Somente arquivos jpg, png e gif com no maximo 256kb.",
"settings": "Configura&ccedil;&otilde;es",
"show_email": "Mostrar meu email",
"has_no_follower": "Ningu&eacute;m est&aacute; seguindo esse usu&aacute;rio...",
"follows_no_one": "Este usu&aacute;rio n&atilde;o est&aacute; seguindo ninguem...",
"email_hidden": "Email Escondido",
"hidden": "Escondido"
}

@ -0,0 +1,9 @@
{
"latest_users": "Usu&aacute;rios Recentes",
"top_posters": "Top Posters",
"most_reputation": "Com Mais Reputa&ccedil;&atilde;o",
"online": "Online",
"search": "Procurar",
"enter_username": "Digite um usu&aacute;rio para buscar",
"load_more": "Carregar mais"
}

@ -537,12 +537,28 @@ var socket,
app.alternatingTitle('');
});
createHeaderTooltips();
templates.setGlobal('relative_path', RELATIVE_PATH);
templates.setGlobal('usePagination', config.usePagination);
templates.setGlobal('topicsPerPage', config.topicsPerPage);
templates.setGlobal('postsPerPage', config.postsPerPage);
});
function createHeaderTooltips() {
$('#header-menu li i[title]').each(function() {
$(this).parents('li').tooltip({
placement: 'bottom',
title: $(this).attr('title')
});
});
$('#user_label').tooltip({
placement: 'bottom',
title: $('#user_dropdown').attr('title')
});
}
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;
app.loadConfig();

@ -178,13 +178,13 @@ define(['uploader'], function(uploader) {
});
// Permissions modal
$('.permissions').on('click', function() {
$('.admin-categories').on('click', '.permissions', function() {
var cid = $(this).parents('li[data-cid]').attr('data-cid');
Categories.launchPermissionsModal(cid);
});
$('.upload-button').on('click', function() {
$('.admin-categories').on('click', '.upload-button', function() {
var inputEl = this;
var cid = $(this).parents('li[data-cid]').attr('data-cid');
uploader.open(RELATIVE_PATH + '/admin/category/uploadpicture', {cid:cid}, function(imageUrlOnServer) {
@ -196,7 +196,7 @@ define(['uploader'], function(uploader) {
});
});
$('.admin-categories').delegate('.delete-image', 'click', function() {
$('.admin-categories').on('click', '.delete-image', function() {
var parent = $(this).parents('li[data-cid]'),
inputEl = parent.find('.upload-button'),
preview = parent.find('.preview-box'),

@ -18,6 +18,7 @@ define(function() {
};
Admin.updateRoomUsage = function(err, data) {
function getUserCountIn(room) {
var count = 0;
for(var user in data[room]) {
@ -25,27 +26,36 @@ define(function() {
}
return count;
}
var active_users = $('#active_users'),
var active_users = $('#active_users').html(''),
total = 0;
if(!active_users.length) {
return;
}
active_users.html('');
var usersHtml = '';
var sortedData = [];
for (var room in data) {
if (room !== '') {
var count = getUserCountIn(room);
total += count;
usersHtml += "<div class='alert alert-success'><strong>" + room + "</strong> " + count + " active user" + (count > 1 ? "s" : "") + "</div>";
sortedData.push({room: room, count: data[room].length});
total += data[room].length;
}
}
sortedData.sort(function(a, b) {
return parseInt(b.count, 10) - parseInt(a.count, 10);
});
var usersHtml = '';
for(var i=0; i<sortedData.length; ++i) {
usersHtml += "<div class='alert alert-success'><strong>" + sortedData[i].room + "</strong> " +
sortedData[i].count + " active user" + (sortedData[i].count > 1 ? "s" : "") + "</div>";
}
active_users.html(usersHtml);
document.getElementById('connections').innerHTML = total;
$('#connections').html(total);
};
return Admin;

@ -145,7 +145,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
loadingMoreTopics = true;
socket.emit('categories.loadMore', {
cid: cid,
after: $('#topics-container').children('.category-item').length
after: $('#topics-container').attr('data-nextstart')
}, function (err, data) {
if(err) {
return app.alertError(err.message);
@ -153,6 +153,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
if (data && data.topics.length) {
Category.onTopicsLoaded(data.topics);
$('#topics-container').attr('data-nextstart', data.nextStart);
}
loadingMoreTopics = false;
});

@ -86,7 +86,7 @@ define(function() {
Recent.loadMoreTopics = function() {
loadingMoreTopics = true;
socket.emit('topics.loadMoreRecentTopics', {
after: $('#topics-container').children('li').length,
after: $('#topics-container').attr('data-nextstart'),
term: active
}, function(err, data) {
if(err) {
@ -95,6 +95,7 @@ define(function() {
if (data.topics && data.topics.length) {
Recent.onTopicsLoaded('recent', data.topics);
$('#topics-container').attr('data-nextstart', data.nextStart);
}
loadingMoreTopics = false;

@ -2,9 +2,9 @@ define(function() {
var Search = {};
Search.init = function() {
var searchQuery = $('#topics-container').attr('data-search-query');
$('.search-result-text').each(function() {
var searchQuery = $('#topic-results').attr('data-search-query');
console.log(searchQuery);
$('.search-result-text').children().each(function() {
var text = $(this).html();
var regex = new RegExp(searchQuery, 'gi');
text = text.replace(regex, '<span class="label label-success">' + searchQuery + '</span>');

@ -46,7 +46,7 @@ define(['forum/recent'], function(recent) {
function loadMoreTopics() {
loadingMoreTopics = true;
socket.emit('topics.loadMoreUnreadTopics', {
after: parseInt($('#topics-container').attr('data-next-start'), 10)
after: $('#topics-container').attr('data-nextstart')
}, function(err, data) {
if(err) {
return app.alertError(err.message);
@ -54,7 +54,7 @@ define(['forum/recent'], function(recent) {
if (data.topics && data.topics.length) {
recent.onTopicsLoaded('unread', data.topics);
$('#topics-container').attr('data-next-start', data.nextStart);
$('#topics-container').attr('data-nextstart', data.nextStart);
} else {
$('#load-more-btn').hide();
}

@ -6,7 +6,7 @@ define(function() {
var notifContainer = document.getElementsByClassName('notifications')[0],
notifTrigger = notifContainer.querySelector('a'),
notifList = document.getElementById('notif-list'),
notifIcon = $('.notifications a');
notifIcon = $('.notifications a i');
notifTrigger.addEventListener('click', function(e) {
e.preventDefault();
@ -46,14 +46,14 @@ define(function() {
notifList.appendChild(notifFrag);
if (data.unread.length > 0) {
notifIcon.toggleClass('active', true);
notifIcon.removeClass('fa-bell-o').addClass('fa-bell');
} else {
notifIcon.toggleClass('active', false);
notifIcon.removeClass('fa-bell').addClass('fa-bell-o');
}
socket.emit('modules.notifications.mark_all_read', null, function(err) {
if (!err) {
notifIcon.toggleClass('active', false);
notifIcon.removeClass('fa-bell').addClass('fa-bell-o');
app.refreshTitle();
// Update favicon + local count
@ -87,9 +87,9 @@ define(function() {
var updateNotifCount = function(count) {
// Update notification icon, if necessary
if (count > 0) {
notifIcon.toggleClass('active', true);
notifIcon.removeClass('fa-bell-o').addClass('fa-bell');
} else {
notifIcon.toggleClass('active', false);
notifIcon.removeClass('fa-bell').addClass('fa-bell-o');
}
// Update the favicon + saved local count
@ -106,7 +106,9 @@ define(function() {
});
socket.on('event:new_notification', function() {
notifIcon.toggleClass('active', true);
notifIcon.removeClass('fa-bell-o').addClass('fa-bell');
app.alert({
alert_id: 'new_notif',
title: 'New notification',

@ -106,6 +106,7 @@
collapseWhitespace : /\s+/g,
collapseDash : /-+/g,
trimTrailingDash : /-$/g,
trimLeadingDash : /^-/g,
isLatin : /^[\w]+$/,
//http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/
@ -120,6 +121,7 @@
str = str.replace(utils.collapseWhitespace, '-')
str = str.replace(utils.collapseDash, '-');
str = str.replace(utils.trimTrailingDash, '');
str = str.replace(utils.trimLeadingDash, '');
return str;
},

@ -1,23 +0,0 @@
<h1><i class="fa fa-facebook-square"></i> Facebook Social Authentication</h1>
<hr />
<form>
<div class="alert alert-warning">
<p>
Create a <strong>Facebook Application</strong> via the
<a href="https://developers.facebook.com/">Facebook Developers Page</a> and
then paste your application details here.
</p>
<br />
<input type="text" data-field="social:facebook:app_id" title="Application ID" class="form-control input-lg" placeholder="App ID"><br />
<input type="text" data-field="social:facebook:secret" title="Application Secret" class="form-control input-md" placeholder="App Secret"><br />
</div>
</form>
<button class="btn btn-lg btn-primary" id="save">Save</button>
<script>
require(['forum/admin/settings'], function(Settings) {
Settings.prepare();
});
</script>

@ -1,23 +0,0 @@
<h1><i class="fa fa-google-plus-square"></i> Google Accounts Social Authentication</h1>
<hr />
<form>
<div class="alert alert-warning">
<p>
Create a <strong>Google Application</strong> via the
<a href="https://code.google.com/apis/console/">API Console</a> and then paste
your application details here.
</p>
<br />
<input type="text" data-field="social:google:id" title="Client ID" class="form-control input-lg" placeholder="Client ID"><br />
<input type="text" data-field="social:google:secret" title="Client Secret" class="form-control" placeholder="Client Secret"><br />
</div>
</form>
<button class="btn btn-lg btn-primary" id="save">Save</button>
<script>
require(['forum/admin/settings'], function(Settings) {
Settings.prepare();
});
</script>

@ -115,9 +115,6 @@
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Social Authentication</li>
<li><a href="{relative_path}/admin/twitter"><i class="fa fa-fw fa-twitter-square"></i> Twitter</a></li>
<li><a href="{relative_path}/admin/facebook"><i class="fa fa-fw fa-facebook-square"></i> Facebook</a></li>
<li><a href="{relative_path}/admin/gplus"><i class="fa fa-fw fa-google-plus-square"></i> Google+</a></li>
<!-- BEGIN authentication -->
<li>
<a href="{relative_path}/admin{authentication.route}"><i class="fa fa-fw {authentication.icon}"></i> {authentication.name}</a>

@ -1,23 +0,0 @@
<h1><i class="fa fa-twitter-square"></i> Twitter Social Authentication</h1>
<hr />
<form>
<div class="alert alert-warning">
<p>
Create a <strong>Twitter Application</strong> via the
<a href="https://dev.twitter.com/">Twitter Developers Page</a> and then
paste your application details here.
</p>
<br />
<input type="text" data-field="social:twitter:key" title="Consumer Key" class="form-control input-lg" placeholder="Consumer Key"><br />
<input type="text" data-field="social:twitter:secret" title="Consumer Secret" class="form-control input-md" placeholder="Consumer Secret">
</div>
</form>
<button class="btn btn-lg btn-primary" id="save">Save</button>
<script>
require(['forum/admin/settings'], function(Settings) {
Settings.prepare();
});
</script>

@ -28,7 +28,7 @@
<div class="category row">
<div class="{topic_row_size}">
<ul id="topics-container" itemscope itemtype="http://www.schema.org/ItemList">
<ul id="topics-container" itemscope itemtype="http://www.schema.org/ItemList" data-nextstart="{nextStart}">
<meta itemprop="itemListOrder" content="descending">
<!-- BEGIN topics -->
<li class="category-item {topics.deleted-class}" itemprop="itemListElement">

@ -11,10 +11,7 @@
"^admin/plugins/?$": "admin/plugins",
"^admin/languages/?$": "admin/languages",
"^admin/settings.*": "admin/settings",
"^admin/twitter.*": "admin/twitter",
"^admin/facebook.*": "admin/facebook",
"^admin/logger.*": "admin/logger",
"^admin/gplus.*": "admin/gplus",
"^admin/motd/?$": "admin/motd",
"^admin/groups/?$": "admin/groups",
"^users/sort-posts": "users",

@ -92,7 +92,7 @@
</li>
<li class="notifications dropdown text-center hidden-xs">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"></a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"><i class="fa fa-bell-o" title="[[global:header.notifications]]"></i></a>
<ul id="notif-list" class="dropdown-menu" aria-labelledby="notif_dropdown">
<li>
<a href="#"><i class="fa fa-refresh fa-spin"></i> [[global:notifications.loading]]</a>
@ -104,7 +104,7 @@
</li>
<li class="chats dropdown text-center hidden-xs">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="chat_dropdown"><i class="fa fa-comment-o"></i></a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="chat_dropdown"><i class="fa fa-comment-o" title="[[global:header.chats]]"></i></a>
<ul id="chat-list" class="dropdown-menu" aria-labelledby="chat_dropdown">
<li>
<a href="#"><i class="fa fa-refresh fa-spin"></i> [[global:chats.loading]]</a>
@ -113,7 +113,7 @@
</li>
<li id="user_label" class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="user_dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="user_dropdown" title="[[global:header.profile]]">
<img src=""/>
</a>
<ul id="user-control-list" class="dropdown-menu" aria-labelledby="user_dropdown">
@ -152,7 +152,7 @@
</li>
<li class="hidden-xs">
<a href="#" id="search-button" class="hide"><i class="fa fa-search"></i></a>
<a href="#" id="search-button" class="hide"><i class="fa fa-search" title="[[global:header.search]]"></i></a>
</li>
</ul>

@ -21,7 +21,7 @@
<div class="category row">
<div class="col-md-12">
<ul id="topics-container">
<ul id="topics-container" data-nextstart="{nextStart}">
<!-- BEGIN topics -->
<li class="category-item {topics.deleted-class}">
<div class="col-md-12 col-xs-12 panel panel-default topic-row">

@ -13,56 +13,86 @@
</div>
</form>
<div class="category search">
<div class="{show_results}">
<h3>[[topic:topics]]</h3>
<div class="search favourites well">
<div class="{show_results} row">
<!-- IF topic_matches -->
<small>{topic_matches} result(s) matching "{search_query}"</small>
<!-- ENDIF topic_matches -->
<div class="alert alert-info {show_no_topics}">[[topic:no_topics_found]]</div>
<div id="topic-results" class="col-md-12" data-search-query="{search_query}">
<ul id="topics-container" data-search-query="{search_query}">
<h3>[[topic:topics]]</h3>
<!-- IF topic_matches -->
<small>{topic_matches} result(s) matching "{search_query}"</small>
<!-- ENDIF topic_matches -->
<div class="alert alert-info {show_no_topics}">[[topic:no_topics_found]]</div>
<!-- BEGIN topics -->
<li class="category-item">
<a href="{relative_path}/topic/{topics.slug}" id="tid-{topics.tid}">
<div>
<div class="col-md-12 img-thumbnail">
<div class="search-result-post">
<img src="{topics.teaser_userpicture}" />
<strong>{topics.teaser_username}</strong>: <span class="search-result-text">{topics.title}</span>
</div>
<div class="topic-row panel panel-default clearfix">
<div class="panel-body">
<a href="../../user/{topics.userslug}">
<img title="{topics.username}" class="img-rounded user-img" src="{topics.picture}">
</a>
<a href="../../user/{topics.userslug}">
<strong><span>{topics.username}</span></strong>
</a>
<span class="search-result-text">
<p>{topics.title}</p>
</span>
</div>
<div>
<small>
<span class="pull-right">
<a href="../../topic/{topics.slug}">posted</a>
in
<a href="../../category/{topics.categorySlug}">
<i class="fa {topics.categoryIcon}"></i> {topics.categoryName}
</a>
<span class="timeago" title="{topics.relativeTime}"></span>
</span>
</small>
</div>
</a>
</li>
</div>
</div>
<!-- END topics -->
</ul>
</div>
<h3>Posts</h3>
<!-- IF post_matches -->
<small>{post_matches} result(s) matching "{search_query}"</small>
<!-- ENDIF post_matches -->
<div class="alert alert-info {show_no_posts}">No posts found!</div>
<div id="post-results" class="col-md-12" data-search-query="{search_query}">
<h3>Posts</h3>
<!-- IF post_matches -->
<small>{post_matches} result(s) matching "{search_query}"</small>
<!-- ENDIF post_matches -->
<div class="alert alert-info {show_no_posts}">No posts found!</div>
<ul id="topics-container" data-search-query="{search_query}">
<!-- BEGIN posts -->
<li class="category-item">
<a href="{relative_path}/topic/{posts.topicSlug}#{posts.pid}" id="tid-{posts.tid}">
<div>
<div class="col-md-12 img-thumbnail">
<div class="search-result-post">
<img src="{posts.picture}" />
<strong>{posts.username}</strong>: <span class="search-result-text">{posts.content}</span>
</div>
<div class="topic-row panel panel-default clearfix">
<div class="panel-body">
<a href="../../user/{posts.userslug}">
<img title="{posts.username}" class="img-rounded user-img" src="{posts.picture}">
</a>
<a href="../../user/{posts.userslug}">
<strong><span>{posts.username}</span></strong>
</a>
<span class="search-result-text">
{posts.content}
</span>
</div>
<div>
<small>
<span class="pull-right">
<a href="../../topic/{posts.topicSlug}#{posts.pid}">posted</a>
in
<a href="../../category/{posts.categorySlug}">
<i class="fa {posts.categoryIcon}"></i> {posts.categoryName}
</a>
<span class="timeago" title="{posts.relativeTime}"></span>
</span>
</small>
</div>
</a>
</li>
</div>
</div>
<!-- END posts -->
</ul>
</div>
</div>
</div>

@ -16,7 +16,7 @@
<div class="category row">
<div class="col-md-12">
<ul id="topics-container" data-next-start="{nextStart}">
<ul id="topics-container" data-nextstart="{nextStart}">
<!-- BEGIN topics -->
<li class="category-item {topics.deleted-class}">
<div class="col-md-12 col-xs-12 panel panel-default topic-row">

@ -1,8 +1,8 @@
var db = require('./database.js'),
posts = require('./posts.js'),
utils = require('./../public/src/utils.js'),
user = require('./user.js'),
topics = require('./topics.js'),
var db = require('./database'),
posts = require('./posts'),
utils = require('./../public/src/utils'),
user = require('./user'),
topics = require('./topics'),
plugins = require('./plugins'),
CategoryTools = require('./categoryTools'),
meta = require('./meta'),
@ -52,8 +52,8 @@ var db = require('./database.js'),
return callback(err);
}
function getTopicIds(next) {
Categories.getTopicIds(category_id, start, end, next);
function getTopics(next) {
Categories.getCategoryTopics(category_id, start, end, current_user, next);
}
function getActiveUsers(next) {
@ -70,9 +70,12 @@ var db = require('./database.js'),
Categories.getPageCount(category_id, next);
}
async.parallel([getTopicIds, getActiveUsers, getSidebars, getPageCount], function(err, results) {
var tids = results[0],
active_users = results[1],
async.parallel([getTopics, getActiveUsers, getSidebars, getPageCount], function(err, results) {
if(err) {
return callback(err);
}
var active_users = results[1],
sidebars = results[2],
pageCount = results[3];
@ -87,27 +90,22 @@ var db = require('./database.js'),
'topic_row_size': 'col-md-9',
'category_id': category_id,
'active_users': [],
'topics': [],
'topics': results[0].topics,
'nextStart': results[0].nextStart,
'pageCount': pageCount,
'disableSocialButtons': meta.config.disableSocialButtons !== undefined ? parseInt(meta.config.disableSocialButtons, 10) !== 0 : false,
'sidebars': sidebars
};
function getTopics(next) {
topics.getTopicsByTids(tids, category_id, current_user, next);
}
function getModerators(next) {
Categories.getModerators(category_id, next);
}
function getActiveUsers(next) {
user.getMultipleUserFields(active_users, ['uid', 'username', 'userslug', 'picture'], function(err, users) {
next(err, users);
});
user.getMultipleUserFields(active_users, ['uid', 'username', 'userslug', 'picture'], next);
}
if (tids.length === 0) {
if (!category.topics.length) {
getModerators(function(err, moderators) {
category.moderator_block_class = moderators.length > 0 ? '' : 'none';
category.moderators = moderators;
@ -116,11 +114,10 @@ var db = require('./database.js'),
callback(null, category);
});
} else {
async.parallel([getTopics, getModerators, getActiveUsers], function(err, results) {
category.topics = results[0];
category.moderator_block_class = results[1].length > 0 ? '' : 'none';
category.moderators = results[1];
category.active_users = results[2];
async.parallel([getModerators, getActiveUsers], function(err, results) {
category.moderator_block_class = results[0].length > 0 ? '' : 'none';
category.moderators = results[0];
category.active_users = results[1];
category.show_sidebar = category.topics.length > 0 ? 'show' : 'hidden';
callback(null, category);
});
@ -131,13 +128,26 @@ var db = require('./database.js'),
};
Categories.getCategoryTopics = function(cid, start, stop, uid, callback) {
Categories.getTopicIds(cid, start, stop, function(err, tids) {
if(err) {
return callback(err);
}
async.waterfall([
function(next) {
Categories.getTopicIds(cid, start, stop, next);
},
function(tids, next) {
topics.getTopicsByTids(tids, cid, uid, next);
},
function(topics, next) {
db.sortedSetRevRank('categories:' + cid + ':tid', topics[topics.length - 1].tid, function(err, rank) {
if(err) {
return next(err);
}
topics.getTopicsByTids(tids, cid, uid, callback);
});
return next(null, {
topics: topics,
nextStart: parseInt(rank, 10) + 1
});
});
}
], callback);
};
Categories.getTopicIds = function(cid, start, stop, callback) {

@ -656,6 +656,23 @@
});
}
module.sortedSetRevRank = function(key, value, callback) {
if(value !== null && value !== undefined) {
value = value.toString();
}
module.getSortedSetRange(key, 0, -1, function(err, result) {
if(err) {
return callback(err);
}
var rank = result.indexOf(value);
if(rank === -1) {
return callback(null, null);
}
callback(null, result.length - rank - 1);
});
}
module.sortedSetScore = function(key, value, callback) {
if(value !== null && value !== undefined) {
value = value.toString();

@ -382,6 +382,10 @@
redisClient.zrank(key, value, callback);
}
module.sortedSetRevRank = function(key, value, callback) {
redisClient.zrevrank(key, value, callback);
}
module.sortedSetScore = function(key, value, callback) {
redisClient.zscore(key, value, callback);
}

@ -38,13 +38,17 @@
}
}
var description = topicData.posts.length ? topicData.posts[0].content : '';
var image_url = topicData.posts.length ? topicData.posts[0].picture : '';
var author = topicData.posts.length ? topicData.posts[0].username : '';
var feed = new rss({
title: topicData.topic_name,
description: topicData.posts[0].content,
description: description,
feed_url: Feed.defaults.baseUrl + '/topics/' + tid + '.rss',
site_url: nconf.get('url') + '/topic/' + topicData.slug,
image_url: topicData.posts[0].picture,
author: topicData.posts[0].username,
image_url: image_url,
author: author,
ttl: Feed.defaults.ttl
}),
dateStamp;

@ -1,5 +1,5 @@
var user = require('./user'),
bcrypt = require('bcrypt'),
bcrypt = require('bcryptjs'),
db = require('./database'),
path = require('path'),
winston = require('winston'),
@ -56,129 +56,4 @@ var user = require('./user'),
});
}
}
Login.loginViaTwitter = function(twid, handle, photos, callback) {
user.getUidByTwitterId(twid, function(err, uid) {
if(err) {
return callback(err);
}
if (uid !== null) {
// Existing User
callback(null, {
uid: uid
});
} else {
// New User
user.create({username: handle}, function(err, uid) {
if(err) {
return callback(err);
}
// Save twitter-specific information to the user
user.setUserField(uid, 'twid', twid);
db.setObjectField('twid:uid', twid, uid);
// Save their photo, if present
if (photos && photos.length > 0) {
var photoUrl = photos[0].value;
photoUrl = path.dirname(photoUrl) + '/' + path.basename(photoUrl, path.extname(photoUrl)).slice(0, -6) + 'bigger' + path.extname(photoUrl);
user.setUserField(uid, 'uploadedpicture', photoUrl);
user.setUserField(uid, 'picture', photoUrl);
}
callback(null, {
uid: uid
});
});
}
});
};
Login.loginViaGoogle = function(gplusid, handle, email, callback) {
user.getUidByGoogleId(gplusid, function(err, uid) {
if(err) {
return callback(err);
}
if (uid !== null) {
// Existing User
callback(null, {
uid: uid
});
} else {
// New User
var success = function(uid) {
// Save google-specific information to the user
user.setUserField(uid, 'gplusid', gplusid);
db.setObjectField('gplusid:uid', gplusid, uid);
callback(null, {
uid: uid
});
};
user.getUidByEmail(email, function(err, uid) {
if(err) {
return callback(err);
}
if (!uid) {
user.create({username: handle, email: email}, function(err, uid) {
if(err) {
return callback(err);
}
success(uid);
});
} else {
success(uid); // Existing account -- merge
}
});
}
});
};
Login.loginViaFacebook = function(fbid, name, email, callback) {
user.getUidByFbid(fbid, function(err, uid) {
if(err) {
return callback(err);
}
if (uid !== null) {
// Existing User
callback(null, {
uid: uid
});
} else {
// New User
var success = function(uid) {
// Save facebook-specific information to the user
user.setUserField(uid, 'fbid', fbid);
db.setObjectField('fbid:uid', fbid, uid);
callback(null, {
uid: uid
});
};
user.getUidByEmail(email, function(err, uid) {
if(err) {
return callback(err);
}
if (!uid) {
user.create({username: name, email: email}, function(err, uid) {
if(err) {
return callback(err);
}
success(uid);
});
} else {
success(uid); // Existing account -- merge
}
});
}
});
}
}(exports));

@ -56,13 +56,16 @@ var db = require('./database'),
var messages = [];
userData[0].uid = touid;
userData[1].uid = fromuid;
function getMessage(mid, next) {
db.getObject('message:' + mid, function(err, message) {
if (err) {
return next(err);
}
Messaging.parse(message.content, message.fromuid, fromuid, userData[1], userData[0], function(result) {
Messaging.parse(message.content, message.fromuid, fromuid, userData[1], userData[0], false, function(result) {
message.content = result;
messages.push(message);
next(null);
@ -81,7 +84,7 @@ var db = require('./database'),
});
};
Messaging.parse = function (message, fromuid, myuid, toUserData, myUserData, callback) {
Messaging.parse = function (message, fromuid, myuid, toUserData, myUserData, isNew, callback) {
plugins.fireHook('filter:post.parse', message, function(err, parsed) {
if (err) {
return callback(message);
@ -104,6 +107,7 @@ var db = require('./database'),
myuid: myuid,
toUserData: toUserData,
myUserData: myUserData,
isNew: isNew,
parsedMessage: picture + username + parsed
};

@ -58,8 +58,7 @@ var nconf = require('nconf'),
(function () {
var routes = [
'categories/active', 'categories/disabled', 'users', 'topics', 'settings', 'themes',
'twitter', 'facebook', 'gplus', 'database', 'events', 'motd', 'groups', 'plugins',
'languages', 'logger',
'database', 'events', 'motd', 'groups', 'plugins', 'languages', 'logger',
'users/latest', 'users/sort-posts', 'users/sort-reputation', 'users/search'
];
@ -409,18 +408,6 @@ var nconf = require('nconf'),
res.json(200, {});
});
app.get('/twitter', function (req, res) {
res.json(200, {});
});
app.get('/facebook', function (req, res) {
res.json(200, {});
});
app.get('/gplus', function (req, res) {
res.json(200, {});
});
app.get('/testing/categories', function (req, res) {
res.json(200, {});
});

@ -1,9 +1,6 @@
(function(Auth) {
var passport = require('passport'),
passportLocal = require('passport-local').Strategy,
passportTwitter = require('passport-twitter').Strategy,
passportGoogle = require('passport-google-oauth').OAuth2Strategy,
passportFacebook = require('passport-facebook').Strategy,
login_strategies = [],
nconf = require('nconf'),
meta = require('../meta'),
@ -32,75 +29,6 @@
});
});
if (meta.config['social:twitter:key'] && meta.config['social:twitter:secret']) {
passport.use(new passportTwitter({
consumerKey: meta.config['social:twitter:key'],
consumerSecret: meta.config['social:twitter:secret'],
callbackURL: nconf.get('url') + '/auth/twitter/callback'
}, function(token, tokenSecret, profile, done) {
login_module.loginViaTwitter(profile.id, profile.username, profile.photos, function(err, user) {
if (err) {
return done(err);
}
done(null, user);
});
}));
login_strategies.push({
name: 'twitter',
url: '/auth/twitter',
callbackURL: '/auth/twitter/callback',
icon: 'twitter',
scope: ''
});
}
if (meta.config['social:google:id'] && meta.config['social:google:secret']) {
passport.use(new passportGoogle({
clientID: meta.config['social:google:id'],
clientSecret: meta.config['social:google:secret'],
callbackURL: nconf.get('url') + '/auth/google/callback'
}, function(accessToken, refreshToken, profile, done) {
login_module.loginViaGoogle(profile.id, profile.displayName, profile.emails[0].value, function(err, user) {
if (err) {
return done(err);
}
done(null, user);
});
}));
login_strategies.push({
name: 'google',
url: '/auth/google',
callbackURL: '/auth/google/callback',
icon: 'google-plus',
scope: 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'
});
}
if (meta.config['social:facebook:app_id'] && meta.config['social:facebook:secret']) {
passport.use(new passportFacebook({
clientID: meta.config['social:facebook:app_id'],
clientSecret: meta.config['social:facebook:secret'],
callbackURL: nconf.get('url') + '/auth/facebook/callback'
}, function(accessToken, refreshToken, profile, done) {
login_module.loginViaFacebook(profile.id, profile.displayName, profile.emails[0].value, function(err, user) {
if (err) {
return done(err);
}
done(null, user);
});
}));
login_strategies.push({
name: 'facebook',
url: '/auth/facebook',
callbackURL: '/auth/facebook/callback',
icon: 'facebook',
scope: 'email'
});
}
passport.serializeUser(function(user, done) {
done(null, user.uid);
});

@ -75,12 +75,12 @@ var DebugRoute = function(app) {
app.get('/test', function(req, res) {
/*topics.getTopicPosts2(2, 0, 10, 5, function(err, data) {
res.json(data);
})*/
topics.getTopicWithPosts(2, 1, 0, -1, true, function (err, topicData) {
res.json(topicData);
var db = require('./../database');
db.getSortedSetRevRange('topics:recent', 0 , -1, function(err, tids) {
res.json(tids);
});
});
});

@ -18,14 +18,10 @@ SocketCategories.loadMore = function(socket, data, callback) {
var topicsPerPage = parseInt(meta.config.topicsPerPage, 10) || 20;
var start = data.after,
var start = parseInt(data.after, 10),
end = start + topicsPerPage - 1;
categories.getCategoryTopics(data.cid, start, end, socket.uid, function(err, topics) {
callback(err, {
topics: topics
});
});
categories.getCategoryTopics(data.cid, start, end, socket.uid, callback);
};
SocketCategories.getPageCount = function(socket, cid, callback) {

@ -22,12 +22,11 @@ var SocketIO = require('socket.io'),
/* === */
var users = {},
io;
var io;
Sockets.userSockets = {};
Sockets.rooms = {};
Sockets.init = function(server) {
@ -59,9 +58,9 @@ Sockets.init = function(server) {
sessionID = socket.handshake.signedCookies["express.sid"];
db.sessionStore.get(sessionID, function(err, sessionData) {
if (!err && sessionData && sessionData.passport && sessionData.passport.user) {
uid = users[sessionID] = sessionData.passport.user;
uid = sessionData.passport.user;
} else {
uid = users[sessionID] = 0;
uid = 0;
}
socket.uid = parseInt(uid, 10);
@ -110,8 +109,8 @@ Sockets.init = function(server) {
}
if (Sockets.userSockets[uid] && Sockets.userSockets[uid].length === 0) {
delete users[sessionID];
delete Sockets.userSockets[uid];
if (uid) {
db.sortedSetRemove('users:online', uid, function(err, data) {
});
@ -126,17 +125,10 @@ Sockets.init = function(server) {
emitOnlineUserCount();
for (var roomName in Sockets.rooms) {
if (Sockets.rooms.hasOwnProperty(roomName)) {
socket.leave(roomName);
if (Sockets.rooms[roomName][socket.id]) {
delete Sockets.rooms[roomName][socket.id];
}
updateRoomBrowsingText(roomName);
}
for(var roomName in io.sockets.manager.roomClients[socket.id]) {
updateRoomBrowsingText(roomName.slice(1));
}
});
socket.on('*', function(payload, callback) {
@ -222,9 +214,10 @@ function updateRoomBrowsingText(roomName) {
function getUidsInRoom(room) {
var uids = [];
for (var socketId in room) {
if (uids.indexOf(room[socketId]) === -1) {
uids.push(room[socketId]);
var clients = io.sockets.clients(roomName);
for(var i=0; i<clients.length; ++i) {
if (uids.indexOf(clients[i].uid) === -1 && clients[i].uid !== 0) {
uids.push(clients[i].uid);
}
}
return uids;
@ -235,15 +228,14 @@ function updateRoomBrowsingText(roomName) {
var anonCount = 0;
for (var i = 0; i < clients.length; ++i) {
var hs = clients[i].handshake;
if (hs && clients[i].state && clients[i].state.user.uid === 0) {
if(clients[i].uid === 0) {
++anonCount;
}
}
return anonCount;
}
var uids = getUidsInRoom(Sockets.rooms[roomName]),
var uids = getUidsInRoom(roomName),
anonymousCount = getAnonymousCount(roomName);
user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], function(err, users) {

@ -84,18 +84,6 @@ SocketMeta.rooms.enter = function(socket, data) {
}
socket.join(data.enter);
server.rooms[data.enter] = server.rooms[data.enter] || {};
if (socket.uid) {
server.rooms[data.enter][socket.id] = socket.uid;
if (data.leave && server.rooms[data.leave] && server.rooms[data.leave][socket.id] && data.enter !== data.leave) {
delete server.rooms[data.leave][socket.id];
if(!Object.keys(server.rooms[data.leave]).length) {
delete server.rooms[data.leave];
}
}
}
if (data.leave) {
module.parent.exports.updateRoomBrowsingText(data.leave);
@ -104,12 +92,12 @@ SocketMeta.rooms.enter = function(socket, data) {
module.parent.exports.updateRoomBrowsingText(data.enter);
if (data.enter != 'admin') {
server.in('admin').emit('event:meta.rooms.update', null, server.rooms);
server.in('admin').emit('event:meta.rooms.update', null, server.server.sockets.manager.rooms);
}
};
SocketMeta.rooms.getAll = function(socket, data, callback) {
callback(null, server.rooms);
callback(null, server.server.sockets.manager.rooms);
};
/* Exports */

@ -109,7 +109,11 @@ SocketModules.chats.send = function(socket, data) {
});
});
}
Messaging.parse(msg, socket.uid, socket.uid, usersData[1], usersData[0], function(parsed) {
usersData[0].uid = socket.uid;
usersData[1].uid = touid;
Messaging.parse(msg, socket.uid, socket.uid, usersData[1], usersData[0], true, function(parsed) {
Messaging.addMessage(socket.uid, touid, msg, function(err, message) {
var numSockets = 0,
x;

@ -236,7 +236,7 @@ SocketTopics.loadMore = function(socket, data, callback) {
var postsPerPage = parseInt(meta.config.postsPerPage, 10);
postsPerPage = postsPerPage ? postsPerPage : 20;
var start = data.after,
var start = parseInt(data.after, 10),
end = start + postsPerPage - 1;
async.parallel({
@ -256,14 +256,14 @@ SocketTopics.loadMoreRecentTopics = function(socket, data, callback) {
return callback(new Error('invalid data'));
}
var start = data.after,
var start = parseInt(data.after, 10),
end = start + 9;
topics.getLatestTopics(socket.uid, start, end, data.term, callback);
};
SocketTopics.loadMoreUnreadTopics = function(socket, data, callback) {
var start = data.after,
var start = parseInt(data.after, 10),
end = start + 9;
topics.getUnreadTopics(socket.uid, start, end, callback);

@ -426,8 +426,9 @@ var async = require('async'),
};
var since = terms['day'];
if(terms[term])
if(terms[term]) {
since = terms[term];
}
var args = ['topics:recent', '+inf', timestamp - since, 'LIMIT', start, end - start + 1];
db.getSortedSetRevRangeByScore(args, function(err, tids) {
@ -442,23 +443,29 @@ var async = require('async'),
if (!tids || !tids.length) {
latestTopics.no_topics_message = 'show';
callback(err, latestTopics);
return;
return callback(null, latestTopics);
}
// Filter out topics that belong to categories that this user cannot access
async.filter(tids, function(tid, next) {
threadTools.privileges(tid, current_user, function(err, privileges) {
if (!err && privileges.read) {
next(true);
} else {
next(false);
}
next(!err && privileges.read);
});
}, function(tids) {
Topics.getTopicsByTids(tids, 0, current_user, function(err, topicData) {
latestTopics.topics = topicData;
callback(err, latestTopics);
if(err) {
return callback(err);
}
if(!topicData || !topicData.length) {
latestTopics.no_topics_message = 'show';
return callback(null, latestTopics);
}
db.sortedSetRevRank('topics:recent', topicData[topicData.length - 1].tid, function(err, rank) {
latestTopics.nextStart = parseInt(rank,10) + 1;
latestTopics.topics = topicData;
callback(null, latestTopics);
});
});
});
});
@ -538,7 +545,7 @@ var async = require('async'),
return parseInt(read[index], 10) === 0;
});
// Filter out topics that belong to categories that this user cannot access
async.filter(newtids, function(tid, next) {
threadTools.privileges(tid, uid, function(err, privileges) {
if (!err && privileges.read) {
@ -588,16 +595,23 @@ var async = require('async'),
return callback(err);
}
unreadTopics.topics = topicData;
unreadTopics.nextStart = stop + 1;
if (!topicData || topicData.length === 0) {
unreadTopics.no_topics_message = 'show';
}
if (uid === 0 || topicData.length === 0) {
unreadTopics.show_markallread_button = 'hidden';
}
db.sortedSetRevRank('topics:recent', topicData[topicData.length - 1].tid, function(err, rank) {
if(err) {
return callback(err);
}
unreadTopics.topics = topicData;
unreadTopics.nextStart = parseInt(rank, 10) + 1;
callback(null, unreadTopics);
if (!topicData || topicData.length === 0) {
unreadTopics.no_topics_message = 'show';
}
if (uid === 0 || topicData.length === 0) {
unreadTopics.show_markallread_button = 'hidden';
}
callback(null, unreadTopics);
});
});
}
@ -700,6 +714,7 @@ var async = require('async'),
function isTopicVisible(topicData, topicInfo) {
var deleted = parseInt(topicData.deleted, 10) !== 0;
return !deleted || (deleted && topicInfo.privileges.view_deleted) || topicData.uid === current_user;
}

@ -1,4 +1,4 @@
var bcrypt = require('bcrypt'),
var bcrypt = require('bcryptjs'),
async = require('async'),
nconf = require('nconf'),
winston = require('winston'),
@ -742,33 +742,6 @@ var bcrypt = require('bcrypt'),
});
};
User.getUidByTwitterId = function(twid, callback) {
db.getObjectField('twid:uid', twid, function(err, uid) {
if (err) {
return callback(err);
}
callback(null, uid);
});
};
User.getUidByGoogleId = function(gplusid, callback) {
db.getObjectField('gplusid:uid', gplusid, function(err, uid) {
if (err) {
return callback(err);
}
callback(null, uid);
});
};
User.getUidByFbid = function(fbid, callback) {
db.getObjectField('fbid:uid', fbid, function(err, uid) {
if (err) {
return callback(err);
}
callback(null, uid);
});
};
User.isModerator = function(uid, cid, callback) {
db.isSetMember('cid:' + cid + ':moderators', uid, function(err, exists) {
if(err) {
@ -926,21 +899,21 @@ var bcrypt = require('bcrypt'),
confirm: function(code, callback) {
db.getObject('confirm:' + code, function(err, confirmObj) {
if (err) {
callback({
return callback({
status:'error'
});
} else {
if (confirmObj.uid && confirmObj.email) {
db.setObjectField('email:confirmed', confirmObj.email, '1', function() {
callback({
status: 'ok'
});
});
} else {
}
if (confirmObj && confirmObj.uid && confirmObj.email) {
db.setObjectField('email:confirmed', confirmObj.email, '1', function() {
callback({
status: 'not_ok'
status: 'ok'
});
}
});
} else {
callback({
status: 'not_ok'
});
}
});
}

@ -43,9 +43,9 @@ describe('Categories', function() {
describe('.getCategoryTopics', function() {
it('should return a list of topics', function(done) {
Categories.getCategoryTopics(categoryObj.cid, 0, 10, 0, function(err, topics) {
assert(Array.isArray(topics));
assert(topics.every(function(topic) {
Categories.getCategoryTopics(categoryObj.cid, 0, 10, 0, function(err, result) {
assert(Array.isArray(result.topics));
assert(result.topics.every(function(topic) {
return topic instanceof Object;
}));

Loading…
Cancel
Save