Paso 5: Autenticación y roles.
URL: | https://github.com/Uniandes-isis2603/frontstepbystep.git |
---|---|
Release: | git checkout -f paso-5 |
Aplicación
En este paso nos enfocamos en simular una autenticación en la aplicación para permitir hacer determinadas acciones dentro de ella. Es de aclarar que la simulación se hace únicamente en el FrontEnd de la aplicación. Una autenticación real conlleva muchos más pasos y detalles que incluyen al BackEnd.
Cuando vamos a dar clic en la opción de login nos aparecerá un estado asociado al login como el siguiente:
Iniciamos sesión con un usuario de prueba que es administrador y podrá hacer todas las acciones posibles.
En este caso, una vez ha iniciado sesión se puede observar en la parte superior derecha de la aplicación que aparece el nombre del usuario que inició sesión y la opción de logout.
En la siguiente imagen podemos ver a otro usuario que no es administrador tratando de crear un autor, pero, la aplicación le indica que no tiene permisos.
Antes de iniciar es importante hacer un cambio en la versión de nuestro angular-ui-router |
---|
Vaya al archivo bower.json y reemplace la dependencia de angular-ui-router por la siguiente "angular-ui-router": "~1.0.11"
. Este cambio se hace por compatibilidad de unos métodos que vamos a usar más adelante.
Requerimientos Nuevos
- Iniciar sesión y manejo de roles
Iniciar sesión
- Crear el template para
login
ylogout
- Crear en el módulo
loginModule
el estado asociado alogin
ylogout
. - Crear los controladores asociado a los estados.
- Actualizar el
index.html
para incluir los nuevos controladores y css. - Actualizar
app.js
- Actualizar template
author.delete.html
,authors.new.html
- Actualizar
authors.mod.js
1. Crear el template para login
y logout
El siguiente fragmento de código representa el template para el login que llamaremos como login.html en nuestra aplicación.
Es importante notar que allí se hace uso también del ng-if que usamos en el paso anterior. También vemos que el formulario en el button de Sign In tenemos ng-click una directiva de angular para indicarle que vaya a un método en especifico en el controlador.
También otro cambio que notamos en la directiva ng-model es que tiene asociado el nombre de una variable en el scope llamada data que esta definida en el controlador.
El siguiente fragmento de código representa el template para el logout en nuestra aplicación.
En este template vamos a indicarle al usuario que ha cerrado su sesión en nuestra aplicación.
2. Crear en el módulo loginModule
el estado asociado a login
y logout
.
El módulo para el login y el logout sigue la misma convención de todos los módulos declarados hasta ahora en los anteriores pasos.
Ahora, si ha detallado el código del módulo notamos que aparece algo nuevo para nosotros y es la variable data dentro de la definición del estado.
La variable data tiene dos propiedades que usaremos mas adelante. Por consiguiente, tengamos en cuenta que dentro de data están requiereLogin y roles.
3. Crear los controladores asociado a los estados.
Vamos a crear el controlador llamado login.ctrl que tendrá la siguiente lógica con un método llamado $scope.autenticar:
Lo primero que encontramos en el controlador es la definición de dos variables en el $scope
La variable $scope.user la vamos a usar para asignar los datos del usuario y la variable $scope.data es nuestra variable que vamos a usar para recoger cada uno de los valores ingresados en el formulario de login.
Luego, encontramos un $http con el método GET que nos lee una colección de usuarios que tenemos definidos en un JSON en la ruta data/users.json. Esto sigue la misma lógica que usamos en los primeros pasos cuando leíamos las colecciones de datos para mostrar la información de books, authors y editorials.
El método $scope.autenticar nos ayudará a validar la información que tenemos desde el formulario contra nuestra colección de usuarios.
Lo lógica que sigue el método es:
Validar que lo ingresado en el formulario coincida en usuario ($scope.data.username), contraseña ($scope.data.password) y rol ($scope.data.rol) con los usuarios que tenemos en el arreglo llamado $scope.users
Cuando se ha cumplido la condición asignamos a $scope.user los valores asociados a ese usuario, y pedimos enviamos al usuario a un estado ya existente.
Hacemos uso del sessionStorage para almacenar allí los valores del usuario.
Vamos a crear el controlador llamado logout.ctrl que tendrá la siguiente lógica:
Cuando analizamos el código notamos que validamos si en sessionStorage existe la propiedad username, es decir, nos indica si el usuario esta o no autenticado en nuestra aplicación. Si la condición se cumple hacemos sessionStorage.clear();
para cerrar sesión.
4. Actualizar el index.html
para incluir los nuevos controladores y css.
5. Actualizar app.js
En el app.js
tenemos los siguientes cambios que nos ayudarán a manejar la simulación de nuestro inicio de sesión en la aplicación.
- Hacer uso del bloque de run que nos permite ejecutar fragmentos de código al iniciar la aplicación. Para mas detalles de run blocks puede ampliar la información en la documentación de AngularJS.
En este fragmento de código inyectamos $rootScope y $transitions.
- Hacemos uso del método onSuccess de $transtions que nos permite verificar que una vez se haya completado un estado satisfactoriamente podamos conocer todos los detalles del estado.
Ahora, si usted detalla el anterior fragmento de código tenemos una variable llamada $state que nos almacena todo lo que tiene determinado estado. En ese orden de ideas, tenemos declaradas las variables requiereLogin y roles que van a almacenar lo que contiene el estado en la variable data que habíamos definido arriba en el modulo de login
- Definir dos métodos en el $rootScope que nos ayudarán a la simulación de la autenticación.
Explicación de los anteriores métodos, $rootScope.isAuthenticated permite verificar si en sessionStorage hay datos del usuario como el username devolviendo un true o false dependiendo del caso. $rootScope.hasPermissions permite verificar si el rol que tiene el usuario esta asociado a los roles que permite el estado.
Es decir que,
La variable roles es un arreglo con los roles permitidos para ese estado, y al obtener el rol del usuario verificamos que exista en ese arreglo.
- El último fragmento de código que encontramos es el siguiente:
Allí validamos si el estado necesita o no de autenticación por medio de la variable requiereLogin y usamos el event.preventDefault();
detiene la acción predeterminada de un elemento, es decir, el método preventDefault()
cancela el evento si es cancelable, lo que significa que la acción predeterminada que pertenece al evento no ocurrirá. Para más detalles puede consultar aquí. Dicho en otras palabras estamos impidiendo que se vaya a un estado que requiere login sin la autenticación realizada por el usuario.
Todo el código completo es como el siguiente:
6. Actualizar template author.delete.html
, authors.new.html
En los templates debemos hacer uso de los métodos que acabamos de crear para permitir o no determinadas acciones.
El siguiente fragmento de código muestra el mensaje de You do not have permission for this action. Si el usuario esta autenticado pero no tiene permisos. Este mismo fragmento de código se usa en ambos templates.
Dentro de nuestra etiqueta div
vamos a usar nuevamente la directiva de ng-if. Para validar que esta autenticado y tiene los permisos para la acción.
7. Actualizar authors.mod.js
La actualización en el módulo de authors
se ve reflejada añadiendo al código la variable de data.
Por ejemplo:
Si usted detalla el código vemos que para los estado create y delete esta el rol admin mientras que para el update incluimos el rol de assistant esto quiere decir que, el rol de assistant solo podrá editar en nuestra aplicación.