26 jun. 2018

Tests unitarios y refactorización: hacia una arquitectura de microservicios (1)

Siguiendo con el ejemplo que me ha traído hasta aquí (1, 2 y 3) el objetivo de este artículo es ver como podemos organizar, dividiéndolo en librerías y organizando la solución por carpetas, un servicio que pretende aplicar DDD. Digo pretende porque en nuestro caso el dominio es quizá demasiado simple pues solo hablamos de usuarios y prácticamente no hemos añadido nada a Identity pero lo vamos a estructurar así porque el objetivo de este proyecto es crecer y aplicar una arquitectura basada en microservicios. ¿Qué va a tener ésta futura arquitectura? En cuanto a servicios, a grandes rasgos el objetivo es tener:

  1. NetCore21.Site será nuestro "servicio de entrada", es decir, la interfaz de la arquitectura hacia el mundo exterior, tanto porque ahí alojemos nuestra web como porque también exponemos un API autenticado que podrá ser utilizado por, potencialmente, cualquier tipo de cliente como podrían ser aplicaciones de escritorio o móviles nativas.
  2. NetCore21.Authentication.Service, aquí tendremos, en un servicio aislado, todo lo referente a la autenticación
  3. NetCore21.Whatever.Service,  que como bien dice el nombre será cualquier cosa, cualquier unidad de negocio, funcional y con entidad propia. tal que, como hace NetCore21.Authentication.Service tenga razón de ser por si mismo, con pocos o ningún punto de contacto con el dominio global de la solución. Este tipo de microservicios pueden ser desarrollados y mantenidos por pequeños grupos de desarrollo además de poder ser desplegados y escalados de forma independiente, sin duda las principales ventajas de los microservicios.
Respecto a los microservicios, sobre microservicios se ha escrito y se escribe mucho, hay muchas lecturas recomendadas y varios repositorios muy inspiradores. Mi experiencia me dice que, respecto a los microservicios, el principal reto es dividir el dominio global en pequeños contextos aislados minimizando todo lo posible las interrelaciones entre ellos. Para diseñar una arquitectura de microservicios se hace necesario conocer conceptos como API Gateway, DDD, EventSourcing y CQRS, entre otros muchos. Además requiere que se conozca muy bien el negocio para poder realizar la subdivisión en unidades de negocio o unidades funcionales, las cuales, a su vez, son las principales candidatas en convertirse en uno o varios microservicios.  Este artículo no pretende convertirse en una introducción a los microservicios (lo apuinto en mi TODO list), el objetivo es reestructurar la actual solución y cubrir con tests unitarios el código que ya tenemos y estamos moviendo, aplicando principios SOLID por el camino, ya de paso.

¿Por dónde empezamos? Pues creo que tiene lógica extraer todo lo referente a autenticación a librerías separadas, vamos a añadir una carpeta de solución, Authentication y a ver qué podemos extraer del actual monolito. (un rato después...)

Hemos extraído cuatro proyectos para la autenticación y ahora tenemos dos proyectos de tests, el inicial del site y otro para la parte de autenticación:

  • Authentication
    • NetCore21.Authentication
    • NetCore21.Authentication.Abstract
    • NetCore21.Authentication.Data
    • NetCore21.Authentication.Domain
  • Tests
    • NetCore21.Authentication.Tests
    • NetCore21.Site.Tests
Y tras adaptar ligeramente nuestro scritp de SonarScanner (ver el "Docker práctico: SonarQube") y escribir varios tests para JwtFactory y TokenGenerator, hemos obetnido una cobertura cercana al 100% en ambas clases:




Y un par de horas después, con calma, Hemos cubierto con tests unitarios Tanto AccountController como los validadores de los view models que usamos en nuestros controladores... Y tras lanzar el script de SonarScanner los resultados son éstos, la cobertura ha aumentado hastya un 34% (he quitado TypeScript del análisis por ahora, ya haré un artículo sobre tests unitarios con Angular, otra tarea a mi TODO list), y hemos conseguido probar el 100% de AccountsController aumentando con ello la cobertura general del proyecto Site:



Respecto al aspecto que tiene el código de tests voy a dejar algún ejemplo pero no todo, ,por ejemplo, AccountsControllerTests utiliza tres mocks, uno por cada dependencia que el controlador tiene, el UserManager, el mapper de AutoMapper, y el DbContext, y en él se prueban:
  1. Los parámetros del constructor (hay gente que discrepa de estos tests pero no podemos dar por hecho que esta clase siempre va a ser usada dentro de esta aplicación con nuestro querido mecanismo nativo de inyección de dependencias)
  2. Que ante un ModelState inválido se devuelve un BadRequest
  3. Que cuando CreateAsync falla se devuelve un BadRequest (dudo de si es la mejor opción)
  4. Que, por último, cuando todo está correcto, se salva el nuevo usuario y se devuelve un Ok (200)
Es decir, tenemos una lista de requisitos de bajo nivel con el comportamiento de ese componente, con las cosas que hace, y esa lista se ha convertido en una lista de tests, los cuales además indican, con su nombre, qué es lo que se está probando. Ya lo dije hace tiempo en otro artículo, los tests, nuestra lista de tests, deberían documentar nuestro código tan sólo con sus nombres pues cubren requisitos de bajo nivel... Os invito a comentar y a criticar estos tests unitarios:


Quedan varios controladores que cubrir con tests unitarios y al hacerlo cubriremos también clases y código usado indirectamente por ellos, voy a continuar con AuthController... Y veinte minutos y siete tests después ya tenemos una cobertura del 100% en AuthController lo que además supone que en total tenemos un 47% de cobertura.

