Skip to main content

nil_server_database/impl/
user.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use crate::error::{Error, Result};
5use crate::model::user::{NewUser, User};
6use crate::sql_types::id::UserId;
7use crate::sql_types::player_id::db_PlayerId;
8use crate::{Database, conn};
9use diesel::prelude::*;
10use diesel::result::{DatabaseErrorKind, Error as DieselError};
11use diesel_async::RunQueryDsl;
12use either::Either;
13
14impl Database {
15  pub async fn count_games_by_user(&self, id: db_PlayerId) -> Result<i64> {
16    let user_id = self.get_user_id(id).await?;
17    self.count_games_by_user_id(user_id).await
18  }
19
20  pub async fn count_games_by_user_id(&self, id: UserId) -> Result<i64> {
21    use crate::schema::game;
22
23    game::table
24      .filter(game::created_by.eq(id))
25      .count()
26      .get_result(conn!(self))
27      .await
28      .map_err(Into::into)
29  }
30
31  pub async fn create_user(&self, new: &NewUser) -> Result<usize> {
32    use crate::schema::user;
33
34    let result = diesel::insert_into(user::table)
35      .values(new)
36      .execute(conn!(self))
37      .await;
38
39    if let Err(DieselError::DatabaseError(kind, _)) = &result
40      && let DatabaseErrorKind::UniqueViolation = kind
41    {
42      Err(Error::UserAlreadyExists(new.player_id()))
43    } else {
44      Ok(result?)
45    }
46  }
47
48  pub async fn get_user(&self, id: impl Into<db_PlayerId>) -> Result<User> {
49    use crate::schema::user;
50
51    let id: db_PlayerId = id.into();
52
53    let result = user::table
54      .filter(user::player_id.eq(&id))
55      .select(User::as_select())
56      .first(conn!(self))
57      .await;
58
59    if let Err(DieselError::NotFound) = &result {
60      Err(Error::UserNotFound(Either::Left(id)))
61    } else {
62      Ok(result?)
63    }
64  }
65
66  pub async fn get_user_by_id(&self, id: UserId) -> Result<User> {
67    use crate::schema::user;
68
69    let result = user::table
70      .find(id)
71      .select(User::as_select())
72      .first(conn!(self))
73      .await;
74
75    if let Err(DieselError::NotFound) = &result {
76      Err(Error::UserNotFound(Either::Right(id)))
77    } else {
78      Ok(result?)
79    }
80  }
81
82  pub async fn get_user_id(&self, id: db_PlayerId) -> Result<UserId> {
83    use crate::schema::user;
84
85    let result = user::table
86      .filter(user::player_id.eq(&id))
87      .select(user::id)
88      .first(conn!(self))
89      .await;
90
91    if let Err(DieselError::NotFound) = &result {
92      Err(Error::UserNotFound(Either::Left(id)))
93    } else {
94      Ok(result?)
95    }
96  }
97
98  pub async fn get_user_player_id(&self, id: UserId) -> Result<db_PlayerId> {
99    use crate::schema::user;
100
101    let result = user::table
102      .find(id)
103      .select(user::player_id)
104      .first::<db_PlayerId>(conn!(self))
105      .await;
106
107    if let Err(DieselError::NotFound) = &result {
108      Err(Error::UserNotFound(Either::Right(id)))
109    } else {
110      Ok(result?)
111    }
112  }
113
114  pub async fn user_exists(&self, id: impl Into<db_PlayerId>) -> Result<bool> {
115    use crate::schema::user;
116    use diesel::dsl::{exists, select};
117
118    let id: db_PlayerId = id.into();
119
120    select(exists(user::table.filter(user::player_id.eq(id))))
121      .get_result(conn!(self))
122      .await
123      .map_err(Into::into)
124  }
125}