Ajout des différents mails, gestion des users et ajout des codes en BO

This commit is contained in:
Romain Bonhomme 2020-11-02 16:18:06 +01:00
parent 9b02fde183
commit 51a697eec9
27 changed files with 548 additions and 44 deletions

View file

@ -18,15 +18,15 @@ class EnterCodeController extends Controller
public function participate(Request $request) {
$code = $request->code;
$codeEan = null;
$settings = Settings::select('use_ean_codes')->first();
if ($settings->use_ean_codes) {
$codeEan = $request->code_ean;
$eanExist = CodesEAN::where('code', $codeEan)->count();
if ($eanExist === 0) {
if ($eanExist === 0)
return redirect()->back()->withErrors('Le code EAN entré est incorrect, veuillez réessayer.');
}
}
$gagne = false;
$gagne = true;
// TODO : Traitement du code, instant gagnant etc
if ($gagne) {
$prizeId = $request->prize;
@ -37,9 +37,8 @@ class EnterCodeController extends Controller
// Page perdu si jeu non 100% gagnant, reduction sinon
$perdant = false;
$nbDefaultPrize = Prizes::where('is_default', 1)->count();
if ($nbDefaultPrize === 0 ) {
if ($nbDefaultPrize === 0)
$perdant = true;
}
if ($perdant) {
return view('front.basic.loose');

View file

@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Mail\PasswordReset;
use App\Mail\VerifyEmail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@ -9,6 +10,7 @@ use Illuminate\Support\Str;
use App\User;
use CPCConnection;
use Exception;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
class LoginController extends Controller
@ -85,4 +87,45 @@ class LoginController extends Controller
$result = true;
return view('front.basic.confirm-email', compact('result'));
}
public function forgotPassword($token = null) {
if ($token) {
$tokenValid = false;
$user = User::where('password_token', $token)->first();
if (!$user)
return view('front.basic.forgot-password', compact('tokenValid'))->withErrors('Le lien de changement du mot de passe est incorrect.');
$tokenValid = true;
return view('front.basic.forgot-password', compact('tokenValid', 'token'));
} else {
return view('front.basic.forgot-password');
}
}
public function mailPassword(Request $request) {
$email = filter_var($request->email, FILTER_SANITIZE_STRING);
$user = User::where('email', $email)->first();
if ($user) {
$user->password_token = Str::uuid();
$user->save();
Mail::to($email)->send(new PasswordReset($user));
return redirect()->route('login')->with('success', 'Un mail de réinitialisation de votre mot de passe vous a été envoyé(e).');
} else {
return redirect()->back()->withInput($email)->withErrors("Le mail que vous avez entré n'est pas enregistré dans nos services.");
}
}
public function changePassword(Request $request) {
$request->validate([
'password' => 'required|min:8|confirmed',
]);
$user = User::where('password_token', filter_var($request->token, FILTER_SANITIZE_STRING))->first();
if (!$user)
return redirect()->back()->withErrors('Le lien de changement de votre mot de passe est incorrect, veuillez réessayer.');
$newPassword = $request->password;
$user->password = Hash::make($newPassword);
$user->password_token = null;
$user->save();
return redirect()->route('login')->with('success', 'Vous pouvez désormais vous connecter avec votre nouveau mot de passe.');
}
}

View file

@ -50,7 +50,7 @@ class RegisterController extends Controller
$request->validate([
'lastname' => 'required|string|max:255',
'firstname' => 'required|string|max:255',
'birth_date' => 'required|date|before_or_equal:' . Carbon::now()->subYear(18)->toDateString(),
'birth_date' => 'required|date|before_or_equal:' . Carbon::now()->subYears(18)->toDateString(),
'email' => 'required|string|email|max:255|unique:users|confirmed',
'password' => 'required|string|min:8|confirmed',
'address' => 'required|string|max:255',

View file

@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\User;
class VerificationController extends Controller
{
public function verifEmail($token) {
// TODO : Vérification email
$user = User::where('email_verify_token', $token)->first();
if ($user != null) {
$user->email_verified_at = now();
$user->save();
return true;
} else {
return false;
}
}
}

View file

@ -2,7 +2,10 @@
namespace App\Http\Controllers;
use App\Mail\WinningProof;
use App\Models\Settings;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class WinningProofController extends Controller
{
@ -38,18 +41,28 @@ class WinningProofController extends Controller
'barcode' => 'required|mimes:jpeg,png,jpg,pdf|max:1536',
]);
// TODO : Ajouter les infos à la table Participation
// TODO : Ajouter les infos à la table Participation et envoyé les infos code unique et ean si utilisé au mail
// TODO : Enregistrement des images dans des dossiers /fichiers/preuve-gain/{id-participaction}/{nom-fichier}-[sticker/ticket/barcode].png
$participationId = 364581; // Pour test, à supprimer
$stickerFileName = $participationId . '-sticker.' . $sticker->extension();
$sticker->move(public_path('fichiers/preuve-de-gain/' . $participationId . '/'), $stickerFileName);
$stickerPath = 'fichiers/preuve-de-gain/' . $participationId . '/' . $stickerFileName;
$ticketFileName = $participationId . '-ticket.' . $ticket->extension();
$ticket->move(public_path('fichiers/preuve-de-gain/' . $participationId . '/'), $ticketFileName);
$ticketPath = 'fichiers/preuve-de-gain/' . $participationId . '/' . $ticketFileName;
$barcodeFileName = $participationId . '-code-barre.' . $barcode->extension();
$barcode->move(public_path('fichiers/preuve-de-gain/' . $participationId . '/'), $barcodeFileName);
$barcodePath = 'fichiers/preuve-de-gain/' . $participationId . '/' . $barcodeFileName;
$settings = Settings::find(1);
$mails = json_decode($settings->notification_emails);
foreach ($mails as $mail) {
// TODO : Donné la participation au mail
Mail::to($mail)->send(new WinningProof($stickerPath, $ticketPath, $barcodePath));
}
return view('front.basic.replay');
}

View file

@ -0,0 +1,26 @@
<?php
namespace App\Http\Controllers\bo;
use App\Http\Controllers\Controller;
use App\Jobs\ProcessUniqueCode;
use App\Models\Codes;
use Illuminate\Http\Request;
class CodesController extends Controller
{
public function index() {
$nbCodeBase = Codes::all()->count();
$nbCodeUsed = Codes::where('code_used', 1)->count();
return view('bo.codes.index', compact('nbCodeBase', 'nbCodeUsed'));
}
public function generate(Request $request) {
$quantity = $request->quantity;
$codeLength = $request->code_length;
ProcessUniqueCode::dispatch($quantity, $codeLength);
return redirect()->back()->with('success', "La génération à commencée, un mail de notification sera envoyé à l'adresse " . config('mail.MAIL_ADMIN') . " lorsque le traitement sera terminé.");
}
}

View file

@ -0,0 +1,80 @@
<?php
namespace App\Jobs;
use App\Mail\CodeGenerationEnd;
use App\Mail\JobFailed;
use App\Models\Codes;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class ProcessUniqueCode implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $quantity;
private $length;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($quantity, $length) {
$this->quantity = $quantity;
$this->length = $length;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
set_time_limit(0);
for ($ib = 1; $ib <= $this->quantity;) {
try {
$code = new Codes();
$code->code_unique = $this->getCode($this->length);
$code->code_used = 0;
$code->date_creation = now();
$code->save();
if ($code){
$ib++;
}
} catch (\PDOException $e) {
if (!strpos($e->getMessage(), 'Duplicate entry')){
die($e->getMessage());
}
}
}
// ---- Fin de la génération
Mail::to(config('mail.MAIL_ADMIN'))->send(new CodeGenerationEnd($this->quantity));
}
private function getCode($car){
$chaine = "ABCDEFGHJKMNPQRSTUWXYZ123456789"; // Caractères autorisés
$valprec = "";
$string = "";
srand();
for ($i = 0; $i < $car;) {
$val = $chaine[rand() % strlen($chaine)];
if ($val != $valprec){
$string .= $val;
$valprec = $val;
$i++;
}
}
return $string;
}
public function failed(Exception $exception) {
Mail::to(config('mail.MAIL_ADMIN'))->send(new JobFailed("ProcessUniqueCode", ['message' => $exception->getMessage(), 'trace' => $exception->getTraceAsString()]));
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class CodeGenerationEnd extends Mailable
{
use Queueable, SerializesModels;
private $quantity;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($quantity) {
$this->quantity = $quantity;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->subject('Fin de génération des codes uniques')->view('bo.mails.generate-end-email')->with('quantity', $this->quantity);
}
}

29
app/Mail/JobFailed.php Normal file
View file

@ -0,0 +1,29 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class JobFailed extends Mailable
{
use Queueable, SerializesModels;
public $job;
public $exception;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($job, $exception)
{
$this->job = $job;
$this->exception = $exception;
}
/**
* Build the message.
*
* @return $this
*/
public function build() {
return $this->subject('[JOB FAILED] Une erreur est survenue pendant le job : ' . $this->job)->view('bo.mails.job-failed');
}
}

View file

@ -0,0 +1,35 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class PasswordReset extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
protected $user;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($user)
{
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->subject('Changement de votre mot de passe')->view('front.basic.password-email')->with('user', $this->user);
}
}

View file

@ -9,7 +9,7 @@ use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Auth;
class VerifyEmail extends Mailable
class VerifyEmail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;

37
app/Mail/WinningProof.php Normal file
View file

@ -0,0 +1,37 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class WinningProof extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
protected $sticker, $ticket, $barcode;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($sticker, $ticket, $barcode)
{
$this->sticker = $sticker;
$this->ticket = $ticket;
$this->barcode = $barcode;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('front.basic.winning-proof-email')->attach($this->sticker)->attach($this->ticket)->attach($this->barcode);
}
}

