Накатал базовую авторизацию
This commit is contained in:
parent
4eb5d8d5b8
commit
a31c8aed39
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\API;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
|
class AuthController extends Controller
|
||||||
|
{
|
||||||
|
public function register(Request $request)
|
||||||
|
{
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'name' => 'required',
|
||||||
|
'email' => 'required|email|unique:users',
|
||||||
|
'password' => 'required',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return response()->json($validator->errors(), 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::create([
|
||||||
|
'name' => $request->name,
|
||||||
|
'email' => $request->email,
|
||||||
|
'password' => bcrypt($request->password),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$token = $user->createToken('auth_token')->plainTextToken;
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'user' => $user,
|
||||||
|
'token' => $token,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function login(Request $request)
|
||||||
|
{
|
||||||
|
if (!Auth::attempt($request->only('email', 'password'))) {
|
||||||
|
return response()->json(['message' => 'Invalid login details'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::where('email', $request['email'])->firstOrFail();
|
||||||
|
|
||||||
|
$token = $user->createToken('auth_token')->plainTextToken;
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'user' => $user,
|
||||||
|
'token' => $token,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout(Request $request)
|
||||||
|
{
|
||||||
|
$request->user()->currentAccessToken()->delete();
|
||||||
|
|
||||||
|
return response()->json(['message' => 'Logged out']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,8 +31,9 @@
|
||||||
:class="menuOpen ? 'mt-2 mb-2 pa-2' : 'mt-10 mb-3 pa-5'"
|
:class="menuOpen ? 'mt-2 mb-2 pa-2' : 'mt-10 mb-3 pa-5'"
|
||||||
>
|
>
|
||||||
<p class="ml-3 mr-3" :class="menuOpen ? 'text-body-1' : 'text-h6'"><RouterLink to="/" class="nav-link text-decoration-none">Главная</RouterLink></p>
|
<p class="ml-3 mr-3" :class="menuOpen ? 'text-body-1' : 'text-h6'"><RouterLink to="/" class="nav-link text-decoration-none">Главная</RouterLink></p>
|
||||||
<p class="ml-3 mr-3" :class="menuOpen ? 'text-body-1' : 'text-h6'"><RouterLink to="/login" class="nav-link text-decoration-none">Войти</RouterLink></p>
|
<p v-if="user == null" class="ml-3 mr-3" :class="menuOpen ? 'text-body-1' : 'text-h6'"><RouterLink to="/login" class="nav-link text-decoration-none">Войти</RouterLink></p>
|
||||||
<p class="ml-3 mr-3" :class="menuOpen ? 'text-body-1' : 'text-h6'"><RouterLink to="/register" class="nav-link text-decoration-none">Регистрация</RouterLink></p>
|
<p v-if="user == null" class="ml-3 mr-3" :class="menuOpen ? 'text-body-1' : 'text-h6'"><RouterLink to="/register" class="nav-link text-decoration-none">Регистрация</RouterLink></p>
|
||||||
|
<p v-else class="ml-3 mr-3" :class="menuOpen ? 'text-body-1' : 'text-h6'"><a href="#" class="nav-link text-decoration-none" @click="logout">Выйти</a></p>
|
||||||
</v-sheet>
|
</v-sheet>
|
||||||
<v-sheet class="rounded-lg main-bg h-100 mt-3 mr-10 ml-10 mb-10 pa-5">
|
<v-sheet class="rounded-lg main-bg h-100 mt-3 mr-10 ml-10 mb-10 pa-5">
|
||||||
<RouterView v-slot="{ Component }">
|
<RouterView v-slot="{ Component }">
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {th} from "vuetify/locale";
|
import {th} from "vuetify/locale";
|
||||||
|
import {useAuthStore} from "./store/auth.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: "App",
|
||||||
|
@ -57,7 +59,19 @@ export default {
|
||||||
isWide: window.innerWidth >= 460,
|
isWide: window.innerWidth >= 460,
|
||||||
menuOpen: false
|
menuOpen: false
|
||||||
}),
|
}),
|
||||||
|
computed: {
|
||||||
|
user() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
return authStore.user;
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
logout() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
authStore.logout();
|
||||||
|
this.username = 'guest';
|
||||||
|
this.$router.push('/login');
|
||||||
|
},
|
||||||
resizeEventHandler(e) {
|
resizeEventHandler(e) {
|
||||||
this.windowHeight = document.documentElement.clientHeight;
|
this.windowHeight = document.documentElement.clientHeight;
|
||||||
this.windowWidth = document.documentElement.clientWidth;
|
this.windowWidth = document.documentElement.clientWidth;
|
||||||
|
|
|
@ -10,6 +10,9 @@ import Login from "./views/Login.vue";
|
||||||
import About from "./views/About.vue";
|
import About from "./views/About.vue";
|
||||||
import Register from "./views/Register.vue";
|
import Register from "./views/Register.vue";
|
||||||
import {createMemoryHistory, createRouter} from "vue-router";
|
import {createMemoryHistory, createRouter} from "vue-router";
|
||||||
|
import { createPinia } from 'pinia';
|
||||||
|
|
||||||
|
const pinia = createPinia();
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{path: '/', component: About, props: true},
|
{path: '/', component: About, props: true},
|
||||||
|
@ -27,4 +30,4 @@ const vuetify = createVuetify({
|
||||||
directives
|
directives
|
||||||
})
|
})
|
||||||
|
|
||||||
createApp(App).use(vuetify).use(router).mount("#app")
|
createApp(App).use(vuetify).use(router).use(pinia).mount("#app")
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export const useAuthStore = defineStore('auth', {
|
||||||
|
state: () => ({
|
||||||
|
user: null,
|
||||||
|
token: localStorage.getItem('token') || null,
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
async login(credentials) {
|
||||||
|
const response = await axios.post('/api/login', credentials);
|
||||||
|
this.user = response.data.user;
|
||||||
|
this.token = response.data.token;
|
||||||
|
localStorage.setItem('token', response.data.token);
|
||||||
|
},
|
||||||
|
async register(credentials) {
|
||||||
|
const response = await axios.post('/api/register', credentials);
|
||||||
|
this.user = response.data.user;
|
||||||
|
this.token = response.data.token;
|
||||||
|
localStorage.setItem('token', response.data.token);
|
||||||
|
},
|
||||||
|
logout() {
|
||||||
|
this.user = null;
|
||||||
|
this.token = null;
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
isAuthenticated: (state) => !!state.token,
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,11 +1,31 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { useAuthStore } from '../store/auth.js';
|
||||||
export default {
|
export default {
|
||||||
name: "About"
|
name: "About",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
username: 'guest'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
user() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
return authStore.user;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
logout() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
authStore.logout();
|
||||||
|
this.username = 'guest';
|
||||||
|
this.$router.push('/login');
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-label class="text-h3">Hello World!</v-label>
|
<v-label class="text-h3">Welcome {{ user != null ? user.name : 'guest' }}!</v-label><br>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -1,6 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="w-100 h-100 d-flex justify-center">
|
<div class="w-100 h-100 d-flex justify-center">
|
||||||
<div class="d-flex flex-column justify-center h-100" :class="isWide ? 'w-50' : 'w-75'">
|
<div class="d-flex flex-column justify-center h-100" :class="isWide ? 'w-50' : 'w-75'">
|
||||||
|
<v-form @submit.prevent="login">
|
||||||
|
<v-label>Логин:</v-label>
|
||||||
|
<v-text-field type="email" v-model="email" label="E-mail" class="flex-grow-0" required></v-text-field>
|
||||||
|
<v-label>Пароль:</v-label>
|
||||||
|
<v-text-field type="password" v-model="password" label="Пароль" class="flex-grow-0" required></v-text-field>
|
||||||
|
<div class="d-flex justify-center" :class="isWide ? '' : 'flex-column align-center'">
|
||||||
|
<v-btn type="submit" color="#F0A068FF" class="ma-5 flex-grow-0" :class="isWide ? 'w-25' : 'w-100 text-body-1'" block>Войти</v-btn>
|
||||||
|
<router-link to="/register" class="text-decoration-none link-no-color ma-5" :class="isWide ? 'w-25' : 'w-100'">
|
||||||
|
<v-btn color="#F0A068FF" :class="isWide ? 'w-100' : 'w-100 text-body-1'">Регистрация</v-btn>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</v-form>
|
||||||
|
<!--
|
||||||
<v-label>Логин:</v-label>
|
<v-label>Логин:</v-label>
|
||||||
<v-text-field label="Логин" class="flex-grow-0"></v-text-field>
|
<v-text-field label="Логин" class="flex-grow-0"></v-text-field>
|
||||||
<v-label>Пароль:</v-label>
|
<v-label>Пароль:</v-label>
|
||||||
|
@ -10,16 +23,33 @@
|
||||||
<router-link to="/register" class="text-decoration-none link-no-color ma-5" :class="isWide ? 'w-25' : 'w-100'">
|
<router-link to="/register" class="text-decoration-none link-no-color ma-5" :class="isWide ? 'w-25' : 'w-100'">
|
||||||
<v-btn color="#F0A068FF" :class="isWide ? 'w-100' : 'w-100 text-body-1'">Регистрация</v-btn>
|
<v-btn color="#F0A068FF" :class="isWide ? 'w-100' : 'w-100 text-body-1'">Регистрация</v-btn>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { useAuthStore } from '../store/auth.js';
|
||||||
export default {
|
export default {
|
||||||
name: "Login",
|
name: "Login",
|
||||||
props: {
|
props: {
|
||||||
isWide: Boolean
|
isWide: Boolean
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async login() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
await authStore.login({
|
||||||
|
email: this.email,
|
||||||
|
password: this.password,
|
||||||
|
});
|
||||||
|
this.$router.push('/');
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,8 +1,27 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { useAuthStore } from '../store/auth.js';
|
||||||
export default {
|
export default {
|
||||||
name: "Register",
|
name: "Register",
|
||||||
props: {
|
props: {
|
||||||
isWide: Boolean
|
isWide: Boolean
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async register() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
await authStore.register({
|
||||||
|
name: this.name,
|
||||||
|
email: this.email,
|
||||||
|
password: this.password,
|
||||||
|
});
|
||||||
|
this.$router.push('/');
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -10,18 +29,20 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<div class="w-100 h-100 d-flex justify-center">
|
<div class="w-100 h-100 d-flex justify-center">
|
||||||
<div class="d-flex flex-column justify-center h-100" :class="isWide ? 'w-50' : 'w-75'">
|
<div class="d-flex flex-column justify-center h-100" :class="isWide ? 'w-50' : 'w-75'">
|
||||||
<v-label>Логин:</v-label>
|
<v-form @submit.prevent="register">
|
||||||
<v-text-field label="Логин" class="flex-grow-0"></v-text-field>
|
<v-label>Имя:</v-label>
|
||||||
<v-label>E-mail:</v-label>
|
<v-text-field type="text" v-model="name" label="Имя" class="flex-grow-0" required></v-text-field>
|
||||||
<v-text-field label="E-mail" class="flex-grow-0"></v-text-field>
|
<v-label>E-mail:</v-label>
|
||||||
<v-label>Пароль:</v-label>
|
<v-text-field type="email" v-model="email" label="E-mail" class="flex-grow-0" required></v-text-field>
|
||||||
<v-text-field label="Пароль" class="flex-grow-0"></v-text-field>
|
<v-label>Пароль:</v-label>
|
||||||
<div class="d-flex justify-center" :class="isWide ? '' : 'flex-column align-center'">
|
<v-text-field type="password" v-model="password" label="Пароль" class="flex-grow-0" required></v-text-field>
|
||||||
<v-btn color="#F0A068FF" class="ma-5" :class="isWide ? 'w-25' : 'w-100 text-body-1'">Зарегистрироваться</v-btn>
|
<div class="d-flex justify-center" :class="isWide ? '' : 'flex-column align-center'">
|
||||||
<router-link to="/login" class="text-decoration-none link-no-color ma-5" :class="isWide ? 'w-25' : 'w-100'">
|
<v-btn type="submit" color="#F0A068FF" class="ma-5" :class="isWide ? 'w-25' : 'w-100 text-body-1'" block>Зарегистрироваться</v-btn>
|
||||||
<v-btn color="#F0A068FF" :class="isWide ? 'w-100' : 'w-100 text-body-1'">Вход</v-btn>
|
<router-link to="/login" class="text-decoration-none link-no-color ma-5" :class="isWide ? 'w-25' : 'w-100'">
|
||||||
</router-link>
|
<v-btn color="#F0A068FF" :class="isWide ? 'w-100' : 'w-100 text-body-1'">Вход</v-btn>
|
||||||
</div>
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</v-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Controllers\API\AuthController;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
@ -17,3 +18,7 @@ use Illuminate\Support\Facades\Route;
|
||||||
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
||||||
return $request->user();
|
return $request->user();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::post('/register', [AuthController::class, 'register']);
|
||||||
|
Route::post('/login', [AuthController::class, 'login']);
|
||||||
|
Route::post('/logout', [AuthController::class, 'logout'])->middleware('auth:sanctum');
|
||||||
|
|
Loading…
Reference in New Issue