Tweaks for the desktop client
This commit is contained in:
		@@ -1,12 +1,12 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "db_name": "PostgreSQL",
 | 
					  "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",
 | 
					  "query": "SELECT\n    users.user_id,\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": {
 | 
					  "describe": {
 | 
				
			||||||
    "columns": [
 | 
					    "columns": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "ordinal": 0,
 | 
					        "ordinal": 0,
 | 
				
			||||||
        "name": "username",
 | 
					        "name": "user_id",
 | 
				
			||||||
        "type_info": "Varchar"
 | 
					        "type_info": "Int4"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "ordinal": 1,
 | 
					        "ordinal": 1,
 | 
				
			||||||
@@ -35,5 +35,5 @@
 | 
				
			|||||||
      false
 | 
					      false
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "hash": "39b78c7f3266bea5e3e44aa372574319cb74dea6b3d0bc16d25e29ca28803317"
 | 
					  "hash": "003349bc951a935fdfb285f99a726c221e3d1d02cb9e47b4c385545298b27217"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								.sqlx/query-1c5dda0e613ee57819d4c9534f3bcd8809f313026a187a2eff66fa4f7ba888a5.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								.sqlx/query-1c5dda0e613ee57819d4c9534f3bcd8809f313026a187a2eff66fa4f7ba888a5.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "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, owner_id, folder_name, created_at\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"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "ordinal": 1,
 | 
				
			||||||
 | 
					        "name": "owner_id",
 | 
				
			||||||
 | 
					        "type_info": "Int4"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "ordinal": 2,
 | 
				
			||||||
 | 
					        "name": "folder_name",
 | 
				
			||||||
 | 
					        "type_info": "Varchar"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "ordinal": 3,
 | 
				
			||||||
 | 
					        "name": "created_at",
 | 
				
			||||||
 | 
					        "type_info": "Timestamptz"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "parameters": {
 | 
				
			||||||
 | 
					      "Left": [
 | 
				
			||||||
 | 
					        "Int4"
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "nullable": [
 | 
				
			||||||
 | 
					      false,
 | 
				
			||||||
 | 
					      false,
 | 
				
			||||||
 | 
					      false,
 | 
				
			||||||
 | 
					      false
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "hash": "1c5dda0e613ee57819d4c9534f3bcd8809f313026a187a2eff66fa4f7ba888a5"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -21,7 +21,7 @@
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        "ordinal": 3,
 | 
					        "ordinal": 3,
 | 
				
			||||||
        "name": "created_at",
 | 
					        "name": "created_at",
 | 
				
			||||||
        "type_info": "Timestamp"
 | 
					        "type_info": "Timestamptz"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "parameters": {
 | 
					    "parameters": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,24 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "db_name": "PostgreSQL",
 | 
					 | 
				
			||||||
  "query": "INSERT INTO folders(parent_folder_id, owner_id, folder_name) VALUES ($1, $2, $3) RETURNING folder_id",
 | 
					 | 
				
			||||||
  "describe": {
 | 
					 | 
				
			||||||
    "columns": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "ordinal": 0,
 | 
					 | 
				
			||||||
        "name": "folder_id",
 | 
					 | 
				
			||||||
        "type_info": "Uuid"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "parameters": {
 | 
					 | 
				
			||||||
      "Left": [
 | 
					 | 
				
			||||||
        "Uuid",
 | 
					 | 
				
			||||||
        "Int4",
 | 
					 | 
				
			||||||
        "Varchar"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "nullable": [
 | 
					 | 
				
			||||||
      false
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "hash": "3dd4a65d3106d742c2221c0589ac68d4621c6e351f9fbb7aa58629ff2d829234"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										17
									
								
								.sqlx/query-3faa32dd95822ae8687784817f68e48e726eedd2b7af7e52712974b4f04a8f80.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.sqlx/query-3faa32dd95822ae8687784817f68e48e726eedd2b7af7e52712974b4f04a8f80.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "db_name": "PostgreSQL",
 | 
				
			||||||
 | 
					  "query": "INSERT INTO folders(parent_folder_id, owner_id, folder_name, folder_id) VALUES ($1, $2, $3, $4)",
 | 
				
			||||||
 | 
					  "describe": {
 | 
				
			||||||
 | 
					    "columns": [],
 | 
				
			||||||
 | 
					    "parameters": {
 | 
				
			||||||
 | 
					      "Left": [
 | 
				
			||||||
 | 
					        "Uuid",
 | 
				
			||||||
 | 
					        "Int4",
 | 
				
			||||||
 | 
					        "Varchar",
 | 
				
			||||||
 | 
					        "Uuid"
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "nullable": []
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "hash": "3faa32dd95822ae8687784817f68e48e726eedd2b7af7e52712974b4f04a8f80"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "db_name": "PostgreSQL",
 | 
					  "db_name": "PostgreSQL",
 | 
				
			||||||
  "query": "SELECT\n    user_id, username, email, \n    GREATEST (\n        similarity (email, $1),\n        similarity (username, $1)\n    ) as \"similarity!\"\nFROM\n    users\nORDER BY\n    \"similarity!\" DESC",
 | 
					  "query": "SELECT\n    user_id, username, email, \n    GREATEST (\n        similarity (email, $1),\n        similarity (username, $1)\n    ) as \"similarity!\"\nFROM\n    users\nORDER BY\n    \"similarity!\" DESC\nLIMIT 20",
 | 
				
			||||||
  "describe": {
 | 
					  "describe": {
 | 
				
			||||||
    "columns": [
 | 
					    "columns": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -36,5 +36,5 @@
 | 
				
			|||||||
      null
 | 
					      null
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "hash": "8d8bf29e632723ba48a19ea52a8466424f7628e84df17178bf26eaca1cc99aca"
 | 
					  "hash": "e0d415b13ccf7aa865558395eb6997bfff50762d36cf3742470a897f4588c802"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -26,12 +26,12 @@
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        "ordinal": 4,
 | 
					        "ordinal": 4,
 | 
				
			||||||
        "name": "created_at",
 | 
					        "name": "created_at",
 | 
				
			||||||
        "type_info": "Timestamp"
 | 
					        "type_info": "Timestamptz"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "ordinal": 5,
 | 
					        "ordinal": 5,
 | 
				
			||||||
        "name": "updated_at",
 | 
					        "name": "updated_at",
 | 
				
			||||||
        "type_info": "Timestamp"
 | 
					        "type_info": "Timestamptz"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "parameters": {
 | 
					    "parameters": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        "ordinal": 3,
 | 
					        "ordinal": 3,
 | 
				
			||||||
        "name": "created_at",
 | 
					        "name": "created_at",
 | 
				
			||||||
        "type_info": "Timestamp"
 | 
					        "type_info": "Timestamptz"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "parameters": {
 | 
					    "parameters": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "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"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "db_name": "PostgreSQL",
 | 
					  "db_name": "PostgreSQL",
 | 
				
			||||||
  "query": "INSERT INTO users(username, email, hashed_password) VALUES ($1, $2, $3) RETURNING user_id",
 | 
					  "query": "INSERT INTO users(username, email, hashed_password) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING RETURNING user_id",
 | 
				
			||||||
  "describe": {
 | 
					  "describe": {
 | 
				
			||||||
    "columns": [
 | 
					    "columns": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -20,5 +20,5 @@
 | 
				
			|||||||
      false
 | 
					      false
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "hash": "879bdad048c3151e54ee70a2c316d90dcc1a0f50a1df2c7681917a2890d082cf"
 | 
					  "hash": "fb94ebf44aff9c5c56cc43ef47f571b4dc1fcdcbc595aef4d245ee2454b0a458"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										45
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -321,9 +321,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "cc"
 | 
					name = "cc"
 | 
				
			||||||
version = "1.1.7"
 | 
					version = "1.1.8"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc"
 | 
					checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "jobserver",
 | 
					 "jobserver",
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
@@ -920,9 +920,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "hyper-util"
 | 
					name = "hyper-util"
 | 
				
			||||||
version = "0.1.6"
 | 
					version = "0.1.7"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956"
 | 
					checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bytes",
 | 
					 "bytes",
 | 
				
			||||||
 "futures-util",
 | 
					 "futures-util",
 | 
				
			||||||
@@ -1259,9 +1259,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "object"
 | 
					name = "object"
 | 
				
			||||||
version = "0.36.2"
 | 
					version = "0.36.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
 | 
					checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "memchr",
 | 
					 "memchr",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -1731,18 +1731,18 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "serde"
 | 
					name = "serde"
 | 
				
			||||||
version = "1.0.204"
 | 
					version = "1.0.205"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
 | 
					checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "serde_derive",
 | 
					 "serde_derive",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "serde_derive"
 | 
					name = "serde_derive"
 | 
				
			||||||
version = "1.0.204"
 | 
					version = "1.0.205"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
 | 
					checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
@@ -1814,6 +1814,15 @@ dependencies = [
 | 
				
			|||||||
 "lazy_static",
 | 
					 "lazy_static",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "signal-hook-registry"
 | 
				
			||||||
 | 
					version = "1.4.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "libc",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "signature"
 | 
					name = "signature"
 | 
				
			||||||
version = "2.2.0"
 | 
					version = "2.2.0"
 | 
				
			||||||
@@ -2156,15 +2165,15 @@ checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "tempfile"
 | 
					name = "tempfile"
 | 
				
			||||||
version = "3.11.0"
 | 
					version = "3.12.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53"
 | 
					checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "cfg-if",
 | 
					 "cfg-if",
 | 
				
			||||||
 "fastrand",
 | 
					 "fastrand",
 | 
				
			||||||
 "once_cell",
 | 
					 "once_cell",
 | 
				
			||||||
 "rustix",
 | 
					 "rustix",
 | 
				
			||||||
 "windows-sys 0.52.0",
 | 
					 "windows-sys 0.59.0",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@@ -2255,6 +2264,7 @@ dependencies = [
 | 
				
			|||||||
 "mio",
 | 
					 "mio",
 | 
				
			||||||
 "parking_lot",
 | 
					 "parking_lot",
 | 
				
			||||||
 "pin-project-lite",
 | 
					 "pin-project-lite",
 | 
				
			||||||
 | 
					 "signal-hook-registry",
 | 
				
			||||||
 "socket2",
 | 
					 "socket2",
 | 
				
			||||||
 "tokio-macros",
 | 
					 "tokio-macros",
 | 
				
			||||||
 "windows-sys 0.52.0",
 | 
					 "windows-sys 0.52.0",
 | 
				
			||||||
@@ -2653,6 +2663,15 @@ dependencies = [
 | 
				
			|||||||
 "windows-targets 0.52.6",
 | 
					 "windows-targets 0.52.6",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "windows-sys"
 | 
				
			||||||
 | 
					version = "0.59.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "windows-targets 0.52.6",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "windows-targets"
 | 
					name = "windows-targets"
 | 
				
			||||||
version = "0.48.5"
 | 
					version = "0.48.5"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,7 +38,7 @@ sqlx = { version = "0.8", features = [
 | 
				
			|||||||
    "uuid",
 | 
					    "uuid",
 | 
				
			||||||
] }
 | 
					] }
 | 
				
			||||||
subtle = "2"
 | 
					subtle = "2"
 | 
				
			||||||
tokio = { version = "1", features = ["parking_lot", "rt-multi-thread"] }
 | 
					tokio = { version = "1", features = ["parking_lot", "rt-multi-thread", "signal"] }
 | 
				
			||||||
tokio-util = { version = "0.7" }
 | 
					tokio-util = { version = "0.7" }
 | 
				
			||||||
tower = { version = "0.4" }
 | 
					tower = { version = "0.4" }
 | 
				
			||||||
tower-http = { version = "0.5", features = [
 | 
					tower-http = { version = "0.5", features = [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1 @@
 | 
				
			|||||||
INSERT INTO folders(parent_folder_id, owner_id, folder_name)
 | 
					INSERT INTO folders(parent_folder_id, owner_id, folder_name, folder_id) VALUES ($1, $2, $3, $4)
 | 
				
			||||||
SELECT $1, owner_id, $2 FROM folders WHERE parent_folder_id = $1
 | 
					 | 
				
			||||||
RETURNING folder_id
 | 
					 | 
				
			||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
SELECT
 | 
					SELECT
 | 
				
			||||||
    username,
 | 
					    users.user_id,
 | 
				
			||||||
    permission_type as "permission_type: PermissionRaw"
 | 
					    permission_type as "permission_type: PermissionRaw"
 | 
				
			||||||
FROM
 | 
					FROM
 | 
				
			||||||
    permissions
 | 
					    permissions
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ WITH
 | 
				
			|||||||
            user_id = $1
 | 
					            user_id = $1
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
SELECT
 | 
					SELECT
 | 
				
			||||||
    folder_id
 | 
					    folder_id, owner_id, folder_name, created_at
 | 
				
			||||||
FROM
 | 
					FROM
 | 
				
			||||||
    folders
 | 
					    folders
 | 
				
			||||||
WHERE
 | 
					WHERE
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,3 +8,4 @@ FROM
 | 
				
			|||||||
    users
 | 
					    users
 | 
				
			||||||
ORDER BY
 | 
					ORDER BY
 | 
				
			||||||
    "similarity!" DESC
 | 
					    "similarity!" DESC
 | 
				
			||||||
 | 
					LIMIT 20
 | 
				
			||||||
@@ -67,10 +67,11 @@ pub async fn get_permissions(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn get_name(file_id: Uuid, pool: &Pool) -> sqlx::Result<Option<String>> {
 | 
					pub async fn get_name(file_id: Uuid, pool: &Pool) -> sqlx::Result<Option<String>> {
 | 
				
			||||||
    let record = sqlx::query!("SELECT file_name FROM files WHERE file_id = $1", file_id)
 | 
					    let name = sqlx::query!("SELECT file_name FROM files WHERE file_id = $1", file_id)
 | 
				
			||||||
        .fetch_optional(pool)
 | 
					        .fetch_optional(pool)
 | 
				
			||||||
        .await?;
 | 
					        .await?
 | 
				
			||||||
    Ok(record.map(|record| record.file_name))
 | 
					        .map(|record| record.file_name);
 | 
				
			||||||
 | 
					    Ok(name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn delete(file_id: Uuid, pool: &Pool) -> sqlx::Result<bool> {
 | 
					pub async fn delete(file_id: Uuid, pool: &Pool) -> sqlx::Result<bool> {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,10 +89,24 @@ pub async fn name_exists(parent_folder_id: Uuid, name: &str, pool: &Pool) -> sql
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Creates a folder in the database. Do not use this function to create the ROOT folder
 | 
					/// Creates a folder in the database. Do not use this function to create the ROOT folder
 | 
				
			||||||
pub async fn insert(parent_folder_id: Uuid, folder_name: &str, pool: &Pool) -> sqlx::Result<Uuid> {
 | 
					pub async fn insert(parent_folder_id: Uuid, folder_name: &str, pool: &Pool) -> sqlx::Result<Uuid> {
 | 
				
			||||||
    sqlx::query_file!("sql/create_folder.sql", parent_folder_id, folder_name)
 | 
					    let folder_id = Uuid::now_v7();
 | 
				
			||||||
        .fetch_one(pool)
 | 
					    let owner_id = get_by_id(parent_folder_id, pool)
 | 
				
			||||||
        .await
 | 
					        .await?
 | 
				
			||||||
        .map(|record| record.folder_id)
 | 
					        .ok_or(sqlx::Error::RowNotFound)?
 | 
				
			||||||
 | 
					        .owner_id;
 | 
				
			||||||
 | 
					    let result = sqlx::query_file!(
 | 
				
			||||||
 | 
					        "sql/create_folder.sql",
 | 
				
			||||||
 | 
					        parent_folder_id,
 | 
				
			||||||
 | 
					        owner_id,
 | 
				
			||||||
 | 
					        folder_name,
 | 
				
			||||||
 | 
					        folder_id
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .execute(pool)
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    if result.rows_affected() == 0 {
 | 
				
			||||||
 | 
					        return Err(sqlx::Error::RowNotFound);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Ok(folder_id)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn delete(folder_id: Uuid, pool: &Pool) -> impl Stream<Item = sqlx::Result<Uuid>> + '_ {
 | 
					pub fn delete(folder_id: Uuid, pool: &Pool) -> impl Stream<Item = sqlx::Result<Uuid>> + '_ {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,11 @@
 | 
				
			|||||||
use std::{borrow::Cow, collections::HashMap};
 | 
					use std::{borrow::Cow, collections::HashMap};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use db::folder::FolderWithoutParentId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::prelude::*;
 | 
					use crate::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(sqlx::Type, Debug, Serialize, Deserialize)]
 | 
					#[derive(sqlx::Type, Debug, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					#[serde(rename_all = "snake_case")]
 | 
				
			||||||
#[sqlx(type_name = "permission")]
 | 
					#[sqlx(type_name = "permission")]
 | 
				
			||||||
#[sqlx(rename_all = "lowercase")]
 | 
					#[sqlx(rename_all = "lowercase")]
 | 
				
			||||||
pub enum PermissionRaw {
 | 
					pub enum PermissionRaw {
 | 
				
			||||||
@@ -120,10 +123,10 @@ pub async fn insert(
 | 
				
			|||||||
pub async fn get_all_for_folder(
 | 
					pub async fn get_all_for_folder(
 | 
				
			||||||
    folder_id: Uuid,
 | 
					    folder_id: Uuid,
 | 
				
			||||||
    pool: &Pool,
 | 
					    pool: &Pool,
 | 
				
			||||||
) -> sqlx::Result<HashMap<String, PermissionRaw>> {
 | 
					) -> sqlx::Result<HashMap<i32, PermissionRaw>> {
 | 
				
			||||||
    sqlx::query_file!("sql/get_all_permissions_for_folder.sql", folder_id)
 | 
					    sqlx::query_file!("sql/get_all_permissions_for_folder.sql", folder_id)
 | 
				
			||||||
        .fetch(pool)
 | 
					        .fetch(pool)
 | 
				
			||||||
        .map_ok(|record| (record.username, record.permission_type))
 | 
					        .map_ok(|record| (record.user_id, record.permission_type))
 | 
				
			||||||
        .try_collect()
 | 
					        .try_collect()
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -135,10 +138,16 @@ pub async fn delete_for_folder(folder_id: Uuid, user_id: i32, pool: &Pool) -> sq
 | 
				
			|||||||
        .map(|_| ())
 | 
					        .map(|_| ())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn get_top_level_permitted_folders(user_id: i32, pool: &Pool) -> sqlx::Result<Vec<Uuid>> {
 | 
					pub async fn get_top_level_permitted_folders(
 | 
				
			||||||
    sqlx::query_file!("sql/get_top_level_folder.sql", user_id)
 | 
					    user_id: i32,
 | 
				
			||||||
        .fetch(pool)
 | 
					    pool: &Pool,
 | 
				
			||||||
        .map_ok(|record| record.folder_id)
 | 
					) -> sqlx::Result<Vec<FolderWithoutParentId>> {
 | 
				
			||||||
        .try_collect()
 | 
					    sqlx::query_file_as!(
 | 
				
			||||||
        .await
 | 
					        FolderWithoutParentId,
 | 
				
			||||||
 | 
					        "sql/get_top_level_folder.sql",
 | 
				
			||||||
 | 
					        user_id
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .fetch(pool)
 | 
				
			||||||
 | 
					    .try_collect()
 | 
				
			||||||
 | 
					    .await
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ pub async fn create_user(
 | 
				
			|||||||
    pool: &Pool,
 | 
					    pool: &Pool,
 | 
				
			||||||
) -> sqlx::Result<Option<i32>> {
 | 
					) -> sqlx::Result<Option<i32>> {
 | 
				
			||||||
    let Some(record) = sqlx::query!(
 | 
					    let Some(record) = sqlx::query!(
 | 
				
			||||||
        "INSERT INTO users(username, email, hashed_password) VALUES ($1, $2, $3) RETURNING user_id",
 | 
					        "INSERT INTO users(username, email, hashed_password) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING RETURNING user_id",
 | 
				
			||||||
        user_name,
 | 
					        user_name,
 | 
				
			||||||
        user_email,
 | 
					        user_email,
 | 
				
			||||||
        hashed_password
 | 
					        hashed_password
 | 
				
			||||||
@@ -80,7 +80,7 @@ pub async fn get(user_id: i32, pool: &Pool) -> sqlx::Result<Option<UserInfo>> {
 | 
				
			|||||||
    .await
 | 
					    .await
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Gets the hashed password field by either the email or th username
 | 
					/// Gets the hashed password field by either the email or the username
 | 
				
			||||||
pub async fn get_hash(search_string: &str, pool: &Pool) -> sqlx::Result<Option<(i32, Vec<u8>)>> {
 | 
					pub async fn get_hash(search_string: &str, pool: &Pool) -> sqlx::Result<Option<(i32, Vec<u8>)>> {
 | 
				
			||||||
    let record = sqlx::query!(
 | 
					    let record = sqlx::query!(
 | 
				
			||||||
        "SELECT user_id, hashed_password FROM users WHERE username = $1 OR email = $1",
 | 
					        "SELECT user_id, hashed_password FROM users WHERE username = $1 OR email = $1",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,15 +14,9 @@ pub async fn delete(
 | 
				
			|||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .can_write_guard()?;
 | 
					        .can_write_guard()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let deleted = db::file::delete(params.file_id, &state.pool)
 | 
					    db::file::delete(params.file_id, &state.pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .handle_internal("Error deleting the file")?;
 | 
					        .handle_internal("Error deleting the file")?;
 | 
				
			||||||
    if !deleted {
 | 
					 | 
				
			||||||
        return Err(GeneralError::message(
 | 
					 | 
				
			||||||
            StatusCode::NOT_FOUND,
 | 
					 | 
				
			||||||
            "Item not found",
 | 
					 | 
				
			||||||
        )); // Will not happen most of the time due to can write guard
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state
 | 
					    state
 | 
				
			||||||
        .storage
 | 
					        .storage
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ pub struct Params {
 | 
				
			|||||||
pub async fn delete(
 | 
					pub async fn delete(
 | 
				
			||||||
    State(state): State<AppState>,
 | 
					    State(state): State<AppState>,
 | 
				
			||||||
    claims: Claims,
 | 
					    claims: Claims,
 | 
				
			||||||
    Json(params): Json<Params>,
 | 
					    Query(params): Query<Params>,
 | 
				
			||||||
) -> GeneralResult<()> {
 | 
					) -> GeneralResult<()> {
 | 
				
			||||||
    let root = db::folder::get_root(claims.user_id, &state.pool)
 | 
					    let root = db::folder::get_root(claims.user_id, &state.pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					use db::{file::FileWithoutParentId, folder::FolderWithoutParentId};
 | 
				
			||||||
use tokio::try_join;
 | 
					use tokio::try_join;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::list::Params;
 | 
					use super::list::Params;
 | 
				
			||||||
@@ -6,13 +7,13 @@ use crate::prelude::*;
 | 
				
			|||||||
#[derive(Serialize, Debug)]
 | 
					#[derive(Serialize, Debug)]
 | 
				
			||||||
pub struct FolderStructure {
 | 
					pub struct FolderStructure {
 | 
				
			||||||
    #[serde(flatten)]
 | 
					    #[serde(flatten)]
 | 
				
			||||||
    folder_base: db::folder::FolderWithoutParentId,
 | 
					    folder_base: FolderWithoutParentId,
 | 
				
			||||||
    folders: Vec<FolderStructure>,
 | 
					    folders: Vec<FolderStructure>,
 | 
				
			||||||
    files: Vec<db::file::FileWithoutParentId>,
 | 
					    files: Vec<FileWithoutParentId>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<db::folder::FolderWithoutParentId> for FolderStructure {
 | 
					impl From<FolderWithoutParentId> for FolderStructure {
 | 
				
			||||||
    fn from(value: db::folder::FolderWithoutParentId) -> Self {
 | 
					    fn from(value: FolderWithoutParentId) -> Self {
 | 
				
			||||||
        FolderStructure {
 | 
					        FolderStructure {
 | 
				
			||||||
            folder_base: value,
 | 
					            folder_base: value,
 | 
				
			||||||
            folders: Vec::new(),
 | 
					            folders: Vec::new(),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@ pub struct Params {
 | 
				
			|||||||
pub async fn delete(
 | 
					pub async fn delete(
 | 
				
			||||||
    State(pool): State<Pool>,
 | 
					    State(pool): State<Pool>,
 | 
				
			||||||
    claims: Claims,
 | 
					    claims: Claims,
 | 
				
			||||||
    Json(params): Json<Params>,
 | 
					    Query(params): Query<Params>,
 | 
				
			||||||
) -> GeneralResult<StatusCode> {
 | 
					) -> GeneralResult<StatusCode> {
 | 
				
			||||||
    if params.user_id != claims.user_id {
 | 
					    if params.user_id != claims.user_id {
 | 
				
			||||||
        db::folder::get_permissions(params.folder_id, claims.user_id, &pool)
 | 
					        db::folder::get_permissions(params.folder_id, claims.user_id, &pool)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,13 +13,13 @@ pub async fn get(
 | 
				
			|||||||
    State(pool): State<Pool>,
 | 
					    State(pool): State<Pool>,
 | 
				
			||||||
    Query(params): Query<Params>,
 | 
					    Query(params): Query<Params>,
 | 
				
			||||||
    claims: Claims,
 | 
					    claims: Claims,
 | 
				
			||||||
) -> GeneralResult<Json<HashMap<String, PermissionRaw>>> {
 | 
					) -> GeneralResult<Json<HashMap<i32, PermissionRaw>>> {
 | 
				
			||||||
    db::folder::get_permissions(params.folder_id, claims.user_id, &pool)
 | 
					    db::folder::get_permissions(params.folder_id, claims.user_id, &pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .can_manage_guard()?;
 | 
					        .can_manage_guard()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let permissions = db::permissions::get_all_for_folder(params.folder_id, &pool)
 | 
					    db::permissions::get_all_for_folder(params.folder_id, &pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .handle_internal("Error getting permissions")?;
 | 
					        .handle_internal("Error getting permissions")
 | 
				
			||||||
    Ok(Json(permissions))
 | 
					        .map(Json)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,13 @@
 | 
				
			|||||||
 | 
					use db::folder::FolderWithoutParentId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::prelude::*;
 | 
					use crate::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn get_top_level(
 | 
					pub async fn get_top_level(
 | 
				
			||||||
    State(pool): State<Pool>,
 | 
					    State(pool): State<Pool>,
 | 
				
			||||||
    claims: Claims,
 | 
					    claims: Claims,
 | 
				
			||||||
) -> GeneralResult<Json<Vec<Uuid>>> {
 | 
					) -> GeneralResult<Json<Vec<FolderWithoutParentId>>> {
 | 
				
			||||||
    let folders = db::permissions::get_top_level_permitted_folders(claims.user_id, &pool)
 | 
					    db::permissions::get_top_level_permitted_folders(claims.user_id, &pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .handle_internal("Error reading from the database")?;
 | 
					        .handle_internal("Error reading from the database")
 | 
				
			||||||
    Ok(Json(folders))
 | 
					        .map(Json)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ pub async fn set(
 | 
				
			|||||||
    if params.folder_id == root {
 | 
					    if params.folder_id == root {
 | 
				
			||||||
        return Err(GeneralError::message(
 | 
					        return Err(GeneralError::message(
 | 
				
			||||||
            StatusCode::BAD_REQUEST,
 | 
					            StatusCode::BAD_REQUEST,
 | 
				
			||||||
            "Cannot delete the root folder",
 | 
					            "Cannot set permissions for the root folder",
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,6 +26,13 @@ pub async fn set(
 | 
				
			|||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .can_manage_guard()?;
 | 
					        .can_manage_guard()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if params.user_id == claims.user_id {
 | 
				
			||||||
 | 
					        return Err(GeneralError::message(
 | 
				
			||||||
 | 
					            StatusCode::BAD_REQUEST,
 | 
				
			||||||
 | 
					            "Cannot set your own permissions",
 | 
				
			||||||
 | 
					        ));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let folder_info = db::folder::get_by_id(params.folder_id, &pool)
 | 
					    let folder_info = db::folder::get_by_id(params.folder_id, &pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .handle_internal("Error getting folder info")?
 | 
					        .handle_internal("Error getting folder info")?
 | 
				
			||||||
@@ -33,7 +40,7 @@ pub async fn set(
 | 
				
			|||||||
    if folder_info.owner_id == params.user_id {
 | 
					    if folder_info.owner_id == params.user_id {
 | 
				
			||||||
        return Err(GeneralError::message(
 | 
					        return Err(GeneralError::message(
 | 
				
			||||||
            StatusCode::BAD_REQUEST,
 | 
					            StatusCode::BAD_REQUEST,
 | 
				
			||||||
            "Cannot set permissions of the folder owner",
 | 
					            "Cannot set permissions of the folder's owner",
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,11 +8,11 @@ pub struct Params {
 | 
				
			|||||||
type Response = GeneralResult<Json<db::users::UserInfo>>;
 | 
					type Response = GeneralResult<Json<db::users::UserInfo>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn get(State(pool): State<Pool>, Query(params): Query<Params>) -> Response {
 | 
					pub async fn get(State(pool): State<Pool>, Query(params): Query<Params>) -> Response {
 | 
				
			||||||
    let info = db::users::get(params.user_id, &pool)
 | 
					    db::users::get(params.user_id, &pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .handle_internal("Error getting the user")?
 | 
					        .handle_internal("Error getting the user")?
 | 
				
			||||||
        .handle(StatusCode::NOT_FOUND, "User not found")?;
 | 
					        .handle(StatusCode::NOT_FOUND, "User not found")
 | 
				
			||||||
    Ok(Json(info))
 | 
					        .map(Json)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn current(state: State<Pool>, claims: Claims) -> Response {
 | 
					pub async fn current(state: State<Pool>, claims: Claims) -> Response {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ use crate::prelude::*;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[derive(Deserialize, Debug, Validate)]
 | 
					#[derive(Deserialize, Debug, Validate)]
 | 
				
			||||||
pub struct Params {
 | 
					pub struct Params {
 | 
				
			||||||
    #[validate(email)]
 | 
					    #[validate(length(min = 3, max = 10))]
 | 
				
			||||||
    username: String,
 | 
					    username: String,
 | 
				
			||||||
    #[validate(email)]
 | 
					    #[validate(email)]
 | 
				
			||||||
    email: String,
 | 
					    email: String,
 | 
				
			||||||
@@ -15,7 +15,7 @@ pub async fn put(
 | 
				
			|||||||
    claims: Claims,
 | 
					    claims: Claims,
 | 
				
			||||||
    Json(params): Json<Params>,
 | 
					    Json(params): Json<Params>,
 | 
				
			||||||
) -> GeneralResult<Json<db::users::UserInfo>> {
 | 
					) -> GeneralResult<Json<db::users::UserInfo>> {
 | 
				
			||||||
    params.validate().handle_validation()?;
 | 
					    params.validate()?;
 | 
				
			||||||
    db::users::update(claims.user_id, ¶ms.username, ¶ms.email, &pool)
 | 
					    db::users::update(claims.user_id, ¶ms.username, ¶ms.email, &pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .handle_internal("Error updating the user")
 | 
					        .handle_internal("Error updating the user")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,7 @@ pub async fn register(
 | 
				
			|||||||
    State(pool): State<Pool>,
 | 
					    State(pool): State<Pool>,
 | 
				
			||||||
    Form(params): Form<Params>,
 | 
					    Form(params): Form<Params>,
 | 
				
			||||||
) -> GeneralResult<Json<Token>> {
 | 
					) -> GeneralResult<Json<Token>> {
 | 
				
			||||||
    params.validate().handle_validation()?;
 | 
					    params.validate()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let password = HashedBytes::hash_bytes(params.password.as_bytes()).as_bytes();
 | 
					    let password = HashedBytes::hash_bytes(params.password.as_bytes()).as_bytes();
 | 
				
			||||||
    let id = db::users::create_user(¶ms.username, ¶ms.email, &password, &pool)
 | 
					    let id = db::users::create_user(¶ms.username, ¶ms.email, &password, &pool)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,12 @@ impl IntoResponse for GeneralError {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<validator::ValidationErrors> for GeneralError {
 | 
				
			||||||
 | 
					    fn from(value: validator::ValidationErrors) -> Self {
 | 
				
			||||||
 | 
					        GeneralError::message(StatusCode::BAD_REQUEST, value.to_string())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type GeneralResult<T> = Result<T, GeneralError>;
 | 
					pub type GeneralResult<T> = Result<T, GeneralError>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait ErrorHandlingExt<T>
 | 
					pub trait ErrorHandlingExt<T>
 | 
				
			||||||
@@ -92,19 +98,6 @@ pub trait ItemNotFoundExt<T> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl<T> ItemNotFoundExt<T> for Option<T> {
 | 
					impl<T> ItemNotFoundExt<T> for Option<T> {
 | 
				
			||||||
    fn item_not_found(self) -> GeneralResult<T> {
 | 
					    fn item_not_found(self) -> GeneralResult<T> {
 | 
				
			||||||
        self.ok_or(GeneralError::const_message(
 | 
					        self.handle(StatusCode::NOT_FOUND, "Item not found")
 | 
				
			||||||
            StatusCode::NOT_FOUND,
 | 
					 | 
				
			||||||
            "Item not found",
 | 
					 | 
				
			||||||
        ))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub trait ValidationExt<T> {
 | 
					 | 
				
			||||||
    fn handle_validation(self) -> GeneralResult<T>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T> ValidationExt<T> for Result<T, validator::ValidationErrors> {
 | 
					 | 
				
			||||||
    fn handle_validation(self) -> GeneralResult<T> {
 | 
					 | 
				
			||||||
        self.map_err(|err| GeneralError::message(StatusCode::BAD_REQUEST, err.to_string()))
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -10,7 +10,7 @@ use std::{env, net::Ipv4Addr};
 | 
				
			|||||||
use auth::HashedBytes;
 | 
					use auth::HashedBytes;
 | 
				
			||||||
use axum::{extract::FromRef, routing::post, Router};
 | 
					use axum::{extract::FromRef, routing::post, Router};
 | 
				
			||||||
use file_storage::FileStorage;
 | 
					use file_storage::FileStorage;
 | 
				
			||||||
use tokio::net::TcpListener;
 | 
					use tokio::{net::TcpListener, signal};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Pool = sqlx::postgres::PgPool;
 | 
					type Pool = sqlx::postgres::PgPool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,11 +66,37 @@ async fn main() -> anyhow::Result<()> {
 | 
				
			|||||||
    let addr = (Ipv4Addr::UNSPECIFIED, 3000);
 | 
					    let addr = (Ipv4Addr::UNSPECIFIED, 3000);
 | 
				
			||||||
    let listener = TcpListener::bind(addr).await?;
 | 
					    let listener = TcpListener::bind(addr).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    axum::serve(listener, router).await?;
 | 
					    axum::serve(listener, router)
 | 
				
			||||||
 | 
					        .with_graceful_shutdown(shutdown_signal())
 | 
				
			||||||
 | 
					        .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async fn shutdown_signal() {
 | 
				
			||||||
 | 
					    let ctrl_c = async {
 | 
				
			||||||
 | 
					        signal::ctrl_c()
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					            .expect("failed to install Ctrl+C handler");
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[cfg(unix)]
 | 
				
			||||||
 | 
					    let terminate = async {
 | 
				
			||||||
 | 
					        signal::unix::signal(signal::unix::SignalKind::terminate())
 | 
				
			||||||
 | 
					            .expect("failed to install signal handler")
 | 
				
			||||||
 | 
					            .recv()
 | 
				
			||||||
 | 
					            .await;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[cfg(not(unix))]
 | 
				
			||||||
 | 
					    let terminate = std::future::pending::<()>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tokio::select! {
 | 
				
			||||||
 | 
					        () = ctrl_c => {},
 | 
				
			||||||
 | 
					        () = terminate => {},
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn app(state: AppState) -> Router {
 | 
					fn app(state: AppState) -> Router {
 | 
				
			||||||
    use axum::{http::header, routing::get};
 | 
					    use axum::{http::header, routing::get};
 | 
				
			||||||
    use endpoints::{
 | 
					    use endpoints::{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,7 @@
 | 
				
			|||||||
pub(crate) use crate::{
 | 
					pub(crate) use crate::{
 | 
				
			||||||
    auth::Claims,
 | 
					    auth::Claims,
 | 
				
			||||||
    db::{self, permissions::PermissionExt as _},
 | 
					    db::{self, permissions::PermissionExt as _},
 | 
				
			||||||
    errors::{
 | 
					    errors::{ErrorHandlingExt as _, GeneralError, GeneralResult, ItemNotFoundExt as _},
 | 
				
			||||||
        ErrorHandlingExt as _, GeneralError, GeneralResult, ItemNotFoundExt as _,
 | 
					 | 
				
			||||||
        ValidationExt as _,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    AppState, Pool,
 | 
					    AppState, Pool,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
pub use axum::{
 | 
					pub use axum::{
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user