Gerenciando Product Backlog usando o Azure DevOps (TFS)

Atualizado em 18/03/19 após a mudança do Visual Studio Online para Azure DevOps!

Quando começamos a estudar o Scrum Guide logo nos deparamos com o artefato Product Backlog. O framework prescreve que o Product Owner deve manter este artefato com todos os itens necessários ao produto/projeto a ser desenvolvido, de maneira priorizada, atualizada e visível.

No entanto, algo que o framework não prescreve é como fazer isso e a ideia do post de hoje é justamente essa, mostrar uma ideia de como organizar o seu Product Backlog usando a ferramenta Azure DevOps, a versão mais recente do antigo Team Foundation Server da Microsoft (TFS), em sua versão SaaS. Não vou falar aqui de priorização de backlog, coisa que já falei em outros posts, mas de como usar esta ferramenta web para fazê-lo e explicando alguns conceitos importantes que podem ser aplicados independente da ferramenta que você venha a utilizar.

Azure DevOps

Em idos de 2008 a empresa que eu trabalhava à época, RedeHost, adquiriu licença para instalarmos em um servidor nosso o Team Foundation Server, uma suíte para gerenciamento do ciclo de vida de aplicações (ALM – Application Lifecycle Management). Nela podíamos gerenciar desde as tarefas de um projeto, o versionamento de seu código, automatizar o seu build, issue tracker, etc.

Em 2010 a Microsoft lançou o preview do TFS na nuvem, em versão SaaS, onde era possível ter acesso à mesma suíte sem necessitar de um servidor local e sem se preocupar com a escala do SQL Server, que era um requisito que incomodava bastante nosso pessoal de infra. De lá pra cá a ferramenta web mudou bastante e, embora não seja uma ferramenta perfeita, é muito útil para gerenciar todo tipo de projeto, independente da tecnologia utilizada, uma vez que oferece suporte a versionamento com Git, diversos plugins, uma API rica e muito mais.

Note que mesmo que você não tenha interesse algum nestas features de Integração Contínua (CI – Continuous Integration), você ainda pode usar a ferramenta para Task Management.

Para poder prosseguir neste tutorial, crie uma conta gratuita definindo uma URL para você. A minha é luiztools.visualstudio.com e tenho essa conta há muitos anos, desde a época do preview. Enquanto você tiver até 5 usuários cadastrados na sua conta, você não terá de pagar nada à Microsoft, o que é excelente para pequenos times de desenvolvimento.

Criando um novo projeto

Na tela inicial da ferramenta você tem um botão New Project no canto direito. Use ele e defina um nome para o projeto. Se você tem apenas um time que toca diversos projetos, pode ser interessante colocar o nome do time aqui, ao invés do nome do projeto atual deles, para fins de histórico.

Create Project
Create Project

Na seção Advanced da criação do projeto você tem outras opções que incluem a tecnologia de versionamento (que eu deixo para você decidir) e o template de Work Items dentre os possíveis:

  • CMM: fundamentado no CMMI;
  • Agile: fundamentado no antigo MSF for Agile da Microsoft;
  • Scrum: fundamentado no Scrum;
  • Basic: não conheço;

Usaremos o Scrum neste tutorial e enquanto o primeiro eu nunca usei, os dois últimos são praticamente idênticos, mudando alguns estados e a nomenclatura de alguns Work Items (User Stories do Agile viram Product Backlog Items no Scrum, por exemplo).

New Project
New Project

Uma vez com o projeto criado, acesse o menu lateral Boards > Backlogs. É aqui que concentramos os nossos esforços neste artigo.

Organizando o Product Backlog

Nesta área nós temos acesso a um modelo de gerenciamento de backlog prescrito pela ferramenta, uma vez que o framework Scrum não toma partido do método A ou B de gerenciamento de backlog.

Níveis de Backlog
Níveis de Backlog

Existem diversos níveis de backlog que auxiliam o Product Owner (principalmente) a se organizar. Para ver todos os níveis, use o pequeno ícone de Settings na extrema direita da tela (uma engrenagem), logo acima das colunas do backlog. Dentro das configurações, na aba Backlogs, marque as três opções: Epics, Features e Product Backlog Items.

Settings - Backlog
Settings – Backlog

