Merge branch 'master' of https://github.com/NodeBB/NodeBB
commit
a2847dc851
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"loading": "Načítání motivů…",
|
"loading": "Načítání motivů…",
|
||||||
"homepage": "Homepage",
|
"homepage": "Domovská stránka",
|
||||||
"select-skin": "Select Skin",
|
"select-skin": "Vyber motiv",
|
||||||
"current-skin": "Current Skin",
|
"current-skin": "Současný motiv",
|
||||||
"skin-updated": "Skin Updated",
|
"skin-updated": "Motiv aktualizován",
|
||||||
"applied-success": "%1 skin was succesfully applied",
|
"applied-success": "%1 skin was succesfully applied",
|
||||||
"revert-success": "Skin reverted to base colours"
|
"revert-success": "Skin reverted to base colours"
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"post-cache": "Кэш записи",
|
"post-cache": "Кэш записи",
|
||||||
"posts-in-cache": "Записей в кэше",
|
"posts-in-cache": "Записей в кэше",
|
||||||
"average-post-size": "Average Post Size",
|
"average-post-size": "Средний размер записи",
|
||||||
"length-to-max": "Length / Max",
|
"length-to-max": "Длина / Максимальная",
|
||||||
"percent-full": "%1% Full",
|
"percent-full": "%1% Full",
|
||||||
"post-cache-size": "Post Cache Size",
|
"post-cache-size": "Размер записи в кэше",
|
||||||
"items-in-cache": "Items in Cache",
|
"items-in-cache": "Items in Cache",
|
||||||
"control-panel": "Control Panel",
|
"control-panel": "Панель управления",
|
||||||
"update-settings": "Update Cache Settings"
|
"update-settings": "Обновить настройки кэша"
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"figure-x": "Znázorniť %1",
|
"figure-x": "Znázorniť %1",
|
||||||
"error-events-per-day": "<code>%1</code> events per day",
|
"error-events-per-day": "<code>%1</code> events per day",
|
||||||
"error.404": "404 Not Found",
|
"error.404": "404 Nenájdené",
|
||||||
"error.503": "503 Service Unavailable",
|
"error.503": "503 Služba nie je k dispozícií",
|
||||||
"manage-error-log": "Manage Error Log",
|
"manage-error-log": "Manage Error Log",
|
||||||
"export-error-log": "Export Error Log (CSV)",
|
"export-error-log": "Export Error Log (CSV)",
|
||||||
"clear-error-log": "Clear Error Log",
|
"clear-error-log": "Clear Error Log",
|
||||||
"route": "Route",
|
"route": "Route",
|
||||||
"count": "Count",
|
"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-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",
|
"events": "Udalosti",
|
||||||
"no-events": "There are no events",
|
"no-events": "Zatiaľ neexistujô žiadne udalosti",
|
||||||
"control-panel": "Events Control Panel",
|
"control-panel": "Ovládací panel udalostí",
|
||||||
"delete-events": "Delete Events"
|
"delete-events": "Odstrániť udalosť"
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"logs": "Protokoly",
|
"logs": "Záznamy",
|
||||||
"control-panel": "Logs Control Panel",
|
"control-panel": "Ovládací panel záznamov",
|
||||||
"reload": "Reload Logs",
|
"reload": "Znovu načítať záznamy",
|
||||||
"clear": "Clear Logs",
|
"clear": "Vyčistiť záznamy",
|
||||||
"clear-success": "Logs Cleared!"
|
"clear-success": "Záznamy vyčistené!"
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"loading": "Loading Skins...",
|
"loading": "Načítať vzhľady...",
|
||||||
"homepage": "Homepage",
|
"homepage": "Domovska stránka",
|
||||||
"select-skin": "Select Skin",
|
"select-skin": "Vybrať vzhľad",
|
||||||
"current-skin": "Current Skin",
|
"current-skin": "Aktuálny vzhľad",
|
||||||
"skin-updated": "Skin Updated",
|
"skin-updated": "Vzhľad aktualizovaný",
|
||||||
"applied-success": "%1 skin was succesfully applied",
|
"applied-success": "%1 vzhľad bol úspešne aplikovaný",
|
||||||
"revert-success": "Skin reverted to base colours"
|
"revert-success": "Vzhľad bol obnovený do základných farieb"
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"checking-for-installed": "Checking for installed themes...",
|
"checking-for-installed": "Kontrola nainštalovaných motívov...",
|
||||||
"homepage": "Homepage",
|
"homepage": "Domovská stránka",
|
||||||
"select-theme": "Select Theme",
|
"select-theme": "Vybrať motív",
|
||||||
"current-theme": "Current Theme",
|
"current-theme": "Aktuálny motív",
|
||||||
"no-themes": "No installed themes found",
|
"no-themes": "Žiadne nainštalované motívy neboli nájdené",
|
||||||
"revert-confirm": "Are you sure you wish to restore the default NodeBB theme?",
|
"revert-confirm": "Ste si istý, že chcete obnoviť predvolený NodeBB motív?",
|
||||||
"theme-changed": "Theme Changed",
|
"theme-changed": "Motív zmenený",
|
||||||
"revert-success": "You have successfully reverted your NodeBB back to it's default theme.",
|
"revert-success": "Úspešne sa Vám podarilo obnoviť Váš NodeBB do predvoleného motívu.",
|
||||||
"restart-to-activate": "Please restart your NodeBB to fully activate this theme"
|
"restart-to-activate": "Prosím, reštartujte Váš NodeBB pre úplne aktivovanie tohto motívu."
|
||||||
}
|
}
|
@ -1,90 +1,94 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
/* global app, define, socket, config */
|
/* global app, define, socket, config */
|
||||||
|
|
||||||
define('sounds', ['buzz'], function (buzz) {
|
define('sounds', function () {
|
||||||
var Sounds = {};
|
var Sounds = {};
|
||||||
|
|
||||||
var loadedSounds = {};
|
var fileMap;
|
||||||
var eventSoundMapping;
|
var soundMap;
|
||||||
var files;
|
var cache = {};
|
||||||
|
|
||||||
socket.on('event:sounds.reloadMapping', function () {
|
Sounds.loadMap = function loadMap(callback) {
|
||||||
Sounds.reloadMapping();
|
socket.emit('modules.sounds.getUserSoundMap', function (err, map) {
|
||||||
});
|
|
||||||
|
|
||||||
Sounds.reloadMapping = function () {
|
|
||||||
socket.emit('modules.sounds.getMapping', function (err, mapping) {
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return app.alertError(err.message);
|
return app.alertError(err.message);
|
||||||
}
|
}
|
||||||
eventSoundMapping = mapping;
|
soundMap = map;
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function loadData(callback) {
|
function loadData(callback) {
|
||||||
socket.emit('modules.sounds.getData', function (err, data) {
|
var outstanding = 2;
|
||||||
if (err) {
|
function after() {
|
||||||
return app.alertError('[sounds] Could not load sound mapping!');
|
outstanding -= 1;
|
||||||
}
|
if (outstanding === 0 && callback) {
|
||||||
eventSoundMapping = data.mapping;
|
callback();
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
|
if (fileMap) {
|
||||||
if (isSoundLoaded(fileName)) {
|
outstanding -= 1;
|
||||||
return callback();
|
} else {
|
||||||
|
$.getJSON(config.relative_path + '/assets/sounds/fileMap.json', function (map) {
|
||||||
|
fileMap = map;
|
||||||
|
after();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!files || !files[fileName]) {
|
Sounds.loadMap(after);
|
||||||
return loadData(createSound);
|
|
||||||
}
|
|
||||||
createSound();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sounds.play = function (name) {
|
Sounds.playSound = function playSound(soundName) {
|
||||||
function play() {
|
if (!soundMap || !fileMap) {
|
||||||
Sounds.playFile(eventSoundMapping[name]);
|
return loadData(after);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eventSoundMapping) {
|
function after() {
|
||||||
return loadData(play);
|
if (!fileMap[soundName]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var audio = cache[soundName] = cache[soundName] || new Audio(config.relative_path + '/assets/sounds/' + fileMap[soundName]);
|
||||||
|
audio.pause();
|
||||||
|
audio.currentTime = 0;
|
||||||
|
audio.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
play();
|
after();
|
||||||
};
|
};
|
||||||
|
|
||||||
Sounds.playFile = function (fileName) {
|
Sounds.play = function play(type, id) {
|
||||||
if (!fileName) {
|
function after() {
|
||||||
return;
|
if (!soundMap[type]) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
var item = 'sounds.handled:' + id;
|
||||||
|
if (sessionStorage.getItem(item)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sessionStorage.setItem(item, true);
|
||||||
|
|
||||||
function play() {
|
setTimeout(function () {
|
||||||
if (loadedSounds[fileName]) {
|
sessionStorage.removeItem(item);
|
||||||
loadedSounds[fileName].play();
|
}, 5000);
|
||||||
} else {
|
|
||||||
app.alertError('[sounds] Not found: ' + fileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sounds.playSound(soundMap[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSoundLoaded(fileName)) {
|
if (!soundMap || !fileMap) {
|
||||||
play();
|
return loadData(after);
|
||||||
} else {
|
|
||||||
loadFile(fileName, play);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
after();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
socket.on('event:sounds.reloadMapping', function () {
|
||||||
|
Sounds.loadMap();
|
||||||
|
});
|
||||||
|
|
||||||
return Sounds;
|
return Sounds;
|
||||||
});
|
});
|
||||||
|
@ -1,24 +1,46 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var meta = require('../../meta');
|
var plugins = require('../../plugins');
|
||||||
|
var db = require('../../database');
|
||||||
|
|
||||||
var soundsController = {};
|
var soundsController = {};
|
||||||
|
|
||||||
soundsController.get = function (req, res, next) {
|
soundsController.get = function (req, res, next) {
|
||||||
meta.sounds.getFiles(function (err, sounds) {
|
db.getObject('settings:sounds', function (err, settings) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
sounds = Object.keys(sounds).map(function (name) {
|
settings = settings || {};
|
||||||
return {
|
|
||||||
name: name
|
var types = [
|
||||||
};
|
'notification',
|
||||||
});
|
'chat-incoming',
|
||||||
|
'chat-outgoing',
|
||||||
|
];
|
||||||
|
var output = {};
|
||||||
|
|
||||||
|
types.forEach(function (type) {
|
||||||
|
var soundpacks = plugins.soundpacks.map(function (pack) {
|
||||||
|
var sounds = Object.keys(pack.sounds).map(function (soundName) {
|
||||||
|
var value = pack.name + ' | ' + soundName;
|
||||||
|
return {
|
||||||
|
name: soundName,
|
||||||
|
value: value,
|
||||||
|
selected: value === settings[type],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
res.render('admin/general/sounds', {
|
return {
|
||||||
sounds: sounds
|
name: pack.name,
|
||||||
|
sounds: sounds,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
output[type + '-sound'] = soundpacks;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
res.render('admin/general/sounds', output);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,109 +1,121 @@
|
|||||||
<div class="registration panel panel-primary">
|
<div class="row">
|
||||||
<div class="panel-heading">
|
<div class="col-xs-12">
|
||||||
[[admin/manage/registration:queue]]
|
<div class="registration panel panel-primary">
|
||||||
</div>
|
<div class="panel-heading">
|
||||||
<!-- IF !users.length -->
|
[[admin/manage/registration:queue]]
|
||||||
<p class="panel-body">
|
</div>
|
||||||
[[admin/manage/registration:description, {config.relative_path}/admin/settings/user]]
|
<!-- IF !users.length -->
|
||||||
</p>
|
<p class="panel-body">
|
||||||
<!-- ENDIF !users.length -->
|
[[admin/manage/registration:description, {config.relative_path}/admin/settings/user]]
|
||||||
<div class="table-responsive">
|
</p>
|
||||||
<table class="table table-striped users-list">
|
<!-- ENDIF !users.length -->
|
||||||
<tr>
|
<div class="table-responsive">
|
||||||
<th>[[admin/manage/registration:list.name]]</th>
|
<table class="table table-striped users-list">
|
||||||
<th>[[admin/manage/registration:list.email]]</th>
|
<thead>
|
||||||
<th class="hidden-xs">[[admin/manage/registration:list.ip]]</th>
|
<tr>
|
||||||
<th class="hidden-xs">[[admin/manage/registration:list.time]]</th>
|
<th>[[admin/manage/registration:list.name]]</th>
|
||||||
<!-- BEGIN customHeaders -->
|
<th>[[admin/manage/registration:list.email]]</th>
|
||||||
<th class="hidden-xs">{customHeaders.label}</th>
|
<th class="hidden-xs">[[admin/manage/registration:list.ip]]</th>
|
||||||
<!-- END customHeaders -->
|
<th class="hidden-xs">[[admin/manage/registration:list.time]]</th>
|
||||||
<th></th>
|
<!-- BEGIN customHeaders -->
|
||||||
</tr>
|
<th class="hidden-xs">{customHeaders.label}</th>
|
||||||
<!-- BEGIN users -->
|
<!-- END customHeaders -->
|
||||||
<tr data-username="{users.username}">
|
<th></th>
|
||||||
<td>
|
</tr>
|
||||||
<!-- IF users.usernameSpam -->
|
</thead>
|
||||||
<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>
|
<tbody>
|
||||||
<!-- ELSE -->
|
<!-- BEGIN users -->
|
||||||
<i class="fa fa-check text-success"></i>
|
<tr data-username="{users.username}">
|
||||||
<!-- ENDIF users.usernameSpam -->
|
<td>
|
||||||
{users.username}
|
<!-- IF users.usernameSpam -->
|
||||||
</td>
|
<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>
|
||||||
<td>
|
<!-- ELSE -->
|
||||||
<!-- IF users.emailSpam -->
|
<i class="fa fa-check text-success"></i>
|
||||||
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.email-spam, {users.spamData.email.frequency}, {users.spamData.email.appears}]]"></i>
|
<!-- ENDIF users.usernameSpam -->
|
||||||
<!-- ELSE -->
|
{users.username}
|
||||||
<i class="fa fa-check text-success"></i>
|
</td>
|
||||||
<!-- ENDIF users.emailSpam -->
|
<td>
|
||||||
{users.email}
|
<!-- IF users.emailSpam -->
|
||||||
</td>
|
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.email-spam, {users.spamData.email.frequency}, {users.spamData.email.appears}]]"></i>
|
||||||
<td class="hidden-xs">
|
<!-- ELSE -->
|
||||||
<!-- IF users.ipSpam -->
|
<i class="fa fa-check text-success"></i>
|
||||||
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.ip-spam, {users.spamData.ip.frequency}, {users.spamData.ip.appears}]]"></i>
|
<!-- ENDIF users.emailSpam -->
|
||||||
<!-- ELSE -->
|
{users.email}
|
||||||
<i class="fa fa-check text-success"></i>
|
</td>
|
||||||
<!-- ENDIF users.ipSpam -->
|
<td class="hidden-xs">
|
||||||
{users.ip}
|
<!-- IF users.ipSpam -->
|
||||||
<!-- BEGIN users.ipMatch -->
|
<i class="fa fa-times-circle text-danger" title="[[admin/manage/registration:list.ip-spam, {users.spamData.ip.frequency}, {users.spamData.ip.appears}]]"></i>
|
||||||
<br>
|
<!-- ELSE -->
|
||||||
<!-- IF users.ipMatch.picture -->
|
<i class="fa fa-check text-success"></i>
|
||||||
<img src="{users.ipMatch.picture}" class="user-img"/>
|
<!-- ENDIF users.ipSpam -->
|
||||||
<!-- ELSE -->
|
{users.ip}
|
||||||
<div class="user-img avatar avatar-sm" style="background-color: {users.ipMatch.icon:bgColor};">{users.ipMatch.icon:text}</div>
|
<!-- BEGIN users.ipMatch -->
|
||||||
<!-- ENDIF users.ipMatch.picture -->
|
<br>
|
||||||
<a href="/uid/{users.ipMatch.uid}">{users.ipMatch.username}</a>
|
<!-- IF users.ipMatch.picture -->
|
||||||
<!-- END users.ipMatch -->
|
<img src="{users.ipMatch.picture}" class="user-img"/>
|
||||||
</td>
|
<!-- ELSE -->
|
||||||
<td class="hidden-xs">
|
<div class="user-img avatar avatar-sm" style="background-color: {users.ipMatch.icon:bgColor};">{users.ipMatch.icon:text}</div>
|
||||||
<span class="timeago" title="{users.timestampISO}"></span>
|
<!-- ENDIF users.ipMatch.picture -->
|
||||||
</td>
|
<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 -->
|
<!-- BEGIN users.customRows -->
|
||||||
<td class="hidden-xs">{users.customRows.value}</td>
|
<td class="hidden-xs">{users.customRows.value}</td>
|
||||||
<!-- END users.customRows -->
|
<!-- END users.customRows -->
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-group pull-right">
|
<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-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>
|
<button class="btn btn-danger btn-xs" data-action="delete"><i class="fa fa-times"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- END users -->
|
<!-- END users -->
|
||||||
</table>
|
</tbody>
|
||||||
</div>
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- IMPORT partials/paginator.tpl -->
|
<!-- IMPORT partials/paginator.tpl -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="invitations panel panel-success">
|
<div class="invitations panel panel-success">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
[[admin/manage/registration:invitations]]
|
[[admin/manage/registration:invitations]]
|
||||||
</div>
|
</div>
|
||||||
<p class="panel-body">
|
<p class="panel-body">
|
||||||
[[admin/manage/registration:invitations.description]]
|
[[admin/manage/registration:invitations.description]]
|
||||||
</p>
|
</p>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-striped invites-list">
|
<table class="table table-striped invites-list">
|
||||||
<tr>
|
<thead>
|
||||||
<th>[[admin/manage/registration:invitations.inviter-username]]</th>
|
<tr>
|
||||||
<th>[[admin/manage/registration:invitations.invitee-email]]</th>
|
<th>[[admin/manage/registration:invitations.inviter-username]]</th>
|
||||||
<th>[[admin/manage/registration:invitations.invitee-username]]</th>
|
<th>[[admin/manage/registration:invitations.invitee-email]]</th>
|
||||||
</tr>
|
<th>[[admin/manage/registration:invitations.invitee-username]]</th>
|
||||||
<!-- BEGIN invites -->
|
</tr>
|
||||||
<!-- BEGIN invites.invitations -->
|
</thead>
|
||||||
<tr data-invitation-mail="{invites.invitations.email}"
|
<tbody>
|
||||||
data-invited-by="{invites.username}">
|
<!-- BEGIN invites -->
|
||||||
<td class ="invited-by"><!-- IF @first -->{invites.username}<!-- ENDIF @first --></td>
|
<!-- BEGIN invites.invitations -->
|
||||||
<td>{invites.invitations.email}</td>
|
<tr data-invitation-mail="{invites.invitations.email}"
|
||||||
<td>{invites.invitations.username}
|
data-invited-by="{invites.username}">
|
||||||
<div class="btn-group pull-right">
|
<td class ="invited-by"><!-- IF @first -->{invites.username}<!-- ENDIF @first --></td>
|
||||||
<button class="btn btn-danger btn-xs" data-action="delete"><i class="fa fa-times"></i></button>
|
<td>{invites.invitations.email}</td>
|
||||||
</div>
|
<td>{invites.invitations.username}
|
||||||
</td>
|
<div class="btn-group pull-right">
|
||||||
</tr>
|
<button class="btn btn-danger btn-xs" data-action="delete"><i class="fa fa-times"></i></button>
|
||||||
<!-- END invites.invitations -->
|
</div>
|
||||||
<!-- END invites -->
|
</td>
|
||||||
</table>
|
</tr>
|
||||||
|
<!-- END invites.invitations -->
|
||||||
|
<!-- END invites -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -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