diff --git a/CMakeLists.txt b/CMakeLists.txt
index da3f5d5f92e99038968e2926fa44c1a10bbb3d1a..2dfb1b4267eaea75be9202d05e4092cdded31f89 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -327,6 +327,7 @@ SET( libringclient_LIB_SRCS
   src/bannedcontactmodel.cpp
   src/contactmodel.cpp
   src/newcallmodel.cpp
+  src/newdevicemodel.cpp
   src/conversationmodel.cpp
   src/database.cpp
   src/authority/daemon.cpp
@@ -498,6 +499,7 @@ SET(libringclient_api_LIB_HDRS
   src/api/lrc.h
   src/api/newaccountmodel.h
   src/api/newcallmodel.h
+  src/api/newdevicemodel.h
   src/api/contactmodel.h
   src/api/conversationmodel.h
   src/api/profile.h
diff --git a/src/api/account.h b/src/api/account.h
index e7151d1530afad5ecc2238c3a59ef43acc91f9c7..d36abdd007916f99e193bb03c9853b730562166a 100644
--- a/src/api/account.h
+++ b/src/api/account.h
@@ -35,6 +35,7 @@ class NewCallModel;
 class ContactModel;
 class ConversationModel;
 class NewAccountModel;
+class NewDeviceModel;
 
 namespace account
 {
@@ -85,6 +86,7 @@ struct Info
     std::unique_ptr<lrc::api::NewCallModel> callModel;
     std::unique_ptr<lrc::api::ContactModel> contactModel;
     std::unique_ptr<lrc::api::ConversationModel> conversationModel;
+    std::unique_ptr<lrc::api::NewDeviceModel> deviceModel;
     NewAccountModel* accountModel {nullptr};
 };
 
diff --git a/src/api/newdevicemodel.h b/src/api/newdevicemodel.h
new file mode 100644
index 0000000000000000000000000000000000000000..1aac83a01d0026e1230e48a7c9cc9b471ec96e7d
--- /dev/null
+++ b/src/api/newdevicemodel.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+ *   Copyright (C) 2017-2018 Savoir-faire Linux                             *
+ *   Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>           *
+ *                                                                          *
+ *   This library is free software; you can redistribute it and/or          *
+ *   modify it under the terms of the GNU Lesser General Public             *
+ *   License as published by the Free Software Foundation; either           *
+ *   version 2.1 of the License, or (at your option) any later version.     *
+ *                                                                          *
+ *   This library is distributed in the hope that it will be useful,        *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
+ *   Lesser General Public License for more details.                        *
+ *                                                                          *
+ *   You should have received a copy of the GNU General Public License      *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+#pragma once
+
+// Std
+#include <memory>
+#include <string>
+#include <list>
+
+// Qt
+#include <qobject.h>
+#include <QObject>
+
+// Lrc
+#include "api/account.h"
+#include "typedefs.h"
+
+namespace lrc
+{
+
+class CallbacksHandler;
+class NewDeviceModelPimpl;
+
+namespace api
+{
+
+namespace account { struct Info; }
+
+struct Device
+{
+    std::string id = "";
+    std::string name = "";
+    bool isCurrent = false;
+};
+
+/**
+  *  @brief Class that manages ring devices for an account
+  */
+class LIB_EXPORT NewDeviceModel : public QObject {
+    Q_OBJECT
+
+public:
+    /**
+     * Used by deviceRevoked's status
+     */
+    enum class Status {
+        SUCCESS = 0,
+        WRONG_PASSWORD = 1,
+        UNKNOWN_DEVICE = 2
+    };
+    const account::Info& owner;
+
+    NewDeviceModel(const account::Info& owner, const CallbacksHandler& callbacksHandler);
+    ~NewDeviceModel();
+
+    /**
+     * Get ring devices of an account
+     * @return a copy of current devices
+     */
+    std::list<Device> getAllDevices() const;
+
+    /**
+     * Retrieve a device by its id
+     * @param id of the device
+     * @return the device if found else a device with a null id
+     */
+    Device getDevice(const std::string& id) const;
+
+    /**
+     * Revoke a ring device
+     * @param id of the device to revoke
+     * @param password of the account's archive
+     * @note will emit deviceRevoked when finished
+     */
+    void revokeDevice(const std::string& id, const std::string& password);
+
+    /**
+     * Change the name of the current device
+     * @param newName
+     * @note will emit deviceUpdated when finished
+     * @note ring can't change the name of another device
+     */
+    void setCurrentDeviceName(const std::string& newName);
+
+Q_SIGNALS:
+    /**
+     * Link to this signal to know when a new device is added
+     * @param id added device
+     */
+    void deviceAdded(const std::string& id) const;
+    /**
+     * Link to this signal to know when a device is removed
+     * @param id removed device
+     * @param Status (SUCCESS, WRONG_PASSWORD, UNKNOWN_DEVICE)
+     */
+    void deviceRevoked(const std::string& id, const Status status) const;
+    /**
+     * Link to this signal when a device get a new name
+     * @param id
+     */
+    void deviceUpdated(const std::string& id) const;
+
+private:
+    std::unique_ptr<NewDeviceModelPimpl> pimpl_;
+};
+
+} // namespace api
+} // namespace lrc
diff --git a/src/callbackshandler.cpp b/src/callbackshandler.cpp
index 1ed6fcef3f4b65d90f4983d0cb48eef2b6205387..88739629a043f855039c71274f0338d362ab786b 100644
--- a/src/callbackshandler.cpp
+++ b/src/callbackshandler.cpp
@@ -118,6 +118,16 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent)
             &ConfigurationManagerInterface::dataTransferEvent,
             this,
             &CallbacksHandler::slotDataTransferEvent);