Os três níveis de Backlog são Epics, Features e Product Backlog Items, à saber:

  • Epics: épicos são histórias de usuário muito grandes e pouco detalhadas, geralmente levando várias sprints para ser concluído (pense na grandeza de meses de trabalho). Você pode criar épicos pensando em marcos/milestones/grandes versões do seu produto/projeto, como “MVP do Produto X” ou como grandes entregas do seu time, como “Entrega de Março”. Ou ainda falando de um módulo específico, que seja muito grande.
  • Features: funcionalidades são incrementos de software dentro de um épico, simbolizando partes coerentes do produto que geram valor ao usuário de uma maneira completa. Dentro de um épico como “MVP do Produto X”, cada funcionalidade que não deve faltar ao MVP é uma feature dentro do épico. O mesmo vale para o épico “Entrega de Março”, onde cada feature é um dos pedaços desta entrega.
  • Product Backlog Items: os famosos itens de backlog do produto são citados no Scrum Guide como sendo a unidade de trabalho do Product Backlog. Um PBI gera valor ao usuário por si só e entregar um ou mais deles pronto (DONE) atinge ao grau máximo de sucesso de uma sprint, o chamando “incremento de software potencialmente entregável”. Embora o Scrum não prescreva uma fórmula para escrever esses itens, o mais comum é que se use o formato de User Stories aqui.

O formato recomendado de escrita é partir do Work Item Type menos granular (Epic) até o mais granular (Product Backlog Item), usando o próprio recurso de “Add Feature”que fica à disposição à esquerda do Epic e “Add Product Backlog Item” que fica à esquerda das Features, sempre com um ícone de adição (+). Sendo assim, acesse o nível Epic do seu Product Backlog e comece criando os seus épicos com apenas títulos. Mais tarde você pode adicionar mais detalhes a cada um deles (mas não muito, eles são apenas visões) clicando no título dos mesmos.

Backlog preenchido
Backlog preenchido

Após adicionar os seus épicos, adicione features dentro de cada um deles, de acordo com o que você sabe hoje sobre os épicos. Faça isso na mesma visão organizacional de Epics, para ir vendo os desdobramentos e hierarquia dos mesmos. Para este exercício, pegue um projeto real do seu time ou então um problema fictício como um cadastro de cliente. O épico seria fazer a v1 do cadastro, sendo que as features poderiam ser “Adicionar novo cliente”, “Excluir cliente”, etc.

Conforme você for adicionando as features dentro do épico você já pode ir quebrando seus Product Backlog Items (PBIs). Se você atendeu à minha sugestão de usar User Stories, pense em todos as histórias de usuário que puder lembrar para cada uma das features. Algumas features simples talvez tenham apenas uma história, enquanto outras mais complicadas podem ter várias. Não esqueça de, além de escrever o título e descrição da história (usando o formato padrão da User Story), escreva também os critérios de aceite no campo adequado (Acceptance Criteria).

Product Backlog Item
Product Backlog Item

É importante ter em mente que o Product Owner tem total liberdade neste momento. Crie, edite e exclua seus Work Items livremente. É comum escrevermos algumas histórias que mais tarde descobrimos serem épicos. É comum épicos serem quebrados em mais épicos para que o sistema não vire um mero waterfall-iterativo. Questões relacionadas a prioridades de itens podem ser feitas usando o campo Priority ou a própria ordenação visual (drag-n-drop com o mouse). Embora o time tenha acesso ao Product Backlog como um todo, não é a partir dele que eles se orientarão no dia-a-dia, como falarei mais adiante.

Organizando as sprints

A visão de backlog que usamos até o momento são de foco do Product Owner. O Time de Desenvolvimento trabalha usando a visão da sprint atual (current sprint) dentro do Visual Studio Online. A visão das sprints fica em Boards > Sprint no menu lateral, sendo que você tem um menu para filtrar as sprints na direita da tela (current é a atual).

Sprints
Sprints

Durante a Sprint Planning o Product Owner explica quais são as prioridades do Product Backlog. Sobre cada história prioritária, o time deve detalhar quais as tarefas serão necessárias para que seja possível estimar o esforço (campo Effort) de entrega daquele Product Backlog Item.