Creo que puedo decir que el código de pruebas es auto explicativo pero aprovecho para recordar que siempre contesto cuando se me pregunta así que si estás leyendo esto y te surge alguna duda por favor compártela conmigo y estaré encantado de ayudarte.

Quedan por probar FaceoobController y ProfileController pero ambos tienen varios problemas que los hacen difícilmente testables como por ejemplo, un DbContext dentro del controlador, que es algo a evitar pues, digamos que debería estar en otra capa debidamente encapsulado, o, por ejemplo, hacer un private HttpCliente = new HttpClient() con lo que se genera una fuerte dependencia que además nos impide hacer un test unitario del bloque o los bloques de codigo que lo usen. 

Como comienzo parece suficiente, hemos empezado a refactorizar, a extraer librerías y a cubir el código con tests unitarios y por el camino hemos limpiado y ordenado un poco todo. En el siguiente artículo vamos a centarnos un poco más en lo que es DDD y en las capas que se proponen y extraeremos de los controladores de nuestro API toda la lógica de negocio a una capa de servicios de aplicación. También abordaremos uno de los típicos módulos reutilizables entre servicios, Http, es decir, el poder hacer peticiones Http entre servicios, nuestros o de terceros como en el caso de la autenticación con Facebook. Durante los últimos años, tomando como punto de partida ResilientHttpClient (lo podéis encontrar en el repositorio eShopsOnContainers del equipo de César de la Torre), lo he ido evolucionando en diferentes proyectos y actualmente dicho componente se ha convertido en uno de esos artefactos de código de los que uno se siente orgulloso por la cantidad de problemas que resuelve. Lo dicho, de momento cerramos este primer artículo y espero tener el siguiente durante los próximos días. 

Un saludo,


Juan

18 jun. 2018

Docker práctico: SonarQube

Durante los dos últimos artículos he estado trabajando en una app con Angular 6 y ASP NET Core 2.1 (1) y (2). En éste artículos vamos a cambiar un poco de temática y vamos a centrarnos en la calidad del código y voy a mostrar de forma práctica como podemos usar Docker para tener en nuestro sistema un servidor de SonarQube para poder hacer un seguimiento de la calidad de nuestro código.

PRE-REQUISITOS


  • Tener Docker instalado en nuestra máquina
  • Tener el SDK de .Net Core (2.1 en nuestro caso,  2.1.300 para ser más exactos)

INVESTIGACIÓN INICIAL

Lo primero que vamos a hacer es localizar la imagen del contenedor que queremos utilizar así que con una simple búsqueda en Google, ' SonarQube Docker' llegamos a su página dentro de Docker Hub. En esa página hay un pequeño HowTo y además vemos que por defecto la imagen utiliza una base de datos H2 embebida pero que está preparada para funcionar también contra un PostgreSQL, también es sencillo llegar al repositorio de GitHub de SonarSource con varias recetas que usaremos nosotros hoy, https://github.com/SonarSource/docker-sonarqube/blob/master/recipes.md .

SETUP SONARQUBE