+
+    connect(&ConfigurationManager::instance(),
+            &ConfigurationManagerInterface::knownDevicesChanged,
+            this,
+            &CallbacksHandler::slotKnownDevicesChanged);
+
+    connect(&ConfigurationManager::instance(),
+            &ConfigurationManagerInterface::deviceRevocationEnded,
+            this,
+            &CallbacksHandler::slotDeviceRevokationEnded);
 }
 
 CallbacksHandler::~CallbacksHandler()
@@ -327,4 +337,23 @@ CallbacksHandler::slotDataTransferEvent(qulonglong dringId, uint codeStatus)
     }
 }
 
+void
+CallbacksHandler::slotKnownDevicesChanged(const QString& accountId,
+                                          const QMap<QString, QString>& devices)
+{
+    std::map<std::string, std::string> stdDevices;
+    for (auto item : devices.keys())
+        stdDevices[item.toStdString()] = devices.value(item).toStdString();
+    auto accountId2 = accountId.toStdString();
+    emit knownDevicesChanged(accountId2, stdDevices);
+}
+
+void
+CallbacksHandler::slotDeviceRevokationEnded(const QString& accountId,
+                                            const QString& deviceId,
+                                            const int status)
+{
+    emit deviceRevocationEnded(accountId.toStdString(), deviceId.toStdString(), status);
+}
+
 } // namespace lrc
diff --git a/src/callbackshandler.h b/src/callbackshandler.h
index 8630cab8ea696813636756ff6e64de0e0b21a3d6..f9dda0de9a3bf260f9b0f49c3a379b4bfb58228c 100644
--- a/src/callbackshandler.h
+++ b/src/callbackshandler.h
@@ -20,6 +20,8 @@
 
 // Std
 #include <memory>
+#include <string>
+#include <map>
 
 // Qt
 #include <qobject.h>
@@ -171,6 +173,25 @@ Q_SIGNALS:
     void transferStatusTimeoutExpired(long long dringId, api::datatransfer::Info info);
     void transferStatusUnjoinable(long long dringId, api::datatransfer::Info info);
 
+
+    /**
+     * Connect this signal to get when a device name changed or a device is added
+     * @param accountId interaction receiver.
+     * @param devices A map of device IDs with corresponding labels.
+     */
+    void knownDevicesChanged(std::string& accountId,
+                             std::map<std::string,std::string> devices);
+
+    /**
+     * Emit deviceRevocationEnded
+     * @param accountId
+     * @param deviceId
+     * @param status SUCCESS = 0, WRONG_PASSWORD = 1, UNKNOWN_DEVICE = 2
+     */
+    void deviceRevocationEnded(const std::string& accountId,
+                               const std::string& deviceId,
+                               const int status);
+
 private Q_SLOTS:
     /**
      * Emit newAccountMessage
@@ -291,6 +312,24 @@ private Q_SLOTS:
 
     void slotDataTransferEvent(qulonglong id, uint code);
 
+    /**
+     * Emit knownDevicesChanged
+     * @param accountId
+     * @param devices A map of device IDs and corresponding labels
+     */
+    void slotKnownDevicesChanged(const QString& accountId,
+                                 const QMap<QString, QString>& devices);
+
+     /**
+      * Emit deviceRevocationEnded
+      * @param accountId
+      * @param deviceId
+      * @param status SUCCESS = 0, WRONG_PASSWORD = 1, UNKNOWN_DEVICE = 2
+      */
+     void slotDeviceRevokationEnded(const QString& accountId,
+                                    const QString& deviceId,
+                                    const int status);
+
 private:
     const api::Lrc& parent;
 };