Uma técnica muito comum utilizada para estas estimativas é a de Planning Poker, já citada aqui no blog. Caso o Time de Desenvolvimento julgue útil, eles podem “quebrar” os Product Backlog Items em Tasks dentro da própria ferramenta usando o botão de + (Add Task) à esquerda do PBI, na mesma visão que o Product Owner usa para gerenciar o backlog.

Quebrando tasks
Quebrando tasks

Existe um campo Work Remaining dentro das Tasks que permite adicionar a estimativa de tempo para realização de cada tarefa. Se você optar por quebrar e/ou estimar as tarefas é uma decisão do time, mas essa atividade é auxiliar para descobrir o esforço da história. Entende-se que somente a entrega completa da história agrega valor ao cliente e consequentemente nos permite dar uma sprint como bem sucedida.

Após descobrir o esforço de cada um dos PBIs prioritários do P.O., o time decide qual o volume de PBIs que cabem na sprint usando o somatório de seus campos Effort. Se esse time já rodou sprints anteriores usando a mecânica de pontos eles já devem ter algum histórico de velocidade. Caso contrário terão de chutar mesmo, posteriormente analisando na Sprint Retrospective o quão próximo estavam da realidade.

Uma vez definido o escopo da próxima sprint, cada uma das Tasks e PBIs que farão parte da mesma devem ter seu campo Iteration ajustado para a sprint correta, como mostra a imagem abaixo.

Iteration - Sprint 1
Iteration – Sprint 1

O Time de Desenvolvimento irá trabalhar somente olhando o backlog da sprint que, via de regra, não deve ser mudado durante o desenvolvimento da mesma sem o consentimento do time. Na aba Board o time tem um taskboard (tipo Kanban) que apesar de não ser tão bom de usar quanto o Trello, é bem útil e completamente personalizável, o que pode ser assunto para outro post.

Taskboard
Taskboard

Boas Práticas

Algumas boas práticas para quem está começando a usar o Visual Studio Online agora e até mesmo está começando com Scrum:

  • Como Product Owner, refine o seu backlog quase que diariamente, detalhando as histórias mais importantes, consultando o time sobre o impacto de cada uma delas, consultando os stakeholders, analisando o mercado, etc. O seu backlog sempre deve estar atualizado, priorizado e visível quando uma Sprint Planning for começar.
  • Cada história pode estar associada a um membro do time (campo Assigned To). Converse com seu time para que ninguém associe mais de uma história a si mesmo para evitar problemas.
  • Como Product Owner, use os três níveis de backlog, isso ajuda a deixar tudo mais organizado e ao time entender para onde o projeto está caminhando.
  • Priorize visualmente o seu backlog, deixando o que é mais prioritário no topo. Apesar de existir um campo Priority, ele é facilmente negligenciado por não ser muito visual.
  • Use o padrão de User Stories em seus PBIs para focar na entrega de valor para o usuário final e facilitar o entendimento dos requisitos por parte do Time de Desenvolvimento.
  • Estime em Story Points as suas histórias e não em horas. Isso tem uma série de benefícios mas principalmente descola alguns conceitos de chão de fábrica como produtividade em horas.
  • use Tags (tem um campo pra isso) nos seus PBIs para facilitar consultas, relatórios e dashboards mais tarde (aba Queries e Dashboards). Use a imaginação, tags podem ser qualquer coisa.
  • não se preocupe em usar tudo que a ferramenta oferece, aprenda o básico que faz sentido pra você e depois vá usando o restante conforme for necessitando. Uso o TFS desde 2008 e até hoje tem coisas lá que nunca precisei.

Espero que tenham gostado do post e até a próxima!

Neste artigo ensino como manter um bom nível de qualidade e detalhamento do backlog.

* OBS: curtiu o post? Então dá uma olhada no meu livro de Scrum e Métodos Ágeis e/ou no meu curso sobre o mesmo assunto!

Curso de Scrum e Métodos Ágeis
Curso de Scrum e Métodos Ágeis

Gerenciando Product Backlog usando o Jira Software

Quando começamos a estudar o Scrum Guide logo nos deparamos com o artefato Product Backlog. O framework prescreve que o Product Owner deve manter este artefato com todos os itens necessários ao produto/projeto a ser desenvolvido, de maneira priorizada, atualizada e visível.

