User endpoints
This commit is contained in:
parent
33356f34e8
commit
d4c1cdb582
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT folder_id FROM folders WHERE folder_id = $1 AND owner_id = $2",
|
||||
"query": "SELECT folder_id FROM files WHERE file_id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -11,13 +11,12 @@
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Int4"
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "dc98f1a609e67b642aed635b26239328e6456e69c12dc8561c474fff3dcd14d5"
|
||||
"hash": "09299172474d10a07387b74f4d714bf389b5422334bd1aa2a0e6f2d63ebdd623"
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT\n username,\n permission_type as \"permission_type: PermissionRaw\"\nFROM\n permissions\n INNER JOIN users ON permissions.user_id = users.user_id\nWHERE\n folder_id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "username",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "permission_type: PermissionRaw",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "permission",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"read",
|
||||
"write",
|
||||
"manage"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "39b78c7f3266bea5e3e44aa372574319cb74dea6b3d0bc16d25e29ca28803317"
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE files SET (sha512, file_size, updated_at) = ($2, $3, NOW()) WHERE file_id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Bytea",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4c7c701a22c49eebb4ba31a21dab15a5dbe2eaba99036932790c7c09599d4cd7"
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH RECURSIVE folder_hierarchy AS (\n -- Start with the given directory\n SELECT \n folder_id \n FROM \n folders \n WHERE \n folder_id = $1\n\n UNION ALL\n\n -- Recursively find all subdirectories\n SELECT \n f.folder_id\n FROM \n folders f\n INNER JOIN \n folder_hierarchy fh ON f.parent_folder_id = fh.folder_id\n)\nINSERT INTO permissions(user_id, folder_id, permission_type)\nSELECT $2::integer as user_id, fh.folder_id::UUID as folder_id, $3\nFROM folder_hierarchy fh\nON CONFLICT (user_id, folder_id) DO UPDATE\nSET permission_type = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Int4",
|
||||
{
|
||||
"Custom": {
|
||||
"name": "permission",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"read",
|
||||
"write",
|
||||
"manage"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "595739c03acbe706107e34a3ebebec8c8f21f70ccc51b5366eff962d9af391d7"
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT\n user_id, username, email\nFROM\n users\nORDER BY\n GREATEST (\n similarity (email, $1),\n similarity (username, $1)\n ) DESC",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "user_id",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "username",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "email",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "61a26b3321bb5b58a0b90e61b2cdcacfb46a03eb0c0a89839c9b3eff53cb7e56"
|
||||
}
|
@ -1,13 +1,12 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO files(file_id, folder_id, owner_id, file_name, file_size, sha512) VALUES ($1, $2, $3, $4, $5, $6)",
|
||||
"query": "INSERT INTO files(file_id, folder_id, file_name, file_size, sha512) VALUES ($1, $2, $3, $4, $5)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Uuid",
|
||||
"Int4",
|
||||
"Varchar",
|
||||
"Int8",
|
||||
"Bytea"
|
||||
@ -15,5 +14,5 @@
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "9a70e24a3de68f4a66718124bd3ca959bd0a992e5e0dda3baae52b8cb545ce66"
|
||||
"hash": "6b58c84cdc19cea97ef025211a98879bb5cc80a934490125a19c960133f6d93d"
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT\n permission_type as \"permission_type: PermissionRaw\"\nFROM\n permissions\nWHERE\n folder_id = $1\n AND user_id = $2\nUNION\nSELECT\n 'manage' as \"permission_type: PermissionRaw\"\nFROM\n folders\nWHERE\n folder_id = $1\n AND owner_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "permission_type: PermissionRaw",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "permission",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"read",
|
||||
"write",
|
||||
"manage"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "87f7df91208438a35516604f57f0443e0f12db718e23acd374f6f7ace65f467d"
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH RECURSIVE folder_hierarchy AS (\n -- Start with the given directory\n SELECT \n folder_id \n FROM \n folders \n WHERE \n folder_id = $1\n\n UNION ALL\n\n -- Recursively find all subdirectories\n SELECT \n f.folder_id\n FROM \n folders f\n INNER JOIN \n folder_hierarchy fh ON f.parent_folder_id = fh.folder_id\n)\nDELETE FROM permissions WHERE user_id = $2 AND folder_id IN (SELECT folder_id FROM folder_hierarchy)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "948f13b631bcc7df1919a9639443f0ed932c4cb37f2ba5bf6f000eb84b265ae2"
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT file_id FROM files WHERE file_id = $1 AND owner_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "file_id",
|
||||
"type_info": "Uuid"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "9a26dab9efbbbb92b7be27792b581a0156210fdc0aadd3756f7003186f428374"
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH\n deleted_files AS (\n DELETE FROM files USING folders\n WHERE\n files.folder_id = folders.folder_id\n AND folders.owner_id = $1 RETURNING files.file_id\n ),\n deleted_users AS (\n DELETE FROM users\n WHERE\n user_id = $1\n )\nSELECT\n *\nFROM\n deleted_files;",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "file_id",
|
||||
"type_info": "Uuid"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "a54829e9cd90e55022c2f6dd413b797efaafd1c4793b60886140bfe9ea6df592"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT file_id, owner_id, file_name, file_size, sha512, created_at, updated_at FROM files WHERE folder_id = $1",
|
||||
"query": "SELECT file_id, file_name, file_size, encode(sha512, 'base64') as \"sha512!\", created_at, updated_at FROM files WHERE folder_id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -10,31 +10,26 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "owner_id",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "file_name",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"ordinal": 2,
|
||||
"name": "file_size",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "sha512",
|
||||
"type_info": "Bytea"
|
||||
"ordinal": 3,
|
||||
"name": "sha512!",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"ordinal": 4,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamp"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"ordinal": 5,
|
||||
"name": "updated_at",
|
||||
"type_info": "Timestamp"
|
||||
}
|
||||
@ -48,11 +43,10 @@
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "5a51ab540453327bdd75f49991f402fac6b1d8fb0a760d420236e2b41d3e7fcf"
|
||||
"hash": "e125c9f06cb89c6ddd2653ed45c576da3aecfb9fb74aabf202e83406fc8c8fff"
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH\n permitted as (\n SELECT\n folder_id\n FROM\n permissions\n WHERE\n user_id = $1\n )\nSELECT\n folder_id\nFROM\n folders\nWHERE\n folder_id IN (\n SELECT\n folder_id\n FROM\n permitted\n )\n AND parent_folder_id NOT IN (\n SELECT\n folder_id\n FROM\n permitted\n )",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "folder_id",
|
||||
"type_info": "Uuid"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "f9e36f45f25dd2439a7a0b16b6df356a0a2a47e70b6e031ea5a0442adc86725b"
|
||||
}
|
123
Cargo.lock
generated
123
Cargo.lock
generated
@ -107,7 +107,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -220,7 +220,7 @@ dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -663,7 +663,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1079,6 +1079,7 @@ checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1419,7 +1420,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1523,7 +1524,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1581,6 +1582,30 @@ dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
@ -1612,6 +1637,8 @@ dependencies = [
|
||||
"tower-http",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"utoipa",
|
||||
"utoipauto",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
@ -2060,7 +2087,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2274,7 +2301,7 @@ dependencies = [
|
||||
"quote",
|
||||
"sqlx-core",
|
||||
"sqlx-macros-core",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2297,7 +2324,7 @@ dependencies = [
|
||||
"sqlx-mysql",
|
||||
"sqlx-postgres",
|
||||
"sqlx-sqlite",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"url",
|
||||
@ -2429,6 +2456,16 @@ version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.72"
|
||||
@ -2502,7 +2539,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2585,7 +2622,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2713,7 +2750,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2819,6 +2856,64 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utoipa"
|
||||
version = "4.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"utoipa-gen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utoipa-gen"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bf0e16c02bc4bf5322ab65f10ab1149bdbcaa782cba66dc7057370a3f8190be"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 2.0.72",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utoipauto"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4713aabc5ed18aabcd594345b48983b112c0b5dab3d24754352e7f5cf924da03"
|
||||
dependencies = [
|
||||
"utoipauto-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utoipauto-core"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17e82ab96c5a55263b5bed151b8426410d93aa909a453acdbd4b6792b5af7d64"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utoipauto-macro"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b8338dc3c9526011ffaa2aa6bd60ddfda9d49d2123108690755c6e34844212"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.72",
|
||||
"utoipauto-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.10.0"
|
||||
@ -2889,7 +2984,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -2923,7 +3018,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -3177,7 +3272,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -51,4 +51,6 @@ tracing-subscriber = { version = "0.3", features = [
|
||||
"parking_lot",
|
||||
"env-filter",
|
||||
] }
|
||||
utoipa = { version = "4", features = ["axum_extras", "uuid", "chrono"] }
|
||||
utoipauto = "0.1"
|
||||
uuid = { version = "1", features = ["serde", "v4"] }
|
||||
|
@ -7,3 +7,5 @@ DROP TABLE folders;
|
||||
DROP TABLE users;
|
||||
|
||||
DROP TYPE permission;
|
||||
|
||||
DROP EXTENSION pg_trgm;
|
@ -1,3 +1,5 @@
|
||||
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
||||
|
||||
CREATE TABLE
|
||||
users (
|
||||
user_id SERIAL PRIMARY KEY,
|
||||
|
16
sql/delete_user.sql
Normal file
16
sql/delete_user.sql
Normal file
@ -0,0 +1,16 @@
|
||||
WITH
|
||||
deleted_files AS (
|
||||
DELETE FROM files USING folders
|
||||
WHERE
|
||||
files.folder_id = folders.folder_id
|
||||
AND folders.owner_id = $1 RETURNING files.file_id
|
||||
),
|
||||
deleted_users AS (
|
||||
DELETE FROM users
|
||||
WHERE
|
||||
user_id = $1
|
||||
)
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
deleted_files;
|
9
sql/search_for_user.sql
Normal file
9
sql/search_for_user.sql
Normal file
@ -0,0 +1,9 @@
|
||||
SELECT
|
||||
user_id, username, email
|
||||
FROM
|
||||
users
|
||||
ORDER BY
|
||||
GREATEST (
|
||||
similarity (email, $1),
|
||||
similarity (username, $1)
|
||||
) DESC
|
@ -1,6 +1,6 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use futures::TryStreamExt;
|
||||
use futures::{Stream, TryStreamExt};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{db::permissions::PermissionRaw, Pool};
|
||||
@ -101,10 +101,8 @@ pub async fn insert(
|
||||
.map(|record| record.folder_id)
|
||||
}
|
||||
|
||||
pub async fn delete(folder_id: Uuid, pool: &Pool) -> sqlx::Result<Vec<Uuid>> {
|
||||
pub fn delete(folder_id: Uuid, pool: &Pool) -> impl Stream<Item = sqlx::Result<Uuid>> + '_ {
|
||||
sqlx::query_file!("sql/delete_folder.sql", folder_id)
|
||||
.fetch(pool)
|
||||
.map_ok(|row| row.file_id)
|
||||
.try_collect()
|
||||
.await
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod file;
|
||||
pub mod folder;
|
||||
pub mod permissions;
|
||||
pub mod users;
|
||||
|
73
src/db/users.rs
Normal file
73
src/db/users.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use futures::{stream::BoxStream, Stream, TryStreamExt};
|
||||
use serde::Serialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::Pool;
|
||||
|
||||
/// Creates user and returns its id
|
||||
pub async fn create_user(user_name: &str, user_email: &str, pool: &Pool) -> sqlx::Result<i32> {
|
||||
let id = sqlx::query!(
|
||||
"INSERT INTO users(username, email) VALUES ($1, $2) RETURNING user_id",
|
||||
user_name,
|
||||
user_email
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await?
|
||||
.user_id;
|
||||
sqlx::query!(
|
||||
"INSERT INTO folders(owner_id, folder_name) VALUES ($1, $2)",
|
||||
id,
|
||||
"ROOT"
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Deletes the user and returns the files that must be deleted
|
||||
pub fn delete_user(user_id: i32, pool: &Pool) -> impl Stream<Item = sqlx::Result<Uuid>> + '_ {
|
||||
sqlx::query_file!("sql/delete_user.sql", user_id)
|
||||
.fetch(pool)
|
||||
.map_ok(|record| record.file_id)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct UserInfo {
|
||||
user_id: i32,
|
||||
username: String,
|
||||
email: String,
|
||||
}
|
||||
|
||||
pub async fn update(
|
||||
user_id: i32,
|
||||
username: &str,
|
||||
email: &str,
|
||||
pool: &Pool,
|
||||
) -> sqlx::Result<UserInfo> {
|
||||
sqlx::query_as!(
|
||||
UserInfo,
|
||||
"UPDATE users SET username = $2, email = $3 WHERE user_id = $1 RETURNING *",
|
||||
user_id,
|
||||
username,
|
||||
email
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get(user_id: i32, pool: &Pool) -> sqlx::Result<UserInfo> {
|
||||
sqlx::query_as!(
|
||||
UserInfo,
|
||||
"SELECT user_id, username, email FROM users WHERE user_id = $1",
|
||||
user_id
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn search_for_user<'a>(
|
||||
search_string: &str,
|
||||
pool: &'a Pool,
|
||||
) -> BoxStream<'a, sqlx::Result<UserInfo>> {
|
||||
sqlx::query_file_as!(UserInfo, "sql/search_for_user.sql", search_string).fetch(pool)
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
use futures::TryStreamExt;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
@ -22,14 +24,12 @@ pub async fn delete(
|
||||
.handle_internal()?
|
||||
.can_write_guard()?;
|
||||
|
||||
let files_to_delete = db::folder::delete(params.folder_id, &state.pool)
|
||||
.await
|
||||
.handle_internal()?;
|
||||
let storage = &state.storage;
|
||||
futures::stream::iter(files_to_delete)
|
||||
.for_each_concurrent(5, |file| async move {
|
||||
db::folder::delete(params.folder_id, &state.pool)
|
||||
.try_for_each_concurrent(5, |file| async move {
|
||||
let _ = storage.delete(file).await;
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
Ok(())
|
||||
.await
|
||||
.handle_internal()
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod file;
|
||||
pub mod folder;
|
||||
pub mod permissions;
|
||||
pub mod users;
|
||||
|
@ -1,4 +1,4 @@
|
||||
pub mod delete;
|
||||
pub mod get;
|
||||
pub mod get_top_level_permitted_folders;
|
||||
pub mod get_top_level;
|
||||
pub mod set;
|
||||
|
17
src/endpoints/users/create.rs
Normal file
17
src/endpoints/users/create.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Params {
|
||||
username: String,
|
||||
email: String,
|
||||
}
|
||||
|
||||
pub async fn create(
|
||||
State(state): State<AppState>,
|
||||
Json(params): Json<Params>,
|
||||
) -> Result<Json<i32>, StatusCode> {
|
||||
let id = db::users::create_user(¶ms.username, ¶ms.email, &state.pool)
|
||||
.await
|
||||
.handle_internal()?;
|
||||
Ok(Json(id))
|
||||
}
|
14
src/endpoints/users/delete.rs
Normal file
14
src/endpoints/users/delete.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use futures::TryStreamExt;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
pub async fn delete(State(state): State<AppState>, claims: Claims) -> Result<(), StatusCode> {
|
||||
let storage = &state.storage;
|
||||
db::users::delete_user(claims.user_id, &state.pool)
|
||||
.try_for_each_concurrent(5, |file_id| async move {
|
||||
let _ = storage.delete(file_id).await;
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
.handle_internal()
|
||||
}
|
16
src/endpoints/users/get.rs
Normal file
16
src/endpoints/users/get.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Params {
|
||||
user_id: i32,
|
||||
}
|
||||
|
||||
pub async fn get(
|
||||
State(state): State<AppState>,
|
||||
Query(params): Query<Params>,
|
||||
) -> Result<Json<db::users::UserInfo>, StatusCode> {
|
||||
let info = db::users::get(params.user_id, &state.pool)
|
||||
.await
|
||||
.handle_internal()?;
|
||||
Ok(Json(info))
|
||||
}
|
5
src/endpoints/users/mod.rs
Normal file
5
src/endpoints/users/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod create;
|
||||
pub mod delete;
|
||||
pub mod get;
|
||||
pub mod put;
|
||||
pub mod search;
|
18
src/endpoints/users/put.rs
Normal file
18
src/endpoints/users/put.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Params {
|
||||
username: String,
|
||||
email: String,
|
||||
}
|
||||
|
||||
pub async fn put(
|
||||
State(state): State<AppState>,
|
||||
claims: Claims,
|
||||
Json(params): Json<Params>,
|
||||
) -> Result<Json<db::users::UserInfo>, StatusCode> {
|
||||
let info = db::users::update(claims.user_id, ¶ms.username, ¶ms.email, &state.pool)
|
||||
.await
|
||||
.handle_internal()?;
|
||||
Ok(Json(info))
|
||||
}
|
20
src/endpoints/users/search.rs
Normal file
20
src/endpoints/users/search.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use futures::TryStreamExt;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Params {
|
||||
search_string: String,
|
||||
}
|
||||
|
||||
pub async fn search(
|
||||
State(state): State<AppState>,
|
||||
Query(params): Query<Params>,
|
||||
) -> sqlx::Result<Json<Vec<db::users::UserInfo>>, StatusCode> {
|
||||
let users = db::users::search_for_user(¶ms.search_string, &state.pool)
|
||||
.take(5)
|
||||
.try_collect()
|
||||
.await
|
||||
.handle_internal()?;
|
||||
Ok(Json(users))
|
||||
}
|
34
src/main.rs
34
src/main.rs
@ -19,25 +19,6 @@ struct AppState {
|
||||
storage: FileStorage,
|
||||
}
|
||||
|
||||
async fn create_user(user_name: &str, user_email: &str, pool: &Pool) -> anyhow::Result<i32> {
|
||||
let id = sqlx::query!(
|
||||
"INSERT INTO users(username, email) VALUES ($1, $2) RETURNING user_id",
|
||||
user_name,
|
||||
user_email
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await?
|
||||
.user_id;
|
||||
sqlx::query!(
|
||||
"INSERT INTO folders(owner_id, folder_name) VALUES ($1, $2)",
|
||||
id,
|
||||
"ROOT"
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
async fn create_debug_users(pool: &Pool) -> anyhow::Result<()> {
|
||||
let count = sqlx::query!("SELECT count(user_id) FROM users")
|
||||
.fetch_one(pool)
|
||||
@ -49,8 +30,8 @@ async fn create_debug_users(pool: &Pool) -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
tokio::try_join!(
|
||||
create_user("Test1", "test1@example.com", pool),
|
||||
create_user("Test2", "test2@example.com", pool)
|
||||
db::users::create_user("Test1", "test1@example.com", pool),
|
||||
db::users::create_user("Test2", "test2@example.com", pool)
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
@ -87,7 +68,8 @@ fn app(state: AppState) -> Router {
|
||||
use axum::{http::header, routing::get};
|
||||
use endpoints::{
|
||||
file, folder,
|
||||
permissions::{self, get_top_level_permitted_folders::get_top_level},
|
||||
permissions::{self, get_top_level::get_top_level},
|
||||
users,
|
||||
};
|
||||
use tower_http::ServiceBuilderExt as _;
|
||||
|
||||
@ -123,6 +105,14 @@ fn app(state: AppState) -> Router {
|
||||
"/permissions/get_top_level_permitted_folders",
|
||||
get(get_top_level),
|
||||
)
|
||||
.route(
|
||||
"/users",
|
||||
get(users::get::get)
|
||||
.post(users::create::create)
|
||||
.delete(users::delete::delete)
|
||||
.put(users::put::put),
|
||||
)
|
||||
.route("/users/search", get(users::search::search))
|
||||
.layer(middleware)
|
||||
.with_state(state)
|
||||
}
|
||||
|
Reference in New Issue
Block a user