One place for hosting & domains

      utilizando

      Como gravar e compartilhar sessões de terminal utilizando o Terminalizer no Ubuntu 18.04


      O autor selecionou a Fundação Electronic Frontier para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O Terminalizer é um aplicativo de gravação de terminal que permite que você grave sua sessão de terminal em tempo real e, em seguida, reproduza-a novamente em uma data futura. Ele funciona da mesma maneira que um gravador de tela da área de trabalho, mas, ao invés disso, é executada em seu terminal.

      Gravar sua sessão de terminal é útil caso queira rever uma atividade em particular mais uma vez, ou para ajudar a depurar um erro particularmente complicado. As gravações feitas com o Terminalizer também podem ser exportadas como GIFs animados, que são ótimos para compartilhar online ou adicionar ao material de marketing para seu software.

      Neste tutorial, você instalará o Terminalizer, o utilizará para gravar e reproduzir as sessões de terminal, personalizar suas gravações e, em seguida, exportá-las para poder compartilhá-las on-line.

      Pré-requisitos

      Para completar este tutorial, você precisará de:

      Caso queira compartilhar suas gravações on-line, também precisará de:

      Assim que tiver tudo pronto, logue no seu servidor como usuário não raiz para começar.

      Passo 1 — Instalando o Terminalizer

      Neste passo, você irá baixar e instalar o Terminalizer no seu sistema. O Terminalizer é escrito utilizando o Node.js e está disponível para instalação utilizando o gerenciador de pacotes npm.

      Para instalar o Terminalizer globalmente no seu sistema, execute o seguinte comando:

      • sudo npm install --global --allow-root --unsafe-perm=true terminalizer

      O Terminalizer utiliza o framework de aplicativo Electron para exportar sessões de terminal gravadas para o formato GIF. O argumento de comando --unsafe-perms=true é necessário para instalar o Electron globalmente no seu sistema.

      Assim que o Terminalizer tiver sido instalado, você verá um resultado parecido com o seguinte:

      Output

      . . . /usr/local/lib └── terminalizer@0.7.1

      Em seguida, verifique sua instalação do Terminalizer executando:

      Isso exibirá algo semelhante ao seguinte:

      Output

      0.7.1

      Por fim, gere um arquivo de configuração padrão do Terminalizer, que pode ser usado para a personalização avançada do Terminalizer (detalhada mais a fundo no Passo 4):

      Isso produzirá um resultado parecido com este:

      Output

      The global config directory is created at /home/user/.terminalizer

      Agora que você instalou o Terminalizer, você pode fazer sua primeira gravação de terminal.

      Passo 2 — Gravando e reproduzindo uma sessão de terminal

      Neste passo, você gravará e reproduzirá uma sessão de terminal.

      Para começar, configure uma nova gravação do Terminalizer usando um nome de sua escolha:

      • terminalizer record your-recording

      Isso gerará o seguinte resultado, indicando que a gravação foi iniciada:

      Output

      The recording session has started Press Ctrl+D to exit and save the recording

      Agora, prossiga e faça tudo o que quiser dentro do seu terminal. Cada tecla pressionada será gravada em tempo real pelo Terminalizer.

      Por exemplo:

      • pwd
      • date
      • whoami
      • echo "Hello, world!"

      Quando quiser parar a gravação, pressione CTRL+D. Então, o Terminalizer salvará a gravação para o arquivo especificado no formato YAML, como, por exemplo, your-recording.yml.

      Output

      Successfully Recorded The recording data is saved into the file: /home/user/your-recording.yml

      Pode ser que você seja solicitado pelo Terminalizer a compartilhar sua gravação on-line. Simplesmente pressione CTRL+C para cancelar isso por enquanto, já que você pode reproduzir a gravação do terminal localmente primeiro.

      Em seguida, reproduza sua sessão de terminal gravada com o comando a seguir:

      • terminalizer play your-recording

      Isso irá reproduzir a sessão gravada em tempo real no seu terminal:

      Output

      user@droplet:~$ pwd /home/user user@droplet:~$ date Sun Mar 8 14:55:36 UTC 2020 user@droplet:~$ whoami user user@droplet:~$ echo "Hello, world!" Hello, world! user@droplet:~$ logout

      Você também pode ajustar a velocidade de reprodução da sua gravação usando a opção --speed-factor.

      Por exemplo, o comando a seguir irá reproduzir sua gravação duas vezes mais devagar (metade da velocidade):

      • terminalizer play your-recording --speed-factor 2

      De maneira alternativa, reproduza sua gravação duas vezes mais rápido (dobro da velocidade):

      • terminalizer play your-recording --speed-factor 0.5

      Você gravou e reproduziu uma sessão de terminal. Em seguida, compartilhe on-line uma sessão de terminal gravada.

      Passo 3 — Compartilhando uma sessão de terminal gravada

      Neste passo, você irá compartilhar sua sessão de terminal gravada na página Explore do Terminalizer.

      Comece selecionando uma sessão gravada para compartilhar:

      • terminalizer share your-recording

      Em seguida, será solicitado que você forneça alguns metadados básicos sobre sua gravação, como o título e a descrição:

      Output

      Please enter some details about your recording ? Title Title of Your Recording ? Description Description of Your Recording ? Tags such as git,bash,game Comma-separated Tags for Your Recording

      Aviso: as gravações do Terminalizer são compartilhadas publicamente por padrão, portanto certifique-se de que não haja detalhes pessoais identificáveis ou confidenciais presentes em sua gravação de terminal que você não deseja compartilhar.

      Caso seja a primeira vez que tenha compartilhado uma sessão gravada usando o Terminalizer, você precisará vincular sua conta do Terminalizer. O Terminalizer exibirá um link de verificação se isso for necessário:

      Output

      Open the following link in your browser and login into your account https://terminalizer.com/token?token=your-token When you do it, press any key to continue

      Aviso: certifique-se de manter seu token do Terminalizer privado, pois ele permitirá a todos que o possuem acessem sua conta do Terminalizer.

      Assim que tiver visitado o link no seu navegador Web e tiver logado em sua conta do Terminalizer, pressione qualquer tecla para continuar.

      O Terminalizer irá agora fazer o upload da sua gravação e dará a você o link para visualizá-la:

      Output

      Successfully Uploaded The recording is available on the link: https://terminalizer.com/view/your-recording-id

      Visitar o link em um navegador Web de desktop permitirá que você veja sua gravação compartilhada:

      Uma captura de tela do site do Terminalizer, mostrando um exemplo de uma gravação de terminal compartilhada

      Você compartilhou uma sessão de terminal gravada no site do Terminalizer e a visualizou em seu navegador Web.

      Passo 4 — Definindo a configuração avançada do Terminalizer

      Agora que ganhou familiaridade com o Terminalizer, você pode começar a rever algumas das opções de personalização mais avançadas, tal como a habilidade de ajustar as cores de exibição e estilo.

      Cada gravação herda a configuração padrão do arquivo global config do Terminalizer, que está localizado em ~/.terminalizer/config.yml. Isso significa que você pode editar a configuração das gravações individuais diretamente editando o arquivo de gravação (por exemplo, your-recording.yml). De maneira alternativa, você pode editar a configuração global, que terá um impacto em todas as novas gravações.

      Neste exemplo, você editará o arquivo de configuração global, mas a mesma orientação se aplica aos arquivos de configuração de gravação individuais.

      Comece abrindo o arquivo de configuração global do Terminalizer em seu editor de texto, como o nano:

      • nano ~/.terminalizer/config.yml

      Cada uma das opções de configuração disponíveis dentro do arquivo serão comentadas de forma a explicar o que elas fazem.

      Há várias opções de configuração comuns que você pode querer ajustar para atenderem ao seu gosto:

      • cols: define o número de colunas de terminal usadas para sua gravação explicitamente.
      • rows: define o número de linhas de terminal usadas para sua gravação explicitamente.
      • frameDelay: sobrepõe o atraso entre cada aperto de tecla durante a reprodução.
      • maxIdleTime: especifica um tempo máximo entre apertos de teclas durante a reprodução.
      • cursorStyle: especifica o estilo padrão do cursor do terminal para block (bloco), bar (barra) e underline (sublinhado).
      • fontFamily: especifica uma lista com as fontes de reprodução preferidas, por ordem de preferência.
      • theme: ajusta o esquema de cores da reprodução, para criar, por exemplo, um terminal preto no branco, etc.

      Como exemplo, você pode definir uma exibição de terminal branco no preto, configurando as seguintes opções:

      config.yml

      . . .
      theme:
        background: "white"
        foreground: "black"
      . . .
      

      Isso produzirá um resultado parecido com este:

      Uma captura de tela do site do Terminalizer, mostrando um exemplo de gravação com um tema branco no preto

      Você pode ajustar o estilo do cursor para facilitar o entendimento da gravação, como, por exemplo, trocando o cursor padrão estilo bloco por um exemplo sublinhado:

      config.yml

      . . .
      cursorStyle: underline
      . . .
      

      Isso gera um resultado parecido com este:

      Uma captura de tela do site do Terminalizer, mostrando um exemplo de gravação com um cursor estilo sublinhado

      Assim que tiver feito todas as alterações desejadas, salve o arquivo e retorne para seu terminal.

      Caso tenha editado a configuração global do Terminalizer, essas configurações se aplicarão a todas as novas gravações a partir daqui. Caso esteja editando uma configuração específica de gravação, o Terminalizer aplicará imediatamente as alterações naquela gravação em particular.

      Note que a estilização personalizada de reprodução se aplica apenas às sessões de gravação compartilhadas. Reproduzi-las novamente diretamente em seu terminal sempre usará seu estilo e esquema de cores padrão do terminal.

      Neste passo final, você revisou algumas das opções de configuração avançadas para o Terminalizer.

      Conclusão

      Neste artigo, você usou o Terminalizer para gravar e compartilhar uma sessão de terminal. Agora, possui o conhecimento necessário para criar demonstrações gravadas do seu software para usar em material de marketing, ou compartilhar truques de linha de comando com amigos.

      Caso queira renderizar e exportar gravações do Terminalizer para o formato GIF, instale o Terminalizer em uma máquina com uma interface gráfica de usuário/desktop e utilize as funcionalidades de renderização integradas:

      Pode ser que também queira pesquisar no site do Terminalizer por sessões de terminal gravadas compartilhadas por outros usuários:



      Source link

      Como desenvolver um aplicativo de citações inspiradoras utilizando o AdonisJs e o MySQL


      O autor selecionou a Tech Education Fund para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O AdonisJs é um framework Web Node.js, escrito em JavaScript simples, que é executado em todos os grandes sistemas operacionais. Ele utiliza o padrão de design popular MVC (Modelo – Visão – Controle) e oferece um ecossistema estável para a escrita de aplicativos Web do servidor. O framework possui autenticação contínua, SQL ORM (mapeamento objeto-relacional), migrations e a propagação de banco de dados. O AdonisJs tem uma arquitetura semelhante ao framework PHP de aplicativo Web, o Laravel, incluindo a mesma estrutura de pasta e vários conceitos de configuração compartilhados.

      Por padrão, o AdonisJs utiliza o mecanismo de modelo Edge, projetado para um uso intuitivo. Assim como o Laravel, o AdonisJs vem com um ORM chamado Lucid que funciona como uma interface para a comunicação entre os modelos de um aplicativo e o banco de dados. Com o AdonisJs, os desenvolvedores podem desenvolver um aplicativo de pilha completa, onde o servidor de back-end será o responsável pela aplicação da lógica de negócios, roteamento e renderização de todas as páginas do aplicativo. Também é possível criar um serviço Web API para retornar as respostas JSON de um controlador; esses serviços Web podem ser consumidos usando os frameworks de front-end, como o Vue.js, o React e o Angular.

      Neste tutorial, você desenvolverá um aplicativo com o AdonisJs usando sua CLI. Você criará rotas, controladores, modelos e visualizações dentro do seu aplicativo e executará as validações de formulário. O exemplo neste tutorial será um aplicativo de citações inspiradoras, no qual um usuário pode se inscrever e fazer o login para criar uma citação inspiradora. Este aplicativo de demonstração dará a você a oportunidade de realizar as operações CRUD (Criar, Ler, Atualizar e Excluir).

      Pré-requisitos

      Antes de iniciar este guia, você precisará do seguinte:

      Nota: este tutorial utiliza uma máquina macOS para desenvolvimento. Caso esteja usando outro sistema operacional, talvez seja necessário, nos primeiros passos, usar os comandos sudo para o npm.

      Passo 1 — Instalando o Adonis CLI

      Nesta seção, você instalará o Adonis CLI e todos os seus pacotes necessários em sua máquina local. O CLI permitirá que você faça a exibição de scaffold em um novo projeto do AdonisJs, bem como criar e gerar um boilerplate para controladores, middlewares e modelos em seu aplicativo. Você também criará seu banco de dados para o projeto.

      Execute o seguinte comando para instalar o AdonisJs CLI em sua máquina, de maneira global, via npm:

      Assim que o processo de instalação terminar, digite o seguinte comando no terminal para confirmar a instalação do AdonisJs e visualizar a versão atual:

      Você verá o resultado mostrando a versão atual do AdonisJs:

      Output

      4.1.0

      Com a instalação do AdonisJs CLI bem-sucedida, você tem acesso e pode usar o comando adonis para criar novas instalações de um projeto AdonisJs, gerenciar seu projeto e gerar arquivos relevantes, como os controladores, modelos, etc.

      Agora, você pode prosseguir para criar um novo projeto do AdonisJs usando o comando adonis como mostrado aqui:

      • adonis new adonis-quotes-app

      O comando anterior criará um aplicativo chamado adonis-quotes-app em um novo diretório com o mesmo nome em seu diretório local com a estrutura relevante do AdonisJs MVC.

      Vá para a pasta do novo aplicativo:

      Então, inicie seu aplicativo executando:

      Isso inicializará o servidor de desenvolvimento na porta padrão 3333, como especificado no arquivo root .env para seu aplicativo. Vá para http://localhost:3333 para visualizar a página de boas-vindas do AdonisJs.

      Página de boas-vindas do AdonisJs

      Agora, você completará a configuração do seu banco de dados. Aqui, você instalará o driver do mysql para se conectar ao seu servidor MySQL através do seu aplicativo Node.js via npm. Para começar, volte para seu terminal onde o aplicativo está funcionando, pare o processo com CTRL + C e execute o seguinte comando:

      Agora que você instalou o driver do MySQL Node.js com êxito para este aplicativo, será necessário criar o banco de dados do aplicativo e configurar a conexão apropriada para ele.

      A versão mais recente do MySQL que você instalou através do tutorial de pré-requisitos utiliza um plug-in de autenticação padrão chamado caching_sha2_password. Ele ainda não é compatível com drivers do Node.js para o MySQL. Para evitar qualquer problema de conexão de banco de dados do seu aplicativo, será necessário criar um novo usuário do MySQL e usar o plug-in de autenticação atualmente suportado, o —mysql_native_password.

      Para começar, acesse o cliente do MySQL usando a conta root:

      Será solicitado que você digite sua senha de conta root, definida durante a instalação do MySQL.

      Em seguida, crie o usuário e a senha usando o plug-in do mysql_native_password:

      • CREATE USER 'sammy'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

      Você verá o seguinte resultado:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Em seguida, crie um banco de dados para o aplicativo com:

      Você verá o seguinte resultado:

      Output

      Query OK, 1 row affected (0.03 sec)

      Você criou o banco de dados para este aplicativo com sucesso.

      Agora, habilite o acesso ao banco de dados criado para o novo usuário do MySQL. Execute o seguinte comando para conceder todos os privilégios ao usuário no banco de dados:

      • GRANT ALL PRIVILEGES ON adonis.* TO 'sammy'@'localhost';

      Recarregue as tabelas de concessão, executando o seguinte comando para aplicar as alterações que acabou de fazer:

      Você verá o seguinte resultado:

      Output

      Query OK, 0 rows affected (0.00 sec)

      Saia do cliente do MySQL com:

      Você instalou o AdonisJs CLI com sucesso, criou um novo projeto do AdonisJs e instalou o mysql via npm. Você também criou o banco de dados para este aplicativo e configurou um usuário do MySQL com os privilégios apropriados a ele. Esta é a configuração básica do seu aplicativo e, na seção seguinte, você começará a criar as visualizações necessárias para seu aplicativo.

      Passo 2 — Usando o mecanismo de modelagem Edge

      O AdonisJs vem com seu próprio mecanismo de modelo chamado Edge. Ele permite que você crie um modelo HTML reutilizável e habilita a introdução da lógica de front-end em seu aplicativo com o mínimo de código. O Edge fornece aos desenvolvedores de JavaScript as ferramentas ao desenvolver um aplicativo para compilar um layout baseado em componentes, escrever condicionais, usar iterações e criar camadas de visualização para reter a lógica. Todos os arquivos do modelo terminam com a extensão .edge, e são armazenados no diretório resources/views.

      A seguir, são exibidas as visualizações que seu aplicativo precisará para funcionar corretamente:

      • Master Layout: com o Edge, é possível criar uma página que terá CSS, arquivos comuns do JavaScript, jQuery e as partes comuns da interface do usuário que serão as mesmas ao longo do aplicativo — por exemplo, a barra de navegação, logotipo, cabeçalho, etc. Uma vez que tiver estabelecido a página de Layout Mestre, outras visualizações (páginas) em seu aplicativo a herdarão.
      • Index view: essa página utilizará o layout mestre para herdar arquivos comuns e também renderizará o conteúdo para a página inicial do aplicativo.
      • Login page: essa página também usará o layout mestre e renderizará o formulário com os campos de entrada para o nome de usuário e a senha para os usuários fazerem o login.
      • Register page: aqui, os usuários verão um formulário para registrar e ter seus detalhes permanentes no banco de dados.
      • Create quote page: os usuários utilizarão essa página para criar uma citação inspiradora.
      • Edit quote page: os usuários usarão esta página para editar uma citação.
      • View quote page: os usuários utilizarão está página para visualizar uma citação em particular.

      Para começar, use o comando adonis para criar a página de layout mestre executando o seguinte comando:

      • adonis make:view layouts/master

      Você verá um resultado similar ao seguinte:

      Output

      ✔ create resources/views/layouts/master.edge

      Esse comando criará automaticamente um arquivo master.edge em sua pasta resources/views/layouts. Abra o novo arquivo:

      • nano resources/views/layouts/master.edge

      Adicione o seguinte código nele:

      /resources/views/layouts/master.edge

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <meta http-equiv="X-UA-Compatible" content="ie=edge">
          <title>adonis-quotes-app</title>
          {{ style('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css') }}
          {{ style('style') }}
          {{ script('https://code.jquery.com/jquery-3.3.1.slim.min.js') }}
      </head>
      <body>
          <div class="container-fliud">
              @include('navbar')
              @!section('content')
          </div>
          {{ script('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js') }}
      
      </body>
      </html>
      

      Neste arquivo, inclua os arquivos CDN para o Bootstrap CSS, o Bootstrap JavaScript e o jQuery. Adicione um nome de arquivo CSS global de nome style.css e dentro do div, inclua um arquivo partial chamado navbar. Para reutilizar os fragmentos do código HTML necessários em várias páginas em seu aplicativo, como nav ou footer, incorpore as parciais. Esses são arquivos menores que contêm o código repetido, tornando mais rápida a atualização do código desses elementos em um único local, em vez de toda instância que ele ocorre. O navbar contém marcações para botões de Login e de Register, um logotipo e um link de página inicial.

      Com isso funcionando, todas as páginas seguintes que serão criadas para este aplicativo podem estender o layout mestre e ter a navbar renderizada sem a necessidade de escrever o conteúdo novamente. Você criará este arquivo navbar mais tarde no tutorial.

      Por fim, defina uma tag de seção @! section() para incluir o conteúdo de outras páginas e tê-las renderizadas pelo layout mestre. Para que isso funcione como esperado, todas as novas páginas que estendem o layout mestre também devem definir uma tag de seção com o mesmo nome (ou seja, @section('content')​​​).

      Salve e saia do arquivo assim que terminar de editá-lo.

      Em seguida, você usará o comando adonis para criar a barra de navegação:

      Você verá um resultado parecido com este:

      Output

      ✔ create resources/views/navbar.edge

      Abra o arquivo recém-criado:

      • nano resources/views/navbar.edge

      Então, adicione o seguinte código a ele:

      /resources/views/navbar.edge

      <nav class="navbar navbar-expand-lg navbar-dark text-white">
          <a class="navbar-brand" >LOGO</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
              <span class="navbar-toggler-icon"></span>
          </button>
      
          <div class="collapse navbar-collapse" id="navbarNav">
              <ul class="navbar-nav">
                  <li class="nav-item active ">
                      <a class="btn text-white" href="https://www.digitalocean.com/">Home</a>
                  </li>
              </ul>
          </div>
          <div class="navbar-right" id="navbarNav">
              @loggedIn
                  <ul class="navbar-nav">
                          <li>
                              <div class="text-right">
                                   <a href="{{route('create.quote')}}" class="btn btn-outline-primary">Create Quote</a>
                              </div>
                          </li>
      
                      <li class="nav-item dropdown">
                          <a class="nav-link dropdown-toggle" href="https://www.digitalocean.com/#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                             {{ auth.user.username}}
                          </a>
                          <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                              <form method="POST" action="{{route('logout')}}">
                                  {{ csrfField() }}
                                    <button  type="submit" class="dropdown-item" href="">logout</button>
                              </form>
                          </div>
                      </li>
                  </ul>
              @else
                  <ul class="navbar-nav">
                      <li class="nav-item active pr-2">
                          <a href="{{route('login.create')}}" class="btn btn-outline-danger">
                            login
                          </a>
                      </li>
                      <li class="nav-item active pr-2">
                          <a href="{{route('register.create')}}" class="btn btn-outline-primary">
                              Register
                          </a>
                      </li>
                  </ul>
              @endloggedIn
          </div>
      </nav>
      

      Além de definir os links para a página inicial e um botão para registrar e fazer login, adicione uma tag @loggedIn. Com isso funcionando, é possível escrever uma instrução condicional em torno do usuário autenticado e exibir o conteúdo adequado, sempre que necessário. Para um usuário autenticado, o aplicativo exibirá seu nome de usuário e um botão para criar uma nova citação. Caso um usuário não esteja logado, seu aplicativo exibirá um botão para fazer login ou registrar-se. Essa página será incluída como uma parcial em cada página, como estava antes no layout mestre para este aplicativo.

      Salve e saia do arquivo.

      Agora, você criará a página de índice que será usada para a página inicial do aplicativo. Ele renderizará e exibirá a lista de todas citações inspiradoras que os usuários escrevem:

      Você verá um resultado similar ao seguinte:

      Output

      ✔ create resources/views/index.edge

      O arquivo criado aqui estará localizado em resources/views/index.edge. Abra o arquivo:

      • nano resources/views/index.edge

      Então, adicione as linhas a seguir:

      /resources/views/index.edge

      @layout('layouts/master')
      @section('content')
      
      <div class="container">
          <div class="text-center">
              @if(flashMessage('successmessage'))
                  <span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
              @endif
          </div>
          <div class="row">
              @each(quote in quotes)
                  <div class="col-md-4 mb-4 quote-wrapper">
                      <a href="https://www.digitalocean.com/view-quote/{{quote.id}}" class="w-100">
                          <div class="card shadow-lg bg-dark text-white">
                              <div class="card-body">
                                  <blockquote class="blockquote mb-0">
                                      <p>{{quote.body}}</p>
                                      <footer class="blockquote-footer">
                                          <cite title="Source Title"> {{quote.username}}</cite>
                                      </footer>
                                  </blockquote>
                                  @if(auth.user.id == quote.user_id)
                                    <div>
                                      <a  href="http://www.digitalocean.com/edit-quote/{{quote.id}}" class="btn btn-primary">edit</a>
                                      <a href="http://www.digitalocean.com/delete-quote/{{quote.id}}" class="btn btn-danger">delete</a>
                                    </div>
                                  @endif
                              </div>
                          </div>
                      </a>
                  </div>
              @else
               <div class="col-md-12 empty-quote text-center">
                      <p>No inspirational quote has been created</p>
               </div>
              @endeach
          </div>
      </div>
      @endsection
      

      Aqui, indique que essa visualização utilizará o layout master, estendendo-a. Esta página pode ter acesso a todas as bibliotecas, folhas de estilos e a navbar incluída no layout master. Em seguida, itere sobre uma matriz de quotes utilizando a tag integrada @each. A matriz de quotes será enviada para essa visualização a partir do QuoteController, que você criará mais tarde neste tutorial. Caso não haja aspas, uma mensagem adequada será exibida.

      Salve e saia deste arquivo.

      Agora, para criar a página de login, execute o seguinte comando a partir do terminal:

      • adonis make:view auth/login

      Você verá um resultado semelhante a:

      Output

      ✔ create resources/views/auth/login.edge

      Isso criará automaticamente uma pasta auth dentro de resources/views e também criará um arquivo login.edge dentro dela. Abra o arquivo login.edge:

      • nano resources/views/auth/login.edge

      Adicione o conteúdo a seguir:

      /resources/views/auth/login.edge

      @layout('layouts/master')
      @section('content')
        <div class="container">
          <div class="row">
            <div class="col-md-4 shadow bg-white mt-5 rounded offset-md-4">
              <form method="POST" action="{{route('login.store')}}">
                {{ csrfField() }}
                  <div>
                    @if(flashMessage('successmessage'))
                      <span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
                    @endif
                  </div>
                  <div class="form-group">
                    <label for="email">Email address</label>
                    <input type="email" class="form-control" id="email" name="email" value="{{old('email','')}}"  placeholder="Enter email">
                    {{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
                  </div>
                  <div class="form-group">
                    <label for="pasword">Password</label>
                    <input type="password" class="form-control" id="password" name="password" value="{{old('password','')}}" placeholder="Password">
                    {{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
                  </div>
      
                  <div class="text-center">
                    <button type="submit" class="btn btn-primary">Submit</button>
                  </div>
              </form>
            </div>
          </div>
        </div>
      @endsection
      

      Esse arquivo possui um formulário que contém elementos de entrada que você utilizará para coletar o nome de usuário e a senha de um usuário registrado, antes de serem autenticados e começarem a criar citações com sucesso. Outro elemento importante para notar nesta página é o {{ csrfField() }}. É uma variável global que o AdonisJs utilizará para passar o token de acesso CSRF quando enviarem um pedido POST, PUT e DELETE de seu aplicativo.

      Isso foi colocado em funcionamento para proteger seu aplicativo de ataques de Falsificação de Solicitação Entre Sites (CSRF). Ele funciona criando um segredo de CSRF único para cada usuário que visita seu site e assim que eles enviarem um pedido HTTP a partir do front-end, um token correspondente é gerado para este segredo e transmitido com o pedido. Isso permitirá que o middleware, criado para essa solicitação dentro do AdonisJs, verifique se o segredo do token e do CSRF é válido e pertence ao usuário atualmente autenticado.

      Salve e saia do arquivo assim que terminar.

      Em seguida, você criará a página de registro com este comando:

      • adonis make:view auth/register

      Você verá um resultado parecido com este:

      Output

      ✔ create resources/views/auth/register.edge

      Localize e abra o arquivo recém-criado em resources/views/auth/register.edge:

      • nano resources/views/auth/register.edge

      Adicione as linhas a seguir:

      resources/views/auth/register.edge

      @layout('layouts/master')
      @section('content')
        <div class="container ">
          <div class="row">
              <div class="col-md-4  bg-white p-3 mt-5 shadow no-border rounded offset-md-4">
                <form method="POST" action="{{route('register.store')}}">
                  {{ csrfField() }}
                    <div class="form-group">
                      <label for="name">Fullname</label>
                      <input type="text" class="form-control" id="name" name="name"  value="{{old('name','')}}" placeholder="Enter Fullname">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('name'), hasErrorFor('name')) }}
                    </div>
                    <div class="form-group">
                      <label for="email">Email address</label>
                      <input type="email" class="form-control" id="email"  name="email" value="{{old('email','')}}" placeholder="Enter email">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
                    </div>
                    <div class="form-group">
                      <label for="pasword">Password</label>
                      <input type="password" class="form-control" id="password" name="password" placeholder="Password">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
                    </div>
                    <div class="text-center">
                        <button type="submit" class="btn btn-primary">Submit</button>
                    </div>
                </form>
              </div>
          </div>
        </div>
      @endsection
      

      De maneira similar a que você tem na página de login, este arquivo contém um formulário HTML com campos de entrada para coletar o name, email e o password de um usuário durante o processo de registro. O {{ csrfField() }} também está incluído, uma vez que ele é necessário para cada pedido de postagem em um aplicativo do AdonisJs.

      Salve e saia do arquivo.

      Agora, gere um novo arquivo para criar uma citação inspiradora, executando o seguinte comando a partir do terminal:

      • adonis make:view quotes/create-quote

      Você verá um resultado como:

      Output

      ✔ create resources/views/quotes/create-quote.edge

      Abra o resources/views/quotes/create-quote.edge:

      • nano resources/views/quotes/create-quote.edge

      E adicione o conteúdo a seguir a ele:

      /resources/views/quotes/create-quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-3"></div>
              <div class="col-md-6 shadow bg-white mt-5 rounded p-3">
                  <div class="float-right">
                      <a href="https://www.digitalocean.com/" class="btn btn-outline-dark ">back</a>
                  </div>
                      <br>
      
                  <div class="clear-fix"></div>
                      <form method="POST" action="{{route('store.quote')}}">
                          {{ csrfField() }}
                          <div class="form-group">
                              <label for="quote">Create Quote</label>
                              <textarea type="text" rows="5"  name='body' id="body" class="form-control" id="quote" placeholder="Write an inspirational quote"></textarea>
                          </div>
      
                          <div class="text-center">
                              <button type="submit" class="btn btn-primary">Submit</button>
                          </div>
                      </form>
                  </div>
              </div>
              <div class="col-md-3"></div>
          </div>
      </div>
      @endsection
      

      Essa página estende o layout mestre e contém um formulário HTML com um elemento de área de texto. Este elemento permite que um usuário digite um texto em várias linhas antes de ser postado e tratado pela rota apropriada.

      Salve e saia do arquivo assim que terminar.

      Em seguida, crie uma página para edição de uma citação em particular. Execute o comando a seguir a partir do terminal:

      • adonis make:view quotes/edit-quote

      Você verá o seguinte resultado:

      Output

      ✔ create resources/views/quotes/edit-quote.edge

      Abra o arquivo com:

      • nano resources/views/quotes/edit-quote.edge

      Adicione o conteúdo a seguir ao resources/views/quotes/edit-quote:

      /resources/views/quotes/edit-quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-6 shadow bg-white rounded p-3 offset-md-3">
                  <div class="float-right">
                      <a href="https://www.digitalocean.com/" class="btn btn-outline-dark ">back</a>
                  </div>
                  <br>
      
                  <div class="clear-fix"></div>
                  <form method="POST" action="/update-quote/{{quote.id}}">
                      {{ csrfField() }}
                      <div class="form-group">
                          <label for="pasword">Edit Quote</label>
                          <textarea type="text" rows="5"  name='body' id="body" class="form-control" id="quote" placeholder="write the inspirational quote">{{quote.body}}</textarea>
                      </div>
                      <div class="text-center">
                          <button type="submit" class="btn btn-primary">Update</button>
                      </div>
      
                  </form>
              </div>
          </div>
      </div>
      @endsection
      

      Essa página possui conteúdo semelhante ao do arquivo create-quote.edge—a diferença é que ela contém os detalhes de uma citação em particular que precisa ser editada, o <form method="POST" action="/update-quote/{{quote.id}}">.

      Salve e saia do arquivo.

      Por fim, gere uma página para visualizar uma única citação inspiradora:

      • adonis make:view quotes/quote

      Você verá um resultado parecido com este:

      Output

      ✔ create resources/views/quotes/quote.edge

      Abra o arquivo com:

      • nano resources/views/quotes/quote.edge

      Adicione as linhas a seguir:

      /resources/views/quotes/quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-6 offset-md-3">
                  <div class="card shadow-lg bg-dark text-white">
                      <div class="card-body">
                          <div class="float-right">
                              <a href="https://www.digitalocean.com/" class="btn btn-outline-primary ">back</a>
                          </div>
                              <br>
                          <div class="clear-fix"></div>
                          <blockquote class="blockquote mb-0">
                              <p>{{quote.body}}</p>
                              <footer class="blockquote-footer">
                                  <cite title="Source Title">{{quote.username}}</cite>
                              </footer>
                          </blockquote>
                      </div>
                  </div>
              </div>
          </div>
      </div>
      @endsection
      

      Essa página renderiza os detalhes de uma citação em particular, que inclui o corpo da citação, quote.body e o autor que a criou, quote.username.

      Quando terminar o arquivo, salve e saia.

      Você criou todas as páginas necessárias para o seu aplicativo, utilizando o mecanismo de modelagem Edge. Em seguida, você configurará e criará uma conexão para o banco de dados do seu aplicativo.

      Passo 3 — Criando um esquema de banco de dados

      Se oferecer o seu aplicativo agora, ele emitirá um erro, pois você ainda deve conectar o aplicativo a um banco de dados. Nesta seção, você configurará uma conexão com o banco de dados e, depois, usará o comando adonis para gerar um arquivo de migração que será usado para criar as tabelas para ele.

      O AdonisJs vem com um ORM chamado Lucid ORM, que fornece a implantação de registro ativo para trabalhar com o seu banco de dados. Ele elimina o incômodo de escrever consultas SQL que recuperam os dados do banco de dados em tempo real. Isso é especialmente útil ao trabalhar em um aplicativo complexo que exige muitas consultas. Como exemplo, é possível recuperar todas as citações do seu aplicativo escrevendo isso:

      const quotes = await Quote.all()
      

      Para prosseguir com a configuração apropriada para o banco de dados do seu aplicativo, certifique-se de que você ainda esteja dentro do diretório raiz do seu aplicativo e crie um arquivo .env:

      Abra o arquivo recém-criado e adicione o seguinte conteúdo:

      .env

      HOST=127.0.0.1
      PORT=3333
      NODE_ENV=development
      APP_URL=http://${HOST}:${PORT}
      CACHE_VIEWS=false
      APP_KEY=bTVOEgUvmTCfkvgrK8gEBC3Qxt1xSYr0
      DB_CONNECTION=mysql
      DB_HOST=127.0.0.1
      DB_PORT=3306
      DB_USER=sammy
      DB_PASSWORD=password
      DB_DATABASE=adonis
      SESSION_DRIVER=cookie
      HASH_DRIVER=bcrypt
      

      Por padrão, a conexão de banco de dados para um aplicativo AdonisJs é a SQLite, que você atualizará para o MySQL aqui. Você também especificará o PORT para o aplicativo, o ambiente do aplicativo e as credenciais de seu banco de dados. Certifique-se de substituir o espaço reservado para o DB_USER, DB_PASSWORD e DB_DATABASE pelas suas credenciais.

      Em seguida, você criará o modelo e um arquivo de migração para o Quote usando o Adonis CLI. Para fazer isso, execute o seguinte comando:

      • adonis make:model Quote --migration

      Você verá um resultado parecido com o seguinte:

      Output

      ✔ create app/Models/Quote.js ✔ create database/migrations/1568209992854_quote_schema.js

      Esse comando criará um modelo para o Quote na pasta app/Models e um arquivo de esquema na pasta database/migrations. O arquivo de esquema recém-criado será prefixado com o carimbo de data/hora atual. Abra o arquivo de esquema com:

      • nano database/migrations/1568209992854_quote_schema.js

      Atualize seu conteúdo com o seguinte código:

      database/migrations/…quote_schema.js

      'use strict'
      /** @type {import('@adonisjs/lucid/src/Schema')} */
      const Schema = use('Schema')
      class QuoteSchema extends Schema {
        up () {
          this.create('quotes', (table) => {
            table.increments()
            table.integer('user_id').notNullable()
            table.string('username', 80).notNullable()
            table.string('body').notNullable()
            table.timestamps()
          })
        }
        down () {
          this.drop('quotes')
        }
      }
      module.exports = QuoteSchema
      

      Um arquivo de esquema no AdonisJs exige dois métodos diferentes, que são:

      • up: usado para criar uma nova tabela ou alterar uma tabela existente.
      • down: usado para reverter as alterações feitas no método up.

      Além dos campos timestamps() e increments(), atualize o conteúdo do arquivo de esquema com os atributos de campo user_id, username e o body de uma citação que será criada. O user_id e username fazem referência aos detalhes do usuário que criam uma citação em particular. Isso define uma relação de um para vários, e significa que um usuário pode ter um número infinito de citações, ao mesmo tempo que uma única citação pode pertencer a somente um usuário.

      Salve e saia do arquivo.

      O AdonisJs vem instalado com um modelo de User e seu arquivo de migração por padrão, que exige apenas uma pequena modificação para estabelecer a relação entre o modelo de User e o Quote.

      Abra o modelo de User no app/Models/User.js:

      Adicione este método imediatamente após o método tokens():

      app/Models/User.js

      ...
      class User extends Model {
        ...
        tokens () {
          return this.hasMany('App/Models/Token')
        }
      
        quote () {
          return this.hasMany('App/Models/Quote')
        }
      }
      
      module.exports = User
      

      Isso estabelecerá um relacionamento de um para vários com a tabela Quote utilizando o user_id como a chave estrangeira.

      Salve e saia do arquivo.

      Para terminar essa seção, utilize o comando a seguir para executar as migrações, que executará o método up() de todos os arquivos de migração:

      Você verá um resultado similar ao seguinte:

      Output

      migrate: 1503248427885_user.js migrate: 1503248427886_token.js migrate: 1568209992854_quote_schema.js Database migrated successfully in 3.42 s

      Você configurou e protegeu uma conexão com seu banco de dados. Você também criou um modelo de Quote e seu arquivo de esquema correspondente e criou um relacionamento de one to many entre o User e o Quote. Em seguida, você gerará rotas e criará controladores para lidar com as solicitações HTTP e a lógica de negócios para criar, editar e excluir uma citação inspiradora.

      Passo 4 — Criando controladores e configurando rotas

      Nesta seção, você começará a criar controladores para lidar com toda a lógica para o aplicativo e, depois, anexará esses controladores a uma rota específica para que ele seja acessado pelos usuários através de uma URL.

      Para começar, utilize o Adonis CLI para criar um novo controlador de solicitação HTTP para lidar com todos os processos de autenticação para seu aplicativo, executando o seguinte comando:

      • adonis make:controller Auth --type http

      Este comando criará um arquivo AuthController.js e o salvará dentro da pasta app/Controllers/Http. Use o sinalizador --type para indicar que quer que este controlador seja um controlador HTTP.

      Você verá um resultado similar ao seguinte:

      Output

      ✔ create app/Controllers/Http/AuthController.js

      Em seguida, abra o arquivo controlador recém-criado:

      • nano app/Controllers/Http/AuthController.js

      Atualize-o com o seguinte conteúdo:

      app/Controllers/Http/AuthController.js

      'use strict'
      const User = use('App/Models/User')
      class AuthController {
      
          loginView({ view }) {
              return view.render('auth.login')
          }
          registrationView({ view }) {
              return view.render('auth.register')
          }
      
          async postLogin({ request, auth, response}) {
              await auth.attempt(request.input('email'), request.input('password'))
              return response.route('index')
          }
      
          async postRegister({ request, session, response }) {
              const user = await User.create({
                  username: request.input('name'),
                  email: request.input('email'),
                  password: request.input('password')
              })
              session.flash({ successmessage: 'User have been created successfully'})
              return response.route('login.create');
          }
      
          async logout ({ auth, response }) {
              await auth.logout()
              return response.route("https://www.digitalocean.com/")
          }
      }
      module.exports = AuthController
      

      Neste arquivo, importe o modelo User e, depois, crie dois métodos chamados loginView() e registerView() para renderizar as páginas de login e de registro, respectivamente. Por fim, crie os seguintes métodos assíncronos:

      • postLogin(): este método obterá o valor do email e password postados com a ajuda do método request integrado no AdonisJs e validará esse usuário com os detalhes no banco de dados. Caso tal usuário exista no banco de dados e tenha digitado as credenciais corretas, ele será redirecionado para a homepage e autenticado antes de criar uma nova citação. Caso contrário, será exibida uma mensagem indicando as credenciais erradas.
      • postRegister(): receberá o valor do nome do username, email e password para um usuário criar uma conta para ele no banco de dados. Uma mensagem indicando que esse usuário foi criado com sucesso será enviada para a sessão e o usuário será redirecionado para a página de login para ser autenticado e começar a criar uma citação.
      • logout(): este método lidará com a funcionalidade de logout e redirecionará o usuário para a página inicial.

      Salve e saia do arquivo.

      Agora que configurou o controlador para registrar e autenticar usuários, prossiga criando um controlador de pedido HTTP para gerenciar todas as operações a respeito das citações.

      De volta ao terminal, execute o comando a seguir para criar o QuoteController:

      • adonis make:controller Quote --type http --resource

      O uso do sinalizador --resource criará um controlador com métodos de recursos pré-definidos para fazer as operações CRUD (criação, consulta, atualização e destruição de dados).

      Você verá:

      Output

      ✔ create app/Controllers/Http/QuoteController.js

      Localize este arquivo dentro de app/Controllers/Http/QuoteController.js:

      • nano app/Controllers/Http/QuoteController.js

      Atualize-o com o seguinte conteúdo:

      app/Controllers/Http/QuoteController.js

      'use strict'
      const Quote = use('App/Models/Quote')
      
      class QuoteController {
      
        async index ({ view }) {
          const quote = await Quote.all()
          return view.render('index', {
            quotes: quote.toJSON()
          })
        }
      
        async create ({ view }) {
          return view.render('quotes.create-quote')
        }
      
        async store ({ request,auth,session, response }) {
          const quote = await Quote.create({
            user_id: auth.user.id,
            username: auth.user.username,
            body: request.input('body')
          })
          session.flash({ 'successmessage': 'Quote has been created'})
          return response.redirect("https://www.digitalocean.com/")
        }
      
        async show ({ params, view }) {
          const quote = await Quote.find(params.id)
          return view.render('quotes.view-quote', {
            quote: quote.toJSON()
          })
        }
      
        async edit ({ params, view }) {
          const quote = await Quote.find(params.id)
          return view.render('quotes.edit-quote', {
            quote: quote.toJSON()
          })
        }
      
        async update ({ params, request, response, session }) {
          const quote = await Quote.find(params.id)
          quote.body = request.input('body')
          await quote.save()
          session.flash({'successmessage': 'Quote has been updated'})
          return response.redirect("https://www.digitalocean.com/")
        }
      
        async destroy ({ params, response, session }) {
          const quote = await Quote.find(params.id)
          await quote.delete()
          session.flash({'successmessage': 'Quote has been deleted'})
          return response.redirect("https://www.digitalocean.com/")
        }
      }
      module.exports = QuoteController
      

      Neste controlador, você importou o modelo Quote e atualizou os métodos a seguir, criados automaticamente usando o AdonisJs CLI:

      • index(): busca todas as citações do banco de dados e as renderiza na página inicial do aplicativo.
      • create(): renderiza uma página para a criação de citações.
      • store(): persiste uma citação recém-criada no banco de dados e retorna uma resposta adequada.
      • show(): obtém a id de uma citação em particular, recupera-a do banco de dados e a renderiza na página de edição de citação.
      • edit(): obtém os detalhes de uma citação em particular do banco de dados e a renderiza para a edição.
      • update(): processa qualquer atualização para uma citação e redireciona o usuário para a página inicial.
      • destroy(): exclui uma citação em particular e remove-a por completo do banco de dados.

      Salve e saia do arquivo.

      Após criar todos os controladores necessários para este aplicativo, é possível configurar as rotas para que os usuários possam interagir com seu aplicativo com facilidade. Para começar, vá para o arquivo start/routes.js

      Substitua seu conteúdo com o seguinte:

      start/routes.js

      'use strict'
      const Route = use('Route')
      
      Route.get("https://www.digitalocean.com/",'QuoteController.index').as('index')
      Route.get('/register','AuthController.registrationView').as('register.create')
      Route.post('/register-store','AuthController.postRegister').as('register.store').validator('Register')
      Route.get('/login','AuthController.loginView').as('login.create')
      Route.post('/login-store','AuthController.postLogin').as('login.store')
      Route.get('/view-quote/:id','QuoteController.show').as('view.quote')
      
      Route.group(() => {
          Route.get('/create-quote','QuoteController.create').as('create.quote')
          Route.post('/store-quote','QuoteController.store').as('store.quote')
          Route.get('/edit-quote/:id','QuoteController.edit').as('edit.quote')
          Route.post('/update-quote/:id','QuoteController.update').as('update.quote')
          Route.get('/delete-quote/:id','QuoteController.destroy').as('delete.quote')
          Route.post('/logout','AuthController.logout').as('logout')
      }).middleware(['auth'])
      

      Aqui, você define o caminho para cada rota em seu aplicativo, especifica os verbos HTTP para cada ação e associa a rota a um método em particular em cada controlador. Você também nomeia cada uma destas rotas, já que elas foram referenciadas dentro dos controladores e das visualizações.

      Para garantir que apenas os usuários autenticados possam acessar todas as rotas das citações, atribui-se um middleware de grupo nomeado para ela. Por fim, você anexa um método validador para a rota register.store para validar as entradas do usuário.

      Salve e saia do arquivo.

      Você criou seus controladores e configurou as rotas para seu aplicativo. Em seguida, você criará o método validador definido neste passo.

      Passo 5 — Validando a entrada do usuário

      O AdonisJs não possui validadores integrados por padrão. Como resultado, você instalará e registrará o validador para seu aplicativo manualmente.

      Execute o comando a seguir para instalá-lo:

      Abra o arquivo a seguir para registrar o provedor validador:

      Então, registre o provedor validador adicionando ele à lista de provedores como mostrado a seguir:

      start/app.js

      ...
      const providers = [
         ...
         '@adonisjs/cors/providers/CorsProvider',
         '@adonisjs/shield/providers/ShieldProvider',
         '@adonisjs/session/providers/SessionProvider',
         '@adonisjs/auth/providers/AuthProvider',
         '@adonisjs/validator/providers/ValidatorProvider'
      ]
      

      Agora que você instalou e registrou o provedor validador dentro do seu aplicativo, crie um validador personalizado para validar as entradas do usuário durante o registro com o seguinte comando:

      • adonis make:validator Register

      Isso criará um arquivo de Register.js no diretório App/validators. Abra o arquivo com:

      • nano app/Validators/Register.js

      Adicione o código a seguir ao arquivo:

      app/Validators/Register.js

      'use strict'
      class Register {
        get rules () {
          return {
            name:'required',
            email:'required|email|unique:users',
            password:'required|min:8'
          }
        }
      
        get messages(){
          return{
            'name.required':'Full name is required',
            'email.required':'email is required',
            'email.unique':'email already exists',
            'password.required':'password is required',
            'password.min':'password should be at least 8 characters'
          }
        }
      }
      module.exports = Register
      

      Defina as regras para campos específicos em seu aplicativo. Caso as validações falhem em algum momento, o validador definirá automaticamente o erro como uma mensagem de erro e o usuário será redirecionado para o formulário.

      Salve e saia do arquivo assim que terminar de editar.

      Por fim, adicione estilos para o seu aplicativo. Abra o seguinte arquivo:

      Substitua o conteúdo dele com o seguinte:

      /public/style.css

      @import url('https://fonts.googleapis.com/css?family=Montserrat:300');
      
      html, body {
        height: 100%;
        width: 100%;
      }
      
      body {
        font-family: 'Montserrat', sans-serif;
        font-weight: 300;
        background-image: url("/splash.png");
        background-color: #220052;
      }
      
      * {
        margin: 0;
        padding: 0;
      }
      
      a {
        color: inherit;
        text-decoration: underline;
      }
      
      p {
        margin: 0.83rem 0;
      }
      
      .quote-wrapper {
        margin-top: 20px;
      }
      
      .quote-wrapper a {
        text-decoration: none;
      }
      
      .quote-wrapper a:hover {
        color: #ffffff;
      }
      
      .empty-quote {
        color: #ffffff;
      }
      
      form {
        padding: 20px;
      }
      

      Neste arquivo, você atualiza o estilo CSS do seu aplicativo no arquivo style.css.

      Você instalou e registrou um provedor validador com o propósito de verificar a entrada de usuários durante o processo de registro. Você também atualizou o conteúdo da sua folha de estilos para adicionar mais estilos ao aplicativo. No passo final, você testará seu aplicativo.

      Passo 6 — Exibindo o aplicativo

      Neste passo, você exibirá seu aplicativo e criará um usuário e senha para testar a autenticação. Você também adicionará uma citação para seu aplicativo e visualizará isso na página inicial.

      Para testar seu aplicativo, inicie o servidor de desenvolvimento com o comando a seguir a partir do diretório raiz do seu aplicativo:

      Isso inicializará o aplicativo na porta definida dentro do arquivo raiz .env, que é a 3333. Vá para http://localhost:3333 em seu navegador.

      Página inicial do aplicativo de citações

      A página inicial está vazia no momento, já que você não criou nenhuma citação. Clique no botão Register.

      Página de registro

      Digite seus detalhes e clique no botão Submit para completar o processo de registro. Você será redirecionado para a página de login. Digite seu endereço de e-mail e senha para a autenticação.

      Página de login

      Assim que estiver autenticado, clique no botão Create Quote.

      Página de criar citação

      Digite uma citação e vá para a página View all para ver sua citação.

      Página de visualização de todas citações

      Você testou seu aplicativo criando e autenticando um usuário e, em seguida, escreveu uma citação.

      Conclusão

      Neste tutorial você criou um aplicativo Web com o AdonisJs. Você configurou o aplicativo utilizando o AdonisJs CLI e usou o CLI para a criação de outros arquivos relevantes, como controladores, modelos e visualizações.

      Você pode desenvolver aplicativos Web com este framework independente do tamanho e complexidade deles. Fique à vontade para baixar o código-fonte para este projeto aqui no GitHub. Para explorar recursos adicionais, visite a documentação oficial.

      Caso queira explorar alguns de nossos outros tutoriais de framework do JavaScrip,confira o seguinte:



      Source link

      Cómo crear e implementar una aplicación de Flask utilizando Docker en Ubuntu 18.04


      El autor seleccionó el Tech Education Fund para que recibiese una donación como parte del programa Write for DOnations.

      Introducción

      Docker es una aplicación de código abierto que permite a los administradores crear, administrar, implementar y replicar aplicaciones usando contenedores. Los contenedores pueden considerarse como un paquete que alberga las dependencias que una aplicación requiere para ejecutarse a nivel de sistema operativo. Esto significa que cada aplicación implementada usando Docker reside en un entorno propio y sus requisitos se gestionan por separado.

      Flask es un micromarco web que se compila con Python. Se denomina micromarco porque no requiere herramientas ni complementos específicos para ejecutarse. El marco de Flask es ligero y flexible, pero muy estructurado. Esto lo convierte en la opción preferida por encima de otros marcos.

      Implementar una aplicación de Flask con Docker le permitirá replicarla en varios servidores con una reconfiguración mínima.

      A través de este tutorial, creará una aplicación de Flask y la implementará con Docker. En este artículo, también se abordará la manera de actualizar una aplicación tras la implementación.

      Requisitos previos

      Para completar este tutorial, necesitará lo siguiente:

      Paso 1: Configurar la aplicación de Flask

      Para comenzar, creará una estructura de directorios que contendrá su aplicación de Flask. En este tutorial, se creará un directorio llamado TestApp en /var/www, pero puede modificar el comando para darle el nombre que desee.

      • sudo mkdir /var/www/TestApp

      Diríjase al directorio TestApp recién creado:

      A continuación, cree la estructura de carpetas para la aplicación de Flask:

      • sudo mkdir -p app/static app/templates

      El indicador -p marca que mkdir creará un directorio y todos los directorios principales que no existen. En este caso, mkdir creará el directorio principal app en el proceso de creación de los directorios static y templates.

      El directorio app contendrá todos los archivos relacionados con la aplicación de Flask, como sus vistas y modelos. Las vistas son el código que uste escribe para responder a las solicitudes a su aplicación. Los modelos crean componentes de aplicaciones, y admiten patrones comunes dentro de una aplicación y entre varias de estas.

      El directorio static es el punto en el que se alojan recursos como los archivos de imagen, CSS y JavaScript. El directorio templates es el espacio en el que dispondrá las plantillas HTML para su proyecto.

      Ahora que la estructura básica de carpetas está completa, cree los archivos necesarios para ejecutar la aplicación de Flask. Primero, cree un archivo __init__.py dentro del directorio app. Este archivo indica al intérprete de Python que el directorio app es un paquete y debería tratarse como tal.

      Ejecute el siguiente comando para crear el archivo:

      • sudo nano app/__init__.py

      Los paquetes de Python le permiten agrupar módulos en jerarquías o espacios de nombres lógicos. Este enfoque permite desglosar el código en bloques individuales y manejables que realizan funciones específicas.

      A continuación, añadirá código al __init__.py que creará una instancia de Flask e importará la lógica desde el archivo views.py, que creará tras guardar este archivo. Añada el siguiente código a su nuevo archivo:

      /var/www/TestApp/__init__.py

      from flask import Flask
      app = Flask(__name__)
      from app import views
      

      Una vez que lo haga, guarde y cierre el archivo.

      Después de crear el archivo __init__.py, estará listo para crear el archivo views.py en su directorio app. Este archivo contendrá la mayor parte de la lógica de su aplicación.

      A continuación, añada el código a su archivo views.py. Con este código se mostrará la cadena hello world! a los usuarios que visiten su página web:

      /var/www/TestApp/app/views.py

      from app import app
      
      @app.route('/')
      def home():
         return "hello world!"
      

      La línea @app.route sobre la función se conoce como decorador. Los decoradores modifican la función que los sigue. En este caso, el decorador indica a Flask la URL que desencadenará la función home(). El texto hello world mostrado por la función home se mostrará al usuario en el navegador.

      Una vez que esté preparado el archivo views.py, estará listo para crear el archivo uwsgi.ini. Este archivo contendrá las configuraciones de uWSGI para nuestra aplicación. uWSGI es una opción de implementación para Nginx que es tanto un protocolo como un servidor de aplicaciones; el servidor de aplicaciones puede proporcionar los protocolos uWSGI, FastCGI y HTTP.

      Para crear este archivo, ejecute el siguiente comando:

      A continuación, añada el siguiente contenido a su archivo para configurar el servidor uWSGI:

      /var/www/TestApp/uwsgi.ini

      [uwsgi]
      module = main
      callable = app
      master = true
      

      Este código define el módulo desde el que se proporcionará la aplicación de Flask. En este caso, este es el archivo main.py, citado aquí como main. La opción callable indica a uWSGI que use la instancia de app exportada por la aplicación principal. La opción master permite que su aplicación siga ejecutándose, de modo que haya poco tiempo de inactividad incluso cuando se vuelva a cargar toda la aplicación.

      A continuación, cree el archivo main.py, que es el punto de entrada a la aplicación. El punto de entrada indica a uWSGI cómo interactuar con la aplicación.

      A continuación, copie lo siguiente y péguelo en el archivo. Con esto, se importará la instancia de Flask llamada app desde el paquete de la aplicación que se creó previamente.

      /var/www/TestApp/main.py

      from app import app
      

      Finalmente, cree un archivo requirements.txt para especificar las dependencias que el administrador de paquetes pip instalará en su implementación de Docker:

      • sudo nano requirements.txt

      Añada la siguiente línea para agregar Flask como dependencia:

      /var/www/TestApp/app/requirements.txt

      Flask==1.0.2
      

      Esto especifica la versión de Flask que se instalará. En el momento en que se redactó este tutorial, la versión 1.0.2 fue la más reciente de Flask. Puede verificar si existen actualizaciones en el sitio web oficial de Flask.

      Guarde y cierre el archivo. De esta manera, habrá configurado correctamente su aplicación de Flask y estará listo para configurar Docker.

      Paso 2: Configurar Docker

      A lo largo de este paso creará dos archivos, Dockerfile y start.sh, para crear su implementación de Docker. El archivo Dockerfile es un documento de texto que contiene los comandos utilizados para ensamblar la imagen. El archivo start.sh es una secuencia de comandos shell que creará una imagen y un contenedor desde Dockerfile.

      Primero, cree Dockerfile.

      A continuación, añada su configuración deseada a Dockerfile. Estos comandos especifican la forma en que se creará la imagen y los requisitos adicionales que se incluirán.

      /var/www/TestApp/Dockerfile

      FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
      RUN apk --update add bash nano
      ENV STATIC_URL /static
      ENV STATIC_PATH /var/www/app/static
      COPY ./requirements.txt /var/www/requirements.txt
      RUN pip install -r /var/www/requirements.txt
      

      En este ejemplo, la imagen de Docker se creará a partir de una imagen existente, tiangolo/uwsgi-nginx-flask, que podrá encontrar en DockerHub. Esta imagen de Docker concreta es una buena opción en comparación con otras, porque es compatible con una amplia variedad de versiones de Python e imágenes de SO.

      Las primeras dos líneas especifican la imagen principal que utilizará para ejecutar la aplicación e instalar el procesador de comandos bash y el editor de texto nano. También instala el cliente git para realizar extracciones desde servicios de alojamiento de control de versiones, como GitHub, GitLab y Bitbucket, e incorporaciones en ellos. ENV STATIC_URL /static es una variable de entorno específica para esta imagen de Docker. Define la carpeta estática desde la cual se proporcionan todos los recursos como imágenes, archivos CSS y archivos JavaScript.

      Las últimas dos líneas copiarán el archivo requirements.txt al contenedor para que pueda ejecutarse y luego analice el archivo requirements.txt para instalar las dependencias especificadas.

      Guarde y cierre el archivo después de añadir su configuración.

      Una vez que este listo su Dockerfile, casi estará preparado listo para escribir la secuencia de comandos start.sh que creará el contenedor de Docker. Antes de escribir la secuencia de comandos start.sh, primero asegúrese de disponer de un puerto abierto para usarlo en la configuración. Para verificar si hay un puerto libre, ejecute el siguiente comando:

      • sudo nc localhost 56733 < /dev/null; echo $?

      Si el resultado del comando anterior es 1, el puerto estará libre y podrá utilizarse. De lo contrario, deberá seleccionar un puerto diferente para usarlo en su archivo de configuración start.sh.

      Una vez que encuentre un puerto abierto para usarlo, cree la secuencia de comandos start.sh:

      La secuencia de comandos start.sh es una secuencia de comandos de shell que creará una imagen desde Dockerfile y un contenedor a partir de la imagen de Docker resultante. Añada su configuración al nuevo archivo:

      /var/www/TestApp/start.sh

      #!/bin/bash
      app="docker.test"
      docker build -t ${app} .
      docker run -d -p 56733:80 
        --name=${app} 
        -v $PWD:/app ${app}
      

      La primera línea se denomina shebang. Especifica que este es un archivo bash y se ejecutará como comandos. En la siguiente línea se especifica el nombre que desea dar a la imagen y al contenedor, y se guarda como una app con nombre variable. La siguiente línea indica a Docker que cree una imagen desde su Dockerfile ubicado en el directorio actual. Con esto, se creará una imagen llamada docker.test en este ejemplo.

      Con las últimas tres líneas se crea un nuevo contenedor llamado docker.test que se expone en el puerto 56733. Finalmente, vincula el directorio actual al directorio /var/www del contenedor.

      El indicador -d se utiliza para iniciar un contenedor en el modo de demonio, o como proceso en segundo plano. El indicador -p se incluye para vincular un puerto del servidor a un puerto concreto del contenedor Docker. En este caso, vinculará el puerto 56733 al puerto 80 en el contenedor Docker. El indicador -v especifica un volumen de Docker para montarlo en el contenedor y, en este caso, usted montará todo el directorio del proyecto en la carpeta /var/www del contenedor de Docker.

      Ejecute la secuencia de comandos start.sh para crear la imagen de Docker y un contenedor a partir de la imagen resultante:

      Una vez que la secuencia de comandos termine de ejecutarse, utilice el siguiente comando para enumerar todos los contenedores en ejecución:

      Verá un resultado en el que se mostrarán los contenedores:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 58b05508f4dd docker.test "/entrypoint.sh /sta…" 12 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:56733->80/tcp docker.test

      Verá el contenedor docker.test en ejecución. Ahora que se está ejecutando, visite la dirección IP en el puerto especificado de su navegador: http://ip-address56733.

      Verá una página similar a la siguiente:

      Página de inicio

      Una vez completado este paso, habrá implementado correctamente su aplicación de Flask en Docker. A continuación, usará plantillas para mostrar el contenido a los usuarios.

      Paso 3: Presentar archivos de plantillas

      Las plantillas son archivos que muestran contenido estático y dinámico a los usuarios que visitan su aplicación. En este paso, creará una plantilla HTML con el propósito de producir una página de inicio para la aplicación.

      Comience creando un archivo home.html en el directorio app/templates:

      • sudo nano app/templates/home.html

      Añada el código para su plantilla. Con este código, se creará una página HTML5 que contiene un título y texto.

      /var/www/TestApp/app/templates/home.html

      
      <!doctype html>
      
      <html lang="en-us">   
        <head>
          <meta charset="utf-8">
          <meta http-equiv="x-ua-compatible" content="ie=edge">
          <title>Welcome home</title>
        </head>
      
        <body>
          <h1>Home Page</h1>
          <p>This is the home page of our application.</p>
        </body>
      </html>
      

      Guarde y cierre el archivo una vez que agregue su plantilla.

      A continuación, modifique el archivo app/views.py para presentar el archivo recién creado:

      Primero, añada la siguiente línea al inicio de su archivo para importar el método render_template desde Flask. Con este método se analiza un archivo HTML para presentar una página web al usuario.

      /var/www/TestApp/app/views.py

      from flask import render_template
      ...
      

      Al final del archivo, también agregará una nueva ruta para representar el archivo de plantilla. Con este código se especifica que los usuarios reciben el contenido del archivo home.html cuando visitan la ruta /template en su aplicación.

      /var/www/TestApp/app/views.py

      ...
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      El archivo app/views.py actualizado tendrá este aspecto:

      /var/www/TestApp/app/views.py

      from flask import render_template
      from app import app
      
      @app.route('/')
      def home():
          return "Hello world!"
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Guarde y cierre el archivo cuando termine.

      Para que estos cambios se apliquen, deberá detener y reiniciar los contenedores de Docker. Ejecute el siguiente comando para volver a compilar el contenedor:

      • sudo docker stop docker.test && sudo docker start docker.test

      Visite su aplicación en http://your-ip-address:56733/template para ver la nueva plantilla que se presenta.

      Página de inicio

      Con esto, habrá creado un archivo de plantilla de Docker que se presentará a los visitantes de su aplicación. En el siguiente paso, verá cómo los cambios que realice a su aplicación pueden aplicarse sin necesidad de reiniciar el contenedor de Docker.

      Paso 4: Actualizar la aplicación

      A veces, deberá realizar en la aplicación cambios que pueden incluir instalar nuevos requisitos, actualizar el contenedor de Docker o aplicar modificaciones vinculadas al HTML y a la lógica. A lo largo de esta sección, configurará touch-reload para realizar estos cambios sin necesidad de reiniciar el contenedor de Docker.

      autoreloading de Python controla el sistema completo de archivos en busca de cambios y actualiza la aplicación cuando detecta uno. No se aconseja el uso de autoreloading en producción porque puede llegar a utilizar muchos recursos de forma muy rápida. En este paso, utilizará touch-reload para realizar la verificación en busca de cambios en un archivo concreto y volver a cargarlo cuando se actualice o sustituya.

      Para implementar esto, abra su archivo uwsgi.ini:

      A continuación, añada la línea resaltada al final del archivo:

      /var/www/TestApp/uwsgi.ini

      module = main
      callable = app
      master = true
      touch-reload = /app/uwsgi.ini
      

      Esto especifica un archivo que se modificará para activar una recarga completa de la aplicación. Una vez que realice los cambios, guarde y cierre el archivo.

      Para demostrar esto, realice un pequeño cambio a su aplicación. Comience abriendo su archivo app/views.py:

      Sustituya la secuencia de comandos mostrada por la función home:

      /var/www/TestApp/app/views.py

      from flask import render_template
      from app import app
      
      @app.route('/')
      def home():
          return "<b>There has been a change</b>"
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Guarde y cierre el archivo después de realizar un cambio.

      A continuación, si abre la página de inicio de su aplicación en http://ip-address56733<^> observará que los cambios no se reflejan. Esto se debe a que la condición para volver a cargar es un cambio en el archivo uwsgi.ini. Para volver a cargar la aplicación, use touch a fin de activar la condición:

      Vuelva a cargar la página de inicio de la aplicación en su navegador. Verá que en la aplicación se incorporaron los cambios:

      Página de inicio actualizada

      Al completar este paso, habrá configurado una condición touch-reload para actualizar su aplicación tras realizar cambios.

      Conclusión

      A través de este tutorial, creó una aplicación de Flask y la implementó en un contenedor de Docker. También configuró touch-reload para actualizar su aplicación sin necesidad de reiniciar el contenedor.

      Con su nueva aplicación en Docker, ahora podrá realizar el escalamiento de forma sencilla. Para obtener más información sobre el uso de Docker, consulte su documentación oficial.



      Source link