Siguiendo esta receta vamos a crearnos una carpeta para trabajar, yo usaré D:\Systems\SonarQube. Podríamos bajar y ejecutar las imagenes por separado, con 'docker run' pero veréis que utilizar ficheros compose es bastante más práctico pues en un fichero compose podemos declarar y configurar todos los servicios, redes y volúmenes que componen o van a componer nuestro sistema. En éste caso necesitamos:
  • Una imagen de SonarQube (servicio de SonarQube que correrá en el puerto 9000)
  • Una imagen de PostgreSQL (la base de datos de moda durante los últimos años, como ellos mismos dicen 'The world's most advanced open source database')
  • Una red internal, sonarnet siguiendo la nomenclatura del ejemplo
  • Varios volúmenes para el almacenamiento de los datos, tanto de PostgreSQL como de SonarQube


Una vez tenemos nuestro fichero docker-compose.yml definido podemos irnos a una consola, a dicha carpeta, y ejecutar docker-compose up, con el siguiente resultado:


Genial, ha sido fácil y ya tenemos un SonarQube listo para trabajar contra él.

SETUP SONAR SCANNER

Para utilizar SonarQube y poder analizar nuestro código en .Net hay que utilizar un componente de software que se llama SonarScanner y para el que hay diferentes "sabores", SonarScanner for MSBuild, SonnarScanner for .Net core etcétera. Las últimas veces que lo usé, en el trabajo principalmente, usé el de MSBuild y ewl de .NEt Core pero viendo su documentación ( https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+MSBuild )  veo que acaban de sacar un "sabor" nuevo y que se puede descargar como herramienta global (Global Tool), sigamos las instrucciones que hay en NuGet https://www.nuget.org/packages/dotnet-sonarscanner para dicho paquete. 

Y tras instalar dicha herramienta y ver que el output dice que podemos invocar directamente sonarscanner haciendo dotnet-sonarscanner quedo gratamente sorprendido porque antes no era tan sencillo, la verdad. Lo siguiente será crear nuestro primer script para analizar con SonarScanner y mandar el resultado a SonarQube.


SCRIPT CON SONAR SCANNER

Para este ejemplo vamos a usar, como dije antes, el proyecto de ASP NET Core 2.1 con Angular 6, para esto crearemos el script en la raiz de dicho proyecto y estaremos atentos a incluir los artefactos generados durante la ejecución de la herramienta en nuestro .gitignore (o lista de ficheros y carpetas ignorados en el control de código fuente), éste es el script más básico que se puede ejecutar:



Como vemos siempre hay que "envolver" el scanner entre un begin y un end, en éste caso tan sólo estamos haciendo dotnet build sobre la solución pero dentro de este bloque podemos ejecutar tests unitarios y utilizar herramientas de cobertura de código para generar unos reportes y mandárselos también a SonarQube, de momento éste script tan básico funciona:
Pero nos da unos resultados realmente desalentadores debido a que en el análisis se han incluido librerías y código auto-generado, algo que será lo siguiente que quitemos:


Vamos a quitar todo lo que haya dentro de wwwroot, todos los ficheros JavaScript y Program.cs y Startup.cs de nuestro análisis incluyendo '/d:sonar.exclusions="**\wwwroot\**,**\*.js, **\Program.cs, **\Startup.cs"' en el begin de nuestro script inicial... Y tras volver a lanzar el script el resultado ya es bastante más acorde a lo que esperábamos:

Una vulnerabilidad (potencial) y 10 code smells que suponen una deuda técnica estimada en alrededor de una hora. Genial! ... Quince minutos después ya hemos resuleto todos esos problemas y nuestro proyecta ya "huele" mucho mejor:


TEST COVERAGE

Ahora es el momento de empezar a pensar en la cobertura de código, hay muchísimo por cubrir y ni un sólo test unitario en nuestro proyecto, eso por un lado, y por otro debemos adapatar nuestro script de SonarScanner para generar esos reportes... ¿Por donde empezamos? Pues preparemos el script para que genere los reportes y un proyecto vacío de tests pero dejemos los tests unitarios y la consecuente refactorización para el siguiente artículo, ¿de acuerdo?

¿Qué necesitamos para generar reportes de cobertura de código? Bueno, nosotros vamos a usar la herramienta cuyo uso está más extendido, OpenCover, para hacerlo, por lo que leo, aún no existe una Global Tool como con SonarScanner, ya que es una característica bastante nueva del framework 2.1... Pero siempre podemos instalar el paquete NuGet y referenciar la ruta de instalación en nuestro script para luego usarlo las veces que queramos.


Lo instalamos, yo lo he hecho creando una librería de clases vacía que será la que contenga los tests unitarios e instalando la referencia a este paquete NuGet desde el propio Visual Studio. Además he modificado ligeramente el script para que ejecute los tests sobre el proyecto de test que acabo de crear, quedando así:


Bueno, venga, vamos a crear tres o cuatro tests "tontos" para ver que empezamos a cubrir código:



Es algo muy simple, vamos a probar los métodos del típico ValuesController, al menos los gets, que son los únicos que tienen una implementación testable, absurda pero testable. 

En este punto lo siguiente que veo necesario es reestructurar un poco la organización del código, así lo dejamos preparado para evolucionar, para lo cuál dejaremos la solución en la raíz, junto con el script de SonarQube, y crearemos una carpeta tests donde estarán los proyectos de tests y otra carpeta NetCore21.Site a donde moveremos el proyecto inicial, incluyendo ya de paso, un pequeño renombrado del mismo proyecto a NetCore21.Site, incluyendo namespaces y usings. Tras esta reestructuración he modificado el script de Sonar para incluir todos estos cambios de rutas y tras ejecutarlo vemos que ya estamos teneiendo un mínimo de cobertura de código:


Ahora es momento de subir todos estos cambios al repositorio y plantear una re-estructuración por proyectos, así como cubrir con tests unitarios todo lo que llevamos hecho hasta ahora, pero todo esto será en el siguiente artículo.

Espero que os esté siendo útil. Saludos,

Juan

ASP NET Core 2.1 + Angular 6 - Autenticación y autorización en 10 pasos

Siguiendo con el ejemplo del artículo anterior éste artículo pretende dar solución a un requisito habitual en cualquier aplicación web, la autenticación y autorización de usuarios. El desarrollo y aplicación de esta característica en nuestras aplicaciones web se puede enfocar de dos maneras:
  1. Delegar: es decir, usar un servicio externo que nos provea de todas las funcionalidades que necesitamos para gestionar tanto en el backend como en el frontend los procesos de registro, login y permisos, para lo cuál hay muchos proveedores entre los que cabe destacar Auth0.

    He probado y usado Auth0 en varias aplicaciones con Angular y tengo que decir que es fácil de integrar ya que su documentación no sólo es extensa, cubre casi todas las casuísticas con multitud de lenguajes y frameworks, sino que es concisa y plagada de ejemplos basados en repositorios de GitHub.
  2. Desarrollar: ponernos manos a la obra e implementar en nuestro propio backend un servicio de autenticación/autorización. Para esto, nosotros que trabajamos con .NET, tenemos un framwork y ejemplos para implementar este servicio pero tengo que decir que, muy a mi pesar, la documentación es enrevesada y la traducción al castellano es pésima. Ya he desarrollado e implementado este tipo de servicios en el pasado pero quiero hacerlo desde cero, como si no supiera nada sobre el tema, y utilizar la página web del anterior artículo, basada en Angular 6 y ASP NET Core 2.1, para otorgarle esas típicas funcionalidades, registro, login y permisos... Pero, ¿por dónde empezar?
A la hora de desarrollar la seguridad de nuestras páginas web con ASP NET ( Core 2.1) el mejor punto de partida es, dentro de la documentación oficial, la sección Security, pero como decía la documentación es, quizá, demasiado extensa. El primer párrafo nos dice:
ASP.NET Core enables developers to easily configure and manage security for their apps. ASP.NET Core contains features for managing authentication, authorization, data protection, SSL enforcement, app secrets, anti-request forgery protection, and CORS management. These security features allow you to build robust yet secure ASP.NET Core apps.
Veamos si es verdad. ¿Por donde empezamos? Bueno, pues lo primero que nos interesa es ASP.NET Core Identity "a membership system which allows you to add login functionality to your application.".

Analicemos la situación, ¿qué necesitamos y cómo vamos a ir evolucionando? Tras analizar la documentación voy a dividir este proceso en 10 pasos:
  1. Crearemos un modelo, es decir, definir qué atributos vamos a guardar para los usuarios de nuestra aplicación, incluso si vamos a tener varios tipos de usuarios. empecemos con algo tan básico como AppUser, es decir, usuarios de nuestra aplicación, Customer, es decir, esos usuarios como clientes, y Partner, esos usuarios como socios.
    1. AppUser
      1. Customer
      2. Partner
  2. Crearemos y configuraremos una base de datos donde almacenar toda esta información, ASP NET Core Identity usa Entity Framework y con EF podemos configurar diferentes tipos de almacenamiento, tanto SQL como No SQL (hay muchos ejemplos por ahí mostrando esto mismo con PostgreSQL o MongoDB). En éste ejemplo usaré EF con SQL Server (en un contenedor) y la creación inicial y las sucesivas modificaciones las gestionaré con Migrations.
  3. Gestionar el registro desde el API (con el típico AcountsController), para empezar sólo con email, registro y ya.
  4. Añadir JWT, JSON Web Tokens, para generarlos y autenticar a nuestros usuarios con ellos una vez hagan Login
  5. Crearemos un controlador protegido, con autenticación basada en claims
  6. Crearemos un formulario de registro y uno de acceso junto con las correspondientes llamadas al API
  7. Crearemos un módulo de administración y un componente profile en el que aparecerán nuestros datos de usuario.
  8. Protegeremos nuestras rutas con AuthGuard para que sólo los usuarios con ciertos permisos puedan acceder a ciertas 'zonas' de nuestro cliente.
  9. Haremos llamadas autenticadas a nuestro API, verificando así que nuestra infraestructura de seguridad está lista para ser utilizada
  10. Implementaremos la autenticación con Facebook aplicando todo lo anterior
Pues, tras terminar nuestra fase de análisis (que aquí parece que ha sido hecha al vuelo pero que en realidad me ha tenido leyendo documentación y artículos durante días, y no es la primera vez que abordo este tema) es momento de ponerse manos a la obra. Tengo que decir que este artículo me hubiera costado muchísimo más tiempo escribirlo si no hubiera sido por Mark Mcneil,(FullStack Mark), desde aquí gracias y un saludo.

0. PAQUETERÍA

Para facilitar el trabajo a quien siga esta guía dejaré aquí la lista de PAquetes que han sido necesarios incluir en el proyecto.

1 EL MODELO

Nuestras clases han de heredar de IdentityUser, que pertence a Microsoft.AspNetCore.Identity:



2.- LA BASE DE DATOS

Bueno, éste no es un artículo sobre EF, que podría escribir uno, y tengo que dar por hecho que si estás leyendo esto conoces EF, sabes lo que es un DbContext y conoces también los diferentes enfoques en cuanto a modelo, DB First, Model First o Code First. Lo que queremos hacer es, en base a modelo que hemos creado para nuestros usuarios, crear una base de datos que lo almacene (esto es Code First, pues hemos definido primero el modelo con código). PAra hacer esto vamos a crear un NetCore21DbContext que herede de IdentityDbContext<T> donde T será nuestro AppUser, además nuestro contexto tendrá dos DbSet, uno para customers y otro para partners.

Nota: le he llamado NetCore21DbContext a propósito porque me gustaría crear una plantilla de solución que incluya todo esto dado un nombre, que reemplazará a NetCore21 en toda la solución.

Además debemos registrar y configurar éste DbContext en nuestro Startup, en ConfigureServices como de costumbre:


Ahora tenemos que crear nuestra base de datos y configurar nuestra cadena de conexión en appsettings.json. Para esto voy a usar un contenedor Docker, en el fondo es igual que tener SQL Server instalado solo que el contenedor apenas gasta recursos y lo para cuando ya no lo necesito.

El siguiente paso es crear la migración de datos inicial y actualizar la base de datos, para lo cual hacen falta dos comandos:

dotnet ef migrations add initial
y
dotnet ef database update
Y ya está, ya podemos empezar a trabajar contra nuestra base de datos.

3.- ACCOUNTS CONTROLLER

Ahora llega la hora de la verdad, vamos a crear un controlador para gestionar las cuentas. Para ello éste controlador necesita varias cosas:

  • Un UserManager<T>, donde T serán nuestros AppUser, éste UseManager nos lo da AspNetCoreIdentity
  • Nuestro DbContext
  • Un mapeador, para lo que vamos a usar AutoMapper, hay otras librerías que también funcionan muy bien pero AutoMapper es la más extendida y sobre la que es más fácil encontrar soluciones.
  • Un ViewModel para el registro, RegistrationViewModel suena bien, ¿verdad?


Además debemos añadir AutoMapper e IdentityCore a nuestros servicios en Startup.ConfigureServices y configurar el mapeo. Dejo el estado actual de Startup.cs un poco más abajo.

Para probar todo esto tenemos dos opciones, usar Swagger, con lo que tendríamos que instalarlo y configurarlo en nuestra aplicación, creo que lo vamos a dejar para el final, o usar Postman... Como somos Full Stack developers entonces usaremos Postman, Postman es nuestro amigo, ¿verdad? Pues si está todo en orde y creamos un POST a localhost:5000/api/account con los datos que hayamos puesto en nuestro RegistrationViewModel entonces deberíamos tener una respuesta similar a esta:

Ok, un logro más, vamos a ver qué aspecto tiene ahora Startup.cs:

¿Notáis algún cambio? Pues es simple, he quitado toda referencia a la SPA, como decía en el anterior artículo, al generar toda la SPA en wwwroot nos podemos olvidar de que existe. Tiene ventajas e inconvenientes y ya os enseñaré como ha impactado en mis desarrollos... Nada crítico ni feo pero podría mejorar.


4.- JSON WEB TOKENS

La implementación de autenticación básica con JWT sobre una API web ASP.NET Core es bastante sencilla. La mayor parte de lo que necesitamos se encuentra en el middleware provisto por el paquete Microsoft.AspNetCore.Authentication.JwtBearer.

Para comenzar, añadimos una clase JwtIssuerOptions y definimos las propiedades de las claims que contendrán nuestros tokens.

También hay que añadir una sección en appsettings.json para poder configurar JwtOptions desde el método ConfigureServices de nuestro Startup.


Después debemos configurar la validación de esos tokens, la autenticación y una política de autorización, es decir, crearemos nuestro propio middleware dentro de ConfigureServices así:
Esto es bastante común y haré el ejercicio de sacarlo a métodos de extensión, no sólo ésta parte sino los diferentes bloques que hemos ido añadiendo a nuestro ConfigureServices, por legibilidad y por potencial reutilización.

¿Qué nos falta? Bueno, nos falta tener una manera de generar estos tokens para poder intercambiarlos entre backend y frontend, algo que deberá ocurrir durante el login, es decir, el último paso durante la autenticación es devolverle al cliente un token con sus permisos, su autorización, para que éste pueda usar dicho token en sucesivas llamadas y poder así en el backend autorizarlas (o no). PAra esto vamos a crear una clase, TokenGenerator, que tendrá ésta misión. para esto además nos hace falta una JwtFactory y su correspondiente interfaz. (No nos olvidemos de inyectarla, por cierto)

Este es un buen momento para volver a agradecer públicamente a Mark Macneil (FullStack Mark) por su artículo y por código al respecto de éste tema, no sé cuanto hubiera tardado sin su ayuda. Como punto de partida la verdad es que ha sido una ayuda inmejorable.


5.- LOGIN CON CLAIMS

Bueno, parece que ésto se mueve, hemos registrado un usuario con nuestro account controller y ahora tenemos una manera de autorizar a nuestros usuario, es momento de crearnos nuestro AuthController junto con su correspondiente CredentialsViewModel.


¿Lo probamos? Vamos a probarlo con Postman:

Pues ahí tenemos nuestro token, token con el que teóricamente podremos autorizar llamadas a nuestra API, vamos con ello.


6.- PROTEGER EL API 

Como hemos visto antes en nuestro Startup hemos establecido una política de autorización pero para que ésta se aplique hay que indicarlo explícitamente en nuestros controladores mediante el uso del atributo [Autorize(Policy=...)]. Vamos a modificar el tan famoso ValuesController para que sólo puedan acceder a él usuarios autorizados, para lo cuál añadiremos   [Authorize(Policy = "ApiUser")]. ¿Qué pasa si lo llamamos ahora?

Pues que como esperábamos hemos obtenido un error 401, que no es otra cosa que un "Unauthorised". Perfecto. ¿Y si nos autenticamos primero y usamos un token? (Es decir, llamamos a login y metemos el token en el header de la siguiente llamada en Postman)


Genial! Ya podemos ponernos a jugar con el frontend, que ya apetecía cambiar de ámbito un rato. Vamos al lío.

7.- SIGNUP Y LOGIN

Bueno, si y no, quiero decir, hasta este momento nuestra aplicación es muy sencilla, de hecho no hay nada modularizado, está todo en nuestro app.component.ts, pero bueno, es un buen punto de partida pues si recordáis para lo único que habíamos usado Angular CLI fue para crear la aplicación, con routing y con scss  (ng new NetCore21 --routing --style=scss.

Vamos a empezar generando dos componentes, uno para el registro, sigup, otro para el login y otro para el home de nuestra app.

  • ng g c signup
  • ng g c login
  • ng g c home


Podemos modificar app.component.html para incluir nuestro router-outlet, es decir, donde se irán cargando los diferentes componentes de acuerdo a la ruta, y dejar algo parecido a esto:

Tenemos que añadir las rtutas a nuestros componentes, en app.routing.component.ts, que quedará de esta forma:

Ahora podemos lanzar la aplicación y ver que podemos ir navegando a home a login y a signup y el contenido de dichos componentes se carga correctamente. Y como creo que lo mejor es seguir el orden lógico de este proceso, vamos a desarrollar el proceso de reguistro.

  • signup.component.html tendrá el formulario html
  • signup.component.ts recogerá los datos del formulario, creará un objeto Signup y se lo pasará a auth.service 
  • Signup.model.ts contendrá la clase con los datos que pasaremos al servicio de auth, el análogo a ResgistrationViewModel pero del lado del cliente.
  • auth.service.ts será el encargado de, teniendo un objeto con los datos necesarios, llamar al API

Veamos como se comporta:



Bueno, necesita mejorar pero como primer paso nos vale, ahora vamos a por el formulario de login. igual que antes tendremos:
  • login.component.html con el formulario html
  • login.component.ts para gestionar el submit del formulario y llamar a auth.service
  • una clase que contendrá los datos de login, user y password, 
  • auth.service.ts con un método de login para llamar al API

Y al probarlo el resultado es el siguiente:
Como vemos ya podríamos gestionar nuestro token del lado del cliente para autenticar sus llamadas a nuestro API...

8.- PROFILE & ADMIN AREA

Hasta aquí todo ha sido muy básico y en éste paso haremos unas cuantas modificaciones sobre lo que ya teníamos, a saber:
  • DashboardController pasará a convertirse en ProfileController porque lo que queremos de él es que nos dé información de los perfiles de nuestros usuarios, y como antes lo seguimos protegiendo con el atributo [Authorize(Policy = "ApiUser")]
  • Crearemos un componente Profile que, dado un UserProfile, nos muestre sus propiedades
  • Crearemos un módulo Admin con un componente dashboard, de momento vacío 
  • Añadiremos las rutas de profile y de admin en app-routing.module.ts
  • Modificaremos el servicio de auth para que:
    • Al reguistrarnos nos envíe a login
    • Al hacer login guarde los datos de sesióin en LocalStorage y nos envíe a profile
    • Al coger el perfil lo devuelva si ya lo tenía o lo pida a nuestro ProfileController protegido
Así ha quedado nuestro código:

Y esto es lo que obtenemos tras hacer login:
Llegados hasta aquí, guardaremos todos estos cambios y seguiremos...


9.- PROTEGER LAS RUTAS

En este paso:
  • Crearemos nuestro AuthGuard, auth.guard.ts
  • Expondremos isLoggedIn desde nuestro AuthService
  • Utilizaremos AuthGuard para establecer si se pueden activar ciertas rutas en nuestra aplicación, admin y profile
  • Mostraremos los enlaces de Login y Signup o un botón de logout de acuerdo al estado del usuario en nuestro Home...
Y lo haremos con éstos cambios:

10.- LOGIN CON REDES SOCIALES (Facebook)

Ésta último paso supone una vuelta de tuerca a todo lo que hemos hecho hasta ahora y revisar y pasar sobre casi todos los pasos, vamos a desarrollar el lgin con Faceboo:
  • Necesitamos unas settings con nuestras credenciales de Facebook como aplicación, settings que estarán en appsettings.json y que inyectaremos desde Startup
  • Necesitamos también ciertas clases de modelo de Facebook para contener el App Access Token, y los datos de usuario
  • Necesitamos crear nuestra app en Facebook (este paso no lo voy a explicar, hay muchos tutoriales de cómo hacerlo y es realmente fácil)
  • Crearemos un nuevo controlador, FacebookController, para gestionar en él la autenticación con Facebook
  • Crearemos también un componente para el login con Facebook, muy simple, un botón que abre la ventana de Login con Facebook y un manejador de respuesta para gestionar el mensaje producido por el callback
  • Una página estática con el javascript que generará el mensaje que necesitamos gestionar una vez nos llegue el callback de Facebook, página que debemos incluir como asset en nuestro angular.json
  • Modificaremos AuthService para que también incluya el Login Con Facebook
El proceso de autentoicación con Facebook (y es similar con otras redes sociales) consiste en:
  1. El usuario decide que quiere hacer Login con Facebook (hace click en el correspodiente botón)
  2. Se abre una nueva ventana que lleva al usuario a logarse en Facebook
  3. Si el login es correcto facebook llama a una url establecida por nosotros, una página dedicada para el callback, con el access token cmo parámetro en la URL
  4. Esa página recoige el access token y lo publica como mensaje para que el componente lo reciba
  5. Una vez recibido el mensaje se puede enviar ese access token al servidor, a FacebookController (a través de AuthService)
  6. Facebook Controller:
    1. genera las credenciales de nuestra aplicación gracias a ñlas settings, con el ClientId y el Secret
    2. Verifica el Access Token del usuario
    3. Recupera el perfil del usuario
    4. Verifica si ya existía en nuestra DB y si no existía lo crea (nos vale como registro)
    5. Genera un JWT para que la app web siga el flujo normal de autenticación autorización
    6. Devuelve dicho token
  7. La app, igual que antes, se guarda en el local storage dicho token para poder hacer llamadas autenticadas a nuestro API, llamadas como GetProfile, además, si todo ha ido bien cierra la ventana de Facebook
Puede parecer enrevesado, la verdad es que creo que en este punto merece la pena tener un pequeño diagrama de secuencia que explique un poco los pasos, a veces una imagen vale más que mil palabras.

Hay mucho código en este paso, sólo voy a dejar aquí lo más relevante, FacebookController.cs, auth.service.ts y facebook-auth.html:




FINAL WORDS

Y de momento para éste artículo eso es todo, a ésta aplicación le queda muchísimo por hacer, por ejemplo:
  • La estructura del proyecto necesita mejorar, habría que empezar a extraer librerías uqe pueden ser reutilizables por otros proyectos
  • Hacen falta Tests Unitartios, los que me conocéis ya sabéis que soy muy maniático con éste tema y durante el tiempo que me ha llevado escribir este artículo me he centrado en la funcionalidad dejando a un lado la calidad, es momento de centrarse en la calidad.
  • Hablando de calidad hay que trabajarla también en el cliente, por ejemplo, las llamadas al API desde el cliente sólo contemplan los casos buenos y no se están manejando las excepciones o los errores adecuadamente.
  • Me gustaría también pasar todo este código por SonarQube para medir la deuda técnica y los code smells, quizá debería ser el primer paso y, según escribo creo que podría ser otro artículo muy iunteresante.
  • Por otro lado la gestión de roles y permisos está ahí, preparada, pero hasta el momento no lo hemos utilizado para nada.
  • La cantidad de datos que se obtienen del perfil de Facebook podría crecer
  • La apariencia del cliente es demasiado básica, por decirlo de alguna manera
  • El auterefresco no funciona, todos los cambios que se hacen en el cliente necesitan que se ejecute manualmente ng build para ser vistos al refrescar, esto hay que resolverlo.
  • Habría que incluir login con otras redes sociales como Google o Microsoft
  • Además, toda esta prueba de concepto puede acabar convirtiéndose en una plantilla de proyecto de Net Core y de Visual Studio y permitir que cualquiera pueda generar toda estructura para sus proyectos y dedicarle tiempo a la parte de configuración para vincularlo con sus cuentas en Facebook o Google...
Veremos como evoluciona todo esto y qué sale en el siguiente artículo, aunque ya adelanto que me voy a enfocar en calidad, Docker y arquitectura más que en nueva funcionalidad. Espero que os haya gustado. Acabo de mergear todo el trabajo implementado durante este artículo a Master y le voy a cambiar el nombre al proyecto, va a pasar a llamarse NetCore21.... Podéis seguir su evolución aquí: https://github.com/JuanGarciaCarmona/NetCore21 

Por supuesto, si os ha gustado y lo compartís os lo agradezco y si tenéis dudas, sugerencias, comentarios, quejas... Ya sabéis dónde estoy.

Un saludo,


Juan



6 jun. 2018

Como crear una aplicación Angular 6 con ASP NET Core 2.1

En éste artículo os voy a enseñar como se crea una aplicación de ASP NET Core 2.1 con Angular 6. En mi entorno de trabajo tengo instalado npm 6.1.0, NodeJS v8.11.2 y dotnet 2.1.300, la primera versión estable de .Net Core 2.1.

1.- Necesitamos tener instalado Angular CLI, para lo que ejecutaremos

npm install -g @angular/cli

2.- El siguiente paso es generar un projecto de Angular 6 con el comando ng new, podéis encontrar toda la documentación sobre ng new aquí: https://github.com/angular/angular-cli/wiki/new  En este caso you usaré routing y scss así que mi comando será:

ng new NetCore21 --routing --style=scss
En alrededor de un minuto Angular CLI nos genera, dentro de esa carpeta, NetCore21, la estructura de un proyecto Angular 6.


Si en este momento ejecutamos ng serve podemos acceder a la página web que acabamos de crear accediendo a la dirección http://localhost:4200


El siguiente paso es generar un proyecto ASP.NET Core Web API con el comando desde la misma carpeta del proyecto donde estábamos:

dotnet new WebAPI
Con lo que obtenemos ésta estructura:


Y ahora podemos ir a nuiestro Visual Studio y abrir ese proyecto.



Editamos angular.json para que la salida sea wwwroot, para ello cambiamos "outputPath": "dist/NetCore21", por "outputPath": "wwwroot", con esto conseguimos que al compilar con ng build el resultado se copie en wwwroot, la carpeta que la applicación web sirve por defecto.

El otro cambio que tenemos que hacer está en Startup.cs, al configurar los servicios (ConfigureServices) hay que decirle que añada los ficheros estáticos de una SPA y que están en wwwroot, que añada MVC. Al configurar la aplicación, el método Configure, decirle que la aplicación usará ficheros por defecto, ficheros estáticos, indicarle la ruta por defecto de MVC para que se pueda acceder a los Controladores e indicarle que se trata de una SPA cuyo origen es wwwroot. Y eso es todo.


Tras seguir estos pasos si ejecutamos el proyecto veremos que funcionan tanto la web como el API, ambas con http y con https:



Una vez llegados hasta aquí lo que voy a hacer es subir éste pequeño proyecto a GitHub para que cualquiera que lea este artículo lo pueda usar como proyecto base de futuras páginas web con ASP NET Core 2.1 y Angular 6. 


Comparto esta receta porque he probado muchas, muchísimas, y tras muchas pruebas y errores ésta es mi propia receta, fácil, sencilla y funcional. Espero que le sea de utilidad a más desarrolladores. No hace falta que diga que cualquier comentario, aclaración, pregunta, es bienvenido.

Un saludo,

Juan

PD: Parece que éste va a ser el primer artículo de una serie enfocada a ASP NET Core, hay varios temas en el tientero, autenticación y autorización, Covertura de código y TDD en el backend. DAL's (SQL y NoSQL).... Si tienes alguna temática que te gustaría que tratara estoy abierto a nuevos retos.

Retomar la divulgación

Hay veces que parece que se alinean los astros, por ejemplo, la semana pasada a petición de varias personas creé una plantilla que nos permite crear muy fácilmente una aplicación ASP .NET Core 2 con Angular 6, algo de lo más novedoso que se podía hacer ese día. Como quedó bastante fácil decidí crear un repositorio público en GitHub y subirlo ahí. 

Al día siguiente por la mañana me llegó la noticia de que la tan esperada versión 2.1 de .Net Core ya había salido así que como tenía el proyecto muy reciente, creo que ni había cerrado Visual Studio, hice la actualización a 2.1 sin ningún problema y lo subí a GitHub, momento en el cuál decidí que podía escribir un breve artículo en Code Project para darlo a conocer.

Tengo que decir que no estoy contento con el resultado, he seguido trabajando sobre esa plantilla en un proyecto personal, la utilicé como punto de partida, y tiene algunos aspectos que dan más problemas que soluciones, es un buen punto de partida, es indudable, pero necesita mejorar, y a eso le dedicaré la siguiente entrada de éste Blog.

Otro momento de alineación astronómica ha llegado esta semana cuando tras llevar años sin usar GitHub para nada, varios días después de hacer público mi primer repositorio de código abierto, resulta que Microsoft compra GitHub (la noticia en el blog oficial de Microsoft: https://blogs.microsoft.com/blog/2018/06/04/microsoft-github-empowering-developers/ ). 

Guau!, no puedo estar más de acuerdo con el título de ese post: "Microsoft + GitHub = Empowering Developers", Y lo digo porque elegí GitHub como el medio ideal para compartir con el mundo mis experimentos y pequeños logros pues le debo mucho a la comunidad OpenSource y actualmente estamos viviendo el renacimiento de .NET gracias a sus políticas aperturistas.

Durante los últimos años, desde mi última etapa en Alstom, he tenido plena libertad en la selección de tecnologías y entornos. Al comenzar aquel proyecto greenfield de I+D+i, un proyecto sin requisitos iniciales pero enfocado en buscar y desarrollar soluciones para Smart Cities, en concreto en transporte inteligente, lo aposté todo a .NET Core. Con .NET Core pudimos crear una arquitectura basada en micro servicios y aplicar una filosofía DevOps de verdad, con todo lo que eso conlleva, y eso que empezamos con la primera versión de .NET Core. 

El equipo pasó de ser sólo yo, desarrollando pruebas de concepto, experimentos, librerías de utilidades e infrastructura, a ser un equipo multidisciplinar con cuatro desarrolladores .NET, los cuatro full stack pero cada uno de nosotros destacando en otros ámbitos, un arqutiecto Big Data, un científico de datos, dos testers y un Project Manager... Y en pocos meses pudimos poner en producción un producto que sé que tras mi marcha de aquel proyecto sigue creciendo y cada vez atrayendo más y más miradas. Si estás leyendo esto comprenderás que no puedo dar detalles de ese proyecto, no más detalles que los que la propia empresa ha hecho públicos, así que te invito a echarle a leer y ver lo que Alstom ha publicado sobre Mastria, el proyecto del que más orgulloso me siento hasta la fecha.

Y voy a volver a los astros, a las casualidades. Como decía, durante estos tres últimos años no he podido publicar nada de lo que estaba haciendo en mi trabajo pero si he tenido tiempo para investigar y hacer experimentos n mis ratos libres. Estoy mirando la fecha de mi última publicación aquí y fué en Septiembre de 2015, y ha llovido muchísimo desde entonces. ¿Qué se puede destacar de todo este tiempo en lo profesional?
  • Obtuve la certificación  de Xamarin Developer
  • He conseguido muchísima experiencia con .NET Core, desde sus comienzos, y me he convertido en un entusiasta del mismo (me gusta pensar que evangelista).
  • He aprendido sobre arquitecturas Big Data (pero no soy ni seré arquitecto Big Data, ese no es mi mundo)
  • He aprendido programación funcional con Scala (gracias a Martin Odersky)
  • He adquirido muchísima experiencia con Docker
  • He aprendido y usado mucho de NodeJS y npm
  • He aprendido mucho sobre Angular, Angular 2, 4, 5 y actualemtne estoy usando Angular 6
  • He montado y dirigido dos equipos de desarrollo incluyendo formación sobre Angular, .Net Core, DDD, SLID, GRASP, PAtrones de diseño y TDD
  • He adquirido e implementado arquitecturas basadas en micro-servicios, mejoradno mis conocimientos en patrones como CQRS, uso de colas de mensajería tipo Kafka o RabbitMQ, la implementación de APIs REST con ASP NET Core y la aplicación de DDD desde el análisis funcional hasta los mas puros detalles de implementación.
  • Además en los últimos meses he salido de mi zona de confort y he usado otros entornos, herramientas y plataformas que desconocía (Jira, Jenkins, Bitbucket, Pivotal CloudFoundry, Concourse, Confluence...) mientras para proyectos personales seguía haciendo uso de mi tan querido, útil y versátil combinación de VS + VSTS + Azure. (Y si me leen mis actuales compañeros insistiré en que "lo barato sale caro")
El caso es que de todo esto que ahora forma parte de mis conocimientos poco he podido compartir con el mundo.Si, he escrito algunos artículos en Code Project y en Medium y he contestado muchas preguntas en Stack Overflow pero saben a poco en comparación con lo que yo creo que podría haber aportado durante todo este tiempo.

Además me he dado cuenta de que todos escribimos en inglés y que la lucha por ser el primero en escribir o demostrar como se usa tal o cuál tecnología es feroz. Como quería retomar la divulgación tecnológica, enfocada principalmente al desarrollo de software, ayer estuve intentando decidirme por qué plataforma usar. Pensé en crearme un blog desde cero, desarrollando web, backend y modelo de datos, pero tengo varios desarrollos a medias, quizá utilice esta idea para crear artículos. Luego pensé en seguir tirando de Code Project porque Medium no me gusta, es demasiado soso, pero luego pensé que ya tenía un blog que empecé en Agosto de 2012 y que éste era el mejor sitio para continuar.

Una vez tomada la decisión ha sido sencillo retomarlo, le he hecho un lavado de cara al blog y aqui estoy, terminado de escribir éste primer artículo de esta nueva etapa. ¿Qué será lo siguiente?

Bueno, en el siguiente artículo voy a explicar como se crea una plantilla de proyecto de dotnet y quiero entrar al máximo detalle con ASP NET Core 2.1 y Angular 6, pero esa será otra historia.