No entanto, algo que o framework não prescreve é como fazer isso e a ideia do post de hoje é justamente essa, mostrar uma ideia de como organizar o seu Product Backlog usando a ferramenta Jira Software, em sua versão SaaS. Não vou falar aqui de priorização de backlog, coisa que já falei em outros posts, mas de como usar esta ferramenta web para fazê-lo e explicando alguns conceitos importantes que podem ser aplicados independente da ferramenta que você venha a utilizar.

Jira Software

O Jira é a ferramenta líder de vendas para gestão de projetos de software no mundo todo, sendo um concorrente direto do Azure DevOps da Microsoft (o antigo TFS). A sua fabricante, Atlassian, possui uma suíte de soluções que vão desde o Trello, para gestão básica de quadros de trabalho, até ferramentas de chat e colaboração entre times, versionamento de código e construção de pipelines automatizados de deploy.

Mesmo que você não venha a usar a suíte completa (até porque sairia bem caro), usar o Jira pode ser uma excelente opção para tocar os seus projetos de maneira mais organizada. A ferramenta SaaS tem muitas funcionalidades interessantes e um grande fit com as metodologias ágeis como Scrum e Kanban, fornecendo todos os artefatos prontos ou configuráveis para os usuários.

Ao contrário do TFS (que te dá 5 usuários free), o Jira não possui versão free (a menos que conte o Trello como sendo um mini-Jira, hehe) e oferece apenas um trial de uma semana na época em que escrevo este artigo. O trial é suficiente para que consiga aprender a usar a ferramenta e seguir este tutorial. Então, crie uma conta no site da Atlassian antes de prosseguir.

Vale salientar que este tutorial cobre apenas a versão SaaS (cloud, online) do Jira, sendo que ele possui uma versão on-premise cuja interface é diferente, embora o funcionamento seja o mesmo.

Criando um novo projeto

Na tela inicial da ferramenta você tem um botão Create Project no canto direito. Use ele e defina um nome para o projeto. Se você tem apenas um time que toca diversos projetos, pode ser interessante colocar o nome do time aqui, ao invés do nome do projeto atual deles, para fins de histórico. Ao longo deste tutorial usarei o template Scrum, que foi selecionado como na imagem abaixo (esquerda).

Novo Projeto
Novo Projeto

Outras opções na criação do projeto incluem o método Kanban e isso influencia bastante a organização dos itens, os quadros e diversos outros fatores, embora seja possível mudar de um para outro.

Organizando o Product Backlog

Uma vez com o projeto criado, você vai ser direcionado para a tela de Backlog do seu projeto, sendo que aqui ele representa o Product Backlog, cuja gestão é de responsabilidade do Product Owner.

Product Backlog
Product Backlog

No Jira existem três níveis de backlog que auxiliam o Product Owner (principalmente) a se organizar, ambos acessíveis na parte esquerda, entre o meno lateral e o backlog, à saber:

  • Epics: épicos são features muito grandes e pouco detalhadas (alto nível de incerteza técnica), geralmente levando várias sprints para serem concluídas (pense na grandeza de semanas a meses de trabalho). Épicos são constituídos de múltiplas User Stories.
  • User Stories: o Jira assume o padrão de Histórias do Usuário para os famosos itens de backlog do produto que são citados no Scrum Guide como sendo a unidade de trabalho do Product Backlog. Uma User Story gera valor ao usuário por si só e entregar uma ou mais delas prontas (DONE). User Stories geralmente levam dias para serem entregues, possuem linguajar de negócio e grau de incerteza técnica médio, podendo ser quebradas em pedaços menores, chamados de Sub-Tasks, para se ter maior assertividade do trabalho a ser realizado.
  • Sub-Task: uma sub-task é uma tarefa que deve levar horas para ser feita, é extremamente técnica, com baixo grau de incerteza técnica e não entrega muito valor por si só, fazendo parte de um grupo que juntas, entregam o valor proposto pela User Story.

O formato recomendado de escrita é partir do Issue Type menos granular (Epic) até o mais granular (Sub-Task), usando o menu Epics que fica à esquerda do backlog, mas antes do menu lateral. Sendo assim, acesse o nível Epic do seu Backlog.

Clique em Epics
Clique em Epics