11
app/Models/Codes.php Normal file
View file

@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Codes extends Model
{
protected $fillable = ['code_unique', 'code_used', 'date_creation'];
public $timestamps = false;
}

View file

@ -2,7 +2,11 @@
namespace App\Providers;
use App\Models\GainView;
use App\Models\Settings;
use Illuminate\Queue\Events\JobProcessed;
use Illuminate\Queue\Events\JobProcessing;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

View file

@ -15,6 +15,9 @@ return [
'default' => env('MAIL_MAILER', 'smtp'),
// Mail admin pour l'envoi de mail comme la fin de la génération des codes uniques
'MAIL_ADMIN' => env('MAIL_ADMIN'),
/*
|--------------------------------------------------------------------------
| Mailer Configurations

View file

@ -30,6 +30,7 @@ class CreateUsersTable extends Migration
$table->string('phone')->nullable();
$table->string('email_verify_token');
$table->boolean('email_verified')->default(0);
$table->string('password_token')->nullable();
$table->integer('role')->default(2);
$table->rememberToken();
$table->timestamps();

View file

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateJobsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('jobs');
}
}

View file

@ -0,0 +1,41 @@
@extends('layouts.bo')
@section('content')
<div class="card">
<div class="card-header">
Gestion des codes uniques
</div>
<form action="{{route('bo.codes')}}" method="POST" enctype="multipart/form-data">
@csrf
<div class="card-body">
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<p>Nombre de code(s) en base : {{$nbCodeBase}}</p>
<p>Nombre de code(s) utilisé(s) : {{$nbCodeUsed}}</p>
<hr/>
<div class="form-group row">
<label class="col-form-label col-md-3">Nombre de codes à générer <span class="required-asterisk">*</span></label>
<input class="form-control col-md-3" type="number" name="quantity" min="0">
<label class="col-form-label col-md-3">Longueur des codes <span class="required-asterisk">*</span></label>
<input class="form-control col-md-3" type="number" name="code_length" min="0">
</div>
</div>
<div class="card-footer text-center">
<button type="submit" class="btn btn-success"><i class="fas fa-cog"></i> Générer</button>
</div>
</form>
</div>
@endsection

View file

@ -0,0 +1 @@
<p>Génération des {{$quantity}} codes uniques terminés sur le jeu {{$settingsGlobal->name}}.</p>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<p>
Job : {{ $job }} <br><br>
Exception : {{ $exception['message'] }} <br><br>
Trace : <br>
{{ $exception['trace'] }}
</p>
</body>
</html>

View file

@ -0,0 +1,92 @@
@extends('front.basic.layout')
@section('title', 'Mot de passe oublié')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
@if (!isset($tokenValid) || !$tokenValid)
<div class="card-header">Mot de passe oublié</div>
<div class="card-body">
<form method="POST" action="{{ route('mail-password') }}">
@method('PUT')
@csrf
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">Adresse email</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">Envoyer</button>
</div>
</div>
</form>
</div>
@elseif ($tokenValid)
<div class="card-header">Changement de votre mot de passe</div>
<div class="card-body">
<form method="POST" action="{{ route('change-password', $token) }}">
@method('PUT')
@csrf
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<div class="form-group row">
<label class="col-md-6 col-form-label">Nouveau mot de passe <span class="required-asterisk">*</span></label>
<input type="password" name="password" class="form-control col-md-6" placeholder="Votre nouveau mot de passe" required>
</div>
<div class="form-group row">
<label class="col-md-6 col-form-label">Confirmer le nouveau mot de passe <span class="required-asterisk">*</span></label>
<input id="password-confirm" type="password" class="form-control col-md-6"
name="password_confirmation" required autocomplete="new-password" placeholder="Confirmer votre nouveau mot de passe">
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<input type="hidden" name="token" value="{{$token}}">
<button type="submit" class="btn btn-primary">Envoyer</button>
</div>
</div>
</form>
</div>
@endif
</div>
</div>
</div>
</div>
@endsection

View file

@ -6,5 +6,5 @@
@section('content')
<p>Vous avez gagné {{$prize->label_one}} !</p>
<p><a href="{{route('saisir-code')}}" class="btn btn-success">Rejouer !</a></p>
<p><a href="{{route('winning-proof')}}" class="btn btn-success">Envoyer mes preuves de gain</a></p>
@endsection

View file

@ -7,7 +7,7 @@
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Login') }}</div>
<div class="card-header">Connexion<a href="{{route('inscription')}}" class="btn btn-primary btn-sm float-right">Inscription</a></div>
<div class="card-body">
<form method="POST" action="{{ route('authenticate') }}">
@ -28,7 +28,7 @@
@endif
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<label for="email" class="col-md-4 col-form-label text-md-right">Adresse email</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
@ -36,7 +36,7 @@
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<label for="password" class="col-md-4 col-form-label text-md-right">Mot de passe</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
@ -49,7 +49,7 @@
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
<label class="form-check-label" for="remember">
{{ __('Remember Me') }}
Se souvenir de moi
</label>
</div>
</div>
@ -57,16 +57,8 @@
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
</button>
<a href="{{route('inscription')}}" class="btn btn-primary">Inscription</a>
@if (Route::has('password.request'))
<a class="btn btn-link" href="{{ route('password.request') }}">
{{ __('Forgot Your Password?') }}
</a>
@endif
<button type="submit" class="btn btn-primary">Connexion</button>
<a class="btn btn-link" href="{{route('forgot-password')}}">Mot de passe oublié ?</a>
</div>
</div>
</form>

View file

@ -0,0 +1,5 @@
<p>Bonjour {{$user->firstname}},</p>
<p>Nous avons reçu une demande de changement de mot de passe pour votre compte {{$settingsGlobal->name}}.</p>
<p>Si vous êtes à l'origine de cette demande, veuillez cliquer sur le lien ci-dessous pour poursuivre votre changement :</p>
<a href="{{route('forgot-password', $user->password_token)}}">Changer mon mot de passe</a>
<p>{{$settingsGlobal->name}} - {{$settingsGlobal->company}}</p>

View file

@ -0,0 +1,19 @@
<p>Bonjour,</p>
<p>Vous trouverez en PJ les preuves de gain du joueur suivant :</p>
<p>
<b>Lot : {{$prize->label_one ?? ''}}</b><br/>
{{Auth::user()->lastname}} {{Auth::user()->firstname}}<br/>
{{Auth::user()->address}}<br/>
@if (Auth::user()->address2 !== null)
{{Auth::user()->address2}}<br/>
@endif
{{Auth::user()->postal_code}} {{Auth::user()->town}} - {{Auth::user()->country}}<br/>
{{Auth::user()->email}}
</p>
<p>Codes utilisés :</p>
<p>
@if (isset($codeEan))
Code On Pack : {{$codeEan}}<br/>
@endif
Code Unique : {{$codeUnique ?? ''}}
</p>

View file

@ -85,6 +85,7 @@
</li>
<a class="nav-link" href="{{route('bo.instant-win')}}">Instant gagnants</a>
<a class="nav-link" href="{{route('bo.codes-ean')}}">Code EAN</a>
<!-- TODO : Social share et liste des gagnants -->
<a class="nav-link" href="#_">Social share</a>
<a class="nav-link" href="#_">Liste des gagnants</a>
<a class="nav-link" href="{{route('bo.banned-ip')}}">IP Bannies</a>
@ -103,6 +104,7 @@
<a class="dropdown-item" href="{{route('bo.faq-questions')}}">Questions</a>
</div>
</li>
<a class="nav-link" href="{{route('bo.codes')}}">Codes uniques</a>
</nav>
</div>
<div class="col-md-10">

View file

@ -24,6 +24,9 @@ Route::get('/faq', 'FAQController@index')->name('faq');
Route::get('/comment-jouer', 'HowToPlayController@index')->name('comment-jouer');
Route::get('/les-gains', 'GainsController@index')->name('les-gains');
Route::get('/confirm-email/{verifyToken}', 'LoginController@confirmEmail')->name('confirm-email');
Route::get('/mdp-oublie/{token?}', 'LoginController@forgotPassword')->name('forgot-password');
Route::put('/mail-mdp', 'LoginController@mailPassword')->name('mail-password');
Route::put('/change-mdp', 'LoginController@changePassword')->name('change-password');
// Front nécessitant d'être connecté
Route::get('/saisir-code', 'EnterCodeController@index')->name('saisir-code')->middleware('auth');
@ -77,4 +80,7 @@ Route::namespace('Bo')
Route::get('/faq-questions', 'FaqQuestionsController@index')->name('faq-questions');
Route::post('/ajax/delete-faq-question', 'FaqQuestionsController@destroy');
Route::post('/ajax/save-faq-question', 'FaqQuestionsController@saveDatas');
// Codes uniques
Route::get('/codes', 'CodesController@index')->name('codes');
Route::post('/codes', 'CodesController@generate')->name('generate-codes');
});