Commit d66b8a0f authored by 20194288-huannh's avatar 20194288-huannh

update jwt/auth ,order model-controller-resource-db

parent 28c31dc7
...@@ -50,3 +50,5 @@ PUSHER_APP_CLUSTER=mt1 ...@@ -50,3 +50,5 @@ PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
JWT_SECRET=
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Resources\OrderResource;
use App\Repositories\OrderRepository;
use App\Http\Controllers\Controller;
use App\Repositories\UserRepository;
use App\Models\User;
class OrderController extends Controller
{
private OrderRepository $orderRepository;
private UserRepository $userRepository;
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function __construct(OrderRepository $orderRepository, UserRepository $userRepository)
{
$this->orderRepository = $orderRepository;
$this->userRepository = $userRepository;
}
public function index(Request $request)
{
$id = $request->id;
$user = $this->userRepository->getByid($id);
if ($user->role == User::ROLE_ADMIN){
$order = $this->orderRepository->paginate($request->page);
} elseif ($user->role == User::ROLE_EDITOR){
$order = $this->orderRepository->getListOrderOfUser($id);
}
return response()->json([
'success' => true,
'meta' => [
'total' => $order->total(),
'pages' => $order->lastPage()
],
'data' => OrderResource::collection($order)
]);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create(Request $request)
{
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$order = $this->orderRepository->create($request->only(['id', 'details', 'client', 'is_fulfilled']));
return response()->json([
'success' => true,
'message' => '',
'data' => $order
]);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show(Request $request)
{
$order = $this->orderRepository->getById($request->id);
return response()->json([
'success' => true,
'message' => '',
'data' => $order
]);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit(Request $request)
{
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$order = $this->orderRepository->update($request->id,
$request->only(['id', 'details', 'client', 'is_fulfilled']));
return response()->json([
'success' => true,
'message' => '',
'data' => $order
]);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$order = $this->orderRepository->deleteById($request->id);
return response()->json([
'success' => true,
'message' => '',
'data' => $order
]);
}
public function search(Request $request){
$order = $this->orderRepository->getListOrderByStatus($request->status);
return response()->json([
'success' => true,
'meta' => [
'total' => $order->total(),
'pages' => $order->lastPage()
],
'data' => OrderResource::collection($order)
]);
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
use Validator;
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
*
* @return void
*/
public function __construct() {
$this->middleware('auth:api', ['except' => ['login', 'register']]);
}
/**
* Get a JWT via given credentials.
*
* @return \Illuminate\Http\JsonResponse
*/
public function login(Request $request){
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required|string|min:6',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
if (! $token = auth('api')->attempt($validator->validated())) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->createNewToken($token);
}
/**
* Register a User.
*
* @return \Illuminate\Http\JsonResponse
*/
public function register(Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|string|between:2,100',
'email' => 'required|string|email|max:100|unique:users',
'password' => 'required|string|confirmed|min:6',
]);
if($validator->fails()){
return response()->json($validator->errors()->toJson(), 400);
}
$user = User::create(array_merge(
$validator->validated(),
['password' => bcrypt($request->password)]
));
return response()->json([
'message' => 'User successfully registered',
'user' => $user
], 201);
}
/**
* Log the user out (Invalidate the token).
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout() {
auth('api')->logout();
return response()->json(['message' => 'User successfully signed out']);
}
/**
* Refresh a token.
*
* @return \Illuminate\Http\JsonResponse
*/
public function refresh() {
return $this->createNewToken(auth('api')->refresh());
}
/**
* Get the authenticated User.
*
* @return \Illuminate\Http\JsonResponse
*/
public function userProfile() {
return response()->json(auth('api')->user());
}
/**
* Get the token array structure.
*
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function createNewToken($token){
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60,
'user' => auth('api')->user()
]);
}
public function changePassWord(Request $request) {
$validator = Validator::make($request->all(), [
'old_password' => 'required|string|min:6',
'new_password' => 'required|string|confirmed|min:6',
]);
if($validator->fails()){
return response()->json($validator->errors()->toJson(), 400);
}
$userId = auth('api')->user()->id;
$user = User::where('id', $userId)->update(
['password' => bcrypt($request->new_password)]
);
return response()->json([
'message' => 'User successfully changed password',
'user' => $user,
], 201);
}
}
<?php
namespace App\Http\Controllers;
use App\Http\Resources\OrderResource;
use Illuminate\Http\Request;
use App\Repositories\OrderRepository;
class OrderController extends Controller
{
private OrderRepository $orderRepository;
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function __construct(OrderRepository $orderRepository)
{
$this->orderRepository = $orderRepository;
}
public function index(Request $request)
{
$order = $this->orderRepository->paginate($request->page);
return response()->json([
'success' => true,
'message' => '',
'data' => OrderResource::collection($order)
]);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create(Request $request)
{
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$order = $this->orderRepository->create($request->only(['id', 'details', 'client', 'is_fulfilled']));
return response()->json([
'success' => true,
'message' => '',
'data' => $order
]);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show(Request $request)
{
$order = $this->orderRepository->getById($request->id);
return response()->json([
'success' => true,
'message' => '',
'data' => $order
]);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit(Request $request)
{
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$order = $this->orderRepository->update($request->id,
$request->only(['id', 'details', 'client', 'is_fulfilled']));
return response()->json([
'success' => true,
'message' => '',
'data' => $order
]);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$order = $this->orderRepository->deleteById($request->id);
return response()->json([
'success' => true,
'message' => '',
'data' => $order
]);
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class OrderDetailController extends Controller
{
//
}
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class OrderResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $this->id,
'details' => $this->details,
'client' => $this->client,
'user' => new UserResource($this->user),
'total' => $this->total,
'status' => $this->status_text,
'is_fulfilled' => $this->is_fulfilled,
'created_at' => $this->created_at
];
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
use HasFactory;
const UN_FULFILLED = false;
const FULFILLED = true;
const STATUS_PENDING = 0;
const STATUS_CONFIRMED = 1;
const STATUS_COMPLETED = 2;
const STATUS_CANCELED = 3;
protected $guarded = [];
protected $casts = [
'is_fulfilled' => 'boolean',
'total' => 'integer',
];
protected $attributes = [
'is_fulfilled' => Order::UN_FULFILLED,
];
public function getStatusTextAttribute($value)
{
if ($value == Order::STATUS_PENDING) {
return 'pending';
}
if ($value == Order::STATUS_CONFIRMED) {
return 'confirmed';
}
if ($value == Order::STATUS_COMPLETED) {
return 'completed';
}
if ($value == Order::STATUS_CANCELED) {
return 'canceled';
}
return $value;
}
public function details()
{
return $this->hasMany(OrderDetail::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class OrderDetail extends Model
{
use HasFactory;
protected $guarded = [];
public function order()
{
return $this->belongsTo(Order::class);
}
public function getPayMoneyAttribute(){
return $this->unit_price * $this->quantity * (100 - $this->discount) / 100;
}
}
...@@ -2,13 +2,14 @@ ...@@ -2,13 +2,14 @@
namespace App\Models; namespace App\Models;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens; use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable class User extends Authenticatable implements JWTSubject
{ {
use HasApiTokens, HasFactory, Notifiable; use HasApiTokens, HasFactory, Notifiable;
const STATUS_ACTIVE = 1; const STATUS_ACTIVE = 1;
...@@ -47,4 +48,26 @@ public function comments() ...@@ -47,4 +48,26 @@ public function comments()
{ {
return $this->hasMany(Comment::class); return $this->hasMany(Comment::class);
} }
// Rest omitted for brevity
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* @return array
*/
public function getJWTCustomClaims()
{
return [];
}
} }
<?php
namespace App\Repositories;
abstract class BaseRepository
{
protected $model;
public function getAll()
{
return $this->model->latest()->all();
}
public function getById($id)
{
return $this->model->findOrFail($id);
}
public function deleteById($id)
{
return $this->getById($id)->delete();
}
public function create(array $details)
{
return $this->model->create($details);
}
public function update($id, array $newDetails)
{
return $this->getById($id)->update($newDetails);
}
public function paginate($size = 15)
{
return $this->model->latest()->paginate($size);
}
}
\ No newline at end of file
<?php
namespace App\Repositories;
use App\Models\Order;
use App\Repositories\BaseRepository;
class OrderRepository extends BaseRepository
{
protected $model;
public function __construct(Order $model)
{
$this->model = $model;
}
public function getAll()
{
return $this->model->latest()->all();
}
public function getFulfilledOrder()
{
$this->model->where('is_fulfilled', true);
}
public function getListOrderOfUser($id)
{
return $order = $this->model->with('user')->whereHas('user', function($query) use ($id) {
$query->where('id', $id);
})->paginate();
}
public function getListOrderByStatus($status)
{
return $order = $this->model->where('status', $status)->paginate();
}
}
<?php
namespace App\Repositories;
use App\Models\User;
use App\Repositories\BaseRepository;
class UserRepository extends BaseRepository
{
protected $model;
public function __construct(User $model)
{
$this->model = $model;
}
public function getFulfilledOrder()
{
$this->model->where('is_fulfilled', true);
}
}
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
"laravel/framework": "^8.75", "laravel/framework": "^8.75",
"laravel/sanctum": "^2.11", "laravel/sanctum": "^2.11",
"laravel/tinker": "^2.5", "laravel/tinker": "^2.5",
"laravel/ui": "^3.4" "laravel/ui": "^3.4",
"tymon/jwt-auth": "*"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "^3.7", "barryvdh/laravel-debugbar": "^3.7",
......
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
*/ */
'guards' => [ 'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
'web' => [ 'web' => [
'driver' => 'session', 'driver' => 'session',
'provider' => 'users', 'provider' => 'users',
......
This diff is collapsed.
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class OrderDetailFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
//
];
}
}
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class OrderFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'user_id' => rand(1, 10),
'details' => $this->faker->sentences(4, true),
'client' => $this->faker->name(),
'is_fulfilled' => $this->faker->boolean(),
];
}
}
<?php
use App\Models\Order;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateOrdersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->text('details')->nullable();
$table->string('client')->nullable();
$table->unsignedInteger('user_id');
$table->unsignedInteger('total')->default(0);
$table->unsignedSmallInteger('status')->default(Order::STATUS_PENDING);
$table->boolean('is_fulfilled')->default(Order::UN_FULFILLED);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('orders');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateOrderDetailsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('order_details', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('unit_price')->default(0);
$table->unsignedInteger('quantity')->default(0);
$table->unsignedInteger('discount')->default(0);
$table->unsignedInteger('order_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('order_details');
}
}
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
use App\Models\Category; use App\Models\Category;
use App\Models\Post; use App\Models\Post;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use App\Models\Order;
use App\Models\OrderDetail;
class DatabaseSeeder extends Seeder class DatabaseSeeder extends Seeder
{ {
...@@ -19,6 +21,7 @@ public function run() ...@@ -19,6 +21,7 @@ public function run()
User::factory(1)->create([ User::factory(1)->create([
'role' => User::ROLE_ADMIN 'role' => User::ROLE_ADMIN
]); ]);
Order::factory(10)->has(OrderDetail::factory()->count(3), 'details')->create();
User::factory(9)->has(Post::factory()->hasCategories(1)->count(30), 'posts')->create(); User::factory(9)->has(Post::factory()->hasCategories(1)->count(30), 'posts')->create();
Category::factory(10)->create(); Category::factory(10)->create();
} }
......
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class OrderDetailSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//
}
}
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Order;
class OrderSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Order::factory()->times(50)->create();
}
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Auth;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| API Routes | API Routes
...@@ -17,3 +17,26 @@ ...@@ -17,3 +17,26 @@
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::group([
'middleware' => 'api',
'prefix' => 'auth'
], function ($router) {
Route::post('login', [App\Http\Controllers\AuthController::class, 'login']);
Route::post('logout', [App\Http\Controllers\AuthController::class, 'logout']);
Route::post('refresh', [App\Http\Controllers\AuthController::class, 'refresh']);
Route::get('user-profile', [App\Http\Controllers\AuthController::class, 'userProfile']);
Route::post('change-password', [App\Http\Controllers\AuthController::class, 'changePassword']);
});
Route::group([
'middleware' => 'api',
], function ($router) {
Route::get('orders/search', [App\Http\Controllers\Api\OrderController::class, 'search']);
Route::resource('orders', App\Http\Controllers\Api\OrderController::class);
});
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
use App\Http\Controllers\UserController; use App\Http\Controllers\UserController;
use App\Http\Controllers\PostController; use App\Http\Controllers\PostController;
use App\Http\Controllers\Auth\LoginController; use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\OrderController;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
...@@ -25,4 +26,6 @@ ...@@ -25,4 +26,6 @@
}); });
Route::get('/', [App\Http\Controllers\HomeController::class, 'index'])->name('home'); Route::get('/', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home'); Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
Route::resource('orders', OrderController::class);
}); });
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment