Identities in Caliopen

Intro

Before summer 2018, Caliopen stack had 2 kinds of identity objects to store data about user's accounts : RemoteIdentity and LocalIdentity. While we made use of LocalIdentity to store data about user's local Caliopen email account, we introduced RemoteIdentity to store data about external accounts belonging to him. This design led us to redundant code and models. Decision was made to merge LocalIdentity and RemoteIdentity into a unique object, an UserIdentity.

Definitions and backend architecture

Definition

An UserIdentity is an account belonging to an user at a communication service provider. It can be local — for example an email address hosted on local Caliopen instance —, or remote — for example an external mastodon account.

At creation, each Caliopen user has at least one UserIdentity, representing its Caliopen email box. This UserIdentity is of type=local and has protocol=smtp.

Model

type: object
properties:
  credentials:    # set of key/value strings
    type: object
    additionalProperties:
      type: string
  display_name:
    type: string
  identifier:
    type: string
  identity_id:
    type: string
  infos:          # set of key/value strings
    type: object
    additionalProperties:
      type: string
  last_check:
    type: string
    format: date-time
  protocol:
    type: string
    enum:
    - imap
    - smtp
  status:
    type: string
    enum:
    - active
    - inactive
    - deleted
  type:
    type: string
    enum:
    - local
    - remote
  user_id:
    type: string
required:
- identifier
- identity_id
- infos
- protocol
- type
- status
- user_id

Has shown above, UserIdentity has a set of mandatory properties. Among them, there are 2 mandatory immutable properties :

The pair identifier + protocol must be unique within an user account. It can't be changed, ie data must be copied into a new UserIdentity if one wants to modify this pair.

ReST API

Identities APIs

Identities APIs keep legacy routes to manage either local or remote identies on 2 different path : …/identities/locals… and …/identities/remotes….

Routes :

When creating a new remote identity (on route …/api/v2/identities/remotes) client MUST provide properties protocol and identifier. These properties are then immutable.

NB : UserIdentity's type property will be enforced by backend on POST and PATCH verbs to match route (ie type=remote on routes …/identities/remotes and type=local on …/identities/locals), even if client provides a wrong type.

Draft API

Routes :

When creating or editing a draft message, client MUST provide one UserIdentity on behalf of which the message will be sent. It can be a local or remote identity. (For now, only one identity per message is supported)

Client links a draft to an UserIdentity by embedding identity_id into draft's user_identities property :

POST …/api/vi/messages
{
    "subject": "My subject",
    "user_identities": ["ae8c45d2-c085-4fa9-bbd9-5ec83b4c8469"],
    "participants": [
        {
            "address": "dev@caliopen.local",
            "label": "Dev Idoire",
            "protocol": "email",
            "type": "To"
        }
    ],
    "body": "my message"
}

As shown above, model for Message object (and consequently for draft) has slightly changed. Property identities has been renamed to user_identities, and is now an array of strings representing a set of user_identity_id. Here is an example of a simple message sent by an user :

{
    "body": "My message",
    "body_is_plain": true,
    "excerpt": "l…",
    "date": "2018-07-20T15:56:06.062Z",
    "date_insert": "2018-07-20T15:53:07.648Z",
    "date_sort": "2018-07-20T15:56:06.062Z",
    "discussion_id": "51d367b2-240a-4db0-8d4d-cedf592b1306",
    "external_references": {
        "message_id": "wkFJWsiC5vHTJcdxEIMvJD0zBL412b_LQ091DmNZdZw=@caliopen.org"
    },
    "user_identities": [
        "ae8c45d2-c085-4fa9-bbd9-5ec83b4c8469"
    ],
    "importance_level": 0,
    "is_answered": false,
    "is_draft": false,
    "is_unread": false,
    "is_received": false,
    "message_id": "de7a5f69-905c-4158-8bdc-9a1e2ac1f197",
    "participants": [
        {
            "address": "dev@caliopen.local",
            "label": "Dev Idoire",
            "protocol": "email",
            "type": "To"
        },
        {
            "address": "dev@caliopen.local",
            "contact_ids": [
                "fb94efe5-1ff6-43cf-9823-5ec3887bc3fb"
            ],
            "label": "Dev Idoire",
            "protocol": "email",
            "type": "From"
        }
    ],
    "raw_msg_id": "cb61ca60-1931-4ae6-b036-67baf50aea76",
    "subject": "My subject",
    "type": "email",
    "user_id": "6cc36d88-6163-4465-805a-cacf58f455e4"
}

User model

User object has no longer a local_identities property embedded. Call to …/identites/locals to fetch relevant data.