Skip to content

An Hike Tracker application written in React JS and NodeJS for the backend part

Notifications You must be signed in to change notification settings

giuseppelazzara98/polito-se2-22-18-HT

Repository files navigation

polito-se2-22-18_HT - HIKE TRACKER PROJECT

Sofware engineering 2 a.a. 2022 / 2023

Developers: Gerardo Braia, Elisa Calì, Francesco Carpegna, Ahmed Khater, Giuseppe Lazzara, Francesco Rosati.

SonarCloud

Vulnerabilities Security Rating Lines of Code

TECHNOLOGIES USED:

  • Front-end: React, SASS;
  • Back-end: nodejs, SQLite, Knex, NodeMailer, JWT;
  • Maps: OpenStreetMap;

HOW TO RUN THE HIKE TRACKER APPLICATION:

  • Into the server folder:
    • npm install
    • node server.js / nodemon server.js
  • Into the client folder:
    • npm install
    • npm start

HOW TO RUN THE TESTS:

  • Into the server folder:

    • npm test -> Unit tests
    • npm run apiTest -> Integration tests
  • Current test coverage file: server/unitTestResult.txt

  • Current front-end test reports: client/tests.md

REACT CLIENT APPLICATION ROUTES:

  • Route /: the route contains the Home component. Here the user can see if not logged in, the complete list of hikes with the related filters and can create if logged in as a local guide, new hikes.
  • Route /login: the route contains the login form, where the user can authenticate himself inserting username and password.
  • Route /signup: the route contains the register form, where the user can register himself inserting name, surname, email, password and the role for which he / she wants to register for.
  • Route /newHike: the route contains the form to create a new hike, where the local guide can insert all the useful informations related to the hike, including the GPX file.
  • Route /newHut: the route contains the form to create a new hut, where the local guide can insert all the useful informations related to the hut, including the provinces selection from the map.
  • Route /newParkingLot: the route contains the form to create a new parking lot, where the local guide can insert all the useful informations related to the Parking Lot, including the provinces selection from the map.
  • Route /HikesOwned: the route contains the list of all the hikes for which an hiker is registered for.
  • Route /verify/:token: the route contains the page related to the confirmation of the email. The link of this page is sended on the email of the new user.
  • Route *: the route displays an error message if a known route is not found or the current route is wrong.

API SERVER:

Login:

URL: /api/sessions
Method: POST
Description: Performs the login of the user.
Request body:

{
    "username":"guide1@gmail.com",
    "password":"password"
}

Response: 200 Ok
Response body:

{
    "id": 1,
    "username": "guide1@gmail.com",
    "name": "Paolo",
    "surname": "Bitta",
    "role": "Local guide"
}

Error responses: 401 Unauthorized

Get current user informations:

URL: /api/sessions/current
Method: GET
Description: Retrieves the informations of the current user.
Request body: None
Response: 200 OK
Response body:

{
    "id": 1,
    "username": "guide1@gmail.com",
    "name": "Paolo",
    "surname": "Bitta",
    "role": "Local guide"
}

Error responses: 401 Unauthorized

Logout:

URL: /api/sessions/current
Method: DELETE
Description: Performs the logout of the current user
Request body: None
Response: 200 Ok
Response body: None

Get all roles:

URL: /api/roles
Method: GET
Description: Retrieves the list of all the roles.
Request body: None
Response: 200 OK
Response body:

[
    {
        "id": 1,
        "role": "Local guide"
    },
    {
        "id": 2,
        "role": "Hiker"
    }, ...
]

Error responses: 500 Internal Server Error

User registration:

URL: /api/newUser
Method: POST
Description: Creates an account for a new user with a specific role sending also an email to verify the account.
Request body:

{
    "email": "hiker2@gmail.com", 
    "name": "Francesco",
    "surname": "Verdi",
    "password": "password",
    "id_role": 1
}

Response: 201 Created
Response body: None
Error responses: 409 Conflict, 422 Unprocessable Entity, 503 Service Unavailable

User email verification:

URL: /api/verify/:token
Method: PUT
Description: Verifies the token sent by email to the user and activates the account.
Request body: None
Response: 200 Ok
Response body: None
Error responses: 401 Unauthorized, 422 Unprocessable Entity, 503 Service Unavailable

Get place by place id:

URL: /api/places/place/:placeId
Method: GET
Description: Retrieves the informations of a place giving its id.
Request body: None
Response: 200 OK
Response body:

{
    "id_place": 2,
    "name": "Parking lot 2",
    "description": "parking lot 2",
    "latitude": 25.037,
    "longitude": 34.522,
    "type": "parking lot"
}

Error responses: 404 Not Found, 422 Unprocessable Entity, 500 Internal Server Error

Get place by province id:

URL: /api/places/:provinceId
Method: GET
Description: Retrieves the list of all the places associated to a specific province id.
Request body: None
Response: 200 OK
Response body:

[ 
    {
        "id_place": 9,
        "name": "Almici",
        "description": "...",
        "latitude": 37.2114,
        "longitude": 75.25,
        "type": "hut"
    },
    {
        "id_place": 16,
        "name": "Morgantini ",
        "description": "...",
        "latitude": 15.347,
        "longitude": 38.142,
        "type": "hut"
    }, ...
]

Error responses: 500 Internal Server Error

Get all provinces:

URL: /api/provinces
Method: GET
Description: Retrieves the list of all the provinces.
Request body: None
Response: 200 OK
Response body:

[ 
    {
        "id_province": 1,
        "name": "TORINO",
        "abbreviation": "TO"
    },
    {
        "id_province": 2,
        "name": "VERCELLI",
        "abbreviation": "VC"
    }, ...
]

Error responses: 500 Internal Server Error

Get the list of all hikes (optionally filtered):

URL: /api/hikes
Method: POST
Description: Retrieves the list of all the filtered hikes.
Request body:

{
	"province": 1,
	"difficulty": [1,2],
	"exp_time": { "min": 5.6, "max": 9.0 },
	"length": { "min": 0.0, "max": 15.7 },
	"ascent": { "min": 500, "max": 2900 },
    "range": {"center": {"lat": 10.21, "long": 11.63}, "radius": 3850000}
}

Response: 200 Ok
Response body:

{
    "hikes": [
        {
            "name": "Afframont Lake",
            "key": 10,
            "description": "...",
            "start_place": "Alpe Bondolo",
            "end_place": "La Calla",
            "province": "TORINO",
            "municipality": "BALME",
            "length": 4,
            "expected_time": 5,
            "ascent": 810,
            "difficulty": 2,
            "position": {
                "lat": 45.3015,
                "long": 7.2238
            }
        }, ...
    ],
    "distinct_ascents": [
        1500,
        2000,
        2500,
        1000,
        500,
        1800,
        2200,
        1450,
        123,
        78
    ], ...
}

Error responses: 422 Unprocessable Entity, 500 Internal Server Error

Create a new hike (only if the user is a local guide and is logged in):

URL: /api/newHike
Method: POST
Description: Create a new hike.
Request body:

{
  "title": "Test1",
  "province": 4,
  "municipality": 7078,
  "length": 4,
  "expectedTimeString": "56m",
  "expectedTime": 0.93,
  "ascent": 1406,
  "difficulty": 1,
  "startPoint": {
    "type": "Hut/Parking lot",
    "id": 8,
    "name": "Alevè",
    "lon": 21.244,
    "lat": 3.325
  },
  "endPoint": {
    "type": "Hut/Parking lot",
    "id": 12,
    "name": "Monte d'Oro",
    "lon": 8.474,
    "lat": 21.2475
  },
  "referencePoints": [
    {
      "id": 15,
      "name": "Monte Talm",
      "description": "...",
      "lat": 18.364,
      "lon": 13.412,
      "type": "hut"
    },
    {
      "type": "Address/Name of location",
      "id": 298324244,
      "name": "Politecnico di Torino, Corso Francesco Ferrucci, Cenisia, Circoscrizione 3, Torino, Piemonte, 10138, Italia",
      "lat": 45.063697399999995,
      "lon": 7.657527285508495
    }
  ],
  "gpxData": '[...]',
  "description": "Test1"
}

Response: 201 Created
Response body: None
Error responses: 401 Unauthorized, 404 Not Found, 422 Unprocessable Entity, 503 Service Unavailable

Get hike points by hike id:

URL: api/hikePoints/:id
Method: GET
Description: Retrieves the detailed list of all points related to a specific hike.
Request body: None
Response: 200 OK
Response body:

{
    "hikePoints": [
        {
            "id_place": 1,
            "name": "Parking lot 1",
            "description": "...",
            "latitude": 20.811,
            "longitude": 14.32,
            "startPoint": true,
            "endPoint": false,
            "type": "parking lot"
        },
        {
            "id_place": 2,
            "name": "Parking lot 2",
            "description": "...",
            "latitude": 25.037,
            "longitude": 34.522,
            "startPoint": false,
            "endPoint": true,
            "type": "parking lot"
        },
        {
            "id_place": 7,
            "name": "Alpe Bondolo",
            "description": "...",
            "latitude": 33.25,
            "longitude": 12.724,
            "startPoint": false,
            "endPoint": false,
            "type": "hut"
        }
    ],
    "gpx": [...]
}

Error responses: 401 Unauthorized, 404 Not Found, 422 Unprocessable Entity, 500 Internal Server Error

Create a new parking lot (only if the user is a local guide and is logged in):

URL: /api/newParkingLot
Method: POST
Description: Create a new parking lot.
Request body:

{
	"province": 1,
	"name": "Parking lot 134",
	"description": "Parking lot 134 description",
	"latitude": 45.123456,
	"longitude": 7.123456,
	"type": "parking lot",
	"capacity": 100
}

Response: 201 Created
Response body: None
Error responses: 401 Unauthorized, 422 Unprocessable Entity, 503 Service Unavailable

Create a new hut (only if the user is a local guide and is logged in):

URL: /api/newHut
Method: POST
Description: Create a new hut.
Request body:

{
	"province": 1,
	"name": "Hut 1",
	"description": "Hut 1 description",
	"latitude": 45.123456,
	"longitude": 7.123456,
	"type": "hut",
	"altitude": 1000,
	"nBeds": 10,
	"phone": "+39 3331234567",
	"email": "guide1@gmail.com",
	"website": "www.hut1.com"
}

Response: 201 Created
Response body: None
Error responses: 401 Unauthorized, 422 Unprocessable Entity, 503 Service Unavailable

Register an hiker for a specific hike (only if the user is an hiker and is logged in):

URL: /api/hikeRegistration
Method: POST
Description: Register a specific hiker to a specific hike.
Request body:

{
	"id_hike": 3
}

Response: 201 Created
Response body: None
Error responses: 401 Unauthorized, 422 Unprocessable Entity, 503 Service Unavailable

Hiker starts a specific hike (only if the user is an hiker and is logged in):

URL: /api/startHike
Method: PUT
Description: Update the the hike for which the user is registered with the start time
Request body:

{
	"id_hike": 1,
	"start_time": "2022/12/20 08:52"
}

Response: 200 Ok
Response body: None
Error responses: 401 Unauthorized, 422 Unprocessable Entity, 503 Service Unavailable

Hiker ends a specific hike (only if the user is an hiker and is logged in):

URL: /api/endHike
Method: PUT
Description: Update the the started hike for which the user is registered with the end time
Request body:

{
	"id_hike": 1,
	"end_time": "2022/12/20 10:43"
}

Response: 200 Ok
Response body: None
Error responses: 401 Unauthorized, 422 Unprocessable Entity, 503 Service Unavailable

Get statistics and information about user's hikes (only if the user is an hiker and is logged in):

URL: /api/hikesStats
Method: GET
Description: Retrieves the informations of the current user.
Request body: None
Response: 200 OK
Response body:

[
    {
        "id_hike": 10,
		"hike_name": "Afframont Lake",
		"start_time": "2022/12/20 08:52",
		"end_time": "2022/12/20 12:52",
		"state": 2,
		"registered": 1
    },
    {
        "id_hike": 11,
	    "hike_name": "Rifugio Barfè",
		"start_time": "2022/12/20 09:45",
		"end_time": "",
		"state": 1,
		"registered": 1
    }, ...
]

Error responses: 401 Unauthorized, 500 Internal Server Error

DATABASE TABLES:

  • Table HIKE: contains the hikes informations, including name, description, province, difficulty, expected time, length, ascent, GPX file, local guide, start place and end place.
  • Table HIKE_PLACE: contains informations related to the association between an hike and one or more places. (A place associated to an hike can be the start point, the end point or a reference point for that hike).
  • Table HUT_DATA: contains the huts informations, including phone, email and an optional website.
  • Table PARKING DATA: contains the parking lots informations, including the capacity in terms of cars that can park there.
  • Table PLACE: contains the places informations, including name, description, province, latitude, longitude and type.
  • Table PREFERENCE: contains the informations related to the association between an user and his / her preferences.
  • Table PROVINCE: contains the provinces informations, including name and abbreviation.
  • Table ROLE: contains the roles informations, including the description.
  • Table USER: contains the users informations, including name, surname, role, email and password.
  • Table USER_HIKE: contains the informations related to the association between an hiker and the hikes he / she is registered to.

USER CREDENTIALS:

Name Surname Username Password Role
Paolo Bitta guide1@gmail.com password Local guide
Goofy The Goof guide2@gmail.com password Local guide
Luca Nervi hiker1@gmail.com password Hiker
Mickey Mouse hiker2@gmail.com password Hiker

About

An Hike Tracker application written in React JS and NodeJS for the backend part

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages