# Utilisateur

## Rôles utilisateurs

  Il existe 2 types de rôle : 
   - Administratif qui sont stocké sur le champs `roles` : 
     - `Administrator`, 
     - `SuperAdmin`, 
     - `Manager`
   - Métier qui sont stocké sur le champs `auth_roles` : 
     - `superadministrateur`, 
     - `demandeur`, 
     - `bailleur`, 
     - `entreprise`, 
     - `cre`, 
     - `rdsl`, 
     - `collaborateur offre logement`, 
     - `collaborateur entreprises`
  
  Le role `superadministrateur` permet d'outrepasser les droits  

## Connexion "en tant que"

### Pour les utilisateurs "collaborateur offre logement"
    
    POST api/dmo/applicants/{ID de l'applicant}/switch

Retourne un token pour pouvoir se connecter "en tant que" l'utilisateur (i.e. target) dont le `main_applicant_id` correspond à l'ID renseigné dans la requête.

    {
      "success": true,
      "info": "Enregistré",
      "email": "email de l'utilisateur target",
      "login": "login de l'utilisateur target",
      "jwt_token": "nouveau_token_genere_pour_le_log_as"
    }

Un collaborateur offre logement connecté "en tant que" aura accès à toutes les requêtes API dont l'utilisateur target a accès.

### Pour les utilisateurs "entreprise"

Le params `entity_id` est **obligatoire** dans le body de la requête : 
    
    POST api/dmo/applicants/{ID de l'applicant}/switch

Avec en body : 

    {
      entity_id: "ID de l'entity"
    }

La réponse est en "success" uniquement si :
  - • L'utilisateur "entreprise" qui switch est **au moins** lecteur de l'`entity_id`.
  - • Il existe une délégation entre l'`entity_id` et l'`applicant_id` renseigné dans la requête API.
  - • La délégation est signée.

Elle retourne un token pour pouvoir se connecter "en tant que" comme précédemment.

Un utilisateur entreprise connecté "en tant que" grâce à la délégation n'aura seulement accès qu'aux requêtes API de la demande de logement (`api/dmo/housing_requests/...`)




## Création d'utilisateur
  Les rôles suivant peuvent créer des utilisateurs : 

    Administrator
    SuperAdmin
    Manager
    superadministrateur
    entity
    bailleur
    rdsl
    cre

  Les `superadministrateur` ne peuvent être créés que par des utilisateurs ayant les rôles suivant :

    Administrator
    SuperAdmin
    Manager
    superadministrateur

## Abonnements

Routes pour les abonnements :

Pour voir l'abonement d'un applicant ou demande:

      GET /api/dmo/users/:user_id/subscriptions

Voici un exemple de résultat :

    GET /api/dmo/users/60362276b93ee306c98163e5/subscriptions
    {
        "data": [
            {
                "id": "603622797a6d007df6b4d23d",
                "type": "subscriptions",
                "attributes": {
                    "responsible": {
                        "id": "60362276b93ee306c98163e5",
                        "first_name": "wafasnneeeee",
                        "last_name": "heyyyy"
                    },
                    "readers": null,
                    "writers": null,
                    "read_level": "guest",
                    "created_at": "2021-02-24T10:55:05.725+01:00",
                    "updated_at": "2021-02-24T10:55:05.725+01:00",
                    "keys": [
                        {
                            "name": "message.new",
                            "email": true,
                            "web": true,
                            "slack": false,
                            "sms": false
                        },
                        {
                            "name": "user.create",
                            "email": true,
                            "web": true,
                            "slack": false,
                            "sms": false
                        },
                        {
                            "name": "user.new_reserved_offer",
                            "email": true,
                            "web": true,
                            "slack": false,
                            "sms": false
                        }
                    ],
                    "subscriber_type": "User",
                    "subscriber_id": "60362276b93ee306c98163e5"
                }
            }
        ],
        "links": {
            "self": "https://api-cerfav4-rcc.be-idys.com/api/dmo/users/60362276b93ee306c98163e5/subscriptions?page%5Bnumber%5D=1&page%5Bsize%5D=30",
            "first": "https://api-cerfav4-rcc.be-idys.com/api/dmo/users/60362276b93ee306c98163e5/subscriptions?page%5Bnumber%5D=1&page%5Bsize%5D=30",
            "prev": null,
            "next": null,
            "last": "https://api-cerfav4-rcc.be-idys.com/api/dmo/users/60362276b93ee306c98163e5/subscriptions?page%5Bnumber%5D=1&page%5Bsize%5D=30"
        },
        "meta": {
            "pagination": {
                "per_page": 30,
                "total_pages": 1,
                "total_objects": 1,
                "links": {
                    "first": "/api/dmo/users/60362276b93ee306c98163e5/subscriptions?page=1",
                    "last": "/api/dmo/users/60362276b93ee306c98163e5/subscriptions?page=1"
                }
            }
        }
    }

Pour s'inscrire/désinscrire :

      PUT /api/dmo/users/:user_id/subscriptions/:subscription_id/unsubscribe
      {
        key: "user.new_reserved_offer" # la clé de notification qui correponds au 'name' dans les clés de l'abonnement
        provider: "email" # paramètre optionnel par défault c'est email
      }

Pour s'inscrire/désinscrire à plusieurs clé en même temps :

      PUT /api/dmo/users/:user_id/subscriptions/:subscription_id/update_keys
      {
        keys: [
          {key: "user.new_reserved_offer", provider:"email", subscribed: true},
          {key: "user.new_published_offer", subscribed: false},
        ]
      }

      provider par défaut : email

Pour aller chercher la date de dernière modification d'un abonnement (en tant quand qu'utilsiateur)

    GET /api/dmo/update_subscriptions?name=user.new_reserved_offer

    Retour : 
    {
         {
        "data": [
            {
                "id": "id",
                "type": "update_subscription",
                "attributes": {
                    "readers": null,
                    "writers": null,
                    "read_level": "guest",
                    "created_at": "2021-02-24T10:55:05.725+01:00",
                    "updated_at": "2021-02-24T10:55:05.725+01:00",
                    "object_id: "user_id",
                    "name": "user.new_reserved_offer",
                    "email": true,
                    "web: true,
                    "slack: false,
                    "sms": false,
                    "user_email: "email@test.com",
                }
            }
        ],
        "links": {
          ...
        },
        "meta": {
          ...
        }
    }
  }

Pour récupérer la liste des utilisateurs qui ont mise à jour depuis une date (en tant que superamdinistrateur)

    GET /api/dmo/update_subscriptions?name=user.new_reserved_offer&updated_at[$gte]=2022-01-01

## Préférence de notification d'utilisateur avant création de compte 

Pour créer :

      POST /api/dmo/signup_user_notification_preferences
      {
        data: {
          attributes: {
            email: email,
            notification_key: 'user.new_reserved_offer', 
            want_to_be_subscribed: false
          }
        }
      }

## Filtre utilisateur

Les `user_filters` permettent au front d'enregistrer les filtres de chaque utilisateur.
Chaque utilsiateur ne peut avoir qu'une seule valeur pour chaque clé (le couple user_id/key est unique).

### Pour créer un filtre :

      POST /api/dmo/user_filters
      {
        data: {
          attributes: {
            user_id: id,
            key: 'key1', 
            value: { test: 'value1', boom: ['a', 'b', 'c']  } # La valeur est un hash
          }
        }
      }

Pour mettre à jour, il faut également faire le même appel, l'API s'occupe décraser la valeur si la clé exite pour cet utilisateur.

### Pour récupérer la liste des filtres pour un utilisateur :

      GET /api/dmo/user_filters

Avec la possibilité de filtrer sur les champs `key` et `value`

### Pour récupérer un seul filtre : 

      GET /api/dmo/user_filters/:id

### Pour supprimer un filtre : 

      DELETE /api/dmo/user_filters/:id


## Invalidation des tokens utilisateur API

Une nouvelle table `user_invalidated_token` est ajoutée pour stocker les tokens invalidés lors de la déconnexion. Elle n’est pas visible via API (postman), ni pour lecture ni pour modification, ni suppression et création classiques. Elle contient les champs `user_id`, `token` et `expiring_at`. 

La route suivante permet de créer un des `user_invalidated_token` d'un utilisateur lors d'une déconnexion coté front :
  
    POST /api/dmo/users/invalidate_token
    {
      "token": "token"
    }

Elle peut répondre avec les retours suivants :
- code : 201 quand le token a été invalidé
- code : 422 quand le token n'est pas fourni

Une fois qu'un token invalidé est expiré (par défaut les tokens générés sont valides 4h), l'entrée dans la base `user_invalidated_token` est supprimée par Mongo (via un index TTL) avec une vérification toutes les minutes. 

Lors de chaque appel sur /api/dmo/X, nous vérifions que le bearer token est valide et qu'il n'est pas expiré. Voici les erreurs possibles que ce processus peut renvoyer :

- code : 401, json : { errors: ['Not Authenticated'], success: false } quand il n'y a pas de bearer token
- code : 401, json : { errors: [''User token invalidated''], success: false } quand le token existe dans '`user_invalidated_token`
- code : 401, json: { errors: ['Token expired'], success: false} quand le token a expiré

Pour vérifier les tokens invalidés existants d'un utilisateur, il est possible d'utiliser la commande suivante :

```ruby
Hermes::UserInvalidatedToken.where(user_id: 'user_id').pluck(:token, :expiring_at)
```