Nesta tela da imagem acima, note que tem um link “Create Epic” ao lado da seção EPICS, clique nele para começar a criar os seus épicos com apenas o título e um resumo. Mais tarde você pode adicionar mais detalhes a cada um deles (mas não muito, eles são apenas visões) clicando no título dos mesmos

Criando um épico
Criando um épico

Após adicionar os seus épicos, você vai ver eles na coluna esquerda do painel. Note na imagem abaixo como o épico “Cartão no App” aparece depois do meu cadastro e com ele a opção “Create issue in epic”, que é justamente para criar elementos dentro dele. Caso já existam issues, elas aparecerão no painel da direita.

Épico criado
Épico criado

Clique no “Create issue in epic” para adicionar uma User Story (o Issue Type padrão), com um título, descrição (a história em si) e o que mais você precisar.

Criando uma US
Criando uma US

Para este exercício, pegue um projeto real do seu time ou então um problema fictício como um cadastro de cliente. O épico seria fazer a versão completa do cadastro, sendo que as User Stories poderiam ser “Adicionar novo cliente”, “Excluir cliente”, etc.

Se você atendeu à sugestão do Jira de usar User Stories, pense em todos as histórias de usuário que puder lembrar para cada um dos épicos. Alguns épicos simples talvez tenham apenas uma ou duas histórias, enquanto outros mais complicados podem ter várias. Não esqueça de, além de escrever o título e descrição da história (usando o formato padrão da User Story), escreva também os critérios de aceite.

É importante ter em mente que o Product Owner tem total liberdade neste momento. Crie, edite e exclua seus Epics e User Stories livremente. É comum escrevermos algumas histórias que mais tarde descobrimos serem épicos. É comum épicos serem quebrados em mais épicos para que o sistema não vire um mero waterfall-iterativo. Embora o time tenha acesso ao Product Backlog como um todo, não é a partir dele que eles se orientarão no dia-a-dia, como falarei mais adiante.

Organizando as sprints

A visão de backlog que usamos até o momento são de foco do Product Owner. O Time de Desenvolvimento trabalha usando a visão da sprint atual (current sprint) dentro do Jira. Assim que tiver algumas User Stories criadas, como abaixo, vai aparecer um botão de “Create Sprint” no canto superior direito.

US criadas
US criadas

Ao iniciar uma planning (ou agora, para fins de exercício), clique no botão “Create Sprint” e você será direcionado para o planejador de sprints. Na parte inferior da tela ele lista as User Stories existentes e, na parte superior, o escopo da sprint atual, que vai se tornar o Sprint Backlog. Explico: durante a Sprint Planning o Product Owner explica quais são as prioridades do Product Backlog.

Criando a Sprint
Criando a Sprint

Sobre cada história priorizada, o time clica nela e deve discutir quais as tarefas serão necessárias para que seja possível estimar o esforço (campo Estimate) de entrega daquela história.

Estimando US
Estimando US

Uma técnica muito comum utilizada para estas estimativas é a de Planning Poker, já citada aqui no blog. Caso o Time de Desenvolvimento julgue útil, eles podem “quebrar” as User Stories em Sub-Tasks dentro da própria visão da User Story que contém um link “Create Sub-Task”, abrindo a tela abaixo.

Create Sub-Task
Create Sub-Task

Aqui você define um nome para a sub-task e sua descrição, sendo que você pode adicionar estimativas para as sub-tasks depois, se quiser. As estimativas, em especial a da histórias, compõem o esforço da sprint e são usadas mais tarde para geração de gráficos e extração de métricas ágeis importantes para o time. Se você optar por quebrar e/ou estimar as tarefas é uma decisão do time, mas essa atividade é auxiliar para descobrir o esforço da história. Entende-se que somente a entrega completa da história agrega valor ao cliente e consequentemente nos permite dar uma sprint como bem sucedida.

Após descobrir o esforço de cada uma das User Stories prioritárias do P.O. (a unidade de medida padrão é Story Points, mas também pode ser configurado), o time decide qual o volume de histórias que cabem na sprint arrastando as mesmas para a parte superior do planejador de sprint, sendo que no rodapé da mesma aparece o esforço total.

Arrastando histórias
Arrastando histórias

