From b7a6fbc9cc5d9d601c60e6ed4123e021e4aeaf5b Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Wed, 11 Jul 2018 18:51:39 +0200 Subject: Added/fixed email verification --- app/Http/Controllers/Auth/RegisterController.php | 45 +++++++++++++++++++--- app/Jobs/SendVerificationEmail.php | 39 +++++++++++++++++++ app/Mail/EmailVerification.php | 36 +++++++++++++++++ app/User.php | 2 +- .../2014_10_12_000000_create_users_table.php | 2 + public/js/app.js | 2 +- resources/views/confirmEmail.blade.php | 16 ++++++++ resources/views/email/verify.blade.php | 3 ++ resources/views/verificationSuccess.blade.php | 17 ++++++++ routes/web.php | 4 ++ 10 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 app/Jobs/SendVerificationEmail.php create mode 100644 app/Mail/EmailVerification.php create mode 100644 resources/views/confirmEmail.blade.php create mode 100644 resources/views/email/verify.blade.php create mode 100644 resources/views/verificationSuccess.blade.php diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index f922f9f..2994499 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -2,11 +2,14 @@ namespace App\Http\Controllers\Auth; -use App\User; use App\Http\Controllers\Controller; +use App\Jobs\SendVerificationEmail; +use App\User; +use Illuminate\Auth\Events\Registered; +use Illuminate\Foundation\Auth\RegistersUsers; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; -use Illuminate\Foundation\Auth\RegistersUsers; class RegisterController extends Controller { @@ -19,7 +22,7 @@ class RegisterController extends Controller | validation and creation. By default this controller uses a trait to | provide this functionality without requiring any additional code. | - */ + */ use RegistersUsers; @@ -64,7 +67,7 @@ class RegisterController extends Controller protected function create(array $data) { $hashedPassword = Hash::make($data['password']); - $previousHash = User::select('hash')->orderBy('id','desc')->first()->hash; + $previousHash = User::select('hash')->orderBy('id', 'desc')->first()->hash; $summedHash = Hash::make($previousHash . $data['name'] . $data['email'] . 'password' . $hashedPassword); // Hash::check to verify return User::create([ @@ -72,7 +75,39 @@ class RegisterController extends Controller 'email' => $data['email'], 'password' => $hashedPassword, 'prevHash' => $previousHash, - 'hash' => $summedHash + 'hash' => $summedHash, + 'email_token' => base64_encode($data['email']), ]); } + + /** + * Handle a registration request for the application. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + + public function register(Request $request) + { + $this->validator($request->all())->validate(); + event(new Registered($user = $this->create($request->all()))); + dispatch(new SendVerificationEmail($user)); + return view('confirmEmail'); + } + + /** + * Handle a registration request for the application. + * + * @param $token + * @return \Illuminate\Http\Response + */ + public function verifyEmail($token) + { + $user = User::where('email_token', $token)->first(); + $user->verified = 1; + if ($user->save()) { + return view('verificationSuccess', ['user' => $user]); + } + } + } diff --git a/app/Jobs/SendVerificationEmail.php b/app/Jobs/SendVerificationEmail.php new file mode 100644 index 0000000..0a71f05 --- /dev/null +++ b/app/Jobs/SendVerificationEmail.php @@ -0,0 +1,39 @@ +user = $user; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + $email = new EmailVerification($this->user); + Mail::to($this->user->email)->send($email); + } +} diff --git a/app/Mail/EmailVerification.php b/app/Mail/EmailVerification.php new file mode 100644 index 0000000..4f393ac --- /dev/null +++ b/app/Mail/EmailVerification.php @@ -0,0 +1,36 @@ +user = $user; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + return $this->view('email.verify')->with([ + 'email_token' => $this->user->email_token, + ]); + } +} diff --git a/app/User.php b/app/User.php index f263c47..9dcf98e 100644 --- a/app/User.php +++ b/app/User.php @@ -13,7 +13,7 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'name', 'email', 'password', 'prevHash', 'hash', + 'name', 'email', 'password', 'prevHash', 'hash', 'email_token' ]; /** diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 1846db1..ab3cbc1 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -21,6 +21,8 @@ class CreateUsersTable extends Migration $table->string('prevHash', 60)->unique(); $table->string('hash', 60)->unique(); $table->string('api_token')->default(""); + $table->tinyInteger('verified')->default(0); + $table->string('email_token')->nullable(); $table->rememberToken(); $table->timestamps(); }); diff --git a/public/js/app.js b/public/js/app.js index 3eb309f..24bab84 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -347,7 +347,7 @@ eval("$(\"#avatarFile\").on(\"change\", function () {\n var preview = documen /* 42 */ /***/ (function(module, exports) { -eval("// var openpgp = window.openpgp;\n\n// var options = {\n// userIds: [{ name:'Marvin Borner', email:'test@test.de' }], // multiple user IDs\n// numBits: 4096, // RSA key size\n// passphrase: 'cool password of private key'\n// };\n\n// openpgp.generateKey(options).then(function(key) {\n// var privateKey = key.privateKeyArmored; // '-----BEGIN PGP PRIVATE KEY BLOCK ... '\n// var publicKey = key.publicKeyArmored; // '-----BEGIN PGP PUBLIC KEY BLOCK ... '\n\n// console.log(publicKey);\n// console.log(privateKey);\n// });\n\n// $.ajax({\n// type: \"POST\",\n// url: \"keys/public/1\",\n// data: {\n// \"key\": \"test_key_2\"\n// },\n// cache: false,\n// success: (results) => {\n// console.log(results);\n// }\n// });\n\n\nvar socket = io('http://127.0.0.1:8890', {\n transports: ['websocket']\n});\nsocket.on('message', function (data) {\n data = JSON.parse(data);\n $(\"#messages\").append(\"
\" + data.user + \" : \" + data.message + \"
\");\n});\n\n$('input.send').click(function (e) {\n e.preventDefault();\n sendMessage();\n});\n\nfunction sendMessage() {\n var message = $('input.message').val();\n $('input.message').val(\"\");\n $.ajax({\n type: \"POST\",\n url: \"sendMessage\",\n data: {\n \"message\": message\n },\n cache: false\n });\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvYXNzZXRzL2pzL2NoYXQuanM/NjE1NCJdLCJuYW1lcyI6WyJzb2NrZXQiLCJpbyIsInRyYW5zcG9ydHMiLCJvbiIsImRhdGEiLCJKU09OIiwicGFyc2UiLCIkIiwiYXBwZW5kIiwidXNlciIsIm1lc3NhZ2UiLCJjbGljayIsImUiLCJwcmV2ZW50RGVmYXVsdCIsInNlbmRNZXNzYWdlIiwidmFsIiwiYWpheCIsInR5cGUiLCJ1cmwiLCJjYWNoZSJdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUtBLElBQUlBLFNBQVNDLEdBQUcsdUJBQUgsRUFBNEI7QUFDckNDLGdCQUFZLENBQUMsV0FBRDtBQUR5QixDQUE1QixDQUFiO0FBR0FGLE9BQU9HLEVBQVAsQ0FBVSxTQUFWLEVBQXFCLFVBQUNDLElBQUQsRUFBVTtBQUMzQkEsV0FBT0MsS0FBS0MsS0FBTCxDQUFXRixJQUFYLENBQVA7QUFDQUcsTUFBRSxXQUFGLEVBQWVDLE1BQWYsQ0FBc0IsUUFBUUosS0FBS0ssSUFBYixHQUFvQixLQUFwQixHQUE0QkwsS0FBS00sT0FBakMsR0FBMkMsTUFBakU7QUFDSCxDQUhEOztBQUtBSCxFQUFFLFlBQUYsRUFBZ0JJLEtBQWhCLENBQXNCLFVBQUNDLENBQUQsRUFBTztBQUN6QkEsTUFBRUMsY0FBRjtBQUNBQztBQUNILENBSEQ7O0FBS0EsU0FBU0EsV0FBVCxHQUF1QjtBQUNuQixRQUFJSixVQUFVSCxFQUFFLGVBQUYsRUFBbUJRLEdBQW5CLEVBQWQ7QUFDQVIsTUFBRSxlQUFGLEVBQW1CUSxHQUFuQixDQUF1QixFQUF2QjtBQUNBUixNQUFFUyxJQUFGLENBQU87QUFDSEMsY0FBTSxNQURIO0FBRUhDLGFBQUssYUFGRjtBQUdIZCxjQUFNO0FBQ0YsdUJBQVdNO0FBRFQsU0FISDtBQU1IUyxlQUFPO0FBTkosS0FBUDtBQVFIIiwiZmlsZSI6IjQyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdmFyIG9wZW5wZ3AgPSB3aW5kb3cub3BlbnBncDtcblxuLy8gdmFyIG9wdGlvbnMgPSB7XG4vLyAgICAgdXNlcklkczogW3sgbmFtZTonTWFydmluIEJvcm5lcicsIGVtYWlsOid0ZXN0QHRlc3QuZGUnIH1dLCAvLyBtdWx0aXBsZSB1c2VyIElEc1xuLy8gICAgIG51bUJpdHM6IDQwOTYsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSU0Ega2V5IHNpemVcbi8vICAgICBwYXNzcGhyYXNlOiAnY29vbCBwYXNzd29yZCBvZiBwcml2YXRlIGtleSdcbi8vIH07XG5cbi8vIG9wZW5wZ3AuZ2VuZXJhdGVLZXkob3B0aW9ucykudGhlbihmdW5jdGlvbihrZXkpIHtcbi8vICAgICB2YXIgcHJpdmF0ZUtleSA9IGtleS5wcml2YXRlS2V5QXJtb3JlZDsgLy8gJy0tLS0tQkVHSU4gUEdQIFBSSVZBVEUgS0VZIEJMT0NLIC4uLiAnXG4vLyAgICAgdmFyIHB1YmxpY0tleSA9IGtleS5wdWJsaWNLZXlBcm1vcmVkOyAgIC8vICctLS0tLUJFR0lOIFBHUCBQVUJMSUMgS0VZIEJMT0NLIC4uLiAnXG5cbi8vICAgICBjb25zb2xlLmxvZyhwdWJsaWNLZXkpO1xuLy8gICAgIGNvbnNvbGUubG9nKHByaXZhdGVLZXkpO1xuLy8gfSk7XG5cbi8vICQuYWpheCh7XG4vLyAgICAgdHlwZTogXCJQT1NUXCIsXG4vLyAgICAgdXJsOiBcImtleXMvcHVibGljLzFcIixcbi8vICAgICBkYXRhOiB7XG4vLyAgICAgICAgIFwia2V5XCI6IFwidGVzdF9rZXlfMlwiXG4vLyAgICAgfSxcbi8vICAgICBjYWNoZTogZmFsc2UsXG4vLyAgICAgc3VjY2VzczogKHJlc3VsdHMpID0+IHtcbi8vICAgICAgICAgY29uc29sZS5sb2cocmVzdWx0cyk7XG4vLyAgICAgfVxuLy8gfSk7XG5cblxuXG5cbnZhciBzb2NrZXQgPSBpbygnaHR0cDovLzEyNy4wLjAuMTo4ODkwJywge1xuICAgIHRyYW5zcG9ydHM6IFsnd2Vic29ja2V0J11cbn0pO1xuc29ja2V0Lm9uKCdtZXNzYWdlJywgKGRhdGEpID0+IHtcbiAgICBkYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAkKFwiI21lc3NhZ2VzXCIpLmFwcGVuZChcIjxwPlwiICsgZGF0YS51c2VyICsgXCIgOiBcIiArIGRhdGEubWVzc2FnZSArIFwiPC9wPlwiKTtcbn0pO1xuXG4kKCdpbnB1dC5zZW5kJykuY2xpY2soKGUpID0+IHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgc2VuZE1lc3NhZ2UoKTtcbn0pO1xuXG5mdW5jdGlvbiBzZW5kTWVzc2FnZSgpIHtcbiAgICB2YXIgbWVzc2FnZSA9ICQoJ2lucHV0Lm1lc3NhZ2UnKS52YWwoKTtcbiAgICAkKCdpbnB1dC5tZXNzYWdlJykudmFsKFwiXCIpO1xuICAgICQuYWpheCh7XG4gICAgICAgIHR5cGU6IFwiUE9TVFwiLFxuICAgICAgICB1cmw6IFwic2VuZE1lc3NhZ2VcIixcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgXCJtZXNzYWdlXCI6IG1lc3NhZ2VcbiAgICAgICAgfSxcbiAgICAgICAgY2FjaGU6IGZhbHNlXG4gICAgfSk7XG59XG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vcmVzb3VyY2VzL2Fzc2V0cy9qcy9jaGF0LmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///42\n"); +eval("// var openpgp = window.openpgp;\n\n// var options = {\n// userIds: [{ name:'Marvin Borner', email:'test@test.de' }], // multiple user IDs\n// numBits: 4096, // RSA key size\n// passphrase: 'cool password of private key'\n// };\n\n// openpgp.generateKey(options).then(function(key) {\n// var privateKey = key.privateKeyArmored; // '-----BEGIN PGP PRIVATE KEY BLOCK ... '\n// var publicKey = key.publicKeyArmored; // '-----BEGIN PGP PUBLIC KEY BLOCK ... '\n\n// console.log(publicKey);\n// console.log(privateKey);\n// });\n\n// $.ajax({\n// type: \"POST\",\n// url: \"keys/public/1\",\n// data: {\n// \"key\": \"test_key_2\"\n// },\n// cache: false,\n// success: (results) => {\n// console.log(results);\n// }\n// });\n\n\nvar socket = io('http://127.0.0.1:8890', {\n transports: ['websocket']\n});\nsocket.on('message', function (data) {\n data = JSON.parse(data);\n $(\"#messages\").append(\"\" + data.user + \" : \" + data.message + \"
\");\n});\n\n$('input.send').click(function (e) {\n e.preventDefault();\n sendMessage();\n});\n\nfunction sendMessage() {\n var message = $('input.message').val();\n $('input.message').val(\"\");\n $.ajax({\n type: \"POST\",\n url: \"sendMessage\",\n data: {\n \"message\": message\n },\n cache: false\n });\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvYXNzZXRzL2pzL2NoYXQuanM/NjE1NCJdLCJuYW1lcyI6WyJzb2NrZXQiLCJpbyIsInRyYW5zcG9ydHMiLCJvbiIsImRhdGEiLCJKU09OIiwicGFyc2UiLCIkIiwiYXBwZW5kIiwidXNlciIsIm1lc3NhZ2UiLCJjbGljayIsImUiLCJwcmV2ZW50RGVmYXVsdCIsInNlbmRNZXNzYWdlIiwidmFsIiwiYWpheCIsInR5cGUiLCJ1cmwiLCJjYWNoZSJdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUlBLElBQUlBLFNBQVNDLEdBQUcsdUJBQUgsRUFBNEI7QUFDckNDLGdCQUFZLENBQUMsV0FBRDtBQUR5QixDQUE1QixDQUFiO0FBR0FGLE9BQU9HLEVBQVAsQ0FBVSxTQUFWLEVBQXFCLFVBQUNDLElBQUQsRUFBVTtBQUMzQkEsV0FBT0MsS0FBS0MsS0FBTCxDQUFXRixJQUFYLENBQVA7QUFDQUcsTUFBRSxXQUFGLEVBQWVDLE1BQWYsQ0FBc0IsUUFBUUosS0FBS0ssSUFBYixHQUFvQixLQUFwQixHQUE0QkwsS0FBS00sT0FBakMsR0FBMkMsTUFBakU7QUFDSCxDQUhEOztBQUtBSCxFQUFFLFlBQUYsRUFBZ0JJLEtBQWhCLENBQXNCLFVBQUNDLENBQUQsRUFBTztBQUN6QkEsTUFBRUMsY0FBRjtBQUNBQztBQUNILENBSEQ7O0FBS0EsU0FBU0EsV0FBVCxHQUF1QjtBQUNuQixRQUFJSixVQUFVSCxFQUFFLGVBQUYsRUFBbUJRLEdBQW5CLEVBQWQ7QUFDQVIsTUFBRSxlQUFGLEVBQW1CUSxHQUFuQixDQUF1QixFQUF2QjtBQUNBUixNQUFFUyxJQUFGLENBQU87QUFDSEMsY0FBTSxNQURIO0FBRUhDLGFBQUssYUFGRjtBQUdIZCxjQUFNO0FBQ0YsdUJBQVdNO0FBRFQsU0FISDtBQU1IUyxlQUFPO0FBTkosS0FBUDtBQVFIIiwiZmlsZSI6IjQyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdmFyIG9wZW5wZ3AgPSB3aW5kb3cub3BlbnBncDtcblxuLy8gdmFyIG9wdGlvbnMgPSB7XG4vLyAgICAgdXNlcklkczogW3sgbmFtZTonTWFydmluIEJvcm5lcicsIGVtYWlsOid0ZXN0QHRlc3QuZGUnIH1dLCAvLyBtdWx0aXBsZSB1c2VyIElEc1xuLy8gICAgIG51bUJpdHM6IDQwOTYsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSU0Ega2V5IHNpemVcbi8vICAgICBwYXNzcGhyYXNlOiAnY29vbCBwYXNzd29yZCBvZiBwcml2YXRlIGtleSdcbi8vIH07XG5cbi8vIG9wZW5wZ3AuZ2VuZXJhdGVLZXkob3B0aW9ucykudGhlbihmdW5jdGlvbihrZXkpIHtcbi8vICAgICB2YXIgcHJpdmF0ZUtleSA9IGtleS5wcml2YXRlS2V5QXJtb3JlZDsgLy8gJy0tLS0tQkVHSU4gUEdQIFBSSVZBVEUgS0VZIEJMT0NLIC4uLiAnXG4vLyAgICAgdmFyIHB1YmxpY0tleSA9IGtleS5wdWJsaWNLZXlBcm1vcmVkOyAgIC8vICctLS0tLUJFR0lOIFBHUCBQVUJMSUMgS0VZIEJMT0NLIC4uLiAnXG5cbi8vICAgICBjb25zb2xlLmxvZyhwdWJsaWNLZXkpO1xuLy8gICAgIGNvbnNvbGUubG9nKHByaXZhdGVLZXkpO1xuLy8gfSk7XG5cbi8vICQuYWpheCh7XG4vLyAgICAgdHlwZTogXCJQT1NUXCIsXG4vLyAgICAgdXJsOiBcImtleXMvcHVibGljLzFcIixcbi8vICAgICBkYXRhOiB7XG4vLyAgICAgICAgIFwia2V5XCI6IFwidGVzdF9rZXlfMlwiXG4vLyAgICAgfSxcbi8vICAgICBjYWNoZTogZmFsc2UsXG4vLyAgICAgc3VjY2VzczogKHJlc3VsdHMpID0+IHtcbi8vICAgICAgICAgY29uc29sZS5sb2cocmVzdWx0cyk7XG4vLyAgICAgfVxuLy8gfSk7XG5cblxuXG52YXIgc29ja2V0ID0gaW8oJ2h0dHA6Ly8xMjcuMC4wLjE6ODg5MCcsIHtcbiAgICB0cmFuc3BvcnRzOiBbJ3dlYnNvY2tldCddXG59KTtcbnNvY2tldC5vbignbWVzc2FnZScsIChkYXRhKSA9PiB7XG4gICAgZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgJChcIiNtZXNzYWdlc1wiKS5hcHBlbmQoXCI8cD5cIiArIGRhdGEudXNlciArIFwiIDogXCIgKyBkYXRhLm1lc3NhZ2UgKyBcIjwvcD5cIik7XG59KTtcblxuJCgnaW5wdXQuc2VuZCcpLmNsaWNrKChlKSA9PiB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHNlbmRNZXNzYWdlKCk7XG59KTtcblxuZnVuY3Rpb24gc2VuZE1lc3NhZ2UoKSB7XG4gICAgdmFyIG1lc3NhZ2UgPSAkKCdpbnB1dC5tZXNzYWdlJykudmFsKCk7XG4gICAgJCgnaW5wdXQubWVzc2FnZScpLnZhbChcIlwiKTtcbiAgICAkLmFqYXgoe1xuICAgICAgICB0eXBlOiBcIlBPU1RcIixcbiAgICAgICAgdXJsOiBcInNlbmRNZXNzYWdlXCIsXG4gICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIFwibWVzc2FnZVwiOiBtZXNzYWdlXG4gICAgICAgIH0sXG4gICAgICAgIGNhY2hlOiBmYWxzZVxuICAgIH0pO1xufVxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3Jlc291cmNlcy9hc3NldHMvanMvY2hhdC5qcyJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///42\n"); /***/ }), /* 43 */ diff --git a/resources/views/confirmEmail.blade.php b/resources/views/confirmEmail.blade.php new file mode 100644 index 0000000..1de32c2 --- /dev/null +++ b/resources/views/confirmEmail.blade.php @@ -0,0 +1,16 @@ +@extends('layouts.app') @section('content') + +