diff --git a/.gitignore b/.gitignore index c6f816ac0..16a9797dc 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,8 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk +# Test sqlite database +/test.db + # VSCode debugger config .vscode/launch.json diff --git a/.sqlx/query-229af3dbe01148ac55574ac7de81f9535210d0165bbd6f0f212242a3a62249e8.json b/.sqlx/query-229af3dbe01148ac55574ac7de81f9535210d0165bbd6f0f212242a3a62249e8.json new file mode 100644 index 000000000..157273b2d --- /dev/null +++ b/.sqlx/query-229af3dbe01148ac55574ac7de81f9535210d0165bbd6f0f212242a3a62249e8.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT value FROM kv WHERE key = ?", + "describe": { + "columns": [ + { + "name": "value", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "229af3dbe01148ac55574ac7de81f9535210d0165bbd6f0f212242a3a62249e8" +} diff --git a/.sqlx/query-2d5393ae20e3136068275a079c7d71d04417f044029da8e8d9a0d735d91a9da8.json b/.sqlx/query-2d5393ae20e3136068275a079c7d71d04417f044029da8e8d9a0d735d91a9da8.json new file mode 100644 index 000000000..edfa37596 --- /dev/null +++ b/.sqlx/query-2d5393ae20e3136068275a079c7d71d04417f044029da8e8d9a0d735d91a9da8.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO sender_keys\n (address, device_id, identity, distribution_id, record)\n VALUES (?, ?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 5 + }, + "nullable": [] + }, + "hash": "2d5393ae20e3136068275a079c7d71d04417f044029da8e8d9a0d735d91a9da8" +} diff --git a/.sqlx/query-3170476b06e6c0c48a054f1ff503e7eb24ba5eb8dba63ddac41154edf3badf69.json b/.sqlx/query-3170476b06e6c0c48a054f1ff503e7eb24ba5eb8dba63ddac41154edf3badf69.json new file mode 100644 index 000000000..4b42a346e --- /dev/null +++ b/.sqlx/query-3170476b06e6c0c48a054f1ff503e7eb24ba5eb8dba63ddac41154edf3badf69.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO identities (address, device_id, identity, record)\n VALUES (?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 4 + }, + "nullable": [] + }, + "hash": "3170476b06e6c0c48a054f1ff503e7eb24ba5eb8dba63ddac41154edf3badf69" +} diff --git a/.sqlx/query-54bfe330f2fe418f03f78d471a42149900b4a154adb466d123fdf9f221af5971.json b/.sqlx/query-54bfe330f2fe418f03f78d471a42149900b4a154adb466d123fdf9f221af5971.json new file mode 100644 index 000000000..25654e3a7 --- /dev/null +++ b/.sqlx/query-54bfe330f2fe418f03f78d471a42149900b4a154adb466d123fdf9f221af5971.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM sessions WHERE address = ? AND device_id = ? AND identity = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "54bfe330f2fe418f03f78d471a42149900b4a154adb466d123fdf9f221af5971" +} diff --git a/.sqlx/query-55efa60cb803a733ed1ec29431aae1bbd23b670d6a6f70a10a87d1037bc05d87.json b/.sqlx/query-55efa60cb803a733ed1ec29431aae1bbd23b670d6a6f70a10a87d1037bc05d87.json new file mode 100644 index 000000000..1181131fa --- /dev/null +++ b/.sqlx/query-55efa60cb803a733ed1ec29431aae1bbd23b670d6a6f70a10a87d1037bc05d87.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT value FROM kv WHERE key = 'registration'", + "describe": { + "columns": [ + { + "name": "value", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false + ] + }, + "hash": "55efa60cb803a733ed1ec29431aae1bbd23b670d6a6f70a10a87d1037bc05d87" +} diff --git a/.sqlx/query-5cc537c00ea4d22c6a8f5f57913b459d87f7e6a0aacdbe4acf5dbcaa44020d6a.json b/.sqlx/query-5cc537c00ea4d22c6a8f5f57913b459d87f7e6a0aacdbe4acf5dbcaa44020d6a.json new file mode 100644 index 000000000..b0a9b55b4 --- /dev/null +++ b/.sqlx/query-5cc537c00ea4d22c6a8f5f57913b459d87f7e6a0aacdbe4acf5dbcaa44020d6a.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO kyber_pre_keys\n (id, identity, is_last_resort, record) VALUES (?, ?, TRUE, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "5cc537c00ea4d22c6a8f5f57913b459d87f7e6a0aacdbe4acf5dbcaa44020d6a" +} diff --git a/.sqlx/query-5d0c805a6fc33ca97f82941bd0a907e8ffe17395f7721138b5ae9f561b55be93.json b/.sqlx/query-5d0c805a6fc33ca97f82941bd0a907e8ffe17395f7721138b5ae9f561b55be93.json new file mode 100644 index 000000000..69248eafc --- /dev/null +++ b/.sqlx/query-5d0c805a6fc33ca97f82941bd0a907e8ffe17395f7721138b5ae9f561b55be93.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM kv WHERE key = 'registration'", + "describe": { + "columns": [], + "parameters": { + "Right": 0 + }, + "nullable": [] + }, + "hash": "5d0c805a6fc33ca97f82941bd0a907e8ffe17395f7721138b5ae9f561b55be93" +} diff --git a/.sqlx/query-621de0b2a2451d04de718349f7bddfbdae66d2c8698c62457ca8cfb26539553e.json b/.sqlx/query-621de0b2a2451d04de718349f7bddfbdae66d2c8698c62457ca8cfb26539553e.json new file mode 100644 index 000000000..9aea1ae6a --- /dev/null +++ b/.sqlx/query-621de0b2a2451d04de718349f7bddfbdae66d2c8698c62457ca8cfb26539553e.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM kv", + "describe": { + "columns": [], + "parameters": { + "Right": 0 + }, + "nullable": [] + }, + "hash": "621de0b2a2451d04de718349f7bddfbdae66d2c8698c62457ca8cfb26539553e" +} diff --git a/.sqlx/query-639fbd073012246a7884f5950b990f956c477d4317643f85fc09002104e9cb95.json b/.sqlx/query-639fbd073012246a7884f5950b990f956c477d4317643f85fc09002104e9cb95.json new file mode 100644 index 000000000..9f9ff9bb6 --- /dev/null +++ b/.sqlx/query-639fbd073012246a7884f5950b990f956c477d4317643f85fc09002104e9cb95.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT device_id AS 'id: u32' FROM sessions\n WHERE address = ? AND device_id != ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "id: u32", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 3 + }, + "nullable": [ + false + ] + }, + "hash": "639fbd073012246a7884f5950b990f956c477d4317643f85fc09002104e9cb95" +} diff --git a/.sqlx/query-6596b08f27ca4a47ed041e593a9c8a1621abb0336cf79a714a80904c6a85c7ed.json b/.sqlx/query-6596b08f27ca4a47ed041e593a9c8a1621abb0336cf79a714a80904c6a85c7ed.json new file mode 100644 index 000000000..1ac0d624d --- /dev/null +++ b/.sqlx/query-6596b08f27ca4a47ed041e593a9c8a1621abb0336cf79a714a80904c6a85c7ed.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT COUNT(id) FROM signed_pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "COUNT(id)", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "6596b08f27ca4a47ed041e593a9c8a1621abb0336cf79a714a80904c6a85c7ed" +} diff --git a/.sqlx/query-759758c0c79377c3004e2b04ecca0e292524dc7965bab1eea79bd714134eba59.json b/.sqlx/query-759758c0c79377c3004e2b04ecca0e292524dc7965bab1eea79bd714134eba59.json new file mode 100644 index 000000000..386d3f6f4 --- /dev/null +++ b/.sqlx/query-759758c0c79377c3004e2b04ecca0e292524dc7965bab1eea79bd714134eba59.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT COUNT(id) FROM kyber_pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "COUNT(id)", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "759758c0c79377c3004e2b04ecca0e292524dc7965bab1eea79bd714134eba59" +} diff --git a/.sqlx/query-7d020ddc267ffdc2ae06427a1ce2aff08c98828abf87c5856e5a370eb2eadca7.json b/.sqlx/query-7d020ddc267ffdc2ae06427a1ce2aff08c98828abf87c5856e5a370eb2eadca7.json new file mode 100644 index 000000000..d46fa1895 --- /dev/null +++ b/.sqlx/query-7d020ddc267ffdc2ae06427a1ce2aff08c98828abf87c5856e5a370eb2eadca7.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM signed_pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false + ] + }, + "hash": "7d020ddc267ffdc2ae06427a1ce2aff08c98828abf87c5856e5a370eb2eadca7" +} diff --git a/.sqlx/query-8c1061a398d8e0df5ab4e756a2dc80d7200e485d78371a125d02dfcf264029f8.json b/.sqlx/query-8c1061a398d8e0df5ab4e756a2dc80d7200e485d78371a125d02dfcf264029f8.json new file mode 100644 index 000000000..bc04526c5 --- /dev/null +++ b/.sqlx/query-8c1061a398d8e0df5ab4e756a2dc80d7200e485d78371a125d02dfcf264029f8.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM kyber_pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "8c1061a398d8e0df5ab4e756a2dc80d7200e485d78371a125d02dfcf264029f8" +} diff --git a/.sqlx/query-99df5c24c97704019d0f2a8a146e0db41d4493ffde5cc3ff357974bb0f529f66.json b/.sqlx/query-99df5c24c97704019d0f2a8a146e0db41d4493ffde5cc3ff357974bb0f529f66.json new file mode 100644 index 000000000..e64f3bdbf --- /dev/null +++ b/.sqlx/query-99df5c24c97704019d0f2a8a146e0db41d4493ffde5cc3ff357974bb0f529f66.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM kyber_pre_keys\n WHERE identity = ? AND is_last_resort = TRUE", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "99df5c24c97704019d0f2a8a146e0db41d4493ffde5cc3ff357974bb0f529f66" +} diff --git a/.sqlx/query-a263ed2911260b16c8dd69756df76011eb7125dd5fb51522d26253088c5fa381.json b/.sqlx/query-a263ed2911260b16c8dd69756df76011eb7125dd5fb51522d26253088c5fa381.json new file mode 100644 index 000000000..5eaa53543 --- /dev/null +++ b/.sqlx/query-a263ed2911260b16c8dd69756df76011eb7125dd5fb51522d26253088c5fa381.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM identities WHERE address = ? AND device_id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 3 + }, + "nullable": [ + false + ] + }, + "hash": "a263ed2911260b16c8dd69756df76011eb7125dd5fb51522d26253088c5fa381" +} diff --git a/.sqlx/query-a273c9f280c542a796ba33c7d28a8dd46afcf57ee09633de84f50911dbd1c68c.json b/.sqlx/query-a273c9f280c542a796ba33c7d28a8dd46afcf57ee09633de84f50911dbd1c68c.json new file mode 100644 index 000000000..b17f8df9a --- /dev/null +++ b/.sqlx/query-a273c9f280c542a796ba33c7d28a8dd46afcf57ee09633de84f50911dbd1c68c.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "a273c9f280c542a796ba33c7d28a8dd46afcf57ee09633de84f50911dbd1c68c" +} diff --git a/.sqlx/query-a76103b5ae8fd6e8b60d81d3a4812e2855b2b3511af5171f21fed953d61f3f40.json b/.sqlx/query-a76103b5ae8fd6e8b60d81d3a4812e2855b2b3511af5171f21fed953d61f3f40.json new file mode 100644 index 000000000..e4be8f369 --- /dev/null +++ b/.sqlx/query-a76103b5ae8fd6e8b60d81d3a4812e2855b2b3511af5171f21fed953d61f3f40.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO kyber_pre_keys (id, identity, record) VALUES (?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "a76103b5ae8fd6e8b60d81d3a4812e2855b2b3511af5171f21fed953d61f3f40" +} diff --git a/.sqlx/query-b14d036992c98c6b4924cbe0c9b73ab4699b0de64f110584462e17f740bcbf86.json b/.sqlx/query-b14d036992c98c6b4924cbe0c9b73ab4699b0de64f110584462e17f740bcbf86.json new file mode 100644 index 000000000..405b21d99 --- /dev/null +++ b/.sqlx/query-b14d036992c98c6b4924cbe0c9b73ab4699b0de64f110584462e17f740bcbf86.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM sender_keys\n WHERE address = ? AND device_id = ? AND identity = ? AND distribution_id = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 4 + }, + "nullable": [ + false + ] + }, + "hash": "b14d036992c98c6b4924cbe0c9b73ab4699b0de64f110584462e17f740bcbf86" +} diff --git a/.sqlx/query-bb92893b22752f1fe76ca9c514d3430ee7239bb622d7d00a6c504ee9cbbe37da.json b/.sqlx/query-bb92893b22752f1fe76ca9c514d3430ee7239bb622d7d00a6c504ee9cbbe37da.json new file mode 100644 index 000000000..1ce62eba0 --- /dev/null +++ b/.sqlx/query-bb92893b22752f1fe76ca9c514d3430ee7239bb622d7d00a6c504ee9cbbe37da.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "bb92893b22752f1fe76ca9c514d3430ee7239bb622d7d00a6c504ee9cbbe37da" +} diff --git a/.sqlx/query-bee82922d353d9346b63e8247d834d7d8282639e182212115560a7f99f0f7f85.json b/.sqlx/query-bee82922d353d9346b63e8247d834d7d8282639e182212115560a7f99f0f7f85.json new file mode 100644 index 000000000..16f5adb52 --- /dev/null +++ b/.sqlx/query-bee82922d353d9346b63e8247d834d7d8282639e182212115560a7f99f0f7f85.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO pre_keys (id, identity, record) VALUES (?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "bee82922d353d9346b63e8247d834d7d8282639e182212115560a7f99f0f7f85" +} diff --git a/.sqlx/query-bf52cac41388a9a6bc0651bd20c7112075c2d74508aaf65da107c5673d006728.json b/.sqlx/query-bf52cac41388a9a6bc0651bd20c7112075c2d74508aaf65da107c5673d006728.json new file mode 100644 index 000000000..a01e04dba --- /dev/null +++ b/.sqlx/query-bf52cac41388a9a6bc0651bd20c7112075c2d74508aaf65da107c5673d006728.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false + ] + }, + "hash": "bf52cac41388a9a6bc0651bd20c7112075c2d74508aaf65da107c5673d006728" +} diff --git a/.sqlx/query-cb2555708665c60b7f8ed462dec5925a7f01fd12f059755cf8cfc58bdace49c1.json b/.sqlx/query-cb2555708665c60b7f8ed462dec5925a7f01fd12f059755cf8cfc58bdace49c1.json new file mode 100644 index 000000000..d7d8fa29c --- /dev/null +++ b/.sqlx/query-cb2555708665c60b7f8ed462dec5925a7f01fd12f059755cf8cfc58bdace49c1.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT MAX(id) AS 'id: u32' FROM pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "id: u32", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true + ] + }, + "hash": "cb2555708665c60b7f8ed462dec5925a7f01fd12f059755cf8cfc58bdace49c1" +} diff --git a/.sqlx/query-d001f0fbc1f0f4b3c579c5c7a7abea02277324296452f76bb25356ce8fb0e63c.json b/.sqlx/query-d001f0fbc1f0f4b3c579c5c7a7abea02277324296452f76bb25356ce8fb0e63c.json new file mode 100644 index 000000000..adeee837d --- /dev/null +++ b/.sqlx/query-d001f0fbc1f0f4b3c579c5c7a7abea02277324296452f76bb25356ce8fb0e63c.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO signed_pre_keys (id, identity, record) VALUES (?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "d001f0fbc1f0f4b3c579c5c7a7abea02277324296452f76bb25356ce8fb0e63c" +} diff --git a/.sqlx/query-d3f0413d5090a5e361c7e0cc27e8a9513212e42c15c645d0c0ebd96fe2d8ecf2.json b/.sqlx/query-d3f0413d5090a5e361c7e0cc27e8a9513212e42c15c645d0c0ebd96fe2d8ecf2.json new file mode 100644 index 000000000..5dd7e3498 --- /dev/null +++ b/.sqlx/query-d3f0413d5090a5e361c7e0cc27e8a9513212e42c15c645d0c0ebd96fe2d8ecf2.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO sessions (address, device_id, identity, record)\n VALUES (?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 4 + }, + "nullable": [] + }, + "hash": "d3f0413d5090a5e361c7e0cc27e8a9513212e42c15c645d0c0ebd96fe2d8ecf2" +} diff --git a/.sqlx/query-d7d74324ae4ca13875e02060afbebdfd2273cc5026506bc634627828600915f8.json b/.sqlx/query-d7d74324ae4ca13875e02060afbebdfd2273cc5026506bc634627828600915f8.json new file mode 100644 index 000000000..6dfdcd733 --- /dev/null +++ b/.sqlx/query-d7d74324ae4ca13875e02060afbebdfd2273cc5026506bc634627828600915f8.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM sessions WHERE address = ? AND device_id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 3 + }, + "nullable": [ + false + ] + }, + "hash": "d7d74324ae4ca13875e02060afbebdfd2273cc5026506bc634627828600915f8" +} diff --git a/.sqlx/query-e617e730d0cbeb70fdabc4a54e6b5ff696f4720ec649057681553fd60206c624.json b/.sqlx/query-e617e730d0cbeb70fdabc4a54e6b5ff696f4720ec649057681553fd60206c624.json new file mode 100644 index 000000000..d5c0ba760 --- /dev/null +++ b/.sqlx/query-e617e730d0cbeb70fdabc4a54e6b5ff696f4720ec649057681553fd60206c624.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM sessions WHERE address = ? AND identity = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "e617e730d0cbeb70fdabc4a54e6b5ff696f4720ec649057681553fd60206c624" +} diff --git a/.sqlx/query-eb7691e6f4227aa79fe925e5f181cff2dca7bf655630d48580e74391c2579a7a.json b/.sqlx/query-eb7691e6f4227aa79fe925e5f181cff2dca7bf655630d48580e74391c2579a7a.json new file mode 100644 index 000000000..5b7946ac0 --- /dev/null +++ b/.sqlx/query-eb7691e6f4227aa79fe925e5f181cff2dca7bf655630d48580e74391c2579a7a.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT MAX(id) AS 'id: u32' FROM kyber_pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "id: u32", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true + ] + }, + "hash": "eb7691e6f4227aa79fe925e5f181cff2dca7bf655630d48580e74391c2579a7a" +} diff --git a/.sqlx/query-efd72a989458fced2cdc60b006c43a1464d9db3e141ceaa2978207659b38572a.json b/.sqlx/query-efd72a989458fced2cdc60b006c43a1464d9db3e141ceaa2978207659b38572a.json new file mode 100644 index 000000000..ecc2bea6a --- /dev/null +++ b/.sqlx/query-efd72a989458fced2cdc60b006c43a1464d9db3e141ceaa2978207659b38572a.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO kv (key, value) VALUES ('registration', ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "efd72a989458fced2cdc60b006c43a1464d9db3e141ceaa2978207659b38572a" +} diff --git a/.sqlx/query-f0a273c8a87f790e3d0cb7595f2f401f35d0abfa4c6cc6a94972e46eb059ad30.json b/.sqlx/query-f0a273c8a87f790e3d0cb7595f2f401f35d0abfa4c6cc6a94972e46eb059ad30.json new file mode 100644 index 000000000..a0c38230a --- /dev/null +++ b/.sqlx/query-f0a273c8a87f790e3d0cb7595f2f401f35d0abfa4c6cc6a94972e46eb059ad30.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT MAX(id) AS 'id: u32' FROM signed_pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "id: u32", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true + ] + }, + "hash": "f0a273c8a87f790e3d0cb7595f2f401f35d0abfa4c6cc6a94972e46eb059ad30" +} diff --git a/.sqlx/query-fadab658b7f0c0dfd2444950966fd8f7f95032eda602bfd5afbc62d6061981f9.json b/.sqlx/query-fadab658b7f0c0dfd2444950966fd8f7f95032eda602bfd5afbc62d6061981f9.json new file mode 100644 index 000000000..8311552f7 --- /dev/null +++ b/.sqlx/query-fadab658b7f0c0dfd2444950966fd8f7f95032eda602bfd5afbc62d6061981f9.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM kyber_pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false + ] + }, + "hash": "fadab658b7f0c0dfd2444950966fd8f7f95032eda602bfd5afbc62d6061981f9" +} diff --git a/justfile b/justfile new file mode 100644 index 000000000..f7c325de1 --- /dev/null +++ b/justfile @@ -0,0 +1,11 @@ +database_url := ("sqlite://" + justfile_directory() + "/test.db") + +prepare-sqlx: setup-sqlx-db + cargo sqlx prepare --workspace --database-url "{{database_url}}" + +[working-directory: "presage-store-sqlite"] +setup-sqlx-db: + cargo sqlx database setup --database-url "{{database_url}}" + +install-sqlx: + cargo binstall sqlx-cli@v0.8.3 diff --git a/presage-store-sled/src/content.rs b/presage-store-sled/src/content.rs index de986e886..bb5e5c5a0 100644 --- a/presage-store-sled/src/content.rs +++ b/presage-store-sled/src/content.rs @@ -88,7 +88,7 @@ impl ContentsStore for SledStore { self.get(SLED_TREE_CONTACTS, id) } - /// Groups + // Groups async fn clear_groups(&mut self) -> Result<(), SledStoreError> { let db = self.write(); @@ -137,7 +137,7 @@ impl ContentsStore for SledStore { Ok(()) } - /// Messages + // Messages async fn clear_messages(&mut self) -> Result<(), SledStoreError> { let db = self.write(); diff --git a/presage-store-sled/src/protobuf.rs b/presage-store-sled/src/protobuf.rs index 5bbe8b8b6..1623ffbe3 100644 --- a/presage-store-sled/src/protobuf.rs +++ b/presage-store-sled/src/protobuf.rs @@ -1,5 +1,4 @@ #[allow(clippy::derive_partial_eq_without_eq)] - mod textsecure { include!(concat!(env!("OUT_DIR"), "/textsecure.rs")); } diff --git a/presage-store-sled/src/protocol.rs b/presage-store-sled/src/protocol.rs index 912e023c4..32c0500e0 100644 --- a/presage-store-sled/src/protocol.rs +++ b/presage-store-sled/src/protocol.rs @@ -1,6 +1,7 @@ use std::marker::PhantomData; use async_trait::async_trait; +use chrono::{DateTime, Utc}; use presage::{ libsignal_service::{ pre_keys::{KyberPreKeyStoreExt, PreKeysStore}, @@ -405,8 +406,6 @@ impl KyberPreKeyStoreExt for SledProtocolStore { &mut self, kyber_prekey_id: KyberPreKeyId, ) -> Result<(), SignalProtocolError> { - self.store - .remove(T::kyber_pre_keys_last_resort(), kyber_prekey_id.sled_key())?; self.store .remove(T::kyber_pre_keys_last_resort(), kyber_prekey_id.sled_key())?; Ok(()) @@ -415,7 +414,7 @@ impl KyberPreKeyStoreExt for SledProtocolStore { /// Analogous to markAllOneTimeKyberPreKeysStaleIfNecessary async fn mark_all_one_time_kyber_pre_keys_stale_if_necessary( &mut self, - _stale_time: chrono::DateTime, + _stale_time: DateTime, ) -> Result<(), SignalProtocolError> { unimplemented!("should not be used yet") } @@ -423,7 +422,7 @@ impl KyberPreKeyStoreExt for SledProtocolStore { /// Analogue of deleteAllStaleOneTimeKyberPreKeys async fn delete_all_stale_one_time_kyber_pre_keys( &mut self, - _threshold: chrono::DateTime, + _threshold: DateTime, _min_count: usize, ) -> Result<(), SignalProtocolError> { unimplemented!("should not be used yet") diff --git a/presage-store-sqlite/.sqlx/query-063159b2ecf475363254eaffd8c3286b4354a2f05a1eb418678ffc3050e09e86.json b/presage-store-sqlite/.sqlx/query-063159b2ecf475363254eaffd8c3286b4354a2f05a1eb418678ffc3050e09e86.json new file mode 100644 index 000000000..06a4f08e3 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-063159b2ecf475363254eaffd8c3286b4354a2f05a1eb418678ffc3050e09e86.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO contacts\n VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 10 + }, + "nullable": [] + }, + "hash": "063159b2ecf475363254eaffd8c3286b4354a2f05a1eb418678ffc3050e09e86" +} diff --git a/presage-store-sqlite/.sqlx/query-0f3b16503d75d03ffae6549b8ed15de08768a88a347555a849ec5d192979355f.json b/presage-store-sqlite/.sqlx/query-0f3b16503d75d03ffae6549b8ed15de08768a88a347555a849ec5d192979355f.json new file mode 100644 index 000000000..fe6239252 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-0f3b16503d75d03ffae6549b8ed15de08768a88a347555a849ec5d192979355f.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT key FROM profile_keys WHERE uuid = ?", + "describe": { + "columns": [ + { + "name": "key", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "0f3b16503d75d03ffae6549b8ed15de08768a88a347555a849ec5d192979355f" +} diff --git a/presage-store-sqlite/.sqlx/query-229af3dbe01148ac55574ac7de81f9535210d0165bbd6f0f212242a3a62249e8.json b/presage-store-sqlite/.sqlx/query-229af3dbe01148ac55574ac7de81f9535210d0165bbd6f0f212242a3a62249e8.json new file mode 100644 index 000000000..157273b2d --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-229af3dbe01148ac55574ac7de81f9535210d0165bbd6f0f212242a3a62249e8.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT value FROM kv WHERE key = ?", + "describe": { + "columns": [ + { + "name": "value", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "229af3dbe01148ac55574ac7de81f9535210d0165bbd6f0f212242a3a62249e8" +} diff --git a/presage-store-sqlite/.sqlx/query-23c67d5b7ad86de40a910d3b7680f0b95aa3b4de8b49fa6424af6d219b52280a.json b/presage-store-sqlite/.sqlx/query-23c67d5b7ad86de40a910d3b7680f0b95aa3b4de8b49fa6424af6d219b52280a.json new file mode 100644 index 000000000..0dae92e7f --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-23c67d5b7ad86de40a910d3b7680f0b95aa3b4de8b49fa6424af6d219b52280a.json @@ -0,0 +1,74 @@ +{ + "db_name": "SQLite", + "query": "SELECT\n master_key,\n title,\n revision AS \"revision: _\",\n invite_link_password,\n access_control AS \"access_control: _\",\n avatar,\n description,\n members AS \"members: _\",\n pending_members AS \"pending_members: _\",\n requesting_members AS \"requesting_members: _\"\n FROM groups\n WHERE master_key = ?\n LIMIT 1", + "describe": { + "columns": [ + { + "name": "master_key", + "ordinal": 0, + "type_info": "Blob" + }, + { + "name": "title", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "revision: _", + "ordinal": 2, + "type_info": "Integer" + }, + { + "name": "invite_link_password", + "ordinal": 3, + "type_info": "Blob" + }, + { + "name": "access_control: _", + "ordinal": 4, + "type_info": "Blob" + }, + { + "name": "avatar", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "description", + "ordinal": 6, + "type_info": "Text" + }, + { + "name": "members: _", + "ordinal": 7, + "type_info": "Blob" + }, + { + "name": "pending_members: _", + "ordinal": 8, + "type_info": "Blob" + }, + { + "name": "requesting_members: _", + "ordinal": 9, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false, + false, + false, + true, + true, + false, + true, + false, + false, + false + ] + }, + "hash": "23c67d5b7ad86de40a910d3b7680f0b95aa3b4de8b49fa6424af6d219b52280a" +} diff --git a/presage-store-sqlite/.sqlx/query-2d5393ae20e3136068275a079c7d71d04417f044029da8e8d9a0d735d91a9da8.json b/presage-store-sqlite/.sqlx/query-2d5393ae20e3136068275a079c7d71d04417f044029da8e8d9a0d735d91a9da8.json new file mode 100644 index 000000000..edfa37596 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-2d5393ae20e3136068275a079c7d71d04417f044029da8e8d9a0d735d91a9da8.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO sender_keys\n (address, device_id, identity, distribution_id, record)\n VALUES (?, ?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 5 + }, + "nullable": [] + }, + "hash": "2d5393ae20e3136068275a079c7d71d04417f044029da8e8d9a0d735d91a9da8" +} diff --git a/presage-store-sqlite/.sqlx/query-3170476b06e6c0c48a054f1ff503e7eb24ba5eb8dba63ddac41154edf3badf69.json b/presage-store-sqlite/.sqlx/query-3170476b06e6c0c48a054f1ff503e7eb24ba5eb8dba63ddac41154edf3badf69.json new file mode 100644 index 000000000..4b42a346e --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-3170476b06e6c0c48a054f1ff503e7eb24ba5eb8dba63ddac41154edf3badf69.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO identities (address, device_id, identity, record)\n VALUES (?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 4 + }, + "nullable": [] + }, + "hash": "3170476b06e6c0c48a054f1ff503e7eb24ba5eb8dba63ddac41154edf3badf69" +} diff --git a/presage-store-sqlite/.sqlx/query-3957d3b7ac391d8b3712f71043ea99136fdb4dfe1c8b3d813f5b78559fd1456b.json b/presage-store-sqlite/.sqlx/query-3957d3b7ac391d8b3712f71043ea99136fdb4dfe1c8b3d813f5b78559fd1456b.json new file mode 100644 index 000000000..b57acdc41 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-3957d3b7ac391d8b3712f71043ea99136fdb4dfe1c8b3d813f5b78559fd1456b.json @@ -0,0 +1,74 @@ +{ + "db_name": "SQLite", + "query": "SELECT\n master_key,\n title,\n revision AS \"revision: _\",\n invite_link_password,\n access_control AS \"access_control: _\",\n avatar,\n description,\n members AS \"members: _\",\n pending_members AS \"pending_members: _\",\n requesting_members AS \"requesting_members: _\"\n FROM groups", + "describe": { + "columns": [ + { + "name": "master_key", + "ordinal": 0, + "type_info": "Blob" + }, + { + "name": "title", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "revision: _", + "ordinal": 2, + "type_info": "Integer" + }, + { + "name": "invite_link_password", + "ordinal": 3, + "type_info": "Blob" + }, + { + "name": "access_control: _", + "ordinal": 4, + "type_info": "Blob" + }, + { + "name": "avatar", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "description", + "ordinal": 6, + "type_info": "Text" + }, + { + "name": "members: _", + "ordinal": 7, + "type_info": "Blob" + }, + { + "name": "pending_members: _", + "ordinal": 8, + "type_info": "Blob" + }, + { + "name": "requesting_members: _", + "ordinal": 9, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false, + false, + false, + true, + true, + false, + true, + false, + false, + false + ] + }, + "hash": "3957d3b7ac391d8b3712f71043ea99136fdb4dfe1c8b3d813f5b78559fd1456b" +} diff --git a/presage-store-sqlite/.sqlx/query-54bfe330f2fe418f03f78d471a42149900b4a154adb466d123fdf9f221af5971.json b/presage-store-sqlite/.sqlx/query-54bfe330f2fe418f03f78d471a42149900b4a154adb466d123fdf9f221af5971.json new file mode 100644 index 000000000..25654e3a7 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-54bfe330f2fe418f03f78d471a42149900b4a154adb466d123fdf9f221af5971.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM sessions WHERE address = ? AND device_id = ? AND identity = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "54bfe330f2fe418f03f78d471a42149900b4a154adb466d123fdf9f221af5971" +} diff --git a/presage-store-sqlite/.sqlx/query-55efa60cb803a733ed1ec29431aae1bbd23b670d6a6f70a10a87d1037bc05d87.json b/presage-store-sqlite/.sqlx/query-55efa60cb803a733ed1ec29431aae1bbd23b670d6a6f70a10a87d1037bc05d87.json new file mode 100644 index 000000000..1181131fa --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-55efa60cb803a733ed1ec29431aae1bbd23b670d6a6f70a10a87d1037bc05d87.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT value FROM kv WHERE key = 'registration'", + "describe": { + "columns": [ + { + "name": "value", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false + ] + }, + "hash": "55efa60cb803a733ed1ec29431aae1bbd23b670d6a6f70a10a87d1037bc05d87" +} diff --git a/presage-store-sqlite/.sqlx/query-58405418d4f7263ed57a611daf81f667982d30aac1059cdd223bd7bbcb3c5f5b.json b/presage-store-sqlite/.sqlx/query-58405418d4f7263ed57a611daf81f667982d30aac1059cdd223bd7bbcb3c5f5b.json new file mode 100644 index 000000000..6f519884e --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-58405418d4f7263ed57a611daf81f667982d30aac1059cdd223bd7bbcb3c5f5b.json @@ -0,0 +1,92 @@ +{ + "db_name": "SQLite", + "query": "SELECT * FROM contacts c\n LEFT JOIN contacts_verification_state cv ON c.uuid = cv.destination_aci\n WHERE c.uuid = ?", + "describe": { + "columns": [ + { + "name": "uuid", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "phone_number", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "name", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "color", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "profile_key", + "ordinal": 4, + "type_info": "Blob" + }, + { + "name": "expire_timer", + "ordinal": 5, + "type_info": "Integer" + }, + { + "name": "expire_timer_version", + "ordinal": 6, + "type_info": "Integer" + }, + { + "name": "inbox_position", + "ordinal": 7, + "type_info": "Integer" + }, + { + "name": "archived", + "ordinal": 8, + "type_info": "Bool" + }, + { + "name": "avatar", + "ordinal": 9, + "type_info": "Blob" + }, + { + "name": "destination_aci", + "ordinal": 10, + "type_info": "Text" + }, + { + "name": "identity_key", + "ordinal": 11, + "type_info": "Blob" + }, + { + "name": "is_verified", + "ordinal": 12, + "type_info": "Bool" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false, + true, + false, + true, + false, + false, + false, + false, + false, + true, + false, + false, + true + ] + }, + "hash": "58405418d4f7263ed57a611daf81f667982d30aac1059cdd223bd7bbcb3c5f5b" +} diff --git a/presage-store-sqlite/.sqlx/query-59b1b15953ac19fc20df9ea14b694f452ae3f979df614d9359d12a423a2c0c63.json b/presage-store-sqlite/.sqlx/query-59b1b15953ac19fc20df9ea14b694f452ae3f979df614d9359d12a423a2c0c63.json new file mode 100644 index 000000000..d865fec87 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-59b1b15953ac19fc20df9ea14b694f452ae3f979df614d9359d12a423a2c0c63.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT id FROM threads WHERE group_master_key = ?", + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "59b1b15953ac19fc20df9ea14b694f452ae3f979df614d9359d12a423a2c0c63" +} diff --git a/presage-store-sqlite/.sqlx/query-5b76d0a4e70c0ca0353359d81fb64f0a13c34eb5a4048a3ebbfe5e4069d15719.json b/presage-store-sqlite/.sqlx/query-5b76d0a4e70c0ca0353359d81fb64f0a13c34eb5a4048a3ebbfe5e4069d15719.json new file mode 100644 index 000000000..c378d3d37 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-5b76d0a4e70c0ca0353359d81fb64f0a13c34eb5a4048a3ebbfe5e4069d15719.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM contacts", + "describe": { + "columns": [], + "parameters": { + "Right": 0 + }, + "nullable": [] + }, + "hash": "5b76d0a4e70c0ca0353359d81fb64f0a13c34eb5a4048a3ebbfe5e4069d15719" +} diff --git a/presage-store-sqlite/.sqlx/query-5bc0a6578cc589b5f02a97c6441b85858b02d9cb67007d8e4a5accc88d8005ea.json b/presage-store-sqlite/.sqlx/query-5bc0a6578cc589b5f02a97c6441b85858b02d9cb67007d8e4a5accc88d8005ea.json new file mode 100644 index 000000000..3ab35e4b9 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-5bc0a6578cc589b5f02a97c6441b85858b02d9cb67007d8e4a5accc88d8005ea.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO profiles VALUES (?, ?, ?, ?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 7 + }, + "nullable": [] + }, + "hash": "5bc0a6578cc589b5f02a97c6441b85858b02d9cb67007d8e4a5accc88d8005ea" +} diff --git a/presage-store-sqlite/.sqlx/query-5cc537c00ea4d22c6a8f5f57913b459d87f7e6a0aacdbe4acf5dbcaa44020d6a.json b/presage-store-sqlite/.sqlx/query-5cc537c00ea4d22c6a8f5f57913b459d87f7e6a0aacdbe4acf5dbcaa44020d6a.json new file mode 100644 index 000000000..b0a9b55b4 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-5cc537c00ea4d22c6a8f5f57913b459d87f7e6a0aacdbe4acf5dbcaa44020d6a.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO kyber_pre_keys\n (id, identity, is_last_resort, record) VALUES (?, ?, TRUE, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "5cc537c00ea4d22c6a8f5f57913b459d87f7e6a0aacdbe4acf5dbcaa44020d6a" +} diff --git a/presage-store-sqlite/.sqlx/query-5d0c805a6fc33ca97f82941bd0a907e8ffe17395f7721138b5ae9f561b55be93.json b/presage-store-sqlite/.sqlx/query-5d0c805a6fc33ca97f82941bd0a907e8ffe17395f7721138b5ae9f561b55be93.json new file mode 100644 index 000000000..69248eafc --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-5d0c805a6fc33ca97f82941bd0a907e8ffe17395f7721138b5ae9f561b55be93.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM kv WHERE key = 'registration'", + "describe": { + "columns": [], + "parameters": { + "Right": 0 + }, + "nullable": [] + }, + "hash": "5d0c805a6fc33ca97f82941bd0a907e8ffe17395f7721138b5ae9f561b55be93" +} diff --git a/presage-store-sqlite/.sqlx/query-621de0b2a2451d04de718349f7bddfbdae66d2c8698c62457ca8cfb26539553e.json b/presage-store-sqlite/.sqlx/query-621de0b2a2451d04de718349f7bddfbdae66d2c8698c62457ca8cfb26539553e.json new file mode 100644 index 000000000..9aea1ae6a --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-621de0b2a2451d04de718349f7bddfbdae66d2c8698c62457ca8cfb26539553e.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM kv", + "describe": { + "columns": [], + "parameters": { + "Right": 0 + }, + "nullable": [] + }, + "hash": "621de0b2a2451d04de718349f7bddfbdae66d2c8698c62457ca8cfb26539553e" +} diff --git a/presage-store-sqlite/.sqlx/query-62c99b81d0ba8bdeea0a23176769014e7ffc8a9510ca9bcbcf38ea4e7ec99142.json b/presage-store-sqlite/.sqlx/query-62c99b81d0ba8bdeea0a23176769014e7ffc8a9510ca9bcbcf38ea4e7ec99142.json new file mode 100644 index 000000000..48f94d46d --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-62c99b81d0ba8bdeea0a23176769014e7ffc8a9510ca9bcbcf38ea4e7ec99142.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT id FROM threads WHERE recipient_id = ?", + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "62c99b81d0ba8bdeea0a23176769014e7ffc8a9510ca9bcbcf38ea4e7ec99142" +} diff --git a/presage-store-sqlite/.sqlx/query-639fbd073012246a7884f5950b990f956c477d4317643f85fc09002104e9cb95.json b/presage-store-sqlite/.sqlx/query-639fbd073012246a7884f5950b990f956c477d4317643f85fc09002104e9cb95.json new file mode 100644 index 000000000..9f9ff9bb6 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-639fbd073012246a7884f5950b990f956c477d4317643f85fc09002104e9cb95.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT device_id AS 'id: u32' FROM sessions\n WHERE address = ? AND device_id != ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "id: u32", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 3 + }, + "nullable": [ + false + ] + }, + "hash": "639fbd073012246a7884f5950b990f956c477d4317643f85fc09002104e9cb95" +} diff --git a/presage-store-sqlite/.sqlx/query-6596b08f27ca4a47ed041e593a9c8a1621abb0336cf79a714a80904c6a85c7ed.json b/presage-store-sqlite/.sqlx/query-6596b08f27ca4a47ed041e593a9c8a1621abb0336cf79a714a80904c6a85c7ed.json new file mode 100644 index 000000000..1ac0d624d --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-6596b08f27ca4a47ed041e593a9c8a1621abb0336cf79a714a80904c6a85c7ed.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT COUNT(id) FROM signed_pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "COUNT(id)", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "6596b08f27ca4a47ed041e593a9c8a1621abb0336cf79a714a80904c6a85c7ed" +} diff --git a/presage-store-sqlite/.sqlx/query-67999ceeb5578a62a2f4d03cb202437dda869071494ae0674e8971482ae3e8d1.json b/presage-store-sqlite/.sqlx/query-67999ceeb5578a62a2f4d03cb202437dda869071494ae0674e8971482ae3e8d1.json new file mode 100644 index 000000000..54a02d676 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-67999ceeb5578a62a2f4d03cb202437dda869071494ae0674e8971482ae3e8d1.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO profile_keys (uuid, key) VALUES (?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "67999ceeb5578a62a2f4d03cb202437dda869071494ae0674e8971482ae3e8d1" +} diff --git a/presage-store-sqlite/.sqlx/query-7128232c28b11f858a82817a667e1c70cc014212551d35b4a53773d4067502e6.json b/presage-store-sqlite/.sqlx/query-7128232c28b11f858a82817a667e1c70cc014212551d35b4a53773d4067502e6.json new file mode 100644 index 000000000..0d9e566f7 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-7128232c28b11f858a82817a667e1c70cc014212551d35b4a53773d4067502e6.json @@ -0,0 +1,62 @@ +{ + "db_name": "SQLite", + "query": "SELECT * FROM thread_messages\n WHERE thread_id = (SELECT id FROM threads WHERE group_master_key = ? OR recipient_id = ?)\n AND coalesce(ts > ?, ts >= ?, true)\n AND coalesce(ts < ?, ts <= ?, true)\n ORDER BY ts DESC", + "describe": { + "columns": [ + { + "name": "ts", + "ordinal": 0, + "type_info": "Integer" + }, + { + "name": "thread_id", + "ordinal": 1, + "type_info": "Integer" + }, + { + "name": "sender_service_id", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "sender_device_id", + "ordinal": 3, + "type_info": "Integer" + }, + { + "name": "destination_service_id", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "needs_receipt", + "ordinal": 5, + "type_info": "Bool" + }, + { + "name": "unidentified_sender", + "ordinal": 6, + "type_info": "Bool" + }, + { + "name": "content_body", + "ordinal": 7, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 6 + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + false + ] + }, + "hash": "7128232c28b11f858a82817a667e1c70cc014212551d35b4a53773d4067502e6" +} diff --git a/presage-store-sqlite/.sqlx/query-75843c68da0d7af5503404586bcf6f78a45867816ea459e8cb2cc2bacf66812a.json b/presage-store-sqlite/.sqlx/query-75843c68da0d7af5503404586bcf6f78a45867816ea459e8cb2cc2bacf66812a.json new file mode 100644 index 000000000..c5a54ec91 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-75843c68da0d7af5503404586bcf6f78a45867816ea459e8cb2cc2bacf66812a.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM groups", + "describe": { + "columns": [], + "parameters": { + "Right": 0 + }, + "nullable": [] + }, + "hash": "75843c68da0d7af5503404586bcf6f78a45867816ea459e8cb2cc2bacf66812a" +} diff --git a/presage-store-sqlite/.sqlx/query-759758c0c79377c3004e2b04ecca0e292524dc7965bab1eea79bd714134eba59.json b/presage-store-sqlite/.sqlx/query-759758c0c79377c3004e2b04ecca0e292524dc7965bab1eea79bd714134eba59.json new file mode 100644 index 000000000..386d3f6f4 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-759758c0c79377c3004e2b04ecca0e292524dc7965bab1eea79bd714134eba59.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT COUNT(id) FROM kyber_pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "COUNT(id)", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "759758c0c79377c3004e2b04ecca0e292524dc7965bab1eea79bd714134eba59" +} diff --git a/presage-store-sqlite/.sqlx/query-7d020ddc267ffdc2ae06427a1ce2aff08c98828abf87c5856e5a370eb2eadca7.json b/presage-store-sqlite/.sqlx/query-7d020ddc267ffdc2ae06427a1ce2aff08c98828abf87c5856e5a370eb2eadca7.json new file mode 100644 index 000000000..d46fa1895 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-7d020ddc267ffdc2ae06427a1ce2aff08c98828abf87c5856e5a370eb2eadca7.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM signed_pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false + ] + }, + "hash": "7d020ddc267ffdc2ae06427a1ce2aff08c98828abf87c5856e5a370eb2eadca7" +} diff --git a/presage-store-sqlite/.sqlx/query-8c1061a398d8e0df5ab4e756a2dc80d7200e485d78371a125d02dfcf264029f8.json b/presage-store-sqlite/.sqlx/query-8c1061a398d8e0df5ab4e756a2dc80d7200e485d78371a125d02dfcf264029f8.json new file mode 100644 index 000000000..bc04526c5 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-8c1061a398d8e0df5ab4e756a2dc80d7200e485d78371a125d02dfcf264029f8.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM kyber_pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "8c1061a398d8e0df5ab4e756a2dc80d7200e485d78371a125d02dfcf264029f8" +} diff --git a/presage-store-sqlite/.sqlx/query-8ddf5edb9c27f8c4a551e12a7852d6575c1207cb43e19804593a52d37ccb5e77.json b/presage-store-sqlite/.sqlx/query-8ddf5edb9c27f8c4a551e12a7852d6575c1207cb43e19804593a52d37ccb5e77.json new file mode 100644 index 000000000..55f3730d9 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-8ddf5edb9c27f8c4a551e12a7852d6575c1207cb43e19804593a52d37ccb5e77.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM sticker_packs WHERE id = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "8ddf5edb9c27f8c4a551e12a7852d6575c1207cb43e19804593a52d37ccb5e77" +} diff --git a/presage-store-sqlite/.sqlx/query-92e6d334e1c9dc7c84054be8deeb14f7ca94450d414940f65308510450c6b416.json b/presage-store-sqlite/.sqlx/query-92e6d334e1c9dc7c84054be8deeb14f7ca94450d414940f65308510450c6b416.json new file mode 100644 index 000000000..113b07e75 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-92e6d334e1c9dc7c84054be8deeb14f7ca94450d414940f65308510450c6b416.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT bytes FROM group_avatars WHERE group_master_key = ?", + "describe": { + "columns": [ + { + "name": "bytes", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "92e6d334e1c9dc7c84054be8deeb14f7ca94450d414940f65308510450c6b416" +} diff --git a/presage-store-sqlite/.sqlx/query-991269516dba7881b75250cf704f6357f9235de096f3c3019708666dd2b6a460.json b/presage-store-sqlite/.sqlx/query-991269516dba7881b75250cf704f6357f9235de096f3c3019708666dd2b6a460.json new file mode 100644 index 000000000..8247e1d5d --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-991269516dba7881b75250cf704f6357f9235de096f3c3019708666dd2b6a460.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO groups VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 10 + }, + "nullable": [] + }, + "hash": "991269516dba7881b75250cf704f6357f9235de096f3c3019708666dd2b6a460" +} diff --git a/presage-store-sqlite/.sqlx/query-99df5c24c97704019d0f2a8a146e0db41d4493ffde5cc3ff357974bb0f529f66.json b/presage-store-sqlite/.sqlx/query-99df5c24c97704019d0f2a8a146e0db41d4493ffde5cc3ff357974bb0f529f66.json new file mode 100644 index 000000000..e64f3bdbf --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-99df5c24c97704019d0f2a8a146e0db41d4493ffde5cc3ff357974bb0f529f66.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM kyber_pre_keys\n WHERE identity = ? AND is_last_resort = TRUE", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "99df5c24c97704019d0f2a8a146e0db41d4493ffde5cc3ff357974bb0f529f66" +} diff --git a/presage-store-sqlite/.sqlx/query-a263ed2911260b16c8dd69756df76011eb7125dd5fb51522d26253088c5fa381.json b/presage-store-sqlite/.sqlx/query-a263ed2911260b16c8dd69756df76011eb7125dd5fb51522d26253088c5fa381.json new file mode 100644 index 000000000..5eaa53543 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-a263ed2911260b16c8dd69756df76011eb7125dd5fb51522d26253088c5fa381.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM identities WHERE address = ? AND device_id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 3 + }, + "nullable": [ + false + ] + }, + "hash": "a263ed2911260b16c8dd69756df76011eb7125dd5fb51522d26253088c5fa381" +} diff --git a/presage-store-sqlite/.sqlx/query-a273c9f280c542a796ba33c7d28a8dd46afcf57ee09633de84f50911dbd1c68c.json b/presage-store-sqlite/.sqlx/query-a273c9f280c542a796ba33c7d28a8dd46afcf57ee09633de84f50911dbd1c68c.json new file mode 100644 index 000000000..b17f8df9a --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-a273c9f280c542a796ba33c7d28a8dd46afcf57ee09633de84f50911dbd1c68c.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "a273c9f280c542a796ba33c7d28a8dd46afcf57ee09633de84f50911dbd1c68c" +} diff --git a/presage-store-sqlite/.sqlx/query-a556d09e8318318f36724d7ec36b1d692c98293dc0f6cdab31ee842a2f38dcc9.json b/presage-store-sqlite/.sqlx/query-a556d09e8318318f36724d7ec36b1d692c98293dc0f6cdab31ee842a2f38dcc9.json new file mode 100644 index 000000000..c58f9d109 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-a556d09e8318318f36724d7ec36b1d692c98293dc0f6cdab31ee842a2f38dcc9.json @@ -0,0 +1,32 @@ +{ + "db_name": "SQLite", + "query": "SELECT id, key, manifest AS \"manifest: _\" FROM sticker_packs", + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Blob" + }, + { + "name": "key", + "ordinal": 1, + "type_info": "Blob" + }, + { + "name": "manifest: _", + "ordinal": 2, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "a556d09e8318318f36724d7ec36b1d692c98293dc0f6cdab31ee842a2f38dcc9" +} diff --git a/presage-store-sqlite/.sqlx/query-a76103b5ae8fd6e8b60d81d3a4812e2855b2b3511af5171f21fed953d61f3f40.json b/presage-store-sqlite/.sqlx/query-a76103b5ae8fd6e8b60d81d3a4812e2855b2b3511af5171f21fed953d61f3f40.json new file mode 100644 index 000000000..e4be8f369 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-a76103b5ae8fd6e8b60d81d3a4812e2855b2b3511af5171f21fed953d61f3f40.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO kyber_pre_keys (id, identity, record) VALUES (?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "a76103b5ae8fd6e8b60d81d3a4812e2855b2b3511af5171f21fed953d61f3f40" +} diff --git a/presage-store-sqlite/.sqlx/query-b01ca4e2420035eeb33e86b85f6c893b81393386ec2dcb4fc3a86e8f62065a22.json b/presage-store-sqlite/.sqlx/query-b01ca4e2420035eeb33e86b85f6c893b81393386ec2dcb4fc3a86e8f62065a22.json new file mode 100644 index 000000000..a8b217f8c --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-b01ca4e2420035eeb33e86b85f6c893b81393386ec2dcb4fc3a86e8f62065a22.json @@ -0,0 +1,32 @@ +{ + "db_name": "SQLite", + "query": "SELECT id, key, manifest AS \"manifest: _\" FROM sticker_packs WHERE id = ?", + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Blob" + }, + { + "name": "key", + "ordinal": 1, + "type_info": "Blob" + }, + { + "name": "manifest: _", + "ordinal": 2, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "b01ca4e2420035eeb33e86b85f6c893b81393386ec2dcb4fc3a86e8f62065a22" +} diff --git a/presage-store-sqlite/.sqlx/query-b14d036992c98c6b4924cbe0c9b73ab4699b0de64f110584462e17f740bcbf86.json b/presage-store-sqlite/.sqlx/query-b14d036992c98c6b4924cbe0c9b73ab4699b0de64f110584462e17f740bcbf86.json new file mode 100644 index 000000000..405b21d99 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-b14d036992c98c6b4924cbe0c9b73ab4699b0de64f110584462e17f740bcbf86.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM sender_keys\n WHERE address = ? AND device_id = ? AND identity = ? AND distribution_id = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 4 + }, + "nullable": [ + false + ] + }, + "hash": "b14d036992c98c6b4924cbe0c9b73ab4699b0de64f110584462e17f740bcbf86" +} diff --git a/presage-store-sqlite/.sqlx/query-b42ba31c82cd8a89bac53c8afe33d5ffb892ab567b549003d4b1063b47cf993f.json b/presage-store-sqlite/.sqlx/query-b42ba31c82cd8a89bac53c8afe33d5ffb892ab567b549003d4b1063b47cf993f.json new file mode 100644 index 000000000..97cdc00c8 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-b42ba31c82cd8a89bac53c8afe33d5ffb892ab567b549003d4b1063b47cf993f.json @@ -0,0 +1,92 @@ +{ + "db_name": "SQLite", + "query": "SELECT * FROM contacts c\n LEFT JOIN contacts_verification_state cv ON c.uuid = cv.destination_aci\n ORDER BY c.inbox_position", + "describe": { + "columns": [ + { + "name": "uuid", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "phone_number", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "name", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "color", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "profile_key", + "ordinal": 4, + "type_info": "Blob" + }, + { + "name": "expire_timer", + "ordinal": 5, + "type_info": "Integer" + }, + { + "name": "expire_timer_version", + "ordinal": 6, + "type_info": "Integer" + }, + { + "name": "inbox_position", + "ordinal": 7, + "type_info": "Integer" + }, + { + "name": "archived", + "ordinal": 8, + "type_info": "Bool" + }, + { + "name": "avatar", + "ordinal": 9, + "type_info": "Blob" + }, + { + "name": "destination_aci", + "ordinal": 10, + "type_info": "Text" + }, + { + "name": "identity_key", + "ordinal": 11, + "type_info": "Blob" + }, + { + "name": "is_verified", + "ordinal": 12, + "type_info": "Bool" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false, + true, + false, + true, + false, + false, + false, + false, + false, + true, + true, + true, + true + ] + }, + "hash": "b42ba31c82cd8a89bac53c8afe33d5ffb892ab567b549003d4b1063b47cf993f" +} diff --git a/presage-store-sqlite/.sqlx/query-b8132dfdac9d908be4a0456599e6baaa6295ed358dac091476662ac6b137ee8c.json b/presage-store-sqlite/.sqlx/query-b8132dfdac9d908be4a0456599e6baaa6295ed358dac091476662ac6b137ee8c.json new file mode 100644 index 000000000..e3dd3fa87 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-b8132dfdac9d908be4a0456599e6baaa6295ed358dac091476662ac6b137ee8c.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "UPDATE group_avatars SET bytes = ? WHERE group_master_key = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "b8132dfdac9d908be4a0456599e6baaa6295ed358dac091476662ac6b137ee8c" +} diff --git a/presage-store-sqlite/.sqlx/query-b9b8df9c4968459e1da40a35b6c83e26514ccddd11f319e5b5982af9333bf34d.json b/presage-store-sqlite/.sqlx/query-b9b8df9c4968459e1da40a35b6c83e26514ccddd11f319e5b5982af9333bf34d.json new file mode 100644 index 000000000..1a0bee851 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-b9b8df9c4968459e1da40a35b6c83e26514ccddd11f319e5b5982af9333bf34d.json @@ -0,0 +1,50 @@ +{ + "db_name": "SQLite", + "query": "SELECT\n p.given_name,\n p.family_name,\n p.about,\n p.about_emoji,\n p.avatar,\n p.unrestricted_unidentified_access\n FROM profile_keys pk\n INNER JOIN profiles p ON p.uuid = pk.uuid\n WHERE pk.uuid = ? AND pk.key = ?", + "describe": { + "columns": [ + { + "name": "given_name", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "family_name", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "about", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "about_emoji", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "avatar", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "unrestricted_unidentified_access", + "ordinal": 5, + "type_info": "Bool" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + true, + true, + true, + true, + true, + false + ] + }, + "hash": "b9b8df9c4968459e1da40a35b6c83e26514ccddd11f319e5b5982af9333bf34d" +} diff --git a/presage-store-sqlite/.sqlx/query-bb92893b22752f1fe76ca9c514d3430ee7239bb622d7d00a6c504ee9cbbe37da.json b/presage-store-sqlite/.sqlx/query-bb92893b22752f1fe76ca9c514d3430ee7239bb622d7d00a6c504ee9cbbe37da.json new file mode 100644 index 000000000..1ce62eba0 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-bb92893b22752f1fe76ca9c514d3430ee7239bb622d7d00a6c504ee9cbbe37da.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "bb92893b22752f1fe76ca9c514d3430ee7239bb622d7d00a6c504ee9cbbe37da" +} diff --git a/presage-store-sqlite/.sqlx/query-bee82922d353d9346b63e8247d834d7d8282639e182212115560a7f99f0f7f85.json b/presage-store-sqlite/.sqlx/query-bee82922d353d9346b63e8247d834d7d8282639e182212115560a7f99f0f7f85.json new file mode 100644 index 000000000..16f5adb52 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-bee82922d353d9346b63e8247d834d7d8282639e182212115560a7f99f0f7f85.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO pre_keys (id, identity, record) VALUES (?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "bee82922d353d9346b63e8247d834d7d8282639e182212115560a7f99f0f7f85" +} diff --git a/presage-store-sqlite/.sqlx/query-beff2826440b05111d590d2bccbd71c8de2e35e5008d73fbcde86a55652dd1c6.json b/presage-store-sqlite/.sqlx/query-beff2826440b05111d590d2bccbd71c8de2e35e5008d73fbcde86a55652dd1c6.json new file mode 100644 index 000000000..60d8ec405 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-beff2826440b05111d590d2bccbd71c8de2e35e5008d73fbcde86a55652dd1c6.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT bytes FROM profile_avatars WHERE uuid = ?", + "describe": { + "columns": [ + { + "name": "bytes", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "beff2826440b05111d590d2bccbd71c8de2e35e5008d73fbcde86a55652dd1c6" +} diff --git a/presage-store-sqlite/.sqlx/query-bf0058fa3b666e5ff5b816a3092bd053874d30f5fbcc09e1c313ecd51c41fad6.json b/presage-store-sqlite/.sqlx/query-bf0058fa3b666e5ff5b816a3092bd053874d30f5fbcc09e1c313ecd51c41fad6.json new file mode 100644 index 000000000..144b553b6 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-bf0058fa3b666e5ff5b816a3092bd053874d30f5fbcc09e1c313ecd51c41fad6.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO contacts_verification_state(destination_aci, identity_key, is_verified)\n VALUES(?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "bf0058fa3b666e5ff5b816a3092bd053874d30f5fbcc09e1c313ecd51c41fad6" +} diff --git a/presage-store-sqlite/.sqlx/query-bf52cac41388a9a6bc0651bd20c7112075c2d74508aaf65da107c5673d006728.json b/presage-store-sqlite/.sqlx/query-bf52cac41388a9a6bc0651bd20c7112075c2d74508aaf65da107c5673d006728.json new file mode 100644 index 000000000..a01e04dba --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-bf52cac41388a9a6bc0651bd20c7112075c2d74508aaf65da107c5673d006728.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false + ] + }, + "hash": "bf52cac41388a9a6bc0651bd20c7112075c2d74508aaf65da107c5673d006728" +} diff --git a/presage-store-sqlite/.sqlx/query-c43853cc74ab0f2f94d0f05231c731102675cd7bf2f7857cc5f2a5ebfcf2a208.json b/presage-store-sqlite/.sqlx/query-c43853cc74ab0f2f94d0f05231c731102675cd7bf2f7857cc5f2a5ebfcf2a208.json new file mode 100644 index 000000000..923d53424 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-c43853cc74ab0f2f94d0f05231c731102675cd7bf2f7857cc5f2a5ebfcf2a208.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "UPDATE profile_avatars SET bytes = ? WHERE uuid = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "c43853cc74ab0f2f94d0f05231c731102675cd7bf2f7857cc5f2a5ebfcf2a208" +} diff --git a/presage-store-sqlite/.sqlx/query-cb2555708665c60b7f8ed462dec5925a7f01fd12f059755cf8cfc58bdace49c1.json b/presage-store-sqlite/.sqlx/query-cb2555708665c60b7f8ed462dec5925a7f01fd12f059755cf8cfc58bdace49c1.json new file mode 100644 index 000000000..d7d8fa29c --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-cb2555708665c60b7f8ed462dec5925a7f01fd12f059755cf8cfc58bdace49c1.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT MAX(id) AS 'id: u32' FROM pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "id: u32", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true + ] + }, + "hash": "cb2555708665c60b7f8ed462dec5925a7f01fd12f059755cf8cfc58bdace49c1" +} diff --git a/presage-store-sqlite/.sqlx/query-d001f0fbc1f0f4b3c579c5c7a7abea02277324296452f76bb25356ce8fb0e63c.json b/presage-store-sqlite/.sqlx/query-d001f0fbc1f0f4b3c579c5c7a7abea02277324296452f76bb25356ce8fb0e63c.json new file mode 100644 index 000000000..adeee837d --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-d001f0fbc1f0f4b3c579c5c7a7abea02277324296452f76bb25356ce8fb0e63c.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO signed_pre_keys (id, identity, record) VALUES (?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "d001f0fbc1f0f4b3c579c5c7a7abea02277324296452f76bb25356ce8fb0e63c" +} diff --git a/presage-store-sqlite/.sqlx/query-d3f0413d5090a5e361c7e0cc27e8a9513212e42c15c645d0c0ebd96fe2d8ecf2.json b/presage-store-sqlite/.sqlx/query-d3f0413d5090a5e361c7e0cc27e8a9513212e42c15c645d0c0ebd96fe2d8ecf2.json new file mode 100644 index 000000000..5dd7e3498 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-d3f0413d5090a5e361c7e0cc27e8a9513212e42c15c645d0c0ebd96fe2d8ecf2.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO sessions (address, device_id, identity, record)\n VALUES (?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 4 + }, + "nullable": [] + }, + "hash": "d3f0413d5090a5e361c7e0cc27e8a9513212e42c15c645d0c0ebd96fe2d8ecf2" +} diff --git a/presage-store-sqlite/.sqlx/query-d7d74324ae4ca13875e02060afbebdfd2273cc5026506bc634627828600915f8.json b/presage-store-sqlite/.sqlx/query-d7d74324ae4ca13875e02060afbebdfd2273cc5026506bc634627828600915f8.json new file mode 100644 index 000000000..6dfdcd733 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-d7d74324ae4ca13875e02060afbebdfd2273cc5026506bc634627828600915f8.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM sessions WHERE address = ? AND device_id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 3 + }, + "nullable": [ + false + ] + }, + "hash": "d7d74324ae4ca13875e02060afbebdfd2273cc5026506bc634627828600915f8" +} diff --git a/presage-store-sqlite/.sqlx/query-d98db13a3ec012ba30a2456f57fb7ddeebe2206372655c5c2cef1c5649237eee.json b/presage-store-sqlite/.sqlx/query-d98db13a3ec012ba30a2456f57fb7ddeebe2206372655c5c2cef1c5649237eee.json new file mode 100644 index 000000000..85e81e601 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-d98db13a3ec012ba30a2456f57fb7ddeebe2206372655c5c2cef1c5649237eee.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO sticker_packs(id, key, manifest) VALUES(?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "d98db13a3ec012ba30a2456f57fb7ddeebe2206372655c5c2cef1c5649237eee" +} diff --git a/presage-store-sqlite/.sqlx/query-e617e730d0cbeb70fdabc4a54e6b5ff696f4720ec649057681553fd60206c624.json b/presage-store-sqlite/.sqlx/query-e617e730d0cbeb70fdabc4a54e6b5ff696f4720ec649057681553fd60206c624.json new file mode 100644 index 000000000..d5c0ba760 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-e617e730d0cbeb70fdabc4a54e6b5ff696f4720ec649057681553fd60206c624.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM sessions WHERE address = ? AND identity = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "e617e730d0cbeb70fdabc4a54e6b5ff696f4720ec649057681553fd60206c624" +} diff --git a/presage-store-sqlite/.sqlx/query-eb7691e6f4227aa79fe925e5f181cff2dca7bf655630d48580e74391c2579a7a.json b/presage-store-sqlite/.sqlx/query-eb7691e6f4227aa79fe925e5f181cff2dca7bf655630d48580e74391c2579a7a.json new file mode 100644 index 000000000..5b7946ac0 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-eb7691e6f4227aa79fe925e5f181cff2dca7bf655630d48580e74391c2579a7a.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT MAX(id) AS 'id: u32' FROM kyber_pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "id: u32", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true + ] + }, + "hash": "eb7691e6f4227aa79fe925e5f181cff2dca7bf655630d48580e74391c2579a7a" +} diff --git a/presage-store-sqlite/.sqlx/query-efd72a989458fced2cdc60b006c43a1464d9db3e141ceaa2978207659b38572a.json b/presage-store-sqlite/.sqlx/query-efd72a989458fced2cdc60b006c43a1464d9db3e141ceaa2978207659b38572a.json new file mode 100644 index 000000000..ecc2bea6a --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-efd72a989458fced2cdc60b006c43a1464d9db3e141ceaa2978207659b38572a.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO kv (key, value) VALUES ('registration', ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "efd72a989458fced2cdc60b006c43a1464d9db3e141ceaa2978207659b38572a" +} diff --git a/presage-store-sqlite/.sqlx/query-f0a273c8a87f790e3d0cb7595f2f401f35d0abfa4c6cc6a94972e46eb059ad30.json b/presage-store-sqlite/.sqlx/query-f0a273c8a87f790e3d0cb7595f2f401f35d0abfa4c6cc6a94972e46eb059ad30.json new file mode 100644 index 000000000..a0c38230a --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-f0a273c8a87f790e3d0cb7595f2f401f35d0abfa4c6cc6a94972e46eb059ad30.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT MAX(id) AS 'id: u32' FROM signed_pre_keys WHERE identity = ?", + "describe": { + "columns": [ + { + "name": "id: u32", + "ordinal": 0, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true + ] + }, + "hash": "f0a273c8a87f790e3d0cb7595f2f401f35d0abfa4c6cc6a94972e46eb059ad30" +} diff --git a/presage-store-sqlite/.sqlx/query-fadab658b7f0c0dfd2444950966fd8f7f95032eda602bfd5afbc62d6061981f9.json b/presage-store-sqlite/.sqlx/query-fadab658b7f0c0dfd2444950966fd8f7f95032eda602bfd5afbc62d6061981f9.json new file mode 100644 index 000000000..8311552f7 --- /dev/null +++ b/presage-store-sqlite/.sqlx/query-fadab658b7f0c0dfd2444950966fd8f7f95032eda602bfd5afbc62d6061981f9.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT record FROM kyber_pre_keys WHERE id = ? AND identity = ?", + "describe": { + "columns": [ + { + "name": "record", + "ordinal": 0, + "type_info": "Blob" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false + ] + }, + "hash": "fadab658b7f0c0dfd2444950966fd8f7f95032eda602bfd5afbc62d6061981f9" +} diff --git a/presage-store-sqlite/Cargo.toml b/presage-store-sqlite/Cargo.toml index 4f3d6057b..ab0aa2e36 100644 --- a/presage-store-sqlite/Cargo.toml +++ b/presage-store-sqlite/Cargo.toml @@ -4,10 +4,16 @@ version = "0.1.0" edition = "2021" [dependencies] -async-trait = "0.1.83" -chrono = "0.4.38" presage = { path = "../presage" } -presage-store-cipher = { path = "../presage-store-cipher", optional = true } -sqlx = { version = "0.8.2", features = ["sqlite"] } +async-trait = "0.1.83" +chrono = "0.4.38" +serde_json = "1.0.135" +sqlx = { version = "0.8.2", features = ["json", "sqlite", "uuid"] } thiserror = "1.0.65" +tracing = "0.1.41" +uuid = "1.12.0" +prost = "0.13.4" +postcard = { version = "1.1.1", features = ["alloc"] } +serde = "1.0.217" +bytes = "1.9.0" diff --git a/presage-store-sqlite/migrations/20250112201436_init.sql b/presage-store-sqlite/migrations/20250112201436_init.sql new file mode 100644 index 000000000..6004bdaa3 --- /dev/null +++ b/presage-store-sqlite/migrations/20250112201436_init.sql @@ -0,0 +1,133 @@ +CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY, value BLOB NOT NULL); + +-- protocol +CREATE TABLE IF NOT EXISTS sessions ( + address TEXT NOT NULL, + device_id INTEGER NOT NULL, + identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')), + record BLOB NOT NULL, + PRIMARY KEY (address, device_id, identity) +); + +CREATE TABLE IF NOT EXISTS identities ( + address TEXT NOT NULL, + device_id INTEGER NOT NULL, + identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')), + record BLOB NOT NULL, + PRIMARY KEY (address, device_id, identity) +); + +CREATE TABLE IF NOT EXISTS pre_keys ( + id INTEGER NOT NULL, + identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')), + record BLOB NOT NULL, + PRIMARY KEY (id, identity) +); + +CREATE TABLE IF NOT EXISTS signed_pre_keys ( + id INTEGER NOT NULL, + identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')), + record BLOB NOT NULL, + PRIMARY KEY (id, identity) +); + +CREATE TABLE IF NOT EXISTS kyber_pre_keys ( + id INTEGER NOT NULL, + identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')), + record BLOB NOT NULL, + is_last_resort INTEGER NOT NULL DEFAULT 0, + PRIMARY KEY (id, identity) +); + +CREATE TABLE sender_keys ( + address TEXT NOT NULL, + device_id INTEGER NOT NULL, + identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')), + distribution_id TEXT NOT NULL, + record BLOB NOT NULL, + PRIMARY KEY (address, device_id, identity, distribution_id) +); + +-- content +CREATE TABLE contacts ( + uuid VARCHAR(36) NOT NULL PRIMARY KEY, + phone_number TEXT, + name TEXT NOT NULL, + color TEXT, + profile_key BLOB NOT NULL, + expire_timer INTEGER NOT NULL, + expire_timer_version INTEGER NOT NULL DEFAULT 2, + inbox_position INTEGER NOT NULL, + archived BOOLEAN NOT NULL, + avatar BLOB +); + +CREATE TABLE contacts_verification_state ( + destination_aci TEXT NOT NULL PRIMARY KEY, + identity_key BLOB NOT NULL, + is_verified BOOLEAN, + FOREIGN KEY (destination_aci) REFERENCES contacts (uuid) ON UPDATE CASCADE +); + +CREATE TABLE profile_keys (uuid BLOB NOT NULL PRIMARY KEY, key BLOB NOT NULL); + +CREATE TABLE profiles ( + uuid BLOB NOT NULL PRIMARY KEY, + given_name TEXT, + family_name TEXT, + about TEXT, + about_emoji TEXT, + avatar TEXT, + unrestricted_unidentified_access BOOLEAN NOT NULL DEFAULT 0, + FOREIGN KEY (uuid) REFERENCES profile_keys (uuid) ON DELETE CASCADE +); + +CREATE TABLE profile_avatars ( + uuid BLOB NOT NULL PRIMARY KEY, + bytes BLOB NOT NULL, + FOREIGN KEY (uuid) REFERENCES profile_keys (uuid) ON UPDATE CASCADE +); + +CREATE TABLE IF NOT EXISTS groups ( + master_key BLOB NOT NULL PRIMARY KEY, + title TEXT NOT NULL, + revision INTEGER NOT NULL DEFAULT 0, + invite_link_password BLOB, + access_control BLOB, + avatar TEXT NOT NULL, + description TEXT, + members BLOB NOT NULL, + pending_members BLOB NOT NULL, + requesting_members BLOB NOT NULL +); + +CREATE TABLE group_avatars ( + group_master_key BLOB PRIMARY KEY, + bytes BLOB NOT NULL, + FOREIGN KEY (group_master_key) REFERENCES groups (master_key) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS threads ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + group_master_key BLOB UNIQUE, + recipient_id TEXT UNIQUE +); + +CREATE TABLE IF NOT EXISTS thread_messages ( + ts INTEGER NOT NULL, + thread_id INTEGER NOT NULL, + sender_service_id TEXT NOT NULL, + sender_device_id INTEGER NOT NULL, + destination_service_id TEXT NOT NULL, + needs_receipt BOOLEAN NOT NULL, + unidentified_sender BOOLEAN NOT NULL, + content_body BLOB NOT NULL, + PRIMARY KEY (ts, thread_id), + FOREIGN KEY (thread_id) REFERENCES threads (id) ON UPDATE CASCADE +); + +CREATE TABLE sticker_packs ( + id BLOB PRIMARY KEY NOT NULL, + key BLOB NOT NULL, + manifest BLOB NOT NULL +); diff --git a/presage-store-sqlite/src/content.rs b/presage-store-sqlite/src/content.rs index b06932ca4..24d387a10 100644 --- a/presage-store-sqlite/src/content.rs +++ b/presage-store-sqlite/src/content.rs @@ -1,23 +1,35 @@ -use std::marker::PhantomData; +use std::ops::{Bound, RangeBounds}; use presage::{ - libsignal_service::{prelude::Content, zkgroup::GroupMasterKeyBytes}, + libsignal_service::{ + content::Metadata, + prelude::{Content, ProfileKey, Uuid}, + zkgroup::GroupMasterKeyBytes, + Profile, + }, model::{contacts::Contact, groups::Group}, - store::{ContentsStore, StickerPack}, + proto::{verified, Verified}, + store::{ContentsStore, StickerPack, Thread}, + AvatarBytes, }; +use sqlx::{query, query_as, query_scalar, types::Json}; -use crate::{SqliteStore, SqliteStoreError}; +use crate::{ + data::{SqlContact, SqlGroup, SqlMessage, SqlProfile, SqlStickerPack}, + SqliteStore, SqliteStoreError, +}; impl ContentsStore for SqliteStore { type ContentsStoreError = SqliteStoreError; - type ContactsIter = DummyIter>; + type ContactsIter = Box>>; - type GroupsIter = DummyIter>; + type GroupsIter = + Box>>; - type MessagesIter = DummyIter>; + type MessagesIter = Box>>; - type StickerPacksIter = DummyIter>; + type StickerPacksIter = Box>>; async fn clear_profiles(&mut self) -> Result<(), Self::ContentsStoreError> { todo!() @@ -31,187 +43,572 @@ impl ContentsStore for SqliteStore { todo!() } - async fn clear_thread( - &mut self, - thread: &presage::store::Thread, - ) -> Result<(), Self::ContentsStoreError> { - todo!() + async fn clear_thread(&mut self, thread: &Thread) -> Result<(), Self::ContentsStoreError> { + let (group_master_key, recipient_id) = thread.unzip(); + query!( + "DELETE FROM thread_messages WHERE thread_id = ( + SELECT id FROM threads WHERE group_master_key = ? OR recipient_id = ?)", + group_master_key, + recipient_id, + ) + .execute(&self.db) + .await?; + Ok(()) } async fn save_message( &self, - thread: &presage::store::Thread, - message: presage::libsignal_service::prelude::Content, + thread: &Thread, + Content { metadata, body }: Content, ) -> Result<(), Self::ContentsStoreError> { - todo!() + let mut tx = self.db.begin().await?; + + let thread_id = match thread { + Thread::Contact(uuid) => { + query_scalar!( + "INSERT INTO threads(recipient_id, group_master_key) VALUES (?, NULL) + ON CONFLICT DO NOTHING RETURNING id", + uuid, + ) + .fetch_one(&mut *tx) + .await? + } + Thread::Group(master_key_bytes) => { + let master_key_bytes = master_key_bytes.as_slice(); + query_scalar!( + "INSERT INTO threads(recipient_id, group_master_key) VALUES (NULL, ?) + ON CONFLICT DO NOTHING RETURNING id", + master_key_bytes + ) + .fetch_one(&mut *tx) + .await? + } + }; + + let Metadata { + sender, + destination, + sender_device, + timestamp, + needs_receipt, + unidentified_sender, + server_guid: _, + } = metadata; + + let sender_service_id = sender.service_id_string(); + let destination_service_id = destination.service_id_string(); + + let proto_bytes = prost::Message::encode_to_vec(&body.into_proto()); + let timestamp: i64 = timestamp + .try_into() + .map_err(|_| SqliteStoreError::InvalidFormat)?; + + query!( + "INSERT OR REPLACE INTO thread_messages ( + ts, + thread_id, + sender_service_id, + sender_device_id, + destination_service_id, + needs_receipt, + unidentified_sender, + content_body + ) + VALUES(?, ?, ?, ?, ?, ?, ?, ?)", + timestamp, + thread_id, + sender_service_id, + sender_device, + destination_service_id, + needs_receipt, + unidentified_sender, + proto_bytes + ) + .execute(&mut *tx) + .await?; + + tx.commit().await?; + Ok(()) } async fn delete_message( &mut self, - thread: &presage::store::Thread, + thread: &Thread, timestamp: u64, ) -> Result { - todo!() + let timestamp: i64 = timestamp + .try_into() + .map_err(|_| SqliteStoreError::InvalidFormat)?; + let (group_master_key, recipient_id) = thread.unzip(); + let res = query!( + "DELETE FROM thread_messages + WHERE ts = ? AND thread_id = ( + SELECT id FROM threads WHERE group_master_key = ? OR recipient_id = ?)", + timestamp, + group_master_key, + recipient_id, + ) + .execute(&self.db) + .await?; + Ok(res.rows_affected() > 0) } async fn message( &self, - thread: &presage::store::Thread, + thread: &Thread, timestamp: u64, - ) -> Result, Self::ContentsStoreError> - { - todo!() + ) -> Result, Self::ContentsStoreError> { + let timestamp: i64 = timestamp + .try_into() + .map_err(|_| SqliteStoreError::InvalidFormat)?; + let (group_master_key, recipient_id) = thread.unzip(); + let message = query_as!( + SqlMessage, + r#"SELECT + ts AS "ts: _", + sender_service_id, + sender_device_id AS "sender_device_id: _", + destination_service_id, + needs_receipt, + unidentified_sender, + content_body + FROM thread_messages + WHERE ts = ? AND thread_id = ( + SELECT id FROM threads WHERE group_master_key = ? OR recipient_id = ?)"#, + timestamp, + group_master_key, + recipient_id, + ) + .fetch_optional(&self.db) + .await?; + message.map(|m| m.try_into()).transpose() } async fn messages( &self, - thread: &presage::store::Thread, - range: impl std::ops::RangeBounds, + thread: &Thread, + range: impl RangeBounds, ) -> Result { - todo!() + let (group_master_key, recipient_id) = thread.unzip(); + + let (start_incl, start_excl) = range.start_bound().into_sql_bound(); + let (end_incl, end_excl) = range.end_bound().into_sql_bound(); + + let rows = query_as!( + SqlMessage, + r#"SELECT + ts AS "ts: _", + sender_service_id, + sender_device_id AS "sender_device_id: _", + destination_service_id, + needs_receipt, + unidentified_sender, + content_body + FROM thread_messages + WHERE thread_id = ( + SELECT id FROM threads WHERE group_master_key = ? OR recipient_id = ?) + AND coalesce(ts > ?, ts >= ?, true) + AND coalesce(ts < ?, ts <= ?, true) + ORDER BY ts DESC"#, + group_master_key, + recipient_id, + start_incl, + start_excl, + end_incl, + end_excl + ) + .fetch_all(&self.db) + .await?; + + Ok(Box::new(rows.into_iter().map(TryInto::try_into))) } async fn clear_contacts(&mut self) -> Result<(), Self::ContentsStoreError> { - todo!() + query!("DELETE FROM contacts").execute(&self.db).await?; + Ok(()) } - async fn save_contact( - &mut self, - contacts: &presage::model::contacts::Contact, - ) -> Result<(), Self::ContentsStoreError> { - todo!() + async fn save_contact(&mut self, contact: &Contact) -> Result<(), Self::ContentsStoreError> { + let profile_key: &[u8] = contact.profile_key.as_ref(); + let avatar_bytes = contact.avatar.as_ref().map(|a| a.reader.to_vec()); + let phone_number = contact.phone_number.as_ref().map(|p| p.to_string()); + + let mut tx = self.db.begin().await?; + + query!( + "INSERT OR REPLACE INTO contacts + VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + contact.uuid, + phone_number, + contact.name, + contact.color, + profile_key, + contact.expire_timer, + contact.expire_timer_version, + contact.inbox_position, + contact.archived, + avatar_bytes, + ) + .execute(&mut *tx) + .await?; + + let Verified { + destination_aci, + identity_key, + state, + .. + } = &contact.verified; + let is_verified = match verified::State::try_from(state.unwrap_or_default()) { + Err(_) | Ok(verified::State::Default) => None, + Ok(verified::State::Unverified) => Some(false), + Ok(verified::State::Verified) => Some(true), + }; + + query!( + "INSERT OR REPLACE INTO contacts_verification_state(destination_aci, identity_key, is_verified) + VALUES(?, ?, ?)", + destination_aci, + identity_key, + is_verified, + ) + .execute(&mut *tx) + .await?; + + tx.commit().await?; + + Ok(()) } async fn contacts(&self) -> Result { - todo!() + let sql_contacts = query_as!( + SqlContact, + "SELECT * FROM contacts c + LEFT JOIN contacts_verification_state cv ON c.uuid = cv.destination_aci + ORDER BY c.inbox_position" + ) + .fetch_all(&self.db) + .await?; + Ok(Box::new(sql_contacts.into_iter().map(TryInto::try_into))) } - async fn contact_by_id( - &self, - id: &presage::libsignal_service::prelude::Uuid, - ) -> Result, Self::ContentsStoreError> { - todo!() + async fn contact_by_id(&self, id: &Uuid) -> Result, Self::ContentsStoreError> { + query_as!( + SqlContact, + "SELECT * FROM contacts c + LEFT JOIN contacts_verification_state cv ON c.uuid = cv.destination_aci + WHERE c.uuid = ?", + id + ) + .fetch_optional(&self.db) + .await? + .map(TryInto::try_into) + .transpose() } async fn clear_groups(&mut self) -> Result<(), Self::ContentsStoreError> { - todo!() + query!("DELETE FROM groups").execute(&self.db).await?; + Ok(()) } async fn save_group( &self, - master_key: presage::libsignal_service::zkgroup::GroupMasterKeyBytes, - group: impl Into, + master_key: GroupMasterKeyBytes, + group: impl Into, ) -> Result<(), Self::ContentsStoreError> { - todo!() + let g = SqlGroup::from_group(&master_key, group.into()); + let master_key = g.master_key.as_ref(); + query!( + "INSERT OR REPLACE INTO groups VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + master_key, + g.title, + g.revision, + g.invite_link_password, + g.access_control, + g.avatar, + g.description, + g.members, + g.pending_members, + g.requesting_members, + ) + .execute(&self.db) + .await?; + Ok(()) } async fn groups(&self) -> Result { - todo!() + let sql_groups = query_as!( + SqlGroup, + r#"SELECT + master_key, + title, + revision AS "revision: _", + invite_link_password, + access_control AS "access_control: _", + avatar, + description, + members AS "members: _", + pending_members AS "pending_members: _", + requesting_members AS "requesting_members: _" + FROM groups"#, + ) + .fetch_all(&self.db) + .await?; + Ok(Box::new(sql_groups.into_iter().map(SqlGroup::into_group))) } async fn group( &self, - master_key: presage::libsignal_service::zkgroup::GroupMasterKeyBytes, - ) -> Result, Self::ContentsStoreError> { - todo!() + master_key: GroupMasterKeyBytes, + ) -> Result, Self::ContentsStoreError> { + let master_key_bytes = master_key.as_slice(); + query_as!( + SqlGroup, + r#"SELECT + master_key, + title, + revision AS "revision: _", + invite_link_password, + access_control AS "access_control: _", + avatar, + description, + members AS "members: _", + pending_members AS "pending_members: _", + requesting_members AS "requesting_members: _" + FROM groups + WHERE master_key = ? + LIMIT 1"#, + master_key_bytes, + ) + .fetch_optional(&self.db) + .await? + .map(|g| g.into_group().map(|(_master_key, group)| group)) + .transpose() } async fn save_group_avatar( &self, - master_key: presage::libsignal_service::zkgroup::GroupMasterKeyBytes, - avatar: &presage::AvatarBytes, + master_key: GroupMasterKeyBytes, + avatar: &AvatarBytes, ) -> Result<(), Self::ContentsStoreError> { - todo!() + let master_key_bytes = master_key.as_slice(); + query!( + "UPDATE group_avatars SET bytes = ? WHERE group_master_key = ?", + avatar, + master_key_bytes, + ) + .execute(&self.db) + .await?; + Ok(()) } async fn group_avatar( &self, - master_key: presage::libsignal_service::zkgroup::GroupMasterKeyBytes, - ) -> Result, Self::ContentsStoreError> { - todo!() + master_key: GroupMasterKeyBytes, + ) -> Result, Self::ContentsStoreError> { + let master_key_bytes = master_key.as_slice(); + query_scalar!( + "SELECT bytes FROM group_avatars WHERE group_master_key = ?", + master_key_bytes, + ) + .fetch_optional(&self.db) + .await + .map_err(From::from) } async fn upsert_profile_key( &mut self, - uuid: &presage::libsignal_service::prelude::Uuid, - key: presage::libsignal_service::prelude::ProfileKey, + uuid: &Uuid, + key: ProfileKey, ) -> Result { - todo!() + let profile_key_bytes = key.bytes.as_slice(); + let res = query_scalar!( + "INSERT OR REPLACE INTO profile_keys (uuid, key) VALUES (?, ?)", + uuid, + profile_key_bytes + ) + .execute(&self.db) + .await?; + Ok(res.rows_affected() == 0) } async fn profile_key( &self, - uuid: &presage::libsignal_service::prelude::Uuid, - ) -> Result, Self::ContentsStoreError> - { - todo!() + uuid: &Uuid, + ) -> Result, Self::ContentsStoreError> { + let profile_key = query_scalar!("SELECT key FROM profile_keys WHERE uuid = ?", uuid) + .fetch_optional(&self.db) + .await? + .and_then(|bytes| bytes.try_into().ok().map(ProfileKey::create)); + Ok(profile_key) } async fn save_profile( &mut self, - uuid: presage::libsignal_service::prelude::Uuid, - key: presage::libsignal_service::prelude::ProfileKey, - profile: presage::libsignal_service::Profile, + uuid: Uuid, + key: ProfileKey, + profile: Profile, ) -> Result<(), Self::ContentsStoreError> { - todo!() + self.upsert_profile_key(&uuid, key).await?; + let Profile { + name, + about, + about_emoji, + avatar, + unrestricted_unidentified_access, + } = profile; + let (given_name, family_name) = name.map(|n| (n.given_name, n.family_name)).unzip(); + let family_name = family_name.flatten(); + query!( + "INSERT OR REPLACE INTO profiles VALUES (?, ?, ?, ?, ?, ?, ?)", + uuid, + given_name, + family_name, + about, + about_emoji, + avatar, + unrestricted_unidentified_access, + ) + .execute(&self.db) + .await?; + Ok(()) } async fn profile( &self, - uuid: presage::libsignal_service::prelude::Uuid, - key: presage::libsignal_service::prelude::ProfileKey, - ) -> Result, Self::ContentsStoreError> { - todo!() + uuid: Uuid, + key: ProfileKey, + ) -> Result, Self::ContentsStoreError> { + let profile_key_bytes = key.bytes.as_slice(); + let profile = query_as!( + SqlProfile, + "SELECT + p.given_name, + p.family_name, + p.about, + p.about_emoji, + p.avatar, + p.unrestricted_unidentified_access + FROM profile_keys pk + INNER JOIN profiles p ON p.uuid = pk.uuid + WHERE pk.uuid = ? AND pk.key = ?", + uuid, + profile_key_bytes, + ) + .fetch_optional(&self.db) + .await?; + Ok(profile.map(|p| p.into())) } async fn save_profile_avatar( &mut self, - uuid: presage::libsignal_service::prelude::Uuid, - key: presage::libsignal_service::prelude::ProfileKey, - profile: &presage::AvatarBytes, + uuid: Uuid, + _key: ProfileKey, + profile: &AvatarBytes, ) -> Result<(), Self::ContentsStoreError> { - todo!() + query!( + "UPDATE profile_avatars SET bytes = ? WHERE uuid = ?", + profile, + uuid, + ) + .execute(&self.db) + .await?; + Ok(()) } async fn profile_avatar( &self, - uuid: presage::libsignal_service::prelude::Uuid, - key: presage::libsignal_service::prelude::ProfileKey, - ) -> Result, Self::ContentsStoreError> { - todo!() + uuid: Uuid, + _key: ProfileKey, + ) -> Result, Self::ContentsStoreError> { + query_scalar!("SELECT bytes FROM profile_avatars WHERE uuid = ?", uuid) + .fetch_optional(&self.db) + .await + .map_err(From::from) } async fn add_sticker_pack( &mut self, - pack: &presage::store::StickerPack, + pack: &StickerPack, ) -> Result<(), Self::ContentsStoreError> { - todo!() + let manifest_json = Json(&pack.manifest); + query!( + "INSERT OR REPLACE INTO sticker_packs(id, key, manifest) VALUES(?, ?, ?)", + pack.id, + pack.key, + manifest_json, + ) + .execute(&self.db) + .await?; + Ok(()) } async fn sticker_pack( &self, id: &[u8], - ) -> Result, Self::ContentsStoreError> { - todo!() + ) -> Result, Self::ContentsStoreError> { + let pack = query_as!( + SqlStickerPack, + r#"SELECT id, key, manifest AS "manifest: _" FROM sticker_packs WHERE id = ?"#, + id + ) + .fetch_optional(&self.db) + .await?; + Ok(pack.map(From::from)) } async fn remove_sticker_pack(&mut self, id: &[u8]) -> Result { - todo!() + let res = query!("DELETE FROM sticker_packs WHERE id = ?", id) + .execute(&self.db) + .await?; + Ok(res.rows_affected() > 0) } async fn sticker_packs(&self) -> Result { - todo!() + let sql_packs = query_as!( + SqlStickerPack, + r#"SELECT id, key, manifest AS "manifest: _" FROM sticker_packs"#, + ) + .fetch_all(&self.db) + .await?; + Ok(Box::new(sql_packs.into_iter().map(|pack| Ok(pack.into())))) } } -pub struct DummyIter { - _data: PhantomData, +trait ThreadExt { + fn group_master_key(&self) -> Option<&[u8]>; + fn recipient_id(&self) -> Option; + + fn unzip(&self) -> (Option<&[u8]>, Option) { + (self.group_master_key(), self.recipient_id()) + } } -impl Iterator for DummyIter { - type Item = T; +impl ThreadExt for Thread { + fn group_master_key(&self) -> Option<&[u8]> { + match self { + Thread::Contact(_) => None, + Thread::Group(master_key) => Some(master_key.as_slice()), + } + } - fn next(&mut self) -> Option { - todo!() + fn recipient_id(&self) -> Option { + match self { + Thread::Contact(uuid) => Some(*uuid), + Thread::Group(_) => None, + } + } +} + +trait BoundExt { + fn into_sql_bound(self) -> (Option, Option); +} + +impl BoundExt for Bound<&u64> { + fn into_sql_bound(self) -> (Option, Option) { + match self { + Bound::Excluded(x) => (Some(*x as i64), None), + Bound::Included(x) => (None, Some(*x as i64)), + Bound::Unbounded => (None, None), + } } } diff --git a/presage-store-sqlite/src/data.rs b/presage-store-sqlite/src/data.rs new file mode 100644 index 000000000..e012cb40f --- /dev/null +++ b/presage-store-sqlite/src/data.rs @@ -0,0 +1,243 @@ +use std::borrow::Cow; + +use bytes::Bytes; +use presage::{ + libsignal_service::{ + content::Metadata, + models::Attachment, + prelude::{phonenumber, AccessControl, Content, Member}, + profile_name::ProfileName, + protocol::ServiceId, + zkgroup::GroupMasterKeyBytes, + Profile, + }, + model::{ + contacts::Contact, + groups::{Group, PendingMember, RequestingMember}, + }, + proto::{self, verified, Verified}, + store::{StickerPack, StickerPackManifest}, +}; +use sqlx::types::Json; + +use crate::SqliteStoreError; + +#[derive(Debug)] +pub struct SqlContact { + pub uuid: String, + pub phone_number: Option, + pub name: String, + pub color: Option, + pub profile_key: Vec, + pub expire_timer: i64, + pub expire_timer_version: i64, + pub inbox_position: i64, + pub archived: bool, + pub avatar: Option>, + + pub destination_aci: Option, + pub identity_key: Option>, + pub is_verified: Option, +} + +impl TryInto for SqlContact { + type Error = SqliteStoreError; + + #[tracing::instrument] + fn try_into(self) -> Result { + Ok(Contact { + uuid: self.uuid.parse()?, + phone_number: self + .phone_number + .map(|p| phonenumber::parse(None, &p)) + .transpose()?, + name: self.name, + color: self.color, + verified: Verified { + destination_aci: self.destination_aci, + identity_key: self.identity_key, + state: self.is_verified.map(|v| { + match v { + true => verified::State::Verified, + false => verified::State::Unverified, + } + .into() + }), + null_message: None, + }, + profile_key: self.profile_key, + expire_timer: self.expire_timer as u32, + expire_timer_version: self.expire_timer_version as u32, + inbox_position: self.inbox_position as u32, + archived: self.archived, + avatar: self.avatar.map(|b| Attachment { + content_type: "application/octet-stream".to_owned(), + reader: Bytes::from(b), + }), + }) + } +} + +#[derive(Debug)] +pub struct SqlProfile { + pub given_name: Option, + pub family_name: Option, + pub about: Option, + pub about_emoji: Option, + pub avatar: Option, + pub unrestricted_unidentified_access: bool, +} + +impl From for Profile { + fn from( + SqlProfile { + given_name, + family_name, + about, + about_emoji, + avatar, + unrestricted_unidentified_access, + }: SqlProfile, + ) -> Self { + Profile { + name: given_name.map(|gn| ProfileName { + given_name: gn, + family_name, + }), + about, + about_emoji, + avatar, + unrestricted_unidentified_access, + } + } +} + +#[derive(Debug)] +pub(crate) struct SqlGroup<'a> { + pub(crate) master_key: Cow<'a, [u8]>, + pub(crate) title: String, + pub(crate) revision: u32, + pub(crate) invite_link_password: Option>, + pub(crate) access_control: Option>, + pub(crate) avatar: String, + pub(crate) description: Option, + pub(crate) members: Json>, + pub(crate) pending_members: Json>, + pub(crate) requesting_members: Json>, +} + +impl SqlGroup<'_> { + #[tracing::instrument] + pub fn from_group(master_key: &GroupMasterKeyBytes, group: Group) -> SqlGroup { + SqlGroup { + master_key: Cow::Borrowed(master_key.as_slice()), + title: group.title, + revision: group.revision, + invite_link_password: Some(group.invite_link_password), + access_control: group.access_control.map(Json), + avatar: group.avatar, + description: group.description, + members: Json(group.members), + pending_members: Json(group.pending_members), + requesting_members: Json(group.requesting_members), + } + } + + #[tracing::instrument] + pub fn into_group(self) -> Result<(GroupMasterKeyBytes, Group), SqliteStoreError> { + let Self { + master_key, + title, + revision, + invite_link_password, + access_control, + avatar, + description, + members: Json(members), + pending_members: Json(pending_members), + requesting_members: Json(requesting_members), + } = self; + let master_key = master_key + .as_ref() + .try_into() + .map_err(|_| SqliteStoreError::InvalidFormat)?; + let access_control = access_control.map(|Json(x)| x); + let group = Group { + title, + avatar, + disappearing_messages_timer: None, + access_control, + revision, + members, + pending_members, + requesting_members, + invite_link_password: invite_link_password.unwrap_or_default(), + description, + }; + Ok((master_key, group)) + } +} + +#[derive(Debug)] +pub struct SqlMessage { + pub ts: u64, + + pub sender_service_id: String, + pub sender_device_id: u32, + pub destination_service_id: String, + pub needs_receipt: bool, + pub unidentified_sender: bool, + + pub content_body: Vec, +} + +impl TryInto for SqlMessage { + type Error = SqliteStoreError; + + #[tracing::instrument] + fn try_into(self) -> Result { + let Self { + ts, + sender_service_id, + sender_device_id, + destination_service_id, + needs_receipt, + unidentified_sender, + content_body, + } = self; + let body: proto::Content = + prost::Message::decode(&*content_body).map_err(|_| SqliteStoreError::InvalidFormat)?; + let sender = ServiceId::parse_from_service_id_string(&sender_service_id) + .ok_or_else(|| SqliteStoreError::InvalidFormat)?; + let destination = ServiceId::parse_from_service_id_string(&destination_service_id) + .ok_or_else(|| SqliteStoreError::InvalidFormat)?; + let metadata = Metadata { + sender, + destination, + sender_device: sender_device_id, + timestamp: ts, + needs_receipt, + unidentified_sender, + server_guid: None, + }; + Content::from_proto(body, metadata).map_err(|_| SqliteStoreError::InvalidFormat) + } +} + +pub(crate) struct SqlStickerPack { + pub(crate) id: Vec, + pub(crate) key: Vec, + pub(crate) manifest: Json, +} + +impl From for StickerPack { + fn from( + SqlStickerPack { + id, + key, + manifest: Json(manifest), + }: SqlStickerPack, + ) -> Self { + StickerPack { id, key, manifest } + } +} diff --git a/presage-store-sqlite/src/error.rs b/presage-store-sqlite/src/error.rs index fa7764462..f7ee6ee04 100644 --- a/presage-store-sqlite/src/error.rs +++ b/presage-store-sqlite/src/error.rs @@ -1,11 +1,40 @@ -use presage::store::StoreError; +use presage::{ + libsignal_service::{prelude::phonenumber, protocol::SignalProtocolError}, + store::StoreError, +}; +use tracing::error; #[derive(Debug, thiserror::Error)] pub enum SqliteStoreError { - #[error("database migration is not supported")] - MigrationConflict, - #[error("data store error: {0}")] + #[error(transparent)] Db(#[from] sqlx::Error), + #[error(transparent)] + Postcard(#[from] postcard::Error), + #[error(transparent)] + Json(#[from] serde_json::Error), + #[error(transparent)] + Uuid(#[from] uuid::Error), + #[error(transparent)] + PhoneNumber(#[from] phonenumber::ParseError), + #[error("conversation error")] + InvalidFormat, } impl StoreError for SqliteStoreError {} + +impl From for presage::libsignal_service::protocol::SignalProtocolError { + fn from(error: SqliteStoreError) -> Self { + error!(%error, "presage sqlite store error"); + Self::InvalidState("presage sqlite store error", error.to_string()) + } +} + +pub(crate) trait SqlxErrorExt { + fn into_protocol_error(self) -> Result; +} + +impl SqlxErrorExt for Result { + fn into_protocol_error(self) -> Result { + self.map_err(|error| SignalProtocolError::InvalidState("sqlite", error.to_string())) + } +} diff --git a/presage-store-sqlite/src/lib.rs b/presage-store-sqlite/src/lib.rs index 90e58977b..3e006e390 100644 --- a/presage-store-sqlite/src/lib.rs +++ b/presage-store-sqlite/src/lib.rs @@ -1,15 +1,12 @@ -#![allow(warnings)] - -use std::path::Path; - use presage::{ model::identity::OnNewIdentity, store::{StateStore, Store}, }; -use protocol::SqliteProtocolStore; -use sqlx::{sqlite::SqliteConnectOptions, SqlitePool}; +use protocol::{IdentityType, SqliteProtocolStore}; +use sqlx::{query, query_scalar, sqlite::SqliteConnectOptions, SqlitePool}; mod content; +mod data; mod error; mod protocol; @@ -17,23 +14,17 @@ pub use error::SqliteStoreError; #[derive(Debug, Clone)] pub struct SqliteStore { - db: SqlitePool, - /// Whether to trust new identities automatically (for instance, when a somebody's phone has changed) - trust_new_identities: OnNewIdentity, + pub(crate) db: SqlitePool, } impl SqliteStore { pub async fn open( - db_path: impl AsRef, - trust_new_identities: OnNewIdentity, + url: &str, + _trust_new_identities: OnNewIdentity, ) -> Result { - let connect_options = SqliteConnectOptions::new().filename(db_path); - let pool = SqlitePool::connect_with(connect_options).await?; - - Ok(Self { - db: pool, - trust_new_identities, - }) + let options: SqliteConnectOptions = url.parse()?; + let pool = SqlitePool::connect_with(options).await?; + Ok(Self { db: pool }) } } @@ -45,18 +36,21 @@ impl Store for SqliteStore { type PniStore = SqliteProtocolStore; async fn clear(&mut self) -> Result<(), SqliteStoreError> { - todo!() + query!("DELETE FROM kv").execute(&self.db).await?; + Ok(()) } fn aci_protocol_store(&self) -> Self::AciStore { SqliteProtocolStore { store: self.clone(), + identity: IdentityType::Aci, } } fn pni_protocol_store(&self) -> Self::PniStore { SqliteProtocolStore { store: self.clone(), + identity: IdentityType::Pni, } } } @@ -67,35 +61,68 @@ impl StateStore for SqliteStore { async fn load_registration_data( &self, ) -> Result, Self::StateStoreError> { - todo!() - } - - async fn set_aci_identity_key_pair( - &self, - key_pair: presage::libsignal_service::protocol::IdentityKeyPair, - ) -> Result<(), Self::StateStoreError> { - todo!() - } - - async fn set_pni_identity_key_pair( - &self, - key_pair: presage::libsignal_service::protocol::IdentityKeyPair, - ) -> Result<(), Self::StateStoreError> { - todo!() + query_scalar!("SELECT value FROM kv WHERE key = 'registration'") + .fetch_optional(&self.db) + .await? + .map(|value| serde_json::from_slice(&value)) + .transpose() + .map_err(From::from) } async fn save_registration_data( &mut self, state: &presage::manager::RegistrationData, ) -> Result<(), Self::StateStoreError> { - todo!() + let value = serde_json::to_string(state)?; + query!( + "INSERT OR REPLACE INTO kv (key, value) VALUES ('registration', ?)", + value + ) + .execute(&self.db) + .await?; + Ok(()) } async fn is_registered(&self) -> bool { - todo!() + self.load_registration_data().await.ok().flatten().is_some() } async fn clear_registration(&mut self) -> Result<(), Self::StateStoreError> { - todo!() + query!("DELETE FROM kv WHERE key = 'registration'") + .execute(&self.db) + .await?; + Ok(()) + } + + async fn set_aci_identity_key_pair( + &self, + key_pair: presage::libsignal_service::protocol::IdentityKeyPair, + ) -> Result<(), Self::StateStoreError> { + let key = IdentityType::Aci.identity_key_pair_key(); + let value = key_pair.serialize(); + query!( + "INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)", + key, + value + ) + .execute(&self.db) + .await?; + Ok(()) + } + + async fn set_pni_identity_key_pair( + &self, + key_pair: presage::libsignal_service::protocol::IdentityKeyPair, + ) -> Result<(), Self::StateStoreError> { + let key = IdentityType::Pni.identity_key_pair_key(); + let value = key_pair.serialize(); + query!( + "INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)", + key, + value + ) + .execute(&self.db) + .await?; + Ok(()) } } diff --git a/presage-store-sqlite/src/protocol.rs b/presage-store-sqlite/src/protocol.rs index 866da1c25..a607eb4e1 100644 --- a/presage-store-sqlite/src/protocol.rs +++ b/presage-store-sqlite/src/protocol.rs @@ -1,22 +1,44 @@ use async_trait::async_trait; use chrono::{DateTime, Utc}; -use presage::libsignal_service::{ - pre_keys::{KyberPreKeyStoreExt, PreKeysStore}, - prelude::{IdentityKeyStore, SessionStoreExt, Uuid}, - protocol::{ - Direction, IdentityKey, IdentityKeyPair, KyberPreKeyId, KyberPreKeyRecord, - KyberPreKeyStore, PreKeyId, PreKeyRecord, PreKeyStore, ProtocolAddress, ProtocolStore, - SenderKeyRecord, SenderKeyStore, ServiceId, SessionRecord, SessionStore, - SignalProtocolError as ProtocolError, SignedPreKeyId, SignedPreKeyRecord, - SignedPreKeyStore, +use presage::{ + libsignal_service::{ + pre_keys::{KyberPreKeyStoreExt, PreKeysStore}, + prelude::{IdentityKeyStore, SessionStoreExt, Uuid}, + protocol::{ + Direction, GenericSignedPreKey, IdentityKey, IdentityKeyPair, KyberPreKeyId, + KyberPreKeyRecord, KyberPreKeyStore, PreKeyId, PreKeyRecord, PreKeyStore, + ProtocolAddress, ProtocolStore, SenderKeyRecord, SenderKeyStore, ServiceId, + SessionRecord, SessionStore, SignalProtocolError, SignedPreKeyId, SignedPreKeyRecord, + SignedPreKeyStore, + }, + push_service::DEFAULT_DEVICE_ID, }, + store::StateStore, }; +use sqlx::{query, query_scalar}; -use crate::SqliteStore; +use crate::{error::SqlxErrorExt, SqliteStore, SqliteStoreError}; #[derive(Clone)] pub struct SqliteProtocolStore { pub(crate) store: SqliteStore, + pub(crate) identity: IdentityType, +} + +#[derive(Debug, Clone, Copy, sqlx::Type)] +#[sqlx(rename_all = "lowercase")] +pub(crate) enum IdentityType { + Aci, + Pni, +} + +impl IdentityType { + pub(crate) fn identity_key_pair_key(&self) -> &'static str { + match self { + Self::Aci => "identity_keypair_aci", + Self::Pni => "identity_keypair_pni", + } + } } impl ProtocolStore for SqliteProtocolStore {} @@ -27,8 +49,20 @@ impl SessionStore for SqliteProtocolStore { async fn load_session( &self, address: &ProtocolAddress, - ) -> Result, ProtocolError> { - todo!() + ) -> Result, SignalProtocolError> { + let device_id: u32 = address.device_id().into(); + let address = address.name(); + query!( + "SELECT record FROM sessions WHERE address = ? AND device_id = ? AND identity = ?", + address, + device_id, + self.identity, + ) + .fetch_optional(&self.store.db) + .await + .into_protocol_error()? + .map(|record| SessionRecord::deserialize(&record.record)) + .transpose() } /// Set the entry for `address` to the value of `record`. @@ -36,8 +70,22 @@ impl SessionStore for SqliteProtocolStore { &mut self, address: &ProtocolAddress, record: &SessionRecord, - ) -> Result<(), ProtocolError> { - todo!(); + ) -> Result<(), SignalProtocolError> { + let device_id: u32 = address.device_id().into(); + let address = address.name(); + let record = record.serialize()?; + query!( + "INSERT OR REPLACE INTO sessions (address, device_id, identity, record) + VALUES (?, ?, ?, ?)", + address, + device_id, + self.identity, + record, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } } @@ -46,29 +94,71 @@ impl SessionStoreExt for SqliteProtocolStore { /// Get the IDs of all known sub devices with active sessions for a recipient. /// /// This should return every device except for the main device [DEFAULT_DEVICE_ID]. - async fn get_sub_device_sessions(&self, name: &ServiceId) -> Result, ProtocolError> { - todo!() + async fn get_sub_device_sessions( + &self, + name: &ServiceId, + ) -> Result, SignalProtocolError> { + let address = name.raw_uuid().to_string(); + query_scalar!( + "SELECT device_id AS 'id: u32' FROM sessions + WHERE address = ? AND device_id != ? AND identity = ?", + address, + DEFAULT_DEVICE_ID, + self.identity, + ) + .fetch_all(&self.store.db) + .await + .into_protocol_error() } /// Remove a session record for a recipient ID + device ID tuple. - async fn delete_session(&self, address: &ProtocolAddress) -> Result<(), ProtocolError> { - todo!() + async fn delete_session(&self, address: &ProtocolAddress) -> Result<(), SignalProtocolError> { + let device_id: u32 = address.device_id().into(); + let address = address.name(); + query!( + "DELETE FROM sessions WHERE address = ? AND device_id = ? AND identity = ?", + address, + device_id, + self.identity, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } /// Remove the session records corresponding to all devices of a recipient /// ID. /// /// Returns the number of deleted sessions. - async fn delete_all_sessions(&self, address: &ServiceId) -> Result { - todo!() + async fn delete_all_sessions(&self, name: &ServiceId) -> Result { + let address = name.raw_uuid(); + let res = query!( + "DELETE FROM sessions WHERE address = ? AND identity = ?", + address, + self.identity + ) + .execute(&self.store.db) + .await + .map_err(SqliteStoreError::from)?; + Ok(res.rows_affected().try_into().expect("usize overflow")) } } #[async_trait(?Send)] impl PreKeyStore for SqliteProtocolStore { /// Look up the pre-key corresponding to `prekey_id`. - async fn get_pre_key(&self, prekey_id: PreKeyId) -> Result { - todo!() + async fn get_pre_key(&self, prekey_id: PreKeyId) -> Result { + let id: u32 = prekey_id.into(); + let record = query_scalar!( + "SELECT record FROM pre_keys WHERE id = ? AND identity = ?", + id, + self.identity + ) + .fetch_one(&self.store.db) + .await + .into_protocol_error()?; + PreKeyRecord::deserialize(&record) } /// Set the entry for `prekey_id` to the value of `record`. @@ -76,41 +166,96 @@ impl PreKeyStore for SqliteProtocolStore { &mut self, prekey_id: PreKeyId, record: &PreKeyRecord, - ) -> Result<(), ProtocolError> { - todo!() + ) -> Result<(), SignalProtocolError> { + let id: u32 = prekey_id.into(); + let record = record.serialize()?; + query!( + "INSERT OR REPLACE INTO pre_keys (id, identity, record) VALUES (?, ?, ?)", + id, + self.identity, + record, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } /// Remove the entry for `prekey_id`. - async fn remove_pre_key(&mut self, prekey_id: PreKeyId) -> Result<(), ProtocolError> { - todo!() + async fn remove_pre_key(&mut self, prekey_id: PreKeyId) -> Result<(), SignalProtocolError> { + let id: u32 = prekey_id.into(); + query!( + "DELETE FROM pre_keys WHERE id = ? AND identity = ?", + id, + self.identity + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } } #[async_trait(?Send)] impl PreKeysStore for SqliteProtocolStore { /// ID of the next pre key - async fn next_pre_key_id(&self) -> Result { - todo!() + async fn next_pre_key_id(&self) -> Result { + let max_id = query_scalar!( + "SELECT MAX(id) AS 'id: u32' FROM pre_keys WHERE identity = ?", + self.identity, + ) + .fetch_one(&self.store.db) + .await + .into_protocol_error()?; + Ok(max_id.map(|id| id + 1).unwrap_or(1)) } /// ID of the next signed pre key - async fn next_signed_pre_key_id(&self) -> Result { - todo!() + async fn next_signed_pre_key_id(&self) -> Result { + let max_id = query_scalar!( + "SELECT MAX(id) AS 'id: u32' FROM signed_pre_keys WHERE identity = ?", + self.identity + ) + .fetch_one(&self.store.db) + .await + .into_protocol_error()?; + Ok(max_id.map(|id| id + 1).unwrap_or(1)) } /// ID of the next PQ pre key - async fn next_pq_pre_key_id(&self) -> Result { - todo!() + async fn next_pq_pre_key_id(&self) -> Result { + let max_id = query_scalar!( + "SELECT MAX(id) AS 'id: u32' FROM kyber_pre_keys WHERE identity = ?", + self.identity + ) + .fetch_one(&self.store.db) + .await + .into_protocol_error()?; + Ok(max_id.map(|id| id + 1).unwrap_or(1)) } /// number of signed pre-keys we currently have in store - async fn signed_pre_keys_count(&self) -> Result { - todo!() + async fn signed_pre_keys_count(&self) -> Result { + query_scalar!( + "SELECT COUNT(id) FROM signed_pre_keys WHERE identity = ?", + self.identity + ) + .fetch_one(&self.store.db) + .await + .into_protocol_error() + .map(|count| count.try_into().expect("invalid usize")) } /// number of kyber pre-keys we currently have in store - async fn kyber_pre_keys_count(&self, last_resort: bool) -> Result { - todo!() + async fn kyber_pre_keys_count(&self, _last_resort: bool) -> Result { + query_scalar!( + "SELECT COUNT(id) FROM kyber_pre_keys WHERE identity = ?", + self.identity + ) + .fetch_one(&self.store.db) + .await + .into_protocol_error() + .map(|count| count.try_into().expect("invalid usize")) } } @@ -120,8 +265,17 @@ impl SignedPreKeyStore for SqliteProtocolStore { async fn get_signed_pre_key( &self, signed_prekey_id: SignedPreKeyId, - ) -> Result { - todo!() + ) -> Result { + let id: u32 = signed_prekey_id.into(); + let bytes = query_scalar!( + "SELECT record FROM signed_pre_keys WHERE id = ? AND identity = ?", + id, + self.identity, + ) + .fetch_one(&self.store.db) + .await + .map_err(SqliteStoreError::from)?; + SignedPreKeyRecord::deserialize(&bytes) } /// Set the entry for `signed_prekey_id` to the value of `record`. @@ -129,8 +283,19 @@ impl SignedPreKeyStore for SqliteProtocolStore { &mut self, signed_prekey_id: SignedPreKeyId, record: &SignedPreKeyRecord, - ) -> Result<(), ProtocolError> { - todo!() + ) -> Result<(), SignalProtocolError> { + let id: u32 = signed_prekey_id.into(); + let bytes = record.serialize()?; + query!( + "INSERT OR REPLACE INTO signed_pre_keys (id, identity, record) VALUES (?, ?, ?)", + id, + self.identity, + bytes, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } } @@ -140,8 +305,17 @@ impl KyberPreKeyStore for SqliteProtocolStore { async fn get_kyber_pre_key( &self, kyber_prekey_id: KyberPreKeyId, - ) -> Result { - todo!() + ) -> Result { + let id: u32 = kyber_prekey_id.into(); + let bytes = query_scalar!( + "SELECT record FROM kyber_pre_keys WHERE id = ? AND identity = ?", + id, + self.identity, + ) + .fetch_one(&self.store.db) + .await + .into_protocol_error()?; + KyberPreKeyRecord::deserialize(&bytes) } /// Set the entry for `kyber_prekey_id` to the value of `record`. @@ -149,8 +323,19 @@ impl KyberPreKeyStore for SqliteProtocolStore { &mut self, kyber_prekey_id: KyberPreKeyId, record: &KyberPreKeyRecord, - ) -> Result<(), ProtocolError> { - todo!() + ) -> Result<(), SignalProtocolError> { + let id: u32 = kyber_prekey_id.into(); + let record = record.serialize()?; + query!( + "INSERT OR REPLACE INTO kyber_pre_keys (id, identity, record) VALUES (?, ?, ?)", + id, + self.identity, + record, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } /// Mark the entry for `kyber_prekey_id` as "used". @@ -158,8 +343,17 @@ impl KyberPreKeyStore for SqliteProtocolStore { async fn mark_kyber_pre_key_used( &mut self, kyber_prekey_id: KyberPreKeyId, - ) -> Result<(), ProtocolError> { - todo!() + ) -> Result<(), SignalProtocolError> { + let id: u32 = kyber_prekey_id.into(); + query!( + "DELETE FROM kyber_pre_keys WHERE id = ? AND identity = ?", + id, + self.identity, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } } @@ -169,46 +363,82 @@ impl KyberPreKeyStoreExt for SqliteProtocolStore { &mut self, kyber_prekey_id: KyberPreKeyId, record: &KyberPreKeyRecord, - ) -> Result<(), ProtocolError> { - todo!() + ) -> Result<(), SignalProtocolError> { + let id: u32 = kyber_prekey_id.into(); + let record = record.serialize()?; + query!( + "INSERT OR REPLACE INTO kyber_pre_keys + (id, identity, is_last_resort, record) VALUES (?, ?, TRUE, ?)", + id, + self.identity, + record, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } async fn load_last_resort_kyber_pre_keys( &self, - ) -> Result, ProtocolError> { - todo!() + ) -> Result, SignalProtocolError> { + query_scalar!( + "SELECT record FROM kyber_pre_keys + WHERE identity = ? AND is_last_resort = TRUE", + self.identity, + ) + .fetch_all(&self.store.db) + .await + .into_protocol_error()? + .into_iter() + .map(|record| KyberPreKeyRecord::deserialize(&record)) + .collect() } async fn remove_kyber_pre_key( &mut self, kyber_prekey_id: KyberPreKeyId, - ) -> Result<(), ProtocolError> { - todo!() + ) -> Result<(), SignalProtocolError> { + let id: u32 = kyber_prekey_id.into(); + query!( + "DELETE FROM kyber_pre_keys WHERE id = ? AND identity = ?", + id, + self.identity, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } /// Analogous to markAllOneTimeKyberPreKeysStaleIfNecessary async fn mark_all_one_time_kyber_pre_keys_stale_if_necessary( &mut self, - stale_time: DateTime, - ) -> Result<(), ProtocolError> { - todo!() + _stale_time: DateTime, + ) -> Result<(), SignalProtocolError> { + unimplemented!("should not be used yet") } /// Analogue of deleteAllStaleOneTimeKyberPreKeys async fn delete_all_stale_one_time_kyber_pre_keys( &mut self, - threshold: DateTime, - min_count: usize, - ) -> Result<(), ProtocolError> { - todo!() + _threshold: DateTime, + _min_count: usize, + ) -> Result<(), SignalProtocolError> { + unimplemented!("should not be used yet") } } #[async_trait(?Send)] impl IdentityKeyStore for SqliteProtocolStore { /// Return the single specific identity the store is assumed to represent, with private key. - async fn get_identity_key_pair(&self) -> Result { - todo!() + async fn get_identity_key_pair(&self) -> Result { + let key = self.identity.identity_key_pair_key(); + let bytes = query_scalar!("SELECT value FROM kv WHERE key = ?", key) + .fetch_one(&self.store.db) + .await + .into_protocol_error()?; + IdentityKeyPair::try_from(&*bytes) } /// Return a [u32] specific to this store instance. @@ -219,11 +449,16 @@ impl IdentityKeyStore for SqliteProtocolStore { /// If the same *device* is unregistered, then registers again, the [ProtocolAddress::device_id] /// may be the same, but the store registration id returned by this method should /// be regenerated. - async fn get_local_registration_id(&self) -> Result { - todo!() + async fn get_local_registration_id(&self) -> Result { + let data = self.store.load_registration_data().await?.ok_or_else(|| { + SignalProtocolError::InvalidState( + "failed to load registration ID", + "no registration data".into(), + ) + })?; + Ok(data.registration_id) } - // TODO: make this into an enum instead of a bool! /// Record an identity into the store. The identity is then considered "trusted". /// /// The return value represents whether an existing identity was replaced (`Ok(true)`). If it is @@ -232,8 +467,26 @@ impl IdentityKeyStore for SqliteProtocolStore { &mut self, address: &ProtocolAddress, identity: &IdentityKey, - ) -> Result { - todo!() + ) -> Result { + let previous = self.get_identity(address).await?; + let is_replaced = previous.as_ref() == Some(identity); + + let device_id: u32 = address.device_id().into(); + let address = address.name(); + let bytes = identity.serialize(); + query!( + "INSERT OR REPLACE INTO identities (address, device_id, identity, record) + VALUES (?, ?, ?, ?)", + address, + device_id, + self.identity, + bytes, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + + Ok(is_replaced) } /// Return whether an identity is trusted for the role specified by `direction`. @@ -241,17 +494,33 @@ impl IdentityKeyStore for SqliteProtocolStore { &self, address: &ProtocolAddress, identity: &IdentityKey, - direction: Direction, - ) -> Result { - todo!() + _direction: Direction, + ) -> Result { + if let Some(trusted_key) = self.get_identity(address).await? { + Ok(trusted_key == *identity) + } else { + Ok(false) + } } /// Return the public identity for the given `address`, if known. async fn get_identity( &self, address: &ProtocolAddress, - ) -> Result, ProtocolError> { - todo!() + ) -> Result, SignalProtocolError> { + let device_id: u32 = address.device_id().into(); + let address = address.name(); + query_scalar!( + "SELECT record FROM identities WHERE address = ? AND device_id = ? AND identity = ?", + address, + device_id, + self.identity, + ) + .fetch_optional(&self.store.db) + .await + .into_protocol_error()? + .map(|bytes| IdentityKey::decode(&bytes)) + .transpose() } } @@ -262,10 +531,25 @@ impl SenderKeyStore for SqliteProtocolStore { &mut self, sender: &ProtocolAddress, distribution_id: Uuid, - // TODO: pass this by value! record: &SenderKeyRecord, - ) -> Result<(), ProtocolError> { - todo!() + ) -> Result<(), SignalProtocolError> { + let address = sender.name(); + let device_id: u32 = sender.device_id().into(); + let record = record.serialize()?; + query!( + "INSERT OR REPLACE INTO sender_keys + (address, device_id, identity, distribution_id, record) + VALUES (?, ?, ?, ?, ?)", + address, + device_id, + self.identity, + distribution_id, + record, + ) + .execute(&self.store.db) + .await + .into_protocol_error()?; + Ok(()) } /// Look up the entry corresponding to `(sender, distribution_id)`. @@ -273,7 +557,21 @@ impl SenderKeyStore for SqliteProtocolStore { &mut self, sender: &ProtocolAddress, distribution_id: Uuid, - ) -> Result, ProtocolError> { - todo!() + ) -> Result, SignalProtocolError> { + let address = sender.name(); + let device_id: u32 = sender.device_id().into(); + query_scalar!( + "SELECT record FROM sender_keys + WHERE address = ? AND device_id = ? AND identity = ? AND distribution_id = ?", + address, + device_id, + self.identity, + distribution_id, + ) + .fetch_optional(&self.store.db) + .await + .into_protocol_error()? + .map(|record| SenderKeyRecord::deserialize(&record)) + .transpose() } } diff --git a/presage-store-sqlite/test.sqlite b/presage-store-sqlite/test.sqlite new file mode 100644 index 000000000..cafaf6d27 Binary files /dev/null and b/presage-store-sqlite/test.sqlite differ diff --git a/presage/src/manager/registered.rs b/presage/src/manager/registered.rs index 1647db233..3c45dde42 100644 --- a/presage/src/manager/registered.rs +++ b/presage/src/manager/registered.rs @@ -1453,10 +1453,10 @@ async fn save_message( // - update the contact if the profile key has changed // TODO: mark this contact as "created by us" maybe to know whether we should update it or not if store.contact_by_id(&sender.raw_uuid()).await?.is_none() - || !store + || store .profile_key(&sender.raw_uuid()) .await? - .is_some_and(|p| p.bytes == profile_key.bytes) + .is_none_or(|p| p.bytes != profile_key.bytes) { if let Some(aci) = sender.aci() { let sender_uuid: Uuid = aci.into(); diff --git a/presage/src/store.rs b/presage/src/store.rs index 499b5899d..4471186bb 100644 --- a/presage/src/store.rs +++ b/presage/src/store.rs @@ -283,7 +283,7 @@ pub trait ContentsStore: Send + Sync { key: ProfileKey, ) -> impl Future, Self::ContentsStoreError>>; - /// Stickers + // Stickers /// Add a sticker pack fn add_sticker_pack(