mirror of
https://github.com/pi-hole/pi-hole
synced 2024-11-19 22:58:16 +00:00
Merge conflict
Signed-off-by: Dan Schaper <dan.schaper@pi-hole.net>
This commit is contained in:
commit
b64066fec7
11
.github/ISSUE_TEMPLATE.md
vendored
11
.github/ISSUE_TEMPLATE.md
vendored
@ -6,16 +6,7 @@
|
||||
|
||||
**How familiar are you with the codebase?:**
|
||||
|
||||
- [] 1 (very unfamiliar)
|
||||
- [] 2
|
||||
- [] 3
|
||||
- [] 4
|
||||
- [] 5
|
||||
- [] 6
|
||||
- [] 7
|
||||
- [] 8
|
||||
- [] 9
|
||||
- [] 10 (very familiar)
|
||||
_{replace this text with a number from 1 to 10, with 1 being not familiar, and 10 being very familiar}_
|
||||
|
||||
---
|
||||
**[FEATURE REQUEST | QUESTION | OTHER]:**
|
||||
|
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -10,16 +10,7 @@
|
||||
|
||||
**How familiar are you with the codebase?:**
|
||||
|
||||
- [] 1 (very unfamiliar)
|
||||
- [] 2
|
||||
- [] 3
|
||||
- [] 4
|
||||
- [] 5
|
||||
- [] 6
|
||||
- [] 7
|
||||
- [] 8
|
||||
- [] 9
|
||||
- [] 10 (very familiar)
|
||||
_{replace this text with a number from 1 to 10, with 1 being not familiar, and 10 being very familiar}_
|
||||
|
||||
---
|
||||
_{replace this line with your pull request content}_
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
## The multi-platform, network-wide ad blocker
|
||||
|
||||
Block ads for **all** your devices _without_ the need to install client-side software. The Pi-hole blocks ads the DNS-level, so all your devices are protected.
|
||||
Block ads for **all** your devices _without_ the need to install client-side software. The Pi-hole blocks ads at the DNS-level, so all your devices are protected.
|
||||
|
||||
- Web Browsers
|
||||
- Cell Phones
|
||||
@ -53,7 +53,7 @@ wget -O basic-install.sh https://install.pi-hole.net
|
||||
bash basic-install.sh
|
||||
```
|
||||
|
||||
Once installed, [configure your router to have **DHCP clients use the Pi as their DNS server**](http://pi-hole.net/faq/can-i-set-the-pi-hole-to-be-the-dns-server-at-my-router-so-i-dont-have-to-change-settings-for-my-devices/) and then any device that connects to your network will have ads blocked without any further configuration. Alternatively, you can manually set each device to [use the Raspberry Pi as its DNS server](http://pi-hole.net/faq/how-do-i-use-the-pi-hole-as-my-dns-server/).
|
||||
Once installed, [configure your router to have **DHCP clients use the Pi as their DNS server**](https://discourse.pi-hole.net/t/how-do-i-configure-my-devices-to-use-pi-hole-as-their-dns-server/245) and then any device that connects to your network will have ads blocked without any further configuration. Alternatively, you can manually set each device to [use the Raspberry Pi as its DNS server](http://pi-hole.net/faq/how-do-i-use-the-pi-hole-as-my-dns-server/).
|
||||
|
||||
## Installing the Pi-hole (Click to Watch!)
|
||||
<p align="center">
|
||||
|
@ -15,8 +15,6 @@
|
||||
piLog="/var/log/pihole.log"
|
||||
gravity="/etc/pihole/gravity.list"
|
||||
|
||||
today=$(date "+%b %e")
|
||||
|
||||
. /etc/pihole/setupVars.conf
|
||||
|
||||
CalcBlockedDomains() {
|
||||
@ -35,7 +33,7 @@ CalcBlockedDomains() {
|
||||
|
||||
CalcQueriesToday() {
|
||||
if [ -e "${piLog}" ]; then
|
||||
queriesToday=$(cat "${piLog}" | grep "${today}" | awk '/query/ {print $6}' | wc -l)
|
||||
queriesToday=$(awk '/query\[/ {print $6}' < "${piLog}" | wc -l)
|
||||
else
|
||||
queriesToday="Err."
|
||||
fi
|
||||
@ -43,7 +41,7 @@ CalcQueriesToday() {
|
||||
|
||||
CalcblockedToday() {
|
||||
if [ -e "${piLog}" ] && [ -e "${gravity}" ];then
|
||||
blockedToday=$(cat ${piLog} | awk '/\/etc\/pihole\/gravity.list/ && !/address/ {print $6}' | wc -l)
|
||||
blockedToday=$(awk '/\/etc\/pihole\/gravity.list/ && !/address/ {print $6}' < "${piLog}" | wc -l)
|
||||
else
|
||||
blockedToday="Err."
|
||||
fi
|
||||
@ -104,7 +102,7 @@ normalChrono() {
|
||||
|
||||
echo "Blocking: ${blockedDomainsTotal}"
|
||||
echo "Queries: ${queriesToday}" #same total calculation as dashboard
|
||||
echo "Pi-holed: ${blockedToday} (${percentBlockedToday}%)"
|
||||
echo "Pi-holed: ${blockedToday} (${percentBlockedToday}%)"
|
||||
|
||||
sleep 5
|
||||
done
|
||||
|
@ -69,7 +69,7 @@ SetWebPassword(){
|
||||
SetDNSServers(){
|
||||
|
||||
# Remove setting from file (create backup setupVars.conf.bak)
|
||||
sed -i.bak '/PIHOLE_DNS_1/d;/PIHOLE_DNS_2/d;/DNS_FQDN_REQUIRED/d;' /etc/pihole/setupVars.conf
|
||||
sed -i.bak '/PIHOLE_DNS_1/d;/PIHOLE_DNS_2/d;/DNS_FQDN_REQUIRED/d;/DNS_BOGUS_PRIV/d;' /etc/pihole/setupVars.conf
|
||||
# Save setting to file
|
||||
echo "PIHOLE_DNS_1=${args[2]}" >> /etc/pihole/setupVars.conf
|
||||
if [[ "${args[3]}" != "none" ]]; then
|
||||
@ -215,6 +215,20 @@ SetDNSDomainName(){
|
||||
|
||||
}
|
||||
|
||||
ResolutionSettings() {
|
||||
|
||||
typ=${args[2]}
|
||||
state=${args[3]}
|
||||
|
||||
if [[ "${typ}" == "forward" ]]; then
|
||||
sed -i.bak '/API_GET_UPSTREAM_DNS_HOSTNAME/d;' /etc/pihole/setupVars.conf
|
||||
echo "API_GET_UPSTREAM_DNS_HOSTNAME=${state}" >> /etc/pihole/setupVars.conf
|
||||
elif [[ "${typ}" == "clients" ]]; then
|
||||
sed -i.bak '/API_GET_CLIENT_HOSTNAME/d;' /etc/pihole/setupVars.conf
|
||||
echo "API_GET_CLIENT_HOSTNAME=${state}" >> /etc/pihole/setupVars.conf
|
||||
fi
|
||||
}
|
||||
|
||||
case "${args[1]}" in
|
||||
"-p" | "password" ) SetWebPassword;;
|
||||
"-c" | "celsius" ) unit="C"; SetTemperatureUnit;;
|
||||
@ -231,6 +245,7 @@ case "${args[1]}" in
|
||||
"layout" ) SetWebUILayout;;
|
||||
"-h" | "--help" ) helpFunc;;
|
||||
"domainname" ) SetDNSDomainName;;
|
||||
"resolve" ) ResolutionSettings;;
|
||||
* ) helpFunc;;
|
||||
esac
|
||||
|
||||
|
@ -13,14 +13,15 @@
|
||||
# scripts, any changes made to this file will be overwritten when the softare
|
||||
# is updated or re-installed. Please make any changes to the appropriate crontab
|
||||
# or other cron file snippets.
|
||||
PATH="$PATH:/usr/local/bin/"
|
||||
|
||||
# Pi-hole: Update the ad sources once a week on Sunday at 01:59
|
||||
# Download any updates from the adlists
|
||||
59 1 * * 7 root PATH="$PATH:/usr/local/bin/" pihole updateGravity
|
||||
59 1 * * 7 root pihole updateGravity
|
||||
|
||||
# Pi-hole: Update Pi-hole! Uncomment to enable auto update
|
||||
#30 2 * * 7 root PATH="$PATH:/usr/local/bin/" pihole updatePihole
|
||||
#30 2 * * 7 root pihole updatePihole
|
||||
|
||||
# Pi-hole: Flush the log daily at 00:00 so it doesn't get out of control
|
||||
# Stats will be viewable in the Web interface thanks to the cron job above
|
||||
00 00 * * * root PATH="$PATH:/usr/local/bin/" pihole flush
|
||||
00 00 * * * root pihole flush
|
||||
|
@ -1,87 +0,0 @@
|
||||
module pihole 1.0;
|
||||
|
||||
require {
|
||||
type var_log_t;
|
||||
type unconfined_t;
|
||||
type init_t;
|
||||
type auditd_t;
|
||||
type syslogd_t;
|
||||
type NetworkManager_t;
|
||||
type mdadm_t;
|
||||
type tuned_t;
|
||||
type avahi_t;
|
||||
type irqbalance_t;
|
||||
type system_dbusd_t;
|
||||
type kernel_t;
|
||||
type httpd_sys_script_t;
|
||||
type systemd_logind_t;
|
||||
type httpd_t;
|
||||
type policykit_t;
|
||||
type dnsmasq_t;
|
||||
type udev_t;
|
||||
type postfix_pickup_t;
|
||||
type sshd_t;
|
||||
type crond_t;
|
||||
type getty_t;
|
||||
type lvm_t;
|
||||
type postfix_qmgr_t;
|
||||
type postfix_master_t;
|
||||
class dir { getattr search };
|
||||
class file { read open setattr };
|
||||
}
|
||||
|
||||
#============= dnsmasq_t ==============
|
||||
allow dnsmasq_t var_log_t:file { open setattr };
|
||||
|
||||
#============= httpd_t ==============
|
||||
allow httpd_t var_log_t:file { read open };
|
||||
|
||||
#============= httpd_sys_script_t (class: dir) ==============
|
||||
allow httpd_sys_script_t NetworkManager_t:dir { getattr search };
|
||||
allow httpd_sys_script_t auditd_t:dir { getattr search };
|
||||
allow httpd_sys_script_t avahi_t:dir { getattr search };
|
||||
allow httpd_sys_script_t crond_t:dir { getattr search };
|
||||
allow httpd_sys_script_t dnsmasq_t:dir { getattr search };
|
||||
allow httpd_sys_script_t getty_t:dir { getattr search };
|
||||
allow httpd_sys_script_t httpd_t:dir { getattr search };
|
||||
allow httpd_sys_script_t init_t:dir { getattr search };
|
||||
allow httpd_sys_script_t irqbalance_t:dir { getattr search };
|
||||
allow httpd_sys_script_t kernel_t:dir { getattr search };
|
||||
allow httpd_sys_script_t lvm_t:dir { getattr search };
|
||||
allow httpd_sys_script_t mdadm_t:dir { getattr search };
|
||||
allow httpd_sys_script_t policykit_t:dir { getattr search };
|
||||
allow httpd_sys_script_t postfix_master_t:dir { getattr search };
|
||||
allow httpd_sys_script_t postfix_pickup_t:dir { getattr search };
|
||||
allow httpd_sys_script_t postfix_qmgr_t:dir { getattr search };
|
||||
allow httpd_sys_script_t sshd_t:dir { getattr search };
|
||||
allow httpd_sys_script_t syslogd_t:dir { getattr search };
|
||||
allow httpd_sys_script_t system_dbusd_t:dir { getattr search };
|
||||
allow httpd_sys_script_t systemd_logind_t:dir { getattr search };
|
||||
allow httpd_sys_script_t tuned_t:dir { getattr search };
|
||||
allow httpd_sys_script_t udev_t:dir { getattr search };
|
||||
allow httpd_sys_script_t unconfined_t:dir { getattr search };
|
||||
|
||||
#============= httpd_sys_script_t (class: file) ==============
|
||||
allow httpd_sys_script_t NetworkManager_t:file { read open };
|
||||
allow httpd_sys_script_t auditd_t:file { read open };
|
||||
allow httpd_sys_script_t avahi_t:file { read open };
|
||||
allow httpd_sys_script_t crond_t:file { read open };
|
||||
allow httpd_sys_script_t dnsmasq_t:file { read open };
|
||||
allow httpd_sys_script_t getty_t:file { read open };
|
||||
allow httpd_sys_script_t httpd_t:file { read open };
|
||||
allow httpd_sys_script_t init_t:file { read open };
|
||||
allow httpd_sys_script_t irqbalance_t:file { read open };
|
||||
allow httpd_sys_script_t kernel_t:file { read open };
|
||||
allow httpd_sys_script_t lvm_t:file { read open };
|
||||
allow httpd_sys_script_t mdadm_t:file { read open };
|
||||
allow httpd_sys_script_t policykit_t:file { read open };
|
||||
allow httpd_sys_script_t postfix_master_t:file { read open };
|
||||
allow httpd_sys_script_t postfix_pickup_t:file { read open };
|
||||
allow httpd_sys_script_t postfix_qmgr_t:file { read open };
|
||||
allow httpd_sys_script_t sshd_t:file { read open };
|
||||
allow httpd_sys_script_t syslogd_t:file { read open };
|
||||
allow httpd_sys_script_t system_dbusd_t:file { read open };
|
||||
allow httpd_sys_script_t systemd_logind_t:file { read open };
|
||||
allow httpd_sys_script_t tuned_t:file { read open };
|
||||
allow httpd_sys_script_t udev_t:file { read open };
|
||||
allow httpd_sys_script_t unconfined_t:file { read open };
|
@ -130,8 +130,14 @@ fi
|
||||
is_repo() {
|
||||
# Use git to check if directory is currently under VCS, return the value
|
||||
local directory="${1}"
|
||||
curdir=$PWD; cd $directory; git status --short &> /dev/null; rc=$?; cd $curdir
|
||||
return $rc
|
||||
if [ -d $directory ]; then
|
||||
# git -C is not used here to support git versions older than 1.8.4
|
||||
curdir=$PWD; cd $directory; git status --short &> /dev/null; rc=$?; cd $curdir
|
||||
return $rc
|
||||
else
|
||||
# non-zero return code if directory does not exist OR is not a valid git repository
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
make_repo() {
|
||||
@ -147,7 +153,7 @@ make_repo() {
|
||||
update_repo() {
|
||||
local directory="${1}"
|
||||
# Pull the latest commits
|
||||
echo -n "::: Updating repo in $1..."
|
||||
echo -n "::: Updating repo in $1..."
|
||||
cd "${directory}" || exit 1
|
||||
git stash -q &> /dev/null
|
||||
git pull -q &> /dev/null
|
||||
@ -821,6 +827,13 @@ installPiholeWeb() {
|
||||
cp /etc/.pihole/advanced/pihole.sudo /etc/sudoers.d/pihole
|
||||
# Add lighttpd user (OS dependent) to sudoers file
|
||||
echo "${LIGHTTPD_USER} ALL=NOPASSWD: /usr/local/bin/pihole" >> /etc/sudoers.d/pihole
|
||||
|
||||
if [[ "$LIGHTTPD_USER" == "lighttpd" ]]; then
|
||||
# Allow executing pihole via sudo with Fedora
|
||||
# Usually /usr/local/bin is not permitted as directory for sudoable programms
|
||||
echo "Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin" >> /etc/sudoers.d/pihole
|
||||
fi
|
||||
|
||||
chmod 0440 /etc/sudoers.d/pihole
|
||||
echo " done!"
|
||||
}
|
||||
@ -841,6 +854,10 @@ runGravity() {
|
||||
echo "::: Cleaning up previous install (preserving whitelist/blacklist)"
|
||||
rm /etc/pihole/list.*
|
||||
fi
|
||||
# Test if /etc/pihole/adlists.default exists
|
||||
if [[ ! -e /etc/pihole/adlists.default ]]; then
|
||||
cp /etc/.pihole/adlists.default /etc/pihole/adlists.default
|
||||
fi
|
||||
echo "::: Running gravity.sh"
|
||||
{ /opt/pihole/gravity.sh; }
|
||||
}
|
||||
@ -898,7 +915,6 @@ installPihole() {
|
||||
installScripts
|
||||
installConfigs
|
||||
CreateLogFile
|
||||
configureSelinux
|
||||
installPiholeWeb
|
||||
installCron
|
||||
configureFirewall
|
||||
@ -929,7 +945,6 @@ updatePihole() {
|
||||
installScripts
|
||||
installConfigs
|
||||
CreateLogFile
|
||||
configureSelinux
|
||||
installPiholeWeb
|
||||
installCron
|
||||
configureFirewall
|
||||
@ -941,7 +956,7 @@ configureSelinux() {
|
||||
if [ -x "$(command -v getenforce)" ]; then
|
||||
printf "\n::: SELinux Detected\n"
|
||||
printf ":::\tChecking for SELinux policy development packages..."
|
||||
install_dependent_packages "selinux-policy-devel" > /dev/null
|
||||
package_check_install "selinux-policy-devel" > /dev/null
|
||||
echo " installed!"
|
||||
printf ":::\tEnabling httpd server side includes (SSI).. "
|
||||
setsebool -P httpd_ssi_exec on &> /dev/null && echo "Success" || echo "SELinux not enabled"
|
||||
@ -949,11 +964,6 @@ configureSelinux() {
|
||||
if ! [ -x "$(command -v systemctl)" ]; then
|
||||
sed -i.bak '/systemd/d' /etc/.pihole/advanced/selinux/pihole.te
|
||||
fi
|
||||
checkmodule -M -m -o /etc/pihole/pihole.mod /etc/.pihole/advanced/selinux/pihole.te
|
||||
semodule_package -o /etc/pihole/pihole.pp -m /etc/pihole/pihole.mod
|
||||
semodule -i /etc/pihole/pihole.pp
|
||||
rm -f /etc/pihole/pihole.mod
|
||||
semodule -l | grep pihole &> /dev/null && echo "::: Installed Pi-Hole SELinux policy" || echo "::: Warning: Pi-Hole SELinux policy did not install."
|
||||
fi
|
||||
}
|
||||
|
||||
@ -1019,7 +1029,8 @@ update_dialogs() {
|
||||
}
|
||||
|
||||
main() {
|
||||
# Check arguments for the undocumented flags
|
||||
|
||||
# Check arguments for the undocumented flags
|
||||
for var in "$@"; do
|
||||
case "$var" in
|
||||
"--reconfigure" ) reconfigure=true;;
|
||||
@ -1054,6 +1065,9 @@ main() {
|
||||
# Install packages used by this installation script
|
||||
install_dependent_packages INSTALLER_DEPS[@]
|
||||
|
||||
# Check if SELinux is Enforcing
|
||||
checkSelinux
|
||||
|
||||
if [[ "${reconfigure}" == true ]]; then
|
||||
echo "::: --reconfigure passed to install script. Not downloading/updating local repos"
|
||||
else
|
||||
@ -1074,10 +1088,10 @@ main() {
|
||||
get_available_interfaces
|
||||
# Find interfaces and let the user choose one
|
||||
chooseInterface
|
||||
# Let the user decide if they want to block ads over IPv4 and/or IPv6
|
||||
use4andor6
|
||||
# Decide what upstream DNS Servers to use
|
||||
setDNS
|
||||
# Let the user decide if they want to block ads over IPv4 and/or IPv6
|
||||
use4andor6
|
||||
# Let the user decide if they want query logging enabled...
|
||||
setLogging
|
||||
|
||||
@ -1143,4 +1157,4 @@ main() {
|
||||
|
||||
if [[ "${PH_TEST}" != true ]] ; then
|
||||
main "$@"
|
||||
fi
|
||||
fi
|
||||
|
63
gravity.sh
63
gravity.sh
@ -104,16 +104,30 @@ gravity_collapse() {
|
||||
# patternCheck - check to see if curl downloaded any new files.
|
||||
gravity_patternCheck() {
|
||||
patternBuffer=$1
|
||||
# check if the patternbuffer is a non-zero length file
|
||||
if [[ -s "${patternBuffer}" ]]; then
|
||||
# Some of the blocklists are copyright, they need to be downloaded
|
||||
# and stored as is. They can be processed for content after they
|
||||
# have been saved.
|
||||
mv "${patternBuffer}" "${saveLocation}"
|
||||
echo " List updated, transport successful!"
|
||||
success=$2
|
||||
error=$3
|
||||
if [ $success = true ]; then
|
||||
# check if download was successful but list has not been modified
|
||||
if [ "${error}" == "304" ]; then
|
||||
echo "::: No changes detected, transport skipped!"
|
||||
# check if the patternbuffer is a non-zero length file
|
||||
elif [[ -s "${patternBuffer}" ]]; then
|
||||
# Some of the blocklists are copyright, they need to be downloaded
|
||||
# and stored as is. They can be processed for content after they
|
||||
# have been saved.
|
||||
mv "${patternBuffer}" "${saveLocation}"
|
||||
echo "::: List updated, transport successful!"
|
||||
else
|
||||
# Empty file -> use previously downloaded list
|
||||
echo "::: Received empty file, using cached one (list not updated!)"
|
||||
fi
|
||||
else
|
||||
# curl didn't download any host files, probably because of the date check
|
||||
echo " No changes detected, transport skipped!"
|
||||
# check if cached list exists
|
||||
if [[ -r "${saveLocation}" ]]; then
|
||||
echo "::: List download failed, using cached list (list not updated!)"
|
||||
else
|
||||
echo "::: Download failed and no cached list available (list will not be considered)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@ -132,9 +146,27 @@ gravity_transport() {
|
||||
fi
|
||||
|
||||
# Silently curl url
|
||||
curl -s -L ${cmd_ext} ${heisenbergCompensator} -A "${agent}" ${url} > ${patternBuffer}
|
||||
# Check for list updates
|
||||
gravity_patternCheck "${patternBuffer}"
|
||||
err=$(curl -s -L ${cmd_ext} ${heisenbergCompensator} -w %{http_code} -A "${agent}" ${url} -o ${patternBuffer})
|
||||
|
||||
echo " done"
|
||||
# Analyze http response
|
||||
echo -n "::: Status: "
|
||||
case "$err" in
|
||||
"200" ) echo "Success (OK)"; success=true;;
|
||||
"304" ) echo "Not modified"; success=true;;
|
||||
"403" ) echo "Forbidden"; success=false;;
|
||||
"404" ) echo "Not found"; success=false;;
|
||||
"408" ) echo "Time-out"; success=false;;
|
||||
"451" ) echo "Unavailable For Legal Reasons"; success=false;;
|
||||
"521" ) echo "Web Server Is Down (Cloudflare)"; success=false;;
|
||||
"522" ) echo "Connection Timed Out (Cloudflare)"; success=false;;
|
||||
"500" ) echo "Internal Server Error"; success=false;;
|
||||
* ) echo "Status $err"; success=false;;
|
||||
esac
|
||||
|
||||
# Process result
|
||||
gravity_patternCheck "${patternBuffer}" ${success} "${err}"
|
||||
|
||||
}
|
||||
|
||||
# spinup - main gravity function
|
||||
@ -181,7 +213,10 @@ gravity_Schwarzchild() {
|
||||
echo -n "::: Aggregating list of domains..."
|
||||
truncate -s 0 ${piholeDir}/${matterAndLight}
|
||||
for i in "${activeDomains[@]}"; do
|
||||
cat "${i}" | tr -d '\r' >> ${piholeDir}/${matterAndLight}
|
||||
# Only assimilate list if it is available (download might have faild permanently)
|
||||
if [[ -r "${i}" ]]; then
|
||||
cat "${i}" | tr -d '\r' >> ${piholeDir}/${matterAndLight}
|
||||
fi
|
||||
done
|
||||
echo " done!"
|
||||
}
|
||||
@ -353,7 +388,7 @@ if [[ "${forceGrav}" == true ]]; then
|
||||
fi
|
||||
|
||||
#Overwrite adlists.default from /etc/.pihole in case any changes have been made. Changes should be saved in /etc/adlists.list
|
||||
cp /etc/.pihole/adlists.default /etc/pihole/adlists.default
|
||||
#cp /etc/.pihole/adlists.default /etc/pihole/adlists.default
|
||||
gravity_collapse
|
||||
gravity_spinup
|
||||
if [[ "${skipDownload}" == false ]]; then
|
||||
|
Loading…
Reference in New Issue
Block a user