Criando uma plataforma do 0 - Dia 2
Tags: laravel, fullstack, product, programming
Published: 2023-11-04 14:06:14

Nesse segundo dia, eu fiz a parte de login e cadastro da aplicação e para facilitar a vida, fiz uso do [Laravel Sanctun]([Laravel Sanctum - Laravel 10.x - The PHP Framework For Web Artisans](https://laravel.com/docs/10.x/sanctum)). O Laravel Sanctum já nos entrega um sistema de autenticação baseado em tokens para usar em nosso front end ou mobile. Dessa forma, cada usuário na nossa aplicação vai ter um token e o interessante é que esse token pode receber o que a documentação chama de escopo e habilidades. Onde podemos definir o que aquele tipo de token pode fazer e no seu escopo podemos definir a expiração token também.
Definido que iria usar o Sanctum, eu segui a documentação no site do próprio Laravel para fazer a instalação dele, mas a única que precisei fazer de fato que o Laravel não me entregou pronto, foi descomentar a linha `\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class` que se estava no arquivo `Kernel.php`, para ter a certeza que as request que irão vir do nosso FrontEnd irão ser Stateful, isto vai dizer para nosso BackEnd manter o estado da nossa sessão.
Outra alteração que precisei fazer foi no arquivo de migration de o Laravel Sanctum gera para gente, no primeiro dia foi definido que a Chave Primária (PK) da nossa tabela de usuários seria um UUID e quando comecei a testar me deparei com um erro dizendo que uma coluna que a migration criou e iria guardar o ID do usuário não aceitava valor do tipo UUID, então a migration que era dessa forma:

```php
Schema::create('personal_access_tokens', function (Blueprint $table) {
  $table->id();
  $table->morphs('tokenable');
  $table->string('name');
  $table->string('token', 64)->unique();
  $table->text('abilities')->nullable();
  $table->timestamp('last_used_at')->nullable();
  $table->timestamp('expires_at')->nullable();
  $table->timestamps();
});
```

Ficou dessa forma, a mudança ocorre na coluna `tokenable`, passamos a utilizar `uuidMorphs` para informar que a coluna irá aceitar tipos UUID:

```php
Schema::create('personal_access_tokens', function (Blueprint $table) {
  $table->id();
  $table->uuidMorphs('tokenable');
  $table->string('name');
  $table->string('token', 64)->unique();
  $table->text('abilities')->nullable();
  $table->timestamp('last_used_at')->nullable();
  $table->timestamp('expires_at')->nullable();
  $table->timestamps();
});
```

Feito essa mudança, partiu agora criar nosso Controller para lidar com o Login e Cadastro dos usuários. Para isso é fácil, bastou rodar o comando `php artisan make:controller Api/Auth/AuthController`, esse comando irá criar um Controller dentro da pasta `app/Http/Controllers/Api/Auth/AuthController.php`.
Agora começa a parte boa, codar a lógica de primeiro de login do usuário e isso foi bem simples, primeiro eu faço a validação dos campos que quero receber, no login eu espero receber o e-mail e senha do usuário, esses dados vão ser do tipo string e obrigatórios, depois eu procuro se tem algum usuário com esse e-mail no banco de dados e faço a verificação se a senha está correta, feita essa primeira parte e tudo estiver ok, eu crio o token daquele usuário e retorno o usuário e o token como resposta.

```php
public function login(Request $request): Response
{
  $data = $request->validate([
    'email' => 'required|string',
    'password' => 'required|string'
  ]);

   $user = User::where('email', $data['email'])->first();

  if (!$user || !Hash::check($data['password'], $user->password)) {
    return response([
      'message' => 'Email ou senha incorretos'
    ], 401);
  }

  $token = $user->createToken('apiToken')->plainTextToken;

  return response([
    'user' => $user,
    'token' => $token
  ], 200);
}
```

Lógica de login feita, basta só cadastrar a rota no arquivo `routes/api.php` e o login já está pronto.
Para cadastro a lógica é parecida, a diferença é que eu faço a validação também do primeiro e último nome e faço um regex na senha para ver se ela atende uma determinada condição e também já gero o token, porque o objetivo é assim que ele fizer o cadastro já cai dentro da plataforma para começar a usar.

## Conclusão
Bom, nesse segundo dia foi isso, pretendo ainda melhor essa parte da geração do token, pois ele por padrão nunca expira e isso no objetivo que tenho em mente pode não ser bom, então as próximas partes eu irei colocar um tempo de expiração e também criar a rota para fazer o logout do usuário e apagar esse token no nosso banco de dados. Então é isso, devagar o sistema vai tomando forma e eu vou aprendendo cada vez mais!