Gestión de cuentas

En esta parte, aprenderemos cómo administrar una cuenta Jami. Esto significa, cómo crear una cuenta Jami, modificar las configuraciones básicas y eliminar la cuenta. Esta parte NO explicará lo que significan todas las configuraciones o cómo podemos usar la cuenta para realizar cualquier acción como agregar un contacto.

What is an account

In Jami, an account is a X509 certificate chain generally containing 3 certificates:

  1. CA (Self-Signed if locally generated or a company)

  2. Account (Where the fingerprint of the public key is called the «Jami ID»)

  3. Dispositivo

This allow a company to revoke an account if needed and an account to revoke a device (if one get stolen for example).

Crear una nueva cuenta

El lado del demonio

API

En cx.ring.Ring.ConfigurationManager:

<method name="addAccount" tp:name-for-bindings="addAccount">
    <tp:docstring>
        Add a new account. When created, the signal <tp:member-ref>accountsChanged</tp:member-ref> is emitted. The clients must then call <tp:member-ref>getAccountList</tp:member-ref> to update their internal data structure.
        <tp:rationale>If no details are specified, the default parameters are used.</tp:rationale>
        <tp:rationale>The core tries to register the account as soon it is created.</tp:rationale>
    </tp:docstring>
    <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="MapStringString"/>
    <arg type="a{ss}" name="details" direction="in"  tp:type="String_String_Map">
        <tp:docstring>
             The new account settings
        </tp:docstring>
    </arg>
    <arg type="s" name="createdAccountId" direction="out">
        <tp:docstring>
             A new account ID
        </tp:docstring>
    </arg>
</method>

The details can be retrieven from the method getAccountTemplate(type) with type=JAMI or type=SIP. For example, this is the following code used in LRC.

std::string
NewAccountModel::createNewAccount(profile::Type type,
                                  const std::string& displayName,
                                  const std::string& archivePath,
                                  const std::string& password,
                                  const std::string& pin)
{

    MapStringString details = type == profile::Type::SIP?
                              ConfigurationManager::instance().getAccountTemplate("SIP") :
                              ConfigurationManager::instance().getAccountTemplate("JAMI");
    using namespace libjami::Account;
    details[ConfProperties::TYPE] = type == profile::Type::SIP? "SIP" : "JAMI";
    details[ConfProperties::DISPLAYNAME] = displayName.c_str();
    details[ConfProperties::ALIAS] = displayName.c_str();
    details[ConfProperties::UPNP_ENABLED] = "true";
    details[ConfProperties::ARCHIVE_PASSWORD] = password.c_str();
    details[ConfProperties::ARCHIVE_PIN] = pin.c_str();
    details[ConfProperties::ARCHIVE_PATH] = archivePath.c_str();
    QString accountId = ConfigurationManager::instance().addAccount(details);
    return accountId.toStdString();
}

Cuando se añade una nueva cuenta, se emitirá la señal accountsChanged. El cliente debe actualizar su estructura interna después de esta señal con otros métodos en ConfigurationManager.

Núcleo

La lógica principal para crear una nueva cuenta se encuentra en src/ringdht/ringaccount.cpp, en RingAccount::createAccount

Cómo funciona, desde cero

Una cuenta Jami es representada por algunos archivos almacenados en un archivo gzip. Si se proporciona una contraseña durante la creación de la cuenta, el archivo se cifrará de la siguiente manera: dht::crypto::aesEncrypt(archive, password) (dht::crypto::aesEncrypt se define en OpenDHT y utiliza nettle/{aes,gcm}). Esto es lo que contendrá el archivo, un gran archivo JSON con:

  1. La clave privada ringAccountKey y la cadena de certificados ringAccountCert (encodificado en base 64)

  2. Generado CA key (para certificados autosuficientes) ringCAKey

  3. Dispositivos revocados ringAccountCRL

  4. La llave privada de Ethereum ethKey para el dispositivo. Sólo se utiliza cuando se registra su nombre en ns.jami.net. No es obligatorio.

  5. Los contactos

  6. Las configuraciones de la cuenta

¡Así que vamos a generarlo!

¡Todo!

Eliminar la cuenta

Eliminar una cuenta Jami es bastante simple. Porque las claves sólo están en el dispositivo, si las claves se eliminan… la cuenta se elimina! Lo único que está fuera del dispositivo es el nombre de usuario, en el servidor de nombres. Para eliminar esta información, depende de cómo funciona el servidor de nombres. Por ejemplo, no es posible con https://ns.jami.net

