Resolve merge conflicts, minify only `.js` files
commit
dd2b930824
@ -1,9 +1,9 @@
|
||||
{
|
||||
"loading": "Načítání motivů…",
|
||||
"homepage": "Homepage",
|
||||
"select-skin": "Select Skin",
|
||||
"current-skin": "Current Skin",
|
||||
"skin-updated": "Skin Updated",
|
||||
"homepage": "Domovská stránka",
|
||||
"select-skin": "Vyber motiv",
|
||||
"current-skin": "Současný motiv",
|
||||
"skin-updated": "Motiv aktualizován",
|
||||
"applied-success": "%1 skin was succesfully applied",
|
||||
"revert-success": "Skin reverted to base colours"
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
{
|
||||
"post-cache": "Кэш записи",
|
||||
"posts-in-cache": "Записей в кэше",
|
||||
"average-post-size": "Average Post Size",
|
||||
"length-to-max": "Length / Max",
|
||||
"average-post-size": "Средний размер записи",
|
||||
"length-to-max": "Длина / Максимальная",
|
||||
"percent-full": "%1% Full",
|
||||
"post-cache-size": "Post Cache Size",
|
||||
"post-cache-size": "Размер записи в кэше",
|
||||
"items-in-cache": "Items in Cache",
|
||||
"control-panel": "Control Panel",
|
||||
"update-settings": "Update Cache Settings"
|
||||
"control-panel": "Панель управления",
|
||||
"update-settings": "Обновить настройки кэша"
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
{
|
||||
"figure-x": "Znázorniť %1",
|
||||
"error-events-per-day": "<code>%1</code> events per day",
|
||||
"error.404": "404 Not Found",
|
||||
"error.503": "503 Service Unavailable",
|
||||
"error.404": "404 Nenájdené",
|
||||
"error.503": "503 Služba nie je k dispozícií",
|
||||
"manage-error-log": "Manage Error Log",
|
||||
"export-error-log": "Export Error Log (CSV)",
|
||||
"clear-error-log": "Clear Error Log",
|
||||
"route": "Route",
|
||||
"count": "Count",
|
||||
"no-routes-not-found": "Hooray! No 404 errors!",
|
||||
"no-routes-not-found": "Hurá! Žiadne chyby 404!",
|
||||
"clear404-confirm": "Are you sure you wish to clear the 404 error logs?",
|
||||
"clear404-success": "\"404 Not Found\" errors cleared"
|
||||
"clear404-success": "Chybné hlásenia \"404 Nenájdené\" vyčistené"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"events": "Udalosti",
|
||||
"no-events": "There are no events",
|
||||
"control-panel": "Events Control Panel",
|
||||
"delete-events": "Delete Events"
|
||||
"no-events": "Zatiaľ neexistujô žiadne udalosti",
|
||||
"control-panel": "Ovládací panel udalostí",
|
||||
"delete-events": "Odstrániť udalosť"
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"logs": "Protokoly",
|
||||
"control-panel": "Logs Control Panel",
|
||||
"reload": "Reload Logs",
|
||||
"clear": "Clear Logs",
|
||||
"clear-success": "Logs Cleared!"
|
||||
"logs": "Záznamy",
|
||||
"control-panel": "Ovládací panel záznamov",
|
||||
"reload": "Znovu načítať záznamy",
|
||||
"clear": "Vyčistiť záznamy",
|
||||
"clear-success": "Záznamy vyčistené!"
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"loading": "Loading Skins...",
|
||||
"homepage": "Homepage",
|
||||
"select-skin": "Select Skin",
|
||||
"current-skin": "Current Skin",
|
||||
"skin-updated": "Skin Updated",
|
||||
"applied-success": "%1 skin was succesfully applied",
|
||||
"revert-success": "Skin reverted to base colours"
|
||||
"loading": "Načítať vzhľady...",
|
||||
"homepage": "Domovska stránka",
|
||||
"select-skin": "Vybrať vzhľad",
|
||||
"current-skin": "Aktuálny vzhľad",
|
||||
"skin-updated": "Vzhľad aktualizovaný",
|
||||
"applied-success": "%1 vzhľad bol úspešne aplikovaný",
|
||||
"revert-success": "Vzhľad bol obnovený do základných farieb"
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
{
|
||||
"checking-for-installed": "Checking for installed themes...",
|
||||
"homepage": "Homepage",
|
||||
"select-theme": "Select Theme",
|
||||
"current-theme": "Current Theme",
|
||||
"no-themes": "No installed themes found",
|
||||
"revert-confirm": "Are you sure you wish to restore the default NodeBB theme?",
|
||||
"theme-changed": "Theme Changed",
|
||||
"revert-success": "You have successfully reverted your NodeBB back to it's default theme.",
|
||||
"restart-to-activate": "Please restart your NodeBB to fully activate this theme"
|
||||
"checking-for-installed": "Kontrola nainštalovaných motívov...",
|
||||
"homepage": "Domovská stránka",
|
||||
"select-theme": "Vybrať motív",
|
||||
"current-theme": "Aktuálny motív",
|
||||
"no-themes": "Žiadne nainštalované motívy neboli nájdené",
|
||||
"revert-confirm": "Ste si istý, že chcete obnoviť predvolený NodeBB motív?",
|
||||
"theme-changed": "Motív zmenený",
|
||||
"revert-success": "Úspešne sa Vám podarilo obnoviť Váš NodeBB do predvoleného motívu.",
|
||||
"restart-to-activate": "Prosím, reštartujte Váš NodeBB pre úplne aktivovanie tohto motívu."
|
||||
}
|
@ -1,90 +1,95 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
define('sounds', ['buzz'], function (buzz) {
|
||||
define('sounds', function () {
|
||||
var Sounds = {};
|
||||
|
||||
var loadedSounds = {};
|
||||
var eventSoundMapping;
|
||||
var files;
|
||||
var fileMap;
|
||||
var soundMap;
|
||||
var cache = {};
|
||||
|
||||
socket.on('event:sounds.reloadMapping', function () {
|
||||
Sounds.reloadMapping();
|
||||
});
|
||||
|
||||
Sounds.reloadMapping = function () {
|
||||
socket.emit('modules.sounds.getMapping', function (err, mapping) {
|
||||
Sounds.loadMap = function loadMap(callback) {
|
||||
socket.emit('modules.sounds.getUserSoundMap', function (err, map) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
eventSoundMapping = mapping;
|
||||
soundMap = map;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function loadData(callback) {
|
||||
socket.emit('modules.sounds.getData', function (err, data) {
|
||||
if (err) {
|
||||
return app.alertError('[sounds] Could not load sound mapping!');
|
||||
}
|
||||
eventSoundMapping = data.mapping;
|
||||
files = data.files;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function isSoundLoaded(fileName) {
|
||||
return loadedSounds[fileName];
|
||||
}
|
||||
|
||||
function loadFile(fileName, callback) {
|
||||
function createSound() {
|
||||
if (files && files[fileName]) {
|
||||
loadedSounds[fileName] = new buzz.sound(files[fileName]);
|
||||
var outstanding = 2;
|
||||
function after() {
|
||||
outstanding -= 1;
|
||||
if (outstanding === 0 && callback) {
|
||||
callback();
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
if (isSoundLoaded(fileName)) {
|
||||
return callback();
|
||||
if (fileMap) {
|
||||
outstanding -= 1;
|
||||
} else {
|
||||
$.getJSON(config.relative_path + '/assets/sounds/fileMap.json', function (map) {
|
||||
fileMap = map;
|
||||
after();
|
||||
});
|
||||
}
|
||||
|
||||
if (!files || !files[fileName]) {
|
||||
return loadData(createSound);
|
||||
}
|
||||
createSound();
|
||||
Sounds.loadMap(after);
|
||||
}
|
||||
|
||||
Sounds.play = function (name) {
|
||||
function play() {
|
||||
Sounds.playFile(eventSoundMapping[name]);
|
||||
Sounds.playSound = function playSound(soundName) {
|
||||
if (!soundMap || !fileMap) {
|
||||
return loadData(after);
|
||||
}
|
||||
|
||||
if (!eventSoundMapping) {
|
||||
return loadData(play);
|
||||
function after() {
|
||||
if (!fileMap[soundName]) {
|
||||
return;
|
||||
}
|
||||
var audio = cache[soundName] || new Audio(config.relative_path + '/assets/sounds/' + fileMap[soundName]);
|
||||
cache[soundName] = audio;
|
||||
audio.pause();
|
||||
audio.currentTime = 0;
|
||||
audio.play();
|
||||
}
|
||||
|
||||
play();
|
||||
after();
|
||||
};
|
||||
|
||||
Sounds.playFile = function (fileName) {
|
||||
if (!fileName) {
|
||||
return;
|
||||
}
|
||||
Sounds.play = function play(type, id) {
|
||||
function after() {
|
||||
if (!soundMap[type]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (id) {
|
||||
var item = 'sounds.handled:' + id;
|
||||
if (sessionStorage.getItem(item)) {
|
||||
return;
|
||||
}
|
||||
sessionStorage.setItem(item, true);
|
||||
|
||||
function play() {
|
||||
if (loadedSounds[fileName]) {
|
||||
loadedSounds[fileName].play();
|
||||
} else {
|
||||
app.alertError('[sounds] Not found: ' + fileName);
|
||||
setTimeout(function () {
|
||||
sessionStorage.removeItem(item);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
Sounds.playSound(soundMap[type]);
|
||||
}
|
||||
|
||||
if (isSoundLoaded(fileName)) {
|
||||
play();
|
||||
} else {
|
||||
loadFile(fileName, play);
|
||||
if (!soundMap || !fileMap) {
|
||||
return loadData(after);
|
||||
}
|
||||
|
||||
after();
|
||||
};
|
||||
|
||||
socket.on('event:sounds.reloadMapping', function () {
|
||||
Sounds.loadMap();
|
||||
});
|
||||
|
||||
return Sounds;
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,109 +1,121 @@
|
||||
<div class="registration panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
[[admin/manage/registration:queue]]
|
||||
</div>
|
||||
<!-- IF !users.length -->
|
||||
<p class="panel-body">
|
||||
[[admin/manage/registration:description, {config.relative_path}/admin/settings/user]]
|
||||
</p>
|
||||
<!-- ENDIF !users.length -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped users-list">
|
||||
<tr>
|
||||
<th>[[admin/manage/registration:list.name]]</th>
|
||||
<th>[[admin/manage/registration:list.email]]</th>
|
||||
<th class="hidden-xs">[[admin/manage/registration:list.ip]]</th>
|
||||
<th class="hidden-xs">[[admin/manage/registration:list.time]]</th>
|
||||
<!-- BEGIN customHeaders -->
|
||||
<th class="hidden-xs">{customHeaders.label}</th>
|
||||
<!-- END customHeaders -->
|
||||
<th></th>
|
||||
</tr>
|
||||
<!-- BEGIN users -->
|
||||
<tr data-username="{users.username}">
|
||||
<td>
|
||||
<!-- IF users.usernameSpam -->
|
||||
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.username-spam, {users.spamData.username.frequency}, {users.spamData.username.appears}, {users.spamData.username.confidence}]]"></i>
|
||||
<!-- ELSE -->
|
||||
<i class="fa fa-check text-success"></i>
|
||||
<!-- ENDIF users.usernameSpam -->
|
||||
{users.username}
|
||||
</td>
|
||||
<td>
|
||||
<!-- IF users.emailSpam -->
|
||||
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.email-spam, {users.spamData.email.frequency}, {users.spamData.email.appears}]]"></i>
|
||||
<!-- ELSE -->
|
||||
<i class="fa fa-check text-success"></i>
|
||||
<!-- ENDIF users.emailSpam -->
|
||||
{users.email}
|
||||
</td>
|
||||
<td class="hidden-xs">
|
||||
<!-- IF users.ipSpam -->
|
||||
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.ip-spam, {users.spamData.ip.frequency}, {users.spamData.ip.appears}]]"></i>
|
||||
<!-- ELSE -->
|
||||
<i class="fa fa-check text-success"></i>
|
||||
<!-- ENDIF users.ipSpam -->
|
||||
{users.ip}
|
||||
<!-- BEGIN users.ipMatch -->
|
||||
<br>
|
||||
<!-- IF users.ipMatch.picture -->
|
||||
<img src="{users.ipMatch.picture}" class="user-img"/>
|
||||
<!-- ELSE -->
|
||||
<div class="user-img avatar avatar-sm" style="background-color: {users.ipMatch.icon:bgColor};">{users.ipMatch.icon:text}</div>
|
||||
<!-- ENDIF users.ipMatch.picture -->
|
||||
<a href="/uid/{users.ipMatch.uid}">{users.ipMatch.username}</a>
|
||||
<!-- END users.ipMatch -->
|
||||
</td>
|
||||
<td class="hidden-xs">
|
||||
<span class="timeago" title="{users.timestampISO}"></span>
|
||||
</td>
|
||||
|
||||
<!-- BEGIN users.customRows -->
|
||||
<td class="hidden-xs">{users.customRows.value}</td>
|
||||
<!-- END users.customRows -->
|
||||
|
||||
<td>
|
||||
<div class="btn-group pull-right">
|
||||
<button class="btn btn-success btn-xs" data-action="accept"><i class="fa fa-check"></i></button>
|
||||
<button class="btn btn-danger btn-xs" data-action="delete"><i class="fa fa-times"></i></button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- END users -->
|
||||
</table>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="registration panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
[[admin/manage/registration:queue]]
|
||||
</div>
|
||||
<!-- IF !users.length -->
|
||||
<p class="panel-body">
|
||||
[[admin/manage/registration:description, {config.relative_path}/admin/settings/user]]
|
||||
</p>
|
||||
<!-- ENDIF !users.length -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped users-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>[[admin/manage/registration:list.name]]</th>
|
||||
<th>[[admin/manage/registration:list.email]]</th>
|
||||
<th class="hidden-xs">[[admin/manage/registration:list.ip]]</th>
|
||||
<th class="hidden-xs">[[admin/manage/registration:list.time]]</th>
|
||||
<!-- BEGIN customHeaders -->
|
||||
<th class="hidden-xs">{customHeaders.label}</th>
|
||||
<!-- END customHeaders -->
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- BEGIN users -->
|
||||
<tr data-username="{users.username}">
|
||||
<td>
|
||||
<!-- IF users.usernameSpam -->
|
||||
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.username-spam, {users.spamData.username.frequency}, {users.spamData.username.appears}, {users.spamData.username.confidence}]]"></i>
|
||||
<!-- ELSE -->
|
||||
<i class="fa fa-check text-success"></i>
|
||||
<!-- ENDIF users.usernameSpam -->
|
||||
{users.username}
|
||||
</td>
|
||||
<td>
|
||||
<!-- IF users.emailSpam -->
|
||||
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.email-spam, {users.spamData.email.frequency}, {users.spamData.email.appears}]]"></i>
|
||||
<!-- ELSE -->
|
||||
<i class="fa fa-check text-success"></i>
|
||||
<!-- ENDIF users.emailSpam -->
|
||||
{users.email}
|
||||
</td>
|
||||
<td class="hidden-xs">
|
||||
<!-- IF users.ipSpam -->
|
||||
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.ip-spam, {users.spamData.ip.frequency}, {users.spamData.ip.appears}]]"></i>
|
||||
<!-- ELSE -->
|
||||
<i class="fa fa-check text-success"></i>
|
||||
<!-- ENDIF users.ipSpam -->
|
||||
{users.ip}
|
||||
<!-- BEGIN users.ipMatch -->
|
||||
<br>
|
||||
<!-- IF users.ipMatch.picture -->
|
||||
<img src="{users.ipMatch.picture}" class="user-img"/>
|
||||
<!-- ELSE -->
|
||||
<div class="user-img avatar avatar-sm" style="background-color: {users.ipMatch.icon:bgColor};">{users.ipMatch.icon:text}</div>
|
||||
<!-- ENDIF users.ipMatch.picture -->
|
||||
<a href="/uid/{users.ipMatch.uid}">{users.ipMatch.username}</a>
|
||||
<!-- END users.ipMatch -->
|
||||
</td>
|
||||
<td class="hidden-xs">
|
||||
<span class="timeago" title="{users.timestampISO}"></span>
|
||||
</td>
|
||||
|
||||
<!-- IMPORT partials/paginator.tpl -->
|
||||
</div>
|
||||
<!-- BEGIN users.customRows -->
|
||||
<td class="hidden-xs">{users.customRows.value}</td>
|
||||
<!-- END users.customRows -->
|
||||
|
||||
<div class="invitations panel panel-success">
|
||||
<div class="panel-heading">
|
||||
[[admin/manage/registration:invitations]]
|
||||
</div>
|
||||
<p class="panel-body">
|
||||
[[admin/manage/registration:invitations.description]]
|
||||
</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped invites-list">
|
||||
<tr>
|
||||
<th>[[admin/manage/registration:invitations.inviter-username]]</th>
|
||||
<th>[[admin/manage/registration:invitations.invitee-email]]</th>
|
||||
<th>[[admin/manage/registration:invitations.invitee-username]]</th>
|
||||
</tr>
|
||||
<!-- BEGIN invites -->
|
||||
<!-- BEGIN invites.invitations -->
|
||||
<tr data-invitation-mail="{invites.invitations.email}"
|
||||
data-invited-by="{invites.username}">
|
||||
<td class ="invited-by"><!-- IF @first -->{invites.username}<!-- ENDIF @first --></td>
|
||||
<td>{invites.invitations.email}</td>
|
||||
<td>{invites.invitations.username}
|
||||
<div class="btn-group pull-right">
|
||||
<button class="btn btn-danger btn-xs" data-action="delete"><i class="fa fa-times"></i></button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- END invites.invitations -->
|
||||
<!-- END invites -->
|
||||
</table>
|
||||
<td>
|
||||
<div class="btn-group pull-right">
|
||||
<button class="btn btn-success btn-xs" data-action="accept"><i class="fa fa-check"></i></button>
|
||||
<button class="btn btn-danger btn-xs" data-action="delete"><i class="fa fa-times"></i></button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- END users -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- IMPORT partials/paginator.tpl -->
|
||||
</div>
|
||||
|
||||
<div class="invitations panel panel-success">
|
||||
<div class="panel-heading">
|
||||
[[admin/manage/registration:invitations]]
|
||||
</div>
|
||||
<p class="panel-body">
|
||||
[[admin/manage/registration:invitations.description]]
|
||||
</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped invites-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>[[admin/manage/registration:invitations.inviter-username]]</th>
|
||||
<th>[[admin/manage/registration:invitations.invitee-email]]</th>
|
||||
<th>[[admin/manage/registration:invitations.invitee-username]]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- BEGIN invites -->
|
||||
<!-- BEGIN invites.invitations -->
|
||||
<tr data-invitation-mail="{invites.invitations.email}"
|
||||
data-invited-by="{invites.username}">
|
||||
<td class ="invited-by"><!-- IF @first -->{invites.username}<!-- ENDIF @first --></td>
|
||||
<td>{invites.invitations.email}</td>
|
||||
<td>{invites.invitations.username}
|
||||
<div class="btn-group pull-right">
|
||||
<button class="btn btn-danger btn-xs" data-action="delete"><i class="fa fa-times"></i></button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- END invites.invitations -->
|
||||
<!-- END invites -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,37 @@
|
||||
<div class="input-group">
|
||||
<input class="form-control" type="text" component="groups/members/search" placeholder="[[global:search]]"/>
|
||||
<span class="input-group-addon search-button"><i class="fa fa-search"></i></span>
|
||||
</div><br />
|
||||
|
||||
<table component="groups/members" class="table table-striped table-hover" data-nextstart="{group.membersNextStart}">
|
||||
<tbody>
|
||||
<!-- BEGIN members -->
|
||||
<tr data-uid="{group.members.uid}">
|
||||
<td>
|
||||
<a href="{config.relative_path}/user/{group.members.userslug}">
|
||||
<!-- IF group.members.picture -->
|
||||
<img class="avatar avatar-sm" src="{group.members.picture}" />
|
||||
<!-- ELSE -->
|
||||
<div class="avatar avatar-sm" style="background-color: {group.members.icon:bgColor};">{group.members.icon:text}</div>
|
||||
<!-- ENDIF group.members.picture -->
|
||||
</a>
|
||||
</td>
|
||||
<td class="member-name">
|
||||
<a href="{config.relative_path}/user/{group.members.userslug}">{group.members.username}</a> <i title="[[groups:owner]]" class="fa fa-star text-warning <!-- IF !group.members.isOwner -->invisible<!-- ENDIF !group.members.isOwner -->"></i>
|
||||
|
||||
<!-- IF group.isOwner -->
|
||||
<div class="owner-controls btn-group pull-right">
|
||||
<a class="btn btn-sm" href="#" data-ajaxify="false" data-action="toggleOwnership" title="[[groups:details.grant]]">
|
||||
<i class="fa fa-star"></i>
|
||||
</a>
|
||||
|
||||
<a class="btn btn-sm" href="#" data-ajaxify="false" data-action="kick" title="[[groups:details.kick]]">
|
||||
<i class="fa fa-ban"></i>
|
||||
</a>
|
||||
</div>
|
||||
<!-- ENDIF group.isOwner -->
|
||||
</td>
|
||||
</tr>
|
||||
<!-- END members -->
|
||||
</tbody>
|
||||
</table>
|
@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
/* global require, after, before*/
|
||||
|
||||
|
||||
var async = require('async');
|
||||
var assert = require('assert');
|
||||
|
||||
var db = require('./mocks/databasemock');
|
||||
var groups = require('../src/groups');
|
||||
var user = require('../src/user');
|
||||
var blacklist = require('../src/meta/blacklist');
|
||||
|
||||
describe('blacklist', function () {
|
||||
var adminUid;
|
||||
|
||||
before(function (done) {
|
||||
groups.resetCache();
|
||||
user.create({ username: 'admin' }, function (err, uid) {
|
||||
assert.ifError(err);
|
||||
adminUid = uid;
|
||||
groups.join('administrators', adminUid, done);
|
||||
});
|
||||
});
|
||||
|
||||
var socketBlacklist = require('../src/socket.io/blacklist');
|
||||
var rules = '1.1.1.1\n2.2.2.2\n::ffff:0:2.2.2.2\n127.0.0.1\n192.168.100.0/22';
|
||||
|
||||
it('should validate blacklist', function (done) {
|
||||
socketBlacklist.validate({ uid: adminUid }, {
|
||||
rules: rules,
|
||||
}, function (err, data) {
|
||||
assert.ifError(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if not admin', function (done) {
|
||||
socketBlacklist.save({ uid: 0 }, rules, function (err) {
|
||||
assert.equal(err.message, '[[error:no-privileges]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should save blacklist', function (done) {
|
||||
socketBlacklist.save({ uid: adminUid }, rules, function (err) {
|
||||
assert.ifError(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass ip test against blacklist async', function (done) {
|
||||
blacklist.test('3.3.3.3', function (err) {
|
||||
assert.ifError(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass ip test against blacklist sync', function (done) {
|
||||
assert(!blacklist.test('3.3.3.3'));
|
||||
done();
|
||||
});
|
||||
|
||||
it('should fail ip test against blacklist async', function (done) {
|
||||
blacklist.test('1.1.1.1', function (err) {
|
||||
assert.equal(err.message, '[[error:blacklisted-ip]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail ip test against blacklist sync', function (done) {
|
||||
assert(blacklist.test('1.1.1.1'));
|
||||
done();
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
db.emptydb(done);
|
||||
});
|
||||
});
|
@ -0,0 +1,177 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Excessive Load Warning</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Ubuntu:400,500,700' rel='stylesheet' type='text/css'>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: #00A9EA;
|
||||
color: white;
|
||||
font-family: 'Ubuntu', sans-serif;
|
||||
text-align: center;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
-moz-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 250px;
|
||||
color: #fff;
|
||||
opacity: 0.5;
|
||||
margin: 10px;
|
||||
cursor: pointer;
|
||||
-moz-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
p strong {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
h1 {
|
||||
font-size: 125px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
p strong {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
position: relative;
|
||||
top: 50%;
|
||||
-webkit-transform: translateY(50%);
|
||||
-ms-transform: translateY(50%);
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
@-webkit-keyframes bounce {
|
||||
0%, 20%, 53%, 80%, 100% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
}
|
||||
|
||||
40%, 43% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
-webkit-transform: translate3d(0, -30px, 0);
|
||||
transform: translate3d(0, -30px, 0);
|
||||
}
|
||||
|
||||
70% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
-webkit-transform: translate3d(0, -15px, 0);
|
||||
transform: translate3d(0, -15px, 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
-webkit-transform: translate3d(0,-4px,0);
|
||||
transform: translate3d(0,-4px,0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%, 20%, 53%, 80%, 100% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
transform: translate3d(0,0,0);
|
||||
}
|
||||
|
||||
40%, 43% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
-webkit-transform: translate3d(0, -30px, 0);
|
||||
transform: translate3d(0, -30px, 0);
|
||||
}
|
||||
|
||||
70% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
-webkit-transform: translate3d(0, -15px, 0);
|
||||
transform: translate3d(0, -15px, 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
-webkit-transform: translate3d(0,-4px,0);
|
||||
transform: translate3d(0,-4px,0);
|
||||
}
|
||||
}
|
||||
|
||||
.bounce {
|
||||
-webkit-animation-name: bounce;
|
||||
animation-name: bounce;
|
||||
-webkit-transform-origin: center bottom;
|
||||
-ms-transform-origin: center bottom;
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
|
||||
.animated {
|
||||
-webkit-animation-duration: 1s;
|
||||
animation-duration: 1s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.animated.infinite {
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.animated.hinge {
|
||||
-webkit-animation-duration: 2s;
|
||||
animation-duration: 2s;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
window.onload = function() {
|
||||
var count = 0,
|
||||
bounce = document.getElementById('click-me');
|
||||
bounce.onclick = function() {
|
||||
count++;
|
||||
bounce.className = '';
|
||||
setTimeout(function() {
|
||||
bounce.className = 'animated bounce';
|
||||
}, 50);
|
||||
|
||||
if (count > 5) {
|
||||
document.getElementById('hide').className = '';
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<div class="center">
|
||||
<h1 id="click-me" class="animated bounce">503</h1>
|
||||
<p>
|
||||
<strong>This forum is temporarily unavailable due to excessive load.</strong>
|
||||
</p>
|
||||
<p>
|
||||
We shouldn't be down for long. Please check back shortly. Sorry for the inconvenience!
|
||||
</p>
|
||||
<p>
|
||||
<small id="hide" class="hide">Alright. You can stop clicking... it's not going to make the site come back sooner!</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.0 KiB |
Loading…
Reference in New Issue