25 #include <boost/asio/post.hpp>
31 #define ERR_UH LOG_STREAM(err, log_mp_user_handler)
32 #define WRN_UH LOG_STREAM(warn, log_mp_user_handler)
33 #define LOG_UH LOG_STREAM(info, log_mp_user_handler)
34 #define DBG_UH LOG_STREAM(debug, log_mp_user_handler)
37 const int USER_INACTIVE = 1;
38 const int USER_IGNORE = 2;
43 , db_users_table_(
c[
"db_users_table"].str())
44 , db_extra_table_(
c[
"db_extra_table"].str())
46 , site_admin_group_(0)
47 , forum_admin_group_(0)
50 mp_mod_group_ =
std::stoi(
c[
"mp_mod_group"].str());
52 ERR_UH <<
"Failed to convert the mp_mod_group value of '" <<
c[
"mp_mod_group"].str() <<
"' into an int! Defaulting to " << mp_mod_group_ <<
".";
55 site_admin_group_ =
std::stoi(
c[
"site_admin_group"].str());
57 ERR_UH <<
"Failed to convert the site_admin_group_ value of '" <<
c[
"site_admin_group"].str() <<
"' into an int! Defaulting to " << site_admin_group_ <<
".";
60 forum_admin_group_ =
std::stoi(
c[
"forum_admin_group"].str());
62 ERR_UH <<
"Failed to convert the forum_admin_group_ value of '" <<
c[
"forum_admin_group"].str() <<
"' into an int! Defaulting to " << forum_admin_group_ <<
".";
66 bool fuh::login(
const std::string& name,
const std::string& password) {
72 return password == hash;
74 ERR_UH <<
"Invalid hash for user '" << name <<
"'";
77 }
catch (
const error&
e) {
78 ERR_UH <<
"Could not retrieve hash for user '" << name <<
"' :" <<
e.message;
94 }
catch (
const error&
e) {
95 ERR_UH <<
"Could not retrieve hash for user '" << name <<
"' :" <<
e.message;
100 return hash.substr(0,12);
106 ERR_UH <<
"Error getting salt from hash of user '" << name <<
"': " <<
err.what();
129 return user_type != USER_INACTIVE && user_type != USER_IGNORE;
150 std::chrono::seconds ban_duration(0);
151 if(
b[
"ban_end"].to_unsigned() != 0) {
153 ban_duration = std::chrono::duration_cast<std::chrono::seconds>(time_remaining);
156 switch(
b[
"ban_type"].to_int())
161 LOG_UH <<
"User '" << name <<
"' ip " << addr <<
" banned by IP address";
162 return {
BAN_IP, ban_duration };
164 LOG_UH <<
"User '" << name <<
"' uid " <<
b[
"user_id"].str() <<
" banned by uid";
167 LOG_UH <<
"User '" << name <<
"' email " <<
b[
"email"].str() <<
" banned by email address";
170 ERR_UH <<
"Invalid ban type '" <<
b[
"ban_type"].to_int() <<
"' returned for user '" << name <<
"'";
177 throw error(
"No user with the name '" + name +
"' exists.");
183 static constexpr std::string_view
format =
"%a %b %d %T %Y";
185 std::string ll_string;
187 if(ll_date > decltype(ll_date){}) {
190 ll_string =
"Never\n";
193 std::stringstream
info;
194 info <<
"Name: " << name <<
"\n"
195 <<
"Registered: " << reg_string
196 <<
"Last login: " << ll_string;
198 info <<
"This account is currently inactive.\n";
233 boost::asio::post([
this, &
s, socket, player_id, offset, &io_service, search_game_name, search_content_type, search_content] {
234 boost::asio::post(io_service, [socket, &
s, doc =
conn_.
get_game_history(player_id, offset, search_game_name, search_content_type, search_content)]{
235 s.send_to_player(socket, *doc);
240 void fuh::db_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){
248 void fuh::db_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){
252 unsigned long long fuh::db_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){
261 boost::asio::post([
this, limit, &io_service] {
262 ERR_UH <<
"async test query starts!";
264 boost::asio::post(io_service, [
i]{ ERR_UH <<
"async test query output: " <<
i; });
272 void fuh::db_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) {
276 unsigned long long fuh::db_insert_login(
const std::string& username,
const std::string& ip,
const std::string& version) {
304 void fuh::db_insert_addon_authors(
const std::string& instance_version,
const std::string&
id,
const std::vector<std::string>& primary_authors,
const std::vector<std::string>& secondary_authors) {
306 std::set<std::string> inserted_authors;
308 for(
const std::string& primary_author : primary_authors) {
309 if(inserted_authors.count(primary_author) == 0) {
310 inserted_authors.emplace(primary_author);
314 for(
const std::string& secondary_author : secondary_authors) {
315 if(inserted_authors.count(secondary_author) == 0) {
316 inserted_authors.emplace(secondary_author);
A config object defines a single node in a WML file, with access to child nodes.
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)
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)
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)
bool user_exists(const std::string &name)
void get_users_for_ip(const std::string &ip, std::ostringstream *out)
unsigned long long insert_login(const std::string &username, const std::string &ip, const std::string &version)
void update_logout(unsigned long long login_id)
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.
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)
int get_user_int(const std::string &table, const std::string &column, const std::string &name)
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)
std::string get_user_string(const std::string &table, const std::string &column, const std::string &name)
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 ¤t_user, const std::string &leaders)
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)
void async_get_and_send_game_history(boost::asio::io_context &io_service, wesnothd::server &s, any_socket_ptr socket, int player_id, int offset, std::string &search_game_name, int search_content_type, std::string &search_content)
Runs an asynchronous query to fetch the user's game history data.
void db_set_oos_flag(const std::string &uuid, int game_id)
Sets the OOS flag in the database if wesnothd is told by a client it has detected an OOS error.
bool user_is_addon_admin(const std::string &name)
std::string db_users_table_
The name of the phpbb users table.
bool user_is_moderator(const std::string &name)
void db_delete_addon_authors(const std::string &instance_version, const std::string &id)
Removes the authors information from addon_author for a particular addon and version.
void db_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)
Inserts information about an uploaded add-on into the database.
std::string get_hashed_password_from_db(const std::string &user)
void set_is_moderator(const std::string &name, const bool &is_moderator)
Sets or unsets whether the player should be considered a moderator in the extra table.
long get_forum_id(const std::string &name)
int mp_mod_group_
The group ID of the forums MP Moderators group.
void get_users_for_ip(const std::string &ip, std::ostringstream *out)
Searches for all players that logged in using the ip address.
std::chrono::system_clock::time_point get_registrationdate(const std::string &user)
bool db_topic_id_exists(int topic_id)
Checks whether a forum thread with topic_id exists.
ban_info user_is_banned(const std::string &name, const std::string &addr)
std::string db_extra_table_
The name of the extras custom table, not part of a phpbb database.
void db_update_game_end(const std::string &uuid, int game_id, const std::string &replay_location)
Update the game related information when the game ends.
std::string get_user_email(const std::string &user)
void async_test_query(boost::asio::io_context &io_service, int limit)
A simple test query for running a query asynchronously.
std::string extract_salt(const std::string &name)
Needed because the hashing algorithm used by phpbb requires some info from the original hash to recre...
std::chrono::system_clock::time_point get_lastlogin(const std::string &user)
void db_update_addon_download_count(const std::string &instance_version, const std::string &id, const std::string &version)
Increments the download count for this add-on for the specific version.
bool db_is_user_secondary_author(const std::string &instance_version, const std::string &id, const std::string &username)
Checks whether the provided username is a secondary author of the add-on.
std::string get_tournaments()
void db_insert_addon_authors(const std::string &instance_version, const std::string &id, const std::vector< std::string > &primary_authors, const std::vector< std::string > &secondary_authors)
Inserts rows for the primary and secondary authors for a particular addon and version.
void user_logged_in(const std::string &name)
Sets the last login time to the current time.
void get_ips_for_user(const std::string &username, std::ostringstream *out)
Searches for all ip addresses used by the player.
bool login(const std::string &name, const std::string &password)
Retrieves the player's hashed password from the phpbb forum database and checks if it matches the has...
fuh(const config &c)
Reads wesnothd's config for the data needed to initialize this class and dbconn.
int site_admin_group_
The group ID of the forums Site Administrators group.
bool user_is_active(const std::string &name)
std::string user_info(const std::string &name)
bool db_do_any_authors_exist(const std::string &instance_version, const std::string &id)
Checks whether any author information exists for a particular addon and version, since if there's no ...
bool db_is_user_primary_author(const std::string &instance_version, const std::string &id, const std::string &username)
Checks whether the provided username is the primary author of the add-on.
unsigned long long db_insert_login(const std::string &username, const std::string &ip, const std::string &version)
Inserts into the database for when a player logs in.
int forum_admin_group_
The group ID of the forums Forum Administrators group.
void db_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 ¤t_user, const std::string &leaders)
Inserts player information per side.
dbconn conn_
An instance of the class responsible for executing the queries and handling the database connection.
bool user_exists(const std::string &name)
config db_get_forum_auth_usage(const std::string &instance_version)
config db_get_addon_admins()
config db_get_addon_downloads_info(const std::string &instance_version, const std::string &id)
Gets a list of download count by version for add-ons.
unsigned long long db_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)
Inserts information about the content being played.
void db_update_logout(unsigned long long login_id)
Updates the database for when a player logs out.
void db_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)
Inserts game related information.
@ BAN_EMAIL
Account email address ban.
@ BAN_USER
User account/name ban.
static bool is_valid_prefix(const std::string &hash)
std::string get_salt() const
static bcrypt from_hash_string(const std::string &input)
static bool is_valid_hash(const std::string &hash)
Definitions for the interface to Wesnoth Markup Language (WML).
auto serialize_timestamp(const std::chrono::system_clock::time_point &time)
auto parse_timestamp(long long val)
auto format_local_timestamp(const std::chrono::system_clock::time_point &time, std::string_view format="%F %T")
int stoi(std::string_view str)
Same interface as std::stoi and meant as a drop in replacement, except:
utils::variant< socket_ptr, tls_socket_ptr > any_socket_ptr
static map_location::direction s