Aller au contenu

Documentation pour les développeurs utilisant l'API de Superset

L'API proposée par Superset

Superset propose une interface de programmation d'application (API - Application Programming Interface), il est donc possible de bénéficier de services tels que le listing des éléments (jeux de données, diagrammes, tableaux de bord, etc).

Une description des fonctions de l'API est disponible à l'adresse suivante :

https://votre-instance.dataviz.din.developpement-durable.gouv.fr/swagger/v1

⚠️ Les terminaisons des chemins ne sont pas homogènes : Certaines fonctions ne s'exécutent qu'avec la présence du / final

Exemples d'une utilisation de l'API :

Lister les diagrammes d'une instance à l'aide d'un programme python

Nous souhaitons réaliser un programme listant les diagrammes disponibles sur une instance Superset. La fonction (de type Get) à utiliser est donc /api/v1/chart/

get_chart.png

Le programme va être réalisé en python 3.9.13, nous ne détaillerons pas l'installation de l'environnement de développement.

Pour atteindre notre objectif, nous utiliserons une bibliothèque simple de requêtage HTTP et une autre dédiée à la manipulation de données JSON.

import requests
import json

1er cas d'utilisation : Lister les diagrammes d'une instance sans authentification préalable

session = requests.Session()
api_url = "https://demo.dataviz.din.developpement-durable.gouv.fr/api/v1/chart/"
reponse = session.get(api_url)
retour = reponse.status_code
if retour == 200 :
     print(json.dumps(reponse.json(), indent=4))
else :
     print('Erreur sur la récupération de la liste des diagrammes')

Sans authentification, le JSON retourné par l'API contient les éventuels diagrammes basés sur un jeu de données public.

results_chart_no_auth.png

2nd cas d'utilisation : Lister les diagrammes d'une instance avec authentification préalable

L'authentification repose sur la fonction API '/api/v1/security/login', la fourniture d'identifiants de connexion valides permet d'obtenir un token d'accès. Les identifiants ne correspondent pas à vos identifiants Cerbère, ils concernent le compte 'superset_api'. Le mot de passe associé est à demander auprès du D3IA.

session = requests.Session()
api_url = "https://demo.dataviz.din.developpement-durable.gouv.fr/api/v1/security/login"
payload = {
     "provider" : "db",
     "refresh" : True,
     "username" : 'superset_api',
     "password" : '*********'
}
reponse = session.post(api_url, json=payload)
retour = reponse.status_code
if retour == 200 :
     # Le résultat est au format json, 2 variables sont retournées : 'access_token' et 'refresh_token'
     # On passe le token dans le header pour une authentification de type 'bearer'
     # L'access_token a une durée de vie (TTL) limitée à 15 minutes
     access_token = reponse.json()['access_token']
     header_bearer = {'Authorization' : 'Bearer ' + access_token}
else :
     print('Erreur sur la récupération du token')

⚠️ La fourniture du token devrait être suffisante mais pour une raison inconnue, elle est sans effet. Un contournement (peu confortable) est possible via la fourniture manuelle d'un cookie.

cookie_manuel = ".eJwljstqQ******************************************-Trq************************-De_********************************************"
header_bearer.update({'cookie' : f'session={cookie_manuel}'})
api_url = "https://demo.dataviz.din.developpement-durable.gouv.fr/api/v1/chart/"
reponse = session.get(api_url, headers = header_bearer)
retour = reponse.status_code
if retour == 200 :
     print(json.dumps(reponse.json(), indent=4))
else :
     print('Erreur sur la récupération de la liste des diagrammes')
Le JSON retourné par l'API contient les diagrammes pour lesquels l'utilisateur authentifié a des droits.

results_chart_with_auth.png

Ajouter un lot d'utilisateurs à l'aide d'un programme python

Les premières étapes sont identiques à l'exemple précédent :

  • Récupération d'un token JWT,
  • Fourniture manuelle d'un cookie.
session = requests.Session()
api_url = "https://demo.dataviz.din.developpement-durable.gouv.fr/api/v1/security/login"
payload = {
     "provider" : "db",
     "refresh" : True,
     "username" : 'superset_api',
     "password" : '*********''
}
reponse = session.post(api_url, json=payload)
retour = reponse.status_code
if retour == 200 :
     # Le résultat est au format json, 2 variables sont retournées : 'access_token' et 'refresh_token'
     # On passe le token dans le header pour une authentification de type 'bearer'
     access_token = reponse.json()['access_token']
     header_bearer = {'Authorization' : 'Bearer ' + access_token}
else :
     print('Erreur sur la récupération du token')

# Le token devrait être suffisant mais pour une raison inconnue, il est sans effet.
# Un contournement (très peu confortable) est possible via la fourniture manuelle d'un cookie
cookie_manuel = ".eJwljstqQ******************************************-Trq************************-De_********************************************"
header_bearer.update({'cookie' : f'session={cookie_manuel}'})

L'ajout d'un utilisateur nécessite la fourniture d'un token CSRF.

⚠️ Le chemin pour l'ajout d'un utilisateur est non référencé dans la documentation API de superset.

api_url = "https://demo.dataviz.din.developpement-durable.gouv.fr/api/v1/security/csrf_token/"
reponse = session.get(api_url, headers=header_bearer)
retour = reponse.status_code
# Le résultat est au format json, 1 variable est retournée : 'result'
if retour == 200 :
     csrf_token = reponse.json()['result']
     header_bearer.update({'X-CSRFToken' : csrf_token})
     api_url = "https://demo.dataviz.din.developpement-durable.gouv.fr/users/add" # https://github.com/apache/superset/issues/3083
     users = [
          # L'authentification étant basée sur Cerbère sur nos instances, il n'est pas nécessaire de fournir le mot de passe (et sa confirmation)
          {
          'first_name': 'User_1',
          'last_name':'ADDED_BY_API',
          'username': 'user-1.added_by_api@mail.com',
          'email': 'user-1.added_by_api@mail.com',
          'roles': ['3'] # 1 --> Admin, 3 --> Alpha, 4 --> Gamma
          },
          {
          'first_name': 'User_2',
          'last_name':'ADDED_BY_API',
          'username': 'user-2.added_by_api@mail.com',
          'email': 'user-2.added_by_api@mail.com',
          'roles': ['3'] # 1 --> Admin, 3 --> Alpha, 4 --> Gamma
          }
     ]
     for user in users :
          payload = {
               'first_name': user['first_name'],
               'last_name': user['last_name'],
               'username': user['username'],
               'email': user['email'],
               'active': True,
               #'conf_password': user['password'],
               #'password': user['password'],
               'roles': user['roles']
          }
          reponse = requests.Session().post(api_url, headers=header_bearer, json=payload)
          retour = reponse.status_code
          if retour == 200 :
               print("ajout d\'un utilisateur : " + str(payload) + " --> " + str(retour))
          else :
               print("ajout impossible d\'un utilisateur : " + str(payload) + " --> " + str(reponse.text))
else :
     print('CSRF KO --> Impossible d\'ajouter un utilisateur')

traces_add_users.png

users_added.png