diff --git a/app/Activity.php b/app/Activity.php index 2a5ced6..41820a5 100644 --- a/app/Activity.php +++ b/app/Activity.php @@ -35,7 +35,7 @@ class Activity extends Model ]; protected $fillable = [ - 'account_id', 'website_id', 'type' + 'account_id', 'website_id', 'type', 'login_key' ]; public function account() diff --git a/app/Console/Commands/MakeLogin.php b/app/Console/Commands/MakeLogin.php index 5071da4..cf6b5bb 100644 --- a/app/Console/Commands/MakeLogin.php +++ b/app/Console/Commands/MakeLogin.php @@ -3,6 +3,9 @@ namespace App\Console\Commands; use App\Account; +use App\Activity; +use App\Enums\ActivityType; +use Illuminate\Support\Str; use Illuminate\Console\Command; class MakeLogin extends Command @@ -67,8 +70,14 @@ private function handleUserEmail() private function makeMagicLink(Account $account) { - return \URL::temporarySignedRoute('login.verify', now()->addDay(), [ - 'account' => $account->id, - ]); + $activity = new Activity; + + $activity->account_id = $account->id; + $activity->type = ActivityType::LoginRequested; + $activity->login_key = Str::uuid(); + + $activity->saveOrFail(); + + return route('login.verify', [$account->account->id, $activity->login_key]); } } diff --git a/app/Console/Commands/SendLogin.php b/app/Console/Commands/SendLogin.php index 48f1564..e365cf4 100644 --- a/app/Console/Commands/SendLogin.php +++ b/app/Console/Commands/SendLogin.php @@ -3,7 +3,6 @@ namespace App\Console\Commands; use App\Account; -use App\Mail\VerifyLogin; use App\Events\LoginRequest; use Illuminate\Console\Command; @@ -71,11 +70,6 @@ private function handleUserID() private function sendEmail(Account $account) { - $signedURL = \URL::temporarySignedRoute('login.verify', now()->addDay(), [ - 'account' => $account->id, - ]); - - \Mail::to($account->email) - ->send(new VerifyLogin($signedURL)); + event(new LoginRequest($account)); } } diff --git a/app/Enums/ActivityType.php b/app/Enums/ActivityType.php index 293228a..9e6f72a 100644 --- a/app/Enums/ActivityType.php +++ b/app/Enums/ActivityType.php @@ -6,8 +6,12 @@ /** * @method static static CreditExhausted() + * @method static static LoginRequested() + * @method static static WebsiteVerification() */ final class ActivityType extends Enum { const CreditExhausted = 0; + const LoginRequested = 1; + const WebsiteVerification = 2; } diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 2d2d160..2278519 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Account; +use App\Activity; use App\Events\LoginRequest; class AuthController extends Controller @@ -28,9 +29,14 @@ public function processLogin() ]); } - public function loginUser(Account $account) + public function loginUser(Account $account, $loginKey) { - \Auth::login($account); + Activity::whereAccountId($account->id) + ->where('login_key', $loginKey) + ->firstOrFail() + ->delete(); + + \Auth::login($account, true); return redirect() ->route('dashboard'); diff --git a/app/Http/Controllers/WebsiteController.php b/app/Http/Controllers/WebsiteController.php index f931d5c..bd48956 100644 --- a/app/Http/Controllers/WebsiteController.php +++ b/app/Http/Controllers/WebsiteController.php @@ -3,7 +3,9 @@ namespace App\Http\Controllers; use App\Website; +use App\Activity; use App\Mail\VerifyWebsite; +use App\Enums\ActivityType; class WebsiteController extends Controller { @@ -12,9 +14,15 @@ public function __construct() $this->middleware('auth')->only('resendVerification'); } - public function verify(Website $website) + public function verify(Website $website, $verificationKey) { try { + Activity::whereWebsiteId($website->id) + ->where('login_key', $verificationKey) + ->where('type', ActivityType::WebsiteVerification) + ->firstOrFail() + ->delete(); + $website->verified = true; $website->saveOrFail(); @@ -24,8 +32,8 @@ public function verify(Website $website) ]); } catch (\Throwable $e) { return view('website.error')->with([ - 'title' => 'Unknown error', - 'error' => 'Something bad happened in my end. Please contact me in twitter if this issue persists', + 'title' => 'Bad Verification', + 'error' => 'The verification link has been expired. Please login to your account and request a new verification link', ]); } } diff --git a/app/Listeners/SendLoginVerification.php b/app/Listeners/SendLoginVerification.php index e840f41..81fbe04 100644 --- a/app/Listeners/SendLoginVerification.php +++ b/app/Listeners/SendLoginVerification.php @@ -2,7 +2,10 @@ namespace App\Listeners; +use App\Activity; use App\Mail\VerifyLogin; +use App\Enums\ActivityType; +use Illuminate\Support\Str; use App\Events\LoginRequest; class SendLoginVerification @@ -25,9 +28,15 @@ public function __construct() */ public function handle(LoginRequest $event) { - $signedURL = \URL::temporarySignedRoute('login.verify', now()->addDay(), [ - 'account' => $event->account->id, - ]); + $activity = new Activity; + + $activity->account_id = $event->account->id; + $activity->type = ActivityType::LoginRequested; + $activity->login_key = Str::uuid(); + + $activity->saveOrFail(); + + $signedURL = route('login.verify', [$event->account->id, $activity->login_key]); \Mail::to($event->account->email) ->send(new VerifyLogin($signedURL)); diff --git a/app/Listeners/SendVerification.php b/app/Listeners/SendVerification.php index bdeb480..a551b88 100644 --- a/app/Listeners/SendVerification.php +++ b/app/Listeners/SendVerification.php @@ -2,8 +2,11 @@ namespace App\Listeners; +use App\Activity; use App\Events\NewWebsite; use App\Mail\VerifyWebsite; +use Illuminate\Support\Str; +use App\Enums\ActivityType; class SendVerification { @@ -25,7 +28,17 @@ public function __construct() */ public function handle(NewWebsite $event) { + $activity = new Activity; + + $activity->account_id = $event->website->account_id; + $activity->website_id = $event->website->id; + $activity->login_key = Str::uuid(); + $activity->type = ActivityType::WebsiteVerification; + + $activity->saveOrFail(); + + $signedURL = route('website.verify', [$event->website->id, $activity->login_key]); \Mail::to($event->website->account->email) - ->send(new VerifyWebsite($event->website)); + ->send(new VerifyWebsite($event->website, $signedURL)); } } diff --git a/app/Mail/VerifyWebsite.php b/app/Mail/VerifyWebsite.php index 2acb9d6..ba1026c 100644 --- a/app/Mail/VerifyWebsite.php +++ b/app/Mail/VerifyWebsite.php @@ -12,15 +12,18 @@ class VerifyWebsite extends Mailable use Queueable, SerializesModels; public $website; + public $signedURL; /** * Create a new message instance. * * @param Website $website + * @param string $signedURL */ - public function __construct(Website $website) + public function __construct(Website $website, $signedURL) { $this->website = $website; + $this->signedURL = $signedURL; } /** @@ -30,17 +33,12 @@ public function __construct(Website $website) */ public function build() { - $signedURL = \URL::temporarySignedRoute('website.verify', now()->addDay(), [ - 'account' => $this->website->account->id, - 'website' => $this->website->id - ]); - return $this->markdown('emails.website.verify') ->subject('[FormZend] Verify new website | ' . $this->website->url) ->replyTo(config('mail.reply.address'), config('mail.reply.name')) ->with([ 'url' => $this->website->url, - 'verify' => $signedURL + 'verify' => $this->signedURL ]); } } diff --git a/database/migrations/2020_11_29_043352_add_customer_and_remember_to_accounts.php b/database/migrations/2020_11_29_043352_add_customer_and_remember_to_accounts.php new file mode 100644 index 0000000..4c0fd7b --- /dev/null +++ b/database/migrations/2020_11_29_043352_add_customer_and_remember_to_accounts.php @@ -0,0 +1,33 @@ +string('customer_id')->nullable(); + $table->rememberToken(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('accounts', function (Blueprint $table) { + $table->dropColumn(['customer_id', 'remember_token']); + }); + } +} diff --git a/database/migrations/2020_11_29_125126_add_login_key_to_activities.php b/database/migrations/2020_11_29_125126_add_login_key_to_activities.php new file mode 100644 index 0000000..ac68c7b --- /dev/null +++ b/database/migrations/2020_11_29_125126_add_login_key_to_activities.php @@ -0,0 +1,32 @@ +string('login_key')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('activities', function (Blueprint $table) { + $table->dropColumn('login_key'); + }); + } +} diff --git a/routes/web.php b/routes/web.php index c466c2c..a87cef3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -25,12 +25,11 @@ Route::get('auth/logout', 'AuthController@logout') ->middleware('auth') ->name('logout'); -Route::get('auth/login/account/{account:id}', 'AuthController@loginUser') - ->middleware('guest', 'signed') +Route::get('auth/login/account/{account:id}/key/{key}', 'AuthController@loginUser') + ->middleware('guest') ->name('login.verify'); -Route::get('verify/website/{website:id}', 'WebsiteController@verify') - ->middleware('signed') +Route::get('verify/website/{website:id}/key/{key}', 'WebsiteController@verify') ->name('website.verify'); Route::get('verify/resend/website/{website:id}', 'WebsiteController@resendVerification') ->name('website.verify.resend');