Se esse time já rodou sprints anteriores usando a mecânica de pontos eles já devem ter algum histórico de velocidade. Caso contrário terão de chutar mesmo, posteriormente analisando na Sprint Retrospective o quão próximo estavam da realidade.

Uma vez definido o escopo da próxima sprint, você clica no botão azul “Start Sprint” que aparece na imagem anterior, lhe permitindo configurar os últimos detalhes desta sprint, como o Sprint Goal e as datas de início e fim.

Iniciando a sprint
Iniciando a sprint

O Time de Desenvolvimento irá trabalhar somente olhando o backlog da sprint que pode ser acessado usando o menu Active Sprint na esquerda, e via de regra, o escopo não deve ser mudado durante o desenvolvimento da mesma. Nessa tela de Active Sprint o time tem um Kanban virtual que apesar de não ser tão bom de usar quanto o Trello, é bem útil e completamente personalizável, o que pode ser assunto para outro post.

Active Sprint
Active Sprint

Boas Práticas

Algumas boas práticas para quem está começando a usar o Jira Software agora e até mesmo está começando com Scrum:

  • Como Product Owner, refine o seu backlog quase que diariamente, detalhando as histórias mais importantes, consultando o time sobre o impacto de cada uma delas, consultando os stakeholders, analisando o mercado, etc. O seu backlog sempre deve estar atualizado, priorizado e visível antes de uma Sprint Planning for começar.
  • Cada história pode estar associada a um membro do time (campo Assigned To). Converse com seu time para que ninguém associe mais de uma história a si mesmo para evitar problemas.
  • Como Product Owner, use e encoraje os três níveis de backlog, isso ajuda a deixar tudo mais organizado e ao time entender para onde o projeto está caminhando.
  • Priorize visualmente o seu backlog, deixando o que é mais prioritário no topo. Apesar de existir campos que auxiliam nisso, as demais configurações são facilmente negligenciadas por não serem muito visuais.
  • Use o padrão de User Stories em suas Issues para focar na entrega de valor para o usuário final e facilitar o entendimento dos requisitos por parte do Time de Desenvolvimento.
  • Estime em Story Points as suas histórias e não em horas. Isso tem uma série de benefícios mas principalmente descola alguns conceitos de chão de fábrica como produtividade em horas.
  • use Tags (tem um campo pra isso) nas suas User Stories para facilitar consultas, relatórios e dashboards mais tarde (aba Reports). Use a imaginação, tags podem ser qualquer coisa.
  • não se preocupe em usar tudo que a ferramenta oferece, aprenda o básico que faz sentido pra você e depois vá usando o restante conforme for necessitando.

Espero que tenham gostado do post e até a próxima!

Neste artigo ensino como manter um bom nível de qualidade e detalhamento do backlog.

* OBS: curtiu o post? Então dá uma olhada no meu livro de Scrum e Métodos Ágeis e/ou no meu curso sobre o mesmo assunto!

Curso de Scrum e Métodos Ágeis
Curso de Scrum e Métodos Ágeis

Autorização em Node.js com Passport – Parte 4

Esse tutorial é uma continuação de uma série de artigos sobre segurança em Node.js que iniciei há algum tempo, usando o módulo Passport, o mais popular para autenticação em Node.js. Nas etapas anteriores nós criamos o login, o cadastro, a recuperação de senha e o logout. Hoje vamos criar a camada de autorização, ou seja, uma vez que o usuário esteja autenticado, devemos permitir ou não que ele faça determinadas operações no sistema conforme o seu perfil de acesso.

Atenção: para que possa acompanhar este tutorial é necessário que tenha realizado as etapas anteriores ou ao menos baixado o zip do tutorial anterior, disponível via formulário sempre ao final dos tutoriais. Note que mesmo baixando o zip, você terá de ter o Node.js e o MongoDB instalados na sua máquina (este último rodando) e tem de revisar o arquivo .env para configurar ele com os seus dados (email, string de conexão do banco, etc). Sugiro cadastrar também alguns usuários no seu Mongo para poder usar o sistema corretamente.

Vale salientar que este artigo possui uma versão em videoaula, disponível aos inscritos em meu curso de Node.js e MongoDB.

Vamos lá!

O tripé de segurança

Os elementos mais básicos de segurança em sistemas são o tripé AAA: Autenticação, Autorização e Auditoria. Já falamos extensivamente sobre autenticação nos artigos anteriores e nesse vamos falar de autorização.

