feat: improve internal sql interface

Switches from rusqlite to sqlx to have a fully async based interface
to sqlite.

Co-authored-by: B. Petersen <r10s@b44t.com>
Co-authored-by: Hocuri <hocuri@gmx.de>
Co-authored-by: link2xt <link2xt@testrun.org>
This commit is contained in:
Friedel Ziegelmayer
2021-04-06 16:03:10 +02:00
committed by dignifiedquire
parent 4dedc2d8ce
commit 6bb5721f29
52 changed files with 5505 additions and 4983 deletions

View File

@@ -4,17 +4,13 @@
//!
//! Tokens are used in countermitm verification protocols.
use deltachat_derive::{FromSql, ToSql};
use crate::chat::ChatId;
use crate::context::Context;
use crate::dc_tools::{dc_create_id, time};
/// Token namespace
#[derive(
Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql,
)]
#[repr(i32)]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, sqlx::Type)]
#[repr(u32)]
pub enum Namespace {
Unknown = 0,
Auth = 110,
@@ -30,26 +26,36 @@ impl Default for Namespace {
/// Creates a new token and saves it into the database.
///
/// Returns created token.
pub async fn save(context: &Context, namespace: Namespace, chat: Option<ChatId>) -> String {
pub async fn save(context: &Context, namespace: Namespace, foreign_id: Option<ChatId>) -> String {
let token = dc_create_id();
match chat {
Some(chat_id) => context
match foreign_id {
Some(foreign_id) => context
.sql
.execute(
"INSERT INTO tokens (namespc, foreign_id, token, timestamp) VALUES (?, ?, ?, ?);",
paramsv![namespace, chat_id, token, time()],
sqlx::query(
"INSERT INTO tokens (namespc, foreign_id, token, timestamp) VALUES (?, ?, ?, ?);"
)
.bind(namespace)
.bind(foreign_id)
.bind(&token)
.bind(time()),
)
.await
.ok(),
None => context
.sql
.execute(
"INSERT INTO tokens (namespc, token, timestamp) VALUES (?, ?, ?);",
paramsv![namespace, token, time()],
sqlx::query(
"INSERT INTO tokens (namespc, token, timestamp) VALUES (?, ?, ?);"
)
.bind(namespace)
.bind(&token)
.bind(time()),
)
.await
.ok(),
};
token
}
@@ -57,50 +63,51 @@ pub async fn lookup(
context: &Context,
namespace: Namespace,
chat: Option<ChatId>,
) -> Option<String> {
match chat {
) -> crate::sql::Result<Option<String>> {
let token = match chat {
Some(chat_id) => {
context
.sql
.query_get_value::<String>(
context,
"SELECT token FROM tokens WHERE namespc=? AND foreign_id=?;",
paramsv![namespace, chat_id],
.query_get_value(
sqlx::query("SELECT token FROM tokens WHERE namespc=? AND foreign_id=?;")
.bind(namespace)
.bind(chat_id),
)
.await
.await?
}
// foreign_id is declared as `INTEGER DEFAULT 0` in the schema.
None => {
context
.sql
.query_get_value::<String>(
context,
"SELECT token FROM tokens WHERE namespc=? AND foreign_id=0;",
paramsv![namespace],
.query_get_value(
sqlx::query("SELECT token FROM tokens WHERE namespc=? AND foreign_id=0;")
.bind(namespace),
)
.await
.await?
}
}
};
Ok(token)
}
pub async fn lookup_or_new(
context: &Context,
namespace: Namespace,
chat: Option<ChatId>,
foreign_id: Option<ChatId>,
) -> String {
if let Some(token) = lookup(context, namespace, chat).await {
if let Ok(Some(token)) = lookup(context, namespace, foreign_id).await {
return token;
}
save(context, namespace, chat).await
save(context, namespace, foreign_id).await
}
pub async fn exists(context: &Context, namespace: Namespace, token: &str) -> bool {
context
.sql
.exists(
"SELECT id FROM tokens WHERE namespc=? AND token=?;",
paramsv![namespace, token],
sqlx::query("SELECT COUNT(*) FROM tokens WHERE namespc=? AND token=?;")
.bind(namespace)
.bind(token),
)
.await
.unwrap_or_default()