Session.C 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (C) 2011 Emweb bvba, Heverlee, Belgium.
  3. *
  4. * See the LICENSE file for terms of use.
  5. */
  6. #include "Session.h"
  7. #include "Wt/Auth/AuthService"
  8. #include "Wt/Auth/HashFunction"
  9. #include "Wt/Auth/PasswordService"
  10. #include "Wt/Auth/PasswordStrengthValidator"
  11. #include "Wt/Auth/PasswordVerifier"
  12. #include "Wt/Auth/GoogleService"
  13. #include "Wt/Auth/Dbo/AuthInfo"
  14. #include "Wt/Auth/Dbo/UserDatabase"
  15. #include <Wt/WApplication>
  16. #include <Wt/WLogger>
  17. #ifndef WT_WIN32
  18. #include <unistd.h>
  19. #endif
  20. #if !defined(WT_WIN32) && !defined(__CYGWIN__) && !defined(ANDROID)
  21. #define HAVE_CRYPT
  22. #endif
  23. using namespace Wt;
  24. namespace dbo = Wt::Dbo;
  25. namespace {
  26. #ifdef HAVE_CRYPT
  27. class UnixCryptHashFunction : public Auth::HashFunction
  28. {
  29. public:
  30. virtual std::string compute(const std::string& msg,
  31. const std::string& salt) const
  32. {
  33. std::string md5Salt = "$1$" + salt;
  34. return crypt(msg.c_str(), md5Salt.c_str());
  35. }
  36. virtual bool verify(const std::string& msg,
  37. const std::string& salt,
  38. const std::string& hash) const
  39. {
  40. return crypt(msg.c_str(), hash.c_str()) == hash;
  41. }
  42. virtual std::string name () const {
  43. return "crypt";
  44. }
  45. };
  46. #endif // HAVE_CRYPT
  47. class MyOAuth : public std::vector<const Auth::OAuthService *>
  48. {
  49. public:
  50. ~MyOAuth()
  51. {
  52. for (unsigned i = 0; i < size(); ++i)
  53. delete (*this)[i];
  54. }
  55. };
  56. Auth::AuthService myAuthService;
  57. Auth::PasswordService myPasswordService(myAuthService);
  58. MyOAuth myOAuthServices;
  59. }
  60. void Session::configureAuth()
  61. {
  62. myAuthService.setAuthTokensEnabled(true, "hangmancookie");
  63. myAuthService.setEmailVerificationEnabled(true);
  64. Auth::PasswordVerifier *verifier = new Auth::PasswordVerifier();
  65. verifier->addHashFunction(new Auth::BCryptHashFunction(7));
  66. #ifdef HAVE_CRYPT
  67. // We want to still support users registered in the pre - Wt::Auth
  68. // version of the hangman example
  69. verifier->addHashFunction(new UnixCryptHashFunction());
  70. #endif
  71. myPasswordService.setVerifier(verifier);
  72. myPasswordService.setStrengthValidator(new Auth::PasswordStrengthValidator());
  73. myPasswordService.setAttemptThrottlingEnabled(true);
  74. if (Auth::GoogleService::configured())
  75. myOAuthServices.push_back(new Auth::GoogleService(myAuthService));
  76. }
  77. Session::Session()
  78. : sqlite3_(WApplication::instance()->appRoot() + "hangman.db")
  79. {
  80. session_.setConnection(sqlite3_);
  81. sqlite3_.setProperty("show-queries", "true");
  82. session_.mapClass<User>("user");
  83. session_.mapClass<AuthInfo>("auth_info");
  84. session_.mapClass<AuthInfo::AuthIdentityType>("auth_identity");
  85. session_.mapClass<AuthInfo::AuthTokenType>("auth_token");
  86. users_ = new UserDatabase(session_);
  87. dbo::Transaction transaction(session_);
  88. try {
  89. session_.createTables();
  90. /*
  91. * Add a default guest/guest account
  92. */
  93. Auth::User guestUser = users_->registerNew();
  94. guestUser.addIdentity(Auth::Identity::LoginName, "guest");
  95. myPasswordService.updatePassword(guestUser, "guest");
  96. Wt::log("info") << "Database created";
  97. } catch (...) {
  98. Wt::log("info") << "Using existing database";
  99. }
  100. transaction.commit();
  101. }
  102. Session::~Session()
  103. {
  104. delete users_;
  105. }
  106. dbo::ptr<User> Session::user() const
  107. {
  108. if (login_.loggedIn()) {
  109. dbo::ptr<AuthInfo> authInfo = users_->find(login_.user());
  110. dbo::ptr<User> user = authInfo->user();
  111. if (!user) {
  112. user = session_.add(new User());
  113. authInfo.modify()->setUser(user);
  114. }
  115. return user;
  116. } else
  117. return dbo::ptr<User>();
  118. }
  119. std::string Session::userName() const
  120. {
  121. if (login_.loggedIn())
  122. return login_.user().identity(Auth::Identity::LoginName).toUTF8();
  123. else
  124. return std::string();
  125. }
  126. void Session::addToScore(int s)
  127. {
  128. dbo::Transaction transaction(session_);
  129. dbo::ptr<User> u = user();
  130. if (u) {
  131. u.modify()->score += s;
  132. ++u.modify()->gamesPlayed;
  133. u.modify()->lastGame = WDateTime::currentDateTime();
  134. }
  135. transaction.commit();
  136. }
  137. std::vector<User> Session::topUsers(int limit)
  138. {
  139. dbo::Transaction transaction(session_);
  140. Users top = session_.find<User>().orderBy("score desc").limit(limit);
  141. std::vector<User> result;
  142. for (Users::const_iterator i = top.begin(); i != top.end(); ++i) {
  143. dbo::ptr<User> user = *i;
  144. result.push_back(*user);
  145. dbo::ptr<AuthInfo> auth = *user->authInfos.begin();
  146. std::string name = auth->identity(Auth::Identity::LoginName).toUTF8();
  147. result.back().name = name;
  148. }
  149. transaction.commit();
  150. return result;
  151. }
  152. int Session::findRanking()
  153. {
  154. dbo::Transaction transaction(session_);
  155. dbo::ptr<User> u = user();
  156. int ranking = -1;
  157. if (u)
  158. ranking = session_.query<int>("select distinct count(score) from user")
  159. .where("score > ?").bind(u->score);
  160. transaction.commit();
  161. return ranking + 1;
  162. }
  163. Auth::AbstractUserDatabase& Session::users()
  164. {
  165. return *users_;
  166. }
  167. const Auth::AuthService& Session::auth()
  168. {
  169. return myAuthService;
  170. }
  171. const Auth::AbstractPasswordService& Session::passwordAuth()
  172. {
  173. return myPasswordService;
  174. }
  175. const std::vector<const Auth::OAuthService *>& Session::oAuth()
  176. {
  177. return myOAuthServices;
  178. }