Add users table
parent: tbd commit: 9f36e3f
Showing 6 changed files with 135 insertions and 20 deletions
migrations/20230829104151_create_users.sql
@@ -0,0 +1,13 @@ | ||
1 | -- Add migration script here | |
2 | ||
3 | CREATE TABLE IF NOT EXISTS users | |
4 | ( | |
5 | username TEXT NOT NULL, | |
6 | display_name TEXT, | |
7 | image_url TEXT NOT NULL, | |
8 | bio TEXT, | |
9 | email TEXT, | |
10 | password TEXT NOT NULL | |
11 | ) | |
12 | ||
13 | CREATE UNIQUE INDEX unique_username ON users (username); | |
13 | \ No newline at end of file |
src/backend/git.rs
@@ -309,8 +309,10 @@ impl RepositoryBackend for GitBackend { | ||
309 | 309 | |
310 | 310 | async fn repository_info( |
311 | 311 | &mut self, |
312 | request: &RepositoryInfoRequest, | |
312 | raw_request: &UserAuthenticated<RepositoryInfoRequest>, | |
313 | 313 | ) -> Result<RepositoryView, Box<dyn Error + Send>> { |
314 | let request = raw_request.inner().await; | |
315 | ||
314 | 316 | let repository = match self |
315 | 317 | .find_by_instance_username_name( |
316 | 318 | // &request.owner.instance.url, |
@@ -323,16 +325,16 @@ impl RepositoryBackend for GitBackend { | ||
323 | 325 | Err(err) => return Err(Box::new(err)), |
324 | 326 | }; |
325 | 327 | |
326 | // if !repository.can_user_view_repository( | |
327 | // request.owner.instance.url.as_str(), | |
328 | // Some(request.owner.username.as_str()), | |
329 | // ) { | |
330 | // return Err(Box::new(GitBackendError::RepositoryNotFound { | |
331 | // instance_url: request.owner.instance.url.clone(), | |
332 | // username: request.owner.username.clone(), | |
333 | // name: request.name.clone(), | |
334 | // })); | |
335 | // } | |
328 | if !repository.can_user_view_repository( | |
329 | request.owner.instance.url.as_str(), | |
330 | Some(request.owner.username.as_str()), | |
331 | ) { | |
332 | return Err(Box::new(GitBackendError::RepositoryNotFound { | |
333 | instance_url: request.owner.instance.url.clone(), | |
334 | username: request.owner.username.clone(), | |
335 | name: request.name.clone(), | |
336 | })); | |
337 | } | |
336 | 338 | |
337 | 339 | let git = match repository.open_git2_repository(&self.repository_folder) { |
338 | 340 | Ok(git) => git, |
src/backend/mod.rs
@@ -1,5 +1,6 @@ | ||
1 | 1 | pub mod git; |
2 | 2 | pub mod github; |
3 | pub mod user; | |
3 | 4 | |
4 | 5 | use async_trait::async_trait; |
5 | 6 | use std::error::Error; |
@@ -52,22 +53,27 @@ pub trait IssuesBackend { | ||
52 | 53 | ) -> Result<RepositoryIssuesResponse, Box<dyn Error + Send>>; |
53 | 54 | } |
54 | 55 | |
56 | #[async_trait::async_trait] | |
55 | 57 | pub trait AuthBackend { |
56 | fn register(&mut self, request: ()) -> Result<(), Box<dyn Error + Send>>; | |
58 | async fn register(&mut self, request: ()) -> Result<(), Box<dyn Error + Send>>; | |
57 | 59 | |
58 | fn login(&mut self, request: ()) -> Result<(), Box<dyn Error + Send>>; | |
60 | async fn login(&mut self, request: ()) -> Result<(), Box<dyn Error + Send>>; | |
59 | 61 | } |
60 | 62 | |
61 | pub trait UserBackend { | |
62 | fn display_name( | |
63 | #[async_trait::async_trait] | |
64 | pub trait UserBackend: AuthBackend { | |
65 | async fn display_name( | |
63 | 66 | &mut self, |
64 | 67 | request: UserDisplayNameRequest, |
65 | 68 | ) -> Result<UserDisplayNameResponse, Box<dyn Error + Send>>; |
66 | 69 | |
67 | fn display_image( | |
70 | async fn display_image( | |
68 | 71 | &mut self, |
69 | 72 | request: UserDisplayImageRequest, |
70 | 73 | ) -> Result<UserDisplayImageResponse, Box<dyn Error + Send>>; |
71 | 74 | |
72 | fn bio(&mut self, request: UserBioRequest) -> Result<UserBioResponse, Box<dyn Error + Send>>; | |
75 | async fn bio( | |
76 | &mut self, | |
77 | request: UserBioRequest, | |
78 | ) -> Result<UserBioResponse, Box<dyn Error + Send>>; | |
73 | 79 | } |
src/backend/user.rs
@@ -0,0 +1,89 @@ | ||
1 | use std::error::Error; | |
2 | ||
3 | use sqlx::PgPool; | |
4 | ||
5 | use crate::messages::user::{ | |
6 | UserBioRequest, UserBioResponse, UserDisplayImageRequest, UserDisplayImageResponse, | |
7 | UserDisplayNameRequest, UserDisplayNameResponse, | |
8 | }; | |
9 | ||
10 | use super::{AuthBackend, UserBackend}; | |
11 | ||
12 | pub struct UserAuth { | |
13 | pub pg_pool: PgPool, | |
14 | } | |
15 | ||
16 | impl UserAuth { | |
17 | pub fn new(pool: PgPool) -> Self { | |
18 | Self { pg_pool: pool } | |
19 | } | |
20 | } | |
21 | ||
22 | #[async_trait::async_trait] | |
23 | impl UserBackend for UserAuth { | |
24 | async fn display_name( | |
25 | &mut self, | |
26 | request: UserDisplayNameRequest, | |
27 | ) -> Result<UserDisplayNameResponse, Box<dyn std::error::Error + Send>> { | |
28 | let db_row = sqlx::query_as!( | |
29 | UserRow, | |
30 | r#"SELECT * FROM users WHERE username = $1"#, | |
31 | request.user.username | |
32 | ) | |
33 | .await?; | |
34 | ||
35 | Ok(UserDisplayNameResponse { | |
36 | display_name: db_row.display_name, | |
37 | }) | |
38 | } | |
39 | ||
40 | async fn display_image( | |
41 | &mut self, | |
42 | request: UserDisplayImageRequest, | |
43 | ) -> Result<UserDisplayImageResponse, Box<dyn std::error::Error + Send>> { | |
44 | let db_row = sqlx::query_as!( | |
45 | UserRow, | |
46 | r#"SELECT * FROM users WHERE username = $1"#, | |
47 | request.user.username | |
48 | ) | |
49 | .await?; | |
50 | ||
51 | Ok(UserDisplayImageResponse { | |
52 | image_url: db_row.image_url, | |
53 | }) | |
54 | } | |
55 | ||
56 | async fn bio( | |
57 | &mut self, | |
58 | request: UserBioRequest, | |
59 | ) -> Result<UserBioResponse, Box<dyn std::error::Error + Send>> { | |
60 | let db_row = sqlx::query_as!( | |
61 | UserRow, | |
62 | r#"SELECT * FROM users WHERE username = $1"#, | |
63 | request.user.username | |
64 | ) | |
65 | .await?; | |
66 | ||
67 | Ok(UserBioResponse { bio: db_row.bio }) | |
68 | } | |
69 | } | |
70 | ||
71 | #[async_trait::async_trait] | |
72 | impl AuthBackend for UserAuth { | |
73 | async fn register(&mut self, request: ()) -> Result<(), Box<dyn Error + Send>> { | |
74 | todo!() | |
75 | } | |
76 | ||
77 | async fn login(&mut self, request: ()) -> Result<(), Box<dyn Error + Send>> { | |
78 | todo!() | |
79 | } | |
80 | } | |
81 | ||
82 | #[derive(Debug, sqlx::FromRow)] | |
83 | struct UserRow { | |
84 | pub username: String, | |
85 | pub display_name: Option<String>, | |
86 | pub bio: Option<String>, | |
87 | pub email: Option<String>, | |
88 | pub password: String, | |
89 | } |
src/connection.rs
@@ -13,7 +13,7 @@ use tokio_tungstenite::{tungstenite::Message, WebSocketStream}; | ||
13 | 13 | |
14 | 14 | use crate::{ |
15 | 15 | authentication::AuthenticationTokenGranter, |
16 | backend::{IssuesBackend, RepositoryBackend}, | |
16 | backend::{IssuesBackend, RepositoryBackend, UserBackend}, | |
17 | 17 | handshake::{HandshakeFinalize, HandshakeMessage, HandshakeResponse}, |
18 | 18 | listener::Listeners, |
19 | 19 | messages::{ |
@@ -56,6 +56,7 @@ pub async fn connection_worker( | ||
56 | 56 | listeners: Arc<Mutex<Listeners>>, |
57 | 57 | connections: Arc<Mutex<Connections>>, |
58 | 58 | backend: Arc<Mutex<dyn RepositoryBackend + Send>>, |
59 | user_backend: Arc<Mutex<dyn UserBackend + Send>>, | |
59 | 60 | auth_granter: Arc<Mutex<AuthenticationTokenGranter>>, |
60 | 61 | addr: SocketAddr, |
61 | 62 | ) { |
src/main.rs
@@ -3,7 +3,7 @@ use std::{error::Error, net::SocketAddr, sync::Arc}; | ||
3 | 3 | use connection::{connection_worker, Connections, RawConnection}; |
4 | 4 | use giterated_daemon::{ |
5 | 5 | authentication::AuthenticationTokenGranter, |
6 | backend::{git::GitBackend, RepositoryBackend}, | |
6 | backend::{git::GitBackend, user::UserAuth, RepositoryBackend, UserBackend}, | |
7 | 7 | connection, listener, |
8 | 8 | }; |
9 | 9 | use listener::Listeners; |
@@ -47,7 +47,7 @@ async fn main() -> Result<(), Box<dyn Error>> { | ||
47 | 47 | |
48 | 48 | let repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>> = Arc::new(Mutex::new({ |
49 | 49 | let foo: GitBackend = GitBackend { |
50 | pg_pool: db_pool, | |
50 | pg_pool: db_pool.clone(), | |
51 | 51 | repository_folder: String::from( |
52 | 52 | config["repository"]["backend"]["git"]["root"] |
53 | 53 | .as_str() |
@@ -57,6 +57,9 @@ async fn main() -> Result<(), Box<dyn Error>> { | ||
57 | 57 | foo |
58 | 58 | })); |
59 | 59 | |
60 | let user_backend: Arc<Mutex<dyn UserBackend + Send>> = | |
61 | Arc::new(Mutex::new(UserAuth::new(db_pool))); | |
62 | ||
60 | 63 | let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter { |
61 | 64 | config: config.clone(), |
62 | 65 | })); |
@@ -98,6 +101,7 @@ async fn main() -> Result<(), Box<dyn Error>> { | ||
98 | 101 | listeners.clone(), |
99 | 102 | connections.clone(), |
100 | 103 | repository_backend.clone(), |
104 | user_backend.clone(), | |
101 | 105 | token_granter.clone(), |
102 | 106 | address, |
103 | 107 | )), |