diff --git a/src/newaccountmodel.cpp b/src/newaccountmodel.cpp
index 142441530d7b9318184e1bb833fab08506a5a573..862d42499e70630a24e8ef3040e594710120c78d 100644
--- a/src/newaccountmodel.cpp
+++ b/src/newaccountmodel.cpp
@@ -20,12 +20,13 @@
 
 
 // LRC
-#include "api/lrc.h"
-#include "api/newcallmodel.h"
-#include "api/contactmodel.h"
-#include "api/conversationmodel.h"
 #include "api/account.h"
 #include "api/behaviorcontroller.h"
+#include "api/contactmodel.h"
+#include "api/conversationmodel.h"
+#include "api/lrc.h"
+#include "api/newcallmodel.h"
+#include "api/newdevicemodel.h"
 #include "authority/databasehelper.h"
 #include "callbackshandler.h"
 #include "database.h"
@@ -219,6 +220,7 @@ NewAccountModelPimpl::addToAccounts(const std::string& accountId)
     owner.callModel = std::make_unique<NewCallModel>(owner, callbacksHandler);
     owner.contactModel = std::make_unique<ContactModel>(owner, database, callbacksHandler);
     owner.conversationModel = std::make_unique<ConversationModel>(owner, lrc, database, callbacksHandler, behaviorController);
+    owner.deviceModel = std::make_unique<NewDeviceModel>(owner, callbacksHandler);
     owner.accountModel = &linked;
 }
 
