mirror of
https://github.com/Synzvato/decentraleyes.git
synced 2026-01-05 21:58:38 -05:00
Compare commits
15 Commits
experiment
...
v1.3.10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7187a83e5 | ||
|
|
955d932b11 | ||
|
|
50a43bfc2e | ||
|
|
18df769998 | ||
|
|
27a60cdec7 | ||
|
|
694fa25a3a | ||
|
|
6c061b2235 | ||
|
|
bd2278fd32 | ||
|
|
a64d6f3f41 | ||
|
|
682570cdea | ||
|
|
19cb2beacf | ||
|
|
f5f3cc9be4 | ||
|
|
e73ad04845 | ||
|
|
2f8733bd0a | ||
|
|
0d868e072f |
@@ -1,7 +1,7 @@
|
||||
Decentraleyes
|
||||
=============
|
||||
|
||||
A [Firefox add-on](https://addons.mozilla.org/firefox/addon/decentraleyes) that emulates Content Delivery Networks (CDNs) locally by intercepting requests, finding the required resource and injecting it into the environment. This all happens instantaneously, automatically, and no prior configuration is required. Feel free to use this [testing utility](https://decentraleyes.org/test) to see if it's properly installed, enabled, and correctly configured.
|
||||
A [web browser extension](https://decentraleyes.org) that emulates Content Delivery Networks locally by intercepting requests, finding the required resource and injecting it into the environment. This all happens instantaneously, automatically, and no prior configuration is required. Feel free to use this [testing utility](https://decentraleyes.org/test) to see if it's properly installed, enabled, and correctly configured.
|
||||
|
||||
> **Note:** Decentraleyes is no silver bullet, but it does prevent a lot of websites from making you send these kinds of requests. Ultimately, you can make Decentraleyes block requests for any missing CDN resources, too.
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ var { Class } = require('sdk/core/heritage');
|
||||
var { Unknown } = require('sdk/platform/xpcom');
|
||||
var { Cc, Ci, Cr } = require('chrome');
|
||||
|
||||
var main = require('./main');
|
||||
|
||||
/**
|
||||
* Gets and sets add-on specific preferences.
|
||||
* @var {object} simplePreferences
|
||||
@@ -116,6 +118,7 @@ var Interceptor = new Class({
|
||||
|
||||
//noinspection JSUnresolvedVariable
|
||||
preferences.amountInjected++;
|
||||
main.broadcastInjection();
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
123
lib/main.js
123
lib/main.js
@@ -17,15 +17,23 @@
|
||||
* Imports
|
||||
*/
|
||||
|
||||
var Interceptor = require('./interceptor');
|
||||
var LoadWatcher = require('./load-watcher');
|
||||
var preferences = require('sdk/simple-prefs');
|
||||
var webextension = null;
|
||||
|
||||
var preferences = require('sdk/simple-prefs').prefs;
|
||||
var self = require('sdk/self');
|
||||
var tabs = require("sdk/tabs");
|
||||
|
||||
var Interceptor = require('./interceptor');
|
||||
var LoadWatcher = require('./load-watcher');
|
||||
|
||||
/**
|
||||
* Main
|
||||
* Variables
|
||||
*/
|
||||
|
||||
var webextensionPort = null;
|
||||
|
||||
/**
|
||||
* Initializations
|
||||
*/
|
||||
|
||||
var interceptor = new Interceptor();
|
||||
@@ -36,6 +44,10 @@ var featurelessVersions = {
|
||||
'1.3.7': true
|
||||
};
|
||||
|
||||
/**
|
||||
* Main
|
||||
*/
|
||||
|
||||
// Executed as soon as the add-on is loaded.
|
||||
exports.main = function (options) {
|
||||
|
||||
@@ -43,15 +55,75 @@ exports.main = function (options) {
|
||||
interceptor.register();
|
||||
loadWatcher.register();
|
||||
|
||||
if (preferences.showReleaseNotes) {
|
||||
// Display the release notes if desired.
|
||||
if (preferences.prefs.showReleaseNotes) {
|
||||
|
||||
if (options.loadReason === 'install' || (options.loadReason === 'upgrade' && !featurelessVersions[self.version])) {
|
||||
|
||||
if (preferences['sdk.baseURI']) {
|
||||
tabs.open(preferences['sdk.baseURI'] + 'static/release-notes.html');
|
||||
if (preferences.prefs['sdk.baseURI']) {
|
||||
tabs.open(preferences.prefs['sdk.baseURI'] + 'static/release-notes.html');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
webextension = require('sdk/webextension');
|
||||
} catch (exception) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the embedded WebExtension.
|
||||
webextension.startup().then(({ browser }) => {
|
||||
|
||||
browser.runtime.onConnect.addListener(port => {
|
||||
|
||||
if (port.name === 'webextension') {
|
||||
|
||||
webextensionPort = port;
|
||||
|
||||
preferences.on('', function (preferenceName) {
|
||||
|
||||
let content = null;
|
||||
|
||||
if (preferenceName === 'amountInjected') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preferenceName === 'domainWhitelist') {
|
||||
|
||||
let domainWhitelist = preferences.prefs['domainWhitelist'];
|
||||
|
||||
content = {
|
||||
'whitelistedDomains': _parseDomainWhitelist(domainWhitelist)
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
content = {
|
||||
[preferenceName]: preferences.prefs[preferenceName]
|
||||
};
|
||||
}
|
||||
|
||||
port.postMessage({
|
||||
'subject': 'update-preferences',
|
||||
'content': content
|
||||
});
|
||||
});
|
||||
|
||||
let domainWhitelist = preferences.prefs['domainWhitelist'];
|
||||
|
||||
port.postMessage({
|
||||
'subject': 'migrate-preferences',
|
||||
'content': {
|
||||
'amountInjected': preferences.prefs['amountInjected'],
|
||||
'blockMissing': preferences.prefs['blockMissing'],
|
||||
'whitelistedDomains': _parseDomainWhitelist(domainWhitelist),
|
||||
'showReleaseNotes': preferences.prefs['showReleaseNotes']
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Executed as soon as the add-on is unloaded.
|
||||
@@ -60,3 +132,40 @@ exports.onUnload = function () {
|
||||
// Clean up add-on state.
|
||||
interceptor.unregister();
|
||||
};
|
||||
|
||||
// Sends injection updates to the WebExtension.
|
||||
exports.broadcastInjection = function () {
|
||||
|
||||
if (webextensionPort !== null) {
|
||||
|
||||
webextensionPort.postMessage({
|
||||
'subject': 'register-injection'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Private Methods
|
||||
*/
|
||||
|
||||
function _parseDomainWhitelist(value) {
|
||||
|
||||
let whitelistedDomains = {};
|
||||
|
||||
value.split(';').forEach(function (domain) {
|
||||
whitelistedDomains[_normalizeDomain(domain)] = true;
|
||||
});
|
||||
|
||||
return whitelistedDomains;
|
||||
}
|
||||
|
||||
function _normalizeDomain(domain) {
|
||||
|
||||
domain = domain.toLowerCase().trim();
|
||||
|
||||
if (domain.startsWith('www.')) {
|
||||
domain = domain.slice(4);
|
||||
}
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
8
locale/el/options.dtd
Normal file
8
locale/el/options.dtd
Normal file
@@ -0,0 +1,8 @@
|
||||
<!ENTITY options.addNotice.title "Προσθήκη σχολίων σε τοπικά τοποθετημένα αρχεία">
|
||||
<!ENTITY options.addNotice.description "Πρόσθεση αυτόματης ειδοποίησης ανάκτησης εγγράφων ώστε να σηματοδοτηθεί τοπική παράδοση.">
|
||||
<!ENTITY options.blockMissing.title "Μπλοκ αιτήσεων για ανύπαρκτους πόρους">
|
||||
<!ENTITY options.blockMissing.description "Ακύρωση απομακρυσμένης αίτησης, αν ο απαιτούμενος πόρος δεν είναι τοπικά διαθέσιμος.">
|
||||
<!ENTITY options.domainWhitelist.title "Εξαίρεση διευθύνσεων από επιθεωρήσεις">
|
||||
<!ENTITY options.domainWhitelist.description "Εισαγωγή διευθύνσεων στις επιτρεπόμενες. Διαχωρίστε πολλαπλές καταχωρήσεις με ερωτηματικά (;).">
|
||||
<!ENTITY options.amountInjected.title "Μετρητής εμβόλιμων τοπικών πόρων">
|
||||
<!ENTITY options.amountInjected.description "Ποσοστό εμβόλιμων τοπικών πόρων Δικτύων Παροχής Περιεχομένου από την στιγμή της εγκατάστασης.">
|
||||
@@ -3,11 +3,12 @@
|
||||
"author": "Thomas Rientjes",
|
||||
"license": "MPL-2.0",
|
||||
"title": "Decentraleyes",
|
||||
"version": "1.3.7",
|
||||
"version": "1.3.10",
|
||||
"main": "lib/main.js",
|
||||
"homepage": "https://addons.mozilla.org/firefox/addon/decentraleyes",
|
||||
"name": "decentraleyes",
|
||||
"id": "jid1-BoFifL9Vbdl2zQ@jetpack",
|
||||
"hasEmbeddedWebExtension": true,
|
||||
"permissions": {
|
||||
"multiprocess": true
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>Decentraleyes - What's New?</title>
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">
|
||||
<meta charset="UTF-8">
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
@@ -111,13 +111,13 @@
|
||||
|
||||
<div class="container">
|
||||
|
||||
<h1>Decentraleyes <i>v1.3.7</i></h1>
|
||||
<h1>Decentraleyes <i>v1.3.10</i></h1>
|
||||
|
||||
<br><br>
|
||||
|
||||
<div class="notice">
|
||||
|
||||
<span class="subtle-hint"><span class="topic-label">Pro Tip:</span> Would you rather not see this page after installations or updates? You can disable it by navigating to <strong>about:config</strong> (in a new tab), then searching for <strong>BoFifL9V</strong>, and setting <strong>showReleaseNotes</strong> to false.</span>
|
||||
<span class="subtle-hint"><span class="topic-label">Important:</span> This update automatically migrates your existing settings over to the upcoming (completely rewritten) version of Decentraleyes. The next release will be <span class="help-panel" data-title="It will feature an optional graphical user interface.">less shy</span>, and fully ready for future versions of Firefox.</span>
|
||||
|
||||
<br><br><hr>
|
||||
|
||||
@@ -127,148 +127,15 @@
|
||||
|
||||
<div class="notice">
|
||||
|
||||
<span class="topic-label">New:</span> <strong>Multi-process support.</strong> The add-on now officially supports multi-process tabs. Compatibility was tested with the help of several <span class="help-panel" data-title="Thank you Andreas, Bisaloo, dralley, gitarra, OdinGitDat, and TriMoon.">volunteers</span>. The feature enhances security and performance.
|
||||
<span class="subtle-hint"><span class="topic-label">For Firefox Nightly Users:</span> You can start using a beta version of the upcoming release today. Please see <a href="https://github.com/Synzvato/decentraleyes/issues/173#issuecomment-322821857" target="_blank">this announcement</a> for more information on how to get started. Feel free to leave feedback!</span>
|
||||
|
||||
<br><br><hr>
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="notice">
|
||||
|
||||
<i>Release Notes for version 1.3.5:</i>
|
||||
|
||||
<br><br>
|
||||
|
||||
<span class="topic-label">New:</span> <strong>Additional languages.</strong> Languages <span class="subtle-text"><span class="help-panel" data-title="Thanks to Petercpg.">Chinese <i>(Traditional)</i></span>, <span class="help-panel" data-title="Thanks to Mikini.">Danish</span>, <span class="help-panel" data-title="Thanks to Spagy.">Esperanto</span>, <span class="help-panel" data-title="Thanks to Najoj.">Swedish</span>, and <span class="help-panel" data-title="Thanks to Msva.">Russian</span></span> were added to the list of fourteen initial translations. This brings the total to nineteen.
|
||||
|
||||
<br><br>
|
||||
|
||||
<span class="topic-label">Enhanced:</span> <strong>Improved CDN-mappings.</strong> The add-on now supports a greater amount of Google Hosted Libraries shorthand mappings. This effectively means that it's now able to detect even more injection opportunities, and can prevent an even higher amount of requests to this particular network.
|
||||
|
||||
<br><br><hr>
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="notice">
|
||||
|
||||
<i>Release Notes for version 1.3.0:</i>
|
||||
|
||||
<br><br>
|
||||
|
||||
<span class="topic-label">New:</span> <strong>Let there be languages.</strong> This version supports locales and features fourteen <a href="https://github.com/Synzvato/decentraleyes/issues/44" target="_blank">initial translations</a>: <span class="subtle-text"> <span class="help-panel" data-title="Thanks to AdmiralAnimE.">Bulgarian</span>, <span class="help-panel" data-title="Thanks to Louy2 and YFdyh000.">Chinese <i>(Simplified)</i></span>, Dutch, English <i>(United Kingdom)</i>, English <i>(United States)</i>, <span class="help-panel" data-title="Thanks to Semired.">Finnish</span>, <span class="help-panel" data-title="Thanks to Simpson, Thuban, and TraderStf."> French</span>, <span class="help-panel" data-title="Thanks to C4R2T3N, Flysch, Sabajo, and Schnaidar.">German</span>, <span class="help-panel" data-title="Thanks to Zmni.">Indonesian</span>, <span class="help-panel" data-title="Thanks to Mtvento.">Italian</span>, <span class="help-panel" data-title="Thanks to Brindflontia.">Japanese</span>, <span class="help-panel" data-title="Thanks to Marekjm.">Polish</span>, <span class="help-panel" data-title="Thanks to SW1FTmeister.">Portuguese <i>(European)</i></span>, and <span class="help-panel" data-title="Thanks to Adri and Ergotronix.">Spanish</span></span>.
|
||||
|
||||
<br><br>
|
||||
|
||||
<span class="topic-label">New:</span> <strong>Official support for SeaMonkey.</strong> If you use SeaMonkey <i>(a free and open-source internet suite consisting of a web browser, an e-mail client, and a news aggregator)</i>, you might be glad to know that this release is fully compatible with all modern versions of the application.
|
||||
|
||||
<br><br>
|
||||
|
||||
<span class="topic-label">Enhanced:</span> <strong>A large amount of internal changes for improved performance and stability.</strong> A lot of work has gone into making this version as fast and reliable as possible. As a result, this release proudly brings you an even more optimized, carefree, and stable overall experience.
|
||||
|
||||
<br><br><hr><br>
|
||||
|
||||
<span class="subtle-hint"><span class="topic-label">Getting started:</span> Decentraleyes works right out of the box and no manual configuration is required! You can check if you're properly protected by using the following <strong><a href="https://decentraleyes.org/test" target="_blank">testing utility</a></strong>.</span>
|
||||
|
||||
<br><br>
|
||||
|
||||
<span class="subtle-hint">To get a glimpse of what this add-on actually does for you, go to this application's main menu, click <strong>"Add-ons" > "Decentraleyes" > "Preferences"</strong>, scroll down, and familiarize yourself with the local injections counter.</span>
|
||||
|
||||
<br><br><hr>
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="notice">
|
||||
|
||||
<i>General notice:</i><br><br>
|
||||
|
||||
Decentraleyes is a young project. Expect many improvements in the realms of clear user feedback and ease-of-use as it matures. It does a lot to protect you, and is becoming less and less shy about it.
|
||||
|
||||
<br><br><hr>
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="notice">
|
||||
|
||||
<i>Detailed v1.3.7 changelog:</i>
|
||||
|
||||
<ul>
|
||||
<li>Fixed issues with localized variants of various Yandex services.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="notice">
|
||||
|
||||
<i>Detailed v1.3.6 changelog:</i>
|
||||
|
||||
<ul>
|
||||
<li>Added support for multi-process tabs, to improve security and overall performance.</li>
|
||||
<li>Added new jQuery (v1.12.x) scripts to the resource bundle.</li>
|
||||
<li>Fixed a <span class="help-panel" data-title="Reported by Rob--W."><a href="https://github.com/mozilla/addons-linter/issues/1035#issuecomment-258800562" target="_blank">security issue</a></span> that caused CSPs to be less effective against XSS.</li>
|
||||
<li>Fixed additional compatibility issues with various Yandex services.</li>
|
||||
<li>Fixed a <span class="help-panel" data-title="Reported by fireflyy.">grammatical error</span> in the German localization.</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="notice">
|
||||
|
||||
<i>Detailed v1.3.5 changelog:</i>
|
||||
|
||||
<ul>
|
||||
<li>Added support for the languages Danish, Esperanto, Swedish, and Russian.</li>
|
||||
<li>Created additional shorthand mappings to uncover new injection opportunities.</li>
|
||||
<li>Applied a security update to the embedded local resource audit script.</li>
|
||||
<li>Fixed reported compatibility issues with various Yandex services.</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
||||
<i>Detailed v1.3.0 changelog:</i>
|
||||
|
||||
<ul>
|
||||
<li>Decentraleyes now officially supports modern versions of SeaMonkey.</li>
|
||||
<li>Created mappings for yastatic.net and deprecated its predecessor (yandex.st).</li>
|
||||
<li>Added test cases, and <span class="help-panel" data-title="With code contributions by Ngksternhagen.">improved existing unit tests</span> and exception handling.</li>
|
||||
<li>Applied a wide range of performance optimizations and stability improvements.</li>
|
||||
<li>Added support for localizations and embedded fourteen initial translations.</li>
|
||||
<li>Implemented a watcher that keeps pages with specific security policies from breaking.</li>
|
||||
<li><span class="help-panel" data-title="With code contributions by Thegoodthings.">Added a preference</span> to allow users to hide release notes upon install and upgrade.</li>
|
||||
<li>Optimized mapping expressions to reveal uncommon injection opportunities.</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
||||
<i>Detailed v1.2.2 changelog:</i>
|
||||
|
||||
<ul>
|
||||
<li>Decentraleyes now supports Fennec (better known as Firefox for mobile).</li>
|
||||
<li>Experimental support for whitelisting domains from preferences (Add-ons Manager).</li>
|
||||
<li>Amount of injected resources shown in preferences (Add-ons Manager).</li>
|
||||
<li>Fixed a rare bug where shorthand mapping notations broke specific websites.</li>
|
||||
<li>Removed Pale Moon compatibility as it will receive separate, tailored, builds.</li>
|
||||
<li>Took out rare resources to make room for more common candidates.</li>
|
||||
<li>Added new AngularJS, Dojo, and <span class="help-panel" data-title="With code contributions by Matthieuy.">jQuery UI</span> scripts to the resource bundle.</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="notice">
|
||||
<p>
|
||||
<a href="https://github.com/Synzvato/decentraleyes" target="_blank">GitHub</a> / <a href="https://addons.mozilla.org/en-US/firefox/addon/decentraleyes" target="_blank">Add-on Listing</a> / <a href="https://github.com/Synzvato/decentraleyes/issues/44" target="_blank">Help Translate</a>
|
||||
<a href="https://github.com/Synzvato/decentraleyes" target="_blank">GitHub</a> / <a href="https://decentraleyes.org" target="_blank">Official Website</a> / <a href="https://github.com/Synzvato/decentraleyes/issues/44" target="_blank">Help Translate</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
90
webextension/background.js
Normal file
90
webextension/background.js
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Embedded WebExtension - Background Script
|
||||
* Belongs to Decentraleyes.
|
||||
*
|
||||
* @author Thomas Rientjes
|
||||
* @since 2017-08-18
|
||||
* @license MPL 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Variables
|
||||
*/
|
||||
|
||||
var webextensionPort = {};
|
||||
|
||||
var amountInjected = null;
|
||||
var pendingCount = 0;
|
||||
|
||||
/**
|
||||
* Initializations
|
||||
*/
|
||||
|
||||
webextensionPort = browser.runtime.connect({name: 'webextension'});
|
||||
|
||||
/**
|
||||
* Event Handlers
|
||||
*/
|
||||
|
||||
webextensionPort.onMessage.addListener((message) => {
|
||||
|
||||
if (message.subject === 'migrate-preferences') {
|
||||
|
||||
browser.storage.local.get(function (items) {
|
||||
|
||||
// Covers storage API failures.
|
||||
if (items === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let preference of Object.keys(message.content)) {
|
||||
|
||||
// Makes sure no existing preferences are overwritten.
|
||||
if (!items.hasOwnProperty(preference)) {
|
||||
|
||||
browser.storage.local.set({
|
||||
[preference]: message.content[preference]
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (message.subject === 'register-injection') {
|
||||
|
||||
if (amountInjected !== null && !isNaN(amountInjected)) {
|
||||
|
||||
++amountInjected;
|
||||
browser.storage.local.set({amountInjected});
|
||||
}
|
||||
|
||||
++pendingCount;
|
||||
|
||||
if (pendingCount > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
chrome.storage.local.get({
|
||||
|
||||
// The stored amount, or zero.
|
||||
amountInjected: 0
|
||||
|
||||
}, function (items) {
|
||||
|
||||
// Accounts for the fact that the storage API is asynchronous.
|
||||
amountInjected = (items && items.amountInjected || 0) + pendingCount;
|
||||
browser.storage.local.set({amountInjected});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if (message.subject === 'update-preferences') {
|
||||
chrome.storage.local.set(message.content);
|
||||
}
|
||||
});
|
||||
18
webextension/manifest.json
Normal file
18
webextension/manifest.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Decentraleyes Module",
|
||||
"version": "1.3.10",
|
||||
|
||||
"author": "Thomas Rientjes",
|
||||
|
||||
"background": {
|
||||
|
||||
"scripts": [
|
||||
"background.js"
|
||||
]
|
||||
},
|
||||
|
||||
"permissions": [
|
||||
"storage"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user