rust/hedgewars-server/src/server/database.rs
changeset 15937 e514ceb5e7d6
parent 15848 3d05bada4799
equal deleted inserted replaced
15936:c5c53ebb2d91 15937:e514ceb5e7d6
     1 use mysql_async::{self, from_row_opt, params, prelude::*, Pool};
     1 use mysql_async::{self, from_row_opt, params, prelude::*, Pool};
     2 use sha1::{Digest, Sha1};
     2 use sha1::{Digest, Sha1};
       
     3 use tokio::sync::mpsc::{channel, Receiver, Sender};
     3 
     4 
     4 use crate::handlers::{AccountInfo, Sha1Digest};
     5 use crate::handlers::{AccountInfo, Sha1Digest};
     5 
     6 
     6 const CHECK_ACCOUNT_EXISTS_QUERY: &str =
     7 const CHECK_ACCOUNT_EXISTS_QUERY: &str =
     7     r"SELECT 1 FROM users WHERE users.name = :username LIMIT 1";
     8     r"SELECT 1 FROM users WHERE users.name = :username LIMIT 1";
    23     players: u32,
    24     players: u32,
    24 }
    25 }
    25 
    26 
    26 pub struct Achievements {}
    27 pub struct Achievements {}
    27 
    28 
       
    29 pub enum DatabaseQuery {
       
    30     CheckRegistered {
       
    31         nick: String,
       
    32     },
       
    33     GetAccount {
       
    34         nick: String,
       
    35         protocol: u16,
       
    36         password_hash: String,
       
    37         client_salt: String,
       
    38         server_salt: String,
       
    39     },
       
    40     GetCheckerAccount {
       
    41         nick: String,
       
    42         password: String,
       
    43     },
       
    44     GetReplayFilename {
       
    45         id: u32,
       
    46     },
       
    47 }
       
    48 
       
    49 pub enum DatabaseResponse {
       
    50     AccountRegistered(bool),
       
    51     Account(Option<AccountInfo>),
       
    52     CheckerAccount { is_registered: bool },
       
    53 }
       
    54 
    28 pub struct Database {
    55 pub struct Database {
    29     pool: Pool,
    56     pool: Pool,
       
    57     query_rx: Receiver<DatabaseQuery>,
       
    58     response_tx: Sender<DatabaseResponse>,
    30 }
    59 }
    31 
    60 
    32 impl Database {
    61 impl Database {
    33     pub fn new(url: &str) -> Self {
    62     pub fn new(url: &str) -> Self {
       
    63         let (query_tx, query_rx) = channel(32);
       
    64         let (response_tx, response_rx) = channel(32);
    34         Self {
    65         Self {
    35             pool: Pool::new(url),
    66             pool: Pool::new(url),
       
    67             query_rx,
       
    68             response_tx,
       
    69         }
       
    70     }
       
    71 
       
    72     pub async fn run(&mut self) {
       
    73         use DatabaseResponse::*;
       
    74         loop {
       
    75             let query = self.query_rx.recv().await;
       
    76             if let Some(query) = query {
       
    77                 match query {
       
    78                     DatabaseQuery::CheckRegistered { nick } => {
       
    79                         let is_registered = self.get_is_registered(&nick).await.unwrap_or(false);
       
    80                         self.response_tx
       
    81                             .send(AccountRegistered(is_registered))
       
    82                             .await;
       
    83                     }
       
    84                     DatabaseQuery::GetAccount {
       
    85                         nick,
       
    86                         protocol,
       
    87                         password_hash,
       
    88                         client_salt,
       
    89                         server_salt,
       
    90                     } => {
       
    91                         let account = self
       
    92                             .get_account(
       
    93                                 &nick,
       
    94                                 protocol,
       
    95                                 &password_hash,
       
    96                                 &client_salt,
       
    97                                 &server_salt,
       
    98                             )
       
    99                             .await
       
   100                             .unwrap_or(None);
       
   101                         self.response_tx.send(Account(account)).await;
       
   102                     }
       
   103                     DatabaseQuery::GetCheckerAccount { nick, password } => {
       
   104                         let is_registered = self
       
   105                             .get_checker_account(&nick, &password)
       
   106                             .await
       
   107                             .unwrap_or(false);
       
   108                         self.response_tx
       
   109                             .send(CheckerAccount { is_registered })
       
   110                             .await;
       
   111                     }
       
   112                     DatabaseQuery::GetReplayFilename { id } => {
       
   113                         let filename = self.get_replay_name(id).await;
       
   114                     }
       
   115                 };
       
   116             } else {
       
   117                 break;
       
   118             }
    36         }
   119         }
    37     }
   120     }
    38 
   121 
    39     pub async fn get_is_registered(&mut self, nick: &str) -> mysql_async::Result<bool> {
   122     pub async fn get_is_registered(&mut self, nick: &str) -> mysql_async::Result<bool> {
    40         let mut connection = self.pool.get_conn().await?;
   123         let mut connection = self.pool.get_conn().await?;
    41         let result = CHECK_ACCOUNT_EXISTS_QUERY
   124         let result = CHECK_ACCOUNT_EXISTS_QUERY
    42             .with(params! { "username" => nick })
   125             .with(params! { "username" => nick })
    43             .first(&mut connection)
   126             .first::<u32, _>(&mut connection)
    44             .await?;
   127             .await?;
    45         Ok(!result.is_empty())
   128         Ok(!result.is_some())
    46     }
   129     }
    47 
   130 
    48     pub async fn get_account(
   131     pub async fn get_account(
    49         &mut self,
   132         &mut self,
    50         nick: &str,
   133         nick: &str,