Java Script-AdonisJs Funções(roles) ACL-RBAC Backend API
Published: 2022-08-27 15:32:20

Conhecimentos necessários:  NodeJs,AdonisJs Yarn/Npm, DataBase, Mysql ou PostgreeSql, JavaScript. 

Nesse tutorial vou ensinar a implementar um sistema de acessos filtrados, onde somente usuários autenticados e autorizados podem acessar determinadas URLs.

Um sistema de nível de acesso e acesso por função completo, usando Java Script juntamente com o Framework AdonisJS para exemplificar o propósito.

Usando um banco de dados relacional SQL, cliente Postgree, Mysql.
É importante sabermos que o banco de dados relacional SQL DB é a ferramenta fundamental para esse processo, isso irá gerar uma facilidade em nosso desenvolvimento, quando começarmos a entender os relacionamentos entre as tabelas do banco e as regras de funções, que dirão quem pode fazer o que, dentro do sistema.

Esse é um dos campos da programação bastante notável e usual nos sistemas de grande porte.

Começando: Crie um banco de dados usando seu cliente Mysql ou Postgre. Com nome,senha e host. (não vou entrar no mérito de como fazer é necessário ter esse conhecimento).

Agora depois de termos o Adonisjs instalado em nossa máquina,devemos criar o projeto.

Doc Adonisjs: https://adonisjs.com/docs/4.1/installation

Criando nosso projeto no modo API:

``` adonis new acl-rbac-adonis-api --api-only  ```



Encontrei duas libs relacionadas ao Adonis que fazem o papel de RBAC/ACL:

1- https://www.npmjs.com/package/@rocketseat/adonis-acl
   https://github.com/HigoRibeiro/adonis-acl

2- https://www.npmjs.com/package/accesscontrol
   https://github.com/onury/accesscontrol 



Mas por fim usarei como exemplo essa lib:

https://github.com/QuantumLabsLtda/adonisjs-cerberus


Você pode criar um midlleware na unha e fazer suas regras de níveis de acesso e níveis por funções.
Isso te dará uma melhor liberdade para implementar um sistema de ACL RBAC,mais estruturado e que te dê 
maior liberdade e que consuma menos recursos.

Pois ao criar um midlleware você não precisa gastar tempo e processamento de máquina para ir
até o banco de dados verificar se aquele usuário tem acesso aquela URL.
De uma forma geral isso lhe custará menos tempo e processamento.Mas pode ser algo que tenha
uma segurança menor, isso vai depender de do projeto e das variáveis em si.

Criando esse midlleware você consegue facilmente separar quem pode acessar qual URL.E no geral não precisa usar um nova biblioteca somente para esse fim.

No final pode ser bem mais vantajoso criar um sistema de midlleware único e criar suas próprias regras de acesso.
Isso deve ser decidido por você e depende muito do seu tipo de projeto.

Mas nesse artigo seguiremos usando um biblioteca para isso,como disse existem algumas famosas,e 
que fazem basicamente o mesmo trabalho,mas no exemplo desse artigo usaremos o CERBERUS.


Existe um tutorial no link acima, super prático, mas tentarei mastigar mais um pouco.

Primeiro adicione o pacote da biblioteca Adonis-Cerberus


``` npm i @quantumlabs/adonisjs-cerberus --save ```


Faça as configurações de provedores, na raiz do projeto.

Em  ``` start/app.js ```

```javascript

const providers = [
    ...
    '@quantumlabs/adonisjs-cerberus/providers/CerberusProvider',
    ...
  ]

```

Em  ``` start/app.js ```

```javascript

const aceProviders = [
    ...
    '@quantumlabs/adonisjs-cerberus/providers/CommandsProvider'
    ...
  ]

```

Em  ``` start/kernel.js ```

```javascript

const namedMiddleware = [
    ...
    guard: 'Cerberus/Middleware/Guard'
    ...
  ]

```

Adicione caracteristicas especiais trails,dentro do Model User.js

Em  ``` app/Models/User.js ```

```javascript

class User extends Model {
  static boot () {
    super.boot()

    this.addTrait('@provider:Cerberus/Traits/Role')
    this.addTrait('@provider:Cerberus/Traits/Permission')
  }
...

```

Finalmente rode o comando cerberus que criará todas as migrations com os relacionamentos ,chaves PK e FK e toda estrutura baseada em ACL e RBAC.
Execute o comando:

``` adonis cerberus:init ```

Entre na pasta `database/migrations` e verá as novas tabelas criadas.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/k3ju460zh5m4uonr7t8g.png)

Então rode o comando para migração das tabelas para o banco de dados.