A diferença mais básica é que autenticação se resume a dizer quem pode ou não entrar. Já autorização, é o que cada usuário que entrou, pode fazer no sistema.

Existem várias maneiras de implementar isso, das mais elaboradas (usando recursos dedicados de infraestrutura como Active Directory ou LDAP, por exemplo) às mais simples, ter perfis no seu banco de dados e dar match com eles na hora de ver se o usuário pode ou não fazer algo que ele quer. Eu irei neste tutorial pela segunda abordagem.

Espero em artigos futuros falar do terceiro A do tripé: a auditoria, que nada mais é do que o registro das atividades dos usuários no sistema, para consulta futura.

Autorização com ExpressJS e Passport

Como já foi implementado nos tutoriais anteriores e extensivamente explicado, o Passport é um framework genérico para construir de maneira modular a segurança do seu sistema. Nos tutoriais passados usamos ele em conjunto com um conector de MongoDB, pra usar o respectivo banco como sendo a verdade em termos de autenticação do sistema.

Assim, a cada requisição do ExpressJS, usamos o middleware para chamar uma função de verificação e dizer se o usuário pode ou não continuar fazendo aquela requisição ou se deve ser jogado para a tela de login. O que iremos fazer aqui são três coisas:

  • fornecer funções genéricas para que possa ser verificado a autorização do usuário para determinada operação;
  • aplicar tais funções no middleware do Express para, nas chamadas do Passport, avaliar não apenas a autenticação, mas também a autorização;
  • chamar tais funções também na renderização da interface, para garantir que ela atenda às necessidades de segurança conforme usuário autenticado;

Com isso, você não terá um sistema completo, mas um overview de como aplicar tais conceitos e códigos em um sistema real.

Adaptando o cadastro

A primeira coisa que vamos fazer é adaptar a nossa tela de signup para incluir a informação de perfil do usuário. Aqui faremos algo super simples: ao cadastrar um novo usuário, você vai selecionar entre os perfis de administrador e de usuário.

Modifique a view signup.ejs para incluir um select de perfil, como abaixo:

O que vai resultar em uma tela renderizada assim:

Signup com Perfil
Signup com Perfil

O usuário é salvo no banco de dados através de uma função createUser que fica no nosso módulo db.js. Assim, vamo nesse módulo alterar a respectiva função:

Note que você já tem usuários cadastrados no sistema, eles não terão a informação de profile (perfil) salva neles. Aí você tem duas opções: tratar quem não tem perfil como sendo um usuário padrão (que não é administrador), ou fazer um script para alterar todos os usuários já cadastrados no MongoDB para terem a informação de profile também.

Eu vou de primeira opção, vou considerar que por padrão os usuários sem profile NÃO são administradores.

Agora, para fazer o botão Save voltar a funcionar, vamos na rota users.js e vamos editar o código que trata requisições POST no endpoint /signup para que ele espere e salve o dado do perfil também, usando a função que acabamos de alterar, como abaixo:

Com isso, seu cadastro já deve estar funcionando novamente e sugiro que cadastre um novo usuário como sendo administrador, já que os anteriores vão ser todos considerados comuns.

Está curtindo o post? Para uma formação ainda mais completa como programador web recomendo meu livro sobre programação web com Node.js clicando no banner abaixo!

Inserindo autorização por página

Agora que você tem a informação de perfil junto ao usuário cadastrado e cadastrou um usuário administrador, vamos dar alguns privilégios apenas para administradores. Que tal criar uma página que somente eles podem acessar?

Vamos criar uma nova view chamada views/reports.ejs com um conteúdo bem simples, só pra testarmos o conceito:

E vamos criar um novo arquivo de rota em routes/reports.js com apenas o tratamento de um GET, como abaixo:

Note como o global.autheticationMiddeware() é chamado, não apenas nesta, mas em todas rotas do sistema. Isso garante uma centralização das regras de segurança de acesso, que vamos modificar depois.

Registre essa nova rota no app.js como abaixo:

Se você rodar essa aplicação agora e tentar acessar digitando a URL http://localhost:3000/reports no seu navegador, conseguirá acessar normalmente esta página com qualquer usuário devidamente autenticado, mas não conseguirá acessar antes de fazer login (o servidor vai te redirecionar pra página de login se tentar fazer isso).

