add login logic

This commit is contained in:
2025-11-20 00:15:17 +03:00
parent c266131666
commit 1ec7e58088
13 changed files with 396 additions and 16 deletions

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CommentsController extends Controller
{
public function store(Request $request, int $id): JsonResponse
{
return response()->json([
'id' => 1,
'text' => $request->get('text'),
'post_id' => $id
], Response::HTTP_CREATED);
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class PostsController extends Controller
{
public function index(): JsonResponse
{
return response()->json([
[
'id' => 1,
'title' => 'My first post',
],
[
'id' => 2,
'title' => 'New post',
]
]);
}
public function destroy(int $id): JsonResponse
{
// мы бы здесь написали вызов запроса delete из БД
return response()->json([
'success' => true,
], Response::HTTP_ACCEPTED);
}
public function store(Request $request): JsonResponse
{
return response()->json([
'title' => $request->get('title'),
'text' => $request->get('text'),
], Response::HTTP_CREATED);
}
public function update(Request $request, int $id): JsonResponse
{
return response()->json([
'title' => $request->get('title'),
'text' => $request->get('text'),
], Response::HTTP_ACCEPTED);
}
public function show(int $id): JsonResponse
{
if ($id === 5) {
return response()->json(
[
'status' => 'Not found'
],
Response::HTTP_NOT_FOUND
);
}
return response()->json([
'id' => $id,
'title' => 'My first post',
'text' => 'My first post text',
]);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Http\Controllers;
use App\Models\Project;
use Illuminate\Http\Request;
class ProjectsController extends Controller
{
public function index()
{
return response()->json(Project::all()->toJson());
}
public function create(Request $request)
{
$title = $request->get('title');
$description = $request->get('description');
$creatorUserId = 1;
$project = new Project();
$project->title = $title;
$project->description = $description;
$project->creator_user_id = $creatorUserId;
$project->save();
return response()->json($project->toJson());
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
class UsersController extends Controller
{
public function create(Request $request)
{
$user = new User();
$name = $request->get('name');
$email = $request->get('email');
$password = Hash::make($request->get('password'));
$user->name = $name;
$user->email = $email;
$user->password = $password;
$user->save();
return ['token' => $user->createToken('frontend')->plainTextToken];
}
}

15
app/Models/Project.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
//
protected $fillable = [
'title',
'description',
'creator_user_id',
];
}

View File

@@ -6,11 +6,12 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
use HasFactory, Notifiable, HasApiTokens;
/**
* The attributes that are mass assignable.

View File

@@ -8,8 +8,8 @@ return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
api: __DIR__.'/../routes/api.php',
health: '/up',
api: __DIR__.'/../routes/api.php',
)
->withMiddleware(function (Middleware $middleware) {
//

View File

@@ -11,6 +11,7 @@
"require": {
"php": "^8.2",
"laravel/framework": "^12.0",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.10.1"
},
"require-dev": {

66
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "88970a0117c062eed55fa8728fc43833",
"content-hash": "85c1d2065f70e38b0d6bf66559fb13c5",
"packages": [
{
"name": "brick/math",
@@ -1328,6 +1328,70 @@
},
"time": "2025-02-11T13:34:40+00:00"
},
{
"name": "laravel/sanctum",
"version": "v4.2.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/sanctum.git",
"reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/sanctum/zipball/fd6df4f79f48a72992e8d29a9c0ee25422a0d677",
"reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677",
"shasum": ""
},
"require": {
"ext-json": "*",
"illuminate/console": "^11.0|^12.0",
"illuminate/contracts": "^11.0|^12.0",
"illuminate/database": "^11.0|^12.0",
"illuminate/support": "^11.0|^12.0",
"php": "^8.2",
"symfony/console": "^7.0"
},
"require-dev": {
"mockery/mockery": "^1.6",
"orchestra/testbench": "^9.0|^10.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^11.3"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Sanctum\\SanctumServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Sanctum\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.",
"keywords": [
"auth",
"laravel",
"sanctum"
],
"support": {
"issues": "https://github.com/laravel/sanctum/issues",
"source": "https://github.com/laravel/sanctum"
},
"time": "2025-07-09T19:45:24+00:00"
},
{
"name": "laravel/serializable-closure",
"version": "v2.0.4",

84
config/sanctum.php Normal file
View File

@@ -0,0 +1,84 @@
<?php
use Laravel\Sanctum\Sanctum;
return [
/*
|--------------------------------------------------------------------------
| Stateful Domains
|--------------------------------------------------------------------------
|
| Requests from the following domains / hosts will receive stateful API
| authentication cookies. Typically, these should include your local
| and production domains which access your API via a frontend SPA.
|
*/
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
Sanctum::currentApplicationUrlWithPort(),
// Sanctum::currentRequestHost(),
))),
/*
|--------------------------------------------------------------------------
| Sanctum Guards
|--------------------------------------------------------------------------
|
| This array contains the authentication guards that will be checked when
| Sanctum is trying to authenticate a request. If none of these guards
| are able to authenticate the request, Sanctum will use the bearer
| token that's present on an incoming request for authentication.
|
*/
'guard' => ['web'],
/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. This will override any values set in the token's
| "expires_at" attribute, but first-party sessions are not affected.
|
*/
'expiration' => null,
/*
|--------------------------------------------------------------------------
| Token Prefix
|--------------------------------------------------------------------------
|
| Sanctum can prefix new tokens in order to take advantage of numerous
| security scanning initiatives maintained by open source platforms
| that notify developers if they commit tokens into repositories.
|
| See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning
|
*/
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
/*
|--------------------------------------------------------------------------
| Sanctum Middleware
|--------------------------------------------------------------------------
|
| When authenticating your first-party SPA with Sanctum you may need to
| customize some of the middleware Sanctum uses while processing the
| request. You may change the middleware listed below as required.
|
*/
'middleware' => [
'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
],
];

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
//title description creator_user_id
Schema::create('projects', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('title');
$table->text('description');
$table->foreignId('creator_user_id')->constrained('users');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('projects');
}
};

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->text('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable()->index();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};

View File

@@ -1,17 +1,27 @@
<?php
use App\Http\Controllers\Api\CommentsController;
use App\Http\Controllers\Api\PostsController;
use App\Http\Controllers\ProjectsController;
use App\Http\Controllers\UsersController;
use Illuminate\Support\Facades\Route;
Route::post('/test', function () {
return response()->json([
'status' => 'success',]);
Route::prefix('posts')->group(function () {
Route::get('/', [PostsController::class, 'index']);
Route::post('/', [PostsController::class, 'store']);
Route::prefix('{id}')->group(function () {
Route::delete('/', [PostsController::class, 'destroy']);
Route::put('/', [PostsController::class, 'update']);
Route::get('/', [PostsController::class, 'show']);
Route::prefix('comments')->group(function () {
Route::post('/', [CommentsController::class, 'store']);
});
});
});
Route::get('/test-level', function () {
return response()->json([
'level1' => [
[
'level2' => [
'level3' => 'success',
]]
],]);
});
Route::get('projects', [ProjectsController::class, 'index']);
Route::post('projects', [ProjectsController::class, 'create']);
Route::post('users', [UsersController::class, 'create']);