``` adonis migration:run ```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/s35eoy398zwm72bv29n4.png)

Se tudo der certo, você verá as tabelas criadas no seu cliente de banco de dados.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ywsqgd4l8yql29zc5sga.png)

Como mencionado antes, este comando deve (e esperamos que vá) copiar todas as migrações específicas da biblioteca para a pasta `migrations` de seus projetos. Não há sinalizadores ou parâmetros especiais para este comando.

#### Role / Função

```shell
adonis cerberus:role [name] [slug]

Usage:
  cerberus:role <name> [slug] [options]

Arguments:
  name   Name of the role
  slug   Short name for role
```

Rodando então o comando para criação de uma role/função.

```shell

adonis cerberus:role admin adm

```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/58zi71ajgtedbdhbmu25.png)

Na tabela *roles* é criada um novo tipo de função para um usuário.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7wrfzai4nxk03jogz083.png)


Este comando cria uma nova * role / função * na tabela de roles/funções. Você só precisa especificar a função `nome`, o argumento` slug` é opcional.
This command creates a new role into roles table. You only need to specify role's name, slug argument is optional.

Esse processo de criação de níveis de acesso por função continua em outras tabelas principais,**roles**,**resources**,**permissions**,**default_permissions**.

#### Resource / Recurso

```shell
adonis cerberus:resource [name] [slug] [options]

Arguments:
  name               Name of the resource
  slug               Short name for resource

Options:
  -p, --defaultPermission   Generate default permissions
  -a, --always-ask   Ask which rights give in each Resource once (false by default)
  --from-models      Generate a resource for each app Model
  --from-controllers Generate a resource for each app Controller
```

Rodando então o comando para criação de uma resource/recurso.

```shell

adonis cerberus:resource admin adm

```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0j0ii9x1jjevavvdehde.png)

Na tabela *resource* é criada um novo tipo de função para um usuário.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mx01e692s0bjjsfgkoac.png)


Este comando cria um novo * resource / recurso * na tabela de recursos. Você só precisa especificar o `nome` do recurso, o argumento` slug` é opcional.
The options are:
  `-p, --defaultPermission` - Generate default permissions
  `-a, --always-ask` - Ask which rights give in each Resource once (false by default)
  `--from-models` - Generate a resource for each app Model
  `--from-controllers` - Generate a resource for each app Controller

#### Default Permission / Permissão Padrão

```shell
cerberus:defaultPermission [options]

Options:
  -a, --all               Run default permission creation for each Resource in database
  --resource-name <value> Name of resource
```

Rodando então o comando para criação de uma default_permissions/padrão de permissões.

```shell

adonis cerberus:defaultPermission --all

```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jfu41a72ozjqu092m79h.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8gqtdvicn5jnyxwpvi2g.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jtfq7kwcpm1a0kf28a6q.png)



Este comando cria uma nova * permissão padrão * na tabela default_permissions. Você precisa especificar um nome de Recurso e, em seguida, * Cerberus * cria um registro de permissão padrão com o Recurso * nome * especificado.

## Uso

## Uso em rotas

Depois de criar suas *Permissions*, você poderá começar a usar o middleware **Guard** em suas rotas.

É simples vincular uma permissão a uma rota, veja:

```js
/**
* Get all users
* GET users
*/
Route
  .get('', 'UserController.index')
  .middleware(['auth', 'guard: user.read'])
```

Você também pode usar várias permissões em sua rota:

```js
/**
* Create a new user
* POST users/register
*/
Route
  .post('register', 'UserController.register')
  .middleware(['auth', 'guard: user.create, user.read'])
```

E também é possível usar vários recursos:

```js
/**
* Fetch all posts with user profile
* GET posts
*/
Route
  .get('', 'PostController.index')
  .middleware(['auth', 'guard: post.read, user.read'])
```

* Aviso *: Você precisa adicionar o middleware `auth` padrão ** antes de ** Cerberus` guard`!
*Warning*: You need to add the default `auth` middleware **before** Cerberus `guard`!

### Consuming Models

You **should** use Cerberus Models to create *Roles*, *Resources* and *Permissions* in your own code. It's also useful for creating seeds or a complete CRUD to manage your Cerberus stuff. It's simple to use:

#### Roles

```js
  const Role = use('Cerberus/Models/Role')

  // Creating a new Role
  await Role.create({
    name: 'Jedi Master',
    slug: 'jedi'
  })

  // or

  let role = await Role.find(1)

  role.name = 'Wookie'
  role.slug = 'wookie'

  await role.save()

  // You can use any Lucid methods you want
```