Gestão de contas

Nesta parte, vamos aprender a gerir uma conta Jami. Isto significa, como criar uma conta Jami, modificar as configurações básicas e eliminar a conta. Esta parte NÃO explica o significado de todas as configurações ou como podemos utilizar a conta para realizar qualquer ação, como adicionar um contacto.

O que é uma conta

No Jami, uma conta é uma cadeia de certificados X509 que contém geralmente 3 certificados:

  1. CA (auto-assinada se gerada localmente ou por uma empresa)

  2. Conta (onde a impressão digital da chave pública é designada por «Jami ID»)

  3. Dispositivo

Isto permite a uma empresa revogar uma conta, se necessário, e a uma conta revogar um dispositivo (se um for roubado, por exemplo).

Criar uma nova conta

Lado daemon

API

Em 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 retrieved 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();
}

Quando uma nova conta é adicionada, o sinal accountsChanged será emitido. O cliente deve atualizar a sua estrutura interna após este sinal com outros métodos no ConfigurationManager.

Núcleo

A lógica principal para criar uma nova conta está localizada em src/ringdht/ringaccount.cpp em RingAccount::createAccount

Como funciona, a partir do zero

Uma conta Jami é, de facto, representada por alguns ficheiros armazenados num arquivo gzip. Se for fornecida uma palavra-passe durante a criação da conta, o arquivo será encriptado da seguinte forma: dht::crypto::aesEncrypt(archive, password) (dht::crypto::aesEncrypt é definido no OpenDHT e utiliza nettle/{aes,gcm}). É com isto que o arquivo conterá um grande ficheiro JSON:

  1. A chave privada ringAccountKey e a cadeia de certificados ringAccountCert (codificado em base64)

  2. Chave CA gerada (para certificados auto-assinados) ringCAKey

  3. Dispositivos revogados ringAccountCRL

  4. A chave privada ethereum ethKey para o dispositivo. Só é utilizada quando regista o seu nome em ns.jami.net. Não é obrigatório.

  5. Os contactos

  6. Configurações da conta

Então vamos gerá-lo!

A FAZER

Eliminar a conta

A eliminação de uma conta Jami é bastante simples. Porque as chaves estão apenas no dispositivo, se as chaves forem eliminadas… a conta é eliminada! A única coisa fora do dispositivo é o nome de utilizador, no servidor de nomes. Para remover esta informação, depende de como o servidor de nomes funciona. Por exemplo, não é possível com https://ns.jami.net

Lado daemon

API

Em 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>

Quando a conta é eliminada, é emitido o sinal accountsChanged. O cliente deve atualizar a sua estrutura interna após este sinal com outros métodos no ConfigurationManager.

Núcleo

A lógica principal para criar uma nova conta está localizada em src/manager.cpp, em Manager::removeAccount. Ele remove os arquivos de contas e atualiza a configuração (dring.yml).

Atualizar os detalhes de uma conta

API

Em 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>

O mapa pode conter uma atualização parcial e accountDetailsChanged será emitido em caso de sucesso. getAccountDetails

Adicionar um dispositivo

Existem duas possibilidades para adicionar um dispositivo.

Arquivo de cópia de segurança (depois importar da cópia de segurança)

API

Em 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 em DHT

API

Em 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>

Em seguida, é emitida exportOnRingEnded.

Revogar 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>