From 49499411a2ba92f928442f27ca34ae9aee2f80ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?L=C3=A9o=20Banno-Cloutier?=
 <leo.banno-cloutier@savoirfairelinux.com>
Date: Fri, 28 Jul 2023 17:35:37 -0400
Subject: [PATCH] datastore: reduce DAO abstraction to remove complexity

StatementList and StatementElement were an attempt at creating our own
ORM for JAMS. However, doing an database query was very verbose on the
caller side, and if the 1st, 2nd or 4th field of StatementElement was
user input, we would be vulnerable to SQL injections. This patch
hardcoded the SQL queries in the DAO, making it easier on SQL expert to
audit the queries.

Change-Id: I4699bf3146a077efe03efd178b6190dfe60c72e9
---
 .../jami/jams/ad/connector/ADConnector.java   |   5 +-
 .../connector/service/UserProfileService.java |   9 +-
 .../jami/jams/authmodule/TokenController.java |   1 -
 .../authmodule/UserAuthenticationModule.java  |  36 ++--
 .../net/jami/datastore/dao/AbstractDao.java   |  98 +++++++----
 .../net/jami/datastore/dao/ContactDao.java    |  48 ++----
 .../net/jami/datastore/dao/DeviceDao.java     |  70 +++-----
 .../java/net/jami/datastore/dao/GroupDao.java |  82 +++------
 .../java/net/jami/datastore/dao/JwtDao.java   |  71 --------
 .../net/jami/datastore/dao/PolicyDao.java     |  92 ++++------
 .../net/jami/datastore/dao/SystemDao.java     |  40 ++---
 .../java/net/jami/datastore/dao/UserDao.java  |  98 ++++-------
 .../datastore/dao/UserGroupMappingsDao.java   |  84 ++++-----
 .../jami/datastore/dao/UserProfileDao.java    | 116 ++++++++-----
 .../net/jami/datastore/main/DataStore.java    |  69 ++------
 .../java/net/jami/datastore/dao/DAOTest.java  |  20 +--
 .../jami/jams/nameserver/LocalNameServer.java |  28 ++-
 .../ca/workers/csr/builders/UserBuilder.java  |  21 ++-
 .../jami/jams/ca/workers/ocsp/OCSPWorker.java |   2 +-
 .../common/dao/DeleteStatementBuilder.java    |  61 -------
 .../common/dao/SelectStatementBuilder.java    |  72 --------
 .../jams/common/dao/StatementConstraints.java |  34 ----
 .../jams/common/dao/StatementElement.java     |  39 -----
 .../jami/jams/common/dao/StatementList.java   |  40 -----
 .../common/dao/UpdateStatementBuilder.java    |  65 -------
 .../jams/common/objects/user/UserProfile.java |  20 +--
 .../common/objects/contacts/ContactTest.java  |   4 +-
 .../java/net/jami/jams/server/Server.java     |   2 +-
 .../core/workflows/RegisterDeviceFlow.java    |  61 ++-----
 .../core/workflows/RevokeDeviceFlow.java      |  15 +-
 .../server/core/workflows/RevokeUserFlow.java |   7 +-
 .../jams/server/servlets/LoginServlet.java    |  16 +-
 .../api/admin/contacts/ContactServlet.java    |  44 ++---
 .../api/admin/devices/DeviceServlet.java      |  34 ++--
 .../api/admin/devices/DevicesServlet.java     |   6 +-
 .../directory/DirectoryEntryServlet.java      |  26 +--
 .../api/admin/group/GroupServlet.java         |  48 +-----
 .../api/admin/group/GroupsServlet.java        |   2 +-
 .../api/admin/group/PolicyProfileServlet.java |  38 ++---
 .../api/admin/group/PolicyServlet.java        |  46 +----
 .../api/admin/group/UserGroupServlet.java     |  27 +--
 .../api/admin/users/UserGroupsServlet.java    |  10 +-
 .../servlets/api/admin/users/UserServlet.java | 160 +++++++++---------
 .../api/admin/users/UsersServlet.java         |   4 +-
 .../api/auth/contacts/ContactServlet.java     |  54 +++---
 .../api/auth/device/DeviceServlet.java        |  48 +++---
 .../api/auth/device/DevicesServlet.java       |   6 +-
 .../auth/directory/DirectoryEntryServlet.java |  10 +-
 .../directory/SearchDirectoryServlet.java     | 112 +++++-------
 .../auth/policyData/PolicyDataServlet.java    |   4 +-
 .../servlets/api/auth/user/UserServlet.java   |  59 +++----
 .../api/install/StartInstallServlet.java      |  13 +-
 .../server/servlets/filters/DApiFilter.java   |  31 ++--
 .../server/servlets/filters/FilterUtils.java  |  15 +-
 .../server/servlets/x509/OCSPServlet.java     |  78 +++------
 .../server/startup/CryptoEngineLoader.java    |  23 +--
 .../connector/service/UserProfileService.java |  10 +-
 pom.xml                                       |   6 +
 58 files changed, 725 insertions(+), 1615 deletions(-)
 delete mode 100644 datastore/src/main/java/net/jami/datastore/dao/JwtDao.java
 delete mode 100644 jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java
 delete mode 100644 jams-common/src/main/java/net/jami/jams/common/dao/SelectStatementBuilder.java
 delete mode 100644 jams-common/src/main/java/net/jami/jams/common/dao/StatementConstraints.java
 delete mode 100644 jams-common/src/main/java/net/jami/jams/common/dao/StatementElement.java
 delete mode 100644 jams-common/src/main/java/net/jami/jams/common/dao/StatementList.java
 delete mode 100644 jams-common/src/main/java/net/jami/jams/common/dao/UpdateStatementBuilder.java

diff --git a/ad-connector/src/main/java/net/jami/jams/ad/connector/ADConnector.java b/ad-connector/src/main/java/net/jami/jams/ad/connector/ADConnector.java
index 60d69108..2d8ea030 100644
--- a/ad-connector/src/main/java/net/jami/jams/ad/connector/ADConnector.java
+++ b/ad-connector/src/main/java/net/jami/jams/ad/connector/ADConnector.java
@@ -72,9 +72,8 @@ public class ADConnector implements AuthenticationSource {
         endpoint.setUserAccountName(
                 ADConnector.settings.getRealm()
                         + "\\"
-                        + settings
-                                .getUsername()); // * You can use the user's Distinguished Name as
-                                                 // well
+                        + settings.getUsername()); // * You can use the user's Distinguished Name as
+        // well
         endpoint.setPassword(settings.getPassword());
         return endpoint;
     }
diff --git a/ad-connector/src/main/java/net/jami/jams/ad/connector/service/UserProfileService.java b/ad-connector/src/main/java/net/jami/jams/ad/connector/service/UserProfileService.java
index 1e1bf0d7..95c6bb00 100644
--- a/ad-connector/src/main/java/net/jami/jams/ad/connector/service/UserProfileService.java
+++ b/ad-connector/src/main/java/net/jami/jams/ad/connector/service/UserProfileService.java
@@ -43,8 +43,6 @@ import lombok.extern.slf4j.Slf4j;
 
 import net.jami.datastore.main.DataStore;
 import net.jami.jams.ad.connector.ADConnector;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.UserProfile;
 
 import java.util.*;
@@ -138,12 +136,7 @@ public class UserProfileService {
                             .map(UserProfileService::profileFromResponse)
                             .collect(Collectors.toList());
             for (UserProfile p : profilesFromResponse) {
-                StatementList statementList = new StatementList();
-                StatementElement st = new StatementElement("username", "=", p.getUsername(), "");
-                statementList.addStatement(st);
-
-                if (dataStore.getUserProfileDao().getObjects(statementList).isEmpty())
-                    dataStore.getUserProfileDao().storeObject(p);
+                dataStore.getUserProfileDao().insertIfNotExists(p);
             }
 
             return profilesFromResponse;
diff --git a/authentication-module/src/main/java/net/jami/jams/authmodule/TokenController.java b/authentication-module/src/main/java/net/jami/jams/authmodule/TokenController.java
index 27ee8f41..30eef877 100644
--- a/authentication-module/src/main/java/net/jami/jams/authmodule/TokenController.java
+++ b/authentication-module/src/main/java/net/jami/jams/authmodule/TokenController.java
@@ -72,7 +72,6 @@ public class TokenController {
         SignedJWT signedJWT = new SignedJWT(jwsHeader, jwtClaims);
         try {
             signedJWT.sign(new RSASSASigner(signingKey));
-            UserAuthenticationModule.datastore.getJwtDao().storeObject(signedJWT);
             authTokenResponse.setAccess_token(signedJWT.serialize());
             authTokenResponse.setExpires_in(30 * 60L);
             authTokenResponse.setToken_type("Bearer");
diff --git a/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java b/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java
index 89a515a4..0f3dc031 100644
--- a/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java
+++ b/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java
@@ -33,8 +33,6 @@ import net.jami.jams.common.authmodule.AuthModuleKey;
 import net.jami.jams.common.authmodule.AuthTokenResponse;
 import net.jami.jams.common.authmodule.AuthenticationModule;
 import net.jami.jams.common.cryptoengineapi.CertificateAuthority;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.jami.NameServer;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.User;
@@ -55,6 +53,7 @@ import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPublicKey;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 
 @Slf4j
@@ -159,11 +158,8 @@ public class UserAuthenticationModule implements AuthenticationModule {
     public AuthTokenResponse authenticateUser(String username, String password) {
         AuthTokenResponse res = null;
         String hashPass = "";
-        if (datastore.userExists(username)) {
-            StatementList statementList = new StatementList();
-            StatementElement statementElement = new StatementElement("username", "=", username, "");
-            statementList.addStatement(statementElement);
-            User user = datastore.getUserDao().getObjects(statementList).get(0);
+        if (datastore.getUserDao().getByUsername(username).isPresent()) {
+            User user = datastore.getUserDao().getByUsername(username).orElseThrow();
             if ((user.getUserType() == AuthenticationSourceType.LOCAL))
                 hashPass = PasswordUtil.hashPassword(password, Base64.decodeBase64(user.getSalt()));
             else hashPass = password;
@@ -174,12 +170,11 @@ public class UserAuthenticationModule implements AuthenticationModule {
                             .authenticate(username, hashPass))
                 return tokenController.getToken(user, null);
         }
-        // The second case is much more violent, because we don't know in advance "where" this user
-        // comes
-        // from, so we have to infer (this is only really true for "users", all others are usually
-        // pre-marked)
-        // This is also the case when we store the user into the DAO - because he never existed
-        // before.
+        // The second case is much more violent, because we don't know in
+        // advance "where" this user comes from, so we have to infer
+        // (this is only really true for "users", all others are usually pre-marked)
+        // This is also the case when we store the user into the DAO
+        // - because he never existed before.
         for (AuthModuleKey key : authenticationSources.keySet()) {
             if (authenticationSources.get(key).authenticate(username, password)) {
                 User user = new User();
@@ -211,10 +206,7 @@ public class UserAuthenticationModule implements AuthenticationModule {
             if (crl.getRevokedCertificate(clientCert.getSerialNumber()) != null) return null;
             String username = X509Utils.extractDNFromCertificate(clientCert).get("CN");
             // We need to extract the deviceId from the certificate
-            StatementList statementList = new StatementList();
-            StatementElement statementElement = new StatementElement("username", "=", username, "");
-            statementList.addStatement(statementElement);
-            User user = datastore.getUserDao().getObjects(statementList).get(0);
+            User user = datastore.getUserDao().getByUsername(username).orElseThrow();
             return tokenController.getToken(
                     user, X509Utils.extractDNFromCertificate(deviceCert).get("UID"));
         } catch (Exception e) {
@@ -261,14 +253,8 @@ public class UserAuthenticationModule implements AuthenticationModule {
 
     @Override
     public char[] getOTP(String username) {
-        if (datastore.userExists(username)) {
-            StatementList statementList = new StatementList();
-            StatementElement statementElement = new StatementElement("username", "=", username, "");
-            statementList.addStatement(statementElement);
-            User user = datastore.getUserDao().getObjects(statementList).get(0);
-            return (user.getPassword()).toCharArray();
-        }
-        return new char[0];
+        Optional<User> user = datastore.getUserDao().getByUsername(username);
+        return user.map(u -> u.getPassword().toCharArray()).orElse(new char[0]);
     }
 
     @Override
diff --git a/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java b/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java
index 0e7f8826..bd3cee61 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java
@@ -27,89 +27,113 @@ import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 
 import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.DeleteStatementBuilder;
-import net.jami.jams.common.dao.SelectStatementBuilder;
-import net.jami.jams.common.dao.StatementConstraints;
-import net.jami.jams.common.dao.StatementList;
-import net.jami.jams.common.dao.UpdateStatementBuilder;
 import net.jami.jams.common.dao.connectivity.SQLConnection;
+import net.jami.jams.common.serialization.database.DatabaseObject;
 
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 @Slf4j
 public abstract class AbstractDao<T> {
 
     @Getter @Setter private String tableName;
-    @Getter @Setter private Class<T> tClass;
+    @Getter @Setter protected Class<T> tClass;
 
     public abstract boolean storeObject(T object);
 
-    public List<T> getObjects(StatementList constraints) {
-        List<T> result = new ArrayList<>();
+    protected ResultSet executeQuery(String query) {
+        return executeQuery(query, new ArrayList<>());
+    }
+
+    protected ResultSet executeQuery(String query, String param) {
+        return executeQuery(query, List.of(param));
+    }
+
+    protected ResultSet executeQuery(String query, List<String> params) {
         SQLConnection connection = DataStore.connectionPool.getConnection();
         try {
-            PreparedStatement ps =
-                    SelectStatementBuilder.buildStatement(tableName, constraints, null, connection);
-            ResultSet rs = ps.executeQuery();
-            while (rs.next()) {
-                result.add(tClass.getConstructor(ResultSet.class).newInstance(rs));
+            PreparedStatement ps = connection.getConnection().prepareStatement(query);
+            for (int i = 0; i < params.size(); i++) {
+                ps.setString(i + 1, params.get(i));
             }
-            return result;
+            return ps.executeQuery();
         } catch (Exception e) {
-            log.error("An error has occurred while trying to fetch an object: " + e);
+            log.error("An error has occurred while trying to fetch an object:");
+            e.printStackTrace();
             return null;
         } finally {
             DataStore.connectionPool.returnConnection(connection);
         }
     }
 
-    public List<T> getObjects(
-            StatementList constraints, StatementConstraints statementConstraints) {
+    protected Optional<T> getFirstObjectFromResultSet(ResultSet rs) {
+        try {
+            if (rs.next()) {
+                T obj = tClass.getConstructor(ResultSet.class).newInstance(rs);
+                rs.close();
+                return Optional.of(obj);
+            }
+        } catch (Exception e) {
+            log.error(
+                    "An error has occurred while trying to get the first result from the database:");
+            e.printStackTrace();
+        }
+
+        return Optional.empty();
+    }
+
+    protected List<T> getObjectsFromResultSet(ResultSet rs) {
         List<T> result = new ArrayList<>();
-        SQLConnection connection = DataStore.connectionPool.getConnection();
+
         try {
-            PreparedStatement ps =
-                    SelectStatementBuilder.buildStatement(
-                            tableName, constraints, statementConstraints, connection);
-            ResultSet rs = ps.executeQuery();
             while (rs.next()) {
                 result.add(tClass.getConstructor(ResultSet.class).newInstance(rs));
             }
-            return result;
+
+            rs.close();
         } catch (Exception e) {
-            log.error("An error has occurred while trying to fetch a device: " + e);
-            return null;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
+            log.error("An error has occurred while trying to get results from the database:");
+            e.printStackTrace();
         }
+
+        return result;
     }
 
-    public boolean updateObject(StatementList update, StatementList constraints) {
+    protected boolean executeUpdate(String query, List<String> params) {
         SQLConnection connection = DataStore.connectionPool.getConnection();
+
         try {
-            PreparedStatement ps =
-                    UpdateStatementBuilder.buildStatement(
-                            tableName, update, constraints, connection);
-            return ps.execute();
+            PreparedStatement ps = connection.getConnection().prepareStatement(query);
+
+            for (int i = 0; i < params.size(); i++) {
+                ps.setString(i + 1, params.get(i));
+            }
+
+            return ps.executeUpdate() != 0;
         } catch (Exception e) {
-            log.error("An error has occurred while trying to fetch a device: " + e);
+            log.error("An error has occurred while trying to execute update:");
+            e.printStackTrace();
             return false;
         } finally {
             DataStore.connectionPool.returnConnection(connection);
         }
     }
 
-    public boolean deleteObject(StatementList delete) {
+    protected boolean executeInsert(String query, DatabaseObject object) {
         SQLConnection connection = DataStore.connectionPool.getConnection();
+
         try {
-            PreparedStatement ps =
-                    DeleteStatementBuilder.buildStatement(tableName, delete, connection);
+            PreparedStatement ps = connection.getConnection().prepareStatement(query);
+
+            ps = object.getInsert(ps);
+
             return ps.executeUpdate() != 0;
         } catch (Exception e) {
-            log.error("An error has occurred while trying to fetch a device: " + e);
+            log.error("An error has occurred while trying to execute insert:");
+            e.printStackTrace();
             return false;
         } finally {
             DataStore.connectionPool.returnConnection(connection);
diff --git a/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java b/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java
index 63e839c4..c42385e1 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java
@@ -26,12 +26,11 @@ package net.jami.datastore.dao;
 import lombok.extern.slf4j.Slf4j;
 
 import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.contacts.Contact;
 
 import java.sql.PreparedStatement;
-import java.sql.SQLException;
+import java.sql.ResultSet;
 import java.util.List;
 
 @Slf4j
@@ -42,24 +41,18 @@ public class ContactDao extends AbstractDao<Contact> {
         this.setTClass(Contact.class);
     }
 
+    public List<Contact> getByOwner(String owner) {
+        ResultSet rs = executeQuery("SELECT * FROM contacts WHERE owner = ?", owner);
+        return getObjectsFromResultSet(rs);
+    }
+
     // Not used because the strategy here is different.
     @Override
     public boolean storeObject(Contact object) {
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            String insert =
-                    "INSERT INTO contacts (owner, uri, displayName, `timestamp`, status) VALUES "
-                            + "(?, ?, ?, ?, ?)";
-            PreparedStatement ps = connection.getConnection().prepareStatement(insert);
-            object.getInsert(ps);
-            ps.executeQuery();
-            return true;
-        } catch (Exception e) {
-            log.error("Could not update contacts!");
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+        String query =
+                "INSERT INTO contacts (owner, uri, displayName, timestamp, status)"
+                        + " VALUES (?, ?, ?, ?, ?)";
+        return executeInsert(query, object);
     }
 
     public boolean storeContactList(List<Contact> contactList) {
@@ -86,23 +79,8 @@ public class ContactDao extends AbstractDao<Contact> {
         }
     }
 
-    @Override
-    public boolean deleteObject(StatementList constraints) {
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement("DELETE FROM contacts WHERE owner = ? AND uri = ?");
-            ps.setString(1, constraints.getStatements().get(0).getValue());
-            ps.setString(2, constraints.getStatements().get(1).getValue());
-            return ps.executeUpdate() != 0;
-        } catch (SQLException e) {
-            log.error("Could not delete contact: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public boolean deleteObject(String owner, String uri) {
+        String query = "DELETE FROM contacts WHERE owner = ? AND uri = ?";
+        return executeUpdate(query, List.of(owner, uri));
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java b/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java
index fb131082..79b085de 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java
@@ -25,12 +25,11 @@ package net.jami.datastore.dao;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.StatementList;
-import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.devices.Device;
 
-import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.List;
+import java.util.Optional;
 
 @Slf4j
 public class DeviceDao extends AbstractDao<Device> {
@@ -40,51 +39,30 @@ public class DeviceDao extends AbstractDao<Device> {
         this.setTClass(Device.class);
     }
 
-    @Override
-    public boolean storeObject(Device object) {
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "INSERT INTO devices "
-                                            + "(deviceId, owner, displayName, certificate, privatekey) "
-                                            + "VALUES "
-                                            + "(?, ?, ?, ?, ?)");
-            ps = object.getInsert(ps);
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to store a user: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public List<Device> getByOwner(String owner) {
+        ResultSet rs = executeQuery("SELECT * FROM devices WHERE owner = ?", List.of(owner));
+        return getObjectsFromResultSet(rs);
     }
 
-    @Override
-    public boolean updateObject(StatementList update, StatementList constraints) {
-        String deviceName = update.getStatements().get(0).getValue();
-        String user = update.getStatements().get(1).getValue();
-        String deviceId = update.getStatements().get(2).getValue();
+    public Optional<Device> getByDeviceIdAndOwner(String deviceId, String owner) {
+        // TODO deviceId is the primary key, owner is possibly a useless field
+        String query = "SELECT * FROM devices WHERE deviceId = ? AND owner = ?";
+        ResultSet rs = executeQuery(query, List.of(deviceId, owner));
+        return getFirstObjectFromResultSet(rs);
+    }
 
-        SQLConnection connection = DataStore.connectionPool.getConnection();
+    @Override
+    public boolean storeObject(Device object) {
+        String query =
+                "INSERT INTO devices "
+                        + "(deviceId, owner, displayName, certificate, privatekey) "
+                        + "VALUES "
+                        + "(?, ?, ?, ?, ?)";
+        return executeInsert(query, object);
+    }
 
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "UPDATE devices SET displayName = ? WHERE owner = ? AND deviceId = ?");
-            ps.setString(1, deviceName);
-            ps.setString(2, user);
-            ps.setString(3, deviceId);
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to update a user: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public boolean updateObject(String deviceName, String username, String deviceId) {
+        String query = "UPDATE devices SET displayName = ? WHERE owner = ? AND deviceId = ?";
+        return executeUpdate(query, List.of(deviceName, username, deviceId));
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/GroupDao.java b/datastore/src/main/java/net/jami/datastore/dao/GroupDao.java
index 301b0097..1c1c2b06 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/GroupDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/GroupDao.java
@@ -2,13 +2,11 @@ package net.jami.datastore.dao;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.StatementList;
-import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.user.Group;
 
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
+import java.sql.ResultSet;
+import java.util.List;
+import java.util.Optional;
 
 @Slf4j
 public class GroupDao extends AbstractDao<Group> {
@@ -18,69 +16,29 @@ public class GroupDao extends AbstractDao<Group> {
         this.setTClass(Group.class);
     }
 
-    @Override
-    public boolean storeObject(Group object) {
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "INSERT INTO groups "
-                                            + "(id, name, blueprint) VALUES (?, ?, ?)");
-            ps = object.getInsert(ps);
-            return ps.executeUpdate() != 0;
-        } catch (SQLException e) {
-            log.error("An error has occurred while trying to store a group: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public List<Group> getAll() {
+        ResultSet rs = executeQuery("SELECT * FROM groups");
+        return getObjectsFromResultSet(rs);
     }
 
-    @Override
-    public boolean updateObject(StatementList update, StatementList constraints) {
-
-        String id = update.getStatements().get(0).getValue();
-        String name = update.getStatements().get(1).getValue();
-        String blueprint = update.getStatements().get(2).getValue();
-
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "UPDATE groups SET name = ?, blueprint = ? WHERE id = ?");
-            ps.setString(1, name);
-            ps.setString(2, blueprint);
-            ps.setString(3, id);
-            return ps.executeUpdate() != 0;
-        } catch (SQLException e) {
-            log.error("An error has occurred while trying to update a group: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public Optional<Group> getById(String id) {
+        ResultSet rs = executeQuery("SELECT * FROM groups WHERE id = ?", List.of(id));
+        return getFirstObjectFromResultSet(rs);
     }
 
     @Override
-    public boolean deleteObject(StatementList constraints) {
+    public boolean storeObject(Group object) {
+        String query = "INSERT INTO groups " + "(id, name, blueprint) VALUES (?, ?, ?)";
+        return executeInsert(query, object);
+    }
 
-        String id = constraints.getStatements().get(0).getValue();
-        SQLConnection connection = DataStore.connectionPool.getConnection();
+    public boolean updateObject(String id, String name, String blueprint) {
+        String query = "UPDATE groups SET name = ?, blueprint = ? WHERE id = ?";
+        return executeUpdate(query, List.of(id, name, blueprint));
+    }
 
-        try {
-            PreparedStatement ps =
-                    connection.getConnection().prepareStatement("DELETE FROM groups WHERE id = ?");
-            ps.setString(1, id);
-            return ps.executeUpdate() != 0;
-        } catch (SQLException e) {
-            log.error("An error has occurred while trying to delete a group: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public boolean deleteObject(String id) {
+        String query = "DELETE FROM groups WHERE id = ?";
+        return executeUpdate(query, List.of(id));
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/JwtDao.java b/datastore/src/main/java/net/jami/datastore/dao/JwtDao.java
deleted file mode 100644
index b22ce1d5..00000000
--- a/datastore/src/main/java/net/jami/datastore/dao/JwtDao.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 by Savoir-faire Linux
- * Authors: William Enright <william.enright@savoirfairelinux.com>
- *          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
- *          Johnny Flores <johnny.flores@savoirfairelinux.com>
- *          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
- *          Felix Sidokhine <felix.sidokhine@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, see <https://www.gnu.org/licenses/>.
- */
-
-package net.jami.datastore.dao;
-
-import com.nimbusds.jwt.SignedJWT;
-
-import lombok.extern.slf4j.Slf4j;
-
-import net.jami.jams.common.dao.StatementList;
-
-import java.util.List;
-
-@Slf4j
-public class JwtDao extends AbstractDao<SignedJWT> {
-
-    private static final String SQL_STORE_TOKEN =
-            "INSERT INTO tokens (userid,deviceId,token) VALUES (?,?,?)";
-    private static final String SQL_DELETE_TOKEN =
-            "DELETE FROM tokens WHERE userid = ? AND deviceId = ?";
-    private static final String SQL_GET_TOKEN = "SELECT COUNT(token) FROM tokens WHERE token = ?";
-
-    public JwtDao() {
-        this.setTableName("tokens");
-        this.setTClass(SignedJWT.class);
-    }
-
-    @Override
-    public boolean storeObject(SignedJWT object) {
-        // TODO: Implement this.
-        return true;
-    }
-
-    public boolean validateToken(SignedJWT signedJWT) {
-        // TODO: Implement this.
-        return true;
-    }
-
-    // This method is not needed because we are only concerned with the existence of a token,
-    // we never actually look them up.
-    @Override
-    public List<SignedJWT> getObjects(StatementList constraints) {
-        return null;
-    }
-
-    // TODO: Implement this method.
-    @Override
-    public boolean deleteObject(StatementList delete) {
-        return false;
-    }
-}
diff --git a/datastore/src/main/java/net/jami/datastore/dao/PolicyDao.java b/datastore/src/main/java/net/jami/datastore/dao/PolicyDao.java
index f2641198..3084dcd0 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/PolicyDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/PolicyDao.java
@@ -2,13 +2,11 @@ package net.jami.datastore.dao;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.StatementList;
-import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.user.Policy;
 
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
+import java.sql.ResultSet;
+import java.util.List;
+import java.util.Optional;
 
 @Slf4j
 public class PolicyDao extends AbstractDao<Policy> {
@@ -18,69 +16,41 @@ public class PolicyDao extends AbstractDao<Policy> {
         this.setTClass(Policy.class);
     }
 
-    @Override
-    public boolean storeObject(Policy object) {
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "INSERT INTO policies " + "(name, policyData) VALUES (?, ?)");
-            ps = object.getInsert(ps);
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to store a blueprint: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public List<Policy> getAll() {
+        ResultSet rs = executeQuery("SELECT * FROM policies");
+        return getObjectsFromResultSet(rs);
     }
 
-    @Override
-    public boolean updateObject(StatementList update, StatementList constraints) {
-        String name = update.getStatements().get(0).getValue();
-        String policyData = update.getStatements().get(1).getValue();
-        String oldName = constraints.getStatements().get(0).getValue();
-
-        SQLConnection connection = DataStore.connectionPool.getConnection();
+    public Optional<Policy> getByName(String name) {
+        String q = "SELECT * FROM policies WHERE name = ?";
+        ResultSet rs = executeQuery(q, List.of(name));
+        return getFirstObjectFromResultSet(rs);
+    }
 
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "UPDATE policies SET name = ?, policyData = ? WHERE name = ?");
-            ps.setString(1, name);
-            ps.setString(2, policyData);
-            ps.setString(3, oldName);
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to update a blueprint: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public Optional<Policy> getByUsername(String username) {
+        // TODO this can return multiple policies
+        String query =
+                "SELECT * FROM usergroupmappings ugm"
+                        + " JOIN groups g ON ugm.groupid = g.id"
+                        + " JOIN policies p ON g.blueprint = p.name"
+                        + " WHERE ugm.username = ?";
+        ResultSet rs = executeQuery(query, List.of(username));
+        return getFirstObjectFromResultSet(rs);
     }
 
     @Override
-    public boolean deleteObject(StatementList constraints) {
+    public boolean storeObject(Policy object) {
+        String query = "INSERT INTO policies (name, policyData) VALUES (?, ?)";
+        return executeInsert(query, object);
+    }
 
-        String name = constraints.getStatements().get(0).getValue();
-        SQLConnection connection = DataStore.connectionPool.getConnection();
+    public boolean updateObject(String name, String policyData) {
+        String query = "UPDATE policies SET policyData = ? WHERE name = ?";
+        return executeUpdate(query, List.of(policyData, name));
+    }
 
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement("DELETE FROM policies WHERE name = ?");
-            ps.setString(1, name);
-            return ps.executeUpdate() != 0;
-        } catch (SQLException e) {
-            log.error("An error has occurred while trying to delete a blueprint: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public boolean deleteObject(String name) {
+        String query = "DELETE FROM policies WHERE name = ?";
+        return executeUpdate(query, List.of(name));
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java b/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java
index 6babcfc9..53da8855 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java
@@ -25,12 +25,10 @@ package net.jami.datastore.dao;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.StatementList;
-import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.system.SystemAccount;
 
-import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.Optional;
 
 @Slf4j
 public class SystemDao extends AbstractDao<SystemAccount> {
@@ -40,30 +38,20 @@ public class SystemDao extends AbstractDao<SystemAccount> {
         this.setTClass(SystemAccount.class);
     }
 
-    @Override
-    public boolean storeObject(SystemAccount object) {
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "INSERT INTO system "
-                                            + "(entity,certificate,privatekey)"
-                                            + "VALUES "
-                                            + "(?, ?, ?)");
-            ps = object.getInsert(ps);
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to store a system entity: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public Optional<SystemAccount> getCA() {
+        ResultSet rs = executeQuery("SELECT * FROM system WHERE entity = 'CA'");
+        return getFirstObjectFromResultSet(rs);
+    }
+
+    public Optional<SystemAccount> getOCSP() {
+        ResultSet rs = executeQuery("SELECT * FROM system WHERE entity = 'OCSP'");
+        return getFirstObjectFromResultSet(rs);
     }
 
     @Override
-    public boolean updateObject(StatementList update, StatementList constraints) {
-        return false;
+    public boolean storeObject(SystemAccount object) {
+        String query =
+                "INSERT INTO system " + "(entity,certificate,privatekey)" + "VALUES " + "(?, ?, ?)";
+        return executeInsert(query, object);
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/UserDao.java b/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
index 6be8ca59..75772d94 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
@@ -25,12 +25,11 @@ package net.jami.datastore.dao;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.StatementList;
-import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.user.User;
 
-import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.List;
+import java.util.Optional;
 
 @Slf4j
 public class UserDao extends AbstractDao<User> {
@@ -40,74 +39,45 @@ public class UserDao extends AbstractDao<User> {
         this.setTClass(User.class);
     }
 
-    @Override
-    public boolean storeObject(User object) {
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "INSERT INTO users "
-                                            + "(username, password, userType, realm, ethAddress, ethKey, jamiId,certificate, privatekey, accessLevel, needsPasswordReset, salt) "
-                                            + " VALUES "
-                                            + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
-            ps = object.getInsert(ps);
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to store a user: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public List<User> getAll() {
+        ResultSet rs = executeQuery("SELECT * FROM users");
+        return getObjectsFromResultSet(rs);
     }
 
-    public boolean updateUserCertificate(String username, String certificate) {
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "UPDATE users SET certificate = ? WHERE username = ?");
-            ps.setString(1, certificate);
-            ps.setString(2, username);
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to update a user certificate: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public Optional<User> getByUsername(String username) {
+        ResultSet rs = executeQuery("SELECT * FROM users WHERE username = ?", username);
+        return getFirstObjectFromResultSet(rs);
     }
 
-    @Override
-    public boolean updateObject(StatementList update, StatementList constraints) {
+    public List<User> getByJamiId(String jamiId) {
+        ResultSet rs = executeQuery("SELECT * FROM users WHERE jamiId = ?", jamiId);
+        return getObjectsFromResultSet(rs);
+    }
 
-        String pw = update.getStatements().get(0).getValue();
-        String salt = "";
-        if (update.getStatements().size() > 1) salt = update.getStatements().get(1).getValue();
+    @Override
+    public boolean storeObject(User object) {
+        String query =
+                "INSERT INTO users "
+                        + "(username, password, userType, realm, ethAddress, ethKey, jamiId,certificate, privatekey, accessLevel, needsPasswordReset, salt) "
+                        + " VALUES "
+                        + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
 
-        String user = constraints.getStatements().get(0).getValue();
+        return executeInsert(query, object);
+    }
 
-        SQLConnection connection = DataStore.connectionPool.getConnection();
+    public boolean updateUserCertificate(String username, String certificate) {
+        String query = "UPDATE users SET certificate = ? WHERE username = ?";
+        return executeUpdate(query, List.of(certificate, username));
+    }
 
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "UPDATE users SET password = ?, salt = ? WHERE username = ?");
-            ps.setString(1, pw);
-            ps.setString(2, salt);
-            ps.setString(3, user);
+    public boolean updateObject(String password, String username) {
+        String query =
+                "UPDATE users SET password = ?, needsPasswordReset = 'true' WHERE username = ?";
+        return executeUpdate(query, List.of(password, username));
+    }
 
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to update a user: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public boolean updateObject(String password, String salt, String username) {
+        String query = "UPDATE users SET password = ?, salt = ? WHERE username = ?";
+        return executeUpdate(query, List.of(password, salt, username));
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/UserGroupMappingsDao.java b/datastore/src/main/java/net/jami/datastore/dao/UserGroupMappingsDao.java
index 98afdfcb..e585421e 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/UserGroupMappingsDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/UserGroupMappingsDao.java
@@ -2,13 +2,11 @@ package net.jami.datastore.dao;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.StatementList;
-import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.user.UserGroupMapping;
 
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
+import java.sql.ResultSet;
+import java.util.List;
+import java.util.Optional;
 
 @Slf4j
 public class UserGroupMappingsDao extends AbstractDao<UserGroupMapping> {
@@ -18,60 +16,38 @@ public class UserGroupMappingsDao extends AbstractDao<UserGroupMapping> {
         this.setTClass(UserGroupMapping.class);
     }
 
-    @Override
-    public boolean storeObject(UserGroupMapping object) {
+    public List<UserGroupMapping> getByGroupId(String groupId) {
+        ResultSet rs = executeQuery("SELECT * FROM usergroupmappings WHERE groupId = ?", groupId);
+        return getObjectsFromResultSet(rs);
+    }
 
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "INSERT INTO usergroupmappings "
-                                            + "(username, groupId)"
-                                            + " VALUES "
-                                            + "(?,?)");
-            ps = object.getInsert(ps);
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to store a user profile: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public List<UserGroupMapping> getByUsername(String username) {
+        ResultSet rs = executeQuery("SELECT * FROM usergroupmappings WHERE username = ?", username);
+        return getObjectsFromResultSet(rs);
     }
 
-    @Override
-    public boolean deleteObject(StatementList constraints) {
+    public Optional<UserGroupMapping> getByGroupIdAndUsername(String groupId, String username) {
+        // TODO The primary key should be (groupId, username)
+        String query = "SELECT * FROM usergroupmappings WHERE groupId = ? AND username = ?";
+        List<String> params = List.of(groupId, username);
+        ResultSet rs = executeQuery(query, params);
+        return getFirstObjectFromResultSet(rs);
+    }
 
-        String username = constraints.getStatements().get(0).getValue();
-        String groupId = constraints.getStatements().get(1).getValue();
-        SQLConnection connection = DataStore.connectionPool.getConnection();
+    @Override
+    public boolean storeObject(UserGroupMapping object) {
+        String query =
+                "INSERT INTO usergroupmappings " + "(username, groupId)" + " VALUES " + "(?, ?)";
+        return executeInsert(query, object);
+    }
 
-        try {
-            if (username.equals("*")) {
-                PreparedStatement ps =
-                        connection
-                                .getConnection()
-                                .prepareStatement(
-                                        "DELETE FROM usergroupmappings WHERE groupId = ?");
-                ps.setString(1, groupId);
-                return ps.executeUpdate() != 0;
-            } else {
-                PreparedStatement ps =
-                        connection
-                                .getConnection()
-                                .prepareStatement(
-                                        "DELETE FROM usergroupmappings WHERE username = ? AND groupId = ?");
-                ps.setString(1, username);
-                ps.setString(2, groupId);
-                return ps.executeUpdate() != 0;
-            }
-        } catch (SQLException e) {
-            log.error("An error has occurred while trying to delete a group member: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
+    public boolean deleteObject(String username, String groupId) {
+        if (username.equals("*")) {
+            String query = "DELETE FROM usergroupmappings WHERE groupId = ?";
+            return executeUpdate(query, List.of(groupId));
         }
+
+        String query = "DELETE FROM usergroupmappings WHERE username = ? AND groupId = ?";
+        return executeUpdate(query, List.of(username, groupId));
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java b/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java
index fd025a63..242c59ac 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java
@@ -25,65 +25,93 @@ package net.jami.datastore.dao;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.StatementList;
-import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.user.UserProfile;
 
-import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
 
 @Slf4j
 public class UserProfileDao extends AbstractDao<UserProfile> {
 
-    // Fis this to include the fields from AD/LDAP.
+    // Fix this to include the fields from AD/LDAP.
     public UserProfileDao() {
         this.setTableName("local_directory");
         this.setTClass(UserProfile.class);
     }
 
-    @Override
-    public boolean storeObject(UserProfile object) {
+    public void insertIfNotExists(UserProfile userProfile) throws SQLException {
+        String query =
+                "INSERT INTO local_directory"
+                        + " (username, firstName, lastName, email, profilePicture, organization, phoneNumber, phoneNumberExtension, faxNumber, mobileNumber)"
+                        + " SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, ?"
+                        + " FROM local_directory"
+                        + " WHERE NOT EXISTS (SELECT 1 FROM local_directory WHERE username = ?)";
+
+        List<String> params = new ArrayList<>();
+        params.add(userProfile.getUsername());
+        params.add(userProfile.getFirstName());
+        params.add(userProfile.getLastName());
+        params.add(userProfile.getEmail());
+        params.add(userProfile.getProfilePicture());
+        params.add(userProfile.getOrganization());
+        params.add(userProfile.getPhoneNumber());
+        params.add(userProfile.getPhoneNumberExtension());
+        params.add(userProfile.getFaxNumber());
+        params.add(userProfile.getMobileNumber());
+        params.add(userProfile.getUsername());
+
+        this.executeUpdate(query, params);
+    }
+
+    public List<UserProfile> getAllUserProfile() {
+        ResultSet rs = executeQuery("SELECT * FROM local_directory");
+        return getObjectsFromResultSet(rs);
+    }
 
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "INSERT INTO local_directory "
-                                            + "(username, firstName, lastName, email, profilePicture, organization, phoneNumber, phoneNumberExtension, faxNumber, mobileNumber)"
-                                            + " VALUES "
-                                            + "(?,?,?,?,?,?,?,?,?,?)");
-            ps = object.getInsert(ps);
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to store a user profile: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public List<UserProfile> searchUsername(String username) {
+        String query = "SELECT * FROM local_directory WHERE username LIKE ?";
+        ResultSet rs = executeQuery(query, username + "%");
+        return getObjectsFromResultSet(rs);
+    }
+
+    public List<UserProfile> searchFullName(String name) {
+        String query = "SELECT * FROM local_directory WHERE firstName LIKE ? OR lastName ?";
+        name = name + "%";
+        ResultSet rs = executeQuery(query, List.of(name, name));
+        return getObjectsFromResultSet(rs);
+    }
+
+    public Optional<UserProfile> getByUsername(String username) {
+        ResultSet rs = executeQuery("SELECT * FROM local_directory WHERE username = ?", username);
+        return getFirstObjectFromResultSet(rs);
     }
 
     @Override
-    public boolean updateObject(StatementList update, StatementList constraints) {
+    public boolean storeObject(UserProfile object) {
+        String query =
+                "INSERT INTO local_directory "
+                        + "(firstName, lastName, email, profilePicture, organization, phoneNumber, phoneNumberExtension, faxNumber, mobileNumber, username)"
+                        + " VALUES "
+                        + "(?,?,?,?,?,?,?,?,?,?)";
+        return executeInsert(query, object);
+    }
 
-        SQLConnection connection = DataStore.connectionPool.getConnection();
-        try {
-            PreparedStatement ps =
-                    connection
-                            .getConnection()
-                            .prepareStatement(
-                                    "UPDATE local_directory SET firstname = ?, lastName = ?, email = ?, profilePicture = ?, organization = ?, phoneNumber = ?, phoneNumberExtension = ?, faxNumber = ?, mobileNumber = ? WHERE username = ?");
-            for (int i = 1; i < update.getStatements().size(); i++) {
-                ps.setString(i, update.getStatements().get(i).getValue());
-            }
-            ps.setString(update.getStatements().size(), update.getStatements().get(0).getValue());
-            return ps.executeUpdate() != 0;
-        } catch (Exception e) {
-            log.error("An error has occurred while trying to update a user profile: " + e);
-            return false;
-        } finally {
-            DataStore.connectionPool.returnConnection(connection);
-        }
+    public boolean updateUserProfile(UserProfile userProfile) {
+        String query =
+                "UPDATE local_directory SET"
+                        + " firstname = ?,"
+                        + " lastName = ?,"
+                        + " email = ?,"
+                        + " profilePicture = ?,"
+                        + " organization = ?,"
+                        + " phoneNumber = ?,"
+                        + " phoneNumberExtension = ?,"
+                        + " faxNumber = ?,"
+                        + " mobileNumber = ?"
+                        + " WHERE username = ?";
+        return executeInsert(query, userProfile);
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/main/DataStore.java b/datastore/src/main/java/net/jami/datastore/main/DataStore.java
index 507cafaf..80e9491e 100644
--- a/datastore/src/main/java/net/jami/datastore/main/DataStore.java
+++ b/datastore/src/main/java/net/jami/datastore/main/DataStore.java
@@ -28,7 +28,6 @@ import lombok.Setter;
 import net.jami.datastore.dao.ContactDao;
 import net.jami.datastore.dao.DeviceDao;
 import net.jami.datastore.dao.GroupDao;
-import net.jami.datastore.dao.JwtDao;
 import net.jami.datastore.dao.PolicyDao;
 import net.jami.datastore.dao.SystemDao;
 import net.jami.datastore.dao.UserDao;
@@ -37,8 +36,6 @@ import net.jami.datastore.dao.UserProfileDao;
 import net.jami.jams.common.authentication.AuthenticationSource;
 import net.jami.jams.common.authentication.AuthenticationSourceInfo;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.dao.connectivity.ConnectionPool;
 import net.jami.jams.common.objects.user.User;
 import net.jami.jams.common.objects.user.UserProfile;
@@ -61,7 +58,6 @@ public class DataStore implements AuthenticationSource {
     private DeviceDao deviceDao;
     private SystemDao systemDao;
     private ContactDao contactDao;
-    private JwtDao jwtDao;
     private UserProfileDao userProfileDao;
     private UserGroupMappingsDao userGroupMappingsDao;
     public static final Integer RESULTS_PER_PAGE = 24;
@@ -78,19 +74,10 @@ public class DataStore implements AuthenticationSource {
         deviceDao = new DeviceDao();
         systemDao = new SystemDao();
         contactDao = new ContactDao();
-        jwtDao = new JwtDao();
         userProfileDao = new UserProfileDao();
         userGroupMappingsDao = new UserGroupMappingsDao();
     }
 
-    public boolean userExists(String username) {
-        StatementList statementList = new StatementList();
-        StatementElement statementElement = new StatementElement("username", "=", username, "");
-        statementList.addStatement(statementElement);
-        List<User> userList = userDao.getObjects(statementList);
-        return (userList.size() == 1);
-    }
-
     @Override
     public boolean createUser(User user) {
         return userDao.storeObject(user);
@@ -101,20 +88,17 @@ public class DataStore implements AuthenticationSource {
             String queryString, String field, Optional<Integer> page) {
         List<UserProfile> userList;
 
-        if (!queryString.equals("*")) {
-            StatementList statementList = new StatementList();
-            String startQueryString = queryString.concat("%");
+        if (queryString.equals("*")) {
+            userList = userProfileDao.getAllUserProfile();
+        } else {
             if (field.equals("LOGON_NAME")) {
-                statementList.addStatement(
-                        new StatementElement("username", "LIKE", startQueryString, ""));
+                userList = userProfileDao.searchUsername(queryString);
             } else if (field.equals("FULL_TEXT_NAME")) {
-                statementList.addStatement(
-                        new StatementElement("firstName", "LIKE", startQueryString, "OR"));
-                statementList.addStatement(
-                        new StatementElement("lastName", "LIKE", startQueryString, ""));
+                userList = userProfileDao.searchFullName(queryString);
+            } else {
+                throw new IllegalArgumentException("Invalid field");
             }
-            userList = userProfileDao.getObjects(statementList);
-        } else userList = userProfileDao.getObjects(null);
+        }
 
         if (userList == null) userList = new ArrayList<>();
 
@@ -137,11 +121,7 @@ public class DataStore implements AuthenticationSource {
 
     @Override
     public UserProfile getUserProfile(String username) {
-        StatementList statementList = new StatementList();
-        statementList.addStatement(new StatementElement("username", "=", username, ""));
-        List<UserProfile> userList = userProfileDao.getObjects(statementList);
-        if (userList.size() != 1) return null;
-        else return userList.get(0);
+        return userProfileDao.getByUsername(username).orElse(null);
     }
 
     @Override
@@ -150,26 +130,7 @@ public class DataStore implements AuthenticationSource {
     }
 
     public boolean updateUserProfile(UserProfile userProfile) {
-
-        StatementList update = new StatementList();
-        update.addStatement(new StatementElement("username", "=", userProfile.getUsername(), ""));
-        update.addStatement(new StatementElement("firstName", "=", userProfile.getFirstName(), ""));
-        update.addStatement(new StatementElement("lastName", "=", userProfile.getLastName(), ""));
-        update.addStatement(new StatementElement("email", "=", userProfile.getEmail(), ""));
-        update.addStatement(
-                new StatementElement("profilePicture", "=", userProfile.getProfilePicture(), ""));
-        update.addStatement(
-                new StatementElement("organization", "=", userProfile.getOrganization(), ""));
-        update.addStatement(
-                new StatementElement("phoneNumber", "=", userProfile.getPhoneNumber(), ""));
-        update.addStatement(
-                new StatementElement(
-                        "phoneNumberExtension", "=", userProfile.getPhoneNumberExtension(), ""));
-        update.addStatement(new StatementElement("faxNumber", "=", userProfile.getFaxNumber(), ""));
-        update.addStatement(
-                new StatementElement("mobileNumber", "=", userProfile.getMobileNumber(), ""));
-
-        return userProfileDao.updateObject(update, null);
+        return userProfileDao.updateUserProfile(userProfile);
     }
 
     public boolean updateUserCertificate(User user) {
@@ -179,12 +140,10 @@ public class DataStore implements AuthenticationSource {
 
     @Override
     public boolean authenticate(String username, String password) {
-        StatementList statementList = new StatementList();
-        StatementElement statementElement = new StatementElement("username", "=", username, "");
-        statementList.addStatement(statementElement);
-        List<User> userList = userDao.getObjects(statementList);
-        if (userList.size() != 1 || userList.get(0).getPassword() == null) return false;
-        return userList.get(0).getPassword().equals(password);
+        return userDao.getByUsername(username)
+                .map(user -> user.getPassword())
+                .orElse("")
+                .equals(password);
     }
 
     @Override
diff --git a/datastore/src/test/java/net/jami/datastore/dao/DAOTest.java b/datastore/src/test/java/net/jami/datastore/dao/DAOTest.java
index 5d465c9a..dcf39d91 100644
--- a/datastore/src/test/java/net/jami/datastore/dao/DAOTest.java
+++ b/datastore/src/test/java/net/jami/datastore/dao/DAOTest.java
@@ -26,8 +26,6 @@ import lombok.extern.slf4j.Slf4j;
 
 import net.jami.datastore.main.DataStore;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.devices.Device;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.User;
@@ -87,9 +85,7 @@ class DAOTest {
         UserDao userDAO = new UserDao();
         userDAO.storeObject(user);
 
-        StatementList statementList = new StatementList();
-        statementList.addStatement(new StatementElement("username", "=", "fsidokhine", ""));
-        User user1 = userDAO.getObjects(statementList).get(0);
+        User user1 = userDAO.getByUsername("fsidokhine").get();
         Assertions.assertNotNull(user1);
         Assertions.assertEquals(user1.getAccessLevel(), AccessLevel.ADMIN);
     }
@@ -110,9 +106,7 @@ class DAOTest {
         UserDao userDAO = new UserDao();
         userDAO.storeObject(user);
 
-        StatementList statementList = new StatementList();
-        statementList.addStatement(new StatementElement("username", "=", "TestUser", ""));
-        User user1 = userDAO.getObjects(statementList).get(0);
+        User user1 = userDAO.getByUsername("TestUser").get();
         Assertions.assertNotNull(user1);
         Assertions.assertEquals(user1.getAccessLevel(), AccessLevel.USER);
 
@@ -121,7 +115,7 @@ class DAOTest {
                 X509Utils.getPEMStringFromCertificate(
                         X509Utils.getCertificateFromPEMString(refreshedCertificate)));
 
-        User user2 = userDAO.getObjects(statementList).get(0);
+        User user2 = userDAO.getByUsername("TestUser").get();
         Assertions.assertNotEquals(user1.getCertificate(), user2.getCertificate());
     }
 
@@ -135,9 +129,7 @@ class DAOTest {
         DeviceDao deviceDAO = new DeviceDao();
         deviceDAO.storeObject(device);
 
-        StatementList statementList = new StatementList();
-        statementList.addStatement(new StatementElement("owner", "=", "fsidokhine", ""));
-        Device device1 = deviceDAO.getObjects(statementList).get(0);
+        Device device1 = deviceDAO.getByOwner("fsidokhine").get(0);
         Assertions.assertNotNull(device1);
     }
 
@@ -155,9 +147,7 @@ class DAOTest {
         UserDao userDAO = new UserDao();
         userDAO.storeObject(user);
 
-        StatementList statementList = new StatementList();
-        statementList.addStatement(new StatementElement("username", "=", "admin", ""));
-        User user1 = userDAO.getObjects(statementList).get(0);
+        User user1 = userDAO.getByUsername("admin").get();
         Assertions.assertNotNull(user1);
         Assertions.assertEquals(user1.getAccessLevel(), AccessLevel.ADMIN);
     }
diff --git a/jami-nameserver/src/main/java/net/jami/jams/nameserver/LocalNameServer.java b/jami-nameserver/src/main/java/net/jami/jams/nameserver/LocalNameServer.java
index ce44aa42..765fe786 100644
--- a/jami-nameserver/src/main/java/net/jami/jams/nameserver/LocalNameServer.java
+++ b/jami-nameserver/src/main/java/net/jami/jams/nameserver/LocalNameServer.java
@@ -27,8 +27,6 @@ import lombok.extern.slf4j.Slf4j;
 import net.jami.datastore.main.DataStore;
 import net.jami.jams.common.authmodule.AuthModuleKey;
 import net.jami.jams.common.authmodule.AuthenticationModule;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.jami.NameLookupResponse;
 import net.jami.jams.common.jami.NameRegistrationRequest;
 import net.jami.jams.common.jami.NameServer;
@@ -37,6 +35,7 @@ import net.jami.jams.common.objects.user.User;
 import net.jami.jams.common.objects.user.UserProfile;
 
 import java.util.List;
+import java.util.Optional;
 
 @Slf4j
 public class LocalNameServer implements NameServer {
@@ -62,12 +61,8 @@ public class LocalNameServer implements NameServer {
 
     @Override
     public NameLookupResponse getAddressFromName(String username) {
-        NameLookupResponse nameLookupResponse = null;
-        StatementList statementList = new StatementList();
-        StatementElement statementElement = new StatementElement("username", "=", username, "");
-        statementList.addStatement(statementElement);
-        List<User> results = dataStore.getUserDao().getObjects(statementList);
-        if (results.size() == 0) {
+        Optional<User> result = dataStore.getUserDao().getByUsername(username);
+        if (result.isEmpty()) {
             // Reattempt resolution via directory lookups.
             final User user = new User();
             for (AuthModuleKey key : authenticationModule.getAuthSources().keySet()) {
@@ -87,22 +82,19 @@ public class LocalNameServer implements NameServer {
             }
             if (user.getUsername() == null) return null;
             // resolve again in the database to be sure.
-            results = dataStore.getUserDao().getObjects(statementList);
-            if (results.size() == 0) return null;
+            result = dataStore.getUserDao().getByUsername(username);
+            if (result.isEmpty()) return null;
         }
-        nameLookupResponse = new NameLookupResponse();
-        nameLookupResponse.setName(results.get(0).getUsername());
-        nameLookupResponse.setAddr(results.get(0).getJamiId());
+        NameLookupResponse nameLookupResponse = new NameLookupResponse();
+        nameLookupResponse.setName(result.get().getUsername());
+        nameLookupResponse.setAddr(result.get().getJamiId());
         return nameLookupResponse;
     }
 
     @Override
     public String getNameFromAddress(String address) {
-        StatementList statementList = new StatementList();
-        StatementElement statementElement = new StatementElement("jamiId", "=", address, "");
-        statementList.addStatement(statementElement);
-        List<User> results = dataStore.getUserDao().getObjects(statementList);
-        if (results.size() == 0) return null;
+        List<User> results = dataStore.getUserDao().getByJamiId(address);
+        if (results.isEmpty()) return null;
         return results.get(0).getUsername();
     }
 
diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/UserBuilder.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/UserBuilder.java
index d176275b..86f7437f 100644
--- a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/UserBuilder.java
+++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/UserBuilder.java
@@ -56,11 +56,10 @@ public class UserBuilder {
             keyPairGenerator.initialize(4096);
             KeyPair keyPair = keyPairGenerator.generateKeyPair();
 
-            user.getX509Fields()
-                    .setUid(
-                            Hex.encodeHexString(
-                                    MessageDigest.getInstance(MessageDigestAlgorithms.SHA_1)
-                                            .digest(keyPair.getPublic().getEncoded())));
+            byte[] digest =
+                    MessageDigest.getInstance(MessageDigestAlgorithms.SHA_1)
+                            .digest(keyPair.getPublic().getEncoded());
+            user.getX509Fields().setUid(Hex.encodeHexString(digest));
 
             X509v3CertificateBuilder builder =
                     new X509v3CertificateBuilder(
@@ -90,13 +89,13 @@ public class UserBuilder {
     }
 
     public static User refreshUser(User user, long userLifeTime) {
-        try {
-            long now = System.currentTimeMillis();
-
-            user.setX509Fields(new X509Fields());
-            user.getX509Fields().setCommonName(user.getUsername());
-            user.getX509Fields().setUid(user.getJamiId());
+        long now = System.currentTimeMillis();
+        X509Fields x509 = new X509Fields();
+        x509.setCommonName(user.getUsername());
+        x509.setUid(user.getJamiId());
+        user.setX509Fields(x509);
 
+        try {
             X509v3CertificateBuilder builder =
                     new X509v3CertificateBuilder(
                             new JcaX509CertificateHolder(JamsCA.CA.getCertificate()).getSubject(),
diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/ocsp/OCSPWorker.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/ocsp/OCSPWorker.java
index 3b064f6a..463f7081 100644
--- a/jams-ca/src/main/java/net/jami/jams/ca/workers/ocsp/OCSPWorker.java
+++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/ocsp/OCSPWorker.java
@@ -96,7 +96,7 @@ public class OCSPWorker extends X509Worker<String> {
             if (validateRequest(ocspRequest) != null)
                 throw new OCSPException(
                         "Request is not valid"); // this means the request is invalid and we should
-                                                 // notify the client.
+            // notify the client.
             // If the request was valid, we move on to other things.
             BasicOCSPRespBuilder responseBuilder = new BasicOCSPRespBuilder(responderID);
             // Add appropriate extensions
diff --git a/jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java b/jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java
deleted file mode 100644
index b89eb731..00000000
--- a/jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2020 by Savoir-faire Linux
- * Authors: William Enright <william.enright@savoirfairelinux.com>
- *          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
- *          Johnny Flores <johnny.flores@savoirfairelinux.com>
- *          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
- *          Felix Sidokhine <felix.sidokhine@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, see <https://www.gnu.org/licenses/>.
- */
-package net.jami.jams.common.dao;
-
-import net.jami.jams.common.dao.connectivity.SQLConnection;
-
-import java.sql.PreparedStatement;
-
-public class DeleteStatementBuilder {
-
-    public static PreparedStatement buildStatement(
-            String table, StatementList statementElements, SQLConnection connection)
-            throws Exception {
-        PreparedStatement ps = null;
-        StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder.append("DELETE FROM ").append(table);
-        if (statementElements != null) {
-            stringBuilder.append(" WHERE ");
-            for (StatementElement statementElement : statementElements.getStatements()) {
-                stringBuilder
-                        .append(statementElement.getColumn())
-                        .append(" ")
-                        .append(statementElement.getOperator())
-                        .append(" ")
-                        .append("?")
-                        .append(" ")
-                        .append(statementElement.getNextStatementRelation())
-                        .append(" ");
-            }
-            ps = connection.getConnection().prepareStatement(stringBuilder.toString());
-            int i = 1;
-            for (StatementElement statementElement : statementElements.getStatements()) {
-                ps.setString(i, statementElement.getValue());
-                i++;
-            }
-        } else {
-            ps = connection.getConnection().prepareStatement(stringBuilder.toString());
-        }
-        return ps;
-    }
-}
diff --git a/jams-common/src/main/java/net/jami/jams/common/dao/SelectStatementBuilder.java b/jams-common/src/main/java/net/jami/jams/common/dao/SelectStatementBuilder.java
deleted file mode 100644
index cd591e9c..00000000
--- a/jams-common/src/main/java/net/jami/jams/common/dao/SelectStatementBuilder.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 by Savoir-faire Linux
- * Authors: William Enright <william.enright@savoirfairelinux.com>
- *          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
- *          Johnny Flores <johnny.flores@savoirfairelinux.com>
- *          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
- *          Felix Sidokhine <felix.sidokhine@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, see <https://www.gnu.org/licenses/>.
- */
-package net.jami.jams.common.dao;
-
-import net.jami.jams.common.dao.connectivity.SQLConnection;
-
-import java.sql.PreparedStatement;
-
-public class SelectStatementBuilder {
-
-    public static PreparedStatement buildStatement(
-            String table,
-            StatementList statementElements,
-            StatementConstraints statementConstraints,
-            SQLConnection connection)
-            throws Exception {
-        PreparedStatement ps = null;
-        StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder.append("SELECT * FROM ").append(table);
-        if (statementElements != null) {
-            stringBuilder.append(" WHERE ");
-            for (StatementElement statementElement : statementElements.getStatements()) {
-
-                stringBuilder
-                        .append("lower(" + statementElement.getColumn() + ")")
-                        .append(" ")
-                        .append(statementElement.getOperator())
-                        .append(" ")
-                        .append("?")
-                        .append(" ")
-                        .append(statementElement.getNextStatementRelation())
-                        .append(" ");
-            }
-            ps = connection.getConnection().prepareStatement(stringBuilder.toString());
-            int i = 1;
-            for (StatementElement statementElement : statementElements.getStatements()) {
-                ps.setString(i, (statementElement.getValue()).toLowerCase());
-                i++;
-            }
-        } else {
-            if (statementConstraints != null) {
-                stringBuilder
-                        .append(" LIMIT ")
-                        .append(statementConstraints.getRowCount())
-                        .append(" OFFSET ")
-                        .append(statementConstraints.getOffset());
-            }
-            ps = connection.getConnection().prepareStatement(stringBuilder.toString());
-        }
-        return ps;
-    }
-}
diff --git a/jams-common/src/main/java/net/jami/jams/common/dao/StatementConstraints.java b/jams-common/src/main/java/net/jami/jams/common/dao/StatementConstraints.java
deleted file mode 100644
index f2f2294c..00000000
--- a/jams-common/src/main/java/net/jami/jams/common/dao/StatementConstraints.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 by Savoir-faire Linux
- * Authors: William Enright <william.enright@savoirfairelinux.com>
- *          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
- *          Johnny Flores <johnny.flores@savoirfairelinux.com>
- *          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
- *          Felix Sidokhine <felix.sidokhine@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, see <https://www.gnu.org/licenses/>.
- */
-package net.jami.jams.common.dao;
-
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-public class StatementConstraints {
-
-    private Long rowCount;
-    private Long offset;
-}
diff --git a/jams-common/src/main/java/net/jami/jams/common/dao/StatementElement.java b/jams-common/src/main/java/net/jami/jams/common/dao/StatementElement.java
deleted file mode 100644
index 6e1446b2..00000000
--- a/jams-common/src/main/java/net/jami/jams/common/dao/StatementElement.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 by Savoir-faire Linux
- * Authors: William Enright <william.enright@savoirfairelinux.com>
- *          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
- *          Johnny Flores <johnny.flores@savoirfairelinux.com>
- *          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
- *          Felix Sidokhine <felix.sidokhine@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, see <https://www.gnu.org/licenses/>.
- */
-package net.jami.jams.common.dao;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-public class StatementElement {
-    private String column;
-    private String operator;
-    private String value;
-    private String nextStatementRelation;
-}
diff --git a/jams-common/src/main/java/net/jami/jams/common/dao/StatementList.java b/jams-common/src/main/java/net/jami/jams/common/dao/StatementList.java
deleted file mode 100644
index 8767fda0..00000000
--- a/jams-common/src/main/java/net/jami/jams/common/dao/StatementList.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 by Savoir-faire Linux
- * Authors: William Enright <william.enright@savoirfairelinux.com>
- *          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
- *          Johnny Flores <johnny.flores@savoirfairelinux.com>
- *          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
- *          Felix Sidokhine <felix.sidokhine@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, see <https://www.gnu.org/licenses/>.
- */
-package net.jami.jams.common.dao;
-
-import lombok.Getter;
-import lombok.Setter;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@Getter
-@Setter
-public class StatementList {
-
-    private List<StatementElement> statements = new ArrayList<>();
-
-    public void addStatement(StatementElement statementElement) {
-        statements.add(statementElement);
-    }
-}
diff --git a/jams-common/src/main/java/net/jami/jams/common/dao/UpdateStatementBuilder.java b/jams-common/src/main/java/net/jami/jams/common/dao/UpdateStatementBuilder.java
deleted file mode 100644
index 8743e00e..00000000
--- a/jams-common/src/main/java/net/jami/jams/common/dao/UpdateStatementBuilder.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2020 by Savoir-faire Linux
- * Authors: William Enright <william.enright@savoirfairelinux.com>
- *          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
- *          Johnny Flores <johnny.flores@savoirfairelinux.com>
- *          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
- *          Felix Sidokhine <felix.sidokhine@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, see <https://www.gnu.org/licenses/>.
- */
-package net.jami.jams.common.dao;
-
-import net.jami.jams.common.dao.connectivity.SQLConnection;
-
-import java.sql.PreparedStatement;
-
-public class UpdateStatementBuilder {
-    public static PreparedStatement buildStatement(
-            String table,
-            StatementList updateElements,
-            StatementList conditionalElements,
-            SQLConnection connection)
-            throws Exception {
-        PreparedStatement ps = null;
-        StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder.append("UPDATE ").append(table).append(" SET ");
-        for (int i = 0; i < updateElements.getStatements().size(); i++) {
-            StatementElement statementElement = updateElements.getStatements().get(i);
-            stringBuilder.append(statementElement.getColumn()).append(" = ").append("?");
-            if (i != updateElements.getStatements().size() - 1) stringBuilder.append(",");
-        }
-        stringBuilder.append(" WHERE ");
-        for (StatementElement statementElement : conditionalElements.getStatements()) {
-            stringBuilder
-                    .append(statementElement.getColumn())
-                    .append(" ")
-                    .append(statementElement.getOperator())
-                    .append(" ")
-                    .append("?")
-                    .append(" ")
-                    .append(statementElement.getNextStatementRelation());
-        }
-        ps = connection.getConnection().prepareStatement(stringBuilder.toString());
-        // Now we have to feed this all the elements it should have.
-        updateElements.getStatements().addAll(conditionalElements.getStatements());
-        int i = 1;
-        for (StatementElement statementElement : updateElements.getStatements()) {
-            ps.setString(i, statementElement.getValue());
-            i++;
-        }
-        return ps;
-    }
-}
diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java b/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java
index 609fa345..fdfbb1af 100644
--- a/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java
+++ b/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java
@@ -122,16 +122,16 @@ public class UserProfile implements DatabaseObject {
 
     @Override
     public PreparedStatement getInsert(PreparedStatement ps) throws Exception {
-        ps.setString(1, username);
-        ps.setString(2, firstName);
-        ps.setString(3, lastName);
-        ps.setString(4, email);
-        ps.setString(5, profilePicture);
-        ps.setString(6, organization);
-        ps.setString(7, phoneNumber);
-        ps.setString(8, phoneNumberExtension);
-        ps.setString(9, faxNumber);
-        ps.setString(10, mobileNumber);
+        ps.setString(1, firstName);
+        ps.setString(2, lastName);
+        ps.setString(3, email);
+        ps.setString(4, profilePicture);
+        ps.setString(5, organization);
+        ps.setString(6, phoneNumber);
+        ps.setString(7, phoneNumberExtension);
+        ps.setString(8, faxNumber);
+        ps.setString(9, mobileNumber);
+        ps.setString(10, username);
         return ps;
     }
 
diff --git a/jams-common/src/test/java/net/jami/jams/common/objects/contacts/ContactTest.java b/jams-common/src/test/java/net/jami/jams/common/objects/contacts/ContactTest.java
index 2a953419..601a34f3 100644
--- a/jams-common/src/test/java/net/jami/jams/common/objects/contacts/ContactTest.java
+++ b/jams-common/src/test/java/net/jami/jams/common/objects/contacts/ContactTest.java
@@ -25,8 +25,8 @@ class ContactTest {
     @Test
     public void deserialize() {
         String str =
-                "[{\"uri\":\"tcp://def@local\",\"added\":1594742298377,\"banned\":false,\"confirmed\":true,\"confirmed\":6a61013979964f70c8fb9183a8b238d58a1846ed},"
-                        + "{\"uri\":\"tcp://abc@19293.com\",\"removed\":1594742298377,\"banned\":true,\"confirmed\":true,\"confirmed\":2b61024119964f70c8fb9183a8b238d58a1846ed}]";
+                "[{\"uri\":\"tcp://def@local\",\"added\":1594742298377,\"banned\":false,\"confirmed\":true,\"conversationId\":\"6a61013979964f70c8fb9183a8b238d58a1846ed\"},"
+                        + "{\"uri\":\"tcp://abc@19293.com\",\"removed\":1594742298377,\"banned\":true,\"confirmed\":true,\"conversationId\":\"2b61024119964f70c8fb9183a8b238d58a1846e\"}]";
         Contact[] contacts = JsonIterator.deserialize(str, Contact[].class);
         Assertions.assertEquals(2, contacts.length);
     }
diff --git a/jams-server/src/main/java/net/jami/jams/server/Server.java b/jams-server/src/main/java/net/jami/jams/server/Server.java
index 40488b8c..4a750d07 100644
--- a/jams-server/src/main/java/net/jami/jams/server/Server.java
+++ b/jams-server/src/main/java/net/jami/jams/server/Server.java
@@ -46,7 +46,7 @@ import net.jami.jams.server.startup.CryptoEngineLoader;
 import net.jami.jams.server.update.JAMSUpdater;
 import net.jami.jams.server.update.UpdateInterface;
 
-import java.awt.*;
+import java.awt.Desktop;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
diff --git a/jams-server/src/main/java/net/jami/jams/server/core/workflows/RegisterDeviceFlow.java b/jams-server/src/main/java/net/jami/jams/server/core/workflows/RegisterDeviceFlow.java
index ccc9a912..ed742f18 100644
--- a/jams-server/src/main/java/net/jami/jams/server/core/workflows/RegisterDeviceFlow.java
+++ b/jams-server/src/main/java/net/jami/jams/server/core/workflows/RegisterDeviceFlow.java
@@ -32,21 +32,15 @@ import lombok.extern.slf4j.Slf4j;
 
 import net.jami.jams.authmodule.UserAuthenticationModule;
 import net.jami.jams.common.authmodule.AuthModuleKey;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.devices.Device;
 import net.jami.jams.common.objects.requests.DeviceRegistrationRequest;
 import net.jami.jams.common.objects.responses.DeviceRegistrationResponse;
-import net.jami.jams.common.objects.user.Group;
-import net.jami.jams.common.objects.user.Policy;
 import net.jami.jams.common.objects.user.User;
-import net.jami.jams.common.objects.user.UserGroupMapping;
 import net.jami.jams.common.objects.user.UserProfile;
 import net.jami.jams.dht.DeviceReceiptGenerator;
 
 import java.security.cert.X509Certificate;
 import java.util.Date;
-import java.util.List;
 import java.util.Optional;
 
 @Slf4j
@@ -55,9 +49,7 @@ public class RegisterDeviceFlow {
     public static DeviceRegistrationResponse registerDevice(
             String username, DeviceRegistrationRequest registrationRequest) {
         try {
-            StatementList statementList = new StatementList();
-            statementList.addStatement(new StatementElement("username", "=", username, ""));
-            User user = dataStore.getUserDao().getObjects(statementList).get(0);
+            User user = dataStore.getUserDao().getByUsername(username).orElseThrow();
 
             UserProfile userProfile =
                     userAuthenticationModule
@@ -66,11 +58,6 @@ public class RegisterDeviceFlow {
                             .searchUserProfiles(username, "LOGON_NAME", Optional.empty())
                             .get(0);
 
-            if (user == null) {
-                log.error(
-                        "Tried to enroll a device, but could not find a user, this is impossible!");
-            }
-
             // Renew user certificate if expired with same private key
             if (!user.getCertificate().getNotAfter().after(new Date())) {
                 user = UserAuthenticationModule.certificateAuthority.getRefreshedCertificate(user);
@@ -88,10 +75,8 @@ public class RegisterDeviceFlow {
             }
             dataStore.getDeviceDao().storeObject(device);
 
-            Group group = getGroupByUsername(username);
-
             DeviceRegistrationResponse response = new DeviceRegistrationResponse();
-            String policyData = getPolicyData(group);
+            String policyData = getPolicyData(username);
             if (policyData != null) {
                 response.setPolicyData(policyData);
             }
@@ -124,39 +109,17 @@ public class RegisterDeviceFlow {
         }
     }
 
-    public static Group getGroupByUsername(String username) {
-        Group group = new Group();
-
-        StatementList statementList = new StatementList();
-        statementList.addStatement(new StatementElement("username", "=", username, ""));
-        List<UserGroupMapping> userGroupMappings =
-                dataStore.getUserGroupMappingsDao().getObjects(statementList);
-
-        if (userGroupMappings != null && !userGroupMappings.isEmpty()) {
-            UserGroupMapping mapping = userGroupMappings.get(0);
-            statementList = new StatementList();
-            statementList.addStatement(new StatementElement("id", "=", mapping.getGroupId(), ""));
-            group = dataStore.getGroupDao().getObjects(statementList).get(0);
-        }
-
-        return group;
-    }
-
-    public static String getPolicyData(Group group) {
-        if (!group.isEmpty() && group.hasBlueprint()) {
-            StatementElement statementElement =
-                    new StatementElement("name", "=", group.getBlueprint(), "");
-            StatementList statementList = new StatementList();
-            statementList.addStatement(statementElement);
-            try {
-                Policy policy = dataStore.getPolicyDao().getObjects(statementList).get(0);
-                return policy.getPolicyData();
-            } catch (Exception e) {
-                log.warn(
-                        "No policy available for user - not adding a policy component to response");
-            }
+    public static String getPolicyData(String username) {
+        String policy =
+                dataStore
+                        .getPolicyDao()
+                        .getByUsername(username)
+                        .map(p -> p.getPolicyData())
+                        .orElse(null);
+        if (policy == null) {
+            log.warn("No policy available for user - not adding a policy component to response");
         }
 
-        return null;
+        return policy;
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/core/workflows/RevokeDeviceFlow.java b/jams-server/src/main/java/net/jami/jams/server/core/workflows/RevokeDeviceFlow.java
index 410d2a73..1d0a112f 100644
--- a/jams-server/src/main/java/net/jami/jams/server/core/workflows/RevokeDeviceFlow.java
+++ b/jams-server/src/main/java/net/jami/jams/server/core/workflows/RevokeDeviceFlow.java
@@ -27,14 +27,13 @@ import static net.jami.jams.server.Server.dataStore;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.devices.Device;
 import net.jami.jams.common.objects.requests.RevocationRequest;
 import net.jami.jams.common.objects.requests.RevocationType;
 import net.jami.jams.common.objects.responses.DeviceRevocationResponse;
 
 import java.math.BigInteger;
+import java.util.Optional;
 
 @Slf4j
 public class RevokeDeviceFlow {
@@ -42,17 +41,15 @@ public class RevokeDeviceFlow {
     public static DeviceRevocationResponse revokeDevice(String username, String deviceId) {
         DeviceRevocationResponse response = new DeviceRevocationResponse();
         try {
-            StatementList statementList = new StatementList();
-            StatementElement st1 = new StatementElement("owner", "=", username, "AND");
-            StatementElement st2 = new StatementElement("deviceId", "=", deviceId, "");
-            statementList.addStatement(st1);
-            statementList.addStatement(st2);
-            Device device = dataStore.getDeviceDao().getObjects(statementList).get(0);
-            if (device == null) {
+            Optional<Device> result =
+                    dataStore.getDeviceDao().getByDeviceIdAndOwner(deviceId, username);
+            if (result.isEmpty()) {
                 log.error("Could not find device!");
                 return null;
             }
 
+            Device device = result.get();
+
             BigInteger serialNumber = device.getCertificate().getSerialNumber();
 
             RevocationRequest request = new RevocationRequest(serialNumber, RevocationType.DEVICE);
diff --git a/jams-server/src/main/java/net/jami/jams/server/core/workflows/RevokeUserFlow.java b/jams-server/src/main/java/net/jami/jams/server/core/workflows/RevokeUserFlow.java
index a7193298..0b2a1c93 100644
--- a/jams-server/src/main/java/net/jami/jams/server/core/workflows/RevokeUserFlow.java
+++ b/jams-server/src/main/java/net/jami/jams/server/core/workflows/RevokeUserFlow.java
@@ -27,8 +27,6 @@ import static net.jami.jams.server.Server.dataStore;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.requests.RevocationRequest;
 import net.jami.jams.common.objects.requests.RevocationType;
 import net.jami.jams.common.objects.responses.DeviceRevocationResponse;
@@ -40,10 +38,7 @@ public class RevokeUserFlow {
     public static DeviceRevocationResponse revokeUser(String username) {
         DeviceRevocationResponse response = new DeviceRevocationResponse();
         try {
-            StatementList statementList = new StatementList();
-            StatementElement st1 = new StatementElement("username", "=", username, "");
-            statementList.addStatement(st1);
-            User user = dataStore.getUserDao().getObjects(statementList).get(0);
+            User user = dataStore.getUserDao().getByUsername(username).get();
             if (user == null) {
                 log.error("Could not find user!");
                 return null;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/LoginServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/LoginServlet.java
index 34940230..1ba1ba3c 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/LoginServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/LoginServlet.java
@@ -37,15 +37,13 @@ import jakarta.servlet.http.HttpServletResponse;
 
 import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.authmodule.AuthTokenResponse;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.User;
 import net.jami.jams.common.serialization.tomcat.TomcatCustomErrorHandler;
 import net.jami.jams.server.servlets.api.auth.login.LoginRequest;
 
 import java.io.IOException;
 import java.security.cert.X509Certificate;
-import java.util.List;
+import java.util.Optional;
 
 @WebServlet("/api/login")
 // This method returns the token which is used for all the next calls to the
@@ -86,19 +84,15 @@ public class LoginServlet extends HttpServlet {
                             req.getInputStream().readAllBytes(), LoginRequest.class);
             if (object.getUsername() != null && object.getPassword() != null) {
                 res = processUsernamePasswordAuth(object.getUsername(), object.getPassword());
-                StatementList statementList = new StatementList();
-                StatementElement statementElement =
-                        new StatementElement("username", "=", object.getUsername(), "");
-                statementList.addStatement(statementElement);
-                List<User> users = dataStore.getUserDao().getObjects(statementList);
-                if (users.size() != 0
+                Optional<User> user = dataStore.getUserDao().getByUsername(object.getUsername());
+                if (user.isPresent()
                         && certificateAuthority.getLatestCRL().get() != null
-                        && !users.get(0).getAccessLevelName().equals("ADMIN")
+                        && !user.get().getAccessLevelName().equals("ADMIN")
                         && certificateAuthority
                                         .getLatestCRL()
                                         .get()
                                         .getRevokedCertificate(
-                                                users.get(0).getCertificate().getSerialNumber())
+                                                user.get().getCertificate().getSerialNumber())
                                 != null) {
                     TomcatCustomErrorHandler.sendCustomError(
                             resp, 401, "Invalid credentials provided!");
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/contacts/ContactServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/contacts/ContactServlet.java
index fd1df0c1..6149f387 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/contacts/ContactServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/contacts/ContactServlet.java
@@ -35,8 +35,6 @@ import jakarta.servlet.http.HttpServletResponse;
 
 import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.annotations.ScopedServletMethod;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.contacts.Contact;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.serialization.tomcat.TomcatCustomErrorHandler;
@@ -69,10 +67,8 @@ public class ContactServlet extends HttpServlet {
     @JsonContent
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        StatementList statementList = new StatementList();
-        statementList.addStatement(
-                new StatementElement("owner", "=", req.getParameter("username"), ""));
-        List<Contact> contactList = dataStore.getContactDao().getObjects(statementList);
+        List<Contact> contactList =
+                dataStore.getContactDao().getByOwner(req.getParameter("username"));
         resp.getOutputStream().write(JsonStream.serialize(contactList).getBytes());
     }
 
@@ -96,6 +92,7 @@ public class ContactServlet extends HttpServlet {
         Scanner s = new Scanner(req.getInputStream()).useDelimiter("\\A");
         String res = s.hasNext() ? s.next() : "";
         final JSONObject obj = new JSONObject(res);
+
         Contact contact = new Contact();
         // TODO: Replace with mergetool.
         contact.setDisplayName(obj.get("displayName").toString());
@@ -103,13 +100,13 @@ public class ContactServlet extends HttpServlet {
         contact.setStatus('A');
         contact.setOwner(req.getParameter("username"));
         contact.setUri(obj.get("uri").toString());
-        StatementList statementList = new StatementList();
-        statementList.addStatement(
-                new StatementElement("owner", "=", req.getParameter("username"), ""));
-        List<Contact> localList = dataStore.getContactDao().getObjects(statementList);
+
+        List<Contact> localList =
+                dataStore.getContactDao().getByOwner(req.getParameter("username"));
         List<Contact> remoteList = new ArrayList<>();
         remoteList.add(contact);
         List<Contact> result = ContactMerger.mergeContacts(localList, remoteList);
+
         if (dataStore.getContactDao().storeContactList(result)) resp.setStatus(200);
         else
             TomcatCustomErrorHandler.sendCustomError(
@@ -131,22 +128,9 @@ public class ContactServlet extends HttpServlet {
     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN})
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        StatementList statementList = new StatementList();
-        statementList.addStatement(
-                new StatementElement("owner", "=", req.getParameter("username"), "AND"));
-        statementList.addStatement(new StatementElement("uri", "=", req.getParameter("uri"), ""));
-        /*
-         * List<Contact> remoteList =
-         * dataStore.getContactDao().getObjects(statementList);
-         * remoteList.get(0).setStatus('D');
-         * remoteList.get(0).setTimestamp(System.currentTimeMillis()); statementList =
-         * new StatementList(); statementList.addStatement(new
-         * StatementElement("owner","=",req.getParameter("username").toString(),""));
-         * List<Contact> localList =
-         * dataStore.getContactDao().getObjects(statementList); List<Contact> result =
-         * ContactMerger.mergeContacts(localList,remoteList);
-         */
-        if (dataStore.getContactDao().deleteObject(statementList)) resp.setStatus(200);
+        String owner = req.getParameter("username");
+        String uri = req.getParameter("uri");
+        if (dataStore.getContactDao().deleteObject(owner, uri)) resp.setStatus(200);
         else
             TomcatCustomErrorHandler.sendCustomError(
                     resp, 500, "could not delete a contact due to server-side error");
@@ -170,16 +154,16 @@ public class ContactServlet extends HttpServlet {
     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN})
     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        StatementList statementList = new StatementList();
-        statementList.addStatement(
-                new StatementElement("owner", "=", req.getParameter("username"), ""));
-        List<Contact> localList = dataStore.getContactDao().getObjects(statementList);
+        List<Contact> localList =
+                dataStore.getContactDao().getByOwner(req.getParameter("username"));
         List<Contact> remoteList =
                 Arrays.asList(
                         JsonIterator.deserialize(
                                 req.getInputStream().readAllBytes(), Contact[].class));
+
         remoteList.forEach(contact -> contact.setOwner(req.getParameter("username")));
         List<Contact> result = ContactMerger.mergeContacts(localList, remoteList);
+
         if (!dataStore.getContactDao().storeContactList(result))
             TomcatCustomErrorHandler.sendCustomError(resp, 500, "Could not store contacts!");
         else resp.getOutputStream().write(JsonStream.serialize(result).getBytes());
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DeviceServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DeviceServlet.java
index 100bf578..656f3c22 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DeviceServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DeviceServlet.java
@@ -33,8 +33,7 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
 import net.jami.jams.common.annotations.ScopedServletMethod;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
+import net.jami.jams.common.objects.devices.Device;
 import net.jami.jams.common.objects.responses.DeviceRevocationResponse;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.server.core.workflows.RevokeDeviceFlow;
@@ -51,16 +50,9 @@ public class DeviceServlet extends HttpServlet {
             throws ServletException, IOException {
         String username = req.getParameter("username");
         String deviceId = req.getParameter("deviceId");
-        StatementList statementList = new StatementList();
-        StatementElement st1 = new StatementElement("owner", "=", username, "AND");
-        StatementElement st2 = new StatementElement("deviceId", "=", deviceId, "");
-        statementList.addStatement(st1);
-        statementList.addStatement(st2);
-        resp.getOutputStream()
-                .write(
-                        JsonStream.serialize(
-                                        dataStore.getDeviceDao().getObjects(statementList).get(0))
-                                .getBytes());
+        Device device =
+                dataStore.getDeviceDao().getByDeviceIdAndOwner(deviceId, username).orElseThrow();
+        resp.getOutputStream().write(JsonStream.serialize(device).getBytes());
     }
 
     // Update device data.
@@ -71,15 +63,9 @@ public class DeviceServlet extends HttpServlet {
         String username = req.getParameter("username");
         String deviceId = req.getParameter("deviceId");
         String deviceName = req.getParameter("deviceName");
-        StatementList update = new StatementList();
-        StatementElement st0 = new StatementElement("deviceName", "=", deviceName, "");
-        update.addStatement(st0);
-        StatementList constraint = new StatementList();
-        StatementElement st1 = new StatementElement("owner", "=", username, "AND");
-        StatementElement st2 = new StatementElement("deviceId", "=", deviceId, "");
-        update.addStatement(st1);
-        update.addStatement(st2);
-        if (dataStore.getDeviceDao().updateObject(update, constraint)) resp.setStatus(200);
+
+        if (dataStore.getDeviceDao().updateObject(deviceName, username, deviceId))
+            resp.setStatus(200);
         else resp.sendError(500, "could not update the device's information!");
     }
 
@@ -88,9 +74,9 @@ public class DeviceServlet extends HttpServlet {
     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN})
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        DeviceRevocationResponse devResponse =
-                RevokeDeviceFlow.revokeDevice(
-                        req.getParameter("username"), req.getParameter("deviceId"));
+        String username = req.getParameter("username");
+        String deviceId = req.getParameter("deviceId");
+        DeviceRevocationResponse devResponse = RevokeDeviceFlow.revokeDevice(username, deviceId);
         if (devResponse != null)
             resp.getOutputStream().write(JsonStream.serialize(devResponse).getBytes());
         else resp.sendError(500, "An exception has occurred while trying to revoke a device!");
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DevicesServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DevicesServlet.java
index 4697c5a1..a4b3de09 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DevicesServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DevicesServlet.java
@@ -35,8 +35,6 @@ import jakarta.servlet.http.HttpServletResponse;
 
 import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.annotations.ScopedServletMethod;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.devices.Device;
 import net.jami.jams.common.objects.user.AccessLevel;
 
@@ -53,9 +51,7 @@ public class DevicesServlet extends HttpServlet {
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
         String username = req.getParameter("username");
-        StatementList statementList = new StatementList();
-        statementList.addStatement(new StatementElement("owner", "=", username, ""));
-        List<Device> devices = dataStore.getDeviceDao().getObjects(statementList);
+        List<Device> devices = dataStore.getDeviceDao().getByOwner(username);
         if (certificateAuthority.getLatestCRL() != null) {
             devices.forEach(
                     device -> {
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java
index 97266012..faba6795 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java
@@ -41,8 +41,6 @@ import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.annotations.ScopedServletMethod;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.authmodule.AuthModuleKey;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.User;
 import net.jami.jams.common.objects.user.UserProfile;
@@ -97,16 +95,12 @@ public class DirectoryEntryServlet extends HttpServlet {
         // Check if he is AD/LDAP - then return a 500, because we can't update those profile datas.
         UserProfile userProfile =
                 JsonIterator.deserialize(req.getInputStream().readAllBytes(), UserProfile.class);
-        StatementList select = new StatementList();
-        StatementElement st = new StatementElement("username", "=", userProfile.getUsername(), "");
-        select.addStatement(st);
 
-        User targetUser = dataStore.getUserDao().getObjects(select).get(0);
-        select = new StatementList();
-        st = new StatementElement("username", "=", req.getAttribute("username").toString(), "");
-        select.addStatement(st);
+        String username = req.getAttribute("username").toString();
 
-        User callingUser = dataStore.getUserDao().getObjects(select).get(0);
+        User targetUser =
+                dataStore.getUserDao().getByUsername(userProfile.getUsername()).orElseThrow();
+        User callingUser = dataStore.getUserDao().getByUsername(username).orElseThrow();
 
         if (targetUser.getUserType() != AuthenticationSourceType.LOCAL) {
             resp.sendError(
@@ -117,16 +111,14 @@ public class DirectoryEntryServlet extends HttpServlet {
         if (callingUser.getAccessLevel() == AccessLevel.ADMIN
                 || (callingUser.getAccessLevel() == AccessLevel.USER
                         && callingUser.getUsername().equals(targetUser.getUsername()))) {
-            select = new StatementList();
-            select.addStatement(
-                    new StatementElement("username", "=", userProfile.getUsername(), ""));
             if (dataStore.updateUserProfile(userProfile)) resp.setStatus(200);
             else resp.sendError(500, "Could not update the users's profile information");
-        } else {
-            resp.sendError(
-                    403,
-                    "The user is either not an admin account or is attempting to edit a profile that is not his own!");
+
+            return;
         }
+        resp.sendError(
+                403,
+                "The user is either not an admin account or is attempting to edit a profile that is not his own!");
     }
 
     @Override
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupServlet.java
index 489de813..e6e0c668 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupServlet.java
@@ -14,14 +14,13 @@ import lombok.extern.slf4j.Slf4j;
 
 import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.annotations.ScopedServletMethod;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.Group;
 
 import org.json.JSONObject;
 
 import java.io.IOException;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 @WebServlet("/api/admin/group/*")
@@ -33,18 +32,13 @@ public class GroupServlet extends HttpServlet {
     @JsonContent
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        Group singleGroup = null;
         String id = req.getPathInfo().replace("/", "");
 
-        StatementList statementList = new StatementList();
-        StatementElement st = new StatementElement("id", "=", id, "");
+        Optional<Group> singleGroup = dataStore.getGroupDao().getById(id);
 
-        statementList.addStatement(st);
-        if (!dataStore.getGroupDao().getObjects(statementList).isEmpty())
-            singleGroup = dataStore.getGroupDao().getObjects(statementList).get(0);
-
-        if (singleGroup != null) {
-            resp.getOutputStream().write(JsonStream.serialize(singleGroup).getBytes());
+        if (singleGroup.isPresent()) {
+            resp.getOutputStream()
+                    .write(JsonStream.serialize(singleGroup.orElseThrow()).getBytes());
             resp.setStatus(200);
         } else {
             log.info("No group with this id was found!");
@@ -56,7 +50,6 @@ public class GroupServlet extends HttpServlet {
     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN})
     @JsonContent
     protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
-
         String id = req.getPathInfo().replace("/", "");
 
         final JSONObject obj =
@@ -68,20 +61,7 @@ public class GroupServlet extends HttpServlet {
         String name = obj.getString("name");
         String blueprint = obj.getString("blueprint");
 
-        StatementList update = new StatementList();
-
-        StatementElement st0 = new StatementElement("id", "=", id, "");
-        update.addStatement(st0);
-
-        StatementElement st1 = new StatementElement("name", "=", name, "");
-        update.addStatement(st1);
-
-        StatementElement st2 = new StatementElement("blueprint", "=", blueprint, "");
-        update.addStatement(st2);
-
-        StatementList constraint = new StatementList();
-
-        if (dataStore.getGroupDao().updateObject(update, constraint)) resp.setStatus(200);
+        if (dataStore.getGroupDao().updateObject(id, name, blueprint)) resp.setStatus(200);
         else resp.sendError(500, "Could not update group!");
     }
 
@@ -89,20 +69,10 @@ public class GroupServlet extends HttpServlet {
     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN})
     @JsonContent
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {
-        String id = req.getPathInfo().replace("/", "");
+        String groupId = req.getPathInfo().replace("/", "");
 
-        StatementElement statementElement = new StatementElement("id", "=", id, "");
-
-        StatementList constraint = new StatementList();
-        constraint.addStatement(statementElement);
-        if (dataStore.getGroupDao().deleteObject(constraint)) {
-            StatementElement statementElement1 = new StatementElement("username", "=", "*", "");
-            StatementElement statementElement2 = new StatementElement("groupId", "=", id, "");
-            StatementList constraintMapping = new StatementList();
-            constraintMapping.addStatement(statementElement1);
-            constraintMapping.addStatement(statementElement2);
-            if (dataStore.getUserGroupMappingsDao().deleteObject(constraintMapping))
-                resp.setStatus(200);
+        if (dataStore.getGroupDao().deleteObject(groupId)) {
+            if (dataStore.getUserGroupMappingsDao().deleteObject("*", groupId)) resp.setStatus(200);
             else resp.sendError(500, "Could not delete the group mappings successfully!");
         } else {
             resp.sendError(500, "Could not delete the group successfully!");
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupsServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupsServlet.java
index 9b5d34e6..38c7b761 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupsServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/GroupsServlet.java
@@ -30,7 +30,7 @@ public class GroupsServlet extends HttpServlet {
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
 
-        List<Group> groups = dataStore.getGroupDao().getObjects(null);
+        List<Group> groups = dataStore.getGroupDao().getAll();
 
         if (!groups.isEmpty()) {
             resp.getOutputStream().write(JsonStream.serialize(groups).getBytes());
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/PolicyProfileServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/PolicyProfileServlet.java
index 174ededd..06c5f0ce 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/PolicyProfileServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/PolicyProfileServlet.java
@@ -14,13 +14,12 @@ import lombok.extern.slf4j.Slf4j;
 
 import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.annotations.ScopedServletMethod;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.Policy;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Optional;
 
 @WebServlet("/api/admin/policy/*")
 @Slf4j
@@ -31,29 +30,26 @@ public class PolicyProfileServlet extends HttpServlet {
     @JsonContent
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-
-        List<Policy> policies;
         String name = req.getPathInfo().replace("/", "");
+        getPolicyAndSendResponse(resp, name);
+    }
 
-        if (!name.equals("*")) {
-            StatementList statementList = new StatementList();
-            StatementElement st = new StatementElement("name", "=", name, "");
-            statementList.addStatement(st);
-            if (!dataStore.getPolicyDao().getObjects(statementList).isEmpty()) {
-                resp.getOutputStream()
-                        .write(
-                                JsonStream.serialize(
-                                                dataStore
-                                                        .getPolicyDao()
-                                                        .getObjects(statementList)
-                                                        .get(0))
-                                        .getBytes());
-                resp.setStatus(200);
-            }
-        } else {
-            policies = dataStore.getPolicyDao().getObjects(null);
+    public static void getPolicyAndSendResponse(HttpServletResponse resp, String name)
+            throws IOException {
+        if (name.equals("*")) {
+            List<Policy> policies = dataStore.getPolicyDao().getAll();
             resp.getOutputStream().write(JsonStream.serialize(policies).getBytes());
             resp.setStatus(200);
+            return;
+        }
+
+        Optional<Policy> policy = dataStore.getPolicyDao().getByName(name);
+        if (policy.isPresent()) {
+            byte[] bytes = JsonStream.serialize(policy.orElseThrow()).getBytes();
+            resp.getOutputStream().write(bytes);
+            resp.setStatus(200);
+        } else {
+            resp.sendError(404, "{\"message\": \"No policy found.\"}");
         }
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/PolicyServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/PolicyServlet.java
index 09ca1d93..c4b83690 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/PolicyServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/PolicyServlet.java
@@ -2,8 +2,6 @@ package net.jami.jams.server.servlets.api.admin.group;
 
 import static net.jami.jams.server.Server.dataStore;
 
-import com.jsoniter.output.JsonStream;
-
 import jakarta.servlet.ServletException;
 import jakarta.servlet.annotation.WebServlet;
 import jakarta.servlet.http.HttpServlet;
@@ -14,15 +12,12 @@ import lombok.extern.slf4j.Slf4j;
 
 import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.annotations.ScopedServletMethod;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.Policy;
 
 import org.json.JSONObject;
 
 import java.io.IOException;
-import java.util.List;
 import java.util.Scanner;
 
 @Slf4j
@@ -34,27 +29,8 @@ public class PolicyServlet extends HttpServlet {
     @JsonContent
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-
-        List<Policy> policies;
         String name = req.getParameter("name");
-
-        if (!name.equals("*")) {
-            StatementList statementList = new StatementList();
-            StatementElement st = new StatementElement("name", "=", name, "");
-            statementList.addStatement(st);
-            policies = dataStore.getPolicyDao().getObjects(statementList);
-            if (!policies.isEmpty()) {
-                resp.getOutputStream().write(JsonStream.serialize(policies.get(0)).getBytes());
-                resp.setStatus(200);
-            } else {
-                resp.setStatus(404); // 404 status code for Not Found
-                resp.getWriter().write("{\"message\": \"No policy found.\"}");
-            }
-        } else {
-            policies = dataStore.getPolicyDao().getObjects(null);
-            resp.getOutputStream().write(JsonStream.serialize(policies).getBytes());
-            resp.setStatus(200);
-        }
+        PolicyProfileServlet.getPolicyAndSendResponse(resp, name);
     }
 
     @Override
@@ -65,17 +41,9 @@ public class PolicyServlet extends HttpServlet {
         Scanner s = new Scanner(req.getInputStream()).useDelimiter("\\A");
         String result = s.hasNext() ? s.next() : "";
         final JSONObject obj = new JSONObject(result);
-        final String jsonString = obj.toString();
+        final String policyData = obj.toString();
 
-        StatementList update = new StatementList();
-        StatementElement st0 = new StatementElement("name", "=", name, "");
-        update.addStatement(st0);
-        StatementElement st2 = new StatementElement("policyData", "=", jsonString, "");
-        update.addStatement(st2);
-        StatementList constraint = new StatementList();
-        StatementElement st3 = new StatementElement("name", "=", name, "");
-        constraint.addStatement(st3);
-        if (dataStore.getPolicyDao().updateObject(update, constraint)) resp.setStatus(200);
+        if (dataStore.getPolicyDao().updateObject(name, policyData)) resp.setStatus(200);
         else resp.sendError(500, "could not update the group's name!");
     }
 
@@ -102,10 +70,10 @@ public class PolicyServlet extends HttpServlet {
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {
         String name = req.getParameter("name");
 
-        StatementElement statementElement = new StatementElement("name", "=", name, "");
-        StatementList constraint = new StatementList();
-        constraint.addStatement(statementElement);
-        if (dataStore.getPolicyDao().deleteObject(constraint)) resp.setStatus(200);
+        if (dataStore.getPolicyDao().deleteObject(name)) {
+            resp.setStatus(200);
+            return;
+        }
 
         resp.sendError(500, "Could not delete the blueprint successfully!");
     }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/UserGroupServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/UserGroupServlet.java
index 6a9462a3..ab32114b 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/UserGroupServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/group/UserGroupServlet.java
@@ -13,8 +13,6 @@ import lombok.extern.slf4j.Slf4j;
 
 import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.annotations.ScopedServletMethod;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.UserGroupMapping;
 
@@ -22,6 +20,7 @@ import org.json.JSONObject;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 @WebServlet("/api/admin/group/members/*")
@@ -47,13 +46,7 @@ public class UserGroupServlet extends HttpServlet {
 
         String groupId = req.getPathInfo().replace("/", "");
 
-        StatementList statementList = new StatementList();
-        StatementElement st = new StatementElement("groupId", "=", groupId, "");
-
-        statementList.addStatement(st);
-
-        List<UserGroupMapping> result =
-                dataStore.getUserGroupMappingsDao().getObjects(statementList);
+        List<UserGroupMapping> result = dataStore.getUserGroupMappingsDao().getByGroupId(groupId);
 
         if (result.isEmpty()) resp.sendError(404, "No users found for this group!");
         else {
@@ -77,17 +70,15 @@ public class UserGroupServlet extends HttpServlet {
 
         String username = obj.getString("username");
 
-        StatementList statementList = new StatementList();
-        statementList.addStatement(new StatementElement("groupId", "=", groupId, "AND"));
-        statementList.addStatement(new StatementElement("username", "=", username, ""));
+        Optional<UserGroupMapping> existingMapping =
+                dataStore.getUserGroupMappingsDao().getByGroupIdAndUsername(groupId, username);
 
-        if (!dataStore.getUserGroupMappingsDao().getObjects(statementList).isEmpty()) {
+        if (existingMapping.isPresent()) {
             resp.sendError(409, "The user already part of the group!");
             return;
         }
 
         UserGroupMapping mapping = new UserGroupMapping();
-
         mapping.setGroupId(groupId);
         mapping.setUsername(username);
 
@@ -111,13 +102,7 @@ public class UserGroupServlet extends HttpServlet {
 
         String username = obj.getString("username");
 
-        StatementElement statementElement1 = new StatementElement("username", "=", username, "AND");
-        StatementElement statementElement2 = new StatementElement("groupId", "=", groupId, "");
-
-        StatementList constraint = new StatementList();
-        constraint.addStatement(statementElement1);
-        constraint.addStatement(statementElement2);
-        if (dataStore.getUserGroupMappingsDao().deleteObject(constraint)) {
+        if (dataStore.getUserGroupMappingsDao().deleteObject(username, groupId)) {
             resp.setStatus(200);
         } else {
             resp.sendError(500, "Could not delete mapping between user and group!");
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserGroupsServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserGroupsServlet.java
index 8dfbdba3..796e78d5 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserGroupsServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserGroupsServlet.java
@@ -13,8 +13,6 @@ import lombok.extern.slf4j.Slf4j;
 
 import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.annotations.ScopedServletMethod;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.UserGroupMapping;
 
@@ -45,13 +43,7 @@ public class UserGroupsServlet extends HttpServlet {
 
         String username = req.getPathInfo().replace("/", "");
 
-        StatementList statementList = new StatementList();
-        StatementElement st = new StatementElement("username", "=", username, "");
-
-        statementList.addStatement(st);
-
-        List<UserGroupMapping> result =
-                dataStore.getUserGroupMappingsDao().getObjects(statementList);
+        List<UserGroupMapping> result = dataStore.getUserGroupMappingsDao().getByUsername(username);
 
         if (result.isEmpty()) resp.sendError(404, "No groups found for this user!");
         else {
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserServlet.java
index ee33defd..0e7ab354 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserServlet.java
@@ -39,8 +39,6 @@ import net.jami.jams.authmodule.PasswordUtil;
 import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.annotations.ScopedServletMethod;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.devices.Device;
 import net.jami.jams.common.objects.responses.DeviceRevocationResponse;
 import net.jami.jams.common.objects.user.AccessLevel;
@@ -49,11 +47,14 @@ import net.jami.jams.server.core.workflows.RevokeDeviceFlow;
 import net.jami.jams.server.core.workflows.RevokeUserFlow;
 
 import org.apache.commons.codec.binary.Base64;
+import org.bouncycastle.cert.X509CRLEntryHolder;
+import org.bouncycastle.cert.X509CRLHolder;
 import org.json.JSONObject;
 
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
@@ -64,48 +65,37 @@ public class UserServlet extends HttpServlet {
     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN})
     @JsonContent
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
-        StatementList statementList = new StatementList();
-        StatementElement st1 =
-                new StatementElement("username", "=", req.getParameter("username"), "");
-        statementList.addStatement(st1);
-        if (!dataStore.getUserDao().getObjects(statementList).isEmpty()) {
-            User user = dataStore.getUserDao().getObjects(statementList).get(0);
-            if (certificateAuthority.getLatestCRL().get() != null)
-                user.setRevoked(
-                        certificateAuthority
-                                        .getLatestCRL()
-                                        .get()
-                                        .getRevokedCertificate(
-                                                user.getCertificate().getSerialNumber())
-                                != null);
-            else user.setRevoked(false);
-            if (!user.getNeedsPasswordReset() && req.getParameter("needPW") != null) {
-                String pw =
-                        PasswordUtil.hashPassword(
-                                req.getParameter("password"), Base64.decodeBase64(user.getSalt()));
-                StatementList update = new StatementList();
-                StatementElement st0 = new StatementElement("password", "=", pw, "");
-                update.addStatement(st0);
-                StatementList constraint = new StatementList();
-                StatementElement st =
-                        new StatementElement("username", "=", req.getParameter("username"), "");
-                constraint.addStatement(st);
-                StatementElement st2 = new StatementElement("needsPasswordReset", "=", "true", "");
-                update.addStatement(st2);
-                // refresh variable
-                dataStore.getUserDao().updateObject(update, constraint);
-                user = dataStore.getUserDao().getObjects(statementList).get(0);
-            }
-            user.setPassword("");
-            user.setSalt("");
-            resp.getOutputStream().write(JsonStream.serialize(user).getBytes());
-            resp.setStatus(200);
-        } else {
+        String username = req.getParameter("username");
+        Optional<User> result = dataStore.getUserDao().getByUsername(username);
+        if (result.isEmpty()) {
             resp.sendError(404, "Could not obtain user!");
         }
+
+        User user = result.get();
+        X509CRLHolder crl = certificateAuthority.getLatestCRL().get();
+        if (crl != null) {
+            X509CRLEntryHolder revoked =
+                    crl.getRevokedCertificate(user.getCertificate().getSerialNumber());
+            user.setRevoked(revoked != null);
+        } else {
+            user.setRevoked(false);
+        }
+
+        if (!user.getNeedsPasswordReset() && req.getParameter("needPW") != null) {
+            String pw = req.getParameter("password");
+            String password = PasswordUtil.hashPassword(pw, Base64.decodeBase64(user.getSalt()));
+            dataStore.getUserDao().updateObject(password, username);
+
+            user = dataStore.getUserDao().getByUsername(username).get();
+        }
+        user.setPassword("");
+        user.setSalt("");
+        resp.getOutputStream().write(JsonStream.serialize(user).getBytes());
+        resp.setStatus(200);
     }
-    // Create an internal user - this is always technically available, because internal users have
-    // the right to exist.
+
+    // Create an internal user - this is always technically available, because
+    // internal users have the right to exist.
     @Override
     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN})
     @JsonContent
@@ -116,29 +106,39 @@ public class UserServlet extends HttpServlet {
                         req.getReader()
                                 .lines()
                                 .collect(Collectors.joining(System.lineSeparator())));
-        String pw = obj.getString("password");
-        if (!pw.isEmpty()) {
-            User user = new User();
-            user.setUsername(obj.getString("username"));
-            user.setNeedsPasswordReset(true);
-            byte[] salt = PasswordUtil.generateSalt();
-            pw = PasswordUtil.hashPassword(pw, salt);
-            user.setPassword(pw);
-            user.setSalt(Base64.encodeBase64String(salt));
-            user.setRealm("LOCAL");
-            user.setUserType(AuthenticationSourceType.LOCAL);
-            if (userAuthenticationModule.createUser(
-                    user.getUserType(), user.getRealm(), nameServer, user)) {
-                HashMap<String, String> statusInfo = new HashMap<>();
-                statusInfo.put("password", pw);
-                resp.getOutputStream().write(JsonStream.serialize(statusInfo).getBytes());
-                resp.setStatus(200);
-                return;
-            }
+
+        String password = obj.getString("password");
+
+        if (password.isEmpty()) {
+            resp.sendError(400, "Password is empty!");
+            return;
+        }
+
+        byte[] salt = PasswordUtil.generateSalt();
+        String hashedPassword = PasswordUtil.hashPassword(password, salt);
+
+        String username = obj.getString("username");
+
+        User user = new User();
+        user.setUsername(username);
+        user.setNeedsPasswordReset(true);
+        user.setPassword(hashedPassword);
+        user.setSalt(Base64.encodeBase64String(salt));
+        user.setRealm("LOCAL");
+        user.setUserType(AuthenticationSourceType.LOCAL);
+
+        if (userAuthenticationModule.createUser(
+                user.getUserType(), user.getRealm(), nameServer, user)) {
+            HashMap<String, String> statusInfo = new HashMap<>();
+            statusInfo.put("password", hashedPassword);
+            resp.getOutputStream().write(JsonStream.serialize(statusInfo).getBytes());
+            resp.setStatus(200);
+            return;
         }
 
         resp.sendError(500, "Could not create a user successfully!");
     }
+
     // Update user data.
     @Override
     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN})
@@ -151,17 +151,17 @@ public class UserServlet extends HttpServlet {
         String pw = obj.getString("password");
         String username = obj.getString("username");
 
-        StatementList statementList = new StatementList();
-        StatementElement st0 = new StatementElement("username", "=", username, "");
-        statementList.addStatement(st0);
-        if (dataStore.getUserDao().getObjects(statementList).isEmpty()) {
+        Optional<User> result = dataStore.getUserDao().getByUsername(username);
+
+        if (result.isEmpty()) {
             resp.sendError(404, "User was not found!");
             return;
         }
 
-        User user = dataStore.getUserDao().getObjects(statementList).get(0);
+        User user = result.get();
 
-        // Check if he is AD/LDAP - then return a 403, because we can't set such password.
+        // Check if he is AD/LDAP - then return a 403, because we can't set such
+        // password.
         if (user.getUserType() != AuthenticationSourceType.LOCAL) {
             resp.sendError(
                     500, "The user is not a local user, therefore we cannot change his data!");
@@ -169,29 +169,22 @@ public class UserServlet extends HttpServlet {
         }
 
         byte[] salt = PasswordUtil.generateSalt();
-        StatementList update = new StatementList();
-        StatementElement st1 =
-                new StatementElement("password", "=", PasswordUtil.hashPassword(pw, salt), "");
-        update.addStatement(st1);
-        StatementElement st2 =
-                new StatementElement("salt", "=", Base64.encodeBase64String(salt), "");
-        update.addStatement(st2);
-        StatementList constraint = new StatementList();
-        StatementElement st3 = new StatementElement("username", "=", username, "");
-        constraint.addStatement(st3);
-        if (dataStore.getUserDao().updateObject(update, constraint)) resp.setStatus(200);
+        String password = PasswordUtil.hashPassword(pw, salt);
+        String encodedSalt = Base64.encodeBase64String(salt);
+        if (dataStore.getUserDao().updateObject(password, encodedSalt, username))
+            resp.setStatus(200);
         else resp.sendError(500, "could not update the users's data field!");
     }
+
     // Revoke a user.
     @Override
     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN})
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+        String username = req.getParameter("username");
         AtomicReference<DeviceRevocationResponse> devResponse =
-                new AtomicReference<>(RevokeUserFlow.revokeUser(req.getParameter("username")));
-        StatementList statementList = new StatementList();
-        StatementElement st1 = new StatementElement("owner", "=", req.getParameter("username"), "");
-        statementList.addStatement(st1);
-        List<Device> devices = dataStore.getDeviceDao().getObjects(statementList);
+                new AtomicReference<>(RevokeUserFlow.revokeUser(username));
+        List<Device> devices = dataStore.getDeviceDao().getByOwner(username);
+
         if (certificateAuthority.getLatestCRL() != null) {
             devices.forEach(
                     device -> {
@@ -202,8 +195,7 @@ public class UserServlet extends HttpServlet {
                                                 device.getCertificate().getSerialNumber())
                                 == null)
                             devResponse.set(
-                                    RevokeDeviceFlow.revokeDevice(
-                                            req.getParameter("username"), device.getDeviceId()));
+                                    RevokeDeviceFlow.revokeDevice(username, device.getDeviceId()));
                     });
         }
         if (devResponse.get() != null && devResponse.get().isSuccess()) {
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UsersServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UsersServlet.java
index 6ec96c57..a2f593cb 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UsersServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UsersServlet.java
@@ -46,8 +46,6 @@ public class UsersServlet extends HttpServlet {
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
         resp.getOutputStream()
-                .write(
-                        JsonStream.serialize(dataStore.getUserDao().getObjects(null).get(0))
-                                .getBytes());
+                .write(JsonStream.serialize(dataStore.getUserDao().getAll().get(0)).getBytes());
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java
index 246332af..1eb9d414 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java
@@ -33,8 +33,6 @@ import jakarta.servlet.http.HttpServlet;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.contacts.Contact;
 import net.jami.jams.common.serialization.tomcat.TomcatCustomErrorHandler;
 import net.jami.jams.common.utils.ContactMerger;
@@ -42,7 +40,6 @@ import net.jami.jams.common.utils.ContactMerger;
 import org.json.JSONObject;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Scanner;
@@ -64,10 +61,8 @@ public class ContactServlet extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        StatementList statementList = new StatementList();
-        statementList.addStatement(
-                new StatementElement("owner", "=", req.getAttribute("username").toString(), ""));
-        List<Contact> contactList = dataStore.getContactDao().getObjects(statementList);
+        String username = req.getAttribute("username").toString();
+        List<Contact> contactList = dataStore.getContactDao().getByOwner(username);
         resp.getOutputStream().write(JsonStream.serialize(contactList).getBytes());
     }
 
@@ -90,20 +85,21 @@ public class ContactServlet extends HttpServlet {
         Scanner s = new Scanner(req.getInputStream()).useDelimiter("\\A");
         String res = s.hasNext() ? s.next() : "";
         final JSONObject obj = new JSONObject(res);
-        Contact contact = new Contact();
+
         // TODO: Replace with mergetool.
+        Contact contact = new Contact();
         contact.setDisplayName(obj.get("displayName").toString());
         contact.setTimestamp(System.currentTimeMillis() / 1000);
         contact.setStatus('A');
         contact.setOwner(req.getAttribute("username").toString());
         contact.setUri(obj.get("uri").toString());
-        StatementList statementList = new StatementList();
-        statementList.addStatement(
-                new StatementElement("owner", "=", req.getAttribute("username").toString(), ""));
-        List<Contact> localList = dataStore.getContactDao().getObjects(statementList);
-        List<Contact> remoteList = new ArrayList<>();
-        remoteList.add(contact);
+
+        String owner = req.getAttribute("username").toString();
+        List<Contact> localList = dataStore.getContactDao().getByOwner(owner);
+
+        List<Contact> remoteList = List.of(contact);
         List<Contact> result = ContactMerger.mergeContacts(localList, remoteList);
+
         if (dataStore.getContactDao().storeContactList(result)) resp.setStatus(200);
         else
             TomcatCustomErrorHandler.sendCustomError(
@@ -124,22 +120,10 @@ public class ContactServlet extends HttpServlet {
     @Override
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        StatementList statementList = new StatementList();
-        statementList.addStatement(
-                new StatementElement("owner", "=", req.getAttribute("username").toString(), "AND"));
-        statementList.addStatement(new StatementElement("uri", "=", req.getParameter("uri"), ""));
-        /*
-         * List<Contact> remoteList =
-         * dataStore.getContactDao().getObjects(statementList);
-         * remoteList.get(0).setStatus('D');
-         * remoteList.get(0).setTimestamp(System.currentTimeMillis()); statementList =
-         * new StatementList(); statementList.addStatement(new
-         * StatementElement("owner","=",req.getAttribute("username").toString(),""));
-         * List<Contact> localList =
-         * dataStore.getContactDao().getObjects(statementList); List<Contact> result =
-         * ContactMerger.mergeContacts(localList,remoteList);
-         */
-        if (dataStore.getContactDao().deleteObject(statementList)) resp.setStatus(200);
+        String owner = req.getAttribute("username").toString();
+        String uri = req.getParameter("uri");
+
+        if (dataStore.getContactDao().deleteObject(owner, uri)) resp.setStatus(200);
         else
             TomcatCustomErrorHandler.sendCustomError(
                     resp, 500, "could not delete a contact due to server-side error");
@@ -162,16 +146,16 @@ public class ContactServlet extends HttpServlet {
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        StatementList statementList = new StatementList();
-        statementList.addStatement(
-                new StatementElement("owner", "=", req.getAttribute("username").toString(), ""));
-        List<Contact> localList = dataStore.getContactDao().getObjects(statementList);
+        String owner = req.getAttribute("username").toString();
+        List<Contact> localList = dataStore.getContactDao().getByOwner(owner);
         List<Contact> remoteList =
                 Arrays.asList(
                         JsonIterator.deserialize(
                                 req.getInputStream().readAllBytes(), Contact[].class));
-        remoteList.forEach(contact -> contact.setOwner(req.getAttribute("username").toString()));
+
+        remoteList.forEach(contact -> contact.setOwner(owner));
         List<Contact> result = ContactMerger.mergeContacts(localList, remoteList);
+
         if (!dataStore.getContactDao().storeContactList(result))
             TomcatCustomErrorHandler.sendCustomError(resp, 500, "Could not store contacts!");
         else resp.getOutputStream().write(JsonStream.serialize(result).getBytes());
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DeviceServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DeviceServlet.java
index f812e639..aa3031ec 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DeviceServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DeviceServlet.java
@@ -37,8 +37,6 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
 import net.jami.jams.common.annotations.ScopedServletMethod;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.devices.Device;
 import net.jami.jams.common.objects.requests.DeviceRegistrationRequest;
 import net.jami.jams.common.objects.responses.DeviceRegistrationResponse;
@@ -76,12 +74,10 @@ public class DeviceServlet extends HttpServlet {
             throws ServletException, IOException {
         String username = req.getAttribute("username").toString();
         String deviceId = req.getPathInfo().replace("/", "");
-        StatementList statementList = new StatementList();
-        StatementElement st1 = new StatementElement("owner", "=", username, "AND");
-        StatementElement st2 = new StatementElement("deviceId", "=", deviceId, "");
-        statementList.addStatement(st1);
-        statementList.addStatement(st2);
-        Device device = dataStore.getDeviceDao().getObjects(statementList).get(0);
+
+        Device device =
+                dataStore.getDeviceDao().getByDeviceIdAndOwner(deviceId, username).orElseThrow();
+
         if (certificateAuthority.getLatestCRL().get() != null)
             device.setRevoked(
                     certificateAuthority
@@ -123,11 +119,14 @@ public class DeviceServlet extends HttpServlet {
     @Override
     @ScopedServletMethod(securityGroups = {AccessLevel.USER})
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+        Gson gson = new Gson();
+        String username = req.getAttribute("username").toString();
+
         DeviceRegistrationRequest request =
                 JsonIterator.deserialize(
                         req.getInputStream().readAllBytes(), DeviceRegistrationRequest.class);
         DeviceRegistrationResponse devResponse =
-                RegisterDeviceFlow.registerDevice(req.getAttribute("username").toString(), request);
+                RegisterDeviceFlow.registerDevice(username, request);
 
         if (devResponse == null) {
             TomcatCustomErrorHandler.sendCustomError(
@@ -135,7 +134,6 @@ public class DeviceServlet extends HttpServlet {
             return;
         }
 
-        Gson gson = new Gson();
         String filteredJson = gson.toJson(devResponse);
         JsonObject obj = gson.fromJson(filteredJson, JsonObject.class);
 
@@ -204,15 +202,9 @@ public class DeviceServlet extends HttpServlet {
         String username = req.getAttribute("username").toString();
         String deviceId = req.getPathInfo().replace("/", "");
         String deviceName = req.getParameter("deviceName");
-        StatementList update = new StatementList();
-        StatementElement st0 = new StatementElement("deviceName", "=", deviceName, "");
-        update.addStatement(st0);
-        StatementList constraint = new StatementList();
-        StatementElement st1 = new StatementElement("owner", "=", username, "AND");
-        StatementElement st2 = new StatementElement("deviceId", "=", deviceId, "");
-        update.addStatement(st1);
-        update.addStatement(st2);
-        if (dataStore.getDeviceDao().updateObject(update, constraint)) resp.setStatus(200);
+
+        if (dataStore.getDeviceDao().updateObject(deviceName, username, deviceId))
+            resp.setStatus(200);
         else
             TomcatCustomErrorHandler.sendCustomError(
                     resp, 500, "could not update device information due to server-side error");
@@ -235,20 +227,20 @@ public class DeviceServlet extends HttpServlet {
             throws ServletException, IOException {
         String deviceId = req.getPathInfo().replace("/", "");
         // If the device does not belong to the user throw a 403
-        StatementList statementList = new StatementList();
-        StatementElement statementElement =
-                new StatementElement("owner", "=", req.getAttribute("username").toString(), "");
-        statementList.addStatement(statementElement);
-        if (dataStore.getDeviceDao().getObjects(statementList).stream()
+        String owner = req.getAttribute("username").toString();
+
+        long deviceIdCount =
+                dataStore.getDeviceDao().getByOwner(owner).stream()
                         .filter(device -> device.getDeviceId().equals(deviceId))
-                        .count()
-                == 0) {
+                        .count();
+
+        if (deviceIdCount == 0) {
             TomcatCustomErrorHandler.sendCustomError(
                     resp, 403, "You do not have sufficient rights to revoke this device!");
             return;
         }
-        DeviceRevocationResponse devResponse =
-                RevokeDeviceFlow.revokeDevice(req.getAttribute("username").toString(), deviceId);
+
+        DeviceRevocationResponse devResponse = RevokeDeviceFlow.revokeDevice(owner, deviceId);
         if (devResponse != null)
             resp.getOutputStream().write(JsonStream.serialize(devResponse).getBytes());
         else
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DevicesServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DevicesServlet.java
index e99fa203..e8af8c4b 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DevicesServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DevicesServlet.java
@@ -33,8 +33,6 @@ import jakarta.servlet.http.HttpServlet;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.devices.Device;
 
 import java.io.IOException;
@@ -64,9 +62,7 @@ public class DevicesServlet extends HttpServlet {
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
         String username = req.getAttribute("username").toString();
-        StatementList statementList = new StatementList();
-        statementList.addStatement(new StatementElement("owner", "=", username, ""));
-        List<Device> devices = dataStore.getDeviceDao().getObjects(statementList);
+        List<Device> devices = dataStore.getDeviceDao().getByOwner(username);
         if (certificateAuthority.getLatestCRL() != null) {
             devices.forEach(
                     device -> {
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoryEntryServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoryEntryServlet.java
index 365723c0..281f0d1c 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoryEntryServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoryEntryServlet.java
@@ -32,11 +32,11 @@ import jakarta.servlet.annotation.WebServlet;
 import jakarta.servlet.http.HttpServlet;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+
 import lombok.extern.slf4j.Slf4j;
+
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.authmodule.AuthModuleKey;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.User;
 import net.jami.jams.common.objects.user.UserProfile;
 
@@ -203,11 +203,7 @@ public class DirectoryEntryServlet extends HttpServlet {
 
         String jamiId = req.getParameter("jamiId");
         if (jamiId != null) {
-            StatementList statementList = new StatementList();
-            StatementElement statementElement =
-                    new StatementElement("jamiId", "=", jamiId, null);
-            statementList.addStatement(statementElement);
-            User user = dataStore.getUserDao().getObjects(statementList).get(0);
+            User user = dataStore.getUserDao().getByJamiId(jamiId).get(0);
             List<UserProfile> userProfiles = new ArrayList<>();
             userAuthenticationModule
                     .getAuthSources()
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java
index 4319ce71..ce82b41f 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java
@@ -40,14 +40,10 @@ import net.jami.jams.common.annotations.JsonContent;
 import net.jami.jams.common.authentication.AuthenticationSource;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.authmodule.AuthModuleKey;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.AccessLevel;
-import net.jami.jams.common.objects.user.Group;
 import net.jami.jams.common.objects.user.Policy;
 import net.jami.jams.common.objects.user.PolicyData;
 import net.jami.jams.common.objects.user.User;
-import net.jami.jams.common.objects.user.UserGroupMapping;
 import net.jami.jams.common.objects.user.UserProfile;
 
 import org.json.JSONObject;
@@ -71,50 +67,31 @@ public class SearchDirectoryServlet extends HttpServlet {
     // requires changes on the name server as well.
     List<UserProfile> userProfiles = new ArrayList<>();
 
-    /**
-     *
-     */
     @Override
     @JsonContent
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+        String pageParam = req.getParameter("page");
         Optional<Integer> page;
-        if (req.getParameter("page") == null) page = Optional.empty();
-        else page = Optional.ofNullable(Integer.parseInt(req.getParameter("page")));
+        if (pageParam == null) page = Optional.empty();
+        else page = Optional.ofNullable(Integer.parseInt(pageParam));
 
         ConcurrentHashMap<AuthModuleKey, AuthenticationSource> authSources =
                 new ConcurrentHashMap<>(userAuthenticationModule.getAuthSources());
 
         // Check if the actual user is allowed to lookup in the directory
-        Group group = new Group();
-        StatementList statementList1 = new StatementList();
-
-        statementList1.addStatement(
-                new StatementElement("username", "=", req.getAttribute("username").toString(), ""));
-        List<UserGroupMapping> mappings =
-                dataStore.getUserGroupMappingsDao().getObjects(statementList1);
-        if (mappings != null && !mappings.isEmpty()) {
-            statementList1 = new StatementList();
-            statementList1.addStatement(
-                    new StatementElement("id", "=", mappings.get(0).getGroupId(), ""));
-            group = dataStore.getGroupDao().getObjects(statementList1).get(0);
-        }
+        String username = req.getAttribute("username").toString();
+
+        try {
+            Policy policy = dataStore.getPolicyDao().getByUsername(username).orElseThrow();
+            PolicyData policyData =
+                    JsonIterator.deserialize(policy.getPolicyData(), PolicyData.class);
 
-        if (!group.isEmpty() && group.hasBlueprint()) {
-            StatementElement st2 = new StatementElement("name", "=", group.getBlueprint(), "");
-            StatementList statementList2 = new StatementList();
-            statementList2.addStatement((st2));
-            try {
-                Policy policy = dataStore.getPolicyDao().getObjects(statementList2).get(0);
-                PolicyData policyData =
-                        JsonIterator.deserialize(policy.getPolicyData(), PolicyData.class);
-                if (!policyData.getAllowLookup()) {
-                    resp.sendError(403, "Operation not allowed!");
-                    return;
-                }
-            } catch (Exception e1) {
-                log.warn(
-                        "No policy available for user - not adding a policy component to response");
+            if (!policyData.getAllowLookup()) {
+                resp.sendError(403, "Operation not allowed!");
+                return;
             }
+        } catch (Exception e1) {
+            log.warn("No policy available for user - not adding a policy component to response");
         }
 
         if (authSources.size() > 1) {
@@ -124,51 +101,42 @@ public class SearchDirectoryServlet extends HttpServlet {
                     });
         }
 
+        String queryString = req.getParameter("queryString");
+
         authSources.forEach(
                 (k, v) -> {
-                    if (req.getParameter("queryString").equals("*"))
-                        userProfiles =
-                                v.searchUserProfiles(
-                                        req.getParameter("queryString"), "FULL_TEXT_NAME", page);
-                    else {
-                        userProfiles =
-                                v.searchUserProfiles(
-                                        req.getParameter("queryString"), "FULL_TEXT_NAME", page);
-                        if (userProfiles.isEmpty()
-                                && userProfiles.addAll(
-                                        v.searchUserProfiles(
-                                                req.getParameter("queryString"),
-                                                "LOGON_NAME",
-                                                page))) {
-                            Set<UserProfile> s =
-                                    new TreeSet<UserProfile>(
-                                            new Comparator<UserProfile>() {
-                                                @Override
-                                                public int compare(UserProfile o1, UserProfile o2) {
-                                                    if (o1.getUsername().equals(o2.getUsername()))
-                                                        return 0;
-                                                    return 1;
-                                                }
-                                            });
-                            s.addAll(userProfiles);
-                            userProfiles = new ArrayList<>(s);
-                        }
+                    if (queryString.equals("*")) {
+                        userProfiles = v.searchUserProfiles(queryString, "FULL_TEXT_NAME", page);
+                    }
+                    userProfiles = v.searchUserProfiles(queryString, "FULL_TEXT_NAME", page);
+                    if (userProfiles.isEmpty()
+                            && userProfiles.addAll(
+                                    v.searchUserProfiles(queryString, "LOGON_NAME", page))) {
+                        Set<UserProfile> s =
+                                new TreeSet<UserProfile>(
+                                        new Comparator<UserProfile>() {
+                                            @Override
+                                            public int compare(UserProfile o1, UserProfile o2) {
+                                                if (o1.getUsername().equals(o2.getUsername()))
+                                                    return 0;
+                                                return 1;
+                                            }
+                                        });
+                        s.addAll(userProfiles);
+                        userProfiles = new ArrayList<>(s);
                     }
                     userProfiles.parallelStream()
                             .forEach(
                                     profile -> {
-                                        StatementList statementList = new StatementList();
-                                        StatementElement statementElement =
-                                                new StatementElement(
-                                                        "username", "=", profile.getUsername(), "");
-                                        statementList.addStatement(statementElement);
                                         List<User> results = new ArrayList<>();
-                                        while (results.size() == 0) {
+                                        while (results.isEmpty()) {
                                             results =
                                                     dataStore
                                                             .getUserDao()
-                                                            .getObjects(statementList);
-                                            if (results.size() == 0) {
+                                                            .getByUsername(profile.getUsername())
+                                                            .map(user -> List.of(user))
+                                                            .orElseGet(() -> List.of());
+                                            if (results.isEmpty()) {
                                                 User user = new User();
                                                 user.setUsername(profile.getUsername());
                                                 user.setRealm(k.getRealm());
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/policyData/PolicyDataServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/policyData/PolicyDataServlet.java
index ff01dd92..c23770a9 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/policyData/PolicyDataServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/policyData/PolicyDataServlet.java
@@ -25,7 +25,6 @@ import jakarta.servlet.http.HttpServlet;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
-import net.jami.jams.common.objects.user.Group;
 import net.jami.jams.common.serialization.tomcat.TomcatCustomErrorHandler;
 import net.jami.jams.server.core.workflows.RegisterDeviceFlow;
 import net.jami.jams.server.servlets.api.auth.device.DeviceServlet;
@@ -69,8 +68,7 @@ public class PolicyDataServlet extends HttpServlet {
             throws ServletException, IOException {
         String username = req.getAttribute("username").toString();
 
-        Group group = RegisterDeviceFlow.getGroupByUsername(username);
-        String policyData = RegisterDeviceFlow.getPolicyData(group);
+        String policyData = RegisterDeviceFlow.getPolicyData(username);
 
         if (policyData == null) {
             TomcatCustomErrorHandler.sendCustomError(
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserServlet.java
index 4fb2a126..c0e76bba 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserServlet.java
@@ -35,12 +35,11 @@ import jakarta.servlet.http.HttpServletResponse;
 
 import net.jami.jams.common.annotations.ScopedServletMethod;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.User;
 
 import java.io.IOException;
+import java.util.Optional;
 
 @WebServlet("/api/auth/user")
 public class UserServlet extends HttpServlet {
@@ -74,24 +73,24 @@ public class UserServlet extends HttpServlet {
     @ScopedServletMethod(securityGroups = {AccessLevel.USER})
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        StatementList statementList = new StatementList();
-        StatementElement st =
-                new StatementElement("username", "=", req.getAttribute("username").toString(), "");
-        statementList.addStatement(st);
-        if (!dataStore.getUserDao().getObjects(statementList).isEmpty()) {
-            User user = dataStore.getUserDao().getObjects(statementList).get(0);
-            if (certificateAuthority.getLatestCRL().get() != null) {
-                user.setRevoked(
-                        certificateAuthority
-                                        .getLatestCRL()
-                                        .get()
-                                        .getRevokedCertificate(
-                                                user.getCertificate().getSerialNumber())
-                                != null);
-            } else user.setRevoked(false);
-            resp.setStatus(200);
-            resp.getOutputStream().write(JsonStream.serialize(user).getBytes());
-        } else resp.sendError(404, "User was not found!");
+        String username = req.getAttribute("username").toString();
+        Optional<User> result = dataStore.getUserDao().getByUsername(username);
+        if (result.isEmpty()) {
+            resp.sendError(404, "User was not found!");
+            return;
+        }
+
+        User user = result.get();
+        if (certificateAuthority.getLatestCRL().get() != null) {
+            user.setRevoked(
+                    certificateAuthority
+                                    .getLatestCRL()
+                                    .get()
+                                    .getRevokedCertificate(user.getCertificate().getSerialNumber())
+                            != null);
+        } else user.setRevoked(false);
+        resp.setStatus(200);
+        resp.getOutputStream().write(JsonStream.serialize(user).getBytes());
     }
 
     // The user can update 3 fields: password,privatekey,publickey
@@ -110,24 +109,18 @@ public class UserServlet extends HttpServlet {
     @ScopedServletMethod(securityGroups = AccessLevel.USER)
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
         String username = req.getAttribute("username").toString();
+
         // Check if he is AD/LDAP - then return a 403, because we can't set such password.
-        StatementList select = new StatementList();
-        StatementElement st = new StatementElement("username", "=", username, "");
-        select.addStatement(st);
-        if (dataStore.getUserDao().getObjects(select).get(0).getUserType()
-                != AuthenticationSourceType.LOCAL) {
+        User user = dataStore.getUserDao().getByUsername(username).orElseThrow();
+        if (user.getUserType() != AuthenticationSourceType.LOCAL) {
             resp.sendError(
                     403, "The user is not a local user, therefore we cannot change his data!");
             return;
         }
-        StatementList update = new StatementList();
-        StatementElement st0 =
-                new StatementElement("password", "=", req.getParameter("password"), "");
-        update.addStatement(st0);
-        StatementList constraint = new StatementList();
-        StatementElement st1 = new StatementElement("username", "=", username, "");
-        constraint.addStatement(st1);
-        if (dataStore.getUserDao().updateObject(update, constraint)) resp.setStatus(200);
+
+        String password = req.getParameter("password");
+
+        if (dataStore.getUserDao().updateObject(password, username)) resp.setStatus(200);
         else resp.sendError(500, "could not update the users's data field!");
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java
index 72b2cc11..0240bb3b 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java
@@ -60,11 +60,12 @@ public class StartInstallServlet extends HttpServlet {
     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
         // Here we must decide which page to show - login or sign-up
-        if (dataStore != null
-                && dataStore.getUserDao() != null
-                && !dataStore.getUserDao().getObjects(null).isEmpty())
-            resp.setHeader("showLogin", "true");
-        else resp.setHeader("showLogin", "false");
+        boolean showLogin =
+                dataStore != null
+                        && dataStore.getUserDao() != null
+                        && !dataStore.getUserDao().getAll().isEmpty();
+
+        resp.setHeader("showLogin", showLogin ? "true" : "false");
     }
 
     @Override
@@ -89,7 +90,7 @@ public class StartInstallServlet extends HttpServlet {
     @JsonContent
     protected void doPut(HttpServletRequest req, HttpServletResponse resp)
             throws ServletException, IOException {
-        if (dataStore.getUserDao().getObjects(null).size() != 0) {
+        if (!dataStore.getUserDao().getAll().isEmpty()) {
             resp.sendError(
                     500,
                     "We have tried to create an administrative account where one already exists!");
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/DApiFilter.java b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/DApiFilter.java
index 6fc069c7..d4515409 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/DApiFilter.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/DApiFilter.java
@@ -42,7 +42,8 @@ import net.jami.jams.server.Server;
 import java.io.IOException;
 
 /**
- * Since we have the @ScopedServletMethod annotation, the admin filter became absolutely useless
+ * Since we have the @ScopedServletMethod annotation, the admin filter became
+ * absolutely useless
  * as we can simply scope things.
  */
 @WebFilter(urlPatterns = {"/api/auth/*", "/api/admin/*"})
@@ -56,23 +57,25 @@ public class DApiFilter implements Filter {
         HttpServletRequest request = (HttpServletRequest) servletRequest;
         HttpServletResponse response = (HttpServletResponse) servletResponse;
         response.setContentType("application/json;charset=UTF-8");
+
         if (!Server.isInstalled.get()) {
             TomcatCustomErrorHandler.sendCustomError(
                     response, 404, "Setup has not yet been completed!");
-        } else {
-            boolean authsuccess = false;
-            boolean isLogin = false;
-            boolean isOCSPCheck = false;
+            return;
+        }
 
-            if (request.getServletPath().contains("login")) isLogin = true;
-            else if (request.getServletPath().contains("ocsp")) isOCSPCheck = true;
-            else authsuccess = doAuthCheck(request);
-            if (authsuccess || isLogin || isOCSPCheck) {
-                filterChain.doFilter(servletRequest, servletResponse);
-            } else {
-                TomcatCustomErrorHandler.sendCustomError(
-                        response, 401, "You are not authenticated!");
-            }
+        boolean authsuccess = false;
+        boolean isLogin = false;
+        boolean isOCSPCheck = false;
+
+        if (request.getServletPath().contains("login")) isLogin = true;
+        else if (request.getServletPath().contains("ocsp")) isOCSPCheck = true;
+        else authsuccess = doAuthCheck(request);
+        if (authsuccess || isLogin || isOCSPCheck) {
+            filterChain.doFilter(servletRequest, servletResponse);
+            return;
         }
+
+        TomcatCustomErrorHandler.sendCustomError(response, 401, "You are not authenticated!");
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/FilterUtils.java b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/FilterUtils.java
index 7bdab5d7..5ba99ad9 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/FilterUtils.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/FilterUtils.java
@@ -35,8 +35,6 @@ import jakarta.servlet.http.HttpServletRequest;
 
 import lombok.extern.slf4j.Slf4j;
 
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.User;
 
@@ -95,13 +93,12 @@ public class FilterUtils {
                 default:
                     return false;
             }
-            StatementList statementList = new StatementList();
-            StatementElement statementElement =
-                    new StatementElement("username", "=", token.getJWTClaimsSet().getSubject(), "");
-            statementList.addStatement(statementElement);
+
+            String username = token.getJWTClaimsSet().getSubject();
             log.info("Getting user from database");
-            User user = dataStore.getUserDao().getObjects(statementList).get(0);
+            User user = dataStore.getUserDao().getByUsername(username).orElseThrow();
             log.info("User retrieved from database: {}", user);
+
             if (!user.getAccessLevelName().equals("ADMIN")
                     && certificateAuthority.getLatestCRL().get() != null) {
                 if (certificateAuthority
@@ -110,10 +107,12 @@ public class FilterUtils {
                                 .getRevokedCertificate(user.getCertificate().getSerialNumber())
                         != null) return false;
             }
+
             JWSVerifier jwsVerifier =
                     new RSASSAVerifier(userAuthenticationModule.getAuthModulePubKey());
+
             if (token.verify(jwsVerifier) && verifyValidity(token)) {
-                request.setAttribute(USERNAME_ATTR, token.getJWTClaimsSet().getSubject());
+                request.setAttribute(USERNAME_ATTR, username);
                 request.setAttribute(
                         ACCESS_LEVEL_ATTR,
                         AccessLevel.valueOf(token.getJWTClaimsSet().getClaim("scope").toString()));
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/x509/OCSPServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/x509/OCSPServlet.java
index 165864a3..819d04ac 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/x509/OCSPServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/x509/OCSPServlet.java
@@ -30,8 +30,6 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
 import net.jami.jams.ca.JamsCA;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.devices.Device;
 import net.jami.jams.common.objects.user.User;
 
@@ -63,8 +61,10 @@ public class OCSPServlet extends HttpServlet {
             String issuerId = req.getPathInfo().replace("/", "");
 
             /*
-             * If there is no issue id we are dealing with a certificate signed byt the CA root
-             * Else the certificate is a device certificate signed by a user with and the issuerId is his Jami Id
+             * If there is no issue id we are dealing with a certificate signed byt the CA
+             * root
+             * Else the certificate is a device certificate signed by a user with and the
+             * issuerId is his Jami Id
              */
 
             if (issuerId == "") {
@@ -79,56 +79,32 @@ public class OCSPServlet extends HttpServlet {
                     byte[] respBytes = response.getEncoded();
                     resp.getOutputStream().write(respBytes);
                 } else resp.setStatus(404);
-            } else {
-                User targetUser = null;
-                StatementList userStatementsList = new StatementList();
-                StatementElement usernameStatement =
-                        new StatementElement("jamiId", "=", issuerId, "");
-                userStatementsList.addStatement(usernameStatement);
-
-                try {
-                    targetUser = dataStore.getUserDao().getObjects(userStatementsList).get(0);
-                    StatementList deviceStatementsList = new StatementList();
-                    StatementElement deviceOwnerStatement =
-                            new StatementElement("owner", "=", targetUser.getUsername(), "");
-                    deviceStatementsList.addStatement(deviceOwnerStatement);
-                    List<Device> devices =
-                            dataStore.getDeviceDao().getObjects(deviceStatementsList);
-
-                    boolean deviceDoesNotExist = true;
-                    for (Device d : devices) {
-                        for (BigInteger id : ids) {
-                            if (d.getCertificate().getSerialNumber().equals(id)) {
-                                deviceDoesNotExist = false;
-                            }
-                        }
-                    }
-                    OCSPResp response = null;
-
-                    if (deviceDoesNotExist) {
-                        response =
-                                JamsCA.getOCSPResponse(
-                                        ocspReq,
-                                        targetUser.getCertificate(),
-                                        targetUser.getPrivateKey(),
-                                        true);
-                    } else {
-                        response =
-                                JamsCA.getOCSPResponse(
-                                        ocspReq,
-                                        targetUser.getCertificate(),
-                                        targetUser.getPrivateKey(),
-                                        false);
-                    }
 
-                    if (response != null) {
-                        byte[] respBytes = response.getEncoded();
-                        resp.getOutputStream().write(respBytes);
-                    } else resp.setStatus(404);
-                } catch (Exception e) {
-                    resp.sendError(404, "Could not find the requested certificate!");
+                return;
+            }
+
+            User targetUser = dataStore.getUserDao().getByJamiId(issuerId).get(0);
+            List<Device> devices = dataStore.getDeviceDao().getByOwner(targetUser.getUsername());
+
+            boolean deviceDoesNotExist = true;
+            for (Device d : devices) {
+                for (BigInteger id : ids) {
+                    if (d.getCertificate().getSerialNumber().equals(id)) {
+                        deviceDoesNotExist = false;
+                    }
                 }
             }
+            OCSPResp response =
+                    JamsCA.getOCSPResponse(
+                            ocspReq,
+                            targetUser.getCertificate(),
+                            targetUser.getPrivateKey(),
+                            deviceDoesNotExist);
+
+            if (response != null) {
+                byte[] respBytes = response.getEncoded();
+                resp.getOutputStream().write(respBytes);
+            } else resp.setStatus(404);
 
         } catch (Exception e) {
             resp.sendError(404, "Could not find the requested certificate!");
diff --git a/jams-server/src/main/java/net/jami/jams/server/startup/CryptoEngineLoader.java b/jams-server/src/main/java/net/jami/jams/server/startup/CryptoEngineLoader.java
index 465d7161..a34d7ed9 100644
--- a/jams-server/src/main/java/net/jami/jams/server/startup/CryptoEngineLoader.java
+++ b/jams-server/src/main/java/net/jami/jams/server/startup/CryptoEngineLoader.java
@@ -26,12 +26,10 @@ import lombok.extern.slf4j.Slf4j;
 
 import net.jami.datastore.main.DataStore;
 import net.jami.jams.common.cryptoengineapi.CertificateAuthority;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.system.SystemAccount;
 import net.jami.jams.common.utils.LibraryLoader;
 
-import java.util.List;
+import java.util.Optional;
 
 @Slf4j
 public class CryptoEngineLoader {
@@ -42,22 +40,17 @@ public class CryptoEngineLoader {
             Class<?> cls = LibraryLoader.classLoader.loadClass("net.jami.jams.ca.JamsCA");
             CertificateAuthority certificateAuthority =
                     (CertificateAuthority) cls.getConstructor().newInstance();
-            StatementList statementList = new StatementList();
-            statementList.addStatement(new StatementElement("entity", "=", "CA", ""));
-            List<SystemAccount> accounts = dataStore.getSystemDao().getObjects(statementList);
-            if (accounts.size() == 0) {
+
+            Optional<SystemAccount> accounts = dataStore.getSystemDao().getCA();
+
+            if (accounts.isEmpty()) {
                 log.info(
                         "This is an fresh install, and it has no CA or any system accounts - if there is a config.json"
                                 + " file in your directory, this means the install is broken and you should delete and restart!");
             } else {
-                statementList = new StatementList();
-                statementList.addStatement(new StatementElement("entity", "=", "CA", ""));
-                SystemAccount caAccount = dataStore.getSystemDao().getObjects(statementList).get(0);
-                statementList = new StatementList();
-                statementList.addStatement(new StatementElement("entity", "=", "OCSP", ""));
-                SystemAccount ocspAccount =
-                        dataStore.getSystemDao().getObjects(statementList).get(0);
-                log.info("Injecting OCSP and CA acocunts...");
+                SystemAccount caAccount = accounts.orElseThrow();
+                SystemAccount ocspAccount = dataStore.getSystemDao().getOCSP().orElseThrow();
+                log.info("Injecting OCSP and CA accounts...");
                 certificateAuthority.init(config, caAccount, ocspAccount);
             }
             log.info(
diff --git a/ldap-connector/src/main/java/net/jami/jams/ldap/connector/service/UserProfileService.java b/ldap-connector/src/main/java/net/jami/jams/ldap/connector/service/UserProfileService.java
index 84e023f3..56c177fa 100644
--- a/ldap-connector/src/main/java/net/jami/jams/ldap/connector/service/UserProfileService.java
+++ b/ldap-connector/src/main/java/net/jami/jams/ldap/connector/service/UserProfileService.java
@@ -27,8 +27,6 @@ import static net.jami.jams.server.Server.dataStore;
 import lombok.extern.slf4j.Slf4j;
 
 import net.jami.datastore.main.DataStore;
-import net.jami.jams.common.dao.StatementElement;
-import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.user.UserProfile;
 import net.jami.jams.ldap.connector.LDAPConnector;
 
@@ -91,13 +89,7 @@ public class UserProfileService {
                                 .map(UserProfileService::profileFromResponse)
                                 .collect(Collectors.toList());
                 for (UserProfile p : profilesFromResponse) {
-                    StatementList statementList = new StatementList();
-                    StatementElement st =
-                            new StatementElement("username", "=", p.getUsername(), "");
-                    statementList.addStatement(st);
-
-                    if (dataStore.getUserProfileDao().getObjects(statementList).isEmpty())
-                        dataStore.getUserProfileDao().storeObject(p);
+                    dataStore.getUserProfileDao().insertIfNotExists(p);
                 }
 
                 return profilesFromResponse;
diff --git a/pom.xml b/pom.xml
index f1d899b0..5aaff754 100644
--- a/pom.xml
+++ b/pom.xml
@@ -149,6 +149,12 @@
                             </includes>
                             <followSymlinks>false</followSymlinks>
                         </fileset>
+                        <fileset>
+                            <directory>coverage/</directory>
+                            <includes>
+                                <include>**</include>
+                            </includes>
+                        </fileset>
                     </filesets>
                 </configuration>
             </plugin>
-- 
GitLab