From 3088349f7d9df3a5133c07db0320dd1bba325b5b Mon Sep 17 00:00:00 2001 From: cortzuy Date: Thu, 25 Aug 2022 22:32:24 +0800 Subject: [PATCH 1/6] Create models --- app/Models/Project.php | 17 +++++++ app/Models/Task.php | 23 +++++++++ app/Models/User.php | 45 ++++-------------- app/Models/User_.php | 44 +++++++++++++++++ .../2014_10_12_000000_create_users_table.php | 8 ++-- ...022_08_25_141036_create_projects_table.php | 32 +++++++++++++ .../2022_08_25_141049_create_tasks_table.php | 47 +++++++++++++++++++ 7 files changed, 175 insertions(+), 41 deletions(-) create mode 100644 app/Models/Project.php create mode 100644 app/Models/Task.php create mode 100644 app/Models/User_.php create mode 100644 database/migrations/2022_08_25_141036_create_projects_table.php create mode 100644 database/migrations/2022_08_25_141049_create_tasks_table.php diff --git a/app/Models/Project.php b/app/Models/Project.php new file mode 100644 index 0000000..97bea82 --- /dev/null +++ b/app/Models/Project.php @@ -0,0 +1,17 @@ +belongsTo(Task::class); + } +} diff --git a/app/Models/Task.php b/app/Models/Task.php new file mode 100644 index 0000000..bb198f6 --- /dev/null +++ b/app/Models/Task.php @@ -0,0 +1,23 @@ +hasOne(User::class); + } + + public function projects() + { + return $this->hasOne(Project::class); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 8996368..91fd372 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,43 +2,16 @@ namespace App\Models; -use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; -use Illuminate\Foundation\Auth\User as Authenticatable; -use Illuminate\Notifications\Notifiable; -use Laravel\Sanctum\HasApiTokens; +use Illuminate\Database\Eloquent\Model; +use Laravel\Passport\HasApiTokens; -class User extends Authenticatable +class User extends Model { - use HasApiTokens, HasFactory, Notifiable; - - /** - * The attributes that are mass assignable. - * - * @var array - */ - protected $fillable = [ - 'name', - 'email', - 'password', - ]; - - /** - * The attributes that should be hidden for serialization. - * - * @var array - */ - protected $hidden = [ - 'password', - 'remember_token', - ]; - - /** - * The attributes that should be cast. - * - * @var array - */ - protected $casts = [ - 'email_verified_at' => 'datetime', - ]; + use HasFactory; + + public function Task() + { + return $this->belongsTo(Task::class); + } } diff --git a/app/Models/User_.php b/app/Models/User_.php new file mode 100644 index 0000000..8996368 --- /dev/null +++ b/app/Models/User_.php @@ -0,0 +1,44 @@ + + */ + protected $fillable = [ + 'name', + 'email', + 'password', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + 'email_verified_at' => 'datetime', + ]; +} diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 621a24e..d6beb0e 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -14,12 +14,10 @@ class CreateUsersTable extends Migration public function up() { Schema::create('users', function (Blueprint $table) { - $table->id(); - $table->string('name'); - $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); + $table->bigIncrements('id'); + $table->string('username')->unique(); $table->string('password'); - $table->rememberToken(); + $table->string('role'); $table->timestamps(); }); } diff --git a/database/migrations/2022_08_25_141036_create_projects_table.php b/database/migrations/2022_08_25_141036_create_projects_table.php new file mode 100644 index 0000000..b34fa90 --- /dev/null +++ b/database/migrations/2022_08_25_141036_create_projects_table.php @@ -0,0 +1,32 @@ +bigIncrements('id'); + $table->string('name')->unique(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('projects'); + } +} diff --git a/database/migrations/2022_08_25_141049_create_tasks_table.php b/database/migrations/2022_08_25_141049_create_tasks_table.php new file mode 100644 index 0000000..8cb416c --- /dev/null +++ b/database/migrations/2022_08_25_141049_create_tasks_table.php @@ -0,0 +1,47 @@ +bigIncrements('id'); + $table->string('title'); + $table->text('description')->nullable(); + $table->string('status'); + $table->unsignedBigInteger('user_id'); + $table->unsignedBigInteger('project_id'); + $table->timestamps(); + + $table->foreign('user_id') + ->references('id') + ->on('users') + ->onDelete('cascade'); + + $table->foreign('project_id') + ->references('id') + ->on('projects') + ->onDelete('cascade'); + + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('tasks'); + } +} From 063ec90b4f4dd9b61491a97ec3c4b7a195edddec Mon Sep 17 00:00:00 2001 From: cortzuy Date: Thu, 25 Aug 2022 22:48:40 +0800 Subject: [PATCH 2/6] Create REST APIs --- app/Http/Controllers/API/AuthController.php | 57 +++++++++++++++ .../Controllers/API/ProjectController.php | 65 +++++++++++++++++ app/Http/Controllers/API/TaskController.php | 71 +++++++++++++++++++ app/Http/Controllers/API/UserController.php | 67 +++++++++++++++++ app/Http/Resources/ProjectResource.php | 13 ++++ app/Http/Resources/TaskResource.php | 13 ++++ app/Http/Resources/UserResource.php | 13 ++++ app/Providers/AuthServiceProvider.php | 5 +- composer.json | 1 + config/app.php | 1 + config/auth.php | 5 ++ routes/api.php | 13 +++- 12 files changed, 321 insertions(+), 3 deletions(-) create mode 100644 app/Http/Controllers/API/AuthController.php create mode 100644 app/Http/Controllers/API/ProjectController.php create mode 100644 app/Http/Controllers/API/TaskController.php create mode 100644 app/Http/Controllers/API/UserController.php create mode 100644 app/Http/Resources/ProjectResource.php create mode 100644 app/Http/Resources/TaskResource.php create mode 100644 app/Http/Resources/UserResource.php diff --git a/app/Http/Controllers/API/AuthController.php b/app/Http/Controllers/API/AuthController.php new file mode 100644 index 0000000..3a6fc88 --- /dev/null +++ b/app/Http/Controllers/API/AuthController.php @@ -0,0 +1,57 @@ +all(), [ + 'username' => 'required|max:55|unique:users', + 'password' => 'required|min:6' + ]); + + if($validator->fails()){ + return response(['error' => $validator->errors()]); + } + + $user = User::create([ + 'username' => $request->username, + 'password' => Hash::make($request->password), + 'role' => $request->role, + ]); + + $accessToken = $user->createToken('authToken')->accessToken; + + return response([ 'user' => $user, 'access_token' => $accessToken]); + } + + public function login(Request $request) + { + $data = $request->all(); + + $validator = Validator::make($data, [ + 'username' => 'required', + 'password' => 'required|min:6' + ]); + + if($validator->fails()){ + return response(['error' => $validator->errors()]); + } + + if (!auth()->attempt($data)) { + return response(['message' => 'Login credentials are invaild']); + } + + $accessToken = auth()->user()->createToken('authToken')->accessToken; + + return response(['access_token' => $accessToken]); + + } +} diff --git a/app/Http/Controllers/API/ProjectController.php b/app/Http/Controllers/API/ProjectController.php new file mode 100644 index 0000000..9b64952 --- /dev/null +++ b/app/Http/Controllers/API/ProjectController.php @@ -0,0 +1,65 @@ + ProjectResource::collection($Projects)]); + } + + public function store(Request $request) + { + $data = $request->all(); + + $validator = Validator::make($data, [ + 'name' => 'required|max:255', + ]); + + if($validator->fails()){ + return response(['error' => $validator->errors(), 'Validation Error']); + } + + $Project = Project::create($data); + + return response(['Project' => new ProjectResource($Project), 'message' => 'Project created successfully']); + } + + public function show(Project $Project) + { + return response(['Project' => new ProjectResource($Project)]); + } + + public function update(Request $request, Project $Project) + { + $data = $request->all(); + + $validator = Validator::make($data, [ + 'name' => 'required|max:255', + ]); + + if($validator->fails()){ + return response(['error' => $validator->errors(), 'Validation Error']); + } + + $Project->update($data); + + return response(['Project' => new ProjectResource($Project), 'message' => 'Project updated successfully']); + } + + public function destroy(Project $Project) + { + $Project->delete(); + + return response(['message' => 'Project deleted successfully']); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/API/TaskController.php b/app/Http/Controllers/API/TaskController.php new file mode 100644 index 0000000..eb7d798 --- /dev/null +++ b/app/Http/Controllers/API/TaskController.php @@ -0,0 +1,71 @@ + TaskResource::collection($Tasks)]); + } + + public function store(Request $request) + { + $data = $request->all(); + + $validator = Validator::make($data, [ + 'title' => 'required|max:255', + 'status' => 'required', + 'project_id' => 'required', + 'user_id' => 'required', + ]); + + if($validator->fails()){ + return response(['error' => $validator->errors(), 'Validation Error']); + } + + $Task = Task::create($data); + + return response(['Task' => new TaskResource($Task), 'message' => 'Task created successfully']); + } + + public function show(Task $Task) + { + return response(['Task' => new TaskResource($Task)]); + } + + public function update(Request $request, Task $Task) + { + $data = $request->all(); + + $validator = Validator::make($data, [ + 'title' => 'required|max:255', + 'status' => 'required', + 'project_id' => 'required', + 'user_id' => 'required', + ]); + + if($validator->fails()){ + return response(['error' => $validator->errors(), 'Validation Error']); + } + + $Task->update($data); + + return response(['Task' => new TaskResource($Task), 'message' => 'Task updated successfully']); + } + + public function destroy(Task $Task) + { + $Task->delete(); + + return response(['message' => 'Task deleted successfully']); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/API/UserController.php b/app/Http/Controllers/API/UserController.php new file mode 100644 index 0000000..6fcd120 --- /dev/null +++ b/app/Http/Controllers/API/UserController.php @@ -0,0 +1,67 @@ + UserResource::collection($Users)]); + } + + public function store(Request $request) + { + $data = $request->all(); + + $validator = Validator::make($data, [ + 'username' => 'required', + 'password' => 'required|min:6', + ]); + + if($validator->fails()){ + return response(['error' => $validator->errors(), 'Validation Error']); + } + + $User = User::create($data); + + return response(['User' => new UserResource($User), 'message' => 'User created successfully']); + } + + public function show(User $User) + { + return response(['User' => new UserResource($User)]); + } + + public function update(Request $request, User $User) + { + $data = $request->all(); + + $validator = Validator::make($data, [ + 'username' => 'required', + 'password' => 'required|min:6', + ]); + + if($validator->fails()){ + return response(['error' => $validator->errors(), 'Validation Error']); + } + + $User->update($data); + + return response(['User' => new UserResource($User), 'message' => 'User updated successfully']); + } + + public function destroy(User $User) + { + $User->delete(); + + return response(['message' => 'User deleted successfully']); + } +} \ No newline at end of file diff --git a/app/Http/Resources/ProjectResource.php b/app/Http/Resources/ProjectResource.php new file mode 100644 index 0000000..ba96ecf --- /dev/null +++ b/app/Http/Resources/ProjectResource.php @@ -0,0 +1,13 @@ + */ protected $policies = [ - // 'App\Models\Model' => 'App\Policies\ModelPolicy', + 'App\Models\Model' => 'App\Policies\ModelPolicy', ]; /** @@ -24,7 +25,7 @@ class AuthServiceProvider extends ServiceProvider public function boot() { $this->registerPolicies(); - + Passport::routes(); // } } diff --git a/composer.json b/composer.json index 2b0c115..27aee5d 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "fruitcake/laravel-cors": "^2.0", "guzzlehttp/guzzle": "^7.0.1", "laravel/framework": "^8.75", + "laravel/passport": "^10.3", "laravel/sanctum": "^2.11", "laravel/tinker": "^2.5" }, diff --git a/config/app.php b/config/app.php index a8d1a82..28b8bdc 100644 --- a/config/app.php +++ b/config/app.php @@ -161,6 +161,7 @@ Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, Illuminate\View\ViewServiceProvider::class, + Laravel\Passport\PassportServiceProvider::class, /* * Package Service Providers... diff --git a/config/auth.php b/config/auth.php index d8c6cee..28cd01a 100644 --- a/config/auth.php +++ b/config/auth.php @@ -40,6 +40,11 @@ 'driver' => 'session', 'provider' => 'users', ], + 'api' => [ + 'driver' => 'passport', + 'provider' => 'users', + 'hash' => false, + ], ], /* diff --git a/routes/api.php b/routes/api.php index eb6fa48..7971873 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,6 +2,10 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; +use App\Http\Controllers\API\AuthController; +use App\Http\Controllers\API\ProjectController; +use App\Http\Controllers\API\UserController; +use App\Http\Controllers\API\TaskController; /* |-------------------------------------------------------------------------- @@ -14,6 +18,13 @@ | */ -Route::middleware('auth:sanctum')->get('/user', function (Request $request) { +Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); }); + +Route::post('/v1/user/register', [AuthController::class, 'register']); +Route::post('/v1/user/login', [AuthController::class, 'login']); + +Route::apiResource('/v1/project', ProjectController::class)->middleware('auth:api'); +Route::apiResource('/v1/users', UserController::class)->middleware('auth:api'); +Route::apiResource('/v1/tasks', TaskController::class)->middleware('auth:api'); \ No newline at end of file From d48ff7bbe4e51d58ac1d05e4ce4a2da16ea446d1 Mon Sep 17 00:00:00 2001 From: cortzuy Date: Thu, 25 Aug 2022 23:38:28 +0800 Subject: [PATCH 3/6] Implement features --- app/Http/Controllers/API/AuthController.php | 2 +- .../Controllers/API/ProjectController.php | 21 +++++++++++++ app/Http/Controllers/API/TaskController.php | 31 +++++++++++++++++++ app/Http/Controllers/API/UserController.php | 31 +++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/API/AuthController.php b/app/Http/Controllers/API/AuthController.php index 3a6fc88..e97086b 100644 --- a/app/Http/Controllers/API/AuthController.php +++ b/app/Http/Controllers/API/AuthController.php @@ -24,7 +24,7 @@ public function register(Request $request) $user = User::create([ 'username' => $request->username, 'password' => Hash::make($request->password), - 'role' => $request->role, + 'role' => 'Admin', ]); $accessToken = $user->createToken('authToken')->accessToken; diff --git a/app/Http/Controllers/API/ProjectController.php b/app/Http/Controllers/API/ProjectController.php index 9b64952..936ef08 100644 --- a/app/Http/Controllers/API/ProjectController.php +++ b/app/Http/Controllers/API/ProjectController.php @@ -17,8 +17,20 @@ public function index() return response(['Projects' => ProjectResource::collection($Projects)]); } + private function checkUserRole() + { + if(auth('api')->user()->role != 'PRODUCT_OWNER'){ + return false; + } + return true; + } + public function store(Request $request) { + if($request->role != 'PRODUCT_OWNER'){ + return Response::deny('You must be a PRODUCT_OWNER.'); + } + $data = $request->all(); $validator = Validator::make($data, [ @@ -41,6 +53,11 @@ public function show(Project $Project) public function update(Request $request, Project $Project) { + + if(!$this->checkUserRole()){ + return Response::deny('You must be a PRODUCT_OWNER.'); + } + $data = $request->all(); $validator = Validator::make($data, [ @@ -58,6 +75,10 @@ public function update(Request $request, Project $Project) public function destroy(Project $Project) { + if(!$this->checkUserRole()){ + return Response::deny('You must be a PRODUCT_OWNER.'); + } + $Project->delete(); return response(['message' => 'Project deleted successfully']); diff --git a/app/Http/Controllers/API/TaskController.php b/app/Http/Controllers/API/TaskController.php index eb7d798..a6ea13c 100644 --- a/app/Http/Controllers/API/TaskController.php +++ b/app/Http/Controllers/API/TaskController.php @@ -11,15 +11,31 @@ class TaskController extends Controller { + public $tasks_status = ['NOT_STARTED', 'IN_PROGRESS', 'READY_FOR_TEST', 'COMPLETED']; + public function index() { $Tasks = Task::all(); return response(['Tasks' => TaskResource::collection($Tasks)]); } + private function checkUserRole() + { + if(auth('api')->user()->role != 'PRODUCT_OWNER'){ + return false; + } + return true; + } + public function store(Request $request) { + + if(!$this->checkUserRole()){ + return Response::deny('You must be a PRODUCT_OWNER.'); + } + $data = $request->all(); + $data['status'] = 'NOT_STARTED'; $validator = Validator::make($data, [ 'title' => 'required|max:255', @@ -32,6 +48,10 @@ public function store(Request $request) return response(['error' => $validator->errors(), 'Validation Error']); } + if(!in_array($data['status'], $this->tasks_status)){ + return Response::deny("You must provide task status from following ['NOT_STARTED', 'IN_PROGRESS', 'READY_FOR_TEST', 'COMPLETED']"); + } + $Task = Task::create($data); return response(['Task' => new TaskResource($Task), 'message' => 'Task created successfully']); @@ -46,6 +66,13 @@ public function update(Request $request, Task $Task) { $data = $request->all(); + if(!$this->checkUserRole()){ + if(auth('api')->user()->id != $data['user_id']){ + return Response::deny('You have no permission to edit task'); + } + return Response::deny('You must be a PRODUCT_OWNER.'); + } + $validator = Validator::make($data, [ 'title' => 'required|max:255', 'status' => 'required', @@ -57,6 +84,10 @@ public function update(Request $request, Task $Task) return response(['error' => $validator->errors(), 'Validation Error']); } + if(!in_array($request->status, $tasks_status)){ + return Response::deny("You must provide task status from following ['NOT_STARTED', 'IN_PROGRESS', 'READY_FOR_TEST', 'COMPLETED']"); + } + $Task->update($data); return response(['Task' => new TaskResource($Task), 'message' => 'Task updated successfully']); diff --git a/app/Http/Controllers/API/UserController.php b/app/Http/Controllers/API/UserController.php index 6fcd120..b5b6c57 100644 --- a/app/Http/Controllers/API/UserController.php +++ b/app/Http/Controllers/API/UserController.php @@ -11,19 +11,38 @@ class UserController extends Controller { + public function __construct(Request $request) { + if($request->username != 'Admin'){ + return Response::deny('You must be an administrator.'); + } + } + public function index() { $Users = User::all(); return response(['Users' => UserResource::collection($Users)]); } + private function checkUserRole() + { + if(auth('api')->user()->role != 'Admin'){ + return false; + } + return true; + } + public function store(Request $request) { + if(!$this->checkUserRole()){ + return Response::deny('You must be a Admin.'); + } + $data = $request->all(); $validator = Validator::make($data, [ 'username' => 'required', 'password' => 'required|min:6', + 'role' => 'required', ]); if($validator->fails()){ @@ -37,11 +56,19 @@ public function store(Request $request) public function show(User $User) { + if(!$this->checkUserRole()){ + return Response::deny('You must be a Admin.'); + } + return response(['User' => new UserResource($User)]); } public function update(Request $request, User $User) { + if(!$this->checkUserRole()){ + return Response::deny('You must be a Admin.'); + } + $data = $request->all(); $validator = Validator::make($data, [ @@ -60,6 +87,10 @@ public function update(Request $request, User $User) public function destroy(User $User) { + if(!$this->checkUserRole()){ + return Response::deny('You must be a Admin.'); + } + $User->delete(); return response(['message' => 'User deleted successfully']); From 95d32307d0a6e0083fda2cffdccb33cf5e87dbb9 Mon Sep 17 00:00:00 2001 From: cortzuy Date: Thu, 25 Aug 2022 23:50:00 +0800 Subject: [PATCH 4/6] Write test --- app/Http/Controllers/API/AuthController.php | 2 +- app/Http/Controllers/API/TaskController.php | 27 +++++++++++++++++++++ app/Models/User.php | 8 +++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/API/AuthController.php b/app/Http/Controllers/API/AuthController.php index e97086b..3a6fc88 100644 --- a/app/Http/Controllers/API/AuthController.php +++ b/app/Http/Controllers/API/AuthController.php @@ -24,7 +24,7 @@ public function register(Request $request) $user = User::create([ 'username' => $request->username, 'password' => Hash::make($request->password), - 'role' => 'Admin', + 'role' => $request->role, ]); $accessToken = $user->createToken('authToken')->accessToken; diff --git a/app/Http/Controllers/API/TaskController.php b/app/Http/Controllers/API/TaskController.php index a6ea13c..b5259f5 100644 --- a/app/Http/Controllers/API/TaskController.php +++ b/app/Http/Controllers/API/TaskController.php @@ -5,6 +5,8 @@ use Illuminate\Auth\Access\Response; use App\Http\Controllers\Controller; use App\Models\Task; +use App\Models\User; +use App\Models\Project; use Illuminate\Http\Request; use App\Http\Resources\TaskResource; use Validator; @@ -52,8 +54,22 @@ public function store(Request $request) return Response::deny("You must provide task status from following ['NOT_STARTED', 'IN_PROGRESS', 'READY_FOR_TEST', 'COMPLETED']"); } + $user = User::find($request->user_id); + if(!$user){ + return Response::deny("User not found to assign task!"); + } + $project = Project::find($request->project_id); + + if(!$project){ + return Response::deny("Project not found!"); + } + $Task = Task::create($data); + $user->role = 'PRODUCT_OWNER'; + + $user->save(); + return response(['Task' => new TaskResource($Task), 'message' => 'Task created successfully']); } @@ -88,6 +104,17 @@ public function update(Request $request, Task $Task) return Response::deny("You must provide task status from following ['NOT_STARTED', 'IN_PROGRESS', 'READY_FOR_TEST', 'COMPLETED']"); } + + $user = User::find($request->user_id); + if(!$user){ + return Response::deny("User not found to assign task!"); + } + $project = Project::find($request->project_id); + + if(!$project){ + return Response::deny("Project not found!"); + } + $Task->update($data); return response(['Task' => new TaskResource($Task), 'message' => 'Task updated successfully']); diff --git a/app/Models/User.php b/app/Models/User.php index 91fd372..6aaa24a 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -5,11 +5,13 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Laravel\Passport\HasApiTokens; +use Illuminate\Notifications\Notifiable; +use Illuminate\Foundation\Auth\User as Authenticatable; -class User extends Model +class User extends Authenticatable { - use HasFactory; - + use HasFactory, Notifiable, HasApiTokens; + protected $fillable = ['username', 'password', 'role']; public function Task() { return $this->belongsTo(Task::class); From 49b92c3f8992d2a87d1dd797eeb63cc0a6838fa6 Mon Sep 17 00:00:00 2001 From: cortzuy Date: Thu, 25 Aug 2022 23:54:07 +0800 Subject: [PATCH 5/6] Implement pagination --- app/Http/Controllers/API/ProjectController.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/API/ProjectController.php b/app/Http/Controllers/API/ProjectController.php index 936ef08..c3d5748 100644 --- a/app/Http/Controllers/API/ProjectController.php +++ b/app/Http/Controllers/API/ProjectController.php @@ -13,8 +13,14 @@ class ProjectController extends Controller { public function index() { - $Projects = Project::all(); - return response(['Projects' => ProjectResource::collection($Projects)]); + $pageSize = isset($_GET['pageSize'])?$_GET['pageSize']:2; + $sortBy = isset($_GET['sortBy'])?$_GET['sortBy']:'name'; + $sortDirection = isset($_GET['sortDirection'])?$_GET['sortDirection']:'ASC'; + $Projects = Project::orderBy($sortBy, $sortDirection); + $q = isset($_GET['q'])?$_GET['q']:''; + $Projects = $q?$Projects->where('name', 'LIKE', "%$q%"):$Projects; + $Projects = $Projects->paginate($pageSize); + return response(['Projects' => $Projects]); } private function checkUserRole() From 18878564fcc2fd6e621aad33a2c608f929307333 Mon Sep 17 00:00:00 2001 From: cortzuy Date: Fri, 26 Aug 2022 09:20:53 +0800 Subject: [PATCH 6/6] Add postman collection --- docs/Telekom Test.postman_collection.json | 793 ++++++++++++++++++++++ 1 file changed, 793 insertions(+) create mode 100644 docs/Telekom Test.postman_collection.json diff --git a/docs/Telekom Test.postman_collection.json b/docs/Telekom Test.postman_collection.json new file mode 100644 index 0000000..c049f0d --- /dev/null +++ b/docs/Telekom Test.postman_collection.json @@ -0,0 +1,793 @@ +{ + "info": { + "_postman_id": "45065865-dc51-4846-84d1-a4a8087f76af", + "name": "Telekom Test", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "217133" + }, + "item": [ + { + "name": "https://telekom.local/api/v1/user/register", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "username", + "value": "admin", + "type": "text" + }, + { + "key": "password", + "value": "123456", + "type": "text" + }, + { + "key": "role", + "value": "Admin", + "type": "text" + } + ] + }, + "url": { + "raw": "https://telekom.local/api/v1/user/register", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "user", + "register" + ] + } + }, + "response": [ + { + "name": "https://telekom.local/api/v1/user/register", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "username", + "value": "admin", + "type": "text" + }, + { + "key": "password", + "value": "123456", + "type": "text" + }, + { + "key": "role", + "value": "Admin", + "type": "text" + } + ] + }, + "url": { + "raw": "https://telekom.local/api/v1/user/register", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "user", + "register" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Host", + "value": "telekom.local" + }, + { + "key": "Date", + "value": "Thu, 25 Aug 2022 23:35:38 GMT" + }, + { + "key": "Date", + "value": "Thu, 25 Aug 2022 23:35:38 GMT" + }, + { + "key": "Connection", + "value": "close" + }, + { + "key": "X-Powered-By", + "value": "PHP/7.4.11" + }, + { + "key": "Cache-Control", + "value": "no-cache, private" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-RateLimit-Limit", + "value": "60" + }, + { + "key": "X-RateLimit-Remaining", + "value": "59" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + } + ], + "cookie": [], + "body": "{\n \"user\": {\n \"username\": \"admin\",\n \"password\": \"$2y$10$bRjrwMvvRZaR502.kzBfUefO1E96y0rmRby7wGiTJc8qOJUAo4c9.\",\n \"role\": \"Admin\",\n \"updated_at\": \"2022-08-25T10:35:36.000000Z\",\n \"created_at\": \"2022-08-25T10:35:36.000000Z\",\n \"id\": 4 }" + } + ] + }, + { + "name": "https://telekom.local/api/v1/user/register", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + }, + { + "key": "", + "value": "", + "type": "text", + "disabled": true + }, + { + "key": "", + "value": "", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "username", + "value": "test-user2", + "type": "text" + }, + { + "key": "password", + "value": "123456", + "type": "text" + }, + { + "key": "role", + "value": "PRODUCT_OWNER", + "type": "text" + } + ] + }, + "url": { + "raw": "https://telekom.local/api/v1/user/register", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "user", + "register" + ] + } + }, + "response": [] + }, + { + "name": "https://telekom.local/api/v1/project", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "name", + "value": "Filemanager Project", + "type": "text" + } + ] + }, + "url": { + "raw": "https://telekom.local/api/v1/project", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "project" + ] + } + }, + "response": [ + { + "name": "https://telekom.local/api/v1/project", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "name", + "value": "Filemanager Project", + "type": "text" + } + ] + }, + "url": { + "raw": "https://telekom.local/api/v1/project", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "project" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Host", + "value": "telekom.local" + }, + { + "key": "Date", + "value": "Thu, 23 Aug 2022 23:56:51 GMT" + }, + { + "key": "Date", + "value": "Thu, 23 Aug 2022 23:56:51 GMT" + }, + { + "key": "Connection", + "value": "close" + }, + { + "key": "X-Powered-By", + "value": "PHP/7.4.11" + }, + { + "key": "Cache-Control", + "value": "no-cache, private" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-RateLimit-Limit", + "value": "60" + }, + { + "key": "X-RateLimit-Remaining", + "value": "59" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + } + ], + "cookie": [], + "body": "{\n \"Project\": {\n \"name\": \"Filemanager Project\",\n \"updated_at\": \"2022-08-25T10:56:51.000000Z\",\n \"created_at\": \"2022-08-25T10:56:51.000000Z\",\n \"id\": 5\n },\n \"message\": \"Project created successfully\"\n}" + } + ] + }, + { + "name": "https://telekom.local/api/v1/tasks", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "title", + "value": "Task 2 to test-user2", + "type": "text" + }, + { + "key": "description", + "value": "Assigned to test-user2", + "type": "text" + }, + { + "key": "project_id", + "value": "5", + "type": "text" + }, + { + "key": "user_id", + "value": "5", + "type": "text" + } + ] + }, + "url": { + "raw": "https://telekom.local/api/v1/tasks", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "tasks" + ] + } + }, + "response": [ + { + "name": "https://telekom.local/api/v1/tasks", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "title", + "value": "Task 2 to test-user2", + "type": "text" + }, + { + "key": "description", + "value": "Assigned to test-user2", + "type": "text" + }, + { + "key": "project_id", + "value": "5", + "type": "text" + }, + { + "key": "user_id", + "value": "5", + "type": "text" + } + ] + }, + "url": { + "raw": "https://telekom.local/api/v1/tasks", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "tasks" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Host", + "value": "telekom.local" + }, + { + "key": "Date", + "value": "Thu, 25 Aug 2022 23:57:56 GMT" + }, + { + "key": "Date", + "value": "Thu, 25 Aug 2022 23:57:56 GMT" + }, + { + "key": "Connection", + "value": "close" + }, + { + "key": "X-Powered-By", + "value": "PHP/7.4.11" + }, + { + "key": "Cache-Control", + "value": "no-cache, private" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-RateLimit-Limit", + "value": "60" + }, + { + "key": "X-RateLimit-Remaining", + "value": "59" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + } + ], + "cookie": [], + "body": "{\n \"Task\": {\n \"title\": \"Task 2 to test-user2\",\n \"description\": \"Assigned to test-user2\",\n \"project_id\": \"5\",\n \"user_id\": \"5\",\n \"status\": \"NOT_STARTED\",\n \"updated_at\": \"2022-08-25T10:57:56.000000Z\",\n \"created_at\": \"2022-08-25T10:57:56.000000Z\",\n \"id\": 5\n },\n \"message\": \"Task created successfully\"\n}" + } + ] + }, + { + "name": "https://telekom.local/api/v1/tasks/", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "title", + "value": "Task1 Assigned to test-user1", + "type": "text" + }, + { + "key": "description", + "value": "task 1", + "type": "text" + }, + { + "key": "project_id", + "value": "5", + "type": "text" + }, + { + "key": "user_id", + "value": "6", + "type": "text" + } + ] + }, + "url": { + "raw": "https://telekom.local/api/v1/tasks", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "tasks" + ], + "query": [ + { + "key": "", + "value": "", + "disabled": true + } + ] + } + }, + "response": [ + { + "name": "https://telekom.local/api/v1/tasks/", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "title", + "value": "Task1 Assigned to test-user1", + "type": "text" + }, + { + "key": "description", + "value": "task 1", + "type": "text" + }, + { + "key": "project_id", + "value": "5", + "type": "text" + }, + { + "key": "user_id", + "value": "6", + "type": "text" + } + ] + }, + "url": { + "raw": "https://telekom.local/api/v1/tasks", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "tasks" + ], + "query": [ + { + "key": "", + "value": null, + "disabled": true + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Host", + "value": "telekom.local" + }, + { + "key": "Date", + "value": "Thu, 25 Aug 2022 23:01:18 GMT" + }, + { + "key": "Date", + "value": "Thu, 25 Aug 2022 23:01:18 GMT" + }, + { + "key": "Connection", + "value": "close" + }, + { + "key": "X-Powered-By", + "value": "PHP/7.4.11" + }, + { + "key": "Cache-Control", + "value": "no-cache, private" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-RateLimit-Limit", + "value": "60" + }, + { + "key": "X-RateLimit-Remaining", + "value": "59" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + } + ], + "cookie": [], + "body": "{\n \"Task\": {\n \"title\": \"Task1 Assigned to test-user1\",\n \"description\": \"task 1\",\n \"project_id\": \"5\",\n \"user_id\": \"6\",\n \"status\": \"NOT_STARTED\",\n \"updated_at\": \"2022-08-25T11:01:18.000000Z\",\n \"created_at\": \"2022-08-25T11:01:18.000000Z\",\n \"id\": 6\n },\n \"message\": \"Task created successfully\"\n}" + } + ] + }, + { + "name": "https://telekom.local/api/v1/project?page=1&pageSize=2&sortBy=id&sortDirection=ASC", + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "https://telekom.local/api/v1/project?page=1&pageSize=2&sortBy=id&sortDirection=ASC", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "project" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "pageSize", + "value": "2" + }, + { + "key": "sortBy", + "value": "id" + }, + { + "key": "sortDirection", + "value": "ASC" + } + ] + } + }, + "response": [ + { + "name": "http://telekom.local/api/v1/project?page=1&pageSize=2&sortBy=id&sortDirection=ASC", + "originalRequest": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "https://telekom.local/api/v1/project?page=1&pageSize=2&sortBy=id&sortDirection=ASC", + "protocol": "https", + "host": [ + "telekom", + "local" + ], + "path": [ + "api", + "v1", + "project" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "pageSize", + "value": "2" + }, + { + "key": "sortBy", + "value": "id" + }, + { + "key": "sortDirection", + "value": "ASC" + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Host", + "value": "telekom.local" + }, + { + "key": "Date", + "value": "Thu, 25 Aug 2022 23:02:20 GMT" + }, + { + "key": "Date", + "value": "Thu, 25 Aug 2022 23:02:20 GMT" + }, + { + "key": "Connection", + "value": "close" + }, + { + "key": "X-Powered-By", + "value": "PHP/7.4.11" + }, + { + "key": "Cache-Control", + "value": "no-cache, private" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-RateLimit-Limit", + "value": "60" + }, + { + "key": "X-RateLimit-Remaining", + "value": "59" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + } + ], + "cookie": [], + "body": "{\n \"Projects\": {\n \"current_page\": 1,\n \"data\": [\n {\n \"id\": 1,\n \"name\": \"Telekom Test\",\n \"created_at\": \"2022-08-25T19:46:14.000000Z\",\n \"updated_at\": \"2022-08-25T19:46:14.000000Z\"\n },\n {\n \"id\": 2,\n \"name\": \"The US Daily News\",\n \"created_at\": null,\n \"updated_at\": null\n }\n ],\n \"first_page_url\": \"http://telekom.local/api/v1/project?page=1\",\n \"from\": 1,\n \"last_page\": 3,\n \"last_page_url\": \"http://telekom.local/api/v1/project?page=3\",\n \"links\": [\n {\n \"url\": null,\n \"label\": \"« Previous\",\n \"active\": false\n },\n {\n \"url\": \"http://telekom.local/api/v1/project?page=1\",\n \"label\": \"1\",\n \"active\": true\n },\n {\n \"url\": \"http://telekom.local/api/v1/project?page=2\",\n \"label\": \"2\",\n \"active\": false\n },\n {\n \"url\": \"http://telekom.local/api/v1/project?page=3\",\n \"label\": \"3\",\n \"active\": false\n },\n {\n \"url\": \"http://telekom.local/api/v1/project?page=2\",\n \"label\": \"Next »\",\n \"active\": false\n }\n ],\n \"next_page_url\": \"http://telekom.local/api/v1/project?page=2\",\n \"path\": \"http://telekom.local/api/v1/project\",\n \"per_page\": \"2\",\n \"prev_page_url\": null,\n \"to\": 2,\n \"total\": 5\n }\n}" + } + ] + } + ] +} \ No newline at end of file