Introduzione
In questa guida descriveremo l’architettura di 4HSE e i servizi web che offre agli sviluppatori. Successivamente, costruiremo un esempio di codice che include l’uso dell’API e copre uno scenario di sviluppo comune.
- Introduzione
- API Standard
- Autenticazione
- oauth2
- access-token
- Autorizzazione (ACL)
- Chiamate
- Esempio di codice
API Standard
La piattaforma 4HSE fornisce un ampio set di servizi web che consentono di gestire i dati dei propri progetti. Tutti i servizi seguono lo Standard HTTP REST API e offrono operazioni CRUD sulle risorse.
Una risorsa è un elenco di attributi (ad esempio, una persona è descritta da nome, cognome, ecc.). Ogni risorsa ha un identificatore univoco, l’attributo
id
, che ne garantisce l’unicità. Le risorse sono raggruppate in collezioni in base al loro tipo (tutte le risorse di tipo “persona” sono raggruppate nella collezione “person”).
Per ogni collezione, generalmente, sono disponibili cinque endpoint di base:
- GET <collection>/index
- GET <collection>/view/<my_resource_id>
- POST <collection>/create {payload}
- PUT <collection>/update/<my_resource_id> {payload}
- DELETE <collection>/delete/<my_resource_id>
Può capitare che una collezione non segua esattamente questo standard. Tuttavia, tutte le API disponibili sono ben documentate qui secondo lo standard Open API.
Autenticazione
Per accedere alle API di 4HSE è necessario autenticarsi. Esistono due modalità di autenticazione:
- oauth2
- auth_code
Supponiamo di voler recuperare l’elenco delle sedi ordinate per nome. In tal caso, bisognerebbe chiamare l’API:
service.4hse.com/office/index?sort=-name&limit=50&offset=51
Se si effettua questa chiamata senza autenticazione, si riceverà il codice di risposta Unauthorized (401)
. È necessario utilizzare uno dei due metodi di autenticazione sopra indicati affinché la chiamata funzioni correttamente.
Questo è solo un esempio. Una spiegazione più dettagliata delle API e delle modalità di chiamata è fornita nei capitoli successivi.
oauth2
Utilizziamo lo standard oauth2 per autenticare gli utenti.
L’URI dell’API è: service.4hse.com/oauth2/token
Per ottenere un token, è necessario conoscere i seguenti dati:
client_id
– un identificatore univoco che rappresenta il clientclient_secret
– la password associata al client_idusername
– il tuo nome utentepassword
– la tua password
oppure, se hai già ottenuto un token:
client_id
– un identificatore univoco che rappresenta il clientclient_secret
– la password associata al client_idrefresh_token
– il token di aggiornamento che hai ricevuto in una chiamata precedente alla stessa API
Ogni cliente che desidera utilizzare l’API deve avere il proprio
client_id
eclient_secret
. Dovresti chiedere al supporto 4hse per ottenere questi due dati.
Quando accedi al servizio per la prima volta, devi utilizzare il tuo nome utente e la tua password (ovviamente anche client_id
e client_secret
):
REQUEST
---
URI: service.4hse.com/oauth2/token
Host: service.4hse.com
Method: POST
Request Payload:
{
"client_id": "example_client_id",
"client_secret": "example_client_secret",
"grant_type": "password",
"username": "example_user",
"password": "example_password"
}
Successivamente, riceverai una risposta simile alla seguente:
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
"access_token": "433b8caa8ea9839b5a732a9455ee50bef31fe4e0",
"expires_in": 86400,
"token_type": "Bearer",
"scope": null,
"refresh_token": "84c893bdd88fb52400c5d8fc246e81bd544a3486",
"user_id": "example_user"
}
L’ access_token
è il token bearer che puoi utilizzare per accedere a tutte le API. Come indicato, scade dopo 86400 secondi (24 ore). Come puoi vedere, nella risposta c’è anche il refresh_token
, che puoi utilizzare per ottenere un nuovo access_token
senza dover usare username
e password
. Ricorda che il refresh_token
scade dopo 14 giorni. La chiamata in questo caso sarà simile a questa:
REQUEST
---
URI: service.4hse.com/oauth2/token
Host: service.4hse.com
Method: POST
Request Payload:
{
"client_id": "example_client_id",
"client_secret": "example_client_secret",
"grant_type": "refresh_token",
"refresh_token": "84c893bdd88fb52400c5d8fc246e81bd544a3486"
}
Questa chiamata ti restituirà un nuovo access_token
e un nuovo refresh_token
(quello precedente verrà disabilitato).
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
"access_token": "b483aff34847b87786bb1a6c313b9e40b2bcf749",
"expires_in": 86400,
"token_type": "Bearer",
"scope": null,
"refresh_token": "c645d84be64791ccf1ee1f148c4f2281a97ae49b",
"user_id": "example_user"
}
Per effettuare una chiamata al sistema utilizzando il bearer token, devi aggiungere a tutte le tue richieste un nuovo header, come nell’esempio sopra:
Authorization: Bearer b483aff34847b87786bb1a6c313b9e40b2bcf749
Ora possiamo tornare alla precedente API che hai chiamato: service.4hse.com/office/index?sort=-name&limit=50&offset=51
. Come ricordi, senza autenticazione hai ricevuto il codice di risposta Unauthorized (401)
. Ma ora che hai il bearer token, puoi effettuare la stessa chiamata aggiungendo l’header di autorizzazione richiesto:
REQUEST
---
URI: service.4hse.com/office/index?sort=-name&limit=50&offset=51
Host: service.4hse.com
Method: GET
Content-Type: application/json
Authorization: Bearer b483aff34847b87786bb1a6c313b9e40b2bcf749
Effettuando la chiamata in questo modo, riceverai il codice Success (200)
e l’elenco degli uffici richiesti.
access-token
Questo metodo è molto semplice, poiché è necessario aggiungere solo il parametro di query access-token
a ogni chiamata API. Devi contattare il supporto 4hse per ottenere l’access-token
. Questo sarà generato su tua richiesta.
Tieni presente che questo
access-token
è completamente diverso e non ha alcuna relazione con l’oauth2.
Quando hai questo token, puoi effettuare la stessa chiamata precedente aggiungendo il parametro di query access-token
. Se il tuo access token è sample-access-token
, puoi semplicemente chiamare:
service.4hse.com/office/index?sort=-name&limit=50&offset=51&access-token=sample-access-token
Effettuando la chiamata in questo modo, riceverai il codice Success (200)
e l’elenco degli uffici richiesti.
Autorizzazione (ACL)
Tutti i servizi web operano all’interno di un sistema di controllo degli accessi. Le regole di controllo degli accessi seguono le autorizzazioni definite per l’utente corrente.
Esempio
L’utente user-1
è manager di office-1
e non ha alcun accesso a office-2
.
Se user-1
tenta di accedere a office-2
chiamando il servizio office/view/office-2
, il server risponde con il codice di stato 404 Not found
perché l’utente non è autorizzato a visualizzare la risorsa office-2
.
Questo comportamento è comune a tutti i servizi, tranne per index
.
Quando un utente chiede l’elenco delle risorse (una collezione) utilizzando index
, il server risponde con l’elenco delle risorse che l’utente può vedere in base alle sue regole di controllo accessi.
Esempio
L’utente user-1
è manager di office-1
e office-3
, e chiama office/index
.
Il server risponde con un elenco di uffici che contiene solo office-1
e office-3
.
L’office-2
viene saltato perché l’utente non può accedervi.
Chiamate
INDEX
Questa chiamata restituisce un elenco delle risorse della collezione a cui si riferisce. Parametri opzionali:
sort
(1): ordina il risultato in base a un attributo della risorsa. Per impostazione predefinita l’ordinamento è in modalità ASC. Per ordinare in modalità DESC aggiungi il prefisso-
.limit
(2): limita il set di risultati a un numero massimo di elementi. Per impostazione predefinita il valore è100
.offset
(3): l’indice del primo elemento del set di risultati.
Per parametri specifici della collezione (filtri, dati aggiuntivi ecc.) puoi consultare la nostra Documentazione API.
REQUEST
---
URI: service.4hse.com/office/index?sort=-name&limit=50&offset=51
Host: service.4hse.com
Method: GET
Content-Type: application/json
Query String Parameters:
sort: -name // <b>(1)</b>
limit: 50 // <b>(2)</b>
offset: 51 // <b>(3)</b>
La risposta contiene:
data
(4): elenco delle risorse che soddisfano i parametri della richiestatotal_count
(5): il numero di elementi che corrispondono alla query corrente. Potrebbe essere diverso dal numero delle risorse presenti indata
.pos
(6): l’offset corrente.
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
"data": [
{
"id": "office-2-534443", // <b>(4)</b>
"office_id": "office-2-534443",
"name": "Office 2",
...
},
{
"id": "office-1-213414",
"office_id": "office-1-213414",
"name": "Office 1",
...
},
...
],
"total_count": "2000" // <b>(5)</b>
"pos": 51 // <b>(6)</b>
}
VIEW
Restituisce una risorsa con i suoi dettagli. Il parametro obbligatorio è id
(1), necessario per identificare la risorsa. Questo parametro sarà riportato due volte nella risposta come attributi id
(2) e <collection>_id
(3). Una sede avrà gli attributi id
e office_id
con lo stesso valore.
Per parametri specifici della collezione (filtri, dati aggiuntivi ecc.) puoi consultare la nostra Documentazione API.
REQUEST
---
URI: service.4hse.com/office/view/office-1-534443
Host: service.4hse.com
Method: GET
Query String Parameters:
id: office-1-534443 // <b>(1)</b>
La risposta contiene la risorsa nel body
.
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
"data": {
"id": "office-1-534443", // <b>(2)</b>
"office_id": "office-1-534443", // <b>(3)</b>
"name": "Office 1",
...
}
}
CREATE
Richiede un payload
(1) contenente l’attributo <collection>_id
(2) e tutti gli attributi richiesti per la risorsa.
Per parametri specifici della collezione puoi consultare la nostra Documentazione API.
REQUEST
---
URI: service.4hse.com/office/create
Host: service.4hse.com
Method: POST
Request Payload: // <b>(1)</b>
{
"office_id": "office-1-534443", // <b>(2)</b>
"name": "Office 1",
...
}
La risposta contiene la risorsa creata all’interno del body
.
RESPONSE
---
Status Code: 201 Created
Content-Type: application/json
Body:
{
"data": {
"id": "office-1-534443",
"office_id": "office-1-534443",
"name": "Office 1",
...
}
}
UPDATE
Come per il view
, è necessario il parametro id
(1) per identificare la risorsa. Inoltre, è necessario fornire un payload
(2) contenente id
(3), <collection>_id
(4) e gli attributi aggiornati (5).
REQUEST
---
URI: service.4hse.com/office/update/office-1-534443
Host: service.4hse.com
Method: PUT
Query String Parameters:
id: office-1-534443 //<b>(1)</b>
Payload: //<b>(2)</b>
{
"id": "office-1-534443", //<b>(3)</b>
"office_id": "office-1-534443", //<b>(4)</b>
"name":"new name for office 1", //<b>(5)</b>
...
}
La risposta contiene la risorsa aggiornata all’interno del body
.
RESPONSE
---
Status Code: 200 OK
Content-Type: application/json
Body:
{
"data": {
"id": "office-1-534443",
"office_id": "office-1-534443",
"name":"new name for office 1",
...
}
}
DELETE
È necessario il parametro id
(1) per identificare la risorsa da eliminare.
Inoltre, è possibile specificare il parametro force
(2), che per impostazione predefinita è false
.
Quando force = false
, il servizio non elimina la risorsa, ma risponde con una richiesta di conferma che include eventualmente le risorse correlate a quella selezionata.
Ogni elemento in 4HSE fa parte di una struttura gerarchica di dipendenze. Se si elimina una persona, tutte le risorse ad essa collegate (certificati, formazioni, ecc.) verranno eliminate insieme ad essa. Questa pratica garantisce la coerenza dei dati ed evita elementi orfani.
REQUEST
---
URI: service.4hse.com/office/delete/office-1-534443
Host: service.4hse.com
Method: DELETE
Query String Parameters:
id: office-1-534443 // <b>(1)</b>
force: false // <b>(2)</b>
Quando force = false
, il servizio risponde con 400 Bad Request
e include nel body
le risorse correlate.
Ogni risorsa collegata è identificata da:
id
(3): identificativo univoco della risorsalabel
(4): etichetta descrittiva della risorsatype
(5): tipologia della risorsa
RESPONSE
---
Status Code: 400 Bad Request
Content-Type: application/json
Body:
{
"message": "Addictions are present",
"code": 1001,
"data": [
{
"id": "office-1-534443", // <b>(3)</b>
"label": "Office 1", // <b>(4)</b>
"type": "OFFICE" // <b>(5)</b>
}
]
}
Se force = true
(2), il servizio elimina la risorsa identificata da id
(1) e tutte le risorse correlate.
REQUEST
---
URI: service.4hse.com/office/delete/office-1-534443
Host: service.4hse.com
Method: DELETE
Query String Parameters:
id: office-1-534443 //<b>(1)</b>
force: true //<b>(2)</b>
RESPONSE
---
Status Code: 204 No Content
Content-Type: application/json
Esempio di codice
In questo esempio di codice realizzeremo una semplice applicazione CRUD che utilizza le API REST di 4HSE.
Requisiti:
- Ambiente di lavoro con Python 3
- Libreria
python-requests
- Libreria
python-uuid
Iniziamo scrivendo il codice per recuperare una lista di uffici chiamando il servizio office/index
.
import requests <b>(1)</b>
params = {'limit': 10, 'sort': '-name'} <b>(2)</b>
r = requests.get('https://service.4hse.com/office/index', params=params) <b>(3)</b>
print(r.text) #{data: [{'office_id':'sad14024000hdg002252','name':'My first office', 'project_id':'prj1234567'}], total_count: 1, pos: 0}
print(r) #<Response [200]>
- Importa la libreria per effettuare richieste HTTP.
- Definisci un insieme di parametri per la richiesta. In questo caso, vogliamo limitare il set di risultati a
10
risorse, ordinate in ordine decrescente per nome della sede. - Effettua la richiesta e stampa i risultati.
Il prossimo passo è la creazione di una nuova sede utilizzando il servizio office/create
.
import uuid
project_id = r.json().get('data')[0].get('project_id') # es. prj1234567 <b>(1)</b>
office_id = uuid.uuid1() # es. 00a5d37c-4fe2-46ee-b820-77ce0ac22725 <b>(2)</b>
payload = {'office_id': office_id, 'name': 'My new office', 'project_id': project_id} <b>(3)</b>
r = requests.post('https://service.4hse.com/office/create', data=payload, params=authentication) <b>(4)</b>
print(r.text) #{'data': {'office_id': '00a5d37c-4fe2-46ee-b820-77ce0ac22725', 'name': 'My new office', 'project_id': 'prj1234567'} }
print(r) #<Response [201]>
- Un attributo obbligatorio per la sede è
project_id
, che identifica il progetto all’interno del quale vogliamo creare la sede. In questo esempio, lo recuperiamo dalla prima sede restituito dalla chiamataindex
. - Utilizza la libreria
uuid
di Python per generare un identificativo univoco per la sede. - Definisci un payload che includa
office_id
,project_id
e l’attributo obbligatorioname
. - Effettua la richiesta e stampa i risultati.
Ora andremo a recuperare la sede appena creata utilizzando il servizio office/view
.
params = {'id': office_id} <b>(1)</b>
r = requests.get('https://service.4hse.com/office/view', params=params) <b>(2)</b>
print(r.text) #{'data': {'office_id': '00a5d37c-4fe2-46ee-b820-77ce0ac22725', 'name': 'My new office', 'project_id': 'prj1234567'} }
print(r) #<Response [200]>
new_office = r.json().get('data') <b>(3)</b>
- Definisci i parametri includendo
office_id
. - Effettua la richiesta e stampa il risultato.
- Infine, memorizziamo la sede appena creata all’interno di
new_office
.
Ora vogliamo modificare il nome della nostra sede utilizzando il servizio office/update
.
params = {'id': office_id}
payload = new_office
payload.update({'name': 'new name for my office'}) <b>(1)</b>
r = requests.put('https://service.4hse.com/office/update', data=payload, params=params) <b>(2)</b>
print(r.text) #{'data': {'office_id': '00a5d37c-4fe2-46ee-b820-77ce0ac22725', 'name': 'new name for my office', 'project_id': 'prj1234567'} }
print(r) #<Response [200]>
- Usa
new_office
come payload della richiesta e cambia il suo attributoname
. - Effettua la richiesta e stampa il risultato.
Infine, eliminiamo la sede utilizzando il servizio office/delete
.
params = {'id': office_id, 'force': 'true'} <b>(1)</b>
r = requests.delete('https://service.4hse.com/office/delete', params=params) <b>(2)</b>
print(r) #<Response [204]>
- Definisci i parametri includendo l’
office_id
che vogliamo eliminare eforce = true
per confermare che vogliamo eliminare l’elemento. - Effettua la richiesta e stampa il risultato.