update wt to 4.0.2

This commit is contained in:
Bartosz Wieczorek 2018-01-25 10:49:11 +01:00
parent adb280d30c
commit 73f4b636fb
23 changed files with 228 additions and 234 deletions

View File

@ -14,7 +14,8 @@ set(HUNTER_BUILD_SHARED_LIBS TRUE)
include(cmake/Compiler.cmake) include(cmake/Compiler.cmake)
include(cmake/FindAllRequirements.cmake) include(cmake/FindAllRequirements.cmake)
include_directories(${CMAKE_BINARY_DIR}/external/include) include_directories(${CMAKE_BINARY_DIR}/external/include SYSTEM)
include_directories(${CMAKE_BINARY_DIR}/external/include/date SYSTEM)
add_subdirectory(src) add_subdirectory(src)
#add_subdirectory(tests) #add_subdirectory(tests)

View File

@ -60,8 +60,8 @@ find_package(spdlog CONFIG REQUIRED)
hunter_add_package(range-v3) hunter_add_package(range-v3)
find_package(range-v3 CONFIG REQUIRED) find_package(range-v3 CONFIG REQUIRED)
#hunter_add_package(PostgreSQL) hunter_add_package(PostgreSQL)
#find_package(PostgreSQL REQUIRED) find_package(PostgreSQL REQUIRED)
set(EXTERNAL_INSTALL_LOCATION ${CMAKE_BINARY_DIR}/lib CACHE STRING "external libs root path") set(EXTERNAL_INSTALL_LOCATION ${CMAKE_BINARY_DIR}/lib CACHE STRING "external libs root path")
set(EXTERNAL_LOCATION ${CMAKE_BINARY_DIR}/external CACHE STRING "external sources root path") set(EXTERNAL_LOCATION ${CMAKE_BINARY_DIR}/external CACHE STRING "external sources root path")
@ -88,8 +88,8 @@ build_external_project(project_wt wt
-DENABLE_FIREBIRD=OFF -DENABLE_FIREBIRD=OFF
-DENABLE_MYSQL=OFF -DENABLE_MYSQL=OFF
-DENABLE_MSSQLSERVER=OFF -DENABLE_MSSQLSERVER=OFF
-DENABLE_LIBWTDBO=TRUE
-DENABLE_QT4=OFF -DENABLE_QT4=OFF
-DENABLE_LIBWTDBO=OFF
-DENABLE_OPENGL=OFF -DENABLE_OPENGL=OFF
-DENABLE_UNWIND=OFF -DENABLE_UNWIND=OFF
-DCONNECTOR_FCGI=OFF -DCONNECTOR_FCGI=OFF
@ -104,10 +104,11 @@ set_target_properties(wthttp PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LOCATION}/l
add_dependencies(wthttp project_wt) add_dependencies(wthttp project_wt)
LIST(APPEND CMAKE_MODULE_PATH "${EXTERNAL_LOCATION}") LIST(APPEND CMAKE_MODULE_PATH "${EXTERNAL_LOCATION}")
#LIST(APPEND CMAKE_MODULE_PATH "${_HUNTER_ROOT}/lib")
build_external_project(project_hhdate date build_external_project(project_hhdate date
https://github.com/HowardHinnant/date.git https://github.com/HowardHinnant/date.git
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_INSTALL_PREFIX=${EXTERNAL_LOCATION} -DCMAKE_INSTALL_PREFIX=${EXTERNAL_LOCATION}
-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_ALT_SEP} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_ALT_SEP}
-DTZ_CXX_STANDARD=14 -DTZ_CXX_STANDARD=14
@ -118,6 +119,8 @@ add_dependencies(date project_hhdate)
build_external_project(project_sqlpp sqlpp build_external_project(project_sqlpp sqlpp
https://github.com/rbock/sqlpp11.git https://github.com/rbock/sqlpp11.git
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_INSTALL_PREFIX=${EXTERNAL_LOCATION} -DCMAKE_INSTALL_PREFIX=${EXTERNAL_LOCATION}
-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_ALT_SEP} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_ALT_SEP}
-DENABLE_TESTS=FALSE -DENABLE_TESTS=FALSE
@ -126,7 +129,8 @@ build_external_project(project_sqlpp sqlpp
add_library(sqlpp INTERFACE IMPORTED) add_library(sqlpp INTERFACE IMPORTED)
add_dependencies(sqlpp project_sqlpp) add_dependencies(sqlpp project_sqlpp)
link_directories(${_HUNTER_ROOT}/lib) link_directories(${_HUNTER_ROOT}/lib GLOBAL)
link_directories(${EXTERNAL_LOCATION}/lib GLOBAL)
find_library(wt REQUIRED) find_library(wt REQUIRED)
find_library(wthttp REQUIRED) find_library(wthttp REQUIRED)
@ -134,10 +138,11 @@ find_library(sqlpp REQUIRED)
build_external_project(project_sqlpp_connector sqlpp_connector build_external_project(project_sqlpp_connector sqlpp_connector
https://github.com/matthijs/sqlpp11-connector-postgresql.git https://github.com/matthijs/sqlpp11-connector-postgresql.git
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_INSTALL_PREFIX=${EXTERNAL_LOCATION} -DCMAKE_INSTALL_PREFIX=${EXTERNAL_LOCATION}
-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_ALT_SEP} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_ALT_SEP}
-DENABLE_TESTS=FALSE -DENABLE_TESTS=FALSE
-DDATE_INCLUDE_DIR=${EXTERNAL_LOCATION}/include/date -DDATE_INCLUDE_DIR=${EXTERNAL_LOCATION}/include/date
-DSQLPP11_INCLUDE_DIR=${EXTERNAL_LOCATION}/include -DSQLPP11_INCLUDE_DIR=${EXTERNAL_LOCATION}/include
) )

View File

@ -1,20 +1,17 @@
set(SOURCES set(SOURCES
main.cpp) main.cpp)
#INCLUDE_DIRECTORIES(${PostgreSQL_INCLUDE_DIRS})
add_executable(eedb ${SOURCES} ) add_executable(eedb ${SOURCES} )
target_link_libraries(eedb target_link_libraries(eedb
wthttp # or {Wt_HTTP_DEBUG_LIBRARY} wthttp # or {Wt_HTTP_DEBUG_LIBRARY}
wt # or {Wt_DEBUG_LIBRARY} wt # or {Wt_DEBUG_LIBRARY}
eedb_db
auth
Boost::system Boost::system
Boost::filesystem Boost::filesystem
Boost::thread Boost::thread
Boost::program_options Boost::program_options
z z
# eedb_db auth
) )

View File

@ -1,11 +1,11 @@
//#include <eedb/EEDB.hpp> #include <eedb/EEDB.hpp>
//#include <eedb/Session.hpp> #include <eedb/Session.hpp>
//#include <eedb/auth/PgUserAuth.hpp> #include <eedb/auth/PgUserAuth.hpp>
//#include <eedb/auth/Services.hpp> #include <eedb/auth/Services.hpp>
//#include <eedb/db/config.hpp> #include <eedb/db/config.hpp>
//#include <eedb/db/connection.hpp> #include <eedb/db/connection.hpp>
//#include <eedb/widgets/DefaultAuthPage.hpp> //#include <eedb/widgets/DefaultAuthPage.hpp>
//#include <eedb/widgets/DefaultHomePage.hpp> //#include <eedb/widgets/DefaultHomePage.hpp>
@ -15,28 +15,28 @@
#include <Wt/WServer.h> #include <Wt/WServer.h>
Wt::WApplication * createApplication(const Wt::WEnvironment & env) { Wt::WApplication * createApplication(const Wt::WEnvironment & env) {
// using std::make_unique; using std::make_unique;
// using std::move; using std::move;
// using std::unique_ptr; using std::unique_ptr;
// auto dbConfig = make_unique< eedb::db::PgConfig >(env); auto dbConfig = make_unique< eedb::db::PgConfig >(env);
// auto dbConnection = make_unique< eedb::db::PgConnection >(move(dbConfig)); // auto dbConnection = make_unique< eedb::db::PgConnection >(move(dbConfig));
// auto session = unique_ptr< eedb::Session >(make_unique< eedb::WebSession >(move(dbConnection), env)); // auto session = unique_ptr< eedb::Session >(make_unique< eedb::WebSession >(move(dbConnection), env));
// auto authPageFactory = [_session = session.get()]()->std::unique_ptr< eedb::AuthPage > { // auto authPageFactory = [_session = session.get()]()->std::unique_ptr< eedb::AuthPage > {
// auto userDatabase = make_unique< eedb::auth::PgUserAuth >(_session->db(), _session->enviroment()); // auto userDatabase = make_unique< eedb::auth::PgUserAuth >(_session->db(), _session->enviroment());
// auto services = eedb::auth::Services(); // auto services = eedb::auth::Services();
// auto & login = _session->login(); // auto & login = _session->login();
// return make_unique< eedb::DefaultAuthPage >(services, std::move(userDatabase), login); // return make_unique< eedb::DefaultAuthPage >(services, std::move(userDatabase), login);
// }; // };
// auto homePageFactory = [_session = session.get()]()->std::unique_ptr< eedb::HomePage > { // auto homePageFactory = [_session = session.get()]()->std::unique_ptr< eedb::HomePage > {
// auto navigationBar = std::make_unique< eedb::DefaultNavigationBar >(); // auto navigationBar = std::make_unique< eedb::DefaultNavigationBar >();
// return make_unique< eedb::DefaultHomePage >(*_session, std::move(navigationBar)); // return make_unique< eedb::DefaultHomePage >(*_session, std::move(navigationBar));
// }; // };
// return new eedb::EEDB{std::move(session), authPageFactory, homePageFactory}; // return new eedb::EEDB{std::move(session), authPageFactory, homePageFactory};
} }
int main(int argc, char ** argv) { int main(int argc, char ** argv) {

View File

@ -1,17 +1,16 @@
file(GLOB SOURCE file(GLOB SOURCE
# EEDB.cpp EEDB.cpp
# Session.cpp Session.cpp
# auth/PgUserAuth.cpp auth/PgUserAuth.cpp
# auth/Services.cpp auth/Services.cpp
# data/* data/*
# widgets/* widgets/*
# model/* model/*
) )
#add_subdirectory(db) include_directories( ${PostgreSQL_INCLUDE_DIRS} )
#include_directories( ${PostgreSQL_INCLUDE_DIRS} ) add_subdirectory(db)
#add_library(auth STATIC ${SOURCE})
#target_link_libraries( auth eedb_db )
add_library(auth STATIC ${SOURCE})
target_link_libraries( auth eedb_db )

View File

@ -39,7 +39,7 @@ EEDB::EEDB(std::unique_ptr< Session > session, AuthPageFactory authPageFactory,
root()->addStyleClass("container"); root()->addStyleClass("container");
useStyleSheet("/resources/style.css"); useStyleSheet("/resources/style.css");
setTheme(_theme->create(this)); setTheme(_theme->create());
_authPage = _authPageFactory(); _authPage = _authPageFactory();
_authPage->registerNeedVerification([] {}); _authPage->registerNeedVerification([] {});

View File

@ -18,17 +18,14 @@
#include <random> #include <random>
#include <string> #include <string>
#include <Wt/Auth/AuthService> #include <Wt/Auth/AuthService.h>
#include <Wt/Auth/Dbo/AuthInfo> #include <Wt/Auth/Dbo/AuthInfo.h>
#include <Wt/WEnvironment> #include <Wt/WEnvironment.h>
#include <Wt/WLogger> #include <Wt/WLogger.h>
#include <tao/json.hh> #include <nlohmann/json.hpp>
#include <tao/json/value.hh>
using namespace sqlpp;
using namespace Wt::Auth; using namespace Wt::Auth;
using namespace std::string_literals;
// enum LoginActions { Login, Logout }; // enum LoginActions { Login, Logout };
// static std::array< std::string_view, 2 > UserActionNames = {{"login", "logout"}}; // static std::array< std::string_view, 2 > UserActionNames = {{"login", "logout"}};
@ -56,7 +53,8 @@ struct TransactionGuard : public Wt::Auth::AbstractUserDatabase::Transaction {
_c.native()->commit_transaction(); _c.native()->commit_transaction();
} }
void rollback() override { void rollback() override {
_c.native()->rollback_transaction(); ///FIXME
// _c.native()->rollback_transaction();
} }
private: private:
@ -85,7 +83,7 @@ namespace {
.from(t_user_action) // .from(t_user_action) //
.where(t_user_action.name == "logout") // .where(t_user_action.name == "logout") //
.limit(1u); .limit(1u);
} } // namespace
PgUserAuth::~PgUserAuth() {} PgUserAuth::~PgUserAuth() {}
@ -108,7 +106,7 @@ User PgUserAuth::findWithId(const std::string & id) const {
User PgUserAuth::findWithIdentity(const std::string & provider, const Wt::WString & identity) const { User PgUserAuth::findWithIdentity(const std::string & provider, const Wt::WString & identity) const {
auto _identity = identity.toUTF8(); auto _identity = identity.toUTF8();
if(_authService && _authService->identityPolicy() == EmailAddressIdentity) { if(_authService && _authService->identityPolicy() == Wt::Auth::IdentityPolicy::EmailAddress ) {
std::transform(_identity.begin(), _identity.end(), _identity.begin(), ::tolower); std::transform(_identity.begin(), _identity.end(), _identity.begin(), ::tolower);
} }
@ -302,7 +300,7 @@ User PgUserAuth::findWithEmail(const std::string & address) const {
return {std::to_string(ret.front().user_uid), *this}; return {std::to_string(ret.front().user_uid), *this};
} }
void PgUserAuth::setEmailToken(const User & user, const Token & token, User::EmailTokenRole role) { void PgUserAuth::setEmailToken(const User & user, const Token & token, EmailTokenRole role) {
auto exp = ::date::floor<::std::chrono::milliseconds >(std::chrono::system_clock::from_time_t(token.expirationTime().toTime_t())); auto exp = ::date::floor<::std::chrono::milliseconds >(std::chrono::system_clock::from_time_t(token.expirationTime().toTime_t()));
db(update(t_info) // db(update(t_info) //
.set( // .set( //
@ -325,14 +323,14 @@ Token PgUserAuth::emailToken(const User & user) const {
return {ret.front().email_token, exp}; return {ret.front().email_token, exp};
} }
User::EmailTokenRole PgUserAuth::emailTokenRole(const User & user) const { EmailTokenRole PgUserAuth::emailTokenRole(const User & user) const {
auto ret = db(select(t_info.email_token_role) // auto ret = db(select(t_info.email_token_role) //
.from(t_info) // .from(t_info) //
.where(t_info.user_uid == std::atoi(user.id().c_str()))); .where(t_info.user_uid == std::atoi(user.id().c_str())));
if(ret.empty()) if(ret.empty())
throw std::exception(); throw std::exception();
auto val = ret.front().email_token_role; auto val = ret.front().email_token_role;
return static_cast< User::EmailTokenRole >(val.value()); return static_cast< EmailTokenRole >(val.value());
} }
User PgUserAuth::findWithEmailToken(const std::string & hash) const { User PgUserAuth::findWithEmailToken(const std::string & hash) const {
@ -378,6 +376,7 @@ User PgUserAuth::findWithAuthToken(const std::string & hash) const {
int PgUserAuth::updateAuthToken(const User & user, const std::string & oldhash, const std::string & newhash) { int PgUserAuth::updateAuthToken(const User & user, const std::string & oldhash, const std::string & newhash) {
// method called only after successful login // method called only after successful login
using namespace std::chrono; using namespace std::chrono;
using namespace std::string_literals;
const auto identity_id = db(select(t_info.id) // const auto identity_id = db(select(t_info.id) //
.from(t_info) // .from(t_info) //
.where(t_info.user_uid == std::atoi(user.id().c_str()))); .where(t_info.user_uid == std::atoi(user.id().c_str())));
@ -392,7 +391,7 @@ int PgUserAuth::updateAuthToken(const User & user, const std::string & oldhash,
if(expires.empty()) if(expires.empty())
return 0; return 0;
const tao::json::value data{ const nlohmann::json data = {
{"status"s, "success"}, // {"status"s, "success"}, //
{"method"s, "token"}, // {"method"s, "token"}, //
{"user_address"s, _env.clientAddress()}, // {"user_address"s, _env.clientAddress()}, //
@ -405,7 +404,7 @@ int PgUserAuth::updateAuthToken(const User & user, const std::string & oldhash,
db(insert_into(t_user_history) db(insert_into(t_user_history)
.set(t_user_history.user_id = std::atoi(user.id().c_str()), .set(t_user_history.user_id = std::atoi(user.id().c_str()),
t_user_history.action_id = select_login_action_id, // t_user_history.action_id = select_login_action_id, //
t_user_history.data = tao::json::to_string(data))); t_user_history.data = data.dump()));
const auto now = system_clock::now(); const auto now = system_clock::now();
const auto diff = expires.front().expires.value() - now; const auto diff = expires.front().expires.value() - now;
@ -413,9 +412,10 @@ int PgUserAuth::updateAuthToken(const User & user, const std::string & oldhash,
} }
void PgUserAuth::setFailedLoginAttempts(const User & user, int count) { void PgUserAuth::setFailedLoginAttempts(const User & user, int count) {
using namespace std::string_literals;
const auto getStatus = [count]() { return count ? "failed"s : "success"s; }; const auto getStatus = [count]() { return count ? "failed"s : "success"s; };
const tao::json::value data{ const nlohmann::json data = {
{"status"s, getStatus()}, // {"status"s, getStatus()}, //
{"method"s, "password"}, // {"method"s, "password"}, //
{"user_address"s, _env.clientAddress()}, // {"user_address"s, _env.clientAddress()}, //
@ -428,13 +428,15 @@ void PgUserAuth::setFailedLoginAttempts(const User & user, int count) {
db(insert_into(t_user_history) db(insert_into(t_user_history)
.set(t_user_history.user_id = std::atoi(user.id().c_str()), .set(t_user_history.user_id = std::atoi(user.id().c_str()),
t_user_history.action_id = select_login_action_id, // t_user_history.action_id = select_login_action_id, //
t_user_history.data = tao::json::to_string(data))); t_user_history.data = data.dump()));
} }
template < typename T > template < typename T >
inline std::string name_of(const T &) { inline std::string name_of(const T &) {
static_assert(sqlpp::is_column_t< T >::value, "T should by a calumn"); return {};
return std::string{sqlpp::name_of< typename T::_table >::char_ptr()} + '.' + sqlpp::name_of< T >::char_ptr(); /// FIXME
// static_assert(sqlpp::is_column_t< T >::value, "T should by a calumn");
// return std::string{sqlpp::name_of< typename T::_table >::char_ptr()} + '.' + sqlpp::name_of< T >::char_ptr();
} }
int PgUserAuth::failedLoginAttempts(const User & user) const { int PgUserAuth::failedLoginAttempts(const User & user) const {
@ -474,15 +476,16 @@ Wt::WDateTime PgUserAuth::lastLoginAttempt(const User & user) const {
} }
void PgUserAuth::logout(const User & user) { void PgUserAuth::logout(const User & user) {
const tao::json::value data{{"status"s, "success"}}; using namespace std::string_literals;
const nlohmann::json data = {{"status"s, "success"}};
db(insert_into(t_user_history) db(insert_into(t_user_history)
.set(t_user_history.user_id = std::atoi(user.id().c_str()), .set(t_user_history.user_id = std::atoi(user.id().c_str()),
t_user_history.action_id = select_logout_action_id, // t_user_history.action_id = select_logout_action_id, //
t_user_history.data = tao::json::to_string(data))); t_user_history.data = data.dump()));
} }
AbstractUserDatabase::Transaction * PgUserAuth::startTransaction() { AbstractUserDatabase::Transaction * PgUserAuth::startTransaction() {
return new TransactionGuard< decltype(db) >(db); return new TransactionGuard< decltype(db) >(db);
} }
} } // namespace eedb::auth

View File

@ -48,9 +48,9 @@ class PgUserAuth : public Wt::Auth::AbstractUserDatabase {
void setUnverifiedEmail(const Wt::Auth::User & user, const std::string & address) override; void setUnverifiedEmail(const Wt::Auth::User & user, const std::string & address) override;
std::string unverifiedEmail(const Wt::Auth::User & user) const override; std::string unverifiedEmail(const Wt::Auth::User & user) const override;
void setEmailToken(const Wt::Auth::User & user, const Wt::Auth::Token & token, Wt::Auth::User::EmailTokenRole role) override; void setEmailToken(const Wt::Auth::User & user, const Wt::Auth::Token & token, Wt::Auth::EmailTokenRole role) override;
Wt::Auth::Token emailToken(const Wt::Auth::User & user) const override; Wt::Auth::Token emailToken(const Wt::Auth::User & user) const override;
Wt::Auth::User::EmailTokenRole emailTokenRole(const Wt::Auth::User & user) const override; Wt::Auth::EmailTokenRole emailTokenRole(const Wt::Auth::User & user) const override;
void addAuthToken(const Wt::Auth::User & user, const Wt::Auth::Token & token) override; void addAuthToken(const Wt::Auth::User & user, const Wt::Auth::Token & token) override;
void removeAuthToken(const Wt::Auth::User &, const std::string & hash) override; void removeAuthToken(const Wt::Auth::User &, const std::string & hash) override;

View File

@ -1,17 +1,17 @@
#include <eedb/auth/Services.hpp> #include <eedb/auth/Services.hpp>
#include <Wt/Auth/PasswordService> #include <Wt/Auth/PasswordService.h>
#include <Wt/Auth/PasswordStrengthValidator> #include <Wt/Auth/PasswordStrengthValidator.h>
#include <Wt/Auth/PasswordVerifier> #include <Wt/Auth/PasswordVerifier.h>
#include <Wt/Auth/AuthService> #include <Wt/Auth/AuthService.h>
#include <Wt/Auth/AuthWidget> #include <Wt/Auth/AuthWidget.h>
#include <Wt/Auth/Dbo/AuthInfo> #include <Wt/Auth/Dbo/AuthInfo.h>
#include <Wt/Auth/Dbo/UserDatabase> #include <Wt/Auth/Dbo/UserDatabase.h>
#include <Wt/Auth/FacebookService> #include <Wt/Auth/FacebookService.h>
#include <Wt/Auth/GoogleService> #include <Wt/Auth/GoogleService.h>
#include <Wt/Auth/HashFunction> #include <Wt/Auth/HashFunction.h>
#include <Wt/Auth/Login> #include <Wt/Auth/Login.h>
namespace { namespace {
@ -45,12 +45,14 @@ void Services::configureAuth() {
myAuthService.setAuthTokensEnabled(true, "logincookie"); myAuthService.setAuthTokensEnabled(true, "logincookie");
myAuthService.setEmailVerificationEnabled(true); myAuthService.setEmailVerificationEnabled(true);
myAuthService.setEmailVerificationRequired(true); myAuthService.setEmailVerificationRequired(true);
{
auto verifier = std::unique_ptr<Wt::Auth::PasswordVerifier>();
verifier->addHashFunction(std::make_unique< Wt::Auth::BCryptHashFunction >(7));
myPasswordService.setVerifier(std::move(verifier));
}
Wt::Auth::PasswordVerifier * verifier = new Wt::Auth::PasswordVerifier();
verifier->addHashFunction(new Wt::Auth::BCryptHashFunction(7));
myPasswordService.setVerifier(verifier);
myPasswordService.setAttemptThrottlingEnabled(true); myPasswordService.setAttemptThrottlingEnabled(true);
myPasswordService.setStrengthValidator(new Wt::Auth::PasswordStrengthValidator()); myPasswordService.setStrengthValidator(std::make_unique< Wt::Auth::PasswordStrengthValidator >());
if(Wt::Auth::GoogleService::configured()) if(Wt::Auth::GoogleService::configured())
myOAuthServices.push_back(new Wt::Auth::GoogleService(myAuthService)); myOAuthServices.push_back(new Wt::Auth::GoogleService(myAuthService));

View File

@ -1,5 +1,5 @@
#include <Wt/WStandardItem> #include <Wt/WStandardItem.h>
#include <Wt/WStandardItemModel> #include <Wt/WStandardItemModel.h>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
@ -9,22 +9,22 @@ auto secondLevelRows = 300;
namespace eedb { namespace eedb {
class CategoriesModel final : public Wt::WStandardItemModel { class CategoriesModel final : public Wt::WStandardItemModel {
public: public:
CategoriesModel(Wt::WObject * parent) : Wt::WStandardItemModel(parent) { CategoriesModel(Wt::WObject * parent) : Wt::WStandardItemModel() {
auto model = this; auto model = this;
auto root = model->invisibleRootItem(); auto root = model->invisibleRootItem();
for(int row = 0; row < topLevelRows; ++row) { for(int row = 0; row < topLevelRows; ++row) {
Wt::WStandardItem * topLevel = new Wt::WStandardItem(); auto topLevel = std::make_unique< Wt::WStandardItem >();
topLevel->setText("Item " + boost::lexical_cast< std::string >(row)); topLevel->setText("Item " + boost::lexical_cast< std::string >(row));
for(int row2 = 0; row2 < secondLevelRows; ++row2) { for(int row2 = 0; row2 < secondLevelRows; ++row2) {
Wt::WStandardItem * item = new Wt::WStandardItem(); auto item = std::make_unique< Wt::WStandardItem >();
item->setToolTip("this is a tooltip"); item->setToolTip("this is a tooltip");
item->setText("Item " + boost::lexical_cast< std::string >(row) + ": " + boost::lexical_cast< std::string >(row2)); item->setText("Item " + boost::lexical_cast< std::string >(row) + ": " + boost::lexical_cast< std::string >(row2));
topLevel->appendRow(item); topLevel->appendRow(std::move(item));
} }
root->appendRow(topLevel); root->appendRow(std::move(topLevel));
} }
} }
private: private:
}; };
} } // namespace eedb

View File

@ -10,7 +10,7 @@
#include <eedb/model/user.h> #include <eedb/model/user.h>
#include <eedb/model/user_audit.h> #include <eedb/model/user_audit.h>
#include <Wt/WString> #include <Wt/WString.h>
#include <boost/spirit/home/support/char_class.hpp> #include <boost/spirit/home/support/char_class.hpp>

View File

@ -1,12 +1,9 @@
set(SOURCE set(SOURCE
connection.cpp connection.cpp
config.cpp config.cpp
) )
find_package(Sqlpp11 REQUIRED)
find_package(PostgreSQL REQUIRED)
INCLUDE_DIRECTORIES( ${PostgreSQL_INCLUDE_DIRS} ) INCLUDE_DIRECTORIES( ${PostgreSQL_INCLUDE_DIRS} )
add_library(eedb_db ${SOURCE}) add_library(eedb_db ${SOURCE})
target_link_libraries( eedb_db sqlpp-postgresql ) target_link_libraries( eedb_db wt sqlpp-postgresql )

View File

@ -1,7 +1,7 @@
#include <eedb/db/config.hpp> #include <eedb/db/config.hpp>
#include <Wt/WEnvironment> #include <Wt/WEnvironment.h>
#include <Wt/WServer> #include <Wt/WServer.h>
namespace eedb::db { namespace eedb::db {
PgConfig::PgConfig(const Wt::WEnvironment & env) { PgConfig::PgConfig(const Wt::WEnvironment & env) {
@ -36,4 +36,4 @@ PgConfig::PgConfig(const Wt::WEnvironment & env) {
readInt("db_port", port, 5432); readInt("db_port", port, 5432);
readBool("db_debug", debug, true); readBool("db_debug", debug, true);
} }
} } // namespace eedb::db

View File

@ -4,12 +4,12 @@
namespace Wt { namespace Wt {
class WEnvironment; class WEnvironment;
} } // namespace Wt
namespace eedb::db { namespace eedb::db {
class PgConfig : public sqlpp::postgresql::connection_config { class PgConfig : public sqlpp::postgresql::connection_config {
public: public:
PgConfig(const Wt::WEnvironment & env); explicit PgConfig(const Wt::WEnvironment & env);
}; };
} } // namespace eedb::db

View File

@ -1,12 +1,12 @@
#include <eedb/widgets/BootstrapTheme.hpp> #include <eedb/widgets/BootstrapTheme.hpp>
#include <Wt/WBootstrapTheme> #include <Wt/WBootstrapTheme.h>
namespace eedb { namespace eedb {
Wt::WTheme * BootstrapTheme::create(Wt::WObject * parent) const { std::shared_ptr<Wt::WTheme> BootstrapTheme::create() const {
auto theme = new Wt::WBootstrapTheme(parent); auto theme = std::shared_ptr<Wt::WBootstrapTheme>();
theme->setVersion(Wt::WBootstrapTheme::Version2); theme->setVersion(Wt::WBootstrapTheme::Version::v3);
// theme->setResponsive(true); // theme->setResponsive(true);
return theme; return theme;
} }

View File

@ -9,6 +9,6 @@ class BootstrapTheme final : public Theme {
BootstrapTheme(Theme &&) {} BootstrapTheme(Theme &&) {}
BootstrapTheme(const Theme &) {} BootstrapTheme(const Theme &) {}
Wt::WTheme * create(Wt::WObject * parent) const override; std::shared_ptr< Wt::WTheme > create() const override;
}; };
} }

View File

@ -2,9 +2,9 @@
#include <eedb/auth/Services.hpp> #include <eedb/auth/Services.hpp>
#include <eedb/widgets/DefaultAuthPage.hpp> #include <eedb/widgets/DefaultAuthPage.hpp>
#include <Wt/Auth/AbstractUserDatabase> #include <Wt/Auth/AbstractUserDatabase.h>
#include <Wt/Auth/AuthWidget> #include <Wt/Auth/AuthWidget.h>
#include <Wt/WContainerWidget> #include <Wt/WContainerWidget.h>
namespace std { namespace std {
@ -15,7 +15,7 @@ struct default_delete< Wt::Auth::AuthWidget > {
delete ptr; delete ptr;
} }
}; };
} } // namespace std
namespace eedb { namespace eedb {
@ -23,7 +23,7 @@ struct DefaultAuthPage::DefaultAuthPagePriv {
DefaultAuthPagePriv(const auth::Services & baseAuth, DefaultAuthPagePriv(const auth::Services & baseAuth,
std::unique_ptr< Wt::Auth::AbstractUserDatabase > userDatabase, std::unique_ptr< Wt::Auth::AbstractUserDatabase > userDatabase,
Wt::Auth::Login & _login) Wt::Auth::Login & _login)
: _authWidget(std::make_unique< Wt::Auth::AuthWidget >(*baseAuth.authService(), *userDatabase.get(), _login, nullptr)), : _authWidget(std::make_unique< Wt::Auth::AuthWidget >(*baseAuth.authService(), *userDatabase.get(), _login)),
_userDatabase(std::move(userDatabase)) { _userDatabase(std::move(userDatabase)) {
_authWidget->model()->addPasswordAuth(eedb::auth::Services::passwordService()); _authWidget->model()->addPasswordAuth(eedb::auth::Services::passwordService());
_authWidget->model()->addOAuth(eedb::auth::Services::oAuthServices()); _authWidget->model()->addOAuth(eedb::auth::Services::oAuthServices());
@ -43,17 +43,18 @@ DefaultAuthPage::DefaultAuthPage(const auth::Services & baseAuth,
std::unique_ptr< Wt::Auth::AbstractUserDatabase > userDatabase, std::unique_ptr< Wt::Auth::AbstractUserDatabase > userDatabase,
Wt::Auth::Login & _login) Wt::Auth::Login & _login)
: _priv(std::make_unique< DefaultAuthPagePriv >(baseAuth, std::move(userDatabase), _login)) { : _priv(std::make_unique< DefaultAuthPagePriv >(baseAuth, std::move(userDatabase), _login)) {
_priv->_authWidget->login().changed().connect([this](auto...) { ///FIXME
if(_priv->_authWidget->login().state() == Wt::Auth::LoginState::StrongLogin) { // _priv->_authWidget->login().changed().connect([this](auto...) {
this->notifyUserStrongLogin(); // if(_priv->_authWidget->login().state() == Wt::Auth::LoginState::Strong) {
} else if(_priv->_authWidget->login().state() == Wt::Auth::LoginState::WeakLogin) { // this->notifyUserStrongLogin();
this->notifyUserWeakLogin(); // } else if(_priv->_authWidget->login().state() == Wt::Auth::LoginState::Weak) {
} else if(_priv->_authWidget->login().state() == Wt::Auth::LoginState::DisabledLogin) { // this->notifyUserWeakLogin();
this->notifyNeedEmailVerification(); // } else if(_priv->_authWidget->login().state() == Wt::Auth::LoginState::Disabled) {
} else { // this->notifyNeedEmailVerification();
this->notifyUserLogout(); // } else {
} // this->notifyUserLogout();
}); // }
// });
} }
DefaultAuthPage::DefaultAuthPage(DefaultAuthPage && rhs) : _priv(std::move(rhs._priv)) {} DefaultAuthPage::DefaultAuthPage(DefaultAuthPage && rhs) : _priv(std::move(rhs._priv)) {}
@ -65,7 +66,7 @@ DefaultAuthPage & DefaultAuthPage::operator=(DefaultAuthPage && rhs) {
DefaultAuthPage::~DefaultAuthPage() = default; DefaultAuthPage::~DefaultAuthPage() = default;
void DefaultAuthPage::attachTo(Wt::WContainerWidget * parent) { void DefaultAuthPage::attachTo(Wt::WContainerWidget * parent) {
parent->addWidget(_priv->_authWidget.get()); parent->addWidget(std::move(_priv->_authWidget));
} }
void DefaultAuthPage::detach() { void DefaultAuthPage::detach() {
@ -79,19 +80,19 @@ void DefaultAuthPage::processEnvironment() {
} }
void DefaultAuthPage::registerNeedVerification(std::function< void() > f) { void DefaultAuthPage::registerNeedVerification(std::function< void() > f) {
_priv->_onNeedEmailVerification.connect([=](auto...) { f(); }); _priv->_onNeedEmailVerification.connect([=]() { f(); });
} }
void DefaultAuthPage::registerOnUserWeakLogin(std::function< void() > f) { void DefaultAuthPage::registerOnUserWeakLogin(std::function< void() > f) {
_priv->_onUserWeakLogin.connect([=](auto...) { f(); }); _priv->_onUserWeakLogin.connect([=]() { f(); });
} }
void DefaultAuthPage::registerOnUserStrongLogin(std::function< void() > f) { void DefaultAuthPage::registerOnUserStrongLogin(std::function< void() > f) {
_priv->_onUserStrongLogin.connect([=](auto...) { f(); }); _priv->_onUserStrongLogin.connect([=]() { f(); });
} }
void DefaultAuthPage::registerOnUserLogout(std::function< void() > f) { void DefaultAuthPage::registerOnUserLogout(std::function< void() > f) {
_priv->_onUserLogout.connect([=](auto...) { f(); }); _priv->_onUserLogout.connect([=]() { f(); });
} }
void DefaultAuthPage::notifyUserStrongLogin() const { void DefaultAuthPage::notifyUserStrongLogin() const {
@ -109,4 +110,4 @@ void DefaultAuthPage::notifyNeedEmailVerification() const {
void DefaultAuthPage::notifyUserLogout() const { void DefaultAuthPage::notifyUserLogout() const {
_priv->_onUserLogout.emit(); _priv->_onUserLogout.emit();
} }
} } // namespace eedb

View File

@ -2,8 +2,8 @@
#include <eedb/data/Category.hpp> #include <eedb/data/Category.hpp>
#include <Wt/WContainerWidget> #include <Wt/WContainerWidget.h>
#include <Wt/WTreeView> #include <Wt/WTreeView.h>
namespace std { namespace std {
@ -30,7 +30,7 @@ DefaultCategoriesTree::DefaultCategoriesTree() : _priv(std::make_unique< Default
DefaultCategoriesTree::~DefaultCategoriesTree() = default; DefaultCategoriesTree::~DefaultCategoriesTree() = default;
void DefaultCategoriesTree::attachTo(Wt::WContainerWidget * parent) { void DefaultCategoriesTree::attachTo(Wt::WContainerWidget * parent) {
parent->addWidget(_priv->tree.get()); parent->addWidget(std::move(_priv->tree));
} }
void DefaultCategoriesTree::registerOnCategoryChanged(std::function< void(const Category &) >) {} void DefaultCategoriesTree::registerOnCategoryChanged(std::function< void(const Category &) >) {}

View File

@ -1,23 +1,23 @@
#include <eedb/widgets/DefaultHomePage.hpp> #include <eedb/widgets/DefaultHomePage.hpp>
#include <Wt/Auth/Login> #include <Wt/Auth/Login.h>
#include <Wt/WContainerWidget> #include <Wt/WContainerWidget.h>
#include <Wt/WEnvironment> #include <Wt/WEnvironment.h>
#include <Wt/WLineEdit> #include <Wt/WLineEdit.h>
#include <Wt/WMessageBox> #include <Wt/WMessageBox.h>
#include <Wt/WServer> #include <Wt/WServer.h>
#include <Wt/WStackedWidget> #include <Wt/WStackedWidget.h>
#include <Wt/WText> #include <Wt/WText.h>
#include <Wt/WTextArea> #include <Wt/WTextArea.h>
#include <Wt/WIconPair> #include <Wt/WIconPair.h>
#include <Wt/WLogger> #include <Wt/WLogger.h>
#include <Wt/WText> #include <Wt/WText.h>
#include <Wt/WTreeNode> #include <Wt/WTreeNode.h>
#include <Wt/WTreeView> #include <Wt/WTreeView.h>
#include <Wt/WHBoxLayout> #include <Wt/WHBoxLayout.h>
#include <Wt/WVBoxLayout> #include <Wt/WVBoxLayout.h>
#include <eedb/Session.hpp> #include <eedb/Session.hpp>
#include <eedb/data/CategoriesModel.hpp> #include <eedb/data/CategoriesModel.hpp>
@ -26,15 +26,15 @@
namespace eedb { namespace eedb {
auto make_tree() { auto make_tree() {
auto tree = new Wt::WTreeView(); auto tree = std::make_unique< Wt::WTreeView >();
Wt::WAbstractItemModel * model = new eedb::CategoriesModel(tree); auto model = std::unique_ptr<eedb::CategoriesModel>();
tree->setModel(model); tree->setModel(std::move(model));
tree->setColumnResizeEnabled(true); tree->setColumnResizeEnabled(true);
tree->setSortingEnabled(false); tree->setSortingEnabled(false);
tree->setSelectionMode(Wt::SingleSelection); tree->setSelectionMode(Wt::SelectionMode::Single);
tree->setEditTriggers(Wt::WAbstractItemView::NoEditTrigger); tree->setEditTriggers(Wt::EditTrigger::None);
return tree; return tree;
} }
@ -45,25 +45,26 @@ eedb::DefaultHomePage::DefaultHomePage(Session & session, std::unique_ptr< eedb:
DefaultHomePage::~DefaultHomePage() = default; DefaultHomePage::~DefaultHomePage() = default;
void DefaultHomePage::attachTo(Wt::WContainerWidget * container) { void DefaultHomePage::attachTo(Wt::WContainerWidget * container) {
auto stackedWidget = new Wt::WStackedWidget(); auto stackedWidget = std::make_unique<Wt::WStackedWidget>();
_navigationBar->attachTo(stackedWidget); _navigationBar->attachTo(stackedWidget.get());
_navigationBar->registerLogoutAction([=]() { this->_session.login().logout(); }); _navigationBar->registerLogoutAction([=]() { this->_session.login().logout(); });
Wt::WVBoxLayout * vbox = new Wt::WVBoxLayout(); auto vbox = std::make_unique< Wt::WVBoxLayout >();
container->setLayout(vbox); container->setLayout(std::move(vbox));
vbox->addWidget(stackedWidget, 0); vbox->addWidget(std::move(stackedWidget), 0);
Wt::WHBoxLayout * hbox = new Wt::WHBoxLayout(); auto hbox = std::unique_ptr<Wt::WHBoxLayout>();
vbox->addLayout(hbox, 10); vbox->addLayout(std::move(hbox), 10);
Wt::WStackedWidget * contents = new Wt::WStackedWidget(); auto contents = std::unique_ptr< Wt::WStackedWidget>();
_categoryTree = make_tree(); auto tree=make_tree();
_categoryTree->clicked().connect([=](auto...) { Wt::log("notice") << "Item selection changed"; }); _categoryTree = tree.get();
_categoryTree->clicked().connect([](Wt::WModelIndex, Wt::WMouseEvent) { Wt::log("notice") << "Item selection changed"; });
hbox->addWidget(_categoryTree, 1); hbox->addWidget(std::move(tree), 1);
hbox->addWidget(contents, 2); hbox->addWidget(std::move(contents), 2);
hbox->setResizable(0, true); hbox->setResizable(0, true);
} }
} }

View File

@ -1,20 +1,9 @@
#include <eedb/widgets/DefaultNavigationBar.hpp> #include <eedb/widgets/DefaultNavigationBar.hpp>
#include <Wt/WMenu> #include <Wt/WMenu.h>
#include <Wt/WNavigationBar> #include <Wt/WNavigationBar.h>
#include <Wt/WPopupMenu> #include <Wt/WPopupMenu.h>
#include <Wt/WStackedWidget> #include <Wt/WStackedWidget.h>
namespace std {
template <>
struct default_delete< Wt::WNavigationBar > {
void operator()(Wt::WNavigationBar * ptr) {
if(ptr && !ptr->parent())
delete ptr;
}
};
}
namespace eedb { namespace eedb {
@ -25,33 +14,34 @@ struct DefaultNavigationBar::DefaultNavigationBarPriv {
return; return;
// Setup a Left-aligned menu. // Setup a Left-aligned menu.
auto mainTabs = new Wt::WMenu(); auto mainTabs = std::make_unique< Wt::WMenu >();
auto homeItem = mainTabs->addItem("Home"); auto homeItem = mainTabs->addItem("Home");
homeItem->setObjectName("navigation_bar.home_menu"); homeItem->setObjectName("navigation_bar.home_menu");
homeItem->triggered().connect([=](auto...) {}); ///FIXME
// homeItem->triggered().connect([=](auto...) {});
// Setup a Right-aligned menu. // Setup a Right-aligned menu.
// Create a popup submenu for the Help menu. // Create a popup submenu for the Help menu.
auto sessionMenuPopup = new Wt::WPopupMenu(); auto sessionMenuPopup = std::make_unique< Wt::WPopupMenu >();
sessionMenuPopup->setObjectName("navigation_bar.session_menu_popup"); sessionMenuPopup->setObjectName("navigation_bar.session_menu_popup");
auto logoutItem = sessionMenuPopup->addItem("Logout"); Wt::WMenuItem * logoutItem = sessionMenuPopup->addItem("Logout");
logoutItem->setObjectName("navigation_bar.session_menu.logout"); logoutItem->setObjectName("navigation_bar.session_menu.logout");
logoutItem->triggered().connect([=](auto...) { this->onLogin.emit(); }); logoutItem->triggered().connect([=](Wt::WMenuItem *) { this->onLogin.emit(); });
auto sessionItem = new Wt::WMenuItem("Session"); auto sessionItem = std::make_unique< Wt::WMenuItem >("Session");
sessionItem->setMenu(sessionMenuPopup); sessionItem->setMenu(std::move(sessionMenuPopup));
auto sessionMenu = new Wt::WMenu(); auto sessionMenu = std::make_unique< Wt::WMenu >();
sessionMenu->setObjectName("navigation_bar.session_menu"); sessionMenu->setObjectName("navigation_bar.session_menu");
sessionMenu->addItem(sessionItem); sessionMenu->addItem(std::move(sessionItem));
_bar = std::make_unique< Wt::WNavigationBar >(); _bar = std::make_unique< Wt::WNavigationBar >();
_bar->setObjectName("navigation_bar"); _bar->setObjectName("navigation_bar");
_bar->setTitle("eedb", "http://eedb.pl"); _bar->setTitle("eedb", "http://eedb.pl");
_bar->setResponsive(true); _bar->setResponsive(true);
_bar->addMenu(mainTabs, Wt::AlignLeft); _bar->addMenu(std::move(mainTabs), Wt::AlignmentFlag::Left);
_bar->addMenu(sessionMenu, Wt::AlignRight); _bar->addMenu(std::move(sessionMenu), Wt::AlignmentFlag::Right);
} }
Wt::Signal<> onLogin; Wt::Signal<> onLogin;
@ -72,7 +62,7 @@ DefaultNavigationBar::~DefaultNavigationBar() = default;
void DefaultNavigationBar::attachTo(Wt::WContainerWidget * container) { void DefaultNavigationBar::attachTo(Wt::WContainerWidget * container) {
_priv->create(); _priv->create();
container->addWidget(_priv->_bar.get()); container->addWidget(std::move(_priv->_bar));
} }
void DefaultNavigationBar::detach() { void DefaultNavigationBar::detach() {
@ -82,6 +72,6 @@ void DefaultNavigationBar::detach() {
} }
void DefaultNavigationBar::registerLogoutAction(std::function< void() > f) { void DefaultNavigationBar::registerLogoutAction(std::function< void() > f) {
_priv->onLogin.connect([f](auto...) { f(); }); _priv->onLogin.connect([f]() { f(); });
}
} }
} // namespace eedb

View File

@ -1,45 +1,42 @@
#include "MenuTree.hpp" #include "MenuTree.hpp"
#include <sqlpp11/postgresql/connection.h>
#include <eedb/db/connection.hpp> #include <eedb/db/connection.hpp>
#include <sqlpp11/sqlpp11.h>
#include <eedb/model/auth_info.h> #include <eedb/model/auth_info.h>
#include <eedb/model/category.h> #include <eedb/model/category.h>
#include <sqlpp11/postgresql/connection.h>
#include <sqlpp11/sqlpp11.h>
#include <utility>
void eedb::MenuTree::createTree() void eedb::MenuTree::createTree() {
{
using namespace eedb::db; using namespace eedb::db;
using namespace sqlpp; // using namespace sqlpp;
Wt::WTree *tree = new Wt::WTree(); Wt::WTree * tree = new Wt::WTree();
tree->setSelectionMode(Wt::ExtendedSelection); tree->setSelectionMode(Wt::SelectionMode::Extended);
Wt::WIconPair *folderIcon auto folderIcon = std::make_unique< Wt::WIconPair >("icons/yellow-folder-closed.png", "icons/yellow-folder-open.png", false);
= new Wt::WIconPair("icons/yellow-folder-closed.png",
"icons/yellow-folder-open.png", false);
Wt::WTreeNode *node = new Wt::WTreeNode("Categories", folderIcon); auto node = std::make_unique< Wt::WTreeNode >("Categories", std::move(folderIcon));
tree->setTreeRoot(node); tree->setTreeRoot(std::move(node));
node->label()->setTextFormat(Wt::PlainText); node->label()->setTextFormat(Wt::TextFormat::Plain);
node->setLoadPolicy(Wt::WTreeNode::NextLevelLoading); node->setLoadPolicy(Wt::ContentLoading::Lazy);
///FIXME
// const eedb::category cat;
const eedb::category cat; // auto r = _db(sqlpp::select(sqlpp::all_of(cat)).from(cat).where(cat.parent_path < 'root'));
auto r = _db(sqlpp::select( sqlpp::all_of(cat) ).from(cat).where(cat.parent_path < 'root') ); // for(const auto & row : r) {
// node->addChildNode(new Wt::WTreeNode(row.Name));
// }
for (const auto & row: r){\ // if (_db.is_open()){
node->addChildNode(new Wt::WTreeNode(row.Name)); // auto sql = "SELECT * FROM category WHERE parent_path <@ 'root'";
} // nontransaction N(C);
// result R( N.exec( sql ));
// if (_db.is_open()){
// auto sql = "SELECT * FROM category WHERE parent_path <@ 'root'";
// nontransaction N(C);
// result R( N.exec( sql ));
// for (auto r = R.begin(); r<R.end(); r++)
// node->addChildNode(new Wt::WTreeNode(r[1].as<std::string>()));
// for (auto r = R.begin(); r<R.end(); r++)
// node->addChildNode(new Wt::WTreeNode(r[1].as<std::string>()));
} }

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <Wt/WIconPair> #include <Wt/WIconPair.h>
#include <Wt/WText> #include <Wt/WText.h>
#include <Wt/WTree> #include <Wt/WTree.h>
#include <Wt/WTreeNode> #include <Wt/WTreeNode.h>
namespace eedb::db { namespace eedb::db {
class PgConnection; class PgConnection;

View File

@ -1,8 +1,9 @@
#pragma once #pragma once
#include <memory>
namespace Wt { namespace Wt {
class WTheme; class WTheme;
class WObject;
} }
namespace eedb { namespace eedb {
@ -13,7 +14,7 @@ class Theme {
virtual ~Theme(); virtual ~Theme();
virtual Wt::WTheme * create(Wt::WObject * parent) const = 0; virtual std::shared_ptr<Wt::WTheme> create() const = 0;
}; };