1use anyhow::Result;
8use deltachat_derive::{FromSql, ToSql};
9
10use crate::context::Context;
11use crate::tools::{create_id, time};
12
13#[derive(
15 Debug, Default, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql,
16)]
17#[repr(u32)]
18pub enum Namespace {
19 #[default]
20 Unknown = 0,
21 Auth = 110,
22 InviteNumber = 100,
23}
24
25pub async fn save(
27 context: &Context,
28 namespace: Namespace,
29 foreign_key: Option<&str>,
30 token: &str,
31) -> Result<()> {
32 context
33 .sql
34 .execute(
35 "INSERT INTO tokens (namespc, foreign_key, token, timestamp) VALUES (?, ?, ?, ?)",
36 (namespace, foreign_key.unwrap_or(""), token, time()),
37 )
38 .await?;
39 Ok(())
40}
41
42pub async fn lookup(
51 context: &Context,
52 namespace: Namespace,
53 foreign_key: Option<&str>,
54) -> Result<Option<String>> {
55 context
56 .sql
57 .query_get_value(
58 "SELECT token FROM tokens WHERE namespc=? AND foreign_key=? ORDER BY timestamp DESC LIMIT 1",
59 (namespace, foreign_key.unwrap_or("")),
60 )
61 .await
62}
63
64pub async fn lookup_or_new(
65 context: &Context,
66 namespace: Namespace,
67 foreign_key: Option<&str>,
68) -> Result<String> {
69 if let Some(token) = lookup(context, namespace, foreign_key).await? {
70 return Ok(token);
71 }
72
73 let token = create_id();
74 save(context, namespace, foreign_key, &token).await?;
75 Ok(token)
76}
77
78pub async fn exists(context: &Context, namespace: Namespace, token: &str) -> Result<bool> {
79 let exists = context
80 .sql
81 .exists(
82 "SELECT COUNT(*) FROM tokens WHERE namespc=? AND token=?;",
83 (namespace, token),
84 )
85 .await?;
86 Ok(exists)
87}
88
89pub async fn auth_foreign_key(context: &Context, token: &str) -> Result<Option<String>> {
94 context
95 .sql
96 .query_row_optional(
97 "SELECT foreign_key FROM tokens WHERE namespc=? AND token=?",
98 (Namespace::Auth, token),
99 |row| {
100 let foreign_key: String = row.get(0)?;
101 Ok(foreign_key)
102 },
103 )
104 .await
105}
106
107pub async fn delete(context: &Context, namespace: Namespace, token: &str) -> Result<()> {
108 context
109 .sql
110 .execute(
111 "DELETE FROM tokens WHERE namespc=? AND token=?;",
112 (namespace, token),
113 )
114 .await?;
115 Ok(())
116}