Skip to content

Commit c2caf70

Browse files
committed
login done 8:09:25
1 parent 9a7be2a commit c2caf70

File tree

14 files changed

+325
-18
lines changed

14 files changed

+325
-18
lines changed

Core/Middleware/Auth.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Core\Middleware;
4+
5+
class Auth
6+
{
7+
// notice how each one has similar method that sort of means the'r confirming to a similar contract
8+
// and that contract states that
9+
// each of middleware classes provides a handle method
10+
// that can be called to determine and evaluate whether
11+
// the request can further continue to the core of your application
12+
// the request should be allowed to proceed or not
13+
public function handle()
14+
{
15+
if (! $_SESSION['user'] ?? false) {
16+
header('Location: /');
17+
exit(); // or die
18+
}
19+
}
20+
}

Core/Middleware/Guest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Core\Middleware;
4+
5+
class Guest
6+
{
7+
public function handle()
8+
{
9+
if ($_SESSION['user'] ?? false) {
10+
header('Location: /');
11+
exit(); // or die
12+
}
13+
}
14+
}

Core/Middleware/Middleware.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Core\Middleware;
4+
5+
class Middleware
6+
{
7+
// we create some kind of map
8+
public const MAP = [
9+
'guest' => Guest::class,
10+
'auth' => Auth::class
11+
];
12+
13+
public static function resolve($key)
14+
{
15+
if (! $key) {
16+
return; // if no middleware is specified, just return
17+
}
18+
19+
// static means use the current instance (late static binding)
20+
$middleware = static::MAP[$key] ?? false;
21+
22+
if (! $middleware) {
23+
throw new \Exception("No matching middleware found for key '{$key}'.");
24+
}
25+
26+
(new $middleware)->handle();
27+
}
28+
}

Core/functions.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,12 @@ function view($path, $attributes = [])
4444
extract($attributes);
4545

4646
require base_path('views/' . $path);
47+
}
48+
49+
function login($user)
50+
{
51+
$_SESSION['user'] = [
52+
'email' => $user['email']
53+
// 'name' => $user['name'],
54+
];
4755
}

Core/router.php

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
namespace Core;
44

5+
use Core\Middleware\Auth;
6+
use Core\Middleware\Guest;
7+
use Core\Middleware\Middleware;
8+
59
class Router
610
{
711
protected $routes = [];
@@ -11,39 +15,96 @@ public function add($method, $uri, $controller)
1115
$this->routes[] = [
1216
'uri' => $uri,
1317
'controller' => $controller,
14-
'method' => $method
18+
'method' => $method,
19+
'middleware' => null
1520
];
21+
22+
return $this;
1623
}
1724

1825
public function get($uri, $controller)
1926
{
20-
$this->add('GET', $uri, $controller);
27+
return $this->add('GET', $uri, $controller);
2128
}
2229

2330
public function post($uri, $controller)
2431
{
25-
$this->add('POST', $uri, $controller);
32+
return $this->add('POST', $uri, $controller);
2633
}
2734

2835
public function delete($uri, $controller)
2936
{
30-
$this->add('DELETE', $uri, $controller);
37+
return $this->add('DELETE', $uri, $controller);
3138
}
3239

3340
public function patch($uri, $controller)
3441
{
35-
$this->add('PATCH', $uri, $controller);
42+
return $this->add('PATCH', $uri, $controller);
3643
}
3744

3845
public function put($uri, $controller)
3946
{
40-
$this->add('PUT', $uri, $controller);
47+
return $this->add('PUT', $uri, $controller);
48+
}
49+
50+
public function only($key)
51+
{
52+
// what we need to do is grab the last route that was added
53+
// and set its middleware to the key that was passed in
54+
// this is a very simple way to do it, but it works
55+
// there are several ways to do this, but this is the simplest
56+
$this->routes[array_key_last($this->routes)]['middleware'] = $key;
57+
58+
return $this;
4159
}
4260