diff --git a/src/newdevicemodel.cpp b/src/newdevicemodel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dc916a716a43b3c167a6b74f2e6c7ec6b1dfe08d
--- /dev/null
+++ b/src/newdevicemodel.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+ *   Copyright (C) 2017-2018 Savoir-faire Linux                             *
+ *   Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>           *
+ *                                                                          *
+ *   This library is free software; you can redistribute it and/or          *
+ *   modify it under the terms of the GNU Lesser General Public             *
+ *   License as published by the Free Software Foundation; either           *
+ *   version 2.1 of the License, or (at your option) any later version.     *
+ *                                                                          *
+ *   This library is distributed in the hope that it will be useful,        *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
+ *   Lesser General Public License for more details.                        *
+ *                                                                          *
+ *   You should have received a copy of the GNU General Public License      *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+#include "api/newdevicemodel.h"
+
+// std
+#include <list>
+#include <mutex>
+
+// LRC
+#include "callbackshandler.h"
+#include "dbus/configurationmanager.h"
+
+// Daemon
+#include <account_const.h>
+
+// Qt
+#include <QObject>
+
+namespace lrc
+{
+
+
+using namespace api;
+
+class NewDeviceModelPimpl: public QObject
+{
+    Q_OBJECT
+public:
+    NewDeviceModelPimpl(const NewDeviceModel& linked, const CallbacksHandler& callbacksHandler);
+    ~NewDeviceModelPimpl();
+
+    const CallbacksHandler& callbacksHandler;
+    const NewDeviceModel& linked;
+
+    std::mutex devicesMtx_;
+    std::string currentDeviceId_;
+    std::list<Device> devices_;
+public Q_SLOTS:
+    /**
+     * Listen from CallbacksHandler to get when a device name changed or a device is added
+     * @param accountId interaction receiver.
+     * @param devices A map of device IDs with corresponding labels.
+     */
+    void slotKnownDevicesChanged(const std::string& accountId,
+                                 const std::map<std::string, std::string> devices);
+
+    /**
+     * update devices_ when a device is revoked
+     * @param accountId
+     * @param deviceId
+     * @param status SUCCESS = 0, WRONG_PASSWORD = 1, UNKNOWN_DEVICE = 2
+     */
+    void slotDeviceRevocationEnded(const std::string& accountId,
+                                   const std::string& deviceId,
+                                   const int status);
+};
+
+NewDeviceModel::NewDeviceModel(const account::Info& owner, const CallbacksHandler& callbacksHandler)
+: owner(owner)
+, pimpl_(std::make_unique<NewDeviceModelPimpl>(*this, callbacksHandler))
+{ }
+
+NewDeviceModel::~NewDeviceModel() {}
+
+std::list<Device>
+NewDeviceModel::getAllDevices() const
+{
+    return pimpl_->devices_;
+}
+
+Device
+NewDeviceModel::getDevice(const std::string& id) const
+{
+    std::lock_guard<std::mutex> lock(pimpl_->devicesMtx_);
+    auto i = std::find_if(
+        pimpl_->devices_.begin(), pimpl_->devices_.end(),
+        [id](const Device& d) {
+            return d.id == id;
+        });
+
+    if (i == pimpl_->devices_.end()) return {};
+
+    return *i;
+}
+
+void
+NewDeviceModel::revokeDevice(const std::string& id, const std::string& password)
+{
+    ConfigurationManager::instance().revokeDevice(owner.id.c_str(), password.c_str(), id.c_str());
+}
+
+void
+NewDeviceModel::setCurrentDeviceName(const std::string& newName)
+{
+    MapStringString details = {};
+    details[DRing::Account::ConfProperties::RING_DEVICE_NAME] = newName.c_str();
+    ConfigurationManager::instance().setAccountDetails(owner.id.c_str(), details);
+}
+
+NewDeviceModelPimpl::NewDeviceModelPimpl(const NewDeviceModel& linked, const CallbacksHandler& callbacksHandler)
+: linked(linked)
+, callbacksHandler(callbacksHandler)
+, devices_({})
+{
+    const MapStringString aDetails = ConfigurationManager::instance().getAccountDetails(linked.owner.id.c_str());
+    currentDeviceId_ = aDetails.value(DRing::Account::ConfProperties::RING_DEVICE_ID).toStdString();
+    const MapStringString accountDevices = ConfigurationManager::instance().getKnownRingDevices(linked.owner.id.c_str());
+    auto it = accountDevices.begin();
+    while (it != accountDevices.end()) {
+        {
+            std::lock_guard<std::mutex> lock(devicesMtx_);
+            auto device = Device {
+                /* id= */it.key().toStdString(),
+                /* name= */it.value().toStdString(),
+                /* isCurrent= */it.key().toStdString() == currentDeviceId_
+            };
+            if (device.isCurrent) {
+                devices_.emplace_front(device);
+            } else {
+                devices_.emplace_back(device);
+            }
+        }
+        ++it;
+    }
+
+    connect(&callbacksHandler, &CallbacksHandler::knownDevicesChanged, this,
+            &NewDeviceModelPimpl::slotKnownDevicesChanged);
+    connect(&callbacksHandler, &CallbacksHandler::deviceRevocationEnded, this,
+            &NewDeviceModelPimpl::slotDeviceRevocationEnded);
+}
+
+NewDeviceModelPimpl::~NewDeviceModelPimpl()
+{
+    disconnect(&callbacksHandler, &CallbacksHandler::knownDevicesChanged, this,
+            &NewDeviceModelPimpl::slotKnownDevicesChanged);
+    disconnect(&callbacksHandler, &CallbacksHandler::deviceRevocationEnded, this,
+            &NewDeviceModelPimpl::slotDeviceRevocationEnded);
+}
+
+void
+NewDeviceModelPimpl::slotKnownDevicesChanged(const std::string& accountId,
+                                             const std::map<std::string, std::string> devices)
+{
+    if (accountId != linked.owner.id) return;
+    auto devicesMap = devices;
+    // Update current devices
+    std::list<std::string> updatedDevices;
+    {
+        std::lock_guard<std::mutex> lock(devicesMtx_);
+        for (auto& device : devices_) {
+            if (devicesMap.find(device.id) != devicesMap.end()) {
+                if (device.name != devicesMap[device.id]) {
+                    updatedDevices.emplace_back(device.id);
+                    device.name = devicesMap[device.id];
+                }
+                devicesMap.erase(device.id);
+            }
+        }
+    }
+    for (const auto& device : updatedDevices)
+        emit linked.deviceUpdated(device);
+
+    // Add new devices
+    std::list<std::string> addedDevices;
+    {
+        std::lock_guard<std::mutex> lock(devicesMtx_);
+        auto it = devicesMap.begin();
+        while (it != devicesMap.end()) {
+            devices_.emplace_back(Device {
+                /* id= */it->first,
+                /* name= */it->second,
+                /* isCurrent= */false
+            });
+            addedDevices.emplace_back(it->first);
+            ++it;
+        }
+    }
+    for (const auto& device : addedDevices)
+        emit linked.deviceAdded(device);
+}
+
+
+void
+NewDeviceModelPimpl::slotDeviceRevocationEnded(const std::string& accountId,
+                                               const std::string& deviceId,
+                                               const int status)
+{
+    if (accountId != linked.owner.id) return;
+    if (status == 0) {
+        std::lock_guard<std::mutex> lock(devicesMtx_);
+        auto it = std::find_if(
+            devices_.begin(), devices_.end(),
+            [deviceId](const Device& d) {
+                return d.id == deviceId;
+            });
+
+        if (it != devices_.end())
+            devices_.erase(it);
+    }
+
+    switch (status) {
+    case 0:
+        emit linked.deviceRevoked(deviceId, NewDeviceModel::Status::SUCCESS);
+        break;
+    case 1:
+        emit linked.deviceRevoked(deviceId, NewDeviceModel::Status::WRONG_PASSWORD);
+        break;
+    case 2:
+        emit linked.deviceRevoked(deviceId, NewDeviceModel::Status::UNKNOWN_DEVICE);
+        break;
+    default:
+        break;
+    }
+}
+
+} // namespace lrc
+
+#include "newdevicemodel.moc"
+#include "api/moc_newdevicemodel.cpp"
diff --git a/src/qtwrapper/configurationmanager_wrap.h b/src/qtwrapper/configurationmanager_wrap.h
index 5846d5f9cdcaa47c55e3c414ab9dff366ee9b67d..3d4e0ca6c6abbf4506921810358f9627dd357491 100644
--- a/src/qtwrapper/configurationmanager_wrap.h
+++ b/src/qtwrapper/configurationmanager_wrap.h
@@ -566,6 +566,10 @@ public Q_SLOTS: // METHODS
         DRing::removeContact(accountId.toStdString(), uri.toStdString(), ban);
     }
 
