diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 704089a..e6bb4a4 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -9,13 +9,15 @@ class Authenticate extends Middleware /** * Get the path the user should be redirected to when they are not authenticated. * - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request * @return string|null */ protected function redirectTo($request) { - if (! $request->expectsJson()) { - return route('login'); - } +// if (! $request->expectsJson()) { +// return route('login'); +// } + + return route('users.index'); } } diff --git a/plan.md b/plan.md new file mode 100644 index 0000000..37b9154 --- /dev/null +++ b/plan.md @@ -0,0 +1,6 @@ +# Plan + +## API + +- api/users // public +- api/users/{id} // Protected diff --git a/routes/api.php b/routes/api.php index eb6fa48..bdc2eb3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,5 +1,6 @@ get('/user', function (Request $request) { return $request->user(); }); + +Route::get('/users', function () { + $users = User::get(); + + return response()->json([ + 'users' => $users + ]); +})->name('users.index'); + +Route::middleware('auth:sanctum')->get('/users/{id}', function ($id) { + $user = User::find($id); + + if (!$user) { + return response()->json([ + 'User Not Found' + ], 404); + } + + return response()->json([ + 'user' => $user + ]); +}); + +Route::post('/tokens/create', function (Request $request) { + $validator = Validator::make($request->all(), [ + 'email' => 'required|email', + 'password' => 'required', + ]); + + if ($validator->fails()) { + return response()->json([ + $validator->errors() + ], 422); + } + + if (!Auth::attempt($request->only('email', 'password'))) { + return response()->json([ + 'message' => 'Invalid Credentials' + ], 401); + } + + $user = User::where('email', $request->email)->first(); + $token = $user->createToken('auth_token')->plainTextToken; + + return response()->json([ + 'access_token' => $token, + 'token_type' => 'Bearer' + ]); +}); diff --git a/tests/Feature/AuthTest.php b/tests/Feature/AuthTest.php new file mode 100644 index 0000000..6a7a3b0 --- /dev/null +++ b/tests/Feature/AuthTest.php @@ -0,0 +1,117 @@ +create([ + 'email' => 'foo@mail.com', + 'password' => bcrypt('password') + ]); + + $response = $this->post('/api/tokens/create', [ + 'email' => 'foo@mail.com', + 'password' => 'password' + ]); + + $response->assertStatus(200); + $response->assertSeeText('access_token'); + $response->assertSeeText('token_type'); + $response->assertSeeText('Bearer'); + } + + /** @test */ + public function it_does_not_provide_token_with_wrong_crednetials() + { + User::factory()->create([ + 'email' => 'foo@mail.com', + 'password' => bcrypt('password') + ]); + + $response = $this->post('/api/tokens/create', [ + 'email' => 'foo@mail.com', + 'password' => 'WRONG-PASSWORD' + ]); + + $response->assertStatus(401); + $response->assertSeeText('Invalid Credentials'); + } + + /** @test */ + public function email_field_is_required() + { + User::factory()->create([ + 'email' => 'foo@mail.com', + 'password' => bcrypt('password') + ]); + + $response = $this->post('/api/tokens/create', [ + 'email' => null, + 'password' => 'password' + ]); + + $response->assertStatus(422); + $response->assertJson([ + [ + 'email' => [ + 'The email field is required.' + ] + ] + ]); + } + + /** @test */ + public function email_value_must_be_a_valid_email_address() + { + User::factory()->create([ + 'email' => 'foo@mail.com', + 'password' => bcrypt('password') + ]); + + $response = $this->post('/api/tokens/create', [ + 'email' => 'foo', + 'password' => 'password' + ]); + + $response->assertStatus(422); + $response->assertJson([ + [ + 'email' => [ + 'The email must be a valid email address.' + ] + ] + ]); + } + + /** @test */ + public function password_field_is_required() + { + User::factory()->create([ + 'email' => 'foo@mail.com', + 'password' => bcrypt('password') + ]); + + $response = $this->post('/api/tokens/create', [ + 'email' => 'foo@mail.com', + 'password' => null, + ]); + + $response->assertStatus(422); + $response->assertJson([ + [ + 'password' => [ + 'The password field is required.' + ] + ] + ]); + } +} diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php deleted file mode 100644 index 1eafba6..0000000 --- a/tests/Feature/ExampleTest.php +++ /dev/null @@ -1,21 +0,0 @@ -get('/'); - - $response->assertStatus(200); - } -} diff --git a/tests/Feature/UserApiTest.php b/tests/Feature/UserApiTest.php new file mode 100644 index 0000000..e754e10 --- /dev/null +++ b/tests/Feature/UserApiTest.php @@ -0,0 +1,75 @@ +create(); + $user2 = User::factory()->create(); + + $response = $this->get('/api/users'); + + $response->assertStatus(200); + $response->assertJson([ + 'users' => [ + [ + 'name' => $user1->name, + 'email' => $user1->email + ], + [ + 'name' => $user2->name, + 'email' => $user2->email + ], + ] + ]); + } + + /** @test */ + public function it_shows_deatils_of_a_user_to_authenticated_user_only() + { + Sanctum::actingAs( + User::factory()->create(), + ); + + $user = User::factory()->create(); + $response = $this->get('/api/users/' . $user->id); + + $response->assertStatus(200); + $response->assertJson([ + 'user' => [ + 'name' => $user->name, + 'email' => $user->email + ], + ]); + } + + /** @test */ + public function it_does_not_allow_to_access_publicly() + { + $response = $this->get('/api/users/1'); + + $response->assertStatus(302); + } + + /** @test */ + public function it_returns_404_if_no_record_found_with_the_given_id() + { + Sanctum::actingAs( + User::factory()->create(), + ); + + $response = $this->get('/api/users/999'); + + $response->assertStatus(404); + } +}