4361
public function route($uri, $method)
4462
{
4563
foreach ($this->routes as $route) {
4664
if ($route['uri'] === $uri && $route['method'] === strtoupper($method)) {
65+
// apply middleware if it exists
66+
// if ($route['middleware'] === 'guest') {
67+
// if($_SESSION['user'] ?? false) {
68+
// header('Location: /');
69+
// exit(); // or die
70+
// }
71+
// }
72+
// if ($route['middleware'] === 'auth') {
73+
// if(! $_SESSION['user'] ?? false) {
74+
// header('Location: /');
75+
// exit(); // or die
76+
// }
77+
// }
78+
// this is pretty sloppy, instead what if the handlers of each of these
79+
// stored in a separate file, and we just require that file
80+
81+
// this is more dynamic way of handling middleware that is we are handling below in comment
82+
// null handling
83+
Middleware::resolve($route['middleware']);
84+
// added below handling in Router.php
85+
// if ($route['middleware']) {
86+
// $middleware = Middleware::MAP[$route['middleware']];
87+
// (new $middleware)->handle();
88+
// }
89+
90+
// if ($route['middleware'] === 'guest') {
91+
// (new Guest)->handle();
92+
// }
93+
// if ($route['middleware'] === 'auth') {
94+
// (new Auth)->handle();
95+
// }
96+
97+
// if later we need to add more middleware, we need to do this
98+
// and its not look good we could simplify this
99+
// its sound like we are associating a key with a corresponding middleware class
100+
// so the guest key points to the Guest class
101+
// the auth key points to the Auth class
102+
// something like that
103+
// so why don't we setup some kind of lookup table
104+
// lets add some kind of parent class called Middleware
105+
// if ($route['middleware'] === 'email-confirmed') {
106+
// (new ConfirmedEmail)->handle();
107+
// }
47108
return require base_path($route['controller']);
48109
}
49110
}

controllers/index.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
$_SESSION['name'] = 'John Doe';
3+
// $_SESSION['name'] = 'John Doe';
44

55
view("index.view.php", [
66
'heading' => 'Home',
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
<?php
22

3+
// if user already logged in, redirect to home page
4+
// you don't want to allow logged-in users to access the registration page
5+
// copy and paste this code in every controller that needs to restrict access
6+
// or we can takel it at route level
7+
// this code is added to Router.php
8+
// if ($_SESSION['user'] ?? false) {
9+
// header('Location: /');
10+
// exit();
11+
// }
312

4-
view('registration/create.view.php', [
5-
6-
]);
13+
view('registration/create.view.php');

controllers/registration/store.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
use Core\Database;
55
use Core\Validator;
66

7+
$db = App::resolve(Database::class);
8+
79
$email = $_POST['email'];
810
$password = $_POST['password'];
911

@@ -24,7 +26,7 @@
2426
]);
2527
}
2628

27-
$db = App::resolve(Database::class);
29+
// $db = App::resolve(Database::class);
2830
// check if the account already exists.
2931
$user = $db->query('SELECT * FROM users WHERE email = :email', [
3032
'email' => $email
@@ -40,7 +42,8 @@
4042
// If no, save one to database, and then log the user in, and redirect.
4143
$db->query('INSERT INTO users (email, password, name) VALUES (:email, :password, :name)', [
4244
':email' => $email,
43-
':password' => $password,
45+
// NEVER store database passwords in clear text. always hash them.
46+
':password' => password_hash($password, PASSWORD_BCRYPT),
4447
':name' => 'test'
4548
]);
4649

@@ -50,9 +53,19 @@
5053
// but we are gonna take this route
5154
// or may be you add multiple values like below helper
5255
// $_SESSION['logged_in'] = true;
53-
$_SESSION['user'] = [
56+
57+
// $_SESSION['user'] = [
58+
// 'email' => $email,
59+
// ];
60+
61+
// refactoring because login comes in
62+
63+
// in future you can do something like this
64+
// login($user); that has all the attributes like email, name, id, etc.
65+
66+
login([
5467
'email' => $email,
55-
];
68+
]);
5669

5770
header('Location: /');
5871
exit(); // or die

controllers/sessions/create.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
view('sessions/create.view.php');

controllers/sessions/store.php

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
// log in the user if the credentials match.
4+
5+
use Core\App;
6+
use Core\Database;
7+
use Core\Validator;
8+
9+
$db = App::resolve(Database::class);
10+
11+
$email = $_POST['email'];
12+
$password = $_POST['password'];
13+
14+
// validate the form inputs.
15+
$errors = [];
16+
if (!Validator::email($email)) {
17+
$errors['email'] = 'Please enter a valid email address.';
18+
}
19+
20+
if (!Validator::string($password)) {
21+
$errors['password'] = 'Please provide a valid password.';
22+
}
23+
24+
if (! empty($errors)) {
25+
return view('/sessions/create.view.php', [
26+
'errors' => $errors
27+
]);
28+
}
29+
30+
// match the credentials with the database.
31+
32+
$user = $db->query('SELECT * FROM users WHERE email = :email', [
33+
'email' => $email
34+
])->find();
35+
36+
// dd($user);
37+
38+
// if (! $user) {
39+
// return view('/sessions/create.view.php', [
40+
// 'errors' => [
41+
// 'email' => 'No matching account found for that email address.'
42+
// ]
43+
// ]);
44+
// }
45+
46+
// we have a user,but we don't know if the password provided matches what we have in the database.
47+
// its not simple like that because we store hash
48+
// if ($user['password' === $password]) {}
49+
50+
// if (password_verify($password, $user['password'])) {
51+
// login([
52+
// 'email' => $email,
53+
// ]);
54+
55+
// header('Location: /');
56+
// exit(); // or die
57+
// }
58+
// // else {
59+
// // // i can do else for otherwise
60+
// // // in this case i use exit so i don't need to use else
61+
// // the else statement is little superfluous here i don't need to do it
62+
// // }
63+
64+
if (! $user) {
65+
// if we found the corresponding user then we do the check
66+
if (password_verify($password, $user['password'])) {
67+
login([
68+
'email' => $email,
69+
]);
70+
71+
header('Location: /');
72+
exit(); // or die
73+
}
74+
}
75+
76+
// otherwise there was no user or if there was a user but the password didn't match
77+
// it gets us around , it allows us to skirt around the issue of us letting the user check if there are certain email addresses in our database.
78+
79+
return view('/sessions/create.view.php', [
80+
'errors' => [
81+
'email' => 'No matching account found for that email address and password.'
82+
]
83+
]);

0 commit comments

Comments
 (0)