diff options
20 files changed, 201 insertions, 319 deletions
diff --git a/server/.sqlx/query-0c60083eadb7c144198ce6586ce5abe50b321b85febfc5a72157990753e404e2.json b/server/.sqlx/query-0c60083eadb7c144198ce6586ce5abe50b321b85febfc5a72157990753e404e2.json deleted file mode 100644 index 6018cd3..0000000 --- a/server/.sqlx/query-0c60083eadb7c144198ce6586ce5abe50b321b85febfc5a72157990753e404e2.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "db_name": "MySQL", - "query": "SELECT id,username,name,dn,review_users.role AS role FROM users JOIN review_users ON review_users.user=id WHERE review_users.review=? ORDER BY role,username,id", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 - } - }, - { - "ordinal": 1, - "name": "username", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", - "char_set": 224, - "max_size": 1024 - } - }, - { - "ordinal": 2, - "name": "name", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "char_set": 224, - "max_size": 4096 - } - }, - { - "ordinal": 3, - "name": "dn", - "type_info": { - "type": "VarString", - "flags": "", - "char_set": 224, - "max_size": 1024 - } - }, - { - "ordinal": 4, - "name": "role", - "type_info": { - "type": "Tiny", - "flags": "NOT_NULL | UNSIGNED", - "char_set": 63, - "max_size": 3 - } - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false, - false, - true, - false - ] - }, - "hash": "0c60083eadb7c144198ce6586ce5abe50b321b85febfc5a72157990753e404e2" -} diff --git a/server/.sqlx/query-323b0d90d6c3bccbf7708556f7588486032bb85b883832366aae944d1e80e589.json b/server/.sqlx/query-1b2b0395773a2207fd7c75ae14151764df6120375321d88455a1ad09fb0abe66.json index edc104b..c332e8a 100644 --- a/server/.sqlx/query-323b0d90d6c3bccbf7708556f7588486032bb85b883832366aae944d1e80e589.json +++ b/server/.sqlx/query-1b2b0395773a2207fd7c75ae14151764df6120375321d88455a1ad09fb0abe66.json @@ -1,30 +1,20 @@ { "db_name": "MySQL", - "query": "SELECT id, username, name, dn, default_role, maintainer FROM users JOIN project_users ON project_users.user=users.id WHERE project_users.project=?", + "query": "SELECT id, name, dn, default_role, maintainer FROM users JOIN project_users ON project_users.user=users.id WHERE project_users.project=?", "describe": { "columns": [ { "ordinal": 0, "name": "id", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 - } - }, - { - "ordinal": 1, - "name": "username", - "type_info": { "type": "VarString", - "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", "char_set": 224, - "max_size": 1024 + "max_size": 512 } }, { - "ordinal": 2, + "ordinal": 1, "name": "name", "type_info": { "type": "VarString", @@ -34,7 +24,7 @@ } }, { - "ordinal": 3, + "ordinal": 2, "name": "dn", "type_info": { "type": "VarString", @@ -44,7 +34,7 @@ } }, { - "ordinal": 4, + "ordinal": 3, "name": "default_role", "type_info": { "type": "Tiny", @@ -54,7 +44,7 @@ } }, { - "ordinal": 5, + "ordinal": 4, "name": "maintainer", "type_info": { "type": "Tiny", @@ -70,11 +60,10 @@ "nullable": [ false, false, - false, true, false, false ] }, - "hash": "323b0d90d6c3bccbf7708556f7588486032bb85b883832366aae944d1e80e589" + "hash": "1b2b0395773a2207fd7c75ae14151764df6120375321d88455a1ad09fb0abe66" } diff --git a/server/.sqlx/query-21e286004af94c0a0e26a4fe494b4a858fc02e4d63cec67231f837748a9f9702.json b/server/.sqlx/query-21e286004af94c0a0e26a4fe494b4a858fc02e4d63cec67231f837748a9f9702.json deleted file mode 100644 index 4abfa06..0000000 --- a/server/.sqlx/query-21e286004af94c0a0e26a4fe494b4a858fc02e4d63cec67231f837748a9f9702.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "MySQL", - "query": "INSERT INTO projects (title, description, remote, main_branch) VALUES (?, ?, ?, ?)", - "describe": { - "columns": [], - "parameters": { - "Right": 4 - }, - "nullable": [] - }, - "hash": "21e286004af94c0a0e26a4fe494b4a858fc02e4d63cec67231f837748a9f9702" -} diff --git a/server/.sqlx/query-d60078d46c209e113e078856951ac0b61416fabb63da0376ba64c331f1867053.json b/server/.sqlx/query-3864a730b1bcee1f511748360f92af157f36f3d92a667c0adc06c100cc495c67.json index 7985a71..e277262 100644 --- a/server/.sqlx/query-d60078d46c209e113e078856951ac0b61416fabb63da0376ba64c331f1867053.json +++ b/server/.sqlx/query-3864a730b1bcee1f511748360f92af157f36f3d92a667c0adc06c100cc495c67.json @@ -1,6 +1,6 @@ { "db_name": "MySQL", - "query": "SELECT reviews.id AS id,project,title,description,state,progress,branch,archived,users.id AS user_id,users.username AS username,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE reviews.id=?", + "query": "SELECT reviews.id AS id,title,description,state,progress,branch,archived,users.id AS user_id,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE project=? AND branch=?", "describe": { "columns": [ { @@ -15,16 +15,6 @@ }, { "ordinal": 1, - "name": "project", - "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | MULTIPLE_KEY | UNSIGNED | NO_DEFAULT_VALUE", - "char_set": 63, - "max_size": 20 - } - }, - { - "ordinal": 2, "name": "title", "type_info": { "type": "VarString", @@ -34,7 +24,7 @@ } }, { - "ordinal": 3, + "ordinal": 2, "name": "description", "type_info": { "type": "Blob", @@ -44,7 +34,7 @@ } }, { - "ordinal": 4, + "ordinal": 3, "name": "state", "type_info": { "type": "Tiny", @@ -54,7 +44,7 @@ } }, { - "ordinal": 5, + "ordinal": 4, "name": "progress", "type_info": { "type": "Float", @@ -64,7 +54,7 @@ } }, { - "ordinal": 6, + "ordinal": 5, "name": "branch", "type_info": { "type": "VarString", @@ -74,7 +64,7 @@ } }, { - "ordinal": 7, + "ordinal": 6, "name": "archived", "type_info": { "type": "Tiny", @@ -84,27 +74,17 @@ } }, { - "ordinal": 8, + "ordinal": 7, "name": "user_id", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 - } - }, - { - "ordinal": 9, - "name": "username", - "type_info": { "type": "VarString", - "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", "char_set": 224, - "max_size": 1024 + "max_size": 512 } }, { - "ordinal": 10, + "ordinal": 8, "name": "name", "type_info": { "type": "VarString", @@ -114,7 +94,7 @@ } }, { - "ordinal": 11, + "ordinal": 9, "name": "user_dn", "type_info": { "type": "VarString", @@ -125,7 +105,7 @@ } ], "parameters": { - "Right": 1 + "Right": 2 }, "nullable": [ false, @@ -137,10 +117,8 @@ false, false, false, - false, - false, true ] }, - "hash": "d60078d46c209e113e078856951ac0b61416fabb63da0376ba64c331f1867053" + "hash": "3864a730b1bcee1f511748360f92af157f36f3d92a667c0adc06c100cc495c67" } diff --git a/server/.sqlx/query-c75ed143fca19b2d827d589ce115a989097782d7f86a1fbfe7687cafb33e040c.json b/server/.sqlx/query-4314c7a7be9e055f82ede8e091cb376fe0d9e580993d47b61c8d77af0fd1ef64.json index 7a582af..c6277c7 100644 --- a/server/.sqlx/query-c75ed143fca19b2d827d589ce115a989097782d7f86a1fbfe7687cafb33e040c.json +++ b/server/.sqlx/query-4314c7a7be9e055f82ede8e091cb376fe0d9e580993d47b61c8d77af0fd1ef64.json @@ -1,30 +1,20 @@ { "db_name": "MySQL", - "query": "SELECT id,username,name,dn FROM users ORDER BY username LIMIT ? OFFSET ?", + "query": "SELECT id,name,dn,review_users.role AS role FROM users JOIN review_users ON review_users.user=id WHERE review_users.review=? ORDER BY role,id", "describe": { "columns": [ { "ordinal": 0, "name": "id", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 - } - }, - { - "ordinal": 1, - "name": "username", - "type_info": { "type": "VarString", - "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", "char_set": 224, - "max_size": 1024 + "max_size": 512 } }, { - "ordinal": 2, + "ordinal": 1, "name": "name", "type_info": { "type": "VarString", @@ -34,7 +24,7 @@ } }, { - "ordinal": 3, + "ordinal": 2, "name": "dn", "type_info": { "type": "VarString", @@ -42,17 +32,27 @@ "char_set": 224, "max_size": 1024 } + }, + { + "ordinal": 3, + "name": "role", + "type_info": { + "type": "Tiny", + "flags": "NOT_NULL | UNSIGNED", + "char_set": 63, + "max_size": 3 + } } ], "parameters": { - "Right": 2 + "Right": 1 }, "nullable": [ false, false, - false, - true + true, + false ] }, - "hash": "c75ed143fca19b2d827d589ce115a989097782d7f86a1fbfe7687cafb33e040c" + "hash": "4314c7a7be9e055f82ede8e091cb376fe0d9e580993d47b61c8d77af0fd1ef64" } diff --git a/server/.sqlx/query-498432f84ea2c01707cc92a490ca116a3d45c7da646182e8e5153ac5b31c8d6f.json b/server/.sqlx/query-498432f84ea2c01707cc92a490ca116a3d45c7da646182e8e5153ac5b31c8d6f.json index b10c944..5215f19 100644 --- a/server/.sqlx/query-498432f84ea2c01707cc92a490ca116a3d45c7da646182e8e5153ac5b31c8d6f.json +++ b/server/.sqlx/query-498432f84ea2c01707cc92a490ca116a3d45c7da646182e8e5153ac5b31c8d6f.json @@ -7,10 +7,10 @@ "ordinal": 0, "name": "count", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 + "type": "VarString", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", + "char_set": 224, + "max_size": 512 } } ], diff --git a/server/.sqlx/query-51f58915888d2523f6de00e206ea36137a50e7b8871751c631edb738db2cd197.json b/server/.sqlx/query-51f58915888d2523f6de00e206ea36137a50e7b8871751c631edb738db2cd197.json index d6650fd..942c054 100644 --- a/server/.sqlx/query-51f58915888d2523f6de00e206ea36137a50e7b8871751c631edb738db2cd197.json +++ b/server/.sqlx/query-51f58915888d2523f6de00e206ea36137a50e7b8871751c631edb738db2cd197.json @@ -7,10 +7,10 @@ "ordinal": 0, "name": "id", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 + "type": "VarString", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", + "char_set": 224, + "max_size": 512 } }, { diff --git a/server/.sqlx/query-bfbd002137bcf942b9911eac9cce4b4592616cad37afdb2b1e40bd38cbf2190c.json b/server/.sqlx/query-5d34251e2084507d7bc10c11df2f01e4e21c83d0fa03b917e5792b8753f32726.json index 61a445f..9d60686 100644 --- a/server/.sqlx/query-bfbd002137bcf942b9911eac9cce4b4592616cad37afdb2b1e40bd38cbf2190c.json +++ b/server/.sqlx/query-5d34251e2084507d7bc10c11df2f01e4e21c83d0fa03b917e5792b8753f32726.json @@ -1,16 +1,16 @@ { "db_name": "MySQL", - "query": "SELECT id,dn FROM users WHERE username=?", + "query": "SELECT id,dn FROM users ORDER BY id", "describe": { "columns": [ { "ordinal": 0, "name": "id", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 + "type": "VarString", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", + "char_set": 224, + "max_size": 512 } }, { @@ -25,12 +25,12 @@ } ], "parameters": { - "Right": 1 + "Right": 0 }, "nullable": [ false, true ] }, - "hash": "bfbd002137bcf942b9911eac9cce4b4592616cad37afdb2b1e40bd38cbf2190c" + "hash": "5d34251e2084507d7bc10c11df2f01e4e21c83d0fa03b917e5792b8753f32726" } diff --git a/server/.sqlx/query-5ebc001294b03e0eadf76878ff3e95fc42a1ee1bec8f145d4a5ed4f94d474fa4.json b/server/.sqlx/query-91e21f94ae4a7a6ff3234ded1c4556dc42ac9158578112c01d7e5f5428eadac4.json index c11e1fb..d3038a4 100644 --- a/server/.sqlx/query-5ebc001294b03e0eadf76878ff3e95fc42a1ee1bec8f145d4a5ed4f94d474fa4.json +++ b/server/.sqlx/query-91e21f94ae4a7a6ff3234ded1c4556dc42ac9158578112c01d7e5f5428eadac4.json @@ -1,26 +1,26 @@ { "db_name": "MySQL", - "query": "SELECT id,username,dn FROM users ORDER BY username", + "query": "SELECT id,name,dn FROM users ORDER BY id LIMIT ? OFFSET ?", "describe": { "columns": [ { "ordinal": 0, "name": "id", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 + "type": "VarString", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", + "char_set": 224, + "max_size": 512 } }, { "ordinal": 1, - "name": "username", + "name": "name", "type_info": { "type": "VarString", - "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", + "flags": "NOT_NULL", "char_set": 224, - "max_size": 1024 + "max_size": 4096 } }, { @@ -35,7 +35,7 @@ } ], "parameters": { - "Right": 0 + "Right": 2 }, "nullable": [ false, @@ -43,5 +43,5 @@ true ] }, - "hash": "5ebc001294b03e0eadf76878ff3e95fc42a1ee1bec8f145d4a5ed4f94d474fa4" + "hash": "91e21f94ae4a7a6ff3234ded1c4556dc42ac9158578112c01d7e5f5428eadac4" } diff --git a/server/.sqlx/query-940807355ceddb03b2b69306d30b081c4855858cd710399f9328075e885704fd.json b/server/.sqlx/query-940807355ceddb03b2b69306d30b081c4855858cd710399f9328075e885704fd.json deleted file mode 100644 index 412ba1f..0000000 --- a/server/.sqlx/query-940807355ceddb03b2b69306d30b081c4855858cd710399f9328075e885704fd.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "MySQL", - "query": "INSERT IGNORE INTO users (username,dn) VALUES (?,?), (?,?)", - "describe": { - "columns": [], - "parameters": { - "Right": 4 - }, - "nullable": [] - }, - "hash": "940807355ceddb03b2b69306d30b081c4855858cd710399f9328075e885704fd" -} diff --git a/server/.sqlx/query-e8f3b6fd1666b9a317ee98fd8aa380e32ed83aee297d7d84b469f4fd068cedeb.json b/server/.sqlx/query-956140cf5bb8421762ee55e7ab7ce179eac7fb43ee9fb4a0c35ef3792a2df831.json index 930ff79..22a6d40 100644 --- a/server/.sqlx/query-e8f3b6fd1666b9a317ee98fd8aa380e32ed83aee297d7d84b469f4fd068cedeb.json +++ b/server/.sqlx/query-956140cf5bb8421762ee55e7ab7ce179eac7fb43ee9fb4a0c35ef3792a2df831.json @@ -1,6 +1,6 @@ { "db_name": "MySQL", - "query": "SELECT reviews.id AS id,title,state,progress,users.id AS user_id,users.username AS username,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE project=? ORDER BY id DESC LIMIT ? OFFSET ?", + "query": "SELECT reviews.id AS id,title,state,progress,users.id AS user_id,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE project=? ORDER BY id DESC LIMIT ? OFFSET ?", "describe": { "columns": [ { @@ -47,24 +47,14 @@ "ordinal": 4, "name": "user_id", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 - } - }, - { - "ordinal": 5, - "name": "username", - "type_info": { "type": "VarString", - "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", "char_set": 224, - "max_size": 1024 + "max_size": 512 } }, { - "ordinal": 6, + "ordinal": 5, "name": "name", "type_info": { "type": "VarString", @@ -74,7 +64,7 @@ } }, { - "ordinal": 7, + "ordinal": 6, "name": "user_dn", "type_info": { "type": "VarString", @@ -94,9 +84,8 @@ false, false, false, - false, true ] }, - "hash": "e8f3b6fd1666b9a317ee98fd8aa380e32ed83aee297d7d84b469f4fd068cedeb" + "hash": "956140cf5bb8421762ee55e7ab7ce179eac7fb43ee9fb4a0c35ef3792a2df831" } diff --git a/server/.sqlx/query-8537211b442452b1e5e0ddd710a924d3552e8aceb50d37d969c83fd7ff3920c5.json b/server/.sqlx/query-9a7d3f823cc6d5978a77ae4bfff82ab8dccd2e48936f8735d5bf6ec79a38ecce.json index 3c25e9a..47eca1c 100644 --- a/server/.sqlx/query-8537211b442452b1e5e0ddd710a924d3552e8aceb50d37d969c83fd7ff3920c5.json +++ b/server/.sqlx/query-9a7d3f823cc6d5978a77ae4bfff82ab8dccd2e48936f8735d5bf6ec79a38ecce.json @@ -1,30 +1,20 @@ { "db_name": "MySQL", - "query": "SELECT id,username,name,dn,project_users.default_role AS role FROM users JOIN project_users ON project_users.user=id WHERE project_users.project=? ORDER BY role,username,id", + "query": "SELECT id,name,dn,project_users.default_role AS role FROM users JOIN project_users ON project_users.user=id WHERE project_users.project=? ORDER BY role,id", "describe": { "columns": [ { "ordinal": 0, "name": "id", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 - } - }, - { - "ordinal": 1, - "name": "username", - "type_info": { "type": "VarString", - "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", "char_set": 224, - "max_size": 1024 + "max_size": 512 } }, { - "ordinal": 2, + "ordinal": 1, "name": "name", "type_info": { "type": "VarString", @@ -34,7 +24,7 @@ } }, { - "ordinal": 3, + "ordinal": 2, "name": "dn", "type_info": { "type": "VarString", @@ -44,7 +34,7 @@ } }, { - "ordinal": 4, + "ordinal": 3, "name": "role", "type_info": { "type": "Tiny", @@ -60,10 +50,9 @@ "nullable": [ false, false, - false, true, false ] }, - "hash": "8537211b442452b1e5e0ddd710a924d3552e8aceb50d37d969c83fd7ff3920c5" + "hash": "9a7d3f823cc6d5978a77ae4bfff82ab8dccd2e48936f8735d5bf6ec79a38ecce" } diff --git a/server/.sqlx/query-a3929af470685bfea9b913dd94f4749fcf1f80cc0389cf3f84f0864a4bfece6f.json b/server/.sqlx/query-a3929af470685bfea9b913dd94f4749fcf1f80cc0389cf3f84f0864a4bfece6f.json new file mode 100644 index 0000000..6f761ee --- /dev/null +++ b/server/.sqlx/query-a3929af470685bfea9b913dd94f4749fcf1f80cc0389cf3f84f0864a4bfece6f.json @@ -0,0 +1,12 @@ +{ + "db_name": "MySQL", + "query": "INSERT INTO projects (id, title, description, remote, main_branch) VALUES (?, ?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 5 + }, + "nullable": [] + }, + "hash": "a3929af470685bfea9b913dd94f4749fcf1f80cc0389cf3f84f0864a4bfece6f" +} diff --git a/server/.sqlx/query-b93e2879cf7334469d3ceb1a49dbf5975b623da8c99241f30e8c042849d7fd8e.json b/server/.sqlx/query-b93e2879cf7334469d3ceb1a49dbf5975b623da8c99241f30e8c042849d7fd8e.json index 93fa0bd..158583c 100644 --- a/server/.sqlx/query-b93e2879cf7334469d3ceb1a49dbf5975b623da8c99241f30e8c042849d7fd8e.json +++ b/server/.sqlx/query-b93e2879cf7334469d3ceb1a49dbf5975b623da8c99241f30e8c042849d7fd8e.json @@ -7,10 +7,10 @@ "ordinal": 0, "name": "id", "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "char_set": 63, - "max_size": 20 + "type": "VarString", + "flags": "NOT_NULL | PRIMARY_KEY | NO_DEFAULT_VALUE", + "char_set": 224, + "max_size": 512 } }, { diff --git a/server/.sqlx/query-d1934a970a5bef4df382ea119c22ff28262a3762add33f8f96f6838312b6b43f.json b/server/.sqlx/query-d1934a970a5bef4df382ea119c22ff28262a3762add33f8f96f6838312b6b43f.json new file mode 100644 index 0000000..26b2d60 --- /dev/null +++ b/server/.sqlx/query-d1934a970a5bef4df382ea119c22ff28262a3762add33f8f96f6838312b6b43f.json @@ -0,0 +1,25 @@ +{ + "db_name": "MySQL", + "query": "SELECT dn FROM users WHERE id=?", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "dn", + "type_info": { + "type": "VarString", + "flags": "", + "char_set": 224, + "max_size": 1024 + } + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true + ] + }, + "hash": "d1934a970a5bef4df382ea119c22ff28262a3762add33f8f96f6838312b6b43f" +} diff --git a/server/migrations/1_initial_eyeballs.sql b/server/migrations/1_initial_eyeballs.sql index b839c42..6dcd8f1 100644 --- a/server/migrations/1_initial_eyeballs.sql +++ b/server/migrations/1_initial_eyeballs.sql @@ -1,5 +1,5 @@ CREATE TABLE IF NOT EXISTS projects ( - id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, + id VARCHAR(128) NOT NULL PRIMARY KEY, title VARCHAR(1024) NOT NULL, description MEDIUMTEXT NOT NULL DEFAULT '', remote VARCHAR(2048) NOT NULL, @@ -7,15 +7,14 @@ CREATE TABLE IF NOT EXISTS projects ( ); CREATE TABLE IF NOT EXISTS users ( - id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, - username VARCHAR(256) NOT NULL UNIQUE, + id VARCHAR(128) NOT NULL PRIMARY KEY, name VARCHAR(1024) NOT NULL DEFAULT '', dn VARCHAR(256) NULL ); CREATE TABLE IF NOT EXISTS project_users ( - project BIGINT UNSIGNED NOT NULL, - user BIGINT UNSIGNED NOT NULL, + project VARCHAR(128) NOT NULL, + user VARCHAR(128) NOT NULL, default_role TINYINT UNSIGNED NOT NULL, maintainer BOOLEAN NOT NULL DEFAULT 0, PRIMARY KEY (project, user), @@ -33,8 +32,8 @@ CREATE TABLE IF NOT EXISTS project_users ( CREATE TABLE IF NOT EXISTS reviews ( id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, - project BIGINT UNSIGNED NOT NULL, - owner BIGINT UNSIGNED NOT NULL, + project VARCHAR(128) NOT NULL, + owner VARCHAR(128) NOT NULL, title VARCHAR(1024) NOT NULL, description MEDIUMTEXT NOT NULL DEFAULT '', state TINYINT UNSIGNED NOT NULL DEFAULT 0, @@ -55,7 +54,7 @@ CREATE TABLE IF NOT EXISTS reviews ( CREATE TABLE IF NOT EXISTS review_users ( review BIGINT UNSIGNED NOT NULL, - user BIGINT UNSIGNED NOT NULL, + user VARCHAR(128) NOT NULL, role TINYINT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (review, user), diff --git a/server/src/api_model.rs b/server/src/api_model.rs index 1b0d7b2..6c614e5 100644 --- a/server/src/api_model.rs +++ b/server/src/api_model.rs @@ -18,10 +18,8 @@ pub enum UserReviewRole { #[derive(Debug, Deserialize, Serialize, PartialEq, ToSchema)] pub struct User { - #[schema(example = 1337u64)] - pub id: u64, #[schema(example = "jsmith")] - pub username: String, + pub id: String, #[schema(example = "John Smith")] pub name: String, #[schema(example = true)] @@ -113,8 +111,8 @@ pub struct ProjectUserEntryData { #[derive(Debug, Deserialize, PartialEq, Serialize, ToSchema)] pub struct Project { - #[schema(example = 1u64)] - pub id: u64, + #[schema(example = "fake")] + pub id: String, #[schema(example = "FAKE: Features All Kids Erase")] pub title: String, #[schema(example = "Example project")] @@ -140,8 +138,8 @@ pub struct ProjectData<'r> { #[derive(Deserialize, Serialize, ToSchema)] pub struct ProjectEntry { - #[schema(example = 1u64)] - pub id: u64, + #[schema(example = "fake")] + pub id: String, #[schema(example = "FAKE: Features All Kids Erase")] pub title: String, } diff --git a/server/src/auth.rs b/server/src/auth.rs index 4889f78..1b7ea89 100644 --- a/server/src/auth.rs +++ b/server/src/auth.rs @@ -74,7 +74,7 @@ struct LdapState { #[derive(Debug, Deserialize, Serialize)] pub struct Session { - pub user_id: u64, + pub user_id: String, session_id: u32, remote: String, } @@ -142,7 +142,7 @@ impl<'r> FromRequest<'r> for Session { fn new_session( sessions: &State<Sessions>, - user_id: u64, + user_id: String, remote: String, max_age: Duration, ) -> Session { @@ -209,17 +209,21 @@ async fn login( mut db: Connection<Db>, login: Form<Login<'_>>, ) -> Result<Json<api_model::StatusResponse>, Unauthorized<&'static str>> { - let (user_id, maybe_dn) = - sqlx::query!("SELECT id,dn FROM users WHERE username=?", login.username) - .fetch_one(&mut **db) - .map_ok(|r| (r.id, r.dn)) - .map_err(|_| Unauthorized("Unknown username or password")) - .await?; + let maybe_dn = sqlx::query!("SELECT dn FROM users WHERE id=?", login.username) + .fetch_one(&mut **db) + .map_ok(|r| r.dn) + .map_err(|_| Unauthorized("Unknown username or password")) + .await?; if let Some(dn) = maybe_dn { if authenticate(ldap_state, dn.as_str(), login.password).await { let max_age = Duration::days(i64::from(auth_config.session_max_age_days)); - let session = new_session(sessions, user_id, ipaddr.to_string(), max_age); + let session = new_session( + sessions, + login.username.to_string(), + ipaddr.to_string(), + max_age, + ); let cookie = Cookie::build((SESSION_COOKIE, json::to_string(&session).unwrap())) .path("/api") @@ -331,16 +335,16 @@ async fn sync_ldap( // TODO: Insert/Update name as well as dn. - let db_users = sqlx::query!("SELECT id,username,dn FROM users ORDER BY username") + let db_users = sqlx::query!("SELECT id,dn FROM users ORDER BY id") .fetch(&mut *tx) - .map_ok(|r| (r.id, r.username, r.dn)) + .map_ok(|r| (r.id, r.dn)) .try_collect::<Vec<_>>() .await .unwrap(); let mut new_users: Vec<(String, String)> = Vec::new(); - let mut updated_users: Vec<(u64, String)> = Vec::new(); - let mut old_users: Vec<u64> = Vec::new(); + let mut updated_users: Vec<(String, String)> = Vec::new(); + let mut old_users: Vec<String> = Vec::new(); let mut db_user = db_users.iter().peekable(); @@ -349,16 +353,16 @@ async fn sync_ldap( let uid = se.attrs.get("uid").unwrap().first().unwrap(); loop { if let Some(du) = db_user.peek() { - match du.1.cmp(uid) { + match du.0.cmp(uid) { Ordering::Equal => { - if du.2.as_ref().is_none_or(|x| *x != se.dn) { - updated_users.push((du.0, se.dn)); + if du.1.as_ref().is_none_or(|x| *x != se.dn) { + updated_users.push((du.0.clone(), se.dn)); } db_user.next(); break; } Ordering::Less => { - old_users.push(du.0); + old_users.push(du.0.clone()); db_user.next(); continue; } @@ -372,7 +376,7 @@ async fn sync_ldap( if !new_users.is_empty() { let mut query_builder: sqlx::QueryBuilder<sqlx::MySql> = - sqlx::QueryBuilder::new("INSERT INTO users (username,dn) VALUES"); + sqlx::QueryBuilder::new("INSERT INTO users (id,dn) VALUES"); let mut first = true; for pair in new_users { @@ -443,7 +447,7 @@ async fn run_import(rocket: Rocket<Build>) -> fairing::Result { async fn run_import(rocket: Rocket<Build>) -> fairing::Result { match Db::fetch(&rocket) { Some(db) => match sqlx::query!( - "INSERT IGNORE INTO users (username,dn) VALUES (?,?), (?,?)", + "INSERT IGNORE INTO users (id,dn) VALUES (?,?), (?,?)", "user", "user", "other", diff --git a/server/src/main.rs b/server/src/main.rs index 88546cb..e48cfb7 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -10,6 +10,7 @@ use rocket::serde::json::Json; use rocket::{futures, Build, Rocket}; use rocket_db_pools::{sqlx, Connection, Database}; use sqlx::Acquire; +use std::path::PathBuf; use utoipa::OpenApi; use utoipa_swagger_ui::SwaggerUi; @@ -132,16 +133,15 @@ async fn projects( async fn get_project( db: &mut Connection<Db>, - projectid: u64, + projectid: &str, ) -> Result<Json<api_model::Project>, NotFound<&'static str>> { let users = sqlx::query!( - "SELECT id, username, name, dn, default_role, maintainer FROM users JOIN project_users ON project_users.user=users.id WHERE project_users.project=?", + "SELECT id, name, dn, default_role, maintainer FROM users JOIN project_users ON project_users.user=users.id WHERE project_users.project=?", projectid) .fetch(&mut ***db) .map_ok(|r| api_model::ProjectUserEntry { user: api_model::User { id: r.id, - username: r.username, name: r.name, active: r.dn.is_some(), }, @@ -184,7 +184,7 @@ async fn get_project( async fn project( mut db: Connection<Db>, _session: auth::Session, - projectid: u64, + projectid: &str, ) -> Result<Json<api_model::Project>, NotFound<&'static str>> { get_project(&mut db, projectid).await } @@ -197,26 +197,25 @@ async fn project( ("session" = []), ), )] -#[post("/project/new", data = "<data>")] +#[post("/project/<projectid>/new", data = "<data>")] async fn project_new( mut db: Connection<Db>, session: auth::Session, + projectid: &str, data: Json<api_model::ProjectData<'_>>, ) -> Json<api_model::Project> { - let projectid: u64; - { let mut tx = db.begin().await.unwrap(); - projectid = sqlx::query!( - "INSERT INTO projects (title, description, remote, main_branch) VALUES (?, ?, ?, ?)", + sqlx::query!( + "INSERT INTO projects (id, title, description, remote, main_branch) VALUES (?, ?, ?, ?, ?)", + projectid, data.title.unwrap_or("Unnamed"), data.description.unwrap_or(""), data.remote.unwrap_or(""), data.main_branch.unwrap_or("main"), ) .execute(&mut *tx) - .map_ok(|r| r.last_insert_id()) .await .unwrap(); @@ -236,7 +235,7 @@ async fn project_new( async fn project_check_maintainer( db: &mut Connection<Db>, session: auth::Session, - projectid: u64, + projectid: &str, ) -> Result<&'static str, Custom<&'static str>> { let is_maintainer = sqlx::query!( "SELECT COUNT(user) AS count FROM project_users WHERE project=? AND user=? AND maintainer=TRUE", @@ -273,7 +272,7 @@ async fn project_check_maintainer( async fn project_update( mut db: Connection<Db>, session: auth::Session, - projectid: u64, + projectid: &str, data: Json<api_model::ProjectData<'_>>, ) -> Result<&'static str, Custom<&'static str>> { project_check_maintainer(&mut db, session, projectid).await?; @@ -316,12 +315,12 @@ async fn project_update( ("session" = []), ), )] -#[post("/project/<projectid>/user/new?<userid>", data = "<data>")] +#[post("/project/<projectid>/user/<userid>/new", data = "<data>")] async fn project_user_add( mut db: Connection<Db>, session: auth::Session, - projectid: u64, - userid: u64, + projectid: &str, + userid: &str, data: Json<api_model::ProjectUserEntryData>, ) -> Result<&'static str, Custom<&'static str>> { project_check_maintainer(&mut db, session, projectid).await?; @@ -357,8 +356,8 @@ async fn project_user_add( async fn project_user_update( mut db: Connection<Db>, session: auth::Session, - projectid: u64, - userid: u64, + projectid: &str, + userid: &str, data: Json<api_model::ProjectUserEntryData>, ) -> Result<&'static str, Custom<&'static str>> { let need_maintainer = data.maintainer.is_some() || userid != session.user_id; @@ -404,8 +403,8 @@ async fn project_user_update( async fn project_user_del( mut db: Connection<Db>, session: auth::Session, - projectid: u64, - userid: u64, + projectid: &str, + userid: &str, ) -> Result<&'static str, Custom<&'static str>> { let need_maintainer = userid != session.user_id; @@ -437,14 +436,14 @@ async fn project_user_del( async fn reviews( mut db: Connection<Db>, _session: auth::Session, - projectid: u64, + projectid: &str, limit: Option<u32>, offset: Option<u32>, ) -> Json<api_model::Reviews> { let uw_offset = offset.unwrap_or(0); let uw_limit = limit.unwrap_or(10); let entries = sqlx::query!( - "SELECT reviews.id AS id,title,state,progress,users.id AS user_id,users.username AS username,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE project=? ORDER BY id DESC LIMIT ? OFFSET ?", + "SELECT reviews.id AS id,title,state,progress,users.id AS user_id,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE project=? ORDER BY id DESC LIMIT ? OFFSET ?", projectid, uw_limit, uw_offset) .fetch(&mut **db) .map_ok(|r| api_model::ReviewEntry { @@ -452,7 +451,6 @@ async fn reviews( title: r.title, owner: api_model::User { id: r.user_id, - username: r.username, name: r.name, active: r.user_dn.is_some(), }, @@ -492,28 +490,24 @@ async fn reviews( ("session" = []), ), )] -#[get("/review/<reviewid>")] +#[get("/review/<projectid>/<branch..>")] async fn review( mut db: Connection<Db>, _session: auth::Session, - reviewid: u64, + projectid: &str, + branch: PathBuf, ) -> Result<Json<api_model::Review>, NotFound<&'static str>> { - let mut projectid = 0; - let mut review = sqlx::query!( - "SELECT reviews.id AS id,project,title,description,state,progress,branch,archived,users.id AS user_id,users.username AS username,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE reviews.id=?", - reviewid) + "SELECT reviews.id AS id,title,description,state,progress,branch,archived,users.id AS user_id,users.name AS name,users.dn AS user_dn FROM reviews JOIN users ON users.id=owner WHERE project=? AND branch=?", + projectid, branch.as_path().to_str().unwrap()) .fetch_one(&mut **db) .map_ok(|r| { - projectid = r.project; - api_model::Review { id: r.id, title: r.title, description: r.description, owner: api_model::User { id: r.user_id, - username: r.username, name: r.name, active: r.user_dn.is_some(), }, @@ -528,13 +522,12 @@ async fn review( .await?; let mut users = sqlx::query!( - "SELECT id,username,name,dn,project_users.default_role AS role FROM users JOIN project_users ON project_users.user=id WHERE project_users.project=? ORDER BY role,username,id", + "SELECT id,name,dn,project_users.default_role AS role FROM users JOIN project_users ON project_users.user=id WHERE project_users.project=? ORDER BY role,id", projectid) .fetch(&mut **db) .map_ok(|r| api_model::ReviewUserEntry { user: api_model::User { id: r.id, - username: r.username, name: r.name, active: r.dn.is_some(), }, @@ -545,13 +538,12 @@ async fn review( .unwrap(); let override_users = sqlx::query!( - "SELECT id,username,name,dn,review_users.role AS role FROM users JOIN review_users ON review_users.user=id WHERE review_users.review=? ORDER BY role,username,id", - reviewid) + "SELECT id,name,dn,review_users.role AS role FROM users JOIN review_users ON review_users.user=id WHERE review_users.review=? ORDER BY role,id", + review.id) .fetch(&mut **db) .map_ok(|r| api_model::ReviewUserEntry { user: api_model::User { id: r.id, - username: r.username, name: r.name, active: r.dn.is_some(), }, @@ -595,14 +587,13 @@ async fn users( let uw_offset = offset.unwrap_or(0); let uw_limit = limit.unwrap_or(10); let entries = sqlx::query!( - "SELECT id,username,name,dn FROM users ORDER BY username LIMIT ? OFFSET ?", + "SELECT id,name,dn FROM users ORDER BY id LIMIT ? OFFSET ?", uw_limit, uw_offset ) .fetch(&mut **db) .map_ok(|r| api_model::User { id: r.id, - username: r.username, name: r.name, active: r.dn.is_some(), }) diff --git a/server/src/tests.rs b/server/src/tests.rs index ca7217b..72bdd78 100644 --- a/server/src/tests.rs +++ b/server/src/tests.rs @@ -180,7 +180,7 @@ async fn get_users<'a>(client: &Client) -> api_model::Users { async fn new_project(client: &Client) -> api_model::Project { get_project_from( client - .post("/api/v1/project/new") + .post("/api/v1/project/test/new") .json(&api_model::ProjectData { title: Some("foo"), description: Some("bar"), @@ -281,13 +281,14 @@ async fn test_project_new() { let project = new_project(&client).await; + assert_eq!(project.id, "test"); assert_eq!(project.title, "foo"); assert_eq!(project.description, "bar"); assert_eq!(project.remote, "fum"); assert_eq!(project.main_branch, "zod"); assert_eq!(project.users.len(), 1); let user = project.users.get(0).unwrap(); - assert_eq!(user.user.username, "user"); + assert_eq!(user.user.id, "user"); assert_eq!(user.default_role, api_model::UserReviewRole::Reviewer); assert_eq!(user.maintainer, true); @@ -309,7 +310,7 @@ async fn test_project_update() { login(&client).await; - let project = get_project_from(client.post("/api/v1/project/new").json( + let project = get_project_from(client.post("/api/v1/project/test/new").json( &api_model::ProjectData { title: Some("foo"), description: None, @@ -351,10 +352,10 @@ async fn test_project_new_user() { let project_url = format!("/api/v1/project/{}", project.id); let users = get_users(&client).await; - let other = users.users.iter().find(|u| u.username == "other").unwrap(); + let other = users.users.iter().find(|u| u.id == "other").unwrap(); let new = client - .post(format!("{project_url}/user/new?userid={}", other.id)) + .post(format!("{project_url}/user/{}/new", other.id)) .json(&api_model::ProjectUserEntryData { default_role: Some(api_model::UserReviewRole::Watcher), maintainer: Some(true), @@ -386,11 +387,11 @@ async fn test_project_change_user() { let project_url = format!("/api/v1/project/{}", project.id); let users = get_users(&client).await; - let user = users.users.iter().find(|u| u.username == "user").unwrap(); - let other = users.users.iter().find(|u| u.username == "other").unwrap(); + let user = users.users.iter().find(|u| u.id == "user").unwrap(); + let other = users.users.iter().find(|u| u.id == "other").unwrap(); let new = client - .post(format!("{project_url}/user/new?userid={}", other.id)) + .post(format!("{project_url}/user/{}/new", other.id)) .json(&api_model::ProjectUserEntryData { default_role: Some(api_model::UserReviewRole::Watcher), maintainer: Some(true), @@ -433,11 +434,11 @@ async fn test_project_check_maintainer() { let project_url = format!("/api/v1/project/{}", project.id); let users = get_users(&client).await; - let user = users.users.iter().find(|u| u.username == "user").unwrap(); - let other = users.users.iter().find(|u| u.username == "other").unwrap(); + let user = users.users.iter().find(|u| u.id == "user").unwrap(); + let other = users.users.iter().find(|u| u.id == "other").unwrap(); let new = client - .post(format!("{project_url}/user/new?userid={}", other.id)) + .post(format!("{project_url}/user/{}/new", other.id)) .json(&api_model::ProjectUserEntryData { default_role: Some(api_model::UserReviewRole::Watcher), maintainer: Some(true), @@ -485,11 +486,11 @@ async fn test_project_dont_check_maintainer() { let project_url = format!("/api/v1/project/{}", project.id); let users = get_users(&client).await; - let user = users.users.iter().find(|u| u.username == "user").unwrap(); - let other = users.users.iter().find(|u| u.username == "other").unwrap(); + let user = users.users.iter().find(|u| u.id == "user").unwrap(); + let other = users.users.iter().find(|u| u.id == "other").unwrap(); let new = client - .post(format!("{project_url}/user/new?userid={}", other.id)) + .post(format!("{project_url}/user/{}/new", other.id)) .json(&api_model::ProjectUserEntryData { default_role: Some(api_model::UserReviewRole::Watcher), maintainer: Some(true), @@ -545,11 +546,11 @@ async fn test_project_delete_user() { let project_url = format!("/api/v1/project/{}", project.id); let users = get_users(&client).await; - let user = users.users.iter().find(|u| u.username == "user").unwrap(); - let other = users.users.iter().find(|u| u.username == "other").unwrap(); + let user = users.users.iter().find(|u| u.id == "user").unwrap(); + let other = users.users.iter().find(|u| u.id == "other").unwrap(); let new = client - .post(format!("{project_url}/user/new?userid={}", other.id)) + .post(format!("{project_url}/user/{}/new", other.id)) .json(&api_model::ProjectUserEntryData { default_role: Some(api_model::UserReviewRole::Watcher), maintainer: Some(true), |
