A progressive Node.js framework for building efficient and scalable server-side applications.
Servicios web para los proyectos de la asignatura de entorno cliente.
Importar la base de datos (directorio SQL). Configurar el archivo src/mikro-orm.config.ts con el servidor (host), usuario, password, y nombre de la base de datos. Ejemplo:
export default {
entities: [User, Post, LikePost, Comment],
type: 'mariadb', // one of `mongo` | `mysql` | `mariadb` | `postgresql` | `sqlite`
dbName: process.env.DB_DATABASE || 'assbook',
user: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '',
host: process.env.DB_SERVER_HOST || 'localhost',
port: parseInt(process.env.DB_SERVER_PORT, 10) || 3306,
debug: true,
} as ConnectionOptions;
A continuación, instalamos los paquetes necesarios con NPM:
$ npm install
Edita el archivo src/google-id.ts para poner ahí tu id de Google o no funcionará el login con dicho proveedor.
Descarga el archivo de cuenta de servicio (Configuración de proyecto -> cuentas de servicio) dentro de la carpeta firebase y renombralo a serviceAccountKey.json. Tiene que ser el mismo proyecto que uses en la aplicación cliente donde habrás descargado el archivo google-services.json. Los servicios están configurados para mandar una notificación push cuando alguien comente en un post, al creador del mismo.
Ejecutamos los servicios web con el siguiente script:
# development
$ npm run start
En el directorio Postman (raíz del proyecto) hay una colección de Postman para importar y probar.
Normalmente, todos los servicios devuelven un resultado en formato JSON. Cuando no se pueda realizar una operación, devolverán un código de error HTTP junto a un objeto JSON con la descripción del mismo.
Todas las colecciones, excepto /auth (/auth/validate sí lo requiere), requieren un token de autenticación para poder utilizar los servicios web, devolviendo un código 401 (Not Authorized) en caso de no incluirlo. Este debe enviarse en la cabecera Authorization con el prefijo Bearer:
Authorization: Bearer auth_token
- POST /auth/login
El servicio comprueba si un usuario y contraseña son correctos, devolviendo un token de autenticación (JWT) si todo va bien. Opcionalmente se puede enviar la posición del usuario para que la actualice.
Ejemplo de petición:
{
"email": "[email protected]",
"password": "1234"
}
Si el login es correcto, la respuesta será algo como esto:
{
"expiresIn": 31536000,
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiaWF0IjoxNTc4MTYyNDA2LCJleHAiOjE2MDk2OTg0MDZ9.HQZ-PO-usLc9WT-0cUpuDPnVRFl_u71njNoQNj_TIx8"
}
En caso de error en el login (usuario y contraseña no válidos), se devolverá el código de error 401:
{
"status": 401,
"error": "Email or password incorrect"
}
- POST /auth/google
Este servicio recibe el campo id_token que devuelve la identificación mediante Google en el cliente. Lo valida y comprueba el correo en la base de datos. Si el correo existe funciona como un login normal, y si no existe registra al usuario (a partir de los datos obtenidos de Google) en la base de datos. Devuelve un token de autenticación válido para el servidor (como el login).
Ejemplo de envío (lat y lng son opcionales):
{
"token": "id_token de Google",
}
Ejemplo de respuesta:
{
"accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0ODU5MDA1MzgsImlkIjoiMSIsIm5hbWUiOiJQcnVlYmEiLCJlbWFpbCI6InBydWViYUBjb3JyZW8uZXMifQ.vf7hwA3gceCDvOCa9RoWxR9cJ5mARnbAs6Nv9VBlPdc"
}
https://developers.google.com/identity/sign-in/web/backend-auth
- POST /auth/facebook
Este servicio recibe el campo accessToken que devuelve la identificación mediante Facebook en el cliente. Lo valida y comprueba el correo en la base de datos. Si el correo existe funciona como un login normal, y si no existe registra al usuario (a partir de los datos obtenidos de Facebook) en la base de datos. Devuelve un token de autenticación válido para el servidor (como el login).
Ejemplo de envío (lat y lng son opcionales):
{
"token": "accessToken de Facebook",
}
Ejemplo de respuesta:
{
"accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0ODU5MDA1MzgsImlkIjoiMSIsIm5hbWUiOiJQcnVlYmEiLCJlbWFpbCI6InBydWViYUBjb3JyZW8uZXMifQ.vf7hwA3gceCDvOCa9RoWxR9cJ5mARnbAs6Nv9VBlPdc"
}
https://lorenstewart.me/2017/03/12/using-node-js-to-interact-with-facebooks-graph-api/
* **POST /auth/register**
Este servicio recibe los datos de un usuario y lo registra en la base de datos.
Ejemplo de **petición** (_lat_ y _lng_ son opcionales):
```json
{
"name": "Prueba",
"email": "[email protected]",
"password": "1234",
"avatar": "Imagen codificada en base64"
}
- GET /auth/validate
Este servicio simplemente comprueba que el token de autenticación que se envía en la cabecera Authorization es correcto (y se ha enviado), devolviendo una respuesta como esta si está todo correcto:
{
"ok": true
}
O un código 401 (Not Authorized) si no es válido.
Todos los servicios de esta colección requieren del token de autenticación.
- GET /posts
Devuelve todos los posts. Además de los datos del post almacenado, el total de likes (totalLikes), el voto si el usuario actual le ha dado a like o dislike (vote), y si el post pertenece al usuario (mine).
{
"posts": [
{
"id": 23,
"title": "Complete post",
"description": "This is the description\nwith more than one line",
"date": "2019-11-19T18:47:03.607Z",
"image": "http://localhost:3000/img\\posts\\1574189223289.jpg",
"mood": 2,
"place": null,
"lat": null,
"lng": null,
"totalLikes": 2,
"creator": {
"id": 3,
"name": "Test User 3",
"email": "[email protected]",
"avatar": "http://localhost:3000/img\\users\\1574290767381.jpg",
"oneSignalId": null,
"followersCount": 0,
"followingCount": 0
},
"vote": {
"likes": true
},
"mine": false
},
...
]
}
- GET /posts/mine
Igual que el servicio /posts pero sólo devuelve los restaurantes cuyo creador es el usuario actual.
- GET /posts/user/:id
Igual que el servicio /posts pero sólo devuelve los restaurantes del usuario cuya id recibe por parametro.
- GET /posts/:id
Devuelve la información del post cuya id recibe por parámetro en la url. En caso de no existir, devolverá un código de error 404.
También devolverá información sobre el usuario creador del mismo.
Ejemplo de llamada a /posts/23.
{
"post": {
"id": 23,
"title": "Complete post",
"description": "This is the description\nwith more than one line",
"date": "2019-11-19T18:47:03.607Z",
"image": "http://localhost:3000/img\\posts\\1574189223289.jpg",
"mood": 2,
"place": null,
"lat": null,
"lng": null,
"totalLikes": 2,
"creator": {
"id": 3,
"name": "Test User 3",
"email": "[email protected]",
"avatar": "http://localhost:3000/img\\users\\1574290767381.jpg",
"oneSignalId": null,
"followersCount": 0,
"followingCount": 0
},
"vote": {
"likes": true
},
"mine": false
}
}
- POST /posts
Crea un nuevo post en la base de datos (debe recibir al menos algún campo). Ejemplo de post con imagen y con localización:
{
"title": "Complete post",
"description": "This is the description\nwith more than one line",
"image": "Imagen en Base64",
"mood": 2
}
{
"title": "Birthday party",
"description": "At my house",
"place": "Vertedero Municipal",
"lat": 43.2386,
"lng": -2.9687,
"mood": 2
}
El servicio devolverá, si todo ha ido bien y se ha insertado el post, el objeto recién insertado en la base de datos, con su id y la url de la imagen guardada en el servidor:
{
"post": {
"title": "Complete post",
"description": "This is the description\nwith more than one line",
"image": "http://localhost:3000/img/posts/1578165006148.jpg",
"mood": 2,
"creator": {
"id": 2,
"name": "Test User 2",
"email": "[email protected]",
"avatar": "http://localhost:3000/img/users/1571756211995.jpg",
"oneSignalId": null,
"followersCount": 2,
"followingCount": 0
},
"place": null,
"lat": null,
"lng": null,
"id": 47,
"date": "2020-01-04T19:10:06.306Z",
"totalLikes": 0
}
}
Normalmente, cuando los datos enviados sean insuficientes o no estén en el formato correcto, el servidor devolverá un error 400 (Bad request).
- PUT /posts/:id
Similar al servicio anterior (añadir restaurante), pero además se envía en la url la id del restaurante que se va a modificar. Se debe enviar toda la información otra vez, dejando los campos que no han cambiado con su valor original. Se debe prestar atención a si queremos enviar una imagen, no enviar los campos lat y lng aunque estuvieran en el post original.
Devuelve, si todo sale bien, el restaurante con la información modificada.
- DELETE /posts/:id
Este servicio borra un post de la base de datos y devuelve la id del post eliminado, o un error 404 si el post a borrar no existe.
Ejemplo de respuesta a la llamada /posts/34
{
"id": 34
}
- POST /posts/:id/likes
Permite votar un post con un like (true) o dislike (false). Este es el json a enviar:
{
"likes": true
}
El servicio responderá con el total de likes para actualizarlo en el post correspondiente:
{
"totalLikes": 1
}
- DELETE /posts/:id/likes
Borra el voto que se le hubiera dado a un post. Al igual que el servicio anterior, devolverá el total de likes resultante.
- GET /posts/:id/comments
Devuelve un objeto que contiene un array con todos los comentarios que han realizado los usuarios sobre un post.
{
"comments": [
{
"id": 9,
"text": "This is a comment",
"date": "2019-11-20T19:46:01.199Z",
"user": {
"id": 3,
"name": "Test User 3",
"email": "[email protected]",
"avatar": "http://localhost:3000/img\\users\\1574290767381.jpg",
"oneSignalId": null,
"followersCount": 0,
"followingCount": 0
}
},
...
]
}
- POST /posts/:id/comments
Inserta un nuevo comentario en un post. Devolverá un 404 si el restaurante no existe, o un 400 si falta información o el formato no es correcto.
Ejemplo de comentario:
{
"text": "This is a comment"
}
La respuesta será la información del comentario insertado en la base de datos:
{
"comment": {
"id": 24,
"text": "This is a comment",
"date": "2020-01-05T19:14:43.797Z",
"user": {
"id": 2,
"name": "Test User 2",
"email": "[email protected]",
"avatar": "http://localhost:3000/img/users/1571756211995.jpg",
"oneSignalId": null,
"followersCount": 2,
"followingCount": 0
}
}
}
Todos los servicios de esta colección requieren del token de autenticación.
- GET /users/me
Devuelve la información del perfil del usuario autenticado. El booleano me indica si la información es del usuario autenticado o de otro.
{
"user": {
"id": 27,
"name": "Tom",
"email": "[email protected]",
"avatar": "img\\users\\1541009537495.jpg",
"lat": "37.8235530",
"lng": "-1.2654570",
"me": true
}
}
- GET /users/:id
Igual que /users/me pero devuelve la información del usuario cuya id recibe en la url. Devuelve un error 404 si el usuario no existe.
Ejemplo de llamada a /users/22:
{
"user": {
"id": 22,
"name": "John Wayne",
"email": "[email protected]",
"avatar": "img/users/1539948671405.jpg",
"lat": "41.3254320",
"lng": "-1.2345500",
"me": false
}
}
- PUT /users/me
Modifica la información del nombre y correo del usuario autenticado.
Ejemplo de petición:
{
"name": "John",
"email": "[email protected]"
}
Responde simplemente con una confirmación si todo ha ido bien (O error 400 si los datos de entrada son insuficientes o erróneos):
{
"ok": true
}
- PUT /users/me/avatar
Modifica el avatar del usuario autenticado. Ejemplo de petición:
{
"avatar": "Imagen en base 64"
}
Responde con la url de la nueva imagen almacenada en el servidor:
{
"avatar": "img/users/1545565439800.jpg"
}
- PUT /users/me/password
Actualiza la contraseña del usuario autenticado:
{
"password": "1234"
}
Responde simplemente con una confirmación si todo ha ido bien:
{
"ok": true
}