Commit ee827259 authored by Davide Aprea's avatar Davide Aprea

Merge branch 'development' into 1103-keys-for-donors

parents 03c61584 a6886610
......@@ -43,6 +43,8 @@ deploymentApiVersion: apps/v1
ingress:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/client-body-buffer-size: "30m"
nginx.ingress.kubernetes.io/proxy-body-size: "30m"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; script-src-elem 'self' 'unsafe-inline'; script-src-attr 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline'; style-src-attr 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; media-src; object-src; prefetch-src; child-src; frame-src 'self'; worker-src; frame-ancestors 'self' https://scripts.zdv.uni-mainz.de; form-action 'self' www.paypal.com; base-uri; manifest-src; plugin-types; report-uri; report-to";
more_set_headers "X-Frame-Options: sameorigin";
......
......@@ -63,6 +63,8 @@ ingress:
secretName: production-auto-deploy-tls
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/client-body-buffer-size: "30m"
nginx.ingress.kubernetes.io/proxy-body-size: "30m"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; script-src-elem 'self' 'unsafe-inline'; script-src-attr 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline'; style-src-attr 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; media-src; object-src; prefetch-src; child-src; frame-src 'self'; worker-src; frame-ancestors 'self' https://scripts.zdv.uni-mainz.de; form-action 'self' www.paypal.com; base-uri; manifest-src; plugin-types; report-uri; report-to";
more_set_headers "X-Frame-Options: sameorigin";
......
......@@ -9,6 +9,8 @@ ingress:
annotations:
kubernetes.io/tls-acme: "false"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/client-body-buffer-size: "30m"
nginx.ingress.kubernetes.io/proxy-body-size: "30m"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; script-src-elem 'self' 'unsafe-inline'; script-src-attr 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline'; style-src-attr 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; media-src; object-src; prefetch-src; child-src; frame-src 'self'; worker-src; frame-ancestors 'self' https://scripts.zdv.uni-mainz.de; form-action 'self' www.paypal.com; base-uri; manifest-src; plugin-types; report-uri; report-to";
more_set_headers "X-Frame-Options: sameorigin";
......
......@@ -55,6 +55,8 @@ RUN sed -i 's/;error_log = log\/php7\/error.log/error_log = \/dev\/stderr/g' /et
sed -i 's/;opcache.max_wasted_percentage=5/opcache.max_wasted_percentage=5/g' /etc/php7/php.ini && \
sed -i 's/;opcache.validate_timestamps=1/opcache.validate_timestamps=1/g' /etc/php7/php.ini && \
sed -i 's/;opcache.revalidate_freq=2/opcache.revalidate_freq=300/g' /etc/php7/php.ini && \
sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 30M/g' /etc/php7/php.ini && \
sed -i 's/post_max_size = 8M/post_max_size = 30M/g' /etc/php7/php.ini && \
echo "daemonize yes" >> /etc/redis.conf && \
ln -s /dev/null /var/log/nginx/access.log && \
ln -s /dev/stdout /var/log/nginx/error.log && \
......
......@@ -46,6 +46,8 @@ RUN sed -i 's/;error_log = log\/php7\/error.log/error_log = \/dev\/stderr/g' /et
sed -i 's/group = www-data/group = nginx/g' /etc/php7/php-fpm.d/www.conf && \
sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php7/php.ini && \
sed -i 's/expose_php = On/expose_php = Off/g' /etc/php7/php.ini && \
sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 30M/g' /etc/php7/php.ini && \
sed -i 's/post_max_size = 8M/post_max_size = 30M/g' /etc/php7/php.ini && \
sed -i 's/;zend_extension=xdebug.so/zend_extension=xdebug.so/g' /etc/php7/conf.d/xdebug.ini && \
echo "xdebug.remote_enable = 1" >> /etc/php7/conf.d/xdebug.ini && \
echo "xdebug.remote_autostart = 1" >> /etc/php7/conf.d/xdebug.ini && \
......
......@@ -155,7 +155,7 @@ class RequestFetcher extends Command
Log::error($error);
}
if ($responseCode !== 200) {
if ($responseCode !== 200 && $responseCode !== 201) {
Log::debug($resulthash);
Log::debug("Got responsecode " . $responseCode . " fetching \"" . curl_getinfo($info["handle"], CURLINFO_EFFECTIVE_URL) . "\n");
} else {
......
......@@ -62,9 +62,16 @@ class KeyController extends Controller
public function removeKey(Request $request)
{
$instantRedir = $request->input("ir", "");
$redirUrl = $request->input('redirUrl', "");
Cookie::queue(Cookie::forget('key'));
Cookie::queue("key", "", 0, '/', null, false, false);
$url = LaravelLocalization::getLocalizedURL(LaravelLocalization::getCurrentLocale(), action('KeyController@index', ['redirUrl' => $redirUrl]));
return redirect($url);
$host = $request->getHttpHost();
if(!empty($instantRedir) && in_array($host, ["metager.de", "metager.es", "metager.org", "metager3.de", "localhost:8080"])){
return redirect($instantRedir);
}else{
return redirect($url);
}
}
}
......@@ -2,9 +2,9 @@
namespace App\Http\Controllers;
use App\Mail\Kontakt;
use App\Mail\Sprachdatei;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;
use Illuminate\Http\Response;
use LaravelLocalization;
use Mail;
......@@ -28,14 +28,16 @@ class MailController extends Controller
$returnMessage = '';
# Wir benötigen 3 Felder von dem Benutzer wenn diese nicht übermittelt wurden, oder nicht korrekt sind geben wir einen Error zurück
$input_data = $request->all();
$maxFileSize = 5 * 1024;
$validator = Validator::make(
[
'email' => $request->input('email'),
'pcsrf' => $request->input('pcsrf'),
],
$input_data,
[
'email' => 'required|email',
'pcsrf' => ['required', 'string', new \App\Rules\PCSRF],
'attachments' => ['max:5'],
'attachments.*' => ['file', 'max:' . $maxFileSize],
]
);
......@@ -56,24 +58,81 @@ class MailController extends Controller
$messageType = "error";
$returnMessage = trans('kontakt.error.1');
} else {
$message = $request->input('message');
$subject = $request->input('subject');
# Wir versenden die Mail des Benutzers an uns:
$mailto = "support@metager.org";
$postdata = [
"alert" => true,
"autorespond" => true,
"source" => "API",
"name" => $name,
"email" => $replyTo,
"subject" => $subject,
"ip" => $request->ip(),
"deptId" => 5,
"message" => "data:text/plain;charset=utf-8, $message",
"attachments" => []
];
if($request->has("attachments") && is_array($request->file("attachments"))){
foreach($request->file("attachments") as $attachment){
$postdata["attachments"][] = [
$attachment->getClientOriginalName() => "data:" . $attachment->getMimeType() . ";base64," . base64_encode(file_get_contents($attachment->getRealPath()))
];
}
}
if (LaravelLocalization::getCurrentLocale() === "de") {
$mailto = "support@suma-ev.de";
$postdata["deptId"] = 1;
}
$message = $request->input('message');
$subject = $request->input('subject');
Mail::to($mailto)
->send(new Kontakt($name, $replyTo, $subject, $message));
$returnMessage = trans('kontakt.success.1');
$messageType = "success";
$postdata = json_encode($postdata);
$resulthash = md5($subject . $message);
$mission = [
"resulthash" => $resulthash,
"url" => env("TICKET_URL", "https://metager.de"),
"useragent" => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0",
"username" => null,
"password" => null,
"headers" => [
"X-API-Key" => env("TICKET_APIKEY", ""),
"Content-Type" => "application/json",
"Content-Length" => strlen($postdata)
],
"cacheDuration" => 0,
"name" => "Ticket",
"curlopts" => [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postdata,
CURLOPT_LOW_SPEED_TIME => 20,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 20
]
];
$mission = json_encode($mission);
Redis::rpush(\App\MetaGer::FETCHQUEUE_KEY, $mission);
// Fetch the result
$answer = Redis::blpop($resulthash, 20);
// Fehlerfall
if(empty($answer) || (is_array($answer) && sizeof($answer) === 2 && $answer[1] === "no-result")){
$messageType = "error";
$returnMessage = trans('kontakt.error.2', ["email" => env("MAIL_USERNAME", "support+46521@metager.de")]);
}else{
$returnMessage = trans('kontakt.success.1', ["email" => $replyTo]);
$messageType = "success";
}
}
return view('kontakt.kontakt')
->with('title', 'Kontakt')
->with('js', ['lib.js'])
->with($messageType, $returnMessage);
}
public function donation(Request $request)
......@@ -185,15 +244,69 @@ class MailController extends Controller
}
try {
Mail::to("spenden@suma-ev.de")
->send(new \App\Mail\Spende($email, $message, $name));
$postdata = [
"alert" => true,
"autorespond" => true,
"source" => "API",
"name" => $name,
"email" => $email,
"subject" => "MetaGer - Spende",
"ip" => $request->ip(),
"deptId" => 4,
"message" => "data:text/plain;charset=utf-8, $message",
];
if (LaravelLocalization::getCurrentLocale() === "de") {
$postdata["deptId"] = 4;
}
$messageType = "success";
$messageToUser = "Herzlichen Dank!! Wir haben Ihre Spendenbenachrichtigung erhalten.";
if($email === "anonymous@suma-ev.de"){
$postdata["autorespond"] = false;
}
$postdata = json_encode($postdata);
$resulthash = md5($message);
$mission = [
"resulthash" => $resulthash,
"url" => env("TICKET_URL", "https://metager.de"),
"useragent" => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0",
"username" => null,
"password" => null,
"headers" => [
"X-API-Key" => env("TICKET_APIKEY", ""),
"Content-Type" => "application/json",
"Content-Length" => strlen($postdata)
],
"cacheDuration" => 0,
"name" => "Ticket",
"curlopts" => [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postdata,
CURLOPT_LOW_SPEED_TIME => 20,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 20
]
];
$mission = json_encode($mission);
Redis::rpush(\App\MetaGer::FETCHQUEUE_KEY, $mission);
// Fetch the result
$answer = Redis::blpop($resulthash, 20);
// Fehlerfall
if(empty($answer) || (is_array($answer) && sizeof($answer) === 2 && $answer[1] === "no-result")){
$messageType = "error";
$messageToUser = "Beim Senden Ihrer Spendenbenachrichtigung ist ein Fehler auf unserer Seite aufgetreten. Bitte schicken Sie eine E-Mail an: dominik@suma-ev.de, damit wir uns darum kümmern können.";
}else{
$messageToUser = "Herzlichen Dank!! Wir haben Ihre Spendenbenachrichtigung erhalten.";
$messageType = "success";
}
} catch (\Swift_TransportException $e) {
Log::error($e->getMessage());
$messageType = "error";
$messageToUser = 'Beim Senden Ihrer Spendenbenachrichtigung ist ein Fehler auf unserer Seite aufgetreten. Bitte schicken Sie eine E-Mail an: office@suma-ev.de, damit wir uns darum kümmern können.';
$messageToUser = 'Beim Senden Ihrer Spendenbenachrichtigung ist ein Fehler auf unserer Seite aufgetreten. Bitte schicken Sie eine E-Mail an: dominik@suma-ev.de, damit wir uns darum kümmern können.';
}
}
......
......@@ -64,5 +64,6 @@ class Kernel extends HttpKernel
'useragentmaster' => \App\Http\Middleware\UserAgentMaster::class,
'browserverification' => \App\Http\Middleware\BrowserVerification::class,
'keyvalidation' => \App\Http\Middleware\KeyValidation::class,
'removekey' => \App\Http\Middleware\RemoveKey::class,
];
}
<?php
namespace App\Http\Middleware;
use Closure;
use Cookie;
class RemoveKey
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Check if a wrong Key Cookie is set and if so remove it
if(Cookie::has("key") && !app('App\Models\Key')->getStatus()){
return redirect(route("removeCookie", ["ir" => url()->full()]));
}
return $next($request);
}
}
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class Kontakt extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($name, $from, $subject, $message)
{
$this->name = $name;
$this->reply = $from;
$this->subject = $subject;
$this->message = $message;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from($this->reply, $this->name)
->subject($this->subject)
->text('kontakt.mail')
->with('messageText', $this->message);
}
}
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class Spende extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($from, $message, $name)
{
$this->subject = "MetaGer - Spende";
$this->reply = $from;
$this->message = $message;
$this->name = $name;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from($this->reply, $this->name)
->subject($this->subject)
->text('kontakt.mail')
->with('messageText', $this->message);
}
}
......@@ -66,6 +66,7 @@ class MetaGer
protected $adDomainsBlacklisted = [];
protected $urlsBlacklisted = [];
protected $adUrlsBlacklisted = [];
protected $blacklistDescriptionUrl = [];
protected $url;
protected $fullUrl;
protected $enabledSearchengines = [];
......@@ -103,6 +104,11 @@ class MetaGer
$this->adUrlsBlacklisted = explode("\n", $tmp);
}
if(file_exists(config_path() . "/blacklistDescriptionUrl.txt")){
$tmp = file_get_contents(config_path() . "/blacklistDescriptionUrl.txt");
$this->blacklistDescriptionUrl = explode("\n", $tmp);
}
# Parser Skripte einhängen
$dir = app_path() . "/Models/parserSkripte/";
foreach (scandir($dir) as $filename) {
......@@ -1831,6 +1837,11 @@ class MetaGer
return $this->domainsBlacklisted;
}
public function getBlacklistDescriptionUrl()
{
return $this->blacklistDescriptionUrl;
}
public function getUrlBlacklist()
{
return $this->urlsBlacklisted;
......
......@@ -2,20 +2,22 @@
namespace App\Models;
use Illuminate\Support\Facades\Redis;
use Request;
class Key
{
public $key;
public $status; # valid key = true, invalid key = false, unidentified key = null
//private $keyserver = "https://key.metager.de/";
private $keyserver = "https://dev.key.metager.de/";
private $keyserver = "https://key.metager.de/";
public function __construct($key, $status = null)
{
$this->key = $key;
$this->status = $status;
/*if (getenv("APP_ENV") !== "production") {
if (getenv("APP_ENV") !== "production") {
$this->keyserver = "https://dev.key.metager.de/";
}*/
}
}
# always returns true or false
......@@ -23,6 +25,29 @@ class Key
{
if ($this->key !== '' && $this->status === null) {
$this->updateStatus();
if(empty($this->status)){
// The user provided an invalid key which we will log to fail2ban
$fail2banEnabled = config("metager.metager.fail2ban_enabled");
if(empty($fail2banEnabled) || !$fail2banEnabled || !env("fail2banurl", false) || !env("fail2banuser") || !env("fail2banpassword")){
return false;
}
// Submit fetch job to worker
$mission = [
"resulthash" => "captcha",
"url" => env("fail2banurl") . "/mgkeytry/",
"useragent" => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0",
"username" => env("fail2banuser"),
"password" => env("fail2banpassword"),
"headers" => [
"ip" => Request::ip()
],
"cacheDuration" => 0,
"name" => "Captcha",
];
$mission = json_encode($mission);
Redis::rpush(\App\MetaGer::FETCHQUEUE_KEY, $mission);
}
}
if ($this->status === null || $this->status === false) {
return false;
......
......@@ -269,6 +269,11 @@ class Result
}
}
// Possibly remove description
if($this->isDescriptionBlackListed($metager)){
$this->descr = "";
}
/*
# Phrasensuche:
$text = strtolower($this->titel) . " " . strtolower($this->descr);
......@@ -324,6 +329,11 @@ class Result
}
public function isDescriptionBlackListed(\App\MetaGer $metager)
{
return in_array($this->strippedLink, $metager->getBlacklistDescriptionUrl()) || in_array($this->strippedLinkAnzeige, $metager->getBlacklistDescriptionUrl());
}
/* Liest aus einem Link den Host.
* Dieser wird dabei in die Form:
* "http://www.foo.bar.de/test?ja=1" -> "foo.bar.de"
......@@ -371,13 +381,13 @@ class Result
if(!empty($parts["host"])){
$proxyUrl .= $parts["host"];
if(!empty($parts["path"])){
$proxyUrl .= "/" . trim($parts["path"], "/");
$proxyUrl .= "/" . rawurlencode(trim($parts["path"], "/"));
}
}
// We need to generate the correct password for the Proxy URLs
// It's an hmac sha256 hash of the url having the proxy password as secret
$password = hash_hmac("sha256", $link, env("PROXY_PASSWORD", "unsecure_password"));
$password = hash_hmac("sha256", rtrim($link, "/"), env("PROXY_PASSWORD", "unsecure_password"));
$urlParameters = [
"url" => $link,
......
......@@ -121,6 +121,10 @@ spec:
mountPath: /html/config/adBlacklistUrl.txt
subPath: adblacklisturl
readOnly: true
- name: secrets
mountPath: /html/config/blacklistDescriptionUrl.txt
subPath: blacklistDescriptionUrl
readOnly: true
- name: secrets
mountPath: /html/config/adBlacklistDomains.txt
subPath: adblacklistdomains
......
......@@ -4,6 +4,8 @@ server {
root /html/public;
index index.php index.html index.htm;
client_max_body_size 30M;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
......
......@@ -4,6 +4,8 @@ server {
root /html/public;
index index.php index.html index.htm;
client_max_body_size 30M;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
......
......@@ -26,6 +26,7 @@ http {
#tcp_nopush on;
keepalive_timeout 65;
client_max_body_size 30M;
gzip on;
......
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Browser Test Suite">
<directory suffix="Test.php">./tests/Browser</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
</phpunit>
......@@ -36,7 +36,7 @@ Es steht dir jedoch frei, ein Ticket zu eröffnen.
## Sicherheitslücken
Falls du eine Sicherheitslücke findest oder dir etwas unsicher vorkommt,
zögere bitte nicht ein [Ticket zu schreiben](https://gitlab.metager.de/open-source/MetaGer/issues) oder eine Mail an [office@suma-ev.de](mailto:office@suma-ev.de) zu senden.
zögere bitte nicht eine [Nachricht zu schreiben](https://metager.de/kontakt).
## Lizenzen
......
$(document).ready(function () {
$(".amount-custom").click(function () {
setTimeout(function () {
$("#custom-amount").focus();
}, 100)
document.addEventListener("DOMContentLoaded", (event) => {
document.querySelectorAll(".amount-custom").forEach(element => {
element.onclick = (e) => {
setTimeout(() => {
document.querySelector("#custom-amount").focus();
}, 100);
}
});
});
\ No newline at end of file
......@@ -2,27 +2,27 @@
* Flag ctrlInfo is used for initial display of the navigation box
*/
var ctrlInfo = false;
$(document).ready(function () {
document.addEventListener("DOMContentLoaded", (event) => {
// Add entry point for tabbing to the first result
$('.result, .ad').first().attr("id", "results-entry");
document.querySelectorAll('.result, .ad')[0].setAttribute("id", "results-entry");
// Initially focus the searchbar
});
/**