The Battle for Wesnoth  1.19.8+dev
dbconn.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020 - 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "config.hpp"
19 
20 #include <mysql/mysql.h>
21 #include "mariadb++/account.hpp"
22 #include "mariadb++/connection.hpp"
23 #include "mariadb++/statement.hpp"
24 #include "mariadb++/result_set.hpp"
25 #include "mariadb++/exceptions.hpp"
26 
27 #include <vector>
28 #include <unordered_map>
29 
30 typedef std::vector<std::variant<bool, int, long, unsigned long long, std::string, const char*>> sql_parameters;
31 
32 /**
33  * This class is responsible for handling the database connections as well as executing queries and handling any results.
34  * @note The account and connection should never ever be provided to anything outside of this class.
35  * @note !DO NOT APPEND VALUES DIRECTLY TO THE SQL TEXT IN ANY QUERY!
36  */
37 class dbconn
38 {
39 public:
40  /**
41  * Initializes the synchronous query connection as well as the account object that has the connection settings.
42  *
43  * @param c The config object to read information from.
44  */
45  dbconn(const config& c);
46 
47  /**
48  * @see forum_user_handler::async_test_query().
49  */
50  int async_test_query(int limit);
51 
52  /**
53  * @see forum_user_handler::get_uuid().
54  */
55  std::string get_uuid();
56 
57  /**
58  * @see forum_user_handler::get_tournaments().
59  */
60  std::string get_tournaments();
61 
62  /**
63  * This is an asynchronous query that is executed on a separate connection to retrieve the game history for the
64  * provided player.
65  *
66  * @param player_id The forum ID of the player to get the game history for.
67  * @param offset The offset to provide to the database for where to start returning rows from.
68  * @param search_game_name Query for games matching this name. Supports leading and/or trailing wildcards.
69  * @param search_content_type The content type to query for (ie: scenario)
70  * @param search_content Query for games using this content ID. Supports leading and/or trailing wildcards.
71  * @return The simple_wml document containing the query results, or simply the @a error attribute if an exception is
72  * thrown.
73  */
74  std::unique_ptr<simple_wml::document> get_game_history(
75  int player_id, int offset, std::string search_game_name, int search_content_type, std::string search_content);
76 
77  /**
78  * @see forum_user_handler::user_exists().
79  */
80  bool user_exists(const std::string& name);
81 
82  /**
83  * @see forum_user_handler::get_forum_id().
84  */
85  long get_forum_id(const std::string& name);
86 
87  /**
88  * @param name The player's username.
89  * @return Whether the player has a row in the extra table.
90  */
91  bool extra_row_exists(const std::string& name);
92 
93  /**
94  * @param name The player's username.
95  * @param group_ids The forum group IDs to check if the user is part of.
96  * @return Whether the user is a member of the forum group.
97  */
98  bool is_user_in_groups(const std::string& name, const std::vector<int>& group_ids);
99 
100  /**
101  * @param table The table that will be queried.
102  * @param column The column that will be selected.
103  * @param name The player's username.
104  * @return The string value in the provided table and column for the provided username.
105  */
106  std::string get_user_string(const std::string& table, const std::string& column, const std::string& name);
107 
108  /**
109  * @param table The table that will be queried.
110  * @param column The column that will be selected.
111  * @param name The player's username.
112  * @return The int value in the provided table and column for the provided username.
113  */
114  int get_user_int(const std::string& table, const std::string& column, const std::string& name);
115 
116  /**
117  * The provided value is updated if a row exists or a new row inserted otherwise.
118  *
119  * @param column The column that the value will be put into.
120  * @param name The player's username.
121  * @param value The value to be put into the column.
122  */
123  void write_user_int(const std::string& column, const std::string& name, int value);
124 
125  /**
126  * @see forum_user_handler::user_is_banned().
127  */
128  config get_ban_info(const std::string& name, const std::string& ip);
129 
130  /**
131  * @see forum_user_handler::db_insert_game_info().
132  */
134  const std::string& uuid,
135  int game_id,
136  const std::string& version,
137  const std::string& name,
138  int reload,
139  int observers,
140  int is_public,
141  int has_password);
142 
143  /**
144  * @see forum_user_handler::db_update_game_end().
145  */
146  void update_game_end(const std::string& uuid, int game_id, const std::string& replay_location);
147 
148  /**
149  * @see forum_user_handler::db_insert_game_player_info().
150  */
152  const std::string& uuid,
153  int game_id,
154  const std::string& username,
155  int side_number,
156  int is_host,
157  const std::string& faction,
158  const std::string& version,
159  const std::string& source,
160  const std::string& current_user,
161  const std::string& leaders);
162 
163  /**
164  * @see forum_user_handler::db_insert_game_content_info().
165  */
166  unsigned long long insert_game_content_info(
167  const std::string& uuid,
168  int game_id,
169  const std::string& type,
170  const std::string& name,
171  const std::string& id,
172  const std::string& addon_id,
173  const std::string& addon_version);
174 
175  /**
176  * @see forum_user_handler::db_set_oos_flag().
177  */
178  void set_oos_flag(const std::string& uuid, int game_id);
179 
180  /**
181  * @see forum_user_handler::db_topic_id_exists().
182  */
183  bool topic_id_exists(int topic_id);
184 
185  /**
186  * @see forum_user_handler::db_insert_addon_info().
187  */
189  const std::string& instance_version,
190  const std::string& id,
191  const std::string& name,
192  const std::string& type,
193  const std::string& version,
194  bool forum_auth,
195  int topic_id,
196  const std::string& uploader);
197 
198  /**
199  * @see forum_user_handler::db_insert_login().
200  */
201  unsigned long long insert_login(const std::string& username, const std::string& ip, const std::string& version);
202 
203  /**
204  * @see forum_user_handler::db_update_logout().
205  */
206  void update_logout(unsigned long long login_id);
207 
208  /**
209  * @see forum_user_handler::get_users_for_ip().
210  */
211  void get_users_for_ip(const std::string& ip, std::ostringstream* out);
212 
213  /**
214  * @see forum_user_handler::get_ips_for_users().
215  */
216  void get_ips_for_user(const std::string& username, std::ostringstream* out);
217 
218  /**
219  * @see forum_user_handler::db_update_addon_download_count().
220  */
222  const std::string& instance_version, const std::string& id, const std::string& version);
223 
224  /**
225  * @see forum_user_handler::is_user_primary_author().
226  * @see forum_user_handler::is_user_secondary_author().
227  */
229  const std::string& instance_version, const std::string& id, const std::string& username, int is_primary);
230 
231  /**
232  * @see forum_user_handler::db_delete_addon_authors().
233  */
234  void delete_addon_authors(const std::string& instance_version, const std::string& id);
235 
236  /**
237  * @see forum_user_handler::db_insert_addon_authors().
238  */
240  const std::string& instance_version, const std::string& id, const std::string& author, int is_primary);
241 
242  /**
243  * @see forum_user_handler::do_any_authors_exist().
244  */
245  bool do_any_authors_exist(const std::string& instance_version, const std::string& id);
246 
247  /**
248  * @see forum_user_handler::get_addon_downloads_info().
249  */
250  config get_addon_downloads_info(const std::string& instance_version, const std::string& id);
251 
252  /**
253  * @see forum_user_handler::get_forum_auth_usage().
254  */
255  config get_forum_auth_usage(const std::string& instance_version);
256 
257  /**
258  * @see forum_user_handler::get_addon_admins().
259  */
260  config get_addon_admins(int site_admin_group, int forum_admin_group);
261 
262 private:
263  /**
264  * The account used to connect to the database.
265  * Also contains the connection settings.
266  * @note settings put on the connection, rather than the account, are NOT kept if a reconnect occurs!
267  */
268  mariadb::account_ref account_;
269  /** The actual connection to the database. */
270  mariadb::connection_ref connection_;
271 
272  /** The name of the table that contains forum user information. */
273  std::string db_users_table_;
274  /** The name of the table that contains forum ban information. */
275  std::string db_banlist_table_;
276  /** The name of the table that contains additional user information. */
277  std::string db_extra_table_;
278  /** The name of the table that contains game-level information. */
279  std::string db_game_info_table_;
280  /** The name of the table that contains player-level information per game. */
282  /** The name of the table that contains game content information. */
284  /** The name of the table that contains forum group information. */
285  std::string db_user_group_table_;
286  /** The text of the SQL query to use to retrieve any currently active tournaments. */
287  std::string db_tournament_query_;
288  /** The name of the table that contains phpbb forum thread information */
289  std::string db_topics_table_;
290  /** The name of the table that contains add-on information. */
291  std::string db_addon_info_table_;
292  /** The name of the table that contains user connection history. */
294  /** The name of the table that contains the add-on authors information */
296 
297  /**
298  * This is used to write out error text when an SQL-related exception occurs.
299  *
300  * @param text Some custom text to log.
301  * @param e The exception that occurred which has information about what went wrong.
302  */
303  void log_sql_exception(const std::string& text, const mariadb::exception::base& e);
304 
305  /**
306  * Creates a new connection object from the account.
307  */
308  mariadb::connection_ref create_connection();
309 
310  /**
311  * @param connection The database connection that will be used to execute the query.
312  * @param handler The lambda that will handle reading the results into a config.
313  * @param sql The SQL text to be executed.
314  * @param params The parameterized values to be inserted into the query.
315  */
316  template <typename F>
318  const mariadb::connection_ref& connection, F* handler, const std::string& sql, const sql_parameters& params);
319 
320  /**
321  * @param connection The database connection that will be used to execute the query.
322  * @param sql The SQL text to be executed.
323  * @param params The parameterized values to be inserted into the query.
324  * @return The single string value queried.
325  * @throws mariadb::exception::base when the query finds no value to be retrieved.
326  */
327  std::string get_single_string(
328  const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
329 
330  /**
331  * @param connection The database connection that will be used to execute the query.
332  * @param sql The SQL text to be executed.
333  * @param params The parameterized values to be inserted into the query.
334  * @return The single long value queried.
335  * @throws mariadb::exception::base when the query finds no value to be retrieved.
336  */
337  long get_single_long(const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
338 
339  /**
340  * @param connection The database connection that will be used to execute the query.
341  * @param sql The SQL text to be executed.
342  * @param params The parameterized values to be inserted into the query.
343  * @return True if any data was returned by the query, otherwise false.
344  */
345  bool exists(const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
346 
347  /**
348  * Executes a select statement.
349  *
350  * @param connection The database connection that will be used to execute the query.
351  * @param sql The SQL text to be executed.
352  * @param params The parameterized values to be inserted into the query.
353  * @return A result set containing the results of the select statement executed.
354  */
355  mariadb::result_set_ref select(
356  const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
357 
358  /**
359  * Executes non-select statements (ie: insert, update, delete).
360  *
361  * @param connection The database connection that will be used to execute the query.
362  * @param sql The SQL text to be executed.
363  * @param params The parameterized values to be inserted into the query.
364  * @return The number of rows modified.
365  */
366  unsigned long long modify(const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
367 
368  /**
369  * Executes non-select statements (ie: insert, update, delete), but primarily intended for inserts that return a
370  * generated ID.
371  *
372  * @param connection The database connection that will be used to execute the query.
373  * @param sql The SQL text to be executed.
374  * @param params The parameterized values to be inserted into the query.
375  * @return The value of an AUTO_INCREMENT column on the table being modified.
376  */
377  unsigned long long modify_get_id(
378  const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
379 
380  /**
381  * For a given connection, set the provided SQL and parameters on a statement.
382  *
383  * @param connection The database connection that will be used to execute the query.
384  * @param sql The SQL text to be executed.
385  * @param params The parameterized values to be inserted into the query.
386  * @return A statement ready to be executed.
387  */
388  mariadb::statement_ref query(
389  const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
390 };
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
This class is responsible for handling the database connections as well as executing queries and hand...
Definition: dbconn.hpp:38
void delete_addon_authors(const std::string &instance_version, const std::string &id)
void insert_addon_author(const std::string &instance_version, const std::string &id, const std::string &author, int is_primary)
bool do_any_authors_exist(const std::string &instance_version, const std::string &id)
void update_addon_download_count(const std::string &instance_version, const std::string &id, const std::string &version)
config get_addon_downloads_info(const std::string &instance_version, const std::string &id)
std::string db_tournament_query_
The text of the SQL query to use to retrieve any currently active tournaments.
Definition: dbconn.hpp:287
bool topic_id_exists(int topic_id)
bool is_user_in_groups(const std::string &name, const std::vector< int > &group_ids)
int async_test_query(int limit)
bool is_user_author(const std::string &instance_version, const std::string &id, const std::string &username, int is_primary)
mariadb::connection_ref connection_
The actual connection to the database.
Definition: dbconn.hpp:270
bool exists(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
long get_forum_id(const std::string &name)
config get_addon_admins(int site_admin_group, int forum_admin_group)
std::unique_ptr< simple_wml::document > get_game_history(int player_id, int offset, std::string search_game_name, int search_content_type, std::string search_content)
This is an asynchronous query that is executed on a separate connection to retrieve the game history ...
void get_ips_for_user(const std::string &username, std::ostringstream *out)
std::string db_addon_authors_table_
The name of the table that contains the add-on authors information.
Definition: dbconn.hpp:295
bool user_exists(const std::string &name)
void get_users_for_ip(const std::string &ip, std::ostringstream *out)
long get_single_long(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
std::string get_single_string(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
std::string db_banlist_table_
The name of the table that contains forum ban information.
Definition: dbconn.hpp:275
config get_complex_results(const mariadb::connection_ref &connection, F *handler, const std::string &sql, const sql_parameters &params)
unsigned long long insert_login(const std::string &username, const std::string &ip, const std::string &version)
mariadb::connection_ref create_connection()
Creates a new connection object from the account.
std::string db_extra_table_
The name of the table that contains additional user information.
Definition: dbconn.hpp:277
void update_logout(unsigned long long login_id)
std::string db_addon_info_table_
The name of the table that contains add-on information.
Definition: dbconn.hpp:291
void write_user_int(const std::string &column, const std::string &name, int value)
The provided value is updated if a row exists or a new row inserted otherwise.
std::string db_game_content_info_table_
The name of the table that contains game content information.
Definition: dbconn.hpp:283
bool extra_row_exists(const std::string &name)
void log_sql_exception(const std::string &text, const mariadb::exception::base &e)
This is used to write out error text when an SQL-related exception occurs.
std::string db_user_group_table_
The name of the table that contains forum group information.
Definition: dbconn.hpp:285
mariadb::account_ref account_
The account used to connect to the database.
Definition: dbconn.hpp:268
config get_ban_info(const std::string &name, const std::string &ip)
void set_oos_flag(const std::string &uuid, int game_id)
void update_game_end(const std::string &uuid, int game_id, const std::string &replay_location)
std::string db_game_info_table_
The name of the table that contains game-level information.
Definition: dbconn.hpp:279
std::string db_game_player_info_table_
The name of the table that contains player-level information per game.
Definition: dbconn.hpp:281
mariadb::statement_ref query(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
For a given connection, set the provided SQL and parameters on a statement.
std::string db_connection_history_table_
The name of the table that contains user connection history.
Definition: dbconn.hpp:293
int get_user_int(const std::string &table, const std::string &column, const std::string &name)
unsigned long long modify(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
Executes non-select statements (ie: insert, update, delete).
void insert_addon_info(const std::string &instance_version, const std::string &id, const std::string &name, const std::string &type, const std::string &version, bool forum_auth, int topic_id, const std::string &uploader)
unsigned long long modify_get_id(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
Executes non-select statements (ie: insert, update, delete), but primarily intended for inserts that ...
std::string db_topics_table_
The name of the table that contains phpbb forum thread information.
Definition: dbconn.hpp:289
std::string get_user_string(const std::string &table, const std::string &column, const std::string &name)
std::string db_users_table_
The name of the table that contains forum user information.
Definition: dbconn.hpp:273
dbconn(const config &c)
Initializes the synchronous query connection as well as the account object that has the connection se...
void insert_game_info(const std::string &uuid, int game_id, const std::string &version, const std::string &name, int reload, int observers, int is_public, int has_password)
config get_forum_auth_usage(const std::string &instance_version)
void insert_game_player_info(const std::string &uuid, int game_id, const std::string &username, int side_number, int is_host, const std::string &faction, const std::string &version, const std::string &source, const std::string &current_user, const std::string &leaders)
mariadb::result_set_ref select(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
Executes a select statement.
std::string get_uuid()
std::string get_tournaments()
unsigned long long insert_game_content_info(const std::string &uuid, int game_id, const std::string &type, const std::string &name, const std::string &id, const std::string &addon_id, const std::string &addon_version)
Definitions for the interface to Wesnoth Markup Language (WML).
std::vector< std::variant< bool, int, long, unsigned long long, std::string, const char * > > sql_parameters
Definition: dbconn.hpp:30
int side_number
Definition: game_info.hpp:40
mock_char c
#define e