+    void revokeDevice(const QString &accountId, const QString &password, const QString &deviceId) {
+        DRing::revokeDevice(accountId.toStdString(), password.toStdString(), deviceId.toStdString());
+    }
+
     void addContact(const QString &accountId, const QString &uri) {
         DRing::addContact(accountId.toStdString(), uri.toStdString());
     }
@@ -676,6 +680,7 @@ Q_SIGNALS: // SIGNALS
     void contactAdded(const QString &accountID, const QString &uri, bool banned);
     void contactRemoved(const QString &accountID, const QString &uri, bool banned);
     void dataTransferEvent(qulonglong transfer_id, uint code);
+    void deviceRevocationEnded(const QString& accountId, const QString& deviceId, int status);
 };
 
 namespace org { namespace ring { namespace Ring {
diff --git a/test/mocks/configurationmanager_mock.h b/test/mocks/configurationmanager_mock.h
index f23d418b5a8b9fc5d924fb3e40a940fd464e2aea..76abe21be97ea2985288d871cdeecede12c5a9d6 100644
--- a/test/mocks/configurationmanager_mock.h
+++ b/test/mocks/configurationmanager_mock.h
@@ -53,6 +53,7 @@ private:
     QMap<QString, VectorMapStringString> accountToContactsMap;
     QStringList availableContacts_;
     std::mutex contactsMtx_;
+    QMap<QString, QMap<QString, QString>> devices;
 
 public:
 
@@ -86,11 +87,22 @@ public:
               }
           }
           accountToContactsMap.insert(account, contacts);
+          // Init devices
+          MapStringString devicesForAccount;
+          devicesForAccount["device0"] = "pc";
+          if (account.toStdString() == "ring3")
+            devicesForAccount["device1"] = "tel";
+          devices[account] = devicesForAccount;
       }
    }
 
    ~ConfigurationManagerInterface() {}
 
+   void addNewDevice(const QString& accountId, const QString& deviceId, const QString& name) {
+       devices[accountId][deviceId] = name;
+       emit knownDevicesChanged(accountId, devices[accountId]);
+   }
+
    void emitIncomingAccountMessage(const QString& accountId, const QString& from, const QMap<QString,QString>& payloads)
    {
        emit incomingAccountMessage(accountId, from, payloads);
@@ -137,9 +149,7 @@ public Q_SLOTS: // METHODS
 
     MapStringString getKnownRingDevices(const QString& accountId)
     {
-        Q_UNUSED(accountId)
-        MapStringString temp;
-        return temp;
+        return devices[accountId];
     }
 
     bool lookupName(const QString& accountId, const QString& nameServiceURL, const QString& name)
@@ -174,6 +184,7 @@ public Q_SLOTS: // METHODS
         } else {
             result.insert("Account.type", "SIP");
         }
+        result.insert("Account.deviceID", "device0");
         return result;
     }
 
@@ -183,6 +194,7 @@ public Q_SLOTS: // METHODS
         accountList << QString("ring0"); // Used in conversationmodeltester
         accountList << QString("ring1"); // Used in contactmodeltester
         accountList << QString("ring2"); // Used in newcallmodeltester
+        accountList << QString("ring3"); // Used in newdevicemodeltester
         accountList << QString("sip0");
         accountList << QString("sip1");
         return accountList;
@@ -448,8 +460,13 @@ public Q_SLOTS: // METHODS
 
     void setAccountDetails(const QString& accountId, MapStringString details)
     {
-        Q_UNUSED(accountId)
-        Q_UNUSED(details)
+        if (accountId.toStdString() == "ring3") {
+            // testSetCurrentDeviceName
+            if (details.contains(DRing::Account::ConfProperties::RING_DEVICE_NAME)) {
+                devices["ring3"]["device0"] = details[DRing::Account::ConfProperties::RING_DEVICE_NAME];
+                emit knownDevicesChanged(accountId, devices[accountId]);
+            }
+        }
     }
 
     void setAccountsOrder(const QString& order)
@@ -648,6 +665,19 @@ public Q_SLOTS: // METHODS
         emit contactRemoved(accountId, uri, ban);
     }
 
+    void revokeDevice(const QString &accountId, const QString &password, const QString &deviceId) {
+        if (password == "") {
+            if (devices[accountId].contains(deviceId)) {
+                devices[accountId].remove(deviceId);
+                emit deviceRevocationEnded(accountId, deviceId, 0);
+            } else {
+                emit deviceRevocationEnded(accountId, deviceId, 2);
+            }
+        } else {
+            emit deviceRevocationEnded(accountId, deviceId, 1);
+        }
+    }
+
     void addContact(const QString &accountId, const QString &uri)
     {
         if (getAccountList().indexOf(accountId) == -1) return;
@@ -803,6 +833,7 @@ Q_SIGNALS: // SIGNALS
    void contactAdded(const QString &accountId, const QString &uri, bool banned);
    void contactRemoved(const QString &accountId, const QString &uri, bool banned);
    void dataTransferEvent(uint64_t transfer_id, uint32_t code);
+   void deviceRevocationEnded(const QString& accountId, const QString& deviceId, int status);
 };
 
 namespace org {
diff --git a/test/newdevicemodeltester.cpp b/test/newdevicemodeltester.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4a585944f84fcb95f65d1e89ec2f72a6fce7d18a
--- /dev/null
+++ b/test/newdevicemodeltester.cpp
@@ -0,0 +1,197 @@
+/*
+ *  Copyright (C) 2017-2018 Savoir-faire Linux Inc.
+ *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+#include "newdevicemodeltester.h"
+
+// std
+#include <string>
+
+// Qt
+#include "utils/waitforsignalhelper.h"
+
+// Lrc
+#include <api/newaccountmodel.h>
+#include <api/newdevicemodel.h>
+#include <dbus/configurationmanager.h>
+
+
+namespace ring
+{
+namespace test
+{
+
+CPPUNIT_TEST_SUITE_REGISTRATION(NewDeviceModelTester);
+
+NewDeviceModelTester::NewDeviceModelTester()
+: lrc_(new lrc::api::Lrc())
+, accInfo_(lrc_->getAccountModel().getAccountInfo("ring3"))
+{
+
+}
+
+void
+NewDeviceModelTester::setUp()
+{
+
+}
+
+void
+NewDeviceModelTester::testGetAllDevices()
+{
+    // See mocked ConfigurationManager::getKnownRingDevices() and getAccountDetails()
+    auto devices = accInfo_.deviceModel->getAllDevices();
+    // Here, we should have 2 devices (device0 pc) and (device1 tel)
+    CPPUNIT_ASSERT_EQUAL(static_cast<int>(devices.size()), 2);
+    auto device0 = devices.front();
+    CPPUNIT_ASSERT_EQUAL(device0.isCurrent, true);
+    CPPUNIT_ASSERT_EQUAL(device0.id, std::string("device0"));
+    CPPUNIT_ASSERT_EQUAL(device0.name, std::string("pc"));
+    auto device1 = devices.back();
+    CPPUNIT_ASSERT_EQUAL(device1.isCurrent, false);
+    CPPUNIT_ASSERT_EQUAL(device1.id, std::string("device1"));
+    CPPUNIT_ASSERT_EQUAL(device1.name, std::string("tel"));
+}
+
+void
+NewDeviceModelTester::testGetValidDevice()
+{
+    // device0 defined in mocked ConfigurationManager
+    auto device0 = accInfo_.deviceModel->getDevice("device0");
+    CPPUNIT_ASSERT_EQUAL(device0.isCurrent, true);
+    CPPUNIT_ASSERT_EQUAL(device0.id, std::string("device0"));
+    CPPUNIT_ASSERT_EQUAL(device0.name, std::string("pc"));
+}
+
+void
+NewDeviceModelTester::testGetInvalidDevice()
+{
+    // notADevice not defined in mocked ConfigurationManager
+    auto device0 = accInfo_.deviceModel->getDevice("notADevice");
+    CPPUNIT_ASSERT_EQUAL(device0.id, std::string(""));
+}
+
+void
+NewDeviceModelTester::testNewDeviceAdded()
+{
+    // this will add a new device for ring3 (see mock)
+    ConfigurationManager::instance().addNewDevice("ring3", "device2", "tv");
+    // Wait for deviceAdded
+    WaitForSignalHelper(*accInfo_.deviceModel,
+        SIGNAL(deviceAdded(const std::string& id))).wait(1000);
+    auto device0 = accInfo_.deviceModel->getDevice("device2");
+    CPPUNIT_ASSERT_EQUAL(device0.isCurrent, false);
+    CPPUNIT_ASSERT_EQUAL(device0.id, std::string("device2"));
+    CPPUNIT_ASSERT_EQUAL(device0.name, std::string("tv"));
+    // Revoke device for other tests
+    // NOTE: should be removed when test will not depends from each others
+    // See mock
+    ConfigurationManager::instance().revokeDevice("ring3", "", "device2");
+}
+
+void
+NewDeviceModelTester::testRevokeDevice()
+{
+    // this will add a new device for ring3 (see mock)
+    ConfigurationManager::instance().addNewDevice("ring3", "device2", "tv");
+    // Wait for deviceAdded
+    WaitForSignalHelper(*accInfo_.deviceModel,
+        SIGNAL(deviceAdded(const std::string& id))).wait(1000);
+    // Then revoke device
+    accInfo_.deviceModel->revokeDevice("device2", "");  // empty password = correct
+    // Wait for deviceAdded
+    WaitForSignalHelper(*accInfo_.deviceModel,
+        SIGNAL(deviceRevoked(const std::string& id,
+                            const lrc::api::NewDeviceModel::Status status)))
+        .wait(1000);
+    // Should not exists anymore
+    auto device2 = accInfo_.deviceModel->getDevice("device2");
+    CPPUNIT_ASSERT_EQUAL(device2.id, std::string(""));
+}
+
+void
+NewDeviceModelTester::testRevokeDeviceInvalidDevice()
+{
+    // this will add a new device for ring3 (see mock)
+    ConfigurationManager::instance().addNewDevice("ring3", "device2", "tv");
+    // Wait for deviceAdded
+    WaitForSignalHelper(*accInfo_.deviceModel,
+        SIGNAL(deviceAdded(const std::string& id))).wait(1000);
+    // Then revoke device
+    accInfo_.deviceModel->revokeDevice("device3", "");  // empty password = correct
+    // Wait for deviceAdded
+    WaitForSignalHelper(*accInfo_.deviceModel,
+        SIGNAL(deviceRevoked(const std::string& id,
+                            const lrc::api::NewDeviceModel::Status status)))
+        .wait(1000);
+    // device2 still exists
+    auto device0 = accInfo_.deviceModel->getDevice("device2");
+    CPPUNIT_ASSERT_EQUAL(device0.id, std::string("device2"));
+    // Revoke device for other tests
+    // NOTE: should be removed when test will not depends from each others
+    // See mock
+    ConfigurationManager::instance().revokeDevice("ring3", "", "device2");
+}
+
+void
+NewDeviceModelTester::testRevokeDeviceInvalidPassword()
+{
+    // this will add a new device for ring3 (see mock)
+    ConfigurationManager::instance().addNewDevice("ring3", "device2", "tv");
+    // Wait for deviceAdded
+    WaitForSignalHelper(*accInfo_.deviceModel,
+        SIGNAL(deviceAdded(const std::string& id))).wait(1000);
+    // Then revoke device
+    accInfo_.deviceModel->revokeDevice("device2", "notAPass");  // !empty password = incorrect
+    // Wait for deviceAdded
+    WaitForSignalHelper(*accInfo_.deviceModel,
+        SIGNAL(deviceRevoked(const std::string& id,
+                            const lrc::api::NewDeviceModel::Status status)))
+        .wait(1000);
+    // device2 still exists
+    auto device0 = accInfo_.deviceModel->getDevice("device2");
+    CPPUNIT_ASSERT_EQUAL(device0.id, std::string("device2"));
+    // Revoke device for other tests
+    // NOTE: should be removed when test will not depends from each others
+    // See mock
+    ConfigurationManager::instance().revokeDevice("ring3", "", "device2");
+}
+
+void
+NewDeviceModelTester::testSetCurrentDeviceName()
+{
+    // Will change the name of device0
+    accInfo_.deviceModel->setCurrentDeviceName("NewDeviceName");
+    // Will call mocked ConfigurationManager::setAccountDetails()
+    // Because known devices changed, NewDeviceModel::deviceUpdated will be emitted
+    WaitForSignalHelper(*accInfo_.deviceModel,
+        SIGNAL(deviceUpdated(const std::string& id))).wait(1000);
+    // device0 should have a new name now.
+    auto device0 = accInfo_.deviceModel->getDevice("device0");
+    CPPUNIT_ASSERT_EQUAL(device0.isCurrent, true);
+    CPPUNIT_ASSERT_EQUAL(device0.id, std::string("device0"));
+    CPPUNIT_ASSERT_EQUAL(device0.name, std::string("NewDeviceName"));
+}
+
+void
+NewDeviceModelTester::tearDown()
+{
+    accInfo_.deviceModel->setCurrentDeviceName("pc");
+}
+
+} // namespace test
+} // namespace ring
diff --git a/test/newdevicemodeltester.h b/test/newdevicemodeltester.h
new file mode 100644
index 0000000000000000000000000000000000000000..be1ee76eaa6fb158992fb478ad2e8320cbd5ecae
--- /dev/null
+++ b/test/newdevicemodeltester.h
@@ -0,0 +1,103 @@
+/*
+ *  Copyright (C) 2017-2018 Savoir-faire Linux Inc.
+ *
+ *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+#pragma once
+
+// cppunit
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+// std
+#include <memory>
+
+// Qt
+#include <QObject>
+
+// lrc
+#include "api/lrc.h"
+#include "api/account.h"
+
+namespace ring
+{
+namespace test
+{
+
+class NewDeviceModelTester :  public CppUnit::TestFixture {
+    CPPUNIT_TEST_SUITE(NewDeviceModelTester);
+    CPPUNIT_TEST(testGetAllDevices);
+    CPPUNIT_TEST(testGetValidDevice);
+    CPPUNIT_TEST(testGetInvalidDevice);
+    CPPUNIT_TEST(testNewDeviceAdded);
+    CPPUNIT_TEST(testRevokeDevice);
+    CPPUNIT_TEST(testRevokeDeviceInvalidDevice);
+    CPPUNIT_TEST(testRevokeDeviceInvalidPassword);
+    CPPUNIT_TEST(testSetCurrentDeviceName);
+    CPPUNIT_TEST_SUITE_END();
+
+public:
+    NewDeviceModelTester();
+    /**
+     * Method automatically called before each test by CppUnit
+     */
+    void setUp();
+    /**
+     * Retrieve all devices of an account
+     */
+    void testGetAllDevices();
+    /**
+     * Test getting an existing device
+     */
+    void testGetValidDevice();
+    /**
+     * Test getting a non existing device
+     */
+    void testGetInvalidDevice();
+    /**
+     * Test new device added
+     */
+    void testNewDeviceAdded();
+    /**
+     * Test to remove a device (valid device, valid password)
+     */
+    void testRevokeDevice();
+    /**
+     * Test to remove a device (invalid device, valid password)
+     */
+    void testRevokeDeviceInvalidDevice();
+    /**
+     * Test to remove a device (valid device, invalid password)
+     */
+    void testRevokeDeviceInvalidPassword();
+    /**
+     * Test to change the current device name
+     */
+    void testSetCurrentDeviceName();
+    /**
+     * Method automatically called after each test by CppUnit
+     */
+    void tearDown();
+
+protected:
+    std::unique_ptr<lrc::api::Lrc> lrc_;
+    const lrc::api::account::Info& accInfo_;
+};
+
+} // namespace test
+} // namespace ring