Skip to content

Commit

Permalink
Merge pull request #10 from ricom/feature/email-filter
Browse files Browse the repository at this point in the history
Feature/email filter
  • Loading branch information
Geist5000 authored Mar 15, 2022
2 parents 52e2030 + 1132602 commit 46a09d1
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 18 deletions.
46 changes: 33 additions & 13 deletions app/Http/Controllers/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
use App\Models\EmailVerification;
use App\Models\User;
use App\Policies\UserPolicy;
use App\Rules\EmailBlockList;
use App\Services\EmailService;
use App\Services\UserService;
use Carbon\Carbon;
use Egulias\EmailValidator\EmailValidator;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\JsonResponse;
Expand All @@ -19,9 +20,6 @@
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Mail;
use Illuminate\Validation\ValidationException;
use Laravel\Passport\Bridge\AccessTokenRepository;
use Laravel\Passport\Bridge\ClientRepository;
use League\OAuth2\Server\AuthorizationServer;
use Validator;

/**
Expand All @@ -32,7 +30,7 @@ class UserController extends Controller
{

/**
* Das regex, welches Benutzt wird um sicherzustellen, dass das User Password
* Das regex, welches Benutzt wird um sicherzustellen, dass das User Password valide ist
* @var string
*/
public static $passwordRegex = "/^(?=.*[a-zäöüß])(?=.*[A-ZÄÖÜ])(?=.*\d)(?=.*[$&§+,:;=?@#|'<>.^*()%!_-])[A-Za-zäöüßÄÖÜ\d$&§+,:;=?@#|'<>.^*()%!_-].+$/";
Expand Down Expand Up @@ -66,18 +64,17 @@ public function store(Request $request, EmailService $emailService, UserService
$validated = Validator::validate($request->all(), [
"username" => ["required", "string", "unique:users"],
"password" => ["required", "string", "min:8", "max:120", "regex:" . UserController::$passwordRegex],
"email" => ["required", "email", "unique:users,email", "unique:" . EmailVerification::class . ",email"],
"email" => ["required", "email", new EmailBlockList($emailService), "unique:users,email", "unique:" . EmailVerification::class . ",email"],
"anonymous_id" => ["integer", "exists:users,id"],
], [
"password.regex" => __("passwords.invalid_regex")
]);


$u = null;
if (array_key_exists("anonymous_id", $validated)) {
$u = User::find($validated["anonymous_id"]);
if($u->anonymous){
$userService->upgradeAnonymousUser($u,$validated,$emailService);
if ($u->anonymous) {
$userService->upgradeAnonymousUser($u, $validated, $emailService);
}

} else {
Expand Down Expand Up @@ -142,7 +139,7 @@ public function update(Request $request, User $user, EmailService $emailService,
$validated = Validator::validate($request->all(), [
"username" => ["string", "unique:users"],
"password" => ["string", "min:8", "max:120", "regex:" . UserController::$passwordRegex],
// "email" => ["email", "unique:users,email", "unique:" . EmailVerification::class . ",email"]
// "email" => ["email", "unique:users,email", new EmailBlockList($emailService), "unique:" . EmailVerification::class . ",email"]
], [
"password.regex" => __("passwords.invalid_regex")
]);
Expand Down Expand Up @@ -176,8 +173,10 @@ public function checkUsername(Request $request, UserService $userService): JsonR
$validated = $request->validate([
"username" => ["string", "required"]
]);
$available = $userService->checkUsername($validated["username"]);
return response()->json(["data" => [
"available" => $userService->checkUsername($validated["username"])
"available" => $available,
"reason" => $available ? "" : "taken"
]]);

}
Expand All @@ -190,13 +189,34 @@ public function checkUsername(Request $request, UserService $userService): JsonR
* @param UserService $userService Dependency Injection
* @return JsonResponse Body enthält available attribut, welches angibt, ob die E-Mail bereits benutzt wird
*/
public function checkEmail(Request $request, UserService $userService): JsonResponse
public function checkEmail(Request $request, UserService $userService, EmailService $emailService): JsonResponse
{
$validated = $request->validate([
"email" => ["string", "required"]
]);
$reason = "";

$validEmail = filter_var($validated["email"], FILTER_VALIDATE_EMAIL);
if ($validEmail !== false) {
$allowed = $emailService->checkBlockLists($validated["email"]);
$available = false;
if ($allowed) {
$available = $userService->checkEmail($validated["email"]);
if (!$available) {
$reason = "taken";
}
} else {
$reason = "blocked";
}
} else {
$available = false;
$reason = "invalid";
}


return response()->json(["data" => [
"available" => $userService->checkEmail($validated["email"])
"available" => $available,
"reason" => $reason,
]]);

}
Expand Down
44 changes: 44 additions & 0 deletions app/Rules/EmailBlockList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace App\Rules;

use App\Services\EmailService;
use Illuminate\Contracts\Validation\Rule;

class EmailBlockList implements Rule
{


private EmailService $emailService;
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct(EmailService $emailService)
{
$this->emailService = $emailService;
}

/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
return $this->emailService->checkBlockLists($value);
}

/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return trans('validation.email_block_list');
}
}
38 changes: 37 additions & 1 deletion app/Services/EmailService.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,42 @@ public function requestEmailChangeOfUser(User $user, string $email)


// is queued because of the ShouldQueue interface of EmailVerificationEmail
Mail::to($emailVerification->email)->send(new EmailVerificationEmail($emailVerification->token,$user->username));
Mail::to($emailVerification->email)->send(new EmailVerificationEmail($emailVerification->token, $user->username));
}

