diff --git a/.sqlx/query-0198d93680a7781f92e2740c73703404ac24cb09cf70c18ff3297a6524cb861d.json b/.sqlx/query-0198d93680a7781f92e2740c73703404ac24cb09cf70c18ff3297a6524cb861d.json index 83eb74c..56494aa 100644 --- a/.sqlx/query-0198d93680a7781f92e2740c73703404ac24cb09cf70c18ff3297a6524cb861d.json +++ b/.sqlx/query-0198d93680a7781f92e2740c73703404ac24cb09cf70c18ff3297a6524cb861d.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-0222c6c56a5836482fab6f4c43987a160f94cbb9968289c781ebebd6051de5f7.json b/.sqlx/query-0222c6c56a5836482fab6f4c43987a160f94cbb9968289c781ebebd6051de5f7.json new file mode 100644 index 0000000..cc327ba --- /dev/null +++ b/.sqlx/query-0222c6c56a5836482fab6f4c43987a160f94cbb9968289c781ebebd6051de5f7.json @@ -0,0 +1,19 @@ +{ + "db_name": "PostgreSQL", + "query": "\nINSERT INTO users (id, email, handle, credentials, created, activated)\nVALUES ( $1, $2, $3, $4, $5, $6 )\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text", + "Text", + "Bytea", + "Timestamptz", + "Bool" + ] + }, + "nullable": [] + }, + "hash": "0222c6c56a5836482fab6f4c43987a160f94cbb9968289c781ebebd6051de5f7" +} diff --git a/.sqlx/query-0dc7a87ffa2ec4c15a5bc653b9719a304127581d930d47d53b7cd8f333f5cf35.json b/.sqlx/query-0dc7a87ffa2ec4c15a5bc653b9719a304127581d930d47d53b7cd8f333f5cf35.json index c4c75d5..cdecbc4 100644 --- a/.sqlx/query-0dc7a87ffa2ec4c15a5bc653b9719a304127581d930d47d53b7cd8f333f5cf35.json +++ b/.sqlx/query-0dc7a87ffa2ec4c15a5bc653b9719a304127581d930d47d53b7cd8f333f5cf35.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-0e9b174f42ef6c82128c63e9ecb187637763ab43600d584b386f5f2abd800fe6.json b/.sqlx/query-0e9b174f42ef6c82128c63e9ecb187637763ab43600d584b386f5f2abd800fe6.json index a0a762e..3aed5bd 100644 --- a/.sqlx/query-0e9b174f42ef6c82128c63e9ecb187637763ab43600d584b386f5f2abd800fe6.json +++ b/.sqlx/query-0e9b174f42ef6c82128c63e9ecb187637763ab43600d584b386f5f2abd800fe6.json @@ -26,7 +26,7 @@ ], "parameters": { "Left": [ - "Int4" + "Uuid" ] }, "nullable": [ diff --git a/.sqlx/query-1572a0c4c40bf93abf33d904fb61d2a698526834e3a42d806fec6c877748ef38.json b/.sqlx/query-1572a0c4c40bf93abf33d904fb61d2a698526834e3a42d806fec6c877748ef38.json deleted file mode 100644 index f32568f..0000000 --- a/.sqlx/query-1572a0c4c40bf93abf33d904fb61d2a698526834e3a42d806fec6c877748ef38.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\nINSERT INTO users (email, handle, credentials, created, activated)\nVALUES ( $1, $2, $3, $4, $5 )\nON CONFLICT(email) DO UPDATE SET handle=excluded.handle, credentials=excluded.credentials, created=excluded.created, activated=excluded.activated \nRETURNING id\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - } - ], - "parameters": { - "Left": [ - "Text", - "Text", - "Bytea", - "Timestamptz", - "Bool" - ] - }, - "nullable": [ - false - ] - }, - "hash": "1572a0c4c40bf93abf33d904fb61d2a698526834e3a42d806fec6c877748ef38" -} diff --git a/.sqlx/query-1b65ca2a3c3ce2c521fe0b1a691b897113cf30f46542052e26fdcb5415a77b9b.json b/.sqlx/query-1b65ca2a3c3ce2c521fe0b1a691b897113cf30f46542052e26fdcb5415a77b9b.json deleted file mode 100644 index 5231ed5..0000000 --- a/.sqlx/query-1b65ca2a3c3ce2c521fe0b1a691b897113cf30f46542052e26fdcb5415a77b9b.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\nDELETE FROM users\nWHERE email = $1\nRETURNING id as \"id!\"\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id!", - "type_info": "Int4" - } - ], - "parameters": { - "Left": [ - "Text" - ] - }, - "nullable": [ - false - ] - }, - "hash": "1b65ca2a3c3ce2c521fe0b1a691b897113cf30f46542052e26fdcb5415a77b9b" -} diff --git a/.sqlx/query-1f3f7bd4f175a191a37461adf59b4566a5cb65c1a0d4c25f15d50302e2e57182.json b/.sqlx/query-1f3f7bd4f175a191a37461adf59b4566a5cb65c1a0d4c25f15d50302e2e57182.json index a4afe2a..581861d 100644 --- a/.sqlx/query-1f3f7bd4f175a191a37461adf59b4566a5cb65c1a0d4c25f15d50302e2e57182.json +++ b/.sqlx/query-1f3f7bd4f175a191a37461adf59b4566a5cb65c1a0d4c25f15d50302e2e57182.json @@ -36,7 +36,7 @@ { "ordinal": 6, "name": "user_id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 7, @@ -51,7 +51,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Bytea" ] }, diff --git a/.sqlx/query-1f75e7d0b5d65108ded2ed744899405bc5c9df9c760d2428698c6ffb9d0d59bd.json b/.sqlx/query-1f75e7d0b5d65108ded2ed744899405bc5c9df9c760d2428698c6ffb9d0d59bd.json deleted file mode 100644 index 268b351..0000000 --- a/.sqlx/query-1f75e7d0b5d65108ded2ed744899405bc5c9df9c760d2428698c6ffb9d0d59bd.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n WITH new_responder(user_id, id, name, path, method, enabled, settings, created_at) AS (\n VALUES ( $1::integer, $2::uuid, $3, $4, $5::bytea, $6::bool, $7::bytea, $8::timestamptz )\n )\n INSERT INTO user_data_webhooks_responders (user_id, id, name, path, method, enabled, settings, created_at)\n SELECT * FROM new_responder\n WHERE NOT EXISTS(\n SELECT id FROM user_data_webhooks_responders \n WHERE user_id = $1 AND path = $4 AND (method = $9 OR $5 = $9)\n )\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int4", - "Uuid", - "Text", - "Text", - "Bytea", - "Bool", - "Bytea", - "Timestamptz", - "Bytea" - ] - }, - "nullable": [] - }, - "hash": "1f75e7d0b5d65108ded2ed744899405bc5c9df9c760d2428698c6ffb9d0d59bd" -} diff --git a/.sqlx/query-25dd81897ddf37b727a99f4048aefda36257f0697b8de4c08b182c3486f1c8e5.json b/.sqlx/query-25dd81897ddf37b727a99f4048aefda36257f0697b8de4c08b182c3486f1c8e5.json index 6fba671..b46acf5 100644 --- a/.sqlx/query-25dd81897ddf37b727a99f4048aefda36257f0697b8de4c08b182c3486f1c8e5.json +++ b/.sqlx/query-25dd81897ddf37b727a99f4048aefda36257f0697b8de4c08b182c3486f1c8e5.json @@ -11,7 +11,7 @@ { "ordinal": 1, "name": "user_id!", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 2, diff --git a/.sqlx/query-2c0b85fd43a4c41034dc025ea26e6f63337cd20e9fdc2f99457de7f7214d5f0c.json b/.sqlx/query-2c0b85fd43a4c41034dc025ea26e6f63337cd20e9fdc2f99457de7f7214d5f0c.json index 267dde9..a24a7de 100644 --- a/.sqlx/query-2c0b85fd43a4c41034dc025ea26e6f63337cd20e9fdc2f99457de7f7214d5f0c.json +++ b/.sqlx/query-2c0b85fd43a4c41034dc025ea26e6f63337cd20e9fdc2f99457de7f7214d5f0c.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-3224d177c41738db1c75252a7183dc9f5bfd376dc90b696ac40e99798225417b.json b/.sqlx/query-3224d177c41738db1c75252a7183dc9f5bfd376dc90b696ac40e99798225417b.json index 7220d99..895ca53 100644 --- a/.sqlx/query-3224d177c41738db1c75252a7183dc9f5bfd376dc90b696ac40e99798225417b.json +++ b/.sqlx/query-3224d177c41738db1c75252a7183dc9f5bfd376dc90b696ac40e99798225417b.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-332b530d376ec5f092d2a12ec371bf9f49547575bae1e7f11fc6ce5d39308523.json b/.sqlx/query-332b530d376ec5f092d2a12ec371bf9f49547575bae1e7f11fc6ce5d39308523.json index c53e81c..ee9546f 100644 --- a/.sqlx/query-332b530d376ec5f092d2a12ec371bf9f49547575bae1e7f11fc6ce5d39308523.json +++ b/.sqlx/query-332b530d376ec5f092d2a12ec371bf9f49547575bae1e7f11fc6ce5d39308523.json @@ -26,7 +26,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-37716056ba8b0f23f73c102fe3a3af805fd53be5f1506e4e35aba8831581602e.json b/.sqlx/query-37716056ba8b0f23f73c102fe3a3af805fd53be5f1506e4e35aba8831581602e.json index 2f33612..3ee88d6 100644 --- a/.sqlx/query-37716056ba8b0f23f73c102fe3a3af805fd53be5f1506e4e35aba8831581602e.json +++ b/.sqlx/query-37716056ba8b0f23f73c102fe3a3af805fd53be5f1506e4e35aba8831581602e.json @@ -6,7 +6,7 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 1, diff --git a/.sqlx/query-3c32dca20bcb04db7df63c1e2d5054e8712dc6e37f70913c4e2ed4f029ca33bc.json b/.sqlx/query-3c32dca20bcb04db7df63c1e2d5054e8712dc6e37f70913c4e2ed4f029ca33bc.json index f47a8a4..bf880ce 100644 --- a/.sqlx/query-3c32dca20bcb04db7df63c1e2d5054e8712dc6e37f70913c4e2ed4f029ca33bc.json +++ b/.sqlx/query-3c32dca20bcb04db7df63c1e2d5054e8712dc6e37f70913c4e2ed4f029ca33bc.json @@ -41,7 +41,7 @@ ], "parameters": { "Left": [ - "Int4" + "Uuid" ] }, "nullable": [ diff --git a/.sqlx/query-4f33d79bf3c4684dd292b491f1ec550261df7ebbd2bf2d6f904a1f9749fd5a80.json b/.sqlx/query-4f33d79bf3c4684dd292b491f1ec550261df7ebbd2bf2d6f904a1f9749fd5a80.json index 0034b45..6225911 100644 --- a/.sqlx/query-4f33d79bf3c4684dd292b491f1ec550261df7ebbd2bf2d6f904a1f9749fd5a80.json +++ b/.sqlx/query-4f33d79bf3c4684dd292b491f1ec550261df7ebbd2bf2d6f904a1f9749fd5a80.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-4f999882ee1b85e4161fd2f9efc2c5b68995a48a9f12730796c62488a83ae1cf.json b/.sqlx/query-4f999882ee1b85e4161fd2f9efc2c5b68995a48a9f12730796c62488a83ae1cf.json index 046bea1..93ad4f6 100644 --- a/.sqlx/query-4f999882ee1b85e4161fd2f9efc2c5b68995a48a9f12730796c62488a83ae1cf.json +++ b/.sqlx/query-4f999882ee1b85e4161fd2f9efc2c5b68995a48a9f12730796c62488a83ae1cf.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Text", "Bytea", diff --git a/.sqlx/query-50887f5150f3642bad8fe216d57ffd86e284acb8718f1182b641f92fe877198d.json b/.sqlx/query-50887f5150f3642bad8fe216d57ffd86e284acb8718f1182b641f92fe877198d.json index 2f17ef3..cf0163f 100644 --- a/.sqlx/query-50887f5150f3642bad8fe216d57ffd86e284acb8718f1182b641f92fe877198d.json +++ b/.sqlx/query-50887f5150f3642bad8fe216d57ffd86e284acb8718f1182b641f92fe877198d.json @@ -6,7 +6,7 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 1, @@ -61,7 +61,7 @@ ], "parameters": { "Left": [ - "Int4" + "Uuid" ] }, "nullable": [ diff --git a/.sqlx/query-5cdc473db00d5ba939fe535796115324b7decfe4f6c9b04e9260f3898f055a55.json b/.sqlx/query-5cdc473db00d5ba939fe535796115324b7decfe4f6c9b04e9260f3898f055a55.json deleted file mode 100644 index 231ab27..0000000 --- a/.sqlx/query-5cdc473db00d5ba939fe535796115324b7decfe4f6c9b04e9260f3898f055a55.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\nINSERT INTO users (email, handle, credentials, created, activated)\nVALUES ( $1, $2, $3, $4, $5 )\nRETURNING id\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - } - ], - "parameters": { - "Left": [ - "Text", - "Text", - "Bytea", - "Timestamptz", - "Bool" - ] - }, - "nullable": [ - false - ] - }, - "hash": "5cdc473db00d5ba939fe535796115324b7decfe4f6c9b04e9260f3898f055a55" -} diff --git a/.sqlx/query-60ab5ef16ade62399689ecdde43329c1787a6fe87161f619b7e9aa5fecd9389d.json b/.sqlx/query-60ab5ef16ade62399689ecdde43329c1787a6fe87161f619b7e9aa5fecd9389d.json index 0f6de95..85da1b3 100644 --- a/.sqlx/query-60ab5ef16ade62399689ecdde43329c1787a6fe87161f619b7e9aa5fecd9389d.json +++ b/.sqlx/query-60ab5ef16ade62399689ecdde43329c1787a6fe87161f619b7e9aa5fecd9389d.json @@ -36,7 +36,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-61af34e2743df1ddf5b814b33b5166c11c5a7c4ecd110bed691566504077ad9c.json b/.sqlx/query-61af34e2743df1ddf5b814b33b5166c11c5a7c4ecd110bed691566504077ad9c.json index 575590e..e0e05f6 100644 --- a/.sqlx/query-61af34e2743df1ddf5b814b33b5166c11c5a7c4ecd110bed691566504077ad9c.json +++ b/.sqlx/query-61af34e2743df1ddf5b814b33b5166c11c5a7c4ecd110bed691566504077ad9c.json @@ -6,7 +6,7 @@ { "ordinal": 0, "name": "id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 1, diff --git a/.sqlx/query-62df38f9d0e21fe51221f6d046042e9c80a2095dbd8072ffafc45b2c0b81f22b.json b/.sqlx/query-62df38f9d0e21fe51221f6d046042e9c80a2095dbd8072ffafc45b2c0b81f22b.json index f1c250c..3ad1a3d 100644 --- a/.sqlx/query-62df38f9d0e21fe51221f6d046042e9c80a2095dbd8072ffafc45b2c0b81f22b.json +++ b/.sqlx/query-62df38f9d0e21fe51221f6d046042e9c80a2095dbd8072ffafc45b2c0b81f22b.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Bytea", "Text", diff --git a/.sqlx/query-64855757e1c707b29863ec1f63865ff6217d0abb729fe0fcd2d7e84bc87c89e4.json b/.sqlx/query-64855757e1c707b29863ec1f63865ff6217d0abb729fe0fcd2d7e84bc87c89e4.json index 704f62d..9979df4 100644 --- a/.sqlx/query-64855757e1c707b29863ec1f63865ff6217d0abb729fe0fcd2d7e84bc87c89e4.json +++ b/.sqlx/query-64855757e1c707b29863ec1f63865ff6217d0abb729fe0fcd2d7e84bc87c89e4.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Text", "Bytea" diff --git a/.sqlx/query-68d09a3d5c91bbbb31be733bd52e105dfd3ba903fca0260a4d47546e143f201a.json b/.sqlx/query-68d09a3d5c91bbbb31be733bd52e105dfd3ba903fca0260a4d47546e143f201a.json index 8e5ea04..cf8a958 100644 --- a/.sqlx/query-68d09a3d5c91bbbb31be733bd52e105dfd3ba903fca0260a4d47546e143f201a.json +++ b/.sqlx/query-68d09a3d5c91bbbb31be733bd52e105dfd3ba903fca0260a4d47546e143f201a.json @@ -36,7 +36,7 @@ { "ordinal": 6, "name": "user_id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 7, diff --git a/.sqlx/query-6a28bed0a5fe290dc5131cc2011ecf8619d517d83d7b36d961d41e82d018d119.json b/.sqlx/query-6a28bed0a5fe290dc5131cc2011ecf8619d517d83d7b36d961d41e82d018d119.json index 7404905..eba8207 100644 --- a/.sqlx/query-6a28bed0a5fe290dc5131cc2011ecf8619d517d83d7b36d961d41e82d018d119.json +++ b/.sqlx/query-6a28bed0a5fe290dc5131cc2011ecf8619d517d83d7b36d961d41e82d018d119.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Text", "Bytea", diff --git a/.sqlx/query-7160231168e9996b47c86ee837300a5dba4b42595ebc97cdaa028ad11055432d.json b/.sqlx/query-7160231168e9996b47c86ee837300a5dba4b42595ebc97cdaa028ad11055432d.json index 5449942..9222cd6 100644 --- a/.sqlx/query-7160231168e9996b47c86ee837300a5dba4b42595ebc97cdaa028ad11055432d.json +++ b/.sqlx/query-7160231168e9996b47c86ee837300a5dba4b42595ebc97cdaa028ad11055432d.json @@ -26,7 +26,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Bytea" ] diff --git a/.sqlx/query-72a47d4706231a10c24c4e00ca7a2b2ed6270d72af7724f66eacad9d8f0f7722.json b/.sqlx/query-72a47d4706231a10c24c4e00ca7a2b2ed6270d72af7724f66eacad9d8f0f7722.json index b1b8b59..a67aebe 100644 --- a/.sqlx/query-72a47d4706231a10c24c4e00ca7a2b2ed6270d72af7724f66eacad9d8f0f7722.json +++ b/.sqlx/query-72a47d4706231a10c24c4e00ca7a2b2ed6270d72af7724f66eacad9d8f0f7722.json @@ -26,7 +26,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-74e30f0636e89b467a434a8849765c9e1cb1037271593604ce7160cc2d41ec6a.json b/.sqlx/query-74e30f0636e89b467a434a8849765c9e1cb1037271593604ce7160cc2d41ec6a.json index 584e3bc..aa8d7ec 100644 --- a/.sqlx/query-74e30f0636e89b467a434a8849765c9e1cb1037271593604ce7160cc2d41ec6a.json +++ b/.sqlx/query-74e30f0636e89b467a434a8849765c9e1cb1037271593604ce7160cc2d41ec6a.json @@ -41,7 +41,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-86fd81510ee0f17c17c0953000b3cae307952a105667cd43c9b391c6bdb090ac.json b/.sqlx/query-86fd81510ee0f17c17c0953000b3cae307952a105667cd43c9b391c6bdb090ac.json new file mode 100644 index 0000000..5f68f01 --- /dev/null +++ b/.sqlx/query-86fd81510ee0f17c17c0953000b3cae307952a105667cd43c9b391c6bdb090ac.json @@ -0,0 +1,19 @@ +{ + "db_name": "PostgreSQL", + "query": "\nINSERT INTO users (id, email, handle, credentials, created, activated)\nVALUES ( $1, $2, $3, $4, $5, $6 )\nON CONFLICT(id) DO UPDATE SET email=excluded.email, handle=excluded.handle, credentials=excluded.credentials, created=excluded.created, activated=excluded.activated\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text", + "Text", + "Bytea", + "Timestamptz", + "Bool" + ] + }, + "nullable": [] + }, + "hash": "86fd81510ee0f17c17c0953000b3cae307952a105667cd43c9b391c6bdb090ac" +} diff --git a/.sqlx/query-9347d958c7d809bf925cc591b552167823cb45ee16412895ce0148080c210c00.json b/.sqlx/query-9347d958c7d809bf925cc591b552167823cb45ee16412895ce0148080c210c00.json index d788ea4..69cdd93 100644 --- a/.sqlx/query-9347d958c7d809bf925cc591b552167823cb45ee16412895ce0148080c210c00.json +++ b/.sqlx/query-9347d958c7d809bf925cc591b552167823cb45ee16412895ce0148080c210c00.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Uuid", "Bytea", diff --git a/.sqlx/query-9349bd205fb7e6a1f84958ade34112ee576e1854545289766871e46180f99570.json b/.sqlx/query-9349bd205fb7e6a1f84958ade34112ee576e1854545289766871e46180f99570.json index 96687cd..5c29ef2 100644 --- a/.sqlx/query-9349bd205fb7e6a1f84958ade34112ee576e1854545289766871e46180f99570.json +++ b/.sqlx/query-9349bd205fb7e6a1f84958ade34112ee576e1854545289766871e46180f99570.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Uuid" ] diff --git a/.sqlx/query-971ae6575e816fe9e574643a7346885bf73cb196cdb14adb947b59e0e5fcd3b7.json b/.sqlx/query-971ae6575e816fe9e574643a7346885bf73cb196cdb14adb947b59e0e5fcd3b7.json index 46e4b08..38c8a82 100644 --- a/.sqlx/query-971ae6575e816fe9e574643a7346885bf73cb196cdb14adb947b59e0e5fcd3b7.json +++ b/.sqlx/query-971ae6575e816fe9e574643a7346885bf73cb196cdb14adb947b59e0e5fcd3b7.json @@ -26,7 +26,7 @@ { "ordinal": 4, "name": "user_id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 5, diff --git a/.sqlx/query-98523a4ee01682cdc05ddeb9a624b4a3c14ff1b80e59f6ae9e759af2de97fd6c.json b/.sqlx/query-98523a4ee01682cdc05ddeb9a624b4a3c14ff1b80e59f6ae9e759af2de97fd6c.json index 559a98a..9d4a8fa 100644 --- a/.sqlx/query-98523a4ee01682cdc05ddeb9a624b4a3c14ff1b80e59f6ae9e759af2de97fd6c.json +++ b/.sqlx/query-98523a4ee01682cdc05ddeb9a624b4a3c14ff1b80e59f6ae9e759af2de97fd6c.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-99e8a35a9d39a6edbd95f087040c54966fe86fbca547db96795343b120e2b591.json b/.sqlx/query-99e8a35a9d39a6edbd95f087040c54966fe86fbca547db96795343b120e2b591.json index 79f931f..163b842 100644 --- a/.sqlx/query-99e8a35a9d39a6edbd95f087040c54966fe86fbca547db96795343b120e2b591.json +++ b/.sqlx/query-99e8a35a9d39a6edbd95f087040c54966fe86fbca547db96795343b120e2b591.json @@ -26,7 +26,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-9d097672913ac29c032bcc48f7ba9c41fd7a4cb21410f3e2dcba9a3b5720e374.json b/.sqlx/query-9d097672913ac29c032bcc48f7ba9c41fd7a4cb21410f3e2dcba9a3b5720e374.json index 72eaebb..7c44490 100644 --- a/.sqlx/query-9d097672913ac29c032bcc48f7ba9c41fd7a4cb21410f3e2dcba9a3b5720e374.json +++ b/.sqlx/query-9d097672913ac29c032bcc48f7ba9c41fd7a4cb21410f3e2dcba9a3b5720e374.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Text", "Bytea", diff --git a/.sqlx/query-9d91a28d9ac9eedab7d75a0108ba1cd336196e61c330d7884a79d309d157fa4b.json b/.sqlx/query-9d91a28d9ac9eedab7d75a0108ba1cd336196e61c330d7884a79d309d157fa4b.json index ab6dd77..09fc6cf 100644 --- a/.sqlx/query-9d91a28d9ac9eedab7d75a0108ba1cd336196e61c330d7884a79d309d157fa4b.json +++ b/.sqlx/query-9d91a28d9ac9eedab7d75a0108ba1cd336196e61c330d7884a79d309d157fa4b.json @@ -36,7 +36,7 @@ ], "parameters": { "Left": [ - "Int4" + "Uuid" ] }, "nullable": [ diff --git a/.sqlx/query-a231b8dc4515d04e7e0021ecc27cf83e6263521afc7ae5a06faf7b5a5c876ce7.json b/.sqlx/query-a231b8dc4515d04e7e0021ecc27cf83e6263521afc7ae5a06faf7b5a5c876ce7.json index af064c7..973a599 100644 --- a/.sqlx/query-a231b8dc4515d04e7e0021ecc27cf83e6263521afc7ae5a06faf7b5a5c876ce7.json +++ b/.sqlx/query-a231b8dc4515d04e7e0021ecc27cf83e6263521afc7ae5a06faf7b5a5c876ce7.json @@ -11,7 +11,7 @@ { "ordinal": 1, "name": "user_id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 2, @@ -26,7 +26,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Bytea" ] }, diff --git a/.sqlx/query-a6ab5f4c7d873dbd2bfe99c8dd8f209a080604faffc70d654f3a1f1aef4daa6a.json b/.sqlx/query-a6ab5f4c7d873dbd2bfe99c8dd8f209a080604faffc70d654f3a1f1aef4daa6a.json index d843db4..a4f4298 100644 --- a/.sqlx/query-a6ab5f4c7d873dbd2bfe99c8dd8f209a080604faffc70d654f3a1f1aef4daa6a.json +++ b/.sqlx/query-a6ab5f4c7d873dbd2bfe99c8dd8f209a080604faffc70d654f3a1f1aef4daa6a.json @@ -26,7 +26,7 @@ { "ordinal": 4, "name": "user_id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 5, diff --git a/.sqlx/query-a807490d7d3eaad38f8ac404bdef695fc6d7d8e5babec9fec19e742fd3cb5aff.json b/.sqlx/query-a807490d7d3eaad38f8ac404bdef695fc6d7d8e5babec9fec19e742fd3cb5aff.json index dd682c3..817f8fe 100644 --- a/.sqlx/query-a807490d7d3eaad38f8ac404bdef695fc6d7d8e5babec9fec19e742fd3cb5aff.json +++ b/.sqlx/query-a807490d7d3eaad38f8ac404bdef695fc6d7d8e5babec9fec19e742fd3cb5aff.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid" ] }, diff --git a/.sqlx/query-a88d81a3637a342d885e39262da39ee50ce9695b3f520f4d61e063d8559c686e.json b/.sqlx/query-a88d81a3637a342d885e39262da39ee50ce9695b3f520f4d61e063d8559c686e.json index 51fd6d3..224803f 100644 --- a/.sqlx/query-a88d81a3637a342d885e39262da39ee50ce9695b3f520f4d61e063d8559c686e.json +++ b/.sqlx/query-a88d81a3637a342d885e39262da39ee50ce9695b3f520f4d61e063d8559c686e.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Uuid", "Bytea", diff --git a/.sqlx/query-a9f9ecff772fe17c0a99cfa86c01572cdfd8d6c4058cab7e3d9af84b17e5d3c5.json b/.sqlx/query-a9f9ecff772fe17c0a99cfa86c01572cdfd8d6c4058cab7e3d9af84b17e5d3c5.json index d924ddd..ab751f2 100644 --- a/.sqlx/query-a9f9ecff772fe17c0a99cfa86c01572cdfd8d6c4058cab7e3d9af84b17e5d3c5.json +++ b/.sqlx/query-a9f9ecff772fe17c0a99cfa86c01572cdfd8d6c4058cab7e3d9af84b17e5d3c5.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Int4", "Timestamptz", "Timestamptz", diff --git a/.sqlx/query-aef3a29ec6dfaa83bad8edb946c7ef9f25b5a13e10567f287a5d7275d1ac8e1e.json b/.sqlx/query-aef3a29ec6dfaa83bad8edb946c7ef9f25b5a13e10567f287a5d7275d1ac8e1e.json index 4ebf348..7cc720b 100644 --- a/.sqlx/query-aef3a29ec6dfaa83bad8edb946c7ef9f25b5a13e10567f287a5d7275d1ac8e1e.json +++ b/.sqlx/query-aef3a29ec6dfaa83bad8edb946c7ef9f25b5a13e10567f287a5d7275d1ac8e1e.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Uuid" ] diff --git a/.sqlx/query-b37dacc418b70478b2cd1e0049e8c7559789a9b84b2bd7ff75a482c3e98b55dd.json b/.sqlx/query-b37dacc418b70478b2cd1e0049e8c7559789a9b84b2bd7ff75a482c3e98b55dd.json index 75eaa38..c51c450 100644 --- a/.sqlx/query-b37dacc418b70478b2cd1e0049e8c7559789a9b84b2bd7ff75a482c3e98b55dd.json +++ b/.sqlx/query-b37dacc418b70478b2cd1e0049e8c7559789a9b84b2bd7ff75a482c3e98b55dd.json @@ -26,7 +26,7 @@ { "ordinal": 4, "name": "user_id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 5, @@ -51,7 +51,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Bytea" ] diff --git a/.sqlx/query-c90ace1efcf0598b1bc81427307e4a4b9939417fd27f0ac2f3be5d75d29189b6.json b/.sqlx/query-c90ace1efcf0598b1bc81427307e4a4b9939417fd27f0ac2f3be5d75d29189b6.json index 35d7ee0..a8b8807 100644 --- a/.sqlx/query-c90ace1efcf0598b1bc81427307e4a4b9939417fd27f0ac2f3be5d75d29189b6.json +++ b/.sqlx/query-c90ace1efcf0598b1bc81427307e4a4b9939417fd27f0ac2f3be5d75d29189b6.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Text", "Bytea", diff --git a/.sqlx/query-c91a9e3f7932e6ce435499aade8500aa507f4007f275a80d907ac20ae6e13526.json b/.sqlx/query-c91a9e3f7932e6ce435499aade8500aa507f4007f275a80d907ac20ae6e13526.json index f9d4aea..cc1c7a3 100644 --- a/.sqlx/query-c91a9e3f7932e6ce435499aade8500aa507f4007f275a80d907ac20ae6e13526.json +++ b/.sqlx/query-c91a9e3f7932e6ce435499aade8500aa507f4007f275a80d907ac20ae6e13526.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Text", "Text", "Bytea", diff --git a/.sqlx/query-cc03a341bac9db439a3f23179a333a076126f071cf2cb4dc66aa317ba5c30194.json b/.sqlx/query-cc03a341bac9db439a3f23179a333a076126f071cf2cb4dc66aa317ba5c30194.json new file mode 100644 index 0000000..46c665d --- /dev/null +++ b/.sqlx/query-cc03a341bac9db439a3f23179a333a076126f071cf2cb4dc66aa317ba5c30194.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n WITH new_responder(user_id, id, name, path, method, enabled, settings, created_at) AS (\n VALUES ( $1::uuid, $2::uuid, $3, $4, $5::bytea, $6::bool, $7::bytea, $8::timestamptz )\n )\n INSERT INTO user_data_webhooks_responders (user_id, id, name, path, method, enabled, settings, created_at)\n SELECT * FROM new_responder\n WHERE NOT EXISTS(\n SELECT id FROM user_data_webhooks_responders \n WHERE user_id = $1 AND path = $4 AND (method = $9 OR $5 = $9)\n )\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Uuid", + "Text", + "Text", + "Bytea", + "Bool", + "Bytea", + "Timestamptz", + "Bytea" + ] + }, + "nullable": [] + }, + "hash": "cc03a341bac9db439a3f23179a333a076126f071cf2cb4dc66aa317ba5c30194" +} diff --git a/.sqlx/query-cd3bebc681cf49b4fd801f5132be7930053baecafe364fdd33c70ad55690b63f.json b/.sqlx/query-cd3bebc681cf49b4fd801f5132be7930053baecafe364fdd33c70ad55690b63f.json index c20e338..e807fa7 100644 --- a/.sqlx/query-cd3bebc681cf49b4fd801f5132be7930053baecafe364fdd33c70ad55690b63f.json +++ b/.sqlx/query-cd3bebc681cf49b4fd801f5132be7930053baecafe364fdd33c70ad55690b63f.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Int4", "Timestamptz", "Timestamptz", diff --git a/.sqlx/query-d1835baa01c8592491555437d447b25a52e3bb5b990ae01b5b76325253147ceb.json b/.sqlx/query-d1835baa01c8592491555437d447b25a52e3bb5b990ae01b5b76325253147ceb.json index 6ddcf6d..12dd87d 100644 --- a/.sqlx/query-d1835baa01c8592491555437d447b25a52e3bb5b990ae01b5b76325253147ceb.json +++ b/.sqlx/query-d1835baa01c8592491555437d447b25a52e3bb5b990ae01b5b76325253147ceb.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Text", "Text", diff --git a/.sqlx/query-d76c9d4c1ec5d3d058cfc60977a8a91878a878d716da8e6052a464689705d6c4.json b/.sqlx/query-d76c9d4c1ec5d3d058cfc60977a8a91878a878d716da8e6052a464689705d6c4.json index 8718386..293b0bb 100644 --- a/.sqlx/query-d76c9d4c1ec5d3d058cfc60977a8a91878a878d716da8e6052a464689705d6c4.json +++ b/.sqlx/query-d76c9d4c1ec5d3d058cfc60977a8a91878a878d716da8e6052a464689705d6c4.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Text", "Text" ] diff --git a/.sqlx/query-dc139034ac870e4570fabdd382f5d6966ad5f1590f5e714e2bade89dda8a67f8.json b/.sqlx/query-dc139034ac870e4570fabdd382f5d6966ad5f1590f5e714e2bade89dda8a67f8.json index 2fef971..b86025c 100644 --- a/.sqlx/query-dc139034ac870e4570fabdd382f5d6966ad5f1590f5e714e2bade89dda8a67f8.json +++ b/.sqlx/query-dc139034ac870e4570fabdd382f5d6966ad5f1590f5e714e2bade89dda8a67f8.json @@ -11,7 +11,7 @@ { "ordinal": 1, "name": "user_id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 2, diff --git a/.sqlx/query-dcb605cadaeb5e99f0ce5351e64c0da818f3b818ab2693f1ea6f3d1f134a253c.json b/.sqlx/query-dcb605cadaeb5e99f0ce5351e64c0da818f3b818ab2693f1ea6f3d1f134a253c.json index 7b239c4..171e3e9 100644 --- a/.sqlx/query-dcb605cadaeb5e99f0ce5351e64c0da818f3b818ab2693f1ea6f3d1f134a253c.json +++ b/.sqlx/query-dcb605cadaeb5e99f0ce5351e64c0da818f3b818ab2693f1ea6f3d1f134a253c.json @@ -6,7 +6,7 @@ { "ordinal": 0, "name": "user_id", - "type_info": "Int4" + "type_info": "Uuid" }, { "ordinal": 1, @@ -26,7 +26,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Text", "Text" ] diff --git a/.sqlx/query-e63db773684d0224f45cb01f8c3245212a5181663fe22b8f70e8d45e958a3ef3.json b/.sqlx/query-e63db773684d0224f45cb01f8c3245212a5181663fe22b8f70e8d45e958a3ef3.json index 5e650e3..495cc96 100644 --- a/.sqlx/query-e63db773684d0224f45cb01f8c3245212a5181663fe22b8f70e8d45e958a3ef3.json +++ b/.sqlx/query-e63db773684d0224f45cb01f8c3245212a5181663fe22b8f70e8d45e958a3ef3.json @@ -41,7 +41,7 @@ ], "parameters": { "Left": [ - "Int4", + "Uuid", "Text", "Bytea", "Bytea" diff --git a/.sqlx/query-e92757701668da44ec39f6c47d7f40a88552f3647fea3cadae9376c78ab34ced.json b/.sqlx/query-e92757701668da44ec39f6c47d7f40a88552f3647fea3cadae9376c78ab34ced.json index 7ddb294..47245c4 100644 --- a/.sqlx/query-e92757701668da44ec39f6c47d7f40a88552f3647fea3cadae9376c78ab34ced.json +++ b/.sqlx/query-e92757701668da44ec39f6c47d7f40a88552f3647fea3cadae9376c78ab34ced.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Text", "Text", diff --git a/.sqlx/query-eefc34b063aaae0f6b7c2ae9a08879234871dae520a60c3007dcc2eea2322aa8.json b/.sqlx/query-eefc34b063aaae0f6b7c2ae9a08879234871dae520a60c3007dcc2eea2322aa8.json index c5e9560..602804c 100644 --- a/.sqlx/query-eefc34b063aaae0f6b7c2ae9a08879234871dae520a60c3007dcc2eea2322aa8.json +++ b/.sqlx/query-eefc34b063aaae0f6b7c2ae9a08879234871dae520a60c3007dcc2eea2322aa8.json @@ -6,7 +6,7 @@ "parameters": { "Left": [ "Uuid", - "Int4", + "Uuid", "Bytea", "Timestamptz" ] diff --git a/.sqlx/query-f8309ea879781324714b2213e121c4934fa3939fad83612a57463a0b59564925.json b/.sqlx/query-f8309ea879781324714b2213e121c4934fa3939fad83612a57463a0b59564925.json index ca3ee2b..976aa77 100644 --- a/.sqlx/query-f8309ea879781324714b2213e121c4934fa3939fad83612a57463a0b59564925.json +++ b/.sqlx/query-f8309ea879781324714b2213e121c4934fa3939fad83612a57463a0b59564925.json @@ -5,7 +5,7 @@ "columns": [], "parameters": { "Left": [ - "Int4", + "Uuid", "Uuid", "Text", "Bytea" diff --git a/.sqlx/query-fa59a4e24dfaeaeb848f9e4f7759f63caa970476e4b4379cf71f0d5f133b3fa3.json b/.sqlx/query-fa59a4e24dfaeaeb848f9e4f7759f63caa970476e4b4379cf71f0d5f133b3fa3.json new file mode 100644 index 0000000..a4ef45d --- /dev/null +++ b/.sqlx/query-fa59a4e24dfaeaeb848f9e4f7759f63caa970476e4b4379cf71f0d5f133b3fa3.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\nDELETE FROM users\nWHERE email = $1\nRETURNING id\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "fa59a4e24dfaeaeb848f9e4f7759f63caa970476e4b4379cf71f0d5f133b3fa3" +} diff --git a/.sqlx/query-faefaa039b94bdc11d3dcb00e606ab1d2de0425c357f45f0351aa0271c420984.json b/.sqlx/query-faefaa039b94bdc11d3dcb00e606ab1d2de0425c357f45f0351aa0271c420984.json index bf9b2a6..a5a59c6 100644 --- a/.sqlx/query-faefaa039b94bdc11d3dcb00e606ab1d2de0425c357f45f0351aa0271c420984.json +++ b/.sqlx/query-faefaa039b94bdc11d3dcb00e606ab1d2de0425c357f45f0351aa0271c420984.json @@ -26,7 +26,7 @@ ], "parameters": { "Left": [ - "Int4" + "Uuid" ] }, "nullable": [ diff --git a/migrations/20240328205631_v1.0.0-beta.1.sql b/migrations/20240328205631_v1.0.0-beta.1.sql index 4581e37..cc4144f 100644 --- a/migrations/20240328205631_v1.0.0-beta.1.sql +++ b/migrations/20240328205631_v1.0.0-beta.1.sql @@ -3,12 +3,12 @@ CREATE COLLATION case_insensitive (provider = icu, locale = 'und-u-ks-level2', d -- Table to store users. CREATE TABLE IF NOT EXISTS users ( - id SERIAL PRIMARY KEY NOT NULL, - email TEXT NOT NULL UNIQUE COLLATE case_insensitive, - handle TEXT NOT NULL UNIQUE COLLATE case_insensitive, - credentials BYTEA NOT NULL, - created TIMESTAMPTZ NOT NULL, - activated BOOL NOT NULL + id UUID PRIMARY KEY NOT NULL, + email TEXT NOT NULL UNIQUE COLLATE case_insensitive, + handle TEXT NOT NULL UNIQUE COLLATE case_insensitive, + credentials BYTEA NOT NULL, + created TIMESTAMPTZ NOT NULL, + activated BOOL NOT NULL ); -- Table to store intermediate WebAuthn Relying Party session data during user registration and authentication. @@ -33,7 +33,7 @@ CREATE TABLE IF NOT EXISTS utils CREATE TABLE IF NOT EXISTS user_shares ( id UUID PRIMARY KEY NOT NULL, - user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, resource BYTEA NOT NULL, created_at TIMESTAMPTZ NOT NULL ); @@ -50,7 +50,7 @@ CREATE TABLE IF NOT EXISTS notifications -- Table to store user data (e.g., settings). CREATE TABLE IF NOT EXISTS user_data ( - user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, namespace TEXT NOT NULL COLLATE case_insensitive, key TEXT NOT NULL COLLATE case_insensitive, value BYTEA NOT NULL, @@ -67,7 +67,7 @@ CREATE TABLE IF NOT EXISTS user_data_certificates_private_keys pkcs8 BYTEA NOT NULL, encrypted BOOL NOT NULL, created_at TIMESTAMPTZ NOT NULL, - user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, UNIQUE (name, user_id) ); @@ -78,7 +78,7 @@ CREATE TABLE IF NOT EXISTS user_data_certificates_certificate_templates name TEXT NOT NULL COLLATE case_insensitive, attributes BYTEA NOT NULL, created_at TIMESTAMPTZ NOT NULL, - user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, UNIQUE (name, user_id) ); @@ -93,7 +93,7 @@ CREATE TABLE IF NOT EXISTS user_data_web_scraping_trackers job_config BYTEA, data BYTEA NOT NULL, created_at TIMESTAMPTZ NOT NULL, - user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, UNIQUE (name, kind, user_id) ); @@ -104,7 +104,7 @@ CREATE TABLE IF NOT EXISTS user_data_web_scraping_trackers_history data BYTEA NOT NULL, created_at TIMESTAMPTZ NOT NULL, tracker_id UUID NOT NULL REFERENCES user_data_web_scraping_trackers (id) ON DELETE CASCADE, - user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, UNIQUE (created_at, tracker_id) ); @@ -115,7 +115,7 @@ CREATE TABLE IF NOT EXISTS user_data_web_security_csp name TEXT NOT NULL COLLATE case_insensitive, directives BYTEA NOT NULL, created_at TIMESTAMPTZ NOT NULL, - user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, UNIQUE (name, user_id) ); @@ -129,7 +129,7 @@ CREATE TABLE IF NOT EXISTS user_data_webhooks_responders method BYTEA NOT NULL, settings BYTEA NOT NULL, created_at TIMESTAMPTZ NOT NULL, - user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE, + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, UNIQUE (name, user_id), UNIQUE (path, method, user_id) ); @@ -141,18 +141,18 @@ CREATE TABLE IF NOT EXISTS user_data_webhooks_responders_history data BYTEA NOT NULL, created_at TIMESTAMPTZ NOT NULL, responder_id UUID NOT NULL REFERENCES user_data_webhooks_responders (id) ON DELETE CASCADE, - user_id INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE + user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE ); -- Table to store user subscriptions. CREATE TABLE IF NOT EXISTS user_subscriptions ( - tier INTEGER NOT NULL, - started_at TIMESTAMPTZ NOT NULL, + tier INTEGER NOT NULL, + started_at TIMESTAMPTZ NOT NULL, ends_at TIMESTAMPTZ, trial_started_at TIMESTAMPTZ, trial_ends_at TIMESTAMPTZ, - user_id INTEGER UNIQUE NOT NULL REFERENCES users (id) ON DELETE CASCADE, + user_id UUID UNIQUE NOT NULL REFERENCES users (id) ON DELETE CASCADE, CHECK ((ends_at IS NULL OR (ends_at > started_at)) AND (trial_started_at IS NULL OR trial_ends_at IS NULL OR (trial_ends_at > trial_started_at))) ); diff --git a/src/config.rs b/src/config.rs index 9968ed9..126bdd8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -152,7 +152,7 @@ mod tests { query: None, fragment: None, }, - search_index_version: 3, + search_index_version: 4, }, scheduler: SchedulerJobsConfig { web_page_trackers_schedule: Schedule { diff --git a/src/config/components_config.rs b/src/config/components_config.rs index 4de5c67..502b28d 100644 --- a/src/config/components_config.rs +++ b/src/config/components_config.rs @@ -17,7 +17,7 @@ impl Default for ComponentsConfig { Self { web_scraper_url: Url::parse("http://localhost:7272") .expect("Cannot parse Web Scraper URL parameter."), - search_index_version: 3, + search_index_version: 4, } } } @@ -31,7 +31,7 @@ mod tests { fn serialization_and_default() { assert_toml_snapshot!(ComponentsConfig::default(), @r###" web-scraper-url = 'http://localhost:7272/' - search-index-version = 3 + search-index-version = 4 "###); } @@ -40,7 +40,7 @@ mod tests { let config: ComponentsConfig = toml::from_str( r#" web-scraper-url = 'http://localhost:7272/' - search-index-version = 3 + search-index-version = 4 "#, ) .unwrap(); diff --git a/src/config/raw_config.rs b/src/config/raw_config.rs index 2a813b0..dc9e1d8 100644 --- a/src/config/raw_config.rs +++ b/src/config/raw_config.rs @@ -96,7 +96,7 @@ mod tests { [components] web-scraper-url = 'http://localhost:7272/' - search-index-version = 3 + search-index-version = 4 [scheduler] web-page-trackers-schedule = '0 * * * * * *' diff --git a/src/logging/user_log_context.rs b/src/logging/user_log_context.rs index aee4d86..5a7294c 100644 --- a/src/logging/user_log_context.rs +++ b/src/logging/user_log_context.rs @@ -27,12 +27,13 @@ mod tests { use crate::{logging::UserLogContext, security::StoredCredentials, tests::MockUserBuilder}; use insta::assert_json_snapshot; use time::OffsetDateTime; + use uuid::uuid; #[test] fn serialization() -> anyhow::Result<()> { - assert_json_snapshot!(UserLogContext::new(1.try_into()?), @r###" + assert_json_snapshot!(UserLogContext::new(uuid!("00000000-0000-0000-0000-000000000001").into()), @r###" { - "id": 1 + "id": "00000000-0000-0000-0000-000000000001" } "###); @@ -42,7 +43,7 @@ mod tests { #[test] fn log_context() -> anyhow::Result<()> { let user = MockUserBuilder::new( - 3.try_into()?, + uuid!("00000000-0000-0000-0000-000000000003").into(), "my-email", "my-handle", StoredCredentials { @@ -54,7 +55,10 @@ mod tests { ) .build(); - assert_eq!(user.log_context(), UserLogContext::new(3.try_into()?)); + assert_eq!( + user.log_context(), + UserLogContext::new(uuid!("00000000-0000-0000-0000-000000000003").into()) + ); Ok(()) } diff --git a/src/main.rs b/src/main.rs index 51c0f7c..fcfbbb2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -77,7 +77,6 @@ mod tests { WebPageResource, WebPageResourceContent, WebPageResourceContentData, }, }; - use anyhow::anyhow; use cron::Schedule; use lettre::transport::stub::AsyncStubTransport; use std::{collections::HashMap, ops::Add, time::Duration}; @@ -96,6 +95,7 @@ mod tests { pub use crate::{network::tests::*, scheduler::tests::*, server::tests::*, utils::tests::*}; use ctor::ctor; use sqlx::{postgres::PgDatabaseError, PgPool}; + use uuid::uuid; pub struct MockUserBuilder { user: User, @@ -243,11 +243,11 @@ mod tests { } pub fn mock_user() -> anyhow::Result { - mock_user_with_id(1) + mock_user_with_id(uuid!("00000000-0000-0000-0000-000000000001")) } - pub fn mock_user_with_id>(id: I) -> anyhow::Result { - let id = id.try_into().map_err(|_| anyhow!("err"))?; + pub fn mock_user_with_id>(id: I) -> anyhow::Result { + let id = id.into(); Ok(MockUserBuilder::new( id, &format!("dev-{}@secutils.dev", *id), diff --git a/src/notifications/api_ext.rs b/src/notifications/api_ext.rs index 5aa746e..fd3b7e8 100644 --- a/src/notifications/api_ext.rs +++ b/src/notifications/api_ext.rs @@ -213,6 +213,7 @@ mod tests { use insta::assert_debug_snapshot; use sqlx::PgPool; use time::OffsetDateTime; + use uuid::uuid; #[sqlx::test] async fn properly_schedules_notification(pool: PgPool) -> anyhow::Result<()> { @@ -224,12 +225,12 @@ mod tests { let notifications = vec![ Notification::new( - NotificationDestination::User(123.try_into()?), + NotificationDestination::User(uuid!("00000000-0000-0000-0000-000000000001").into()), NotificationContent::Text("abc".to_string()), OffsetDateTime::from_unix_timestamp(946720800)?, ), Notification::new( - NotificationDestination::User(123.try_into()?), + NotificationDestination::User(uuid!("00000000-0000-0000-0000-000000000001").into()), NotificationContent::Text("abc".to_string()), OffsetDateTime::from_unix_timestamp(946720800)?, ), @@ -253,7 +254,7 @@ mod tests { ), destination: User( UserId( - 123, + 00000000-0000-0000-0000-000000000001, ), ), content: Text( @@ -271,7 +272,7 @@ mod tests { ), destination: User( UserId( - 123, + 00000000-0000-0000-0000-000000000001, ), ), content: Text( @@ -354,8 +355,8 @@ mod tests { Envelope { forward_path: [ Address { - serialized: "dev-1@secutils.dev", - at_start: 5, + serialized: "dev-00000000-0000-0000-0000-000000000001@secutils.dev", + at_start: 40, }, ], reverse_path: Some( @@ -365,7 +366,7 @@ mod tests { }, ), }, - "From: dev@secutils.dev\r\nReply-To: dev@secutils.dev\r\nTo: dev-1@secutils.dev\r\nSubject: [NO SUBJECT]\r\nDate: Sat, 01 Jan 2000 09:58:20 +0000\r\nContent-Transfer-Encoding: 7bit\r\n\r\nabc", + "From: dev@secutils.dev\r\nReply-To: dev@secutils.dev\r\nTo: dev-00000000-0000-0000-0000-000000000001@secutils.dev\r\nSubject: [NO SUBJECT]\r\nDate: Sat, 01 Jan 2000 09:58:20 +0000\r\nContent-Transfer-Encoding: 7bit\r\n\r\nabc", ), ( Envelope { diff --git a/src/notifications/database_ext.rs b/src/notifications/database_ext.rs index e33f6ba..00197a8 100644 --- a/src/notifications/database_ext.rs +++ b/src/notifications/database_ext.rs @@ -106,6 +106,7 @@ mod tests { use insta::assert_debug_snapshot; use sqlx::PgPool; use time::OffsetDateTime; + use uuid::uuid; #[sqlx::test] async fn can_add_and_retrieve_notifications(pool: PgPool) -> anyhow::Result<()> { @@ -114,12 +115,12 @@ mod tests { let notifications = vec![ Notification::new( - NotificationDestination::User(123.try_into()?), + NotificationDestination::User(uuid!("00000000-0000-0000-0000-000000000001").into()), NotificationContent::Text("abc".to_string()), OffsetDateTime::from_unix_timestamp(946720800)?, ), Notification::new( - NotificationDestination::User(123.try_into()?), + NotificationDestination::User(uuid!("00000000-0000-0000-0000-000000000001").into()), NotificationContent::Text("abc".to_string()), OffsetDateTime::from_unix_timestamp(946720800)?, ), @@ -137,7 +138,7 @@ mod tests { ), destination: User( UserId( - 123, + 00000000-0000-0000-0000-000000000001, ), ), content: Text( @@ -155,7 +156,7 @@ mod tests { ), destination: User( UserId( - 123, + 00000000-0000-0000-0000-000000000001, ), ), content: Text( @@ -176,12 +177,12 @@ mod tests { let notifications = vec![ Notification::new( - NotificationDestination::User(123.try_into()?), + NotificationDestination::User(uuid!("00000000-0000-0000-0000-000000000001").into()), NotificationContent::Text("abc".to_string()), OffsetDateTime::from_unix_timestamp(946720800)?, ), Notification::new( - NotificationDestination::User(123.try_into()?), + NotificationDestination::User(uuid!("00000000-0000-0000-0000-000000000001").into()), NotificationContent::Text("abc".to_string()), OffsetDateTime::from_unix_timestamp(946720800)?, ), @@ -220,7 +221,7 @@ mod tests { for n in 0..=19 { db.insert_notification(&Notification::new( - NotificationDestination::User(123.try_into()?), + NotificationDestination::User(uuid!("00000000-0000-0000-0000-000000000001").into()), NotificationContent::Text(format!("abc{}", n)), OffsetDateTime::from_unix_timestamp(946720700 + n)?, )) diff --git a/src/notifications/database_ext/raw_notification.rs b/src/notifications/database_ext/raw_notification.rs index d8aee83..18d68e4 100644 --- a/src/notifications/database_ext/raw_notification.rs +++ b/src/notifications/database_ext/raw_notification.rs @@ -40,19 +40,22 @@ mod tests { use super::RawNotification; use crate::notifications::{Notification, NotificationContent, NotificationDestination}; use time::OffsetDateTime; + use uuid::uuid; #[test] fn can_convert_to_notification() -> anyhow::Result<()> { assert_eq!( Notification::try_from(RawNotification { id: 1, - destination: vec![0, 246, 1], + destination: vec![0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], content: vec![0, 3, 97, 98, 99], scheduled_at: OffsetDateTime::from_unix_timestamp(946720800)?, })?, Notification { id: 1.try_into()?, - destination: NotificationDestination::User(123.try_into()?), + destination: NotificationDestination::User( + uuid!("00000000-0000-0000-0000-000000000001").into() + ), content: NotificationContent::Text("abc".to_string()), scheduled_at: OffsetDateTime::from_unix_timestamp(946720800)?, } @@ -66,13 +69,15 @@ mod tests { assert_eq!( RawNotification::try_from(&Notification { id: 1.try_into()?, - destination: NotificationDestination::User(123.try_into()?), + destination: NotificationDestination::User( + uuid!("00000000-0000-0000-0000-000000000001").into() + ), content: NotificationContent::Text("abc".to_string()), scheduled_at: OffsetDateTime::from_unix_timestamp(946720800)?, })?, RawNotification { id: 1, - destination: vec![0, 246, 1], + destination: vec![0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], content: vec![0, 3, 97, 98, 99], scheduled_at: OffsetDateTime::from_unix_timestamp(946720800)?, } diff --git a/src/notifications/notification.rs b/src/notifications/notification.rs index a18a402..18b09d6 100644 --- a/src/notifications/notification.rs +++ b/src/notifications/notification.rs @@ -35,18 +35,21 @@ mod tests { use super::{Notification, NotificationContent, NotificationDestination}; use crate::notifications::NotificationId; use time::OffsetDateTime; + use uuid::uuid; #[test] fn new_notification() -> anyhow::Result<()> { assert_eq!( Notification::new( - NotificationDestination::User(123.try_into()?), + NotificationDestination::User(uuid!("00000000-0000-0000-0000-000000000001").into()), NotificationContent::Text("abc".to_string()), OffsetDateTime::from_unix_timestamp(946720800)? ), Notification { id: NotificationId::empty(), - destination: NotificationDestination::User(123.try_into()?), + destination: NotificationDestination::User( + uuid!("00000000-0000-0000-0000-000000000001").into() + ), content: NotificationContent::Text("abc".to_string()), scheduled_at: OffsetDateTime::from_unix_timestamp(946720800)?, } diff --git a/src/notifications/notification_content.rs b/src/notifications/notification_content.rs index ee23632..3ac31ce 100644 --- a/src/notifications/notification_content.rs +++ b/src/notifications/notification_content.rs @@ -186,9 +186,9 @@ mod tests { assert_debug_snapshot!(template, @r###" EmailNotificationContent { subject: "Activate your Secutils.dev account", - text: "To activate your Secutils.dev account, please use the following link: http://localhost:1234/activate?code=some-code&email=dev-1%40secutils.dev", + text: "To activate your Secutils.dev account, please use the following link: http://localhost:1234/activate?code=some-code&email=dev-00000000-0000-0000-0000-000000000001%40secutils.dev", html: Some( - "\n\n\n Activate your Secutils.dev account\n \n \n \n\n\n
\n

Hi there,

\n

Thanks for signing up! To activate your account, please click the button below:

\n Activate my account\n

Alternatively, copy and paste the following URL into your browser:

\n

http://localhost:1234/activate?code=some-code&email=dev-1%40secutils.dev

\n

If you have any trouble activating your account, please email to contact@secutils.dev\n or simply reply to this email.

\n \"Secutils.dev\n
\n\n\n", + "\n\n\n Activate your Secutils.dev account\n \n \n \n\n\n
\n

Hi there,

\n

Thanks for signing up! To activate your account, please click the button below:

\n Activate my account\n

Alternatively, copy and paste the following URL into your browser:

\n

http://localhost:1234/activate?code=some-code&email=dev-00000000-0000-0000-0000-000000000001%40secutils.dev

\n

If you have any trouble activating your account, please email to contact@secutils.dev\n or simply reply to this email.

\n \"Secutils.dev\n
\n\n\n", ), attachments: Some( [ diff --git a/src/notifications/notification_content_template.rs b/src/notifications/notification_content_template.rs index 68ef560..d69f7a6 100644 --- a/src/notifications/notification_content_template.rs +++ b/src/notifications/notification_content_template.rs @@ -108,9 +108,9 @@ mod tests { template, @r###" EmailNotificationContent { subject: "Activate your Secutils.dev account", - text: "To activate your Secutils.dev account, please use the following link: http://localhost:1234/activate?code=some-code&email=dev-1%40secutils.dev", + text: "To activate your Secutils.dev account, please use the following link: http://localhost:1234/activate?code=some-code&email=dev-00000000-0000-0000-0000-000000000001%40secutils.dev", html: Some( - "\n\n\n Activate your Secutils.dev account\n \n \n \n\n\n
\n

Hi there,

\n

Thanks for signing up! To activate your account, please click the button below:

\n Activate my account\n

Alternatively, copy and paste the following URL into your browser:

\n

http://localhost:1234/activate?code=some-code&email=dev-1%40secutils.dev

\n

If you have any trouble activating your account, please email to contact@secutils.dev\n or simply reply to this email.

\n \"Secutils.dev\n
\n\n\n", + "\n\n\n Activate your Secutils.dev account\n \n \n \n\n\n
\n

Hi there,

\n

Thanks for signing up! To activate your account, please click the button below:

\n Activate my account\n

Alternatively, copy and paste the following URL into your browser:

\n

http://localhost:1234/activate?code=some-code&email=dev-00000000-0000-0000-0000-000000000001%40secutils.dev

\n

If you have any trouble activating your account, please email to contact@secutils.dev\n or simply reply to this email.

\n \"Secutils.dev\n
\n\n\n", ), attachments: Some( [ @@ -173,9 +173,9 @@ mod tests { template, @r###" EmailNotificationContent { subject: "Reset password for your Secutils.dev account", - text: "To reset your Secutils.dev password, please use the following link: http://localhost:1234/reset_credentials?code=some-code&email=dev-1%40secutils.dev", + text: "To reset your Secutils.dev password, please use the following link: http://localhost:1234/reset_credentials?code=some-code&email=dev-00000000-0000-0000-0000-000000000001%40secutils.dev", html: Some( - "\n\n\n Reset password for your Secutils.dev account\n \n \n \n\n\n
\n

Hi there,

\n

You recently requested to reset your password. To reset your password, please click the button below:

\n Reset my password\n

Alternatively, copy and paste the following URL into your browser:

\n

http://localhost:1234/reset_credentials?code=some-code&email=dev-1%40secutils.dev

\n

If you did not request to reset your password, please ignore this email and your password will not be changed.

\n

If you have any trouble resetting your password, please email to contact@secutils.dev\n or simply reply to this email.

\n \"Secutils.dev\n
\n\n\n", + "\n\n\n Reset password for your Secutils.dev account\n \n \n \n\n\n
\n

Hi there,

\n

You recently requested to reset your password. To reset your password, please click the button below:

\n Reset my password\n

Alternatively, copy and paste the following URL into your browser:

\n

http://localhost:1234/reset_credentials?code=some-code&email=dev-00000000-0000-0000-0000-000000000001%40secutils.dev

\n

If you did not request to reset your password, please ignore this email and your password will not be changed.

\n

If you have any trouble resetting your password, please email to contact@secutils.dev\n or simply reply to this email.

\n \"Secutils.dev\n
\n\n\n", ), attachments: Some( [ diff --git a/src/notifications/notification_destination.rs b/src/notifications/notification_destination.rs index 6d53eb4..1db6316 100644 --- a/src/notifications/notification_destination.rs +++ b/src/notifications/notification_destination.rs @@ -15,12 +15,15 @@ pub enum NotificationDestination { #[cfg(test)] mod tests { use super::NotificationDestination; + use uuid::uuid; #[test] fn serialization() -> anyhow::Result<()> { assert_eq!( - postcard::to_stdvec(&NotificationDestination::User(123.try_into()?))?, - vec![0, 246, 1] + postcard::to_stdvec(&NotificationDestination::User( + uuid!("00000000-0000-0000-0000-000000000001").into() + ))?, + vec![0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] ); assert_eq!( postcard::to_stdvec(&NotificationDestination::Email("abc".to_string()))?, @@ -36,8 +39,10 @@ mod tests { #[test] fn deserialization() -> anyhow::Result<()> { assert_eq!( - postcard::from_bytes::(&[0, 246, 1])?, - NotificationDestination::User(123.try_into()?) + postcard::from_bytes::(&[ + 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 + ])?, + NotificationDestination::User(uuid!("00000000-0000-0000-0000-000000000001").into()) ); assert_eq!( postcard::from_bytes::(&[1, 3, 97, 98, 99])?, diff --git a/src/scheduler/scheduler_jobs/notifications_send_job.rs b/src/scheduler/scheduler_jobs/notifications_send_job.rs index ead6c8c..f3eb961 100644 --- a/src/scheduler/scheduler_jobs/notifications_send_job.rs +++ b/src/scheduler/scheduler_jobs/notifications_send_job.rs @@ -252,8 +252,8 @@ mod tests { Envelope { forward_path: [ Address { - serialized: "dev-1@secutils.dev", - at_start: 5, + serialized: "dev-00000000-0000-0000-0000-000000000001@secutils.dev", + at_start: 40, }, ], reverse_path: Some( @@ -263,7 +263,7 @@ mod tests { }, ), }, - "From: dev@secutils.dev\r\nReply-To: dev@secutils.dev\r\nTo: dev-1@secutils.dev\r\nSubject: [NO SUBJECT]\r\nDate: Sat, 01 Jan 2000 10:00:00 +0000\r\nContent-Transfer-Encoding: 7bit\r\n\r\nmessage 0", + "From: dev@secutils.dev\r\nReply-To: dev@secutils.dev\r\nTo: dev-00000000-0000-0000-0000-000000000001@secutils.dev\r\nSubject: [NO SUBJECT]\r\nDate: Sat, 01 Jan 2000 10:00:00 +0000\r\nContent-Transfer-Encoding: 7bit\r\n\r\nmessage 0", ) "###); diff --git a/src/scheduler/scheduler_jobs/web_page_trackers_fetch_job.rs b/src/scheduler/scheduler_jobs/web_page_trackers_fetch_job.rs index fbfa90f..1a6fd6b 100644 --- a/src/scheduler/scheduler_jobs/web_page_trackers_fetch_job.rs +++ b/src/scheduler/scheduler_jobs/web_page_trackers_fetch_job.rs @@ -1089,7 +1089,7 @@ mod tests { ( User( UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), ), Template( @@ -1254,7 +1254,7 @@ mod tests { ( User( UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), ), Template( @@ -1453,7 +1453,7 @@ mod tests { ( User( UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), ), Template( @@ -1691,7 +1691,7 @@ mod tests { ( User( UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), ), Template( @@ -1855,7 +1855,7 @@ mod tests { ( User( UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), ), Template( @@ -2018,7 +2018,7 @@ mod tests { ( User( UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), ), Template( @@ -2215,7 +2215,7 @@ mod tests { ( User( UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), ), Template( @@ -2438,7 +2438,7 @@ mod tests { ( User( UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), ), Template( diff --git a/src/search/search_index.rs b/src/search/search_index.rs index 0761a9a..d4afd3c 100644 --- a/src/search/search_index.rs +++ b/src/search/search_index.rs @@ -24,10 +24,12 @@ fn entity_to_document( let mut doc = Document::default(); doc.add_u64(schema_fields.id, entity.id); - doc.add_i64( - schema_fields.user_id, - *entity.user_id.unwrap_or_default() as i64, - ); + + if let Some(id) = entity.user_id { + doc.add_text(schema_fields.user_id, id.to_string()); + } else { + doc.add_text(schema_fields.user_id, ""); + } doc.add_text(schema_fields.label, &entity.label); doc.add_text(schema_fields.label_ngram, &entity.label.to_lowercase()); @@ -170,7 +172,7 @@ impl SearchIndex { search_filter: SearchFilter, ) -> anyhow::Result> { let public_query = Box::new(TermQuery::new( - Term::from_field_i64(self.schema_fields.user_id, *UserId::default() as i64), + Term::from_field_text(self.schema_fields.user_id, ""), IndexRecordOption::Basic, )) as Box; @@ -180,7 +182,7 @@ impl SearchIndex { ( Occur::Should, Box::new(TermQuery::new( - Term::from_field_i64(self.schema_fields.user_id, *user_id as i64), + Term::from_field_text(self.schema_fields.user_id, &user_id.to_string()), IndexRecordOption::Basic, )) as Box, ), @@ -277,9 +279,9 @@ impl SearchIndex { id.replace(field_value_content); } } else if field_value.field == self.schema_fields.user_id { - if let Value::I64(field_value_content) = field_value.value { - if field_value_content != *UserId::default() as i64 { - user_id.replace((field_value_content as i32).try_into()?); + if let Value::Str(field_value_content) = field_value.value { + if !field_value_content.is_empty() { + user_id.replace(field_value_content.parse()?); } } } else if field_value.field == self.schema_fields.label { @@ -354,6 +356,7 @@ mod tests { use insta::assert_debug_snapshot; use tantivy::Index; use time::OffsetDateTime; + use uuid::uuid; #[test] fn can_index_and_retrieve_items() -> anyhow::Result<()> { @@ -377,7 +380,7 @@ mod tests { OffsetDateTime::from_unix_timestamp(1262340000)?, ) .set_keywords("some keywords") - .set_user_id(3.try_into()?) + .set_user_id(uuid!("00000000-0000-0000-0000-000000000003").into()) .set_sub_category("some-handle") .set_meta([("one".to_string(), "two".to_string())]) .build(), @@ -414,7 +417,7 @@ mod tests { ), user_id: Some( UserId( - 3, + 00000000-0000-0000-0000-000000000003, ), ), meta: Some( @@ -501,7 +504,7 @@ mod tests { // January 1, 2000 11:00:00 OffsetDateTime::from_unix_timestamp(946720800)?, ) - .set_user_id(3.try_into()?) + .set_user_id(uuid!("00000000-0000-0000-0000-000000000003").into()) .build(); let item_user_4 = MockSearchItemBuilder::new( 2, @@ -510,7 +513,7 @@ mod tests { // January 1, 2010 11:00:00 OffsetDateTime::from_unix_timestamp(1262340000)?, ) - .set_user_id(4.try_into()?) + .set_user_id(uuid!("00000000-0000-0000-0000-000000000004").into()) .build(); let public_item = MockSearchItemBuilder::new( @@ -530,16 +533,20 @@ mod tests { public_items.sort_by(|item_a, item_b| item_a.id.cmp(&item_b.id)); assert_eq!(public_items, vec![public_item.clone()]); - let mut public_and_user_items = - index.search(SearchFilter::default().with_user_id(3.try_into()?))?; + let mut public_and_user_items = index.search( + SearchFilter::default() + .with_user_id(uuid!("00000000-0000-0000-0000-000000000003").into()), + )?; public_and_user_items.sort_by(|item_a, item_b| item_a.id.cmp(&item_b.id)); assert_eq!( public_and_user_items, vec![item_user_3, public_item.clone()] ); - let mut public_and_user_items = - index.search(SearchFilter::default().with_user_id(4.try_into()?))?; + let mut public_and_user_items = index.search( + SearchFilter::default() + .with_user_id(uuid!("00000000-0000-0000-0000-000000000004").into()), + )?; public_and_user_items.sort_by(|item_a, item_b| item_a.id.cmp(&item_b.id)); assert_eq!( public_and_user_items, @@ -547,7 +554,10 @@ mod tests { ); assert_eq!( - index.search(SearchFilter::default().with_user_id(5.try_into()?))?, + index.search( + SearchFilter::default() + .with_user_id(uuid!("00000000-0000-0000-0000-000000000005").into()) + )?, vec![public_item] ); @@ -605,7 +615,7 @@ mod tests { let index = SearchIndex::open(|schema| Ok(Index::create_in_ram(schema)))?; assert_debug_snapshot!( index.search_filter_into_query(default_filter)?, - @"TermQuery(Term(field=1, type=I64, 0))" + @r###"TermQuery(Term(field=1, type=Str, ""))"### ); Ok(()) @@ -613,11 +623,12 @@ mod tests { #[test] fn filter_with_user_id() -> anyhow::Result<()> { - let filter = SearchFilter::default().with_user_id(1.try_into()?); + let filter = SearchFilter::default() + .with_user_id(uuid!("00000000-0000-0000-0000-000000000001").into()); assert_eq!( filter, SearchFilter { - user_id: Some(1.try_into()?), + user_id: Some(uuid!("00000000-0000-0000-0000-000000000001").into()), query: None, category: None } @@ -631,11 +642,11 @@ mod tests { subqueries: [ ( Should, - TermQuery(Term(field=1, type=I64, 0)), + TermQuery(Term(field=1, type=Str, "")), ), ( Should, - TermQuery(Term(field=1, type=I64, 1)), + TermQuery(Term(field=1, type=Str, "00000000-0000-0000-0000-000000000001")), ), ], } @@ -665,7 +676,7 @@ mod tests { subqueries: [ ( Must, - TermQuery(Term(field=1, type=I64, 0)), + TermQuery(Term(field=1, type=Str, "")), ), ( Must, @@ -796,7 +807,7 @@ mod tests { subqueries: [ ( Must, - TermQuery(Term(field=1, type=I64, 0)), + TermQuery(Term(field=1, type=Str, "")), ), ( Must, @@ -813,12 +824,12 @@ mod tests { #[test] fn filter_with_user_id_and_query() -> anyhow::Result<()> { let filter = SearchFilter::default() - .with_user_id(1.try_into()?) + .with_user_id(uuid!("00000000-0000-0000-0000-000000000001").into()) .with_query("Some-Query"); assert_eq!( filter, SearchFilter { - user_id: Some(1.try_into()?), + user_id: Some(uuid!("00000000-0000-0000-0000-000000000001").into()), query: Some("Some-Query"), category: None } @@ -836,11 +847,11 @@ mod tests { subqueries: [ ( Should, - TermQuery(Term(field=1, type=I64, 0)), + TermQuery(Term(field=1, type=Str, "")), ), ( Should, - TermQuery(Term(field=1, type=I64, 1)), + TermQuery(Term(field=1, type=Str, "00000000-0000-0000-0000-000000000001")), ), ], }, @@ -976,7 +987,7 @@ mod tests { subqueries: [ ( Must, - TermQuery(Term(field=1, type=I64, 0)), + TermQuery(Term(field=1, type=Str, "")), ), ( Must, diff --git a/src/search/search_index_schema_fields.rs b/src/search/search_index_schema_fields.rs index 3a57af3..3e5f036 100644 --- a/src/search/search_index_schema_fields.rs +++ b/src/search/search_index_schema_fields.rs @@ -27,7 +27,7 @@ impl SearchIndexSchemaFields { ( Self { id: schema_builder.add_u64_field("id", FAST | INDEXED | STORED), - user_id: schema_builder.add_i64_field("user_id", FAST | INDEXED | STORED), + user_id: schema_builder.add_text_field("user_id", STRING | STORED), label: schema_builder.add_text_field("label", STRING | STORED), label_ngram: schema_builder.add_text_field( "label_ngram", diff --git a/src/search/search_item.rs b/src/search/search_item.rs index 208857e..0e80a24 100644 --- a/src/search/search_item.rs +++ b/src/search/search_item.rs @@ -60,6 +60,7 @@ mod tests { use crate::search::SearchItem; use insta::{assert_debug_snapshot, assert_json_snapshot}; use time::OffsetDateTime; + use uuid::uuid; #[test] fn serialization() -> anyhow::Result<()> { @@ -88,7 +89,7 @@ mod tests { keywords: Some("some keywords".to_string()), category: "some-category".to_string(), sub_category: Some("some-sub-category".to_string()), - user_id: Some(2.try_into()?), + user_id: Some(uuid!("00000000-0000-0000-0000-000000000002").into()), meta: Some( [("one".to_string(), "two".to_string())] .into_iter() @@ -116,8 +117,8 @@ mod tests { fn can_create_id() -> anyhow::Result<()> { assert_debug_snapshot!(SearchItem::create_id("some-label", "some-category", None, None), @"9401142304413078507"); assert_debug_snapshot!(SearchItem::create_id("some-label", "some-category", Some("some-sub-category"), None), @"1596497830688235325"); - assert_debug_snapshot!(SearchItem::create_id("some-label", "some-category", None, Some(1.try_into()?)), @"1601645354856309167"); - assert_debug_snapshot!(SearchItem::create_id("some-label", "some-category", Some("some-sub-category"), Some(1.try_into()?)), @"15509739472169832845"); + assert_debug_snapshot!(SearchItem::create_id("some-label", "some-category", None, Some(uuid!("00000000-0000-0000-0000-000000000001").into())), @"15620247599751410876"); + assert_debug_snapshot!(SearchItem::create_id("some-label", "some-category", Some("some-sub-category"), Some(uuid!("00000000-0000-0000-0000-000000000001").into())), @"5842154758832312172"); Ok(()) } diff --git a/src/security/api_ext.rs b/src/security/api_ext.rs index 69ee8d6..6c4907b 100644 --- a/src/security/api_ext.rs +++ b/src/security/api_ext.rs @@ -93,7 +93,7 @@ where }; let user = User { - id: UserId::default(), + id: UserId::new(), email: user_email, handle: self.generate_user_handle().await?, credentials, @@ -104,16 +104,11 @@ where // Use insert instead of upsert here to prevent multiple signup requests from the same user. // Consumer of the API is supposed to perform validation before invoking this method. - let user = self - .api + self.api .db .insert_user(&user) .await - .with_context(|| "Cannot signup user, failed to insert a new user.") - .map(|user_id| User { - id: user_id, - ..user - })?; + .with_context(|| "Cannot signup user, failed to insert a new user.")?; // Send email to the user with the account activation link. self.send_activation_link(&user).await?; diff --git a/src/server/handlers/utils_action.rs b/src/server/handlers/utils_action.rs index 6db17bf..1ef0c63 100644 --- a/src/server/handlers/utils_action.rs +++ b/src/server/handlers/utils_action.rs @@ -555,7 +555,7 @@ mod tests { let api = mock_api(pool).await?; // Insert user into the database. - let user = mock_user_with_id(1)?; + let user = mock_user_with_id(uuid!("00000000-0000-0000-0000-000000000001"))?; let users = api.users(); users.upsert(&user).await?; @@ -588,7 +588,7 @@ mod tests { assert_eq!(extracted_user.unwrap().id, user.id); // Both current user and user share that doesn't belong to that user were provided. - let another_user = mock_user_with_id(2)?; + let another_user = mock_user_with_id(uuid!("00000000-0000-0000-0000-000000000002"))?; users.upsert(&another_user).await?; let extracted_user = extract_user( &api, @@ -626,7 +626,7 @@ mod tests { assert_eq!(extracted_user.unwrap().id, another_user.id); // Current user isn't authorized. - let another_user = mock_user_with_id(2)?; + let another_user = mock_user_with_id(uuid!("00000000-0000-0000-0000-000000000002"))?; users.upsert(&another_user).await?; let extracted_user = extract_user( &api, diff --git a/src/server/handlers/webhooks_responders.rs b/src/server/handlers/webhooks_responders.rs index cee307b..aa99218 100644 --- a/src/server/handlers/webhooks_responders.rs +++ b/src/server/handlers/webhooks_responders.rs @@ -366,12 +366,12 @@ mod tests { .await?; let request = TestRequest::with_uri( - "https://secutils.dev/api/webhooks/dev-handle-1/one/two?query=value", + "https://secutils.dev/api/webhooks/dev-handle-00000000-0000-0000-0000-000000000001/one/two?query=value", ) .method(Method::PUT) .insert_header(("x-key", "x-value")) .insert_header(("x-key-2", "x-value-2")) - .param("user_handle", "dev-handle-1") + .param("user_handle", "dev-handle-00000000-0000-0000-0000-000000000001") .param("responder_path", "one/two") .to_http_request(); let path = web::Path::::from_request(&request, &mut Payload::None) @@ -468,9 +468,9 @@ mod tests { .await?; let request = - TestRequest::with_uri("https://dev-handle-1.webhooks.secutils.dev/one/two?query=value") + TestRequest::with_uri("https://dev-handle-00000000-0000-0000-0000-000000000001.webhooks.secutils.dev/one/two?query=value") .insert_header(("x-replaced-path", "/one/two")) - .insert_header(("x-forwarded-host", "dev-handle-1.webhooks.secutils.dev")) + .insert_header(("x-forwarded-host", "dev-handle-00000000-0000-0000-0000-000000000001.webhooks.secutils.dev")) .to_http_request(); let path = web::Path::::from_request(&request, &mut Payload::None) .await @@ -538,10 +538,15 @@ mod tests { }) .await?; - let request = TestRequest::with_uri("https://dev-handle-1.webhooks.secutils.dev") - .insert_header(("x-replaced-path", "/")) - .insert_header(("x-forwarded-host", "dev-handle-1.webhooks.secutils.dev")) - .to_http_request(); + let request = TestRequest::with_uri( + "https://dev-handle-00000000-0000-0000-0000-000000000001.webhooks.secutils.dev", + ) + .insert_header(("x-replaced-path", "/")) + .insert_header(( + "x-forwarded-host", + "dev-handle-00000000-0000-0000-0000-000000000001.webhooks.secutils.dev", + )) + .to_http_request(); let path = web::Path::::from_request(&request, &mut Payload::None) .await .unwrap(); @@ -607,9 +612,9 @@ mod tests { .await?; let request = - TestRequest::with_uri("https://dev-handle-1.webhooks.secutils.dev/one/two?query=some") + TestRequest::with_uri("https://dev-handle-00000000-0000-0000-0000-000000000001.webhooks.secutils.dev/one/two?query=some") .insert_header(("x-replaced-path", "/one/two")) - .insert_header(("x-forwarded-host", "dev-handle-1.webhooks.secutils.dev")) + .insert_header(("x-forwarded-host", "dev-handle-00000000-0000-0000-0000-000000000001.webhooks.secutils.dev")) .peer_addr("127.0.0.1:8080".parse()?) .to_http_request(); let path = web::Path::::from_request(&request, &mut Payload::None) @@ -631,7 +636,7 @@ mod tests { Response HTTP/1.1 300 Multiple Choices headers: "one": "two" - body: Sized(247) + body: Sized(282) , } "###); @@ -644,7 +649,7 @@ mod tests { "method": "GET", "headers": { "x-replaced-path": "/one/two", - "x-forwarded-host": "dev-handle-1.webhooks.secutils.dev", + "x-forwarded-host": "dev-handle-00000000-0000-0000-0000-000000000001.webhooks.secutils.dev", }, "path": "/one/two", "query": { @@ -669,9 +674,9 @@ mod tests { pool: PgPool, ) -> anyhow::Result<()> { let request = - TestRequest::with_uri("https://dev-handle-1.webhooks.secutils.dev/one/two?query=value") + TestRequest::with_uri("https://dev-handle-00000000-0000-0000-0000-000000000001.webhooks.secutils.dev/one/two?query=value") .insert_header(("x-replaced-path", "/one/two")) - .insert_header(("x-forwarded-host", "dev-handle-1.webhooks.secutils.dev")) + .insert_header(("x-forwarded-host", "dev-handle-00000000-0000-0000-0000-000000000001.webhooks.secutils.dev")) .to_http_request(); let app_state = mock_app_state(pool).await?; let app_state = web::Data::new(app_state); diff --git a/src/server/ui_state.rs b/src/server/ui_state.rs index 0818f5e..2e54fdc 100644 --- a/src/server/ui_state.rs +++ b/src/server/ui_state.rs @@ -46,7 +46,7 @@ mod tests { WebhookUrlType, }, tests::{mock_config, mock_user}, - users::{ClientUserShare, SharedResource, UserId, UserShare, UserShareId}, + users::{ClientUserShare, SharedResource, UserShare, UserShareId}, utils::Util, }; @@ -70,7 +70,7 @@ mod tests { }), user_share: Some(ClientUserShare::from(UserShare { id: UserShareId::from(uuid!("00000000-0000-0000-0000-000000000001")), - user_id: UserId::default(), + user_id: uuid!("00000000-0000-0000-0000-000000000002").into(), resource: SharedResource::content_security_policy(uuid!( "00000000-0000-0000-0000-000000000001" )), @@ -97,8 +97,8 @@ mod tests { "level": "available" }, "user": { - "email": "dev-1@secutils.dev", - "handle": "dev-handle-1", + "email": "dev-00000000-0000-0000-0000-000000000001@secutils.dev", + "handle": "dev-handle-00000000-0000-0000-0000-000000000001", "credentials": { "password": true, "passkey": false diff --git a/src/users/api_ext.rs b/src/users/api_ext.rs index 119eafb..e573e4e 100644 --- a/src/users/api_ext.rs +++ b/src/users/api_ext.rs @@ -43,7 +43,7 @@ impl<'a, DR: DnsResolver, ET: EmailTransport> UsersApi<'a, DR, ET> { } /// Inserts or updates user in the `Users` store. - pub async fn upsert>(&self, user: U) -> anyhow::Result { + pub async fn upsert>(&self, user: U) -> anyhow::Result<()> { self.api.db.upsert_user(user).await } @@ -63,7 +63,7 @@ impl<'a, DR: DnsResolver, ET: EmailTransport> UsersApi<'a, DR, ET> { }, }, None => User { - id: UserId::default(), + id: UserId::new(), email: builtin_user.email, handle: builtin_user.handle, credentials: builtin_user.credentials, @@ -79,7 +79,9 @@ impl<'a, DR: DnsResolver, ET: EmailTransport> UsersApi<'a, DR, ET> { }, }; - self.upsert(&user).await + self.upsert(&user).await?; + + Ok(user.id) } /// Removes the user with the specified email. diff --git a/src/users/database_ext.rs b/src/users/database_ext.rs index 3f027eb..b783e4c 100644 --- a/src/users/database_ext.rs +++ b/src/users/database_ext.rs @@ -1,12 +1,8 @@ mod raw_user; mod raw_user_data; mod raw_user_share; -mod raw_user_to_upsert; -use self::{ - raw_user::RawUser, raw_user_data::RawUserData, raw_user_share::RawUserShare, - raw_user_to_upsert::RawUserToUpsert, -}; +use self::{raw_user::RawUser, raw_user_data::RawUserData, raw_user_share::RawUserShare}; use crate::{ database::Database, users::{SharedResource, User, UserData, UserDataKey, UserId, UserShare, UserShareId}, @@ -102,25 +98,25 @@ WHERE u.handle = $1 } /// Inserts user to the `Users` tables, fails if user already exists. - pub async fn insert_user>(&self, user: U) -> anyhow::Result { - let raw_user = RawUserToUpsert::try_from(user.as_ref())?; + pub async fn insert_user>(&self, user: U) -> anyhow::Result<()> { + let raw_user = RawUser::try_from(user.as_ref())?; let tx = self.pool.begin().await?; // Insert user. - let user_id = query_scalar!( + query!( r#" -INSERT INTO users (email, handle, credentials, created, activated) -VALUES ( $1, $2, $3, $4, $5 ) -RETURNING id +INSERT INTO users (id, email, handle, credentials, created, activated) +VALUES ( $1, $2, $3, $4, $5, $6 ) "#, - raw_user.email, - raw_user.handle, + raw_user.id, + &raw_user.email, + &raw_user.handle, raw_user.credentials, raw_user.created, raw_user.activated ) - .fetch_one(&self.pool) + .execute(&self.pool) .await?; // Insert user subscription. @@ -129,7 +125,7 @@ RETURNING id INSERT INTO user_subscriptions (user_id, tier, started_at, ends_at, trial_started_at, trial_ends_at) VALUES ( $1, $2, $3, $4, $5, $6 ) "#, - user_id, + raw_user.id, raw_user.subscription_tier, raw_user.subscription_started_at, raw_user.subscription_ends_at, @@ -139,31 +135,29 @@ VALUES ( $1, $2, $3, $4, $5, $6 ) .execute(&self.pool) .await?; - tx.commit().await?; - - user_id.try_into() + Ok(tx.commit().await?) } /// Inserts or updates user in the `Users` table. - pub async fn upsert_user>(&self, user: U) -> anyhow::Result { - let raw_user = RawUserToUpsert::try_from(user.as_ref())?; + pub async fn upsert_user>(&self, user: U) -> anyhow::Result<()> { + let raw_user = RawUser::try_from(user.as_ref())?; let tx = self.pool.begin().await?; // Update user - let user_id = query_scalar!(r#" -INSERT INTO users (email, handle, credentials, created, activated) -VALUES ( $1, $2, $3, $4, $5 ) -ON CONFLICT(email) DO UPDATE SET handle=excluded.handle, credentials=excluded.credentials, created=excluded.created, activated=excluded.activated -RETURNING id + query!(r#" +INSERT INTO users (id, email, handle, credentials, created, activated) +VALUES ( $1, $2, $3, $4, $5, $6 ) +ON CONFLICT(id) DO UPDATE SET email=excluded.email, handle=excluded.handle, credentials=excluded.credentials, created=excluded.created, activated=excluded.activated "#, - raw_user.email, - raw_user.handle, + raw_user.id, + &raw_user.email, + &raw_user.handle, raw_user.credentials, raw_user.created, raw_user.activated ) - .fetch_one(&self.pool) + .execute(&self.pool) .await?; // Update user subscription. @@ -173,7 +167,7 @@ INSERT INTO user_subscriptions (user_id, tier, started_at, ends_at, trial_starte VALUES ( $1, $2, $3, $4, $5, $6 ) ON CONFLICT(user_id) DO UPDATE SET tier=excluded.tier, started_at=excluded.started_at, ends_at=excluded.ends_at, trial_started_at=excluded.trial_started_at, trial_ends_at=excluded.trial_ends_at "#, - user_id, + raw_user.id, raw_user.subscription_tier, raw_user.subscription_started_at, raw_user.subscription_ends_at, @@ -183,9 +177,7 @@ ON CONFLICT(user_id) DO UPDATE SET tier=excluded.tier, started_at=excluded.start .execute(&self.pool) .await?; - tx.commit().await?; - - user_id.try_into() + Ok(tx.commit().await?) } /// Removes user with the specified email from the `Users` table. @@ -194,18 +186,17 @@ ON CONFLICT(user_id) DO UPDATE SET tier=excluded.tier, started_at=excluded.start email: T, ) -> anyhow::Result> { let email = email.as_ref(); - query_scalar!( + Ok(query_scalar!( r#" DELETE FROM users WHERE email = $1 -RETURNING id as "id!" +RETURNING id "#, email ) .fetch_optional(&self.pool) .await? - .map(UserId::try_from) - .transpose() + .map(UserId::from)) } /// Retrieves user data from the `UserData` table using user id and data key. @@ -417,7 +408,7 @@ mod tests { let users = vec![ MockUserBuilder::new( - UserId::default(), + uuid!("00000000-0000-0000-0000-000000000001").into(), "dev@secutils.dev", "dev-handle", StoredCredentials { @@ -430,7 +421,7 @@ mod tests { .set_activated() .build(), MockUserBuilder::new( - UserId::default(), + uuid!("00000000-0000-0000-0000-000000000002").into(), "prod@secutils.dev", "prod-handle", StoredCredentials { @@ -449,7 +440,7 @@ mod tests { }) .build(), MockUserBuilder::new( - UserId::default(), + uuid!("00000000-0000-0000-0000-000000000003").into(), "user@secutils.dev", "handle", StoredCredentials { @@ -472,13 +463,16 @@ mod tests { db.upsert_user(&user).await?; } - let user_by_id = db.get_user(1.try_into()?).await?.unwrap(); + let user_by_id = db + .get_user(uuid!("00000000-0000-0000-0000-000000000001").into()) + .await? + .unwrap(); let user_by_email = db.get_user_by_email("dev@secutils.dev").await?.unwrap(); assert_eq!(user_by_id.id, user_by_email.id); assert_debug_snapshot!(user_by_email, @r###" User { id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), email: "dev@secutils.dev", handle: "dev-handle", @@ -500,13 +494,16 @@ mod tests { } "###); - let user_by_id = db.get_user(2.try_into()?).await?.unwrap(); + let user_by_id = db + .get_user(uuid!("00000000-0000-0000-0000-000000000002").into()) + .await? + .unwrap(); let user_by_email = db.get_user_by_email("prod@secutils.dev").await?.unwrap(); assert_eq!(user_by_id.id, user_by_email.id); assert_debug_snapshot!(user_by_email, @r###" User { id: UserId( - 2, + 00000000-0000-0000-0000-000000000002, ), email: "prod@secutils.dev", handle: "prod-handle", @@ -528,13 +525,16 @@ mod tests { } "###); - let user_by_id = db.get_user(3.try_into()?).await?.unwrap(); + let user_by_id = db + .get_user(uuid!("00000000-0000-0000-0000-000000000003").into()) + .await? + .unwrap(); let user_by_email = db.get_user_by_email("user@secutils.dev").await?.unwrap(); assert_eq!(user_by_id.id, user_by_email.id); assert_debug_snapshot!(user_by_email, @r###" User { id: UserId( - 3, + 00000000-0000-0000-0000-000000000003, ), email: "user@secutils.dev", handle: "handle", @@ -573,7 +573,7 @@ mod tests { #[sqlx::test] async fn ignores_email_case(pool: PgPool) -> anyhow::Result<()> { let user = MockUserBuilder::new( - UserId::default(), + uuid!("00000000-0000-0000-0000-000000000001").into(), "DeV@secutils.dev", "DeV-handle", StoredCredentials { @@ -593,13 +593,13 @@ mod tests { .set_activated() .build(); let db = Database::create(pool).await?; - let id = db.upsert_user(&user).await?; + db.upsert_user(&user).await?; assert_debug_snapshot!(db.get_user_by_email("dev@secutils.dev").await?, @r###" Some( User { id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), email: "DeV@secutils.dev", handle: "DeV-handle", @@ -623,11 +623,11 @@ mod tests { "###); assert_eq!( db.get_user_by_email("DEV@secutils.dev").await?.unwrap().id, - id + user.id ); assert_eq!( db.get_user_by_email("DeV@secutils.dev").await?.unwrap().id, - id + user.id ); Ok(()) @@ -636,7 +636,7 @@ mod tests { #[sqlx::test] async fn ignores_handle_case(pool: PgPool) -> anyhow::Result<()> { let user = MockUserBuilder::new( - UserId::default(), + uuid!("00000000-0000-0000-0000-000000000001").into(), "DeV@secutils.dev", "DeV-handle", StoredCredentials { @@ -656,13 +656,13 @@ mod tests { }) .build(); let db = Database::create(pool).await?; - let id = db.upsert_user(&user).await?; + db.upsert_user(&user).await?; assert_debug_snapshot!(db.get_user_by_handle("dev-handle").await?, @r###" Some( User { id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), email: "DeV@secutils.dev", handle: "DeV-handle", @@ -684,8 +684,14 @@ mod tests { }, ) "###); - assert_eq!(db.get_user_by_handle("DEV-handle").await?.unwrap().id, id); - assert_eq!(db.get_user_by_handle("DeV-handle").await?.unwrap().id, id); + assert_eq!( + db.get_user_by_handle("DEV-handle").await?.unwrap().id, + user.id + ); + assert_eq!( + db.get_user_by_handle("DeV-handle").await?.unwrap().id, + user.id + ); Ok(()) } @@ -694,28 +700,25 @@ mod tests { async fn can_insert_user(pool: PgPool) -> anyhow::Result<()> { let db = Database::create(pool).await?; - let user_id = db - .insert_user( - &MockUserBuilder::new( - UserId::default(), - "dev@secutils.dev", - "dev-handle", - StoredCredentials { - password_hash: Some("hash".to_string()), - ..Default::default() - }, - // January 1, 2000 11:00:00 - OffsetDateTime::from_unix_timestamp(946720800)?, - ) - .set_activated() - .build(), - ) - .await?; + let user = MockUserBuilder::new( + uuid!("00000000-0000-0000-0000-000000000001").into(), + "dev@secutils.dev", + "dev-handle", + StoredCredentials { + password_hash: Some("hash".to_string()), + ..Default::default() + }, + // January 1, 2000 11:00:00 + OffsetDateTime::from_unix_timestamp(946720800)?, + ) + .set_activated() + .build(); + db.insert_user(&user).await?; assert_debug_snapshot!(db.get_user_by_email("dev@secutils.dev").await?, @r###" Some( User { id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), email: "dev@secutils.dev", handle: "dev-handle", @@ -741,7 +744,7 @@ mod tests { let conflict_error = to_database_error( db.insert_user( &MockUserBuilder::new( - 100.try_into()?, + uuid!("00000000-0000-0000-0000-000000000100").into(), "DEV@secutils.dev", "DEV-handle", StoredCredentials { @@ -760,7 +763,7 @@ mod tests { assert_eq!( db.get_user_by_email("dev@secutils.dev").await?.unwrap().id, - user_id + user.id ); Ok(()) @@ -772,7 +775,7 @@ mod tests { db.upsert_user( &MockUserBuilder::new( - UserId::default(), + uuid!("00000000-0000-0000-0000-000000000001").into(), "dev@secutils.dev", "dev-handle", StoredCredentials { @@ -790,7 +793,7 @@ mod tests { Some( User { id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), email: "dev@secutils.dev", handle: "dev-handle", @@ -815,7 +818,7 @@ mod tests { db.upsert_user( &MockUserBuilder::new( - 100.try_into()?, + uuid!("00000000-0000-0000-0000-000000000001").into(), "DEV@secutils.dev", "DEV-handle", StoredCredentials { @@ -839,9 +842,9 @@ mod tests { Some( User { id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), - email: "dev@secutils.dev", + email: "DEV@secutils.dev", handle: "DEV-handle", credentials: StoredCredentials { password_hash: Some( @@ -877,7 +880,7 @@ mod tests { assert!(db.get_user_by_email("prod@secutils.dev").await?.is_none()); let user_dev = MockUserBuilder::new( - UserId::default(), + UserId::new(), "dev@secutils.dev", "dev-handle", StoredCredentials { @@ -890,7 +893,7 @@ mod tests { .set_activated() .build(); let user_prod = MockUserBuilder::new( - UserId::default(), + UserId::new(), "prod@secutils.dev", "prod-handle", StoredCredentials { @@ -902,32 +905,32 @@ mod tests { ) .build(); - let dev_user_id = db.upsert_user(&user_dev).await?; - let prod_user_id = db.upsert_user(&user_prod).await?; + db.upsert_user(&user_dev).await?; + db.upsert_user(&user_prod).await?; assert_eq!( db.get_user_by_email("dev@secutils.dev").await?.unwrap().id, - dev_user_id + user_dev.id ); assert_eq!( db.get_user_by_email("prod@secutils.dev").await?.unwrap().id, - prod_user_id + user_prod.id ); assert_eq!( db.remove_user_by_email("dev@secutils.dev").await?.unwrap(), - dev_user_id + user_dev.id ); assert!(db.get_user_by_email("dev@secutils.dev").await?.is_none()); assert!(db.remove_user_by_email("dev@secutils.dev").await?.is_none()); assert_eq!( db.get_user_by_email("prod@secutils.dev").await?.unwrap().id, - prod_user_id + user_prod.id ); assert_eq!( db.remove_user_by_email("prod@secutils.dev").await?.unwrap(), - prod_user_id + user_prod.id ); assert!(db.get_user_by_email("prod@secutils.dev").await?.is_none()); assert!(db @@ -942,7 +945,7 @@ mod tests { async fn can_manipulate_user_data(pool: PgPool) -> anyhow::Result<()> { let db = Database::create(pool).await?; let user = MockUserBuilder::new( - 1.try_into()?, + uuid!("00000000-0000-0000-0000-000000000001").into(), "dev@secutils.dev", "dev-handle", StoredCredentials { @@ -1029,7 +1032,7 @@ mod tests { // Create test users let users = vec![ MockUserBuilder::new( - 1.try_into()?, + uuid!("00000000-0000-0000-0000-000000000001").into(), "dev@secutils.dev", "dev-handle", StoredCredentials { @@ -1041,7 +1044,7 @@ mod tests { .set_activated() .build(), MockUserBuilder::new( - 2.try_into()?, + uuid!("00000000-0000-0000-0000-000000000002").into(), "prod@secutils.dev", "prod-handle", StoredCredentials { @@ -1062,7 +1065,7 @@ mod tests { InternalUserDataNamespace::AccountActivationToken, // January 1, 2000 11:00:00 UserData::new( - 1.try_into()?, + uuid!("00000000-0000-0000-0000-000000000001").into(), "data-1", OffsetDateTime::from_unix_timestamp(946720800)?, ), @@ -1072,7 +1075,7 @@ mod tests { InternalUserDataNamespace::AccountActivationToken, // January 1, 2010 11:00:00 UserData::new( - 2.try_into()?, + uuid!("00000000-0000-0000-0000-000000000002").into(), "data-2", OffsetDateTime::from_unix_timestamp(1262340000)?, ), @@ -1080,12 +1083,12 @@ mod tests { .await?; // Check that data exists. - assert_debug_snapshot!(db.get_user_data::(1.try_into()?, InternalUserDataNamespace::AccountActivationToken) + assert_debug_snapshot!(db.get_user_data::(uuid!("00000000-0000-0000-0000-000000000001").into(), InternalUserDataNamespace::AccountActivationToken) .await?, @r###" Some( UserData { user_id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), key: None, value: "data-1", @@ -1093,12 +1096,12 @@ mod tests { }, ) "###); - assert_debug_snapshot!(db.get_user_data::(2.try_into()?, InternalUserDataNamespace::AccountActivationToken) + assert_debug_snapshot!(db.get_user_data::(uuid!("00000000-0000-0000-0000-000000000002").into(), InternalUserDataNamespace::AccountActivationToken) .await?, @r###" Some( UserData { user_id: UserId( - 2, + 00000000-0000-0000-0000-000000000002, ), key: None, value: "data-2", @@ -1117,14 +1120,14 @@ mod tests { // All data should still stay. assert!(db .get_user_data::( - 1.try_into()?, + uuid!("00000000-0000-0000-0000-000000000001").into(), InternalUserDataNamespace::AccountActivationToken ) .await? .is_some()); assert!(db .get_user_data::( - 2.try_into()?, + uuid!("00000000-0000-0000-0000-000000000002").into(), InternalUserDataNamespace::AccountActivationToken ) .await? @@ -1138,14 +1141,14 @@ mod tests { .await?; assert!(db .get_user_data::( - 1.try_into()?, + uuid!("00000000-0000-0000-0000-000000000001").into(), InternalUserDataNamespace::AccountActivationToken ) .await? .is_none()); assert!(db .get_user_data::( - 2.try_into()?, + uuid!("00000000-0000-0000-0000-000000000002").into(), InternalUserDataNamespace::AccountActivationToken ) .await? @@ -1159,7 +1162,7 @@ mod tests { .await?; assert!(db .get_user_data::( - 2.try_into()?, + uuid!("00000000-0000-0000-0000-000000000002").into(), InternalUserDataNamespace::AccountActivationToken ) .await? @@ -1173,7 +1176,7 @@ mod tests { let user_shares = vec![ UserShare { id: UserShareId::from(uuid!("00000000-0000-0000-0000-000000000001")), - user_id: 1.try_into()?, + user_id: uuid!("00000000-0000-0000-0000-000000000001").into(), resource: SharedResource::content_security_policy(uuid!( "00000000-0000-0000-0000-000000000001" )), @@ -1181,7 +1184,7 @@ mod tests { }, UserShare { id: UserShareId::from(uuid!("00000000-0000-0000-0000-000000000002")), - user_id: 2.try_into()?, + user_id: uuid!("00000000-0000-0000-0000-000000000002").into(), resource: SharedResource::content_security_policy(uuid!( "00000000-0000-0000-0000-000000000002" )), @@ -1190,8 +1193,14 @@ mod tests { ]; let db = Database::create(pool).await?; - db.insert_user(mock_user_with_id(1)?).await?; - db.insert_user(mock_user_with_id(2)?).await?; + db.insert_user(mock_user_with_id(uuid!( + "00000000-0000-0000-0000-000000000001" + ))?) + .await?; + db.insert_user(mock_user_with_id(uuid!( + "00000000-0000-0000-0000-000000000002" + ))?) + .await?; for user_share in user_shares.iter() { assert!(db.get_user_share(user_share.id).await?.is_none()); @@ -1218,7 +1227,7 @@ mod tests { let user_shares = [ UserShare { id: UserShareId::from(uuid!("00000000-0000-0000-0000-000000000001")), - user_id: 1.try_into()?, + user_id: uuid!("00000000-0000-0000-0000-000000000001").into(), resource: SharedResource::content_security_policy(uuid!( "00000000-0000-0000-0000-000000000001" )), @@ -1226,7 +1235,7 @@ mod tests { }, UserShare { id: UserShareId::from(uuid!("00000000-0000-0000-0000-000000000002")), - user_id: 2.try_into()?, + user_id: uuid!("00000000-0000-0000-0000-000000000002").into(), resource: SharedResource::content_security_policy(uuid!( "00000000-0000-0000-0000-000000000002" )), @@ -1235,8 +1244,14 @@ mod tests { ]; let db = Database::create(pool).await?; - db.insert_user(mock_user_with_id(1)?).await?; - db.insert_user(mock_user_with_id(2)?).await?; + db.insert_user(mock_user_with_id(uuid!( + "00000000-0000-0000-0000-000000000001" + ))?) + .await?; + db.insert_user(mock_user_with_id(uuid!( + "00000000-0000-0000-0000-000000000002" + ))?) + .await?; // 1. Insert new user shares. for user_share in user_shares.iter() { @@ -1255,7 +1270,10 @@ mod tests { ); assert!(db - .get_user_share_by_resource(3.try_into()?, &user_shares[0].resource) + .get_user_share_by_resource( + uuid!("00000000-0000-0000-0000-000000000003").into(), + &user_shares[0].resource + ) .await? .is_none()); assert!(db @@ -1276,7 +1294,7 @@ mod tests { let user_shares = vec![ UserShare { id: UserShareId::from(uuid!("00000000-0000-0000-0000-000000000001")), - user_id: 1.try_into()?, + user_id: uuid!("00000000-0000-0000-0000-000000000001").into(), resource: SharedResource::content_security_policy(uuid!( "00000000-0000-0000-0000-000000000001" )), @@ -1284,7 +1302,7 @@ mod tests { }, UserShare { id: UserShareId::from(uuid!("00000000-0000-0000-0000-000000000002")), - user_id: 2.try_into()?, + user_id: uuid!("00000000-0000-0000-0000-000000000002").into(), resource: SharedResource::content_security_policy(uuid!( "00000000-0000-0000-0000-000000000002" )), @@ -1293,8 +1311,14 @@ mod tests { ]; let db = Database::create(pool).await?; - db.insert_user(mock_user_with_id(1)?).await?; - db.insert_user(mock_user_with_id(2)?).await?; + db.insert_user(mock_user_with_id(uuid!( + "00000000-0000-0000-0000-000000000001" + ))?) + .await?; + db.insert_user(mock_user_with_id(uuid!( + "00000000-0000-0000-0000-000000000002" + ))?) + .await?; for user_share in user_shares.iter() { assert!(db.get_user_share(user_share.id).await?.is_none()); diff --git a/src/users/database_ext/raw_user.rs b/src/users/database_ext/raw_user.rs index 838b7a6..57f52c9 100644 --- a/src/users/database_ext/raw_user.rs +++ b/src/users/database_ext/raw_user.rs @@ -1,30 +1,32 @@ use crate::users::{User, UserSubscription}; use anyhow::Context; +use std::borrow::Cow; use time::OffsetDateTime; +use uuid::Uuid; #[derive(Debug, Eq, PartialEq, Clone)] -pub(super) struct RawUser { - pub id: i32, - pub email: String, - pub handle: String, +pub(super) struct RawUser<'s> { + pub id: Uuid, + pub email: Cow<'s, str>, + pub handle: Cow<'s, str>, pub credentials: Vec, pub created: OffsetDateTime, pub activated: bool, - pub subscription_tier: i64, + pub subscription_tier: i32, pub subscription_started_at: OffsetDateTime, pub subscription_ends_at: Option, pub subscription_trial_started_at: Option, pub subscription_trial_ends_at: Option, } -impl TryFrom for User { +impl<'u> TryFrom> for User { type Error = anyhow::Error; fn try_from(raw_user: RawUser) -> Result { Ok(User { - id: raw_user.id.try_into()?, - email: raw_user.email, - handle: raw_user.handle, + id: raw_user.id.into(), + email: raw_user.email.into_owned(), + handle: raw_user.handle.into_owned(), credentials: serde_json::from_slice(raw_user.credentials.as_slice()) .with_context(|| "Cannot deserialize user credentials".to_string())?, created: raw_user.created, @@ -40,22 +42,47 @@ impl TryFrom for User { } } +impl<'u> TryFrom<&'u User> for RawUser<'u> { + type Error = anyhow::Error; + + fn try_from(user: &'u User) -> Result { + Ok(Self { + id: *user.id, + email: Cow::Borrowed(user.email.as_ref()), + handle: Cow::Borrowed(user.handle.as_ref()), + credentials: serde_json::ser::to_vec(&user.credentials).with_context(|| { + format!("Failed to serialize user credentials ({}).", user.handle) + })?, + created: user.created, + activated: user.activated, + subscription_tier: user.subscription.tier as i32, + subscription_started_at: user.subscription.started_at, + subscription_ends_at: user.subscription.ends_at, + subscription_trial_started_at: user.subscription.trial_started_at, + subscription_trial_ends_at: user.subscription.trial_ends_at, + }) + } +} + #[cfg(test)] mod tests { use super::RawUser; use crate::{ security::StoredCredentials, - users::{SubscriptionTier, User}, + tests::MockUserBuilder, + users::{SubscriptionTier, User, UserSubscription}, }; use insta::assert_debug_snapshot; + use std::borrow::Cow; use time::OffsetDateTime; + use uuid::uuid; #[test] - fn can_convert_into_user() -> anyhow::Result<()> { + fn can_convert_raw_user_into_user() -> anyhow::Result<()> { assert_debug_snapshot!(User::try_from(RawUser { - id: 1, - email: "dev@secutils.dev".to_string(), - handle: "dev-handle".to_string(), + id: uuid!("00000000-0000-0000-0000-000000000001"), + email: Cow::Borrowed("dev@secutils.dev"), + handle: Cow::Borrowed("dev-handle"), credentials: serde_json::to_vec(&StoredCredentials { password_hash: Some("password-hash".to_string()), ..Default::default() @@ -63,7 +90,7 @@ mod tests { // January 1, 2000 11:00:00 created: OffsetDateTime::from_unix_timestamp(946720800)?, activated: true, - subscription_tier: SubscriptionTier::Ultimate as i64, + subscription_tier: SubscriptionTier::Ultimate as i32, // January 1, 2000 11:00:01 subscription_started_at: OffsetDateTime::from_unix_timestamp(946720801)?, subscription_ends_at: None, @@ -72,7 +99,7 @@ mod tests { })?, @r###" User { id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), email: "dev@secutils.dev", handle: "dev-handle", @@ -95,9 +122,9 @@ mod tests { "###); assert_debug_snapshot!(User::try_from(RawUser { - id: 1, - email: "dev@secutils.dev".to_string(), - handle: "dev-handle".to_string(), + id: uuid!("00000000-0000-0000-0000-000000000001"), + email: Cow::Borrowed("dev@secutils.dev"), + handle: Cow::Borrowed("dev-handle"), credentials: serde_json::to_vec(&StoredCredentials { password_hash: Some("password-hash".to_string()), ..Default::default() @@ -105,7 +132,7 @@ mod tests { // January 1, 2000 11:00:00 created: OffsetDateTime::from_unix_timestamp(946720800)?, activated: true, - subscription_tier: SubscriptionTier::Professional as i64, + subscription_tier: SubscriptionTier::Professional as i32, // January 1, 2000 11:00:01 subscription_started_at: OffsetDateTime::from_unix_timestamp(946720801)?, subscription_ends_at: Some(OffsetDateTime::from_unix_timestamp(946720802)?), @@ -114,7 +141,7 @@ mod tests { })?, @r###" User { id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), email: "dev@secutils.dev", handle: "dev-handle", @@ -145,16 +172,105 @@ mod tests { Ok(()) } + #[test] + fn can_convert_user_into_raw_user() -> anyhow::Result<()> { + assert_eq!( + RawUser::try_from( + &MockUserBuilder::new( + uuid!("00000000-0000-0000-0000-000000000001").into(), + "dev@secutils.dev".to_string(), + "dev-handle".to_string(), + StoredCredentials { + password_hash: Some("password-hash".to_string()), + ..Default::default() + }, + OffsetDateTime::from_unix_timestamp(946720800)?, + ) + .build() + )?, + RawUser { + id: uuid!("00000000-0000-0000-0000-000000000001"), + email: Cow::Borrowed("dev@secutils.dev"), + handle: Cow::Borrowed("dev-handle"), + credentials: serde_json::to_vec(&StoredCredentials { + password_hash: Some("password-hash".to_string()), + ..Default::default() + }) + .unwrap(), + // January 1, 2000 11:00:00 + created: OffsetDateTime::from_unix_timestamp(946720800)?, + subscription_tier: 100, + // January 1, 2000 11:00:01 + subscription_started_at: OffsetDateTime::from_unix_timestamp(946720801)?, + subscription_ends_at: None, + subscription_trial_started_at: None, + subscription_trial_ends_at: None, + activated: false, + } + ); + + Ok(()) + } + + #[test] + fn can_convert_user_into_raw_user_with_custom_subscription() -> anyhow::Result<()> { + assert_eq!( + RawUser::try_from( + &MockUserBuilder::new( + uuid!("00000000-0000-0000-0000-000000000001").into(), + "dev@secutils.dev".to_string(), + "dev-handle".to_string(), + StoredCredentials { + password_hash: Some("password-hash".to_string()), + ..Default::default() + }, + OffsetDateTime::from_unix_timestamp(946720800)?, + ) + .set_subscription(UserSubscription { + tier: SubscriptionTier::Standard, + started_at: OffsetDateTime::from_unix_timestamp(946720801)?, + ends_at: Some(OffsetDateTime::from_unix_timestamp(946720802)?), + trial_started_at: Some(OffsetDateTime::from_unix_timestamp(946720803)?), + trial_ends_at: Some(OffsetDateTime::from_unix_timestamp(946720804)?), + }) + .build() + )?, + RawUser { + id: uuid!("00000000-0000-0000-0000-000000000001"), + email: Cow::Borrowed("dev@secutils.dev"), + handle: Cow::Borrowed("dev-handle"), + credentials: serde_json::to_vec(&StoredCredentials { + password_hash: Some("password-hash".to_string()), + ..Default::default() + }) + .unwrap(), + // January 1, 2000 11:00:00 + created: OffsetDateTime::from_unix_timestamp(946720800)?, + activated: false, + subscription_tier: 20, + // January 1, 2000 11:00:01 + subscription_started_at: OffsetDateTime::from_unix_timestamp(946720801)?, + subscription_ends_at: Some(OffsetDateTime::from_unix_timestamp(946720802)?), + subscription_trial_started_at: Some(OffsetDateTime::from_unix_timestamp( + 946720803 + )?), + subscription_trial_ends_at: Some(OffsetDateTime::from_unix_timestamp(946720804)?), + } + ); + + Ok(()) + } + #[test] fn fails_if_malformed() -> anyhow::Result<()> { assert!(User::try_from(RawUser { - id: 1, - email: "dev@secutils.dev".to_string(), - handle: "dev-handle".to_string(), + id: uuid!("00000000-0000-0000-0000-000000000001"), + email: Cow::Borrowed("dev@secutils.dev"), + handle: Cow::Borrowed("dev-handle"), credentials: vec![1, 2, 3], created: time::Date::MIN.midnight().assume_utc(), activated: true, - subscription_tier: SubscriptionTier::Ultimate as i64, + subscription_tier: SubscriptionTier::Ultimate as i32, subscription_started_at: time::Date::MIN.midnight().assume_utc(), subscription_ends_at: None, subscription_trial_started_at: None, diff --git a/src/users/database_ext/raw_user_data.rs b/src/users/database_ext/raw_user_data.rs index bff1aec..a9cf3c2 100644 --- a/src/users/database_ext/raw_user_data.rs +++ b/src/users/database_ext/raw_user_data.rs @@ -2,10 +2,11 @@ use crate::users::UserData; use anyhow::Context; use serde::{Deserialize, Serialize}; use time::OffsetDateTime; +use uuid::Uuid; #[derive(Debug, Eq, PartialEq, Clone)] pub(super) struct RawUserData { - pub user_id: i32, + pub user_id: Uuid, pub key: Option, pub value: Vec, pub timestamp: OffsetDateTime, @@ -16,7 +17,7 @@ impl Deserialize<'de>> TryFrom for UserData { fn try_from(raw_user_data: RawUserData) -> Result { Ok(UserData { - user_id: raw_user_data.user_id.try_into()?, + user_id: raw_user_data.user_id.into(), key: raw_user_data .key .and_then(|key| if key.is_empty() { None } else { Some(key) }), @@ -44,14 +45,15 @@ impl<'u, V: Serialize> TryFrom<&'u UserData> for RawUserData { #[cfg(test)] mod tests { use super::RawUserData; - use crate::users::{UserData, UserId}; + use crate::users::UserData; use insta::assert_debug_snapshot; use time::OffsetDateTime; + use uuid::uuid; #[test] fn can_convert_into_user_data() -> anyhow::Result<()> { assert_debug_snapshot!(UserData::::try_from(RawUserData { - user_id: 1, + user_id: uuid!("00000000-0000-0000-0000-000000000001"), key: None, value: serde_json::to_vec("hello")?, // January 1, 2000 11:00:00 @@ -59,7 +61,7 @@ mod tests { })?, @r###" UserData { user_id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), key: None, value: "hello", @@ -68,7 +70,7 @@ mod tests { "###); assert_debug_snapshot!(UserData::::try_from(RawUserData { - user_id: 1, + user_id: uuid!("00000000-0000-0000-0000-000000000001"), key: Some("some-key".to_string()), value: serde_json::to_vec("hello")?, // January 1, 2000 11:00:00 @@ -76,7 +78,7 @@ mod tests { })?, @r###" UserData { user_id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), key: Some( "some-key", @@ -87,7 +89,7 @@ mod tests { "###); assert_debug_snapshot!(UserData::::try_from(RawUserData { - user_id: 1, + user_id: uuid!("00000000-0000-0000-0000-000000000001"), key: Some("".to_string()), value: serde_json::to_vec("hello")?, // January 1, 2000 11:00:00 @@ -95,7 +97,7 @@ mod tests { })?, @r###" UserData { user_id: UserId( - 1, + 00000000-0000-0000-0000-000000000001, ), key: None, value: "hello", @@ -110,12 +112,12 @@ mod tests { fn can_convert_into_raw_user_data() -> anyhow::Result<()> { assert_eq!( RawUserData::try_from(&UserData::new( - UserId::default(), + uuid!("00000000-0000-0000-0000-000000000001").into(), "data", OffsetDateTime::from_unix_timestamp(946720800)? ))?, RawUserData { - user_id: *UserId::default(), + user_id: uuid!("00000000-0000-0000-0000-000000000001"), key: None, value: serde_json::to_vec("data")?, // January 1, 2000 11:00:00 diff --git a/src/users/database_ext/raw_user_share.rs b/src/users/database_ext/raw_user_share.rs index 0f782f7..6b99dc6 100644 --- a/src/users/database_ext/raw_user_share.rs +++ b/src/users/database_ext/raw_user_share.rs @@ -5,7 +5,7 @@ use uuid::Uuid; #[derive(Debug, Eq, PartialEq, Clone)] pub(super) struct RawUserShare { pub id: Uuid, - pub user_id: i32, + pub user_id: Uuid, pub resource: Vec, pub created_at: OffsetDateTime, } @@ -16,7 +16,7 @@ impl TryFrom for UserShare { fn try_from(raw_user_share: RawUserShare) -> Result { Ok(UserShare { id: raw_user_share.id.into(), - user_id: raw_user_share.user_id.try_into()?, + user_id: raw_user_share.user_id.into(), resource: postcard::from_bytes(&raw_user_share.resource)?, created_at: raw_user_share.created_at, }) @@ -48,7 +48,7 @@ mod tests { fn can_convert_into_user_share() -> anyhow::Result<()> { assert_debug_snapshot!(UserShare::try_from(RawUserShare { id: uuid!("00000000-0000-0000-0000-000000000001"), - user_id: 1, + user_id: uuid!("00000000-0000-0000-0000-000000000002"), resource: vec![0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // January 1, 2000 10:00:00 created_at: OffsetDateTime::from_unix_timestamp(946720800)?, @@ -58,7 +58,7 @@ mod tests { 00000000-0000-0000-0000-000000000001, ), user_id: UserId( - 1, + 00000000-0000-0000-0000-000000000002, ), resource: ContentSecurityPolicy { policy_id: 00000000-0000-0000-0000-000000000001, @@ -74,14 +74,14 @@ mod tests { fn can_convert_into_raw_user_share() -> anyhow::Result<()> { assert_debug_snapshot!(RawUserShare::try_from(&UserShare { id: uuid!("00000000-0000-0000-0000-000000000001").into(), - user_id: 1.try_into()?, + user_id: uuid!("00000000-0000-0000-0000-000000000002").into(), resource: SharedResource::content_security_policy(uuid!("00000000-0000-0000-0000-000000000001")), // January 1, 2000 10:00:00 created_at: OffsetDateTime::from_unix_timestamp(946720800)?, })?, @r###" RawUserShare { id: 00000000-0000-0000-0000-000000000001, - user_id: 1, + user_id: 00000000-0000-0000-0000-000000000002, resource: [ 0, 16, @@ -113,10 +113,8 @@ mod tests { fn fails_if_malformed() -> anyhow::Result<()> { assert!(UserShare::try_from(RawUserShare { id: uuid!("00000000-0000-0000-0000-000000000001"), - user_id: -1, - resource: postcard::to_stdvec(&SharedResource::content_security_policy(uuid!( - "00000000-0000-0000-0000-000000000001" - )))?, + user_id: uuid!("00000000-0000-0000-0000-000000000002"), + resource: vec![1, 2, 3], // January 1, 2000 10:00:00 created_at: OffsetDateTime::from_unix_timestamp(946720800)?, }) diff --git a/src/users/database_ext/raw_user_to_upsert.rs b/src/users/database_ext/raw_user_to_upsert.rs deleted file mode 100644 index 76c950d..0000000 --- a/src/users/database_ext/raw_user_to_upsert.rs +++ /dev/null @@ -1,136 +0,0 @@ -use crate::users::User; -use anyhow::Context; -use time::OffsetDateTime; - -#[derive(Debug, Eq, PartialEq, Clone)] -pub(super) struct RawUserToUpsert<'a> { - pub email: &'a str, - pub handle: &'a str, - pub credentials: Vec, - pub created: OffsetDateTime, - pub activated: bool, - pub subscription_tier: i32, - pub subscription_started_at: OffsetDateTime, - pub subscription_ends_at: Option, - pub subscription_trial_started_at: Option, - pub subscription_trial_ends_at: Option, -} - -impl<'a> TryFrom<&'a User> for RawUserToUpsert<'a> { - type Error = anyhow::Error; - - fn try_from(user: &'a User) -> Result { - Ok(Self { - email: user.email.as_ref(), - handle: user.handle.as_ref(), - credentials: serde_json::ser::to_vec(&user.credentials).with_context(|| { - format!("Failed to serialize user credentials ({}).", user.handle) - })?, - created: user.created, - activated: user.activated, - subscription_tier: user.subscription.tier as i32, - subscription_started_at: user.subscription.started_at, - subscription_ends_at: user.subscription.ends_at, - subscription_trial_started_at: user.subscription.trial_started_at, - subscription_trial_ends_at: user.subscription.trial_ends_at, - }) - } -} - -#[cfg(test)] -mod tests { - use super::RawUserToUpsert; - use crate::{ - security::StoredCredentials, - tests::MockUserBuilder, - users::{SubscriptionTier, UserSubscription}, - }; - use time::OffsetDateTime; - - #[test] - fn can_convert_into_raw_user_to_upsert() -> anyhow::Result<()> { - assert_eq!( - RawUserToUpsert::try_from( - &MockUserBuilder::new( - 1.try_into()?, - "dev@secutils.dev".to_string(), - "dev-handle".to_string(), - StoredCredentials { - password_hash: Some("password-hash".to_string()), - ..Default::default() - }, - OffsetDateTime::from_unix_timestamp(946720800)?, - ) - .build() - )?, - RawUserToUpsert { - email: "dev@secutils.dev", - handle: "dev-handle", - credentials: serde_json::to_vec(&StoredCredentials { - password_hash: Some("password-hash".to_string()), - ..Default::default() - }) - .unwrap(), - // January 1, 2000 11:00:00 - created: OffsetDateTime::from_unix_timestamp(946720800)?, - subscription_tier: 100, - // January 1, 2000 11:00:01 - subscription_started_at: OffsetDateTime::from_unix_timestamp(946720801)?, - subscription_ends_at: None, - subscription_trial_started_at: None, - subscription_trial_ends_at: None, - activated: false, - } - ); - - Ok(()) - } - - #[test] - fn can_convert_into_raw_user_to_upsert_with_custom_subscription() -> anyhow::Result<()> { - assert_eq!( - RawUserToUpsert::try_from( - &MockUserBuilder::new( - 1.try_into()?, - "dev@secutils.dev".to_string(), - "dev-handle".to_string(), - StoredCredentials { - password_hash: Some("password-hash".to_string()), - ..Default::default() - }, - OffsetDateTime::from_unix_timestamp(946720800)?, - ) - .set_subscription(UserSubscription { - tier: SubscriptionTier::Standard, - started_at: OffsetDateTime::from_unix_timestamp(946720801)?, - ends_at: Some(OffsetDateTime::from_unix_timestamp(946720802)?), - trial_started_at: Some(OffsetDateTime::from_unix_timestamp(946720803)?), - trial_ends_at: Some(OffsetDateTime::from_unix_timestamp(946720804)?), - }) - .build() - )?, - RawUserToUpsert { - email: "dev@secutils.dev", - handle: "dev-handle", - credentials: serde_json::to_vec(&StoredCredentials { - password_hash: Some("password-hash".to_string()), - ..Default::default() - }) - .unwrap(), - // January 1, 2000 11:00:00 - created: OffsetDateTime::from_unix_timestamp(946720800)?, - activated: false, - subscription_tier: 20, - // January 1, 2000 11:00:01 - subscription_started_at: OffsetDateTime::from_unix_timestamp(946720801)?, - subscription_ends_at: Some(OffsetDateTime::from_unix_timestamp(946720802)?), - subscription_trial_started_at: Some(OffsetDateTime::from_unix_timestamp( - 946720803 - )?), - subscription_trial_ends_at: Some(OffsetDateTime::from_unix_timestamp(946720804)?), - } - ); - - Ok(()) - } -} diff --git a/src/users/user.rs b/src/users/user.rs index 01c588c..cf714ef 100644 --- a/src/users/user.rs +++ b/src/users/user.rs @@ -46,11 +46,12 @@ mod tests { }; use insta::assert_json_snapshot; use time::OffsetDateTime; + use uuid::uuid; #[test] fn serialization() -> anyhow::Result<()> { let user_with_password = MockUserBuilder::new( - 1.try_into()?, + uuid!("00000000-0000-0000-0000-000000000001").into(), "my-email", "my-handle", StoredCredentials { @@ -63,7 +64,7 @@ mod tests { .build(); let user_with_passkey = MockUserBuilder::new( - 1.try_into()?, + uuid!("00000000-0000-0000-0000-000000000001").into(), "my-email", "my-handle", StoredCredentials::from_passkey(serde_json::from_str(SERIALIZED_PASSKEY)?), @@ -81,7 +82,7 @@ mod tests { .build(); let user_with_password_and_passkey = MockUserBuilder::new( - 1.try_into()?, + uuid!("00000000-0000-0000-0000-000000000001").into(), "my-email", "my-handle", StoredCredentials { diff --git a/src/users/user_id.rs b/src/users/user_id.rs index 70c2397..61b45e9 100644 --- a/src/users/user_id.rs +++ b/src/users/user_id.rs @@ -1,23 +1,40 @@ use serde::{Deserialize, Serialize}; -use std::ops::Deref; +use std::{ops::Deref, str::FromStr}; +use uuid::Uuid; -#[derive(Serialize, Deserialize, Default, Debug, Eq, PartialEq, Clone, Copy, Hash)] -pub struct UserId(i32); +/// Represents unique identifier of the user. +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone, Copy, Hash)] +pub struct UserId(Uuid); +impl UserId { + /// Creates a new unique user share ID. + #[cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))] + pub fn new() -> Self { + Self(Uuid::new_v4()) + } +} -impl TryFrom for UserId { - type Error = anyhow::Error; +impl From for UserId { + fn from(value: Uuid) -> Self { + Self(value) + } +} - fn try_from(value: i32) -> Result { - if value > 0 { - Ok(Self(value)) - } else { - Err(anyhow::anyhow!("User ID must be greater than 0.")) - } +impl From<&UserId> for Uuid { + fn from(value: &UserId) -> Self { + value.0 + } +} + +impl FromStr for UserId { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(Self(Uuid::parse_str(s)?)) } } impl Deref for UserId { - type Target = i32; + type Target = Uuid; fn deref(&self) -> &Self::Target { &self.0 @@ -27,19 +44,35 @@ impl Deref for UserId { #[cfg(test)] mod tests { use crate::users::UserId; + use uuid::{uuid, Uuid, Version}; #[test] - fn default() { - assert_eq!(*UserId::default(), 0); + fn creation() { + let user_id = UserId::new(); + let underlying_uuid = Uuid::from(&user_id); + assert_eq!(underlying_uuid.get_version(), Some(Version::Random)); + assert!(!underlying_uuid.is_nil()); } #[test] - fn conversion() -> anyhow::Result<()> { - assert_eq!(*UserId::try_from(1)?, 1); - assert_eq!(*UserId::try_from(100)?, 100); + fn conversion() { + assert_eq!( + *UserId::from(uuid!("00000000-0000-0000-0000-000000000001")), + uuid!("00000000-0000-0000-0000-000000000001") + ); - assert!(UserId::try_from(-1).is_err()); - assert!(UserId::try_from(0).is_err()); + assert_eq!( + Uuid::from(&UserId::from(uuid!("00000000-0000-0000-0000-000000000001"))), + uuid!("00000000-0000-0000-0000-000000000001") + ); + } + + #[test] + fn parsing() -> anyhow::Result<()> { + assert_eq!( + "00000000-0000-0000-0000-000000000001".parse::()?, + UserId::from(uuid!("00000000-0000-0000-0000-000000000001")) + ); Ok(()) } diff --git a/src/users/user_share.rs b/src/users/user_share.rs index 08c1312..7a2c715 100644 --- a/src/users/user_share.rs +++ b/src/users/user_share.rs @@ -57,7 +57,7 @@ mod tests { assert_eq!( ClientUserShare::from(UserShare { id: user_share_id, - user_id: UserId::default(), + user_id: UserId::new(), resource: resource.clone(), created_at, }), diff --git a/src/utils/user_share_ext.rs b/src/utils/user_share_ext.rs index 56db84c..5c8b106 100644 --- a/src/utils/user_share_ext.rs +++ b/src/utils/user_share_ext.rs @@ -63,7 +63,7 @@ mod tests { let policy_id = uuid!("00000000-0000-0000-0000-000000000001"); let user_share = UserShare { id: Default::default(), - user_id: UserId::default(), + user_id: UserId::new(), resource: SharedResource::content_security_policy(policy_id), created_at: OffsetDateTime::now_utc(), }; @@ -117,7 +117,7 @@ mod tests { let template_id = uuid!("00000000-0000-0000-0000-000000000001"); let user_share = UserShare { id: Default::default(), - user_id: UserId::default(), + user_id: UserId::new(), resource: SharedResource::certificate_template(template_id), created_at: OffsetDateTime::now_utc(), }; diff --git a/src/utils/web_scraping/database_ext/raw_web_page_tracker.rs b/src/utils/web_scraping/database_ext/raw_web_page_tracker.rs index 16d810e..07cb07e 100644 --- a/src/utils/web_scraping/database_ext/raw_web_page_tracker.rs +++ b/src/utils/web_scraping/database_ext/raw_web_page_tracker.rs @@ -13,7 +13,7 @@ pub(super) struct RawWebPageTracker { pub name: String, pub url: String, pub kind: Vec, - pub user_id: i32, + pub user_id: Uuid, pub job_id: Option, pub job_config: Option>, pub data: Vec, @@ -90,7 +90,7 @@ impl TryFrom for WebPageTracker id: raw.id, name: raw.name, url: raw.url.parse()?, - user_id: raw.user_id.try_into()?, + user_id: raw.user_id.into(), job_id: raw.job_id, job_config, settings: WebPageTrackerSettings { diff --git a/src/utils/webhooks/database_ext.rs b/src/utils/webhooks/database_ext.rs index ab53bd6..6826e1b 100644 --- a/src/utils/webhooks/database_ext.rs +++ b/src/utils/webhooks/database_ext.rs @@ -109,7 +109,7 @@ ORDER BY created_at let result = query!( r#" WITH new_responder(user_id, id, name, path, method, enabled, settings, created_at) AS ( - VALUES ( $1::integer, $2::uuid, $3, $4, $5::bytea, $6::bool, $7::bytea, $8::timestamptz ) + VALUES ( $1::uuid, $2::uuid, $3, $4, $5::bytea, $6::bool, $7::bytea, $8::timestamptz ) ) INSERT INTO user_data_webhooks_responders (user_id, id, name, path, method, enabled, settings, created_at) SELECT * FROM new_responder