Wt examples
3.2.3
|
00001 /* 00002 * Copyright (C) 2011 Emweb bvba, Heverlee, Belgium. 00003 * 00004 * See the LICENSE file for terms of use. 00005 */ 00006 00007 #include "Session.h" 00008 00009 #include "Wt/Auth/AuthService" 00010 #include "Wt/Auth/HashFunction" 00011 #include "Wt/Auth/PasswordService" 00012 #include "Wt/Auth/PasswordStrengthValidator" 00013 #include "Wt/Auth/PasswordVerifier" 00014 #include "Wt/Auth/GoogleService" 00015 #include "Wt/Auth/Dbo/AuthInfo" 00016 #include "Wt/Auth/Dbo/UserDatabase" 00017 00018 #include <Wt/WApplication> 00019 #include <Wt/WLogger> 00020 00021 #ifndef WIN32 00022 #include <unistd.h> 00023 #endif 00024 00025 #if !defined(WIN32) && !defined(__CYGWIN__) && !defined(ANDROID) 00026 #define HAVE_CRYPT 00027 #endif 00028 00029 using namespace Wt; 00030 namespace dbo = Wt::Dbo; 00031 00032 namespace { 00033 00034 #ifdef HAVE_CRYPT 00035 class UnixCryptHashFunction : public Auth::HashFunction 00036 { 00037 public: 00038 virtual std::string compute(const std::string& msg, 00039 const std::string& salt) const 00040 { 00041 std::string md5Salt = "$1$" + salt; 00042 return crypt(msg.c_str(), md5Salt.c_str()); 00043 } 00044 00045 virtual bool verify(const std::string& msg, 00046 const std::string& salt, 00047 const std::string& hash) const 00048 { 00049 return crypt(msg.c_str(), hash.c_str()) == hash; 00050 } 00051 00052 virtual std::string name () const { 00053 return "crypt"; 00054 } 00055 }; 00056 #endif // HAVE_CRYPT 00057 00058 class MyOAuth : public std::vector<const Auth::OAuthService *> 00059 { 00060 public: 00061 ~MyOAuth() 00062 { 00063 for (unsigned i = 0; i < size(); ++i) 00064 delete (*this)[i]; 00065 } 00066 }; 00067 00068 Auth::AuthService myAuthService; 00069 Auth::PasswordService myPasswordService(myAuthService); 00070 MyOAuth myOAuthServices; 00071 } 00072 00073 void Session::configureAuth() 00074 { 00075 myAuthService.setAuthTokensEnabled(true, "hangmancookie"); 00076 myAuthService.setEmailVerificationEnabled(true); 00077 00078 Auth::PasswordVerifier *verifier = new Auth::PasswordVerifier(); 00079 verifier->addHashFunction(new Auth::BCryptHashFunction(7)); 00080 00081 #ifdef HAVE_CRYPT 00082 // We want to still support users registered in the pre - Wt::Auth 00083 // version of the hangman example 00084 verifier->addHashFunction(new UnixCryptHashFunction()); 00085 #endif 00086 00087 myPasswordService.setVerifier(verifier); 00088 myPasswordService.setStrengthValidator(new Auth::PasswordStrengthValidator()); 00089 myPasswordService.setAttemptThrottlingEnabled(true); 00090 00091 if (Auth::GoogleService::configured()) 00092 myOAuthServices.push_back(new Auth::GoogleService(myAuthService)); 00093 } 00094 00095 Session::Session() 00096 : sqlite3_(WApplication::instance()->appRoot() + "hangman.db") 00097 { 00098 session_.setConnection(sqlite3_); 00099 sqlite3_.setProperty("show-queries", "true"); 00100 00101 session_.mapClass<User>("user"); 00102 session_.mapClass<AuthInfo>("auth_info"); 00103 session_.mapClass<AuthInfo::AuthIdentityType>("auth_identity"); 00104 session_.mapClass<AuthInfo::AuthTokenType>("auth_token"); 00105 00106 users_ = new UserDatabase(session_); 00107 00108 dbo::Transaction transaction(session_); 00109 try { 00110 session_.createTables(); 00111 00112 /* 00113 * Add a default guest/guest account 00114 */ 00115 Auth::User guestUser = users_->registerNew(); 00116 guestUser.addIdentity(Auth::Identity::LoginName, "guest"); 00117 myPasswordService.updatePassword(guestUser, "guest"); 00118 00119 Wt::log("info") << "Database created"; 00120 } catch (...) { 00121 Wt::log("info") << "Using existing database"; 00122 } 00123 00124 transaction.commit(); 00125 } 00126 00127 Session::~Session() 00128 { 00129 delete users_; 00130 } 00131 00132 dbo::ptr<User> Session::user() const 00133 { 00134 if (login_.loggedIn()) { 00135 dbo::ptr<AuthInfo> authInfo = users_->find(login_.user()); 00136 dbo::ptr<User> user = authInfo->user(); 00137 00138 if (!user) { 00139 user = session_.add(new User()); 00140 authInfo.modify()->setUser(user); 00141 } 00142 00143 return user; 00144 } else 00145 return dbo::ptr<User>(); 00146 } 00147 00148 std::string Session::userName() const 00149 { 00150 if (login_.loggedIn()) 00151 return login_.user().identity(Auth::Identity::LoginName).toUTF8(); 00152 else 00153 return std::string(); 00154 } 00155 00156 void Session::addToScore(int s) 00157 { 00158 dbo::Transaction transaction(session_); 00159 00160 dbo::ptr<User> u = user(); 00161 if (u) { 00162 u.modify()->score += s; 00163 ++u.modify()->gamesPlayed; 00164 u.modify()->lastGame = WDateTime::currentDateTime(); 00165 } 00166 00167 transaction.commit(); 00168 } 00169 00170 std::vector<User> Session::topUsers(int limit) 00171 { 00172 dbo::Transaction transaction(session_); 00173 00174 Users top = session_.find<User>().orderBy("score desc").limit(20); 00175 00176 std::vector<User> result; 00177 for (Users::const_iterator i = top.begin(); i != top.end(); ++i) { 00178 dbo::ptr<User> user = *i; 00179 result.push_back(*user); 00180 00181 dbo::ptr<AuthInfo> auth = *user->authInfos.begin(); 00182 std::string name = auth->identity(Auth::Identity::LoginName).toUTF8(); 00183 00184 result.back().name = name; 00185 } 00186 00187 transaction.commit(); 00188 00189 return result; 00190 } 00191 00192 int Session::findRanking() 00193 { 00194 dbo::Transaction transaction(session_); 00195 00196 dbo::ptr<User> u = user(); 00197 int ranking = -1; 00198 00199 if (u) 00200 ranking = session_.query<int>("select distinct count(score) from user") 00201 .where("score > ?").bind(u->score); 00202 00203 transaction.commit(); 00204 00205 return ranking + 1; 00206 } 00207 00208 Auth::AbstractUserDatabase& Session::users() 00209 { 00210 return *users_; 00211 } 00212 00213 const Auth::AuthService& Session::auth() 00214 { 00215 return myAuthService; 00216 } 00217 00218 const Auth::AbstractPasswordService& Session::passwordAuth() 00219 { 00220 return myPasswordService; 00221 } 00222 00223 const std::vector<const Auth::OAuthService *>& Session::oAuth() 00224 { 00225 return myOAuthServices; 00226 }