The Battle for Wesnoth  1.15.1+dev
sample_user_handler.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by Thomas Baumhauer <thomas.baumhauer@NOSPAMgmail.com>
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 
16 
17 #include "config.hpp"
18 #include "lexical_cast.hpp"
20 
21 #include <iostream>
22 
24  : user_expiration_(0)
25  , users_()
26 {
27 
28  if(c["user_expiration"].empty()) {
29  user_expiration_ = 60;
30  } else {
31  user_expiration_ = lexical_cast_default<int>(c["user_expiration"], 60);
32  }
33 }
34 
35 void suh::add_user(const std::string& name, const std::string& mail, const std::string& password) {
36  if(user_exists(name)) throw error("This nickname is already registered");
37 
38  users_.emplace(name, user());
39 
40  set_password(name, password);
41  set_mail(name, mail);
42 
43  user_logged_in(name);
44 }
45 
46 void suh::remove_user(const std::string& name) {
47  if(!user_exists(name)) throw error("This nickname is not registered");
48 
49  users_.erase(name);
50 }
51 
52 bool suh::user_exists(const std::string& name) {
53  std::map<std::string,user>::const_iterator u = users_.find(name);
54 
55  return (u != users_.end());
56 }
57 
58 bool suh::user_is_active(const std::string& /*name*/) {
59  // FIXME: add support for inactive users maybe?
60  return true;
61 }
62 
63 std::vector<std::string> suh::users() {
64  std::vector<std::string> users;
65  for(std::map<std::string,user>::const_iterator u = users_.begin(); u != users_.end(); ++u) {
66  users.push_back(u->first);
67  }
68  return users;
69 }
70 
71 void suh::set_user_detail(const std::string& user, const std::string& detail, const std::string& value) {
72  if(detail == "mail") {
73  set_mail(user, value);
74  } else if (detail == "password") {
75  set_password(user, value);
76  } else if (detail == "realname") {
77  set_realname(user, value);
78  } else {
79  throw error("Invalid usersdetail '" + detail + "'. Valid details are: " + get_valid_details());
80  }
81 }
82 
83 std::string suh::get_valid_details() {
84  return "'mail', 'password', 'realname';";
85 }
86 
87 
88 bool suh::user_is_moderator(const std::string& name) {
89  if(!user_exists(name)) return false;
90  return users_[name].is_moderator;
91 }
92 
93 void suh::set_is_moderator(const std::string& name, const bool& is_moderator) {
94  if(!user_exists(name)) return;
95  users_[name].is_moderator = is_moderator;
96 }
97 
98 suh::ban_info suh::user_is_banned(const std::string&, const std::string&) {
99  // FIXME: stub
100  return {};
101 }
102 
103 void suh::set_mail(const std::string& user, const std::string& mail) {
104  check_mail(mail);
105  users_[user].mail = mail;
106 }
107 
108 void suh::set_password(const std::string& user, const std::string& password) {
109  check_password(password);
110  users_[user].password = password;
111 }
112 
113 void suh::set_realname(const std::string& user, const std::string& realname) {
114  check_realname(realname);
115  users_[user].realname = realname;
116 }
117 
118 //--
119 // set_lastlogin() is not called by the server via set_user_detail()
120 // and thus must not throw user_handler::error
121 
122 void suh::set_lastlogin(const std::string& user, const std::time_t& lastlogin) {
123  users_[user].lastlogin = lastlogin;
124 }
125 
126 //---
127 
128 std::string suh::get_mail(const std::string& user) {
129  return users_[user].mail;
130 }
131 
132 std::string suh::get_password(const std::string& user) {
133  return users_[user].password;
134 }
135 
136 std::string suh::get_realname(const std::string& user) {
137  return users_[user].realname;
138 }
139 
140 std::time_t suh::get_lastlogin(const std::string& user) {
141  return users_[user].lastlogin;
142 }
143 
144 std::time_t suh::get_registrationdate(const std::string& user) {
145  return users_[user].registrationdate;
146 }
147 
148 //---
149 
150 void suh::check_name(const std::string& name) {
151  if(!utils::isvalid_username(name)) {
152  throw error("This username contains invalid "
153  "characters. Only alpha-numeric characters, underscores and hyphens"
154  "are allowed.");
155  }
156  if(name.size() > 20) {
157  throw error("This username is too long. Usernames must be 20 characters or less.");
158  }
159 }
160 
161 void suh::check_mail(const std::string& /*mail*/) {
162  return;
163 }
164 
165 void suh::check_password(const std::string& password) {
166  if(!utils::isvalid_username(password)) {
167  throw error("Password contains invalid characters");
168  }
169 }
170 
171 void suh::check_realname(const std::string& realname) {
172  if(realname.size() > 50) {
173  throw error("This name is too long. Names must be 50 characters or less");
174  }
175 }
176 
177 
179  // Remove users that have not logged in for user_expiration_ days:
180  // Check if the last login of this user exceeds the
181  // expiration limit
182 
183  //The expiration time set to 0 means no expiration limit
184  if(!user_expiration_) {
185  return;
186  }
187 
188  std::time_t now = std::time(nullptr);
189 
190  //A minute has 60 seconds, an hour 60 minutes and
191  //a day 24 hours.
192  std::time_t limit = user_expiration_ * 60 * 60 * 24;
193 
194  std::vector<std::string> us = users();
195  for(std::vector<std::string>::const_iterator u = us.begin(); u != us.end(); ++u) {
196  if((now - get_lastlogin(*u)) > limit) {
197  std::cout << "User '" << *u << "' exceeds expiration limit.\n";
198  remove_user(*u);
199  }
200  }
201 }
202 
203 bool suh::login(const std::string& name, const std::string& password, const std::string&) {
204  return password == get_password(name);
205 }
206 
207 void suh::user_logged_in(const std::string& name) {
208  set_lastlogin(name, std::time(nullptr));
209 }
210 
211 std::string suh::user_info(const std::string& name) {
212  if(!user_exists(name)) throw error("No user with the name '" + name + "' exists.");
213 
214  std::time_t reg_date = get_registrationdate(name);
215  std::time_t ll_date = get_lastlogin(name);
216 
217  std::string reg_string = ctime(&reg_date);
218  std::string ll_string;
219 
220  if(ll_date) {
221  ll_string = ctime(&ll_date);
222  } else {
223  ll_string = "Never\n";
224  }
225 
226  std::stringstream info;
227  info << "Name: " << name << "\n"
228  << "Real name: " << get_realname(name) << "\n"
229  << "Registered: " << reg_string
230  << "Last login: " << ll_string;
231  if(!user_is_active(name)) {
232  info << "This account is currently inactive.\n";
233  }
234  return info.str();
235 }
236 
237 std::string suh::get_uuid(){
238  return "";
239 }
240 
241 void suh::db_insert_game_info(const std::string& uuid, int game_id, const std::string& version, const std::string& name){
242  std::cout << uuid << " - " << game_id << " - " << version << " - " << name << std::endl;
243 }
244 void suh::db_update_game_start(const std::string& uuid, int game_id, const std::string& map_name, const std::string& era_name){
245  std::cout << uuid << " - " << game_id << " - " << map_name << " - " << era_name << std::endl;
246 }
247 void suh::db_update_game_end(const std::string& uuid, int game_id, const std::string& replay_location){
248  std::cout << uuid << " - " << game_id << " - " << replay_location << std::endl;
249 }
250 void suh::db_insert_game_player_info(const std::string& uuid, int game_id, const std::string& username, int side_number, const std::string& is_host, const std::string& faction){
251  std::cout << uuid << " - " << game_id << " - " << username << " - " << side_number << " - " << is_host << " - " << faction << std::endl;
252 }
253 void suh::db_insert_modification_info(const std::string& uuid, int game_id, const std::string& modification_name){
254  std::cout << uuid << " - " << game_id << " - " << modification_name << std::endl;
255 }
256 
257 void suh::db_set_oos_flag(const std::string& uuid, int game_id){
258  std::cout << uuid << " - " << game_id << " - " << "OOS occurred!" << std::endl;
259 }
void set_mail(const std::string &user, const std::string &mail)
void check_mail(const std::string &mail)
bool user_is_moderator(const std::string &name)
Returns true if this user is a moderator on this server.
void db_insert_game_player_info(const std::string &uuid, int game_id, const std::string &username, int side_number, const std::string &is_host, const std::string &faction)
void db_insert_game_info(const std::string &uuid, int game_id, const std::string &version, const std::string &name)
bool isvalid_username(const std::string &username)
Check if the username contains only valid characters.
std::time_t get_registrationdate(const std::string &user)
void clean_up()
Called by the server once a day.
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:39
New lexcical_cast header.
logger & info()
Definition: log.cpp:90
bool login(const std::string &name, const std::string &password, const std::string &)
Return true if the given password matches the password for the given user.
ban_info user_is_banned(const std::string &name, const std::string &)
Returns true if this user account or IP address is banned.
Definitions for the interface to Wesnoth Markup Language (WML).
suh(config c)
std::string get_valid_details()
List of details that can be set for this user_handler.
static const char * name(const std::vector< SDL_Joystick *> &joysticks, const std::size_t index)
Definition: joystick.cpp:48
void check_realname(const std::string &realname)
void check_name(const std::string &name)
std::map< std::string, user > users_
void set_realname(const std::string &user, const std::string &realname)
void db_update_game_start(const std::string &uuid, int game_id, const std::string &map_name, const std::string &era_name)
void user_logged_in(const std::string &name)
Executed when the user with the given name logged in.
void set_password(const std::string &user, const std::string &password)
bool user_exists(const std::string &name)
Returns true if a user with the given name exists.
std::time_t get_lastlogin(const std::string &user)
void check_password(const std::string &password)
std::vector< std::string > users()
void db_set_oos_flag(const std::string &uuid, int game_id)
Ban status description.
std::string get_mail(const std::string &user)
Used in send_mail().
std::string password(const std::string &server, const std::string &login)
void set_lastlogin(const std::string &user, const std::time_t &lastlogin)
std::string get_uuid()
std::string get_password(const std::string &user)
void set_is_moderator(const std::string &name, const bool &is_moderator)
Mark this user as a moderator.
void set_user_detail(const std::string &user, const std::string &detail, const std::string &value)
Set data for a given user name.
bool user_is_active(const std::string &name)
Returns true if the specified user account is usable for logins.
std::string get_realname(const std::string &user)
void db_insert_modification_info(const std::string &uuid, int game_id, const std::string &modification_name)
int side_number
Definition: game_info.hpp:39
void remove_user(const std::string &name)
Removes a user.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
mock_char c
void add_user(const std::string &name, const std::string &mail, const std::string &password)
Adds a user.
int user_expiration_
std::string user_info(const std::string &name)
Returns a string containing info like the last login of this user.
void db_update_game_end(const std::string &uuid, int game_id, const std::string &replay_location)