Account management

In this part, we will learn how to manage a Ring account. This means, how to create a Ring account, modify the basic settings and delete the account. This part will NOT explain what all the settings mean or how we can use the account to do any action like adding a contact.

Create a new account

Client side

Gnome

The code related to this feature is located in src/accountcreationwizard.*

LRC

The account creation is mainly managed by the NewAccountModel in src/api/newaccountmodel.h and src/newaccountmodel.cpp

Daemon side

API

In 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=RING 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("RING");
    using namespace DRing::Account;
    details[ConfProperties::TYPE] = type == profile::Type::SIP? "SIP" : "RING";
    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();
}

When a new account is added, the signal accountsChanged will be emitted. The client should update its internal structure after this signal with other methods in ConfigurationManager.

Core

The main logic to create a new account is located in src/ringdht/ringaccount.cpp, in RingAccount::createAccount

How it works, from scratch

A Ring account is in fact represented by some files stored in a gzip archive. If a password is provided during the account creation, the archive will be encrypted as following: dht::crypto::aesEncrypt(archive, password) (dht::crypto::aesEncrypt is defined in OpenDHT and use nettle/{aes,gcm}). This is what the archive will contain a big JSON file with:

  1. The private key ringAccountKey and certificate chain ringAccountCert (base64 encoded)

  2. Generated CA key (for self-signed certificates) ringCAKey

  3. Revocated devices ringAccountCRL

  4. The ethereum private key ethKey for the device. It’s only used when you register your name on ns.ring.cx. Not mandatory.

  5. The contacts

  6. The account settings

So let’s generate it!

TODO

Delete the account

Deleting a Ring account is pretty simple. Because the keys are only on the device, if the keys are deleted… the account is deleted! The only thing outside the device is the username, on the nameserver. To remove this info, it depends how the nameserver work. For example, it’s not possible with https://ns.ring.cx

Client side

Gnome

The code related to this feature is located in newaccountsettingsview.cpp

LRC

The account deletion is in the NewAccountModel in src/api/newaccountmodel.h and src/newaccountmodel.cpp (removeAccount)

Daemon side

API

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

When the account is deleted, the signal accountsChanged will be emitted. The client should update its internal structure after this signal with other methods in ConfigurationManager.

Core

The main logic to create a new account is located in src/manager.cpp, in Manager::removeAccount. It removes the accounts files and update the config (dring.yml).

Update the settings

TODO

Add and revoke devices

TODO