Mas e se quisermos restringir o acesso a essa página somente a administradores?

Existem várias maneiras de fazer isso. Vou te mostrar uma possibilidade que é centralizando em um módulo a estrutura de decisão para acesso às páginas. Certamente você deve ter várias ideias de como fazer melhor isso, mas essa é a mais simples e didática que consegui imaginar.

Crie na raiz do seu projeto um arquivo permissions.js e vamos criar nele uma lógica que, dada uma requisição, verificamos o usuário autenticado e que página ele está tentando acessar. Batemos essas informações com um switch/case e concedemos ou não a autorização para aquela página.

Note que eu inicio o código criando uma constante e uma função muito simples para dizer se um perfil é ou não é admin. Mas é no module.exports que realmente programo algo de valor pois, dado uma request, eu pego as informações que me interessam e confronto elas com as URLs e suas lógicas de autorização.

Essa é uma abordagem centralizada em um módulo para as regras de autorização. Assim fica bem fácil de manter a aplicação com as regras necessárias. Outra abordagem que já usei no passado era de fazer isso em cada página, ao invés de fazer centralizado e ficou bem ruim de dar manutenção pois era fácil de esquecer de adicionar as regras certas. Aqui, do jeito que está, caso você se esquecer, ao testar já não vai abrir a página e você vai lembrar que deve permitir no arquivo permissions.js.

Mas como fazer esse código de fato passar a valer?

Volte ao app.js e você vai encontrar o código que configura o global.authenticationMiddleware. Você vai modificá-lo para, além de verificar se o usuário está autenticado, verificar se ele tem a permissão necessária para acessar aquela rota, usando o módulo que acabamos de criar, assim:

Agora, toda vez que uma rota for acionada, além de verificar se o usuário está autenticado ou não, vai ser verificado se ele possui permissão para acessar aquela rota. Eu deixei um comentário no código do permissions.js que lhe sugere no futuro verificar o method da request também. Assim, você pode diferenciar tentativas de acesso de tentativas de submissão de formulários, por exemplo.

Esse código, do jeito que está, já funciona e se você acessar sua aplicação e se autenticar, dependendo do usuário que utilizou vai conseguir ou não acessar a página /reports.

Customizando a interface pelo perfil

Para finalizar esse artigo, outra coisa bem comum de ser utilizado em sistemas são as interfaces customizadas conforme a permissão do usuário. Por exemplo, um botão pode ser visto apenas um perfil específico, pois é um botão importante.

Claro, você nunca deve confiar apenas em esconder elementos de interface, mas considerando que já garantimos na seção anterior a segurança por acesso, independente se foi feito digitando a URL ou clicando em links, agora vamos fazer um exemplo bem simples de esconder ou mostrar um elemento de interface baseado no perfil autenticado.

Primeiro, vamos na rota index.js e vamos mudar o código levemente, para informar o perfil do usuário autenticado no model que enviaremos pra view, como abaixo:

Note que a única linha que mexi foi aquela do profile, para passá-lo para a view.

Agora, na view views/index.ejs, vamos editar o código HTML para, baseado no perfil do usuário, exibir ou não um link para a página de relatórios. Basta inserir esse trecho em qualquer parte da página:

Com isso, você pode testar sua aplicação com diferentes usuários e verificar que somente quando se autentica com os administradores é que consegue ver o dito-cujo link que acabou de adicionar.

Link para Admins
Link para Admins

O mais legal é que, independente do usuário ver ou não o link, se ele tentar burlar acessando diretamente a página de reports, a nossa segurança que está no middleware vai barrar ele também.

E por hoje é isso, espero que tenha gostado, deixe suas dúvidas nos comentários. Você pode baixar os fontes usando o formulário que pede seu e-mail e, se quiser participar do meu curso de Node.js e MongoDB, além de fazer parte do meu grupo online de Whatsapp com mais de 100 estudantes de Node, clique no banner abaixo.

Este artigo tem uma versão em videoaula em uma das aulas do meu curso de Nodejs e MongoDB que você confere clicando no banner abaixo.

Curso Node.js e MongoDB
Curso Node.js e MongoDB