/**
*
* Prüft die gegebene E-Mail und gibt an, ob sie durch die white oder blacklist verboten wird.
*
* @param string $email die zu prüfende email
* @return bool true wenn die email erlaubt ist, sonst false
*/
public function checkBlockLists(string $email): bool
{
$whitelist = config("accounts.email_whitelist");
$blacklist = config("accounts.email_blacklist");
foreach ($whitelist as $allowedRegex) {
$result = preg_match($this->regexAddDelimiter($allowedRegex), $email);
if ($result === false || $result === 0) {
return false;
}
}

foreach ($blacklist as $permittedRegex) {
$result = preg_match($this->regexAddDelimiter($permittedRegex), $email);

if ($result === 1) {
return false;
}
}

return true;
}

private function regexAddDelimiter(string $regex)
{
$needsDelimiter = !(str_starts_with($regex, "/") && str_ends_with($regex, "/"));

return ($needsDelimiter ? "/" : "") . $regex . ($needsDelimiter ? "/" : "");
}
}
17 changes: 13 additions & 4 deletions app/Services/UserService.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
class UserService
{

private EmailService $emailService;

public function __construct(EmailService $emailService)
{
$this->emailService = $emailService;
}


/** Überprüft ob der Username bereits verwendet wird
* @param string $username Der zu überprüfende Username
Expand All @@ -23,16 +30,18 @@ public function checkUsername(string $username): bool
}

/**
* Überprüft ob die E-Mail bereits verwendet wird
* Überprüft ob die E-Mail bereits verwendet wird und ob sie von der white oder blacklist geblockt wird
*
* zu verifizierende E-Mail-Adressen gelten auch als verwendet
* @param string $email Zu überprüfende E-Mail
* @return bool True, wenn die E-Mail noch verfügbar ist
*/
public function checkEmail(string $email): bool
{
return !(User::whereEmail($email)->exists() ||
EmailVerification::whereEmail($email)->exists());
return !(
User::whereEmail($email)->exists() ||
EmailVerification::whereEmail($email)->exists()
);
}

/**
Expand Down Expand Up @@ -98,7 +107,7 @@ public function upgradeAnonymousUser(User $u, array $data, EmailService $emailSe
$emailService->requestEmailChangeOfUser($u, $data["email"]);
$u->save();
return true;
}else{
} else {
return false;
}
}
Expand Down
25 changes: 25 additions & 0 deletions config/accounts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

return [
/*
* defines which email addresses are allowed.
*
* The given strings are checked against the email a user chooses to register with.
* Regex is supported.
*
* no entries results in allowing all emails which aren't blocked by the blacklist.
*
*/
"email_whitelist" => [
"^.*jade-hs.de$"
],

/*
* defines which email addresses are permitted.
*
* The given strings are checked against the email a user chooses to register with and are allowed by the whitelist.
* Regex is supported.
*/
"email_blacklist" => [
]
];
3 changes: 3 additions & 0 deletions resources/lang/en/validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@
'url' => 'The :attribute format is invalid.',
'uuid' => 'The :attribute must be a valid UUID.',

// custom
'email_block_list' => 'The :attribute :value is blocked by a white and/or blacklist',

/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
Expand Down

0 comments on commit 46a09d1

Please sign in to comment.