Backend DevelopmentFrontend DevelopmentVueJs Tutorials

Building a Simple Real estate App With Laravel and Vuejs 3 Part3

Building a Simple Real estate App With Laravel and Vuejs 3

In this part of the series we will prepare the authentication views for our app, then we will start adding the necessary back-end code for login and registration.

 

 

 

At first we need to prepare the login and register view. Typically this will be in the Register.vue component.

Below is the extracted pages from the template that we downloaded in the first part.

Be sure to run this command to terminal to watch to code changes and compile:

npm run watch

Next update resources/js/components/pages/Register.vue

<template>
    <div class="page-head">
        <div class="container">
            <div class="row">
                <div class="page-head-content">
                    <h1 class="page-title">Home New account / Sign in </h1>
                </div>
            </div>
        </div>
    </div>

    <div class="register-area" style="background-color: rgb(249, 249, 249);">
        <div class="container">

            <div class="col-md-6">
                <div class="box-for overflow">
                    <div class="col-md-12 col-xs-12 register-blocks">
                        <h2>New account : </h2>
                        <form action="#" method="post">
                            <div class="form-group">
                                <label>Name</label>
                                <input type="text" class="form-control" name="name" />
                            </div>
                            <div class="form-group">
                                <label>Email</label>
                                <input type="text" class="form-control" name="email" />
                            </div>
                            <div class="form-group">
                                <label>Password</label>
                                <input type="password" class="form-control" name="password" />
                            </div>
                            <div class="form-group">
                                <label>Confirm Password</label>
                                <input type="password" class="form-control" name="password_confirmation" />
                            </div>
                            <div class="text-center">
                                <button type="submit" class="btn btn-default">Register</button>
                            </div>
                        </form>
                    </div>
                </div>
            </div>

            <div class="col-md-6">
                <div class="box-for overflow">
                    <div class="col-md-12 col-xs-12 login-blocks">
                        <h2>Login : </h2>
                        <form action="#" method="post">
                            <div class="form-group">
                                <label>Email</label>
                                <input type="text" class="form-control" name="email" />
                            </div>
                            <div class="form-group">
                                <label>Password</label>
                                <input type="password" class="form-control" name="password" />
                            </div>
                            <div class="text-center">
                                <button type="submit" class="btn btn-default"> Log in</button>
                            </div>
                        </form>
                    </div>

                </div>
            </div>

        </div>
    </div>
</template>

<script>
export default {
    name: "Login"
}
</script>

This page consists of two sections, the first section for creating new account while the other section to login already existing users.

After making this update if you go to http://localhost:8000 and click on the Login button you will see the login and register sections like above.

 

In the same way let’s update the profile views:

Update resources/js/components/pages/user/EditProfile.vue

<template>
    <div class="page-head">
        <div class="container">
            <div class="row">
                <div class="page-head-content">
                    <h1 class="page-title">Hello : <span class="orange strong">Kimaro kyoto</span></h1>
                </div>
            </div>
        </div>
    </div>

    <div class="content-area user-profiel" style="background-color: #FCFCFC;">&nbsp;
        <div class="container">
            <div class="row">
                <div class="col-sm-10 col-sm-offset-1 profiel-container">

                    <form action="#" method="post">
                        <div class="profiel-header">
                            <h3>
                                <b>BUILD</b> YOUR PROFILE <br>
                                <small>This information will let us know more about you.</small>
                            </h3>
                            <hr>
                        </div>

                        <div class="clear">

                            <div class="col-sm-8 col-sm-offset-3 padding-top-25">

                                <div class="form-group">
                                    <label>Name <small>(required)</small></label>
                                    <input name="name" type="text" class="form-control" placeholder="Andrew..." />
                                </div>
                                <div class="form-group">
                                    <label>Email <small>(required)</small></label>
                                    <input name="email" type="email" class="form-control" placeholder="andrew@email@email.com.com" />
                                </div>
                                <div class="form-group">
                                    <label>Phone :</label>
                                    <input name="Phone" type="text" class="form-control" placeholder="+1 9090909090" />
                                </div>
                            </div>

                        </div>

                        <div class="col-sm-5 col-sm-offset-6">
                            <br>
                            <input type='submit' class='btn btn-finish btn-primary' name='finish' value='Finish' />
                        </div>
                        <br>
                    </form>

                </div>
            </div><!-- end row -->

        </div>
    </div>
</template>

<script>
export default {
    name: "EditProfile"
}
</script>

Update resources/js/components/pages/user/ChangePassword.vue

<template>
    <div class="page-head">
        <div class="container">
            <div class="row">
                <div class="page-head-content">
                    <h1 class="page-title">Hello : <span class="orange strong">Kimaro kyoto</span></h1>
                </div>
            </div>
        </div>
    </div>

    <div class="content-area user-profiel" style="background-color: #FCFCFC;">&nbsp;
        <div class="container">
            <div class="row">
                <div class="col-sm-10 col-sm-offset-1 profiel-container">

                    <form action="#" method="post">

                        <div class="profiel-header">
                            <h3>
                                <b>UPDATE</b> YOUR PASSWORD <br>
                            </h3>
                            <hr>
                        </div>

                        <div class="clear">

                            <div class="col-sm-10 col-sm-offset-1">
                                <div class="form-group">
                                    <label>Password <small>(required)</small></label>
                                    <input type="password" name="Password" class="form-control" />
                                </div>
                                <div class="form-group">
                                    <label>Confirm password : <small>(required)</small></label>
                                    <input type="password" name="password_confirmation" class="form-control" />
                                </div>
                            </div>
                            <div class="col-sm-10 col-sm-offset-1 text-center">
                                <input type='submit' class='btn btn-finish btn-primary' name='update' value='Update' />
                            </div>

                        </div>

                    </form>

                </div>
            </div><!-- end row -->

        </div>
    </div>
</template>

<script>
export default {
    name: "ChangePassword"
}
</script>

After updating these files, we will switch and go to the laravel controller, so we will start creating the required controllers for authenticating users and updating user profile.

 

Handling Authentication With laravel/sanctum

There are many ways to deal with authentication in Laravel, as laravel provides builtin authentication functionality. However the authentication we need here is in the context of a frontend app. In a frontend like Vuejs app usually we use something like JWT tokens and not depend on cookies.

Fortunately with release of Laravel 8 a new authentication methods coming like laravel/sanctum and laravel/fortify packages. These packages server similar purpose which handling user authentication, in except that laravel/fortify have many features than laravel/sanctum.

As per laravel docs laravel/sanctum provides a featherweight authentication system for SPAs (single page applications), mobile applications, and simple, token based APIs. This means that sanctum can be used for cookie based authentication and also token based APIs. This is awesome as we don’t need anymore any third party packages.

In this tutorial we will use laravel/sanctum with cookie based authentication.

To learn more about laravel/sanctum read my article here.

Installing laravel/sanctum:

composer require laravel/sanctum

Publish sanctum configuration files:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

Add sanctum middleware to app/Http/kernel.php

'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

Open .env file and add this line:

SANCTUM_STATEFUL_DOMAINS=localhost,localhost:3000,localhost:8000,127.0.0.1,127.0.0.1:8000,::1

Clear the cache:

php artisan cache:clear

Also change the session driver to be cookie in .env

SESSION_DRIVER=cookie
SESSION_COOKIE=realestateapp_sess_cookie

Update config/cors.php like so:

<?php

return [

    'paths' => ['api/*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

];

Auth Controllers

Create the login and register controllers:

php artisan make:controller Auth/LoginController
php artisan make:controller Auth/RegisterController

Then open each controller and update with the below code:

app/Http/Controllers/Auth/LoginController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class LoginController extends Controller
{
    public function login(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|string',
            'password' => 'required|string',
        ]);

        if($validator->fails()) {
            return response()->json(['status' => false, 'errors' => $validator->errors()], 500);
        }

        $credentials = $request->only('email', 'password');

        if(auth()->attempt($credentials, $request->filled('remember'))) {
            return response()->json(['status' => true, 'user' => auth()->user()]);
        }

        return response()->json(['status' => false, 'message' => 'invalid username or password'], 500);
    }

    public function logout(Request $request)
    {
        auth('web')->logout();

        $request->session()->invalidate();

        $request->session()->regenerateToken();

        return response()->json(['status' => true, 'message' => 'logged out']);
    }
}

app/Http/Controllers/Auth/RegisterController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class RegisterController extends Controller
{
    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:4', 'confirmed'],
        ]);

        if($validator->fails()) {
            return response()->json(['status' => false, 'errors' => $validator->errors()], 500);
        }

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        return response()->json(['status' => true, 'user' => $user]);
    }
}

Update routes/api.php

<?php

use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\Auth\RegisterController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::post('login', [LoginController::class, 'login']);
Route::post('register', [RegisterController::class, 'register']);
Route::post('logout', [LoginController::class, 'logout'])->middleware('auth:sanctum');

 

Installing Vue Toastification

Let’s install the Vue Toastification library to display nice notifications on case of errors or success messages. Vue Toastification fully supported with vue 3 composition api:

npm install --save vue-toastification@next

Next update app.js to enable the plugin:

resources/js/app.js

require('./bootstrap');
import { createApp } from 'vue';
import Toast from "vue-toastification";
import "vue-toastification/dist/index.css";
import App from './components/App.vue';
import router from "./routes";


const app = createApp(App);
app.use(router);
app.use(Toast);

app.mount('#app');

 

Continue to part 4: completing authentication>>>

5 2 votes
Article Rating

What's your reaction?

Excited
0
Happy
1
Not Sure
0
Confused
0

You may also like

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments