mirror of
https://github.com/chatmail/core.git
synced 2026-04-27 18:36:30 +03:00
fix: Save QR code token regardless of whether the group exists (#5954)
Groups promotion to other devices and QR code tokens synchronisation are not synchronised processes, so there are reasons why a QR code token may arrive earlier than the first group message: - We are going to upload sync messages via IMAP while group messages are sent by SMTP. - If sync messages go to the mvbox, they can be fetched earlier than group messages from Inbox.
This commit is contained in:
87
src/token.rs
87
src/token.rs
@@ -7,7 +7,6 @@
|
||||
use anyhow::Result;
|
||||
use deltachat_derive::{FromSql, ToSql};
|
||||
|
||||
use crate::chat::ChatId;
|
||||
use crate::context::Context;
|
||||
use crate::tools::{create_id, time};
|
||||
|
||||
@@ -27,34 +26,22 @@ pub enum Namespace {
|
||||
pub async fn save(
|
||||
context: &Context,
|
||||
namespace: Namespace,
|
||||
foreign_id: Option<ChatId>,
|
||||
foreign_key: Option<&str>,
|
||||
token: &str,
|
||||
) -> Result<()> {
|
||||
match foreign_id {
|
||||
Some(foreign_id) => context
|
||||
.sql
|
||||
.execute(
|
||||
"INSERT INTO tokens (namespc, foreign_id, token, timestamp) VALUES (?, ?, ?, ?);",
|
||||
(namespace, foreign_id, token, time()),
|
||||
)
|
||||
.await?,
|
||||
None => {
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"INSERT INTO tokens (namespc, token, timestamp) VALUES (?, ?, ?);",
|
||||
(namespace, token, time()),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
};
|
||||
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"INSERT INTO tokens (namespc, foreign_key, token, timestamp) VALUES (?, ?, ?, ?)",
|
||||
(namespace, foreign_key.unwrap_or(""), token, time()),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Lookup most recently created token for a namespace/chat combination.
|
||||
/// Looks up most recently created token for a namespace / foreign key combination.
|
||||
///
|
||||
/// As there may be more than one valid token for a chat-id,
|
||||
/// As there may be more than one such valid token,
|
||||
/// (eg. when a qr code token is withdrawn, recreated and revived later),
|
||||
/// use lookup() for qr-code creation only;
|
||||
/// do not use lookup() to check for token validity.
|
||||
@@ -63,43 +50,28 @@ pub async fn save(
|
||||
pub async fn lookup(
|
||||
context: &Context,
|
||||
namespace: Namespace,
|
||||
chat: Option<ChatId>,
|
||||
foreign_key: Option<&str>,
|
||||
) -> Result<Option<String>> {
|
||||
let token = match chat {
|
||||
Some(chat_id) => {
|
||||
context
|
||||
.sql
|
||||
.query_get_value(
|
||||
"SELECT token FROM tokens WHERE namespc=? AND foreign_id=? ORDER BY timestamp DESC LIMIT 1;",
|
||||
(namespace, chat_id),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
// foreign_id is declared as `INTEGER DEFAULT 0` in the schema.
|
||||
None => {
|
||||
context
|
||||
.sql
|
||||
.query_get_value(
|
||||
"SELECT token FROM tokens WHERE namespc=? AND foreign_id=0 ORDER BY timestamp DESC LIMIT 1;",
|
||||
(namespace,),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
};
|
||||
Ok(token)
|
||||
context
|
||||
.sql
|
||||
.query_get_value(
|
||||
"SELECT token FROM tokens WHERE namespc=? AND foreign_key=? ORDER BY timestamp DESC LIMIT 1",
|
||||
(namespace, foreign_key.unwrap_or("")),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn lookup_or_new(
|
||||
context: &Context,
|
||||
namespace: Namespace,
|
||||
foreign_id: Option<ChatId>,
|
||||
foreign_key: Option<&str>,
|
||||
) -> Result<String> {
|
||||
if let Some(token) = lookup(context, namespace, foreign_id).await? {
|
||||
if let Some(token) = lookup(context, namespace, foreign_key).await? {
|
||||
return Ok(token);
|
||||
}
|
||||
|
||||
let token = create_id();
|
||||
save(context, namespace, foreign_id, &token).await?;
|
||||
save(context, namespace, foreign_key, &token).await?;
|
||||
Ok(token)
|
||||
}
|
||||
|
||||
@@ -114,23 +86,22 @@ pub async fn exists(context: &Context, namespace: Namespace, token: &str) -> Res
|
||||
Ok(exists)
|
||||
}
|
||||
|
||||
/// Looks up ChatId by auth token.
|
||||
/// Looks up foreign key by auth token.
|
||||
///
|
||||
/// Returns None if auth token is not valid.
|
||||
/// Returns zero/unset ChatId if the token corresponds to "setup contact" rather than group join.
|
||||
pub async fn auth_chat_id(context: &Context, token: &str) -> Result<Option<ChatId>> {
|
||||
let chat_id: Option<ChatId> = context
|
||||
/// Returns an empty string if the token corresponds to "setup contact" rather than group join.
|
||||
pub async fn auth_foreign_key(context: &Context, token: &str) -> Result<Option<String>> {
|
||||
context
|
||||
.sql
|
||||
.query_row_optional(
|
||||
"SELECT foreign_id FROM tokens WHERE namespc=? AND token=?",
|
||||
"SELECT foreign_key FROM tokens WHERE namespc=? AND token=?",
|
||||
(Namespace::Auth, token),
|
||||
|row| {
|
||||
let chat_id: ChatId = row.get(0)?;
|
||||
Ok(chat_id)
|
||||
let foreign_key: String = row.get(0)?;
|
||||
Ok(foreign_key)
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
Ok(chat_id)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete(context: &Context, namespace: Namespace, token: &str) -> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user