# Données des utilisateurs et scopes des applications
[TOC]
## Données de l'utilisateur
### Notes sur la mise à jour de la structure de certaines listes
On a, par moment, des pseudo-listes avec une structure complexe nécessitant de parser deux fois les données:
* La première fois, c'est le JSON qui est parsé
* Ensuite, on parcours les données et, lorsqu'on tombe sur une clé complexe, on la re-parse pour avoir toutes les informations
Exemple:
```javascript
{
"sectionPhones" : {
"1#Secrétariat[PHONE]" : "+33 4 76 44 41 05",
"2#Mobile[CELLPHONE]" : "+33 6 07 05 71 19 "
}
}
```
L'idée est donc de trouver une nouvelle structuration permettant d'avoir toutes les informations à la sortie du parser JSON.
Donc, dans l'idée:
```javascript
{
sectionPhones: [
{
title: 'Secrétariat',
deviceType: 'PHONE',
areaCode: '+33',
value: '+33476444105'
},
{
title: 'Mobile',
deviceType: 'CELLPHONE',
areaCode: '+33',
value: '+33607057119 '
}
]
}
```
### Users fields
```bash
################### DONNEES SYSTEME ###################
_id # Identifiant unique de document dans MongoDB de type MongoId()
# L'UUID est un champ spécial permettant d'identifier l'utilisateur au sein des APIs, dans l'AccessToken par exemple. Il sera utilisé au lieu de l'username dans les différents process.
# Même s'il s'agit d'une donnée système, elle sera, de fait, visible, BIEN QUE NON MODIFIABLE
UUID
username # TODO: S'assurer qu'il n'est pas modifiable
password # BCrypt
# Roles Symfony (est-ce que ce sera conservé ici ?)
roles[] # Ex: "ROLE_ADMIN"
# TODO: Compléter ce modèle
# Lorsque l'utilisateur demande a changer de mot de passe, la procédure utilisera les données suivantes:
# Voir aussi un flow équivalent dans auth0:
# - https://auth0.com/docs/connections/database/password-change
# - https://auth0.com/docs/api/management/v2#!/Tickets/post_password_change
passwordReset
passwordReset.ticket # clé unique envoyée dans le mail de reset du mot de passe
paswordReset.validityUntil # Date jusqu'à laquelle le ticket est valide (par défaut, 5 jours)
################### DONNEES ADMINISTRATIVES ###################
# String de type "19840618", ou integer équivalent ?
# ( TODO: pros/cons pour les deux)
birthDate
email
firstName
lastName
# Préférences globales de notifications
# Pourra être surchargé par app
preferences.notification.email
preferences.notification.sms
# Adresse
location: {
address
city
country
zipCode
lat
lng
}
mails: [
{
label: 'Main/Pro...etc...'
value
}
]
# Cette partie sera à déplacer dans une partie dédiée au
# aux informations médecin
sectionMedical.adeli.0
sectionMedical.apicrypt
sectionMedical.contactWay
sectionMedical.finess
sectionMedical.mssante
sectionMedical.rpps
# Spécialités médicales pour un médecin.
# À noter que ces valeurs sont codées, une norme est disponible
# TODO: Voir avec Seb pour la récupérer
sectionMedical.specialities[]
phones: [
{
label: 'Secrétariat',
deviceType: 'PHONE',
areaCode: '+33',
value: '+33476444105'
},
{
label: 'Mobile',
deviceType: 'CELLPHONE',
areaCode: '+33',
value: '+33607057119 '
}
]
sex
timeZone
visio
avatar
################### META-DONNEES DES APPLICATIONS #################
applicationMetadata
applicationMetadata.appUID: {
# Structure propre à l'application
# On ne limite pas à un niveau
}
################### DONNEES DE PRESENCE #################
# Il s'agit de toutes les données nécessitant un acces en temps réel
status # presence (online, busy)
```
## Scopes
Dans un premier niveau d'implémentation, on peut considérer qu'un scope représentera une ligne décrivant une autorisation que l'utilisateur devra valider.
Il va donc falloir être assez général pour ne pas inonder la liste et assez précis pour couvrir nos besoins.
L'approche qui a l'air de correspondre au mieux serait un système d'espace de nom qui donnera lieu à une arborescence.
La première partie représentera l'application, la seconde son domaine et la troisième, les actions possibles.
Exemple:
- `user_administrative:read`: Lecture des données administratives de l'utilisateur.
- `user_administrative`: Contrôle total des données administratives de l'utilisateur
- `planning`: Contrôle total des données liées à l'agenda
### CRUD User
Le dépôt de données de l'utilisateur sera, dans un premier temps, composé de trois parties:
- Les données générales de l'utilisateur
- Les données des applications de l'utilisateur
- Les données d'état de l'utilisateur
- Les données "système" (rôles, hash du mot de passe, clé de réinitialisations du mot de passe). Il n'est pas sûr que nous ayons besoin de proposer une API pour toucher à ces données.
#### Données générales
Il s'agit des données administratives, ce qui compose la majeur partie des informations à gérer pour un utilisateur.
**Scopes**:
- `user_administrative:read`: Accès à l'API permettant la lecture des informations administrative de l'utilisateur.
- `user_administrative:write`: Accès à l'API permettant l'écriture des informations administrative de l'utilisateur.
- `user_administrative` (songer peut-être à un alias précisant le scope tel que `user_administrative:admin`): Accès total aux informations de l'utilisateur
#### Données `applicationMetadata`
Il s'agit de données spécifiques à une application, elles sont stockées directement dans les informations utilisateur car on a une relation `1 -- 1` de l'un à l'autre.
Par contre, par défaut (requête `GET /user`), les méta-données d'application ne sont pas renvoyées. Il faudra les demander expressément:
`GET /user/applicationMetadata`
Si on imagine pour cela un stockage des données du type:
```javascript
const currentUser = {
firstName,
lastName,
// ... other user data ...
applicationsMetadata: {
'unique-app-identifier':{
key: value,
app: {
meta: data
}
}
}
}
```
Et que l'application effectuant la requête est identifiée par `application1`, l'API `GET /user/applicationMetadata` renverra les données de `currentUser.applicationsMetadata.application1`.
**Scopes**:
- `user_applicationMetadata`: Autorise l'application à lire/écrire ses propres meta-données liées à l'utilisateur. Elle n'accède pas aux méta-données des autres applications.
**Par contre**, il peut aussi arriver qu'une application souhaite accéder à toutes les informations des applications étrangères.
Si on implémente ce mécanisme, il faudra le protéger par des scopes dédiés.
**Scopes**:
- `user_applicationsMetadata:read`: Accès à l'intégralité des méta-données d'applications en lecture.
- `user_applicationsMetadata:write`: Accès à l'intégralité des méta-données d'applications en écriture.
- `user_applicationsMetadata`: Accès total aux méta-données des applications
#### Informations d'état de l'utilisateur
Pour l'instant, on gère une clé `status` qui correspond à l'état de présence de l'utilisateur dans TELEMEDICA.
**NB**: Cette partie n'est pas encore clairement définie pour le moment, elle sera suceptible d'évoluer par la suite.
Quelques points de réflexion:
- La présence dans TELEMEDICA est valable pour toutes les applications ?
- Est-ce qu'une messagerie (type texte) pourrait par exemple générer un status différent
- Dans un cas plus général, ne faudrait-il pas lier des données temps-réel aux méta-données des application ?
**Scopes**:
- `user_status:read`: Lecture de l'état (présence) de l'utilisateur dans la messagerie/visio.
- `user_status:write`: Ecriture de l'état (présence) de l'utilisateur dans la messagerie/visio.
- `user_status`: Accès total
### Application Planning
L'application d'agenda sera la première à être intégrée avec le système d'autorisations.
Elle propose une API qui pourra faire l'objet des modifications sur l'architecture.
De plus, via l'accès au backoffice, on pourra commencer à développer la première application client pour OAuth si on fait en sorte que la connexion passe par notre serveur d'autorisations.
#### Scopes du serveur de ressources
Il s'agit des scopes dont une application tierce a besoin pour accéder aux données via les API que peut proposer l'agenda.
Seuls les scopes globaux (sans la partie `:read`/`:write`) seront affichés ici
- `planning_users`: Il s'agit ici des utilisateurs gérés dans le contexte du planning qui ont leurs informations propres. Par exemple, dans le modèle actuel, un utilisateur peut être un chariot puisque celui-ci a des disponibilités propres, est lié à un RDV...etc...
- `planning_specialities`: Spécialités médicales affectées aux médecins et aux centres, il s'agit ici d'affecter la liste de ces spécialités (si nécessaire)
- `planning_specialities:search`: Possibilité d'effectuer une recherche dans les spécialités.
- `planning_centers`: Accès aux centres de télémédecine
- `planning_centers:search`: Possibilité d'effectuer une recherche dans les centres.
- `planning_equipements` + `planning_equipements:search`: Gestion et recherche de l'équipement
- `planning_availabilities`: Agenda des utilisateurs (disponibilités, empêchements)
- `planning_meetings`: Rendez-vous de téléconsultation. On aura un scope pour la lecture (`:read`), mais pas pour l'écriture. Par ailleurs, les scopes seront d'avantage détaillés pour cette API:
- `planning_meetings:search`
- `planning_events:create`
- `planning_events:update`
- `planning_events:delete`
#### Scopes utilisés par l'application
Les scopes ci-dessous sont requis par l'application planning dans un contexte de connexion d'un utilisateur par OAuth.
Il s'agit essentiellement de l'accès au backoffice puisque les utilisateurs standards de s'authentifient pas pour accéder à la prise de RDV.
- `user_administrative:read`
- `user_applicationMetadata`: Pourrait être utilisé pour l'enregistrement de préférences
**Un point sur la gestion des rôles**: On a le choix entre l'enregistrement des rôles dans la base du planning en association avec l'utilisateur trouvé dans l'AccessToken, l'utilisation de la clé rôles directement ou l'utilisation de l'`applicationMetadata`.
Pour ce dernier point c'est plus risqué, si une application tierce peut modifier cette information, cela impactera l'accès au backoffice et ce n'est pas maîtrisé.
Il en est de même pour le rôle présent dans les données de l'utilisateur. Ca voudrait dire que le serveur de ressources des utilisateurs pourrait octroyer des droits supplémentaires dans l'application planning.
Les rôles devront donc se gérer par application afin d'isoler les logiques.