Reorganize & implement Authentication view api
This commit is contained in:
12
src/data/.sqlx/query-014cf2ec55142a17047ad7c469685df75ae8e3c95a1a7c6c21be7b5624a82ae1.json
generated
Normal file
12
src/data/.sqlx/query-014cf2ec55142a17047ad7c469685df75ae8e3c95a1a7c6c21be7b5624a82ae1.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "INSERT INTO PackageBases (name, description, created_at, updated_at) VALUES (?, ?, ?, ?)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 4
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "014cf2ec55142a17047ad7c469685df75ae8e3c95a1a7c6c21be7b5624a82ae1"
|
||||
}
|
12
src/data/.sqlx/query-063059de083c42956506d991bc04472929e6b2618ab13eb90e772ad9bd9c1984.json
generated
Normal file
12
src/data/.sqlx/query-063059de083c42956506d991bc04472929e6b2618ab13eb90e772ad9bd9c1984.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Packages SET created_at = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "063059de083c42956506d991bc04472929e6b2618ab13eb90e772ad9bd9c1984"
|
||||
}
|
12
src/data/.sqlx/query-0af939868e37bad5eb9097badeaefca62c247c4b2265a9667c4b33885126c771.json
generated
Normal file
12
src/data/.sqlx/query-0af939868e37bad5eb9097badeaefca62c247c4b2265a9667c4b33885126c771.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE PackageBases SET name = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "0af939868e37bad5eb9097badeaefca62c247c4b2265a9667c4b33885126c771"
|
||||
}
|
84
src/data/.sqlx/query-0bb7353d64231dc12416f5504d94513493670e3f2ae017d87a2f0c3eca045f60.json
generated
Normal file
84
src/data/.sqlx/query-0bb7353d64231dc12416f5504d94513493670e3f2ae017d87a2f0c3eca045f60.json
generated
Normal file
@ -0,0 +1,84 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "SELECT * FROM Users WHERE email = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
|
||||
"max_size": 124
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "email",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "password",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "last_used",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "BINARY",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "0bb7353d64231dc12416f5504d94513493670e3f2ae017d87a2f0c3eca045f60"
|
||||
}
|
12
src/data/.sqlx/query-346beb83d6351740a503b72133a190ac327ae79f6e555def8fec89fcc75fb015.json
generated
Normal file
12
src/data/.sqlx/query-346beb83d6351740a503b72133a190ac327ae79f6e555def8fec89fcc75fb015.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Packages SET version = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "346beb83d6351740a503b72133a190ac327ae79f6e555def8fec89fcc75fb015"
|
||||
}
|
12
src/data/.sqlx/query-389e38e7e0a0b7d9ba667ac148a0a468da889a3455c47325938b819ab41ef4c8.json
generated
Normal file
12
src/data/.sqlx/query-389e38e7e0a0b7d9ba667ac148a0a468da889a3455c47325938b819ab41ef4c8.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "DELETE FROM PackageBases WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "389e38e7e0a0b7d9ba667ac148a0a468da889a3455c47325938b819ab41ef4c8"
|
||||
}
|
12
src/data/.sqlx/query-404747d44ee859e8c967695c29963594bb8273e66c053934ec20d5fc3db9d41e.json
generated
Normal file
12
src/data/.sqlx/query-404747d44ee859e8c967695c29963594bb8273e66c053934ec20d5fc3db9d41e.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "DELETE FROM Users WHERE name = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "404747d44ee859e8c967695c29963594bb8273e66c053934ec20d5fc3db9d41e"
|
||||
}
|
84
src/data/.sqlx/query-68ed36ae997fff190b4b15b80bf24b553d8ac922da251d9e8b8f4e897bab46b0.json
generated
Normal file
84
src/data/.sqlx/query-68ed36ae997fff190b4b15b80bf24b553d8ac922da251d9e8b8f4e897bab46b0.json
generated
Normal file
@ -0,0 +1,84 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "SELECT * FROM Users WHERE name = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
|
||||
"max_size": 124
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "email",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "password",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "last_used",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "BINARY",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "68ed36ae997fff190b4b15b80bf24b553d8ac922da251d9e8b8f4e897bab46b0"
|
||||
}
|
104
src/data/.sqlx/query-695f4b0a4286cf625dc60dc3dfc4a9cd92aaea3ea58ef8702903983cfc32ab47.json
generated
Normal file
104
src/data/.sqlx/query-695f4b0a4286cf625dc60dc3dfc4a9cd92aaea3ea58ef8702903983cfc32ab47.json
generated
Normal file
@ -0,0 +1,104 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "SELECT * FROM Packages WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "package_base",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | UNSIGNED | NO_DEFAULT_VALUE",
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
|
||||
"max_size": 508
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "version",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
|
||||
"max_size": 508
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "description",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "",
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "url",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "",
|
||||
"max_size": 2040
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "flagged_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "BINARY",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "695f4b0a4286cf625dc60dc3dfc4a9cd92aaea3ea58ef8702903983cfc32ab47"
|
||||
}
|
12
src/data/.sqlx/query-7cc4cf73572c0830d1da7b8e621a79a09f3e3d8cfd42d3946bd1fac93838b913.json
generated
Normal file
12
src/data/.sqlx/query-7cc4cf73572c0830d1da7b8e621a79a09f3e3d8cfd42d3946bd1fac93838b913.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Packages SET updated_at = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "7cc4cf73572c0830d1da7b8e621a79a09f3e3d8cfd42d3946bd1fac93838b913"
|
||||
}
|
12
src/data/.sqlx/query-7f06016e9892486c938a5e94c9e5f70903a38ed314235712c28ac5e14d9ac20f.json
generated
Normal file
12
src/data/.sqlx/query-7f06016e9892486c938a5e94c9e5f70903a38ed314235712c28ac5e14d9ac20f.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE PackageBases SET description = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "7f06016e9892486c938a5e94c9e5f70903a38ed314235712c28ac5e14d9ac20f"
|
||||
}
|
64
src/data/.sqlx/query-839cea68f9de889f35a0d0ad0b48b4a0dc1af49f0f0e7bb12238d22a9c37fbbc.json
generated
Normal file
64
src/data/.sqlx/query-839cea68f9de889f35a0d0ad0b48b4a0dc1af49f0f0e7bb12238d22a9c37fbbc.json
generated
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "SELECT * FROM PackageBases WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
|
||||
"max_size": 508
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "description",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "",
|
||||
"max_size": 2040
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "839cea68f9de889f35a0d0ad0b48b4a0dc1af49f0f0e7bb12238d22a9c37fbbc"
|
||||
}
|
12
src/data/.sqlx/query-8af7a0169e934cb82997a1cab04e921f719ed9466c13713fda8736c540d0fa78.json
generated
Normal file
12
src/data/.sqlx/query-8af7a0169e934cb82997a1cab04e921f719ed9466c13713fda8736c540d0fa78.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Users SET updated_at = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8af7a0169e934cb82997a1cab04e921f719ed9466c13713fda8736c540d0fa78"
|
||||
}
|
12
src/data/.sqlx/query-8be76176b46f645095dce3bcbed11134ec0f43504d3a820698282848fd67dbad.json
generated
Normal file
12
src/data/.sqlx/query-8be76176b46f645095dce3bcbed11134ec0f43504d3a820698282848fd67dbad.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Users SET password = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8be76176b46f645095dce3bcbed11134ec0f43504d3a820698282848fd67dbad"
|
||||
}
|
12
src/data/.sqlx/query-8bfaca937858ed1060da5a650f749849d29af3d6345d0e02474abf4d8c78b89d.json
generated
Normal file
12
src/data/.sqlx/query-8bfaca937858ed1060da5a650f749849d29af3d6345d0e02474abf4d8c78b89d.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Packages SET flagged_at = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8bfaca937858ed1060da5a650f749849d29af3d6345d0e02474abf4d8c78b89d"
|
||||
}
|
84
src/data/.sqlx/query-8e3ffe0d11d3eb38cd805771cd133588c0679404a68a8041f414553226abeeb2.json
generated
Normal file
84
src/data/.sqlx/query-8e3ffe0d11d3eb38cd805771cd133588c0679404a68a8041f414553226abeeb2.json
generated
Normal file
@ -0,0 +1,84 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "SELECT * FROM Users WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
|
||||
"max_size": 124
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "email",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "password",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "last_used",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "BINARY",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "8e3ffe0d11d3eb38cd805771cd133588c0679404a68a8041f414553226abeeb2"
|
||||
}
|
12
src/data/.sqlx/query-93ec7d124c9bfa7329478d975614db874788ed297fe2d95275592becb186f942.json
generated
Normal file
12
src/data/.sqlx/query-93ec7d124c9bfa7329478d975614db874788ed297fe2d95275592becb186f942.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE PackageBases SET created_at = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "93ec7d124c9bfa7329478d975614db874788ed297fe2d95275592becb186f942"
|
||||
}
|
104
src/data/.sqlx/query-944eb40633e943a75244dee639fe6efb16919aff7172189c81240cb12462ae58.json
generated
Normal file
104
src/data/.sqlx/query-944eb40633e943a75244dee639fe6efb16919aff7172189c81240cb12462ae58.json
generated
Normal file
@ -0,0 +1,104 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "SELECT * FROM Packages WHERE name = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "package_base",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | UNSIGNED | NO_DEFAULT_VALUE",
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
|
||||
"max_size": 508
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "version",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
|
||||
"max_size": 508
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "description",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "",
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "url",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "",
|
||||
"max_size": 2040
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "flagged_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "BINARY",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW",
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "944eb40633e943a75244dee639fe6efb16919aff7172189c81240cb12462ae58"
|
||||
}
|
12
src/data/.sqlx/query-9be7f66630e64787e55946dff428d28035747b66e57260bc9cd4634a71a037a6.json
generated
Normal file
12
src/data/.sqlx/query-9be7f66630e64787e55946dff428d28035747b66e57260bc9cd4634a71a037a6.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Users SET email = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "9be7f66630e64787e55946dff428d28035747b66e57260bc9cd4634a71a037a6"
|
||||
}
|
12
src/data/.sqlx/query-9fa86328c40ce0469f755efb4876010092b7bc9f240a5d43dc69f9d0b1b5b7ce.json
generated
Normal file
12
src/data/.sqlx/query-9fa86328c40ce0469f755efb4876010092b7bc9f240a5d43dc69f9d0b1b5b7ce.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "DELETE FROM Users WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "9fa86328c40ce0469f755efb4876010092b7bc9f240a5d43dc69f9d0b1b5b7ce"
|
||||
}
|
12
src/data/.sqlx/query-b5814b93236d587957a103e61726b0b9ae811ba6bff0617871e76de3ef0ff662.json
generated
Normal file
12
src/data/.sqlx/query-b5814b93236d587957a103e61726b0b9ae811ba6bff0617871e76de3ef0ff662.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Packages SET url = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "b5814b93236d587957a103e61726b0b9ae811ba6bff0617871e76de3ef0ff662"
|
||||
}
|
12
src/data/.sqlx/query-c1abf048d65d421717f20343bb0ef4fcd78f8571cfe2347c147124763bd17491.json
generated
Normal file
12
src/data/.sqlx/query-c1abf048d65d421717f20343bb0ef4fcd78f8571cfe2347c147124763bd17491.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Packages SET description = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c1abf048d65d421717f20343bb0ef4fcd78f8571cfe2347c147124763bd17491"
|
||||
}
|
12
src/data/.sqlx/query-c2b00adbcb3c35a6ffa6b2bce08a738a9b3cd1ca4aa4c843909c7e14f7ef3e06.json
generated
Normal file
12
src/data/.sqlx/query-c2b00adbcb3c35a6ffa6b2bce08a738a9b3cd1ca4aa4c843909c7e14f7ef3e06.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "DELETE FROM Users WHERE email = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c2b00adbcb3c35a6ffa6b2bce08a738a9b3cd1ca4aa4c843909c7e14f7ef3e06"
|
||||
}
|
12
src/data/.sqlx/query-c8de918b432ce82bc7bf1d09a378f9b092d74c2298ac126f7edbb7d59c536910.json
generated
Normal file
12
src/data/.sqlx/query-c8de918b432ce82bc7bf1d09a378f9b092d74c2298ac126f7edbb7d59c536910.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Packages SET package_base = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c8de918b432ce82bc7bf1d09a378f9b092d74c2298ac126f7edbb7d59c536910"
|
||||
}
|
12
src/data/.sqlx/query-cc8f7e13c6aedf6aa4d6d4fc39db7aa98b84baf911e7f779641c1dc514c676cd.json
generated
Normal file
12
src/data/.sqlx/query-cc8f7e13c6aedf6aa4d6d4fc39db7aa98b84baf911e7f779641c1dc514c676cd.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Users SET last_used = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "cc8f7e13c6aedf6aa4d6d4fc39db7aa98b84baf911e7f779641c1dc514c676cd"
|
||||
}
|
12
src/data/.sqlx/query-cf79e2f6038dddd055d535d2c41dd8dccd1a4e6a763963590c904c25abf33137.json
generated
Normal file
12
src/data/.sqlx/query-cf79e2f6038dddd055d535d2c41dd8dccd1a4e6a763963590c904c25abf33137.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Users SET created_at = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "cf79e2f6038dddd055d535d2c41dd8dccd1a4e6a763963590c904c25abf33137"
|
||||
}
|
12
src/data/.sqlx/query-d289747c7c7fba86e2b66174e2d1546f10e8213d36b6b3cd25016f829e9d731b.json
generated
Normal file
12
src/data/.sqlx/query-d289747c7c7fba86e2b66174e2d1546f10e8213d36b6b3cd25016f829e9d731b.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE PackageBases SET updated_at = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "d289747c7c7fba86e2b66174e2d1546f10e8213d36b6b3cd25016f829e9d731b"
|
||||
}
|
12
src/data/.sqlx/query-d474dd848d0ef8832afd4d1302fa562a3c4a4569032e8636d664043b5dc96661.json
generated
Normal file
12
src/data/.sqlx/query-d474dd848d0ef8832afd4d1302fa562a3c4a4569032e8636d664043b5dc96661.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "DELETE FROM Packages WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "d474dd848d0ef8832afd4d1302fa562a3c4a4569032e8636d664043b5dc96661"
|
||||
}
|
12
src/data/.sqlx/query-daf98e6f1013c4993f7329f6fa690e92bccd89d1ff90131719c40626088dabd1.json
generated
Normal file
12
src/data/.sqlx/query-daf98e6f1013c4993f7329f6fa690e92bccd89d1ff90131719c40626088dabd1.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "INSERT INTO Users (name, email, password, last_used, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 6
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "daf98e6f1013c4993f7329f6fa690e92bccd89d1ff90131719c40626088dabd1"
|
||||
}
|
12
src/data/.sqlx/query-dfc2574c39f3f5a9afc1bdb642d8bf8a5ce85e7f84fa0dadb53c88cce63e5634.json
generated
Normal file
12
src/data/.sqlx/query-dfc2574c39f3f5a9afc1bdb642d8bf8a5ce85e7f84fa0dadb53c88cce63e5634.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "INSERT INTO Packages (package_base, name, version, description, url, flagged_at, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 8
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "dfc2574c39f3f5a9afc1bdb642d8bf8a5ce85e7f84fa0dadb53c88cce63e5634"
|
||||
}
|
12
src/data/.sqlx/query-e8ee44281a87c6e7147332dd5548971cb804a1ab1edcdae8bf009ac39059c2bb.json
generated
Normal file
12
src/data/.sqlx/query-e8ee44281a87c6e7147332dd5548971cb804a1ab1edcdae8bf009ac39059c2bb.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Packages SET name = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "e8ee44281a87c6e7147332dd5548971cb804a1ab1edcdae8bf009ac39059c2bb"
|
||||
}
|
12
src/data/.sqlx/query-f4963ad77bcbc0af4fc929f1f66b7ee842c26c44da32ae9bbbc06c466a908ccf.json
generated
Normal file
12
src/data/.sqlx/query-f4963ad77bcbc0af4fc929f1f66b7ee842c26c44da32ae9bbbc06c466a908ccf.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "DELETE FROM Packages WHERE name = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "f4963ad77bcbc0af4fc929f1f66b7ee842c26c44da32ae9bbbc06c466a908ccf"
|
||||
}
|
12
src/data/.sqlx/query-f656bd1abb82c10af4e0e21b4a04a364988f5329356282f2ae0098dbfcaec671.json
generated
Normal file
12
src/data/.sqlx/query-f656bd1abb82c10af4e0e21b4a04a364988f5329356282f2ae0098dbfcaec671.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE Users SET name = ? WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "f656bd1abb82c10af4e0e21b4a04a364988f5329356282f2ae0098dbfcaec671"
|
||||
}
|
21
src/data/Cargo.toml
Normal file
21
src/data/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
derive_more = { version = "1.0.0", features = ["deref", "into"] }
|
||||
|
||||
chrono = { version = "0.4.39", default-features = false, features = [
|
||||
"std",
|
||||
"now",
|
||||
] }
|
||||
sqlx = { version = "0.8.3", default-features = false, features = [
|
||||
"mysql",
|
||||
"macros",
|
||||
"chrono",
|
||||
"runtime-tokio",
|
||||
] }
|
||||
|
||||
# thiserror = "2.0.11"
|
||||
# garde = { version = "0.22.0", features = ["email", "url", "derive"] }
|
2
src/data/src/adapter.rs
Normal file
2
src/data/src/adapter.rs
Normal file
@ -0,0 +1,2 @@
|
||||
//! Specific implementations of [`crate::port`]s to plug into other parts of the application.
|
||||
pub mod mysql;
|
4
src/data/src/adapter/mysql.rs
Normal file
4
src/data/src/adapter/mysql.rs
Normal file
@ -0,0 +1,4 @@
|
||||
//! `MySQL` adapters.
|
||||
pub mod base;
|
||||
pub mod package;
|
||||
pub mod user;
|
105
src/data/src/adapter/mysql/base.rs
Normal file
105
src/data/src/adapter/mysql/base.rs
Normal file
@ -0,0 +1,105 @@
|
||||
use crate::Result;
|
||||
use crate::port::base::{Base, BaseRepository, Field, New};
|
||||
|
||||
use chrono::Utc;
|
||||
use sqlx::{Executor, MySql};
|
||||
|
||||
pub struct BaseAdapter;
|
||||
|
||||
impl<E> BaseRepository<E> for BaseAdapter
|
||||
where
|
||||
E: Send,
|
||||
for<'a> &'a E: Executor<'a, Database = MySql>,
|
||||
{
|
||||
}
|
||||
impl<E> crate::port::CRUD<E> for BaseAdapter
|
||||
where
|
||||
E: Send,
|
||||
for<'a> &'a E: Executor<'a, Database = MySql>,
|
||||
{
|
||||
type New = New;
|
||||
type Unique = u64;
|
||||
type Update = Field;
|
||||
type Existing = Base;
|
||||
|
||||
async fn create(connection: &mut E, data: Self::New) -> Result<Self::Existing> {
|
||||
let created_at = Utc::now();
|
||||
let id = sqlx::query!(
|
||||
"INSERT INTO PackageBases (name, description, created_at, updated_at) VALUES (?, ?, ?, ?)",
|
||||
data.name.as_str(),
|
||||
data.description.as_ref(),
|
||||
created_at, created_at,
|
||||
)
|
||||
.execute(&*connection)
|
||||
.await?
|
||||
.last_insert_id();
|
||||
|
||||
Ok(Self::Existing {
|
||||
id,
|
||||
name: data.name.into(),
|
||||
description: data.description.into(),
|
||||
created_at,
|
||||
updated_at: created_at,
|
||||
})
|
||||
}
|
||||
|
||||
async fn read(connection: &E, data: Self::Unique) -> Result<Option<Self::Existing>> {
|
||||
Ok(
|
||||
sqlx::query_as!(Base, "SELECT * FROM PackageBases WHERE id = ?", data)
|
||||
.fetch_optional(connection)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
|
||||
async fn update(
|
||||
connection: &mut E,
|
||||
existing: &mut Self::Existing,
|
||||
data: Self::Update,
|
||||
) -> Result {
|
||||
match &data {
|
||||
Field::Name(name) => {
|
||||
sqlx::query!(
|
||||
"UPDATE PackageBases SET name = ? WHERE id = ?",
|
||||
name.as_str(),
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::Description(description) => {
|
||||
sqlx::query!(
|
||||
"UPDATE PackageBases SET description = ? WHERE id = ?",
|
||||
description.as_ref(),
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::CreatedAt(date_time) => sqlx::query!(
|
||||
"UPDATE PackageBases SET created_at = ? WHERE id = ?",
|
||||
date_time,
|
||||
existing.id
|
||||
),
|
||||
Field::UpdatedAt(date_time) => sqlx::query!(
|
||||
"UPDATE PackageBases SET updated_at = ? WHERE id = ?",
|
||||
date_time,
|
||||
existing.id
|
||||
),
|
||||
}
|
||||
.execute(&*connection)
|
||||
.await?;
|
||||
|
||||
match data {
|
||||
Field::Name(s) => existing.name = s.into(),
|
||||
Field::Description(o) => existing.description = o.into(),
|
||||
Field::CreatedAt(date_time) => existing.created_at = date_time,
|
||||
Field::UpdatedAt(date_time) => existing.updated_at = date_time,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete(connection: &mut E, data: Self::Unique) -> Result {
|
||||
sqlx::query!("DELETE FROM PackageBases WHERE id = ?", data)
|
||||
.execute(&*connection)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
162
src/data/src/adapter/mysql/package.rs
Normal file
162
src/data/src/adapter/mysql/package.rs
Normal file
@ -0,0 +1,162 @@
|
||||
use crate::Result;
|
||||
use crate::port::package::{Field, New, Package, PackageRepository, Unique};
|
||||
|
||||
use chrono::Utc;
|
||||
use sqlx::{Executor, MySql};
|
||||
|
||||
pub struct PackageAdapter;
|
||||
|
||||
impl<E> PackageRepository<E> for PackageAdapter
|
||||
where
|
||||
E: Send,
|
||||
for<'a> &'a E: Executor<'a, Database = MySql>,
|
||||
{
|
||||
}
|
||||
impl<E> crate::port::CRUD<E> for PackageAdapter
|
||||
where
|
||||
E: Send,
|
||||
for<'a> &'a E: Executor<'a, Database = MySql>,
|
||||
{
|
||||
type New = New;
|
||||
type Update = Field;
|
||||
type Unique = Unique;
|
||||
type Existing = Package;
|
||||
|
||||
async fn create(connection: &mut E, data: Self::New) -> Result<Self::Existing> {
|
||||
let created_at = Utc::now();
|
||||
let id = sqlx::query!(
|
||||
"INSERT INTO Packages \
|
||||
(package_base, name, version, description, url, flagged_at, created_at, updated_at) \
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
data.package_base.id,
|
||||
data.name.as_str(),
|
||||
data.version.as_str(),
|
||||
data.description.as_ref(),
|
||||
data.url.as_ref(),
|
||||
data.flagged_at,
|
||||
created_at,
|
||||
created_at,
|
||||
)
|
||||
.execute(&*connection)
|
||||
.await?
|
||||
.last_insert_id();
|
||||
|
||||
Ok(Self::Existing {
|
||||
id,
|
||||
package_base: data.package_base.id,
|
||||
name: data.name.into(),
|
||||
version: data.version.into(),
|
||||
description: data.description.into(),
|
||||
url: data.url.into(),
|
||||
flagged_at: data.flagged_at,
|
||||
created_at,
|
||||
updated_at: created_at,
|
||||
})
|
||||
}
|
||||
|
||||
async fn read(connection: &E, data: Self::Unique) -> Result<Option<Self::Existing>> {
|
||||
Ok(match data {
|
||||
Unique::Id(id) => {
|
||||
sqlx::query_as!(Package, "SELECT * FROM Packages WHERE id = ?", id)
|
||||
.fetch_optional(connection)
|
||||
.await
|
||||
}
|
||||
Unique::Name(name) => {
|
||||
sqlx::query_as!(
|
||||
Package,
|
||||
"SELECT * FROM Packages WHERE name = ?",
|
||||
name.as_str()
|
||||
)
|
||||
.fetch_optional(connection)
|
||||
.await
|
||||
}
|
||||
}?)
|
||||
}
|
||||
|
||||
async fn update(
|
||||
connection: &mut E,
|
||||
existing: &mut Self::Existing,
|
||||
data: Self::Update,
|
||||
) -> Result {
|
||||
match &data {
|
||||
Field::Name(name) => {
|
||||
sqlx::query!(
|
||||
"UPDATE Packages SET name = ? WHERE id = ?",
|
||||
name.as_str(),
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::PackageBase(package_base) => {
|
||||
sqlx::query!(
|
||||
"UPDATE Packages SET package_base = ? WHERE id = ?",
|
||||
package_base.id,
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::Version(version) => {
|
||||
sqlx::query!(
|
||||
"UPDATE Packages SET version = ? WHERE id = ?",
|
||||
version.as_str(),
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::Description(description) => {
|
||||
sqlx::query!(
|
||||
"UPDATE Packages SET description = ? WHERE id = ?",
|
||||
description.as_ref(),
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::URL(url) => {
|
||||
sqlx::query!(
|
||||
"UPDATE Packages SET url = ? WHERE id = ?",
|
||||
url.as_ref(),
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::FlaggedAt(date_time) => sqlx::query!(
|
||||
"UPDATE Packages SET flagged_at = ? WHERE id = ?",
|
||||
date_time,
|
||||
existing.id
|
||||
),
|
||||
Field::CreatedAt(date_time) => sqlx::query!(
|
||||
"UPDATE Packages SET created_at = ? WHERE id = ?",
|
||||
date_time,
|
||||
existing.id
|
||||
),
|
||||
Field::UpdatedAt(date_time) => sqlx::query!(
|
||||
"UPDATE Packages SET updated_at = ? WHERE id = ?",
|
||||
date_time,
|
||||
existing.id
|
||||
),
|
||||
}
|
||||
.execute(&*connection)
|
||||
.await?;
|
||||
|
||||
match data {
|
||||
Field::Name(s) => existing.name = s.into(),
|
||||
Field::PackageBase(s) => existing.package_base = s.id,
|
||||
Field::Version(s) => existing.version = s.into(),
|
||||
Field::Description(o) => existing.description = o.into(),
|
||||
Field::URL(o) => existing.url = o.into(),
|
||||
Field::FlaggedAt(date_time) => existing.flagged_at = date_time,
|
||||
Field::CreatedAt(date_time) => existing.created_at = date_time,
|
||||
Field::UpdatedAt(date_time) => existing.updated_at = date_time,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete(connection: &mut E, data: Self::Unique) -> Result {
|
||||
match data {
|
||||
Unique::Id(id) => sqlx::query!("DELETE FROM Packages WHERE id = ?", id),
|
||||
Unique::Name(name) => {
|
||||
sqlx::query!("DELETE FROM Packages WHERE name = ?", name.as_str())
|
||||
}
|
||||
}
|
||||
.execute(&*connection)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
146
src/data/src/adapter/mysql/user.rs
Normal file
146
src/data/src/adapter/mysql/user.rs
Normal file
@ -0,0 +1,146 @@
|
||||
use crate::Result;
|
||||
use crate::port::user::{Field, New, Unique, User, UserRepository};
|
||||
|
||||
use chrono::Utc;
|
||||
use sqlx::{Executor, MySql};
|
||||
|
||||
pub struct UserAdapter;
|
||||
|
||||
impl<E> UserRepository<E> for UserAdapter
|
||||
where
|
||||
E: Send,
|
||||
for<'a> &'a E: Executor<'a, Database = MySql>,
|
||||
{
|
||||
}
|
||||
impl<E> crate::port::CRUD<E> for UserAdapter
|
||||
where
|
||||
E: Send,
|
||||
for<'a> &'a E: Executor<'a, Database = MySql>,
|
||||
{
|
||||
type New = New;
|
||||
type Update = Field;
|
||||
type Unique = Unique;
|
||||
type Existing = User;
|
||||
|
||||
async fn create(connection: &mut E, data: Self::New) -> Result<Self::Existing> {
|
||||
let created_at = Utc::now();
|
||||
let id = sqlx::query!(
|
||||
"INSERT INTO Users (name, email, password, last_used, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
data.name.as_str(),
|
||||
data.email.as_str(),
|
||||
data.password.as_str(),
|
||||
data.last_used,
|
||||
created_at,
|
||||
created_at,
|
||||
)
|
||||
.execute(&*connection)
|
||||
.await?
|
||||
.last_insert_id();
|
||||
|
||||
Ok(Self::Existing {
|
||||
id,
|
||||
name: data.name.into(),
|
||||
email: data.email.into(),
|
||||
password: data.password.into(),
|
||||
last_used: data.last_used,
|
||||
created_at,
|
||||
updated_at: created_at,
|
||||
})
|
||||
}
|
||||
|
||||
async fn read(connection: &E, data: Self::Unique) -> Result<Option<Self::Existing>> {
|
||||
Ok(match data {
|
||||
Unique::Id(id) => {
|
||||
sqlx::query_as!(User, "SELECT * FROM Users WHERE id = ?", id)
|
||||
.fetch_optional(connection)
|
||||
.await
|
||||
}
|
||||
Unique::Name(name) => {
|
||||
sqlx::query_as!(User, "SELECT * FROM Users WHERE name = ?", name.as_str())
|
||||
.fetch_optional(connection)
|
||||
.await
|
||||
}
|
||||
Unique::Email(email) => {
|
||||
sqlx::query_as!(User, "SELECT * FROM Users WHERE email = ?", email.as_str())
|
||||
.fetch_optional(connection)
|
||||
.await
|
||||
}
|
||||
}?)
|
||||
}
|
||||
|
||||
async fn update(
|
||||
connection: &mut E,
|
||||
existing: &mut Self::Existing,
|
||||
data: Self::Update,
|
||||
) -> Result {
|
||||
match &data {
|
||||
Field::Name(name) => {
|
||||
sqlx::query!(
|
||||
"UPDATE Users SET name = ? WHERE id = ?",
|
||||
name.as_str(),
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::Email(email) => {
|
||||
sqlx::query!(
|
||||
"UPDATE Users SET email = ? WHERE id = ?",
|
||||
email.as_str(),
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::Password(password) => {
|
||||
sqlx::query!(
|
||||
"UPDATE Users SET password = ? WHERE id = ?",
|
||||
password.as_str(),
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::LastUsed(date_time) => {
|
||||
sqlx::query!(
|
||||
"UPDATE Users SET last_used = ? WHERE id = ?",
|
||||
date_time,
|
||||
existing.id
|
||||
)
|
||||
}
|
||||
Field::CreatedAt(date_time) => sqlx::query!(
|
||||
"UPDATE Users SET created_at = ? WHERE id = ?",
|
||||
date_time,
|
||||
existing.id
|
||||
),
|
||||
Field::UpdatedAt(date_time) => sqlx::query!(
|
||||
"UPDATE Users SET updated_at = ? WHERE id = ?",
|
||||
date_time,
|
||||
existing.id
|
||||
),
|
||||
}
|
||||
.execute(&*connection)
|
||||
.await?;
|
||||
|
||||
match data {
|
||||
Field::Name(valid) => existing.name = valid.into(),
|
||||
Field::Email(valid) => existing.email = valid.into(),
|
||||
Field::Password(valid) => existing.password = valid.into(),
|
||||
Field::LastUsed(date_time) => existing.last_used = date_time,
|
||||
Field::CreatedAt(date_time) => existing.created_at = date_time,
|
||||
Field::UpdatedAt(date_time) => existing.updated_at = date_time,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete(connection: &mut E, data: Self::Unique) -> Result {
|
||||
match data {
|
||||
Unique::Id(id) => sqlx::query!("DELETE FROM Users WHERE id = ?", id),
|
||||
Unique::Name(name) => {
|
||||
sqlx::query!("DELETE FROM Users WHERE name = ?", name.as_str())
|
||||
}
|
||||
Unique::Email(email) => {
|
||||
sqlx::query!("DELETE FROM Users WHERE email = ?", email.as_str())
|
||||
}
|
||||
}
|
||||
.execute(&*connection)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
43
src/data/src/atomic.rs
Normal file
43
src/data/src/atomic.rs
Normal file
@ -0,0 +1,43 @@
|
||||
//! Unify transaction management for established connections.
|
||||
use crate::Result;
|
||||
|
||||
pub trait Atomic {
|
||||
type Transaction<'a>;
|
||||
|
||||
fn start_transaction(&mut self) -> impl Future<Output = Result<Self::Transaction<'_>>> + Send;
|
||||
fn abort_transaction(transaction: Self::Transaction<'_>)
|
||||
-> impl Future<Output = Result> + Send;
|
||||
fn commit_transaction(
|
||||
transaction: Self::Transaction<'_>,
|
||||
) -> impl Future<Output = Result> + Send;
|
||||
}
|
||||
|
||||
use sqlx::Connection;
|
||||
|
||||
impl Atomic for sqlx::MySqlPool {
|
||||
type Transaction<'a> = sqlx::MySqlTransaction<'a>;
|
||||
|
||||
async fn start_transaction(&mut self) -> Result<Self::Transaction<'_>> {
|
||||
self.begin().await.map_err(Box::from)
|
||||
}
|
||||
async fn abort_transaction(transaction: Self::Transaction<'_>) -> Result {
|
||||
transaction.rollback().await.map_err(Box::from)
|
||||
}
|
||||
async fn commit_transaction(transaction: Self::Transaction<'_>) -> Result {
|
||||
transaction.commit().await.map_err(Box::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl Atomic for sqlx::MySqlConnection {
|
||||
type Transaction<'a> = sqlx::MySqlTransaction<'a>;
|
||||
|
||||
async fn start_transaction(&mut self) -> Result<Self::Transaction<'_>> {
|
||||
self.begin().await.map_err(Box::from)
|
||||
}
|
||||
async fn abort_transaction(transaction: Self::Transaction<'_>) -> Result {
|
||||
transaction.rollback().await.map_err(Box::from)
|
||||
}
|
||||
async fn commit_transaction(transaction: Self::Transaction<'_>) -> Result {
|
||||
transaction.commit().await.map_err(Box::from)
|
||||
}
|
||||
}
|
53
src/data/src/connect.rs
Normal file
53
src/data/src/connect.rs
Normal file
@ -0,0 +1,53 @@
|
||||
//! Driver to manage a connection which is passed to adapters.
|
||||
use crate::Result;
|
||||
|
||||
pub trait Connect {
|
||||
type Connection;
|
||||
|
||||
fn open_connection(&self) -> impl Future<Output = Result<Self::Connection>> + Send;
|
||||
fn close_connection(connection: Self::Connection) -> impl Future<Output = Result> + Send;
|
||||
}
|
||||
|
||||
use sqlx::Connection;
|
||||
pub use sqlx::MySqlConnection as SqlxConnection;
|
||||
pub use sqlx::MySqlPool as SqlxPool;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MySqlPool {
|
||||
pool: SqlxPool,
|
||||
}
|
||||
impl MySqlPool {
|
||||
pub const fn new(pool: SqlxPool) -> Self {
|
||||
Self { pool }
|
||||
}
|
||||
}
|
||||
impl Connect for MySqlPool {
|
||||
type Connection = SqlxPool;
|
||||
|
||||
async fn open_connection(&self) -> Result<Self::Connection> {
|
||||
Ok(self.pool.clone())
|
||||
}
|
||||
async fn close_connection(_: Self::Connection) -> Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MySqlConnection {
|
||||
link: String,
|
||||
}
|
||||
impl MySqlConnection {
|
||||
pub const fn new(link: String) -> Self {
|
||||
Self { link }
|
||||
}
|
||||
}
|
||||
impl Connect for MySqlConnection {
|
||||
type Connection = SqlxConnection;
|
||||
|
||||
async fn open_connection(&self) -> Result<Self::Connection> {
|
||||
SqlxConnection::connect(&self.link).await.map_err(Box::from)
|
||||
}
|
||||
async fn close_connection(connection: Self::Connection) -> Result {
|
||||
connection.close().await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
21
src/data/src/lib.rs
Normal file
21
src/data/src/lib.rs
Normal file
@ -0,0 +1,21 @@
|
||||
//! Data access for the application.
|
||||
pub mod adapter;
|
||||
pub mod atomic;
|
||||
pub mod connect;
|
||||
pub mod port;
|
||||
|
||||
// Don't want to handle errors for dynamic mess.
|
||||
pub type BoxDynError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||
pub type Result<T = (), E = BoxDynError> = std::result::Result<T, E>;
|
||||
|
||||
pub use chrono::Utc;
|
||||
|
||||
pub use atomic::Atomic;
|
||||
pub use connect::*;
|
||||
|
||||
pub use adapter::mysql::base::BaseAdapter as MySqlBaseAdapter;
|
||||
pub use adapter::mysql::package::PackageAdapter as MySqlPackageAdapter;
|
||||
pub use adapter::mysql::user::UserAdapter as MySqlUserAdapter;
|
||||
pub use port::base::{self, Base, BaseRepository};
|
||||
pub use port::package::{self, Package, PackageRepository};
|
||||
pub use port::user::{self, User, UserRepository};
|
58
src/data/src/port.rs
Normal file
58
src/data/src/port.rs
Normal file
@ -0,0 +1,58 @@
|
||||
//! Low-level repository traits for unified data access.
|
||||
//!
|
||||
//! No data validation besides very basic one like length violation.
|
||||
use crate::Result;
|
||||
|
||||
pub mod base;
|
||||
pub mod package;
|
||||
pub mod user;
|
||||
|
||||
pub trait CRUD<C> {
|
||||
type New;
|
||||
type Unique;
|
||||
type Update;
|
||||
type Existing;
|
||||
|
||||
fn create(
|
||||
connection: &mut C,
|
||||
data: Self::New,
|
||||
) -> impl Future<Output = crate::Result<Self::Existing>> + Send;
|
||||
fn read(
|
||||
connection: &C,
|
||||
data: Self::Unique,
|
||||
) -> impl Future<Output = crate::Result<Option<Self::Existing>>> + Send;
|
||||
fn update(
|
||||
connection: &mut C,
|
||||
existing: &mut Self::Existing,
|
||||
data: Self::Update,
|
||||
) -> impl Future<Output = crate::Result> + Send;
|
||||
fn delete(connection: &mut C, data: Self::Unique)
|
||||
-> impl Future<Output = crate::Result> + Send;
|
||||
}
|
||||
|
||||
trait CharLength {
|
||||
fn length(&self) -> usize;
|
||||
}
|
||||
impl CharLength for String {
|
||||
fn length(&self) -> usize {
|
||||
self.chars().count()
|
||||
}
|
||||
}
|
||||
impl CharLength for Option<String> {
|
||||
fn length(&self) -> usize {
|
||||
self.as_ref().map_or(0, CharLength::length)
|
||||
}
|
||||
}
|
||||
|
||||
trait MaxLength {
|
||||
type Inner: CharLength;
|
||||
const MAX_LENGTH: usize;
|
||||
|
||||
fn validate(value: &Self::Inner) -> Result<(), &'static str> {
|
||||
if value.length() > Self::MAX_LENGTH {
|
||||
Err("too long")
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
82
src/data/src/port/base.rs
Normal file
82
src/data/src/port/base.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use super::MaxLength;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use derive_more::{Deref, Into};
|
||||
|
||||
pub trait BaseRepository<C>:
|
||||
super::CRUD<C, New = New, Unique = u64, Update = Field, Existing = Base>
|
||||
{
|
||||
}
|
||||
|
||||
// #[derive(Deref, Into, Clone, Copy)]
|
||||
// pub struct Id(pub(crate) u64);
|
||||
|
||||
#[derive(Clone, Deref, Into)]
|
||||
pub struct Name(String);
|
||||
impl MaxLength for Name {
|
||||
type Inner = String;
|
||||
const MAX_LENGTH: usize = 127;
|
||||
}
|
||||
impl TryFrom<String> for Name {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
Self::validate(&value)?;
|
||||
Ok(Self(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Deref, Into)]
|
||||
pub struct Description(Option<String>);
|
||||
impl MaxLength for Description {
|
||||
type Inner = Option<String>;
|
||||
const MAX_LENGTH: usize = 510;
|
||||
}
|
||||
impl TryFrom<Option<String>> for Description {
|
||||
type Error = (Option<String>, &'static str);
|
||||
|
||||
fn try_from(value: Option<String>) -> Result<Self, Self::Error> {
|
||||
match Self::validate(&value) {
|
||||
Ok(()) => Ok(Self(value)),
|
||||
Err(e) => Err((value, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Field {
|
||||
Name(Name),
|
||||
Description(Description),
|
||||
CreatedAt(DateTime<Utc>),
|
||||
UpdatedAt(DateTime<Utc>),
|
||||
}
|
||||
|
||||
pub struct New {
|
||||
pub name: Name,
|
||||
pub description: Description,
|
||||
}
|
||||
|
||||
pub struct Base {
|
||||
pub(crate) id: u64,
|
||||
pub(crate) name: String,
|
||||
pub(crate) description: Option<String>,
|
||||
pub(crate) created_at: DateTime<Utc>,
|
||||
pub(crate) updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Base {
|
||||
pub const fn id(&self) -> u64 {
|
||||
self.id
|
||||
}
|
||||
pub const fn name(&self) -> &String {
|
||||
&self.name
|
||||
}
|
||||
pub const fn description(&self) -> Option<&String> {
|
||||
self.description.as_ref()
|
||||
}
|
||||
pub const fn created_at(&self) -> DateTime<Utc> {
|
||||
self.created_at
|
||||
}
|
||||
pub const fn updated_at(&self) -> DateTime<Utc> {
|
||||
self.updated_at
|
||||
}
|
||||
}
|
145
src/data/src/port/package.rs
Normal file
145
src/data/src/port/package.rs
Normal file
@ -0,0 +1,145 @@
|
||||
use super::MaxLength;
|
||||
use crate::Base;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use derive_more::{Deref, Into};
|
||||
|
||||
pub trait PackageRepository<C>:
|
||||
super::CRUD<C, New = New, Update = Field, Unique = Unique, Existing = Package>
|
||||
{
|
||||
}
|
||||
|
||||
#[derive(Clone, Deref, Into)]
|
||||
pub struct Name(String);
|
||||
impl MaxLength for Name {
|
||||
type Inner = String;
|
||||
const MAX_LENGTH: usize = 127;
|
||||
}
|
||||
impl TryFrom<String> for Name {
|
||||
type Error = (String, &'static str);
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
match Self::validate(&value) {
|
||||
Ok(()) => Ok(Self(value)),
|
||||
Err(e) => Err((value, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Deref, Into)]
|
||||
pub struct Version(String);
|
||||
impl MaxLength for Version {
|
||||
type Inner = String;
|
||||
const MAX_LENGTH: usize = 127;
|
||||
}
|
||||
impl TryFrom<String> for Version {
|
||||
type Error = (String, &'static str);
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
match Self::validate(&value) {
|
||||
Ok(()) => Ok(Self(value)),
|
||||
Err(e) => Err((value, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Deref, Into)]
|
||||
pub struct Description(Option<String>);
|
||||
impl MaxLength for Description {
|
||||
type Inner = Option<String>;
|
||||
const MAX_LENGTH: usize = 255;
|
||||
}
|
||||
impl TryFrom<Option<String>> for Description {
|
||||
type Error = (Option<String>, &'static str);
|
||||
|
||||
fn try_from(value: Option<String>) -> Result<Self, Self::Error> {
|
||||
match Self::validate(&value) {
|
||||
Ok(()) => Ok(Self(value)),
|
||||
Err(e) => Err((value, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Deref, Into)]
|
||||
pub struct URL(Option<String>);
|
||||
impl MaxLength for URL {
|
||||
type Inner = Option<String>;
|
||||
const MAX_LENGTH: usize = 510;
|
||||
}
|
||||
impl TryFrom<Option<String>> for URL {
|
||||
type Error = (Option<String>, &'static str);
|
||||
|
||||
fn try_from(value: Option<String>) -> Result<Self, Self::Error> {
|
||||
match Self::validate(&value) {
|
||||
Ok(()) => Ok(Self(value)),
|
||||
Err(e) => Err((value, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Unique {
|
||||
Id(u64),
|
||||
Name(Name),
|
||||
}
|
||||
|
||||
pub enum Field {
|
||||
PackageBase(Base),
|
||||
Name(Name),
|
||||
Version(Version),
|
||||
Description(Description),
|
||||
URL(URL),
|
||||
FlaggedAt(Option<DateTime<Utc>>),
|
||||
CreatedAt(DateTime<Utc>),
|
||||
UpdatedAt(DateTime<Utc>),
|
||||
}
|
||||
|
||||
pub struct New {
|
||||
pub package_base: Base,
|
||||
pub name: Name,
|
||||
pub version: Version,
|
||||
pub description: Description,
|
||||
pub url: URL,
|
||||
pub flagged_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
pub struct Package {
|
||||
pub(crate) id: u64,
|
||||
pub(crate) package_base: u64,
|
||||
pub(crate) name: String,
|
||||
pub(crate) version: String,
|
||||
pub(crate) description: Option<String>,
|
||||
pub(crate) url: Option<String>,
|
||||
pub(crate) flagged_at: Option<DateTime<Utc>>,
|
||||
pub(crate) created_at: DateTime<Utc>,
|
||||
pub(crate) updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Package {
|
||||
pub const fn id(&self) -> u64 {
|
||||
self.id
|
||||
}
|
||||
pub const fn package_base(&self) -> u64 {
|
||||
self.package_base
|
||||
}
|
||||
pub const fn name(&self) -> &String {
|
||||
&self.name
|
||||
}
|
||||
pub const fn version(&self) -> &String {
|
||||
&self.version
|
||||
}
|
||||
pub const fn description(&self) -> Option<&String> {
|
||||
self.description.as_ref()
|
||||
}
|
||||
pub const fn url(&self) -> Option<&String> {
|
||||
self.url.as_ref()
|
||||
}
|
||||
pub const fn flagged_at(&self) -> Option<DateTime<Utc>> {
|
||||
self.flagged_at
|
||||
}
|
||||
pub const fn created_at(&self) -> DateTime<Utc> {
|
||||
self.created_at
|
||||
}
|
||||
pub const fn updated_at(&self) -> DateTime<Utc> {
|
||||
self.updated_at
|
||||
}
|
||||
}
|
117
src/data/src/port/user.rs
Normal file
117
src/data/src/port/user.rs
Normal file
@ -0,0 +1,117 @@
|
||||
use super::MaxLength;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use derive_more::{Deref, Into};
|
||||
|
||||
pub trait UserRepository<C>:
|
||||
super::CRUD<C, New = New, Update = Field, Unique = Unique, Existing = User>
|
||||
{
|
||||
}
|
||||
|
||||
#[derive(Clone, Deref, Into)]
|
||||
pub struct Name(String);
|
||||
impl MaxLength for Name {
|
||||
type Inner = String;
|
||||
const MAX_LENGTH: usize = 31;
|
||||
}
|
||||
impl TryFrom<String> for Name {
|
||||
type Error = (String, &'static str);
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
match Self::validate(&value) {
|
||||
Ok(()) => Ok(Self(value)),
|
||||
Err(e) => Err((value, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Deref, Into)]
|
||||
pub struct Email(String);
|
||||
impl MaxLength for Email {
|
||||
type Inner = String;
|
||||
const MAX_LENGTH: usize = 255;
|
||||
}
|
||||
impl TryFrom<String> for Email {
|
||||
type Error = (String, &'static str);
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
match Self::validate(&value) {
|
||||
Ok(()) => Ok(Self(value)),
|
||||
Err(e) => Err((value, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Deref, Into)]
|
||||
pub struct Password(String);
|
||||
impl MaxLength for Password {
|
||||
type Inner = String;
|
||||
const MAX_LENGTH: usize = 255;
|
||||
}
|
||||
impl TryFrom<String> for Password {
|
||||
type Error = (String, &'static str);
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
match Self::validate(&value) {
|
||||
Ok(()) => Ok(Self(value)),
|
||||
Err(e) => Err((value, e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Unique {
|
||||
Id(u64),
|
||||
Name(Name),
|
||||
Email(Email),
|
||||
}
|
||||
|
||||
pub enum Field {
|
||||
Name(Name),
|
||||
Email(Email),
|
||||
Password(Password),
|
||||
LastUsed(Option<DateTime<Utc>>),
|
||||
CreatedAt(DateTime<Utc>),
|
||||
UpdatedAt(DateTime<Utc>),
|
||||
}
|
||||
|
||||
pub struct New {
|
||||
pub name: Name,
|
||||
pub email: Email,
|
||||
pub password: Password,
|
||||
pub last_used: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct User {
|
||||
pub(crate) id: u64,
|
||||
pub(crate) name: String,
|
||||
pub(crate) email: String,
|
||||
pub(crate) password: String,
|
||||
pub(crate) last_used: Option<DateTime<Utc>>,
|
||||
pub(crate) created_at: DateTime<Utc>,
|
||||
pub(crate) updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub const fn id(&self) -> u64 {
|
||||
self.id
|
||||
}
|
||||
pub const fn name(&self) -> &String {
|
||||
&self.name
|
||||
}
|
||||
pub const fn email(&self) -> &String {
|
||||
&self.email
|
||||
}
|
||||
pub const fn password(&self) -> &String {
|
||||
&self.password
|
||||
}
|
||||
pub const fn last_used(&self) -> Option<DateTime<Utc>> {
|
||||
self.last_used
|
||||
}
|
||||
pub const fn created_at(&self) -> DateTime<Utc> {
|
||||
self.created_at
|
||||
}
|
||||
pub const fn updated_at(&self) -> DateTime<Utc> {
|
||||
self.updated_at
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user