El lado del demonio

API

En cx.ring.Ring.ConfigurationManager:

<method name="removeAccount" tp:name-for-bindings="removeAccount">
    <tp:docstring>
        Remove an existing account. When removed, the signal <tp:member-ref>accountsChanged</tp:member-ref> is emitted. The clients must then call <tp:member-ref>getAccountList</tp:member-ref> to update their internal data structure.
    </tp:docstring>
    <arg type="s" name="accoundID" direction="in">
        <tp:docstring>
             The account to remove, identified by its ID
        </tp:docstring>
    </arg>
</method>

Cuando se elimina la cuenta, se emitirá la señal accountsChanged. El cliente debe actualizar su estructura interna después de esta señal con otros métodos en ConfigurationManager.

Núcleo

La lógica principal para crear una nueva cuenta se encuentra en src/manager.cpp, en Manager::removeAccount. Elimina los archivos de las cuentas y actualiza la configuración (dring.yml).

Actualizar los detalles de una cuenta

API

En cx.ring.Ring.ConfigurationManager:

<method name="setAccountDetails" tp:name-for-bindings="setAccountDetails">
    <tp:docstring>
        Send new account parameters, or account parameters changes, to the core. The hash table is not required to be complete, only the updated parameters may be specified.
        <tp:rationale>Account settings are written to the configuration file when the app properly quits.</tp:rationale>
        <tp:rationale>After calling this method, the core will emit the signal <tp:member-ref>accountDetailsChanged</tp:member-ref> with the updated data. The client must subscribe to this signal and use it to update its internal data structure.</tp:rationale>
    </tp:docstring>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="MapStringString"/>
    <arg type="a{ss}" name="details" direction="in" tp:type="String_String_Map">
    </arg>
</method>

El mapa puede contener una actualización parcial y se emitirá accountDetailsChanged al tener éxito. getAccountDetails

Añadir un dispositivo

Hay dos posibilidades para agregar un dispositivo.

Archivo de respaldo (Luego importar desde respaldo)

API

En cx.ring.Ring.ConfigurationManager:

<method name="exportToFile" tp:name-for-bindings="exportToFile">
    <tp:added version="5.1.0"/>
    <tp:docstring>
        Copy the account archive to the path provided in argument.
    </tp:docstring>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <arg type="s" name="destinationPath" direction="in">
    </arg>
    <arg type="s" name="password" direction="in">
    </arg>
    <arg type="b" name="success" direction="out">
        <tp:docstring>
            True if the operation was initialized successfully.
        </tp:docstring>
    </arg>
</method>

Exportar en DHT

API

En cx.ring.Ring.ConfigurationManager:

<method name="exportOnRing" tp:name-for-bindings="exportOnRing">
    <tp:docstring>
        Export account on the DHT using the given password and generated PIN (returned through exportOnRingEnded signal).
    </tp:docstring>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <arg type="s" name="password" direction="in">
    </arg>
    <arg type="b" name="success" direction="out">
        <tp:docstring>
            True if the operation was initialized successfully. exportOnRingEnded will be trigered on completion.
        </tp:docstring>
    </arg>
</method>

Entonces se emite exportOnRingEnded.

Anular dispositivo

API

<method name="revokeDevice" tp:name-for-bindings="revokeDevice">
    <tp:docstring>
        Revoke device attached to the given Jami account, and publish the new revocation list.
    </tp:docstring>
    <arg type="s" name="accountID" direction="in">
    </arg>
    <arg type="s" name="password" direction="in">
    </arg>
    <arg type="s" name="deviceId" direction="in">
    </arg>
    <arg type="b" name="success" direction="out">
        <tp:docstring>
            True if the operation was performed successfully.
        </tp:docstring>
    </arg>
</method>
<signal name="deviceRevocationEnded" tp:name-for-bindings="deviceRevocationEnded">
    <tp:docstring>
        Notify clients when the revokeDevice operation ended.
    </tp:docstring>
    <arg type="s" name="accountID">
    </arg>
    <arg type="s" name="deviceId">
    </arg>
    <arg type="i" name="status">
        <tp:docstring>
            Status code: 0 for success
            <ul>
                <li>SUCCESS = 0         everything went fine. Device is now revoked.</li>
                <li>WRONG_PASSWORD = 1  revocation failed: wrong password.</li>
                <li>UNKNOWN_DEVICE = 2  revocation failed: unknown device.</li>
            </ul>
        </tp:docstring>
    </arg>
</signal>