This commit is contained in:
Bartosz Wieczorek 2018-03-01 09:22:24 +01:00
parent 240654e6a0
commit e927cd9ba0
38 changed files with 261 additions and 127 deletions

View File

@ -18,6 +18,9 @@ include(cmake/Compiler.cmake)
include(cmake/FindAllRequirements.cmake)
include(cmake/cotire.cmake)
set(CMAKE_INSTALL_RPATH "${HUNTER_INSTALL_PREFIX}/lib")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
include_directories(${CMAKE_BINARY_DIR}/external/include SYSTEM)
include_directories(${CMAKE_BINARY_DIR}/external/include/date SYSTEM)
include_directories(share SYSTEM)

View File

@ -20,8 +20,8 @@ find_package(spdlog CONFIG REQUIRED)
hunter_add_package(PostgreSQL)
find_package(PostgreSQL REQUIRED)
#set(MAKE_CMD "${CMAKE_CURRENT_SOURCE_DIR}/cmake/install_deps.sh")
#MESSAGE("COMMAND: ${MAKE_CMD} ${CMAKE_COMMAND} ${CMAKE_GENERATOR} ${CMAKE_CXX_COMPILER} ${CMAKE_C_COMPILER} ${CMAKE_PREFIX_PATH}")
set(MAKE_CMD "${CMAKE_CURRENT_SOURCE_DIR}/cmake/install_deps.sh")
MESSAGE("COMMAND: ${MAKE_CMD} ${CMAKE_COMMAND} ${CMAKE_GENERATOR} ${CMAKE_CXX_COMPILER} ${CMAKE_C_COMPILER} ${CMAKE_PREFIX_PATH} ${Boost_LIBRARY_DIR_DEBUG}")
#execute_process(
# COMMAND x-terminal-emulator -e "sudo ${MAKE_CMD} ${CMAKE_GENERATOR} ${CMAKE_COMMAND} ${CMAKE_CXX_COMPILER} ${CMAKE_C_COMPILER} ${CMAKE_PREFIX_PATH}"
# WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/external )

View File

@ -3,6 +3,7 @@ CMAKE_GENERATOR=$2
CMAKE_CXX_COMPILER=$3
CMAKE_C_COMPILER=$4
CMAKE_PREFIX_PATH=$5
CMAKE_RPATH=$6
# clone all
if [ ! -d date/.git ]; then
@ -52,7 +53,8 @@ cd ../
mkdir wt-build; cd wt-build
${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ../wt -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} \
-DBoost_NO_BOOST_CMAKE=TRUE\
-DBoost_NO_BOOST_CMAKE=FALSE\
-DCMAKE_INSTALL_RPATH=${CMAKE_RPATH}\
-DBoost_NO_SYSTEM_PATHS=TRUE\
-DBUILD_EXAMPLES=OFF\
-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}\
@ -73,5 +75,5 @@ ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ../wt -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COM
${CMAKE_COMMAND} --build . --target install
cd ../
echo "NOW WAIT"
sleep 100000

View File

@ -2,17 +2,9 @@ set(SOURCES
main.cpp
)
find_package(wt)
add_executable(eedb_app ${SOURCES})
target_link_libraries(eedb_app
PRIVATE wthttp # or {Wt_HTTP_DEBUG_LIBRARY}
PRIVATE wt # or {Wt_DEBUG_LIBRARY}
PRIVATE postgres_connector
PRIVATE auth
PRIVATE widgets
PRIVATE app
z
PRIVATE postgres_connector
)

View File

@ -1,88 +1,81 @@
#include <eedb/EEDB.hpp>
#include <eedb/WebSession.hpp>
#include <eedb/auth/PgUserAuth.hpp>
#include <eedb/auth/Services.hpp>
#include <spdlog/spdlog.h>
#include <eedb/db/pg/config.hpp>
#include <eedb/db/pg/connection.hpp>
#include <eedb/db/pg/PgCategoriesRepository.hpp>
#include <eedb/db/pg/PgUsers.hpp>
#include <widget/BootstrapTheme.hpp>
#include <widget/DefaultAuthPage.hpp>
#include <widget/DefaultHomePage.hpp>
#include <widget/DefaultNavigationBar.hpp>
#include <eedb/WebApplicationFactory.hpp>
#include <eedb/WebServer.hpp>
#include <Wt/WApplication.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WServer.h>
#include <Wt/WText.h>
#include <sqlpp11/postgresql/exception.h>
#include <set>
#include <spdlog/spdlog.h>
class ErrorWindow : public Wt::WApplication {
public:
ErrorWindow(const Wt::WEnvironment & env);
};
ErrorWindow::ErrorWindow(const Wt::WEnvironment & env) : Wt::WApplication(env) {
root()->addWidget(std::make_unique< Wt::WText >("error"));
}
std::unique_ptr< Wt::WApplication > createApplication(const Wt::WEnvironment & env) {
try {
using std::make_unique;
using std::move;
using std::unique_ptr;
auto dbConfig = make_unique< eedb::db::PgConfig >(
[&env](const std::string & name, std::string & prop) { return env.server()->readConfigurationProperty(name, prop); });
auto dbConnection = make_unique< eedb::db::PgConnection >(move(dbConfig));
auto session = unique_ptr< eedb::Session >(make_unique< eedb::WebSession >(move(dbConnection), env));
auto authPageFactory = [_session = session.get()]()->std::unique_ptr< eedb::AuthPage > {
auto usersRegistry = make_unique< eedb::PgUsers >(_session->db());
auto userDatabase = make_unique< eedb::auth::UserDatabase >(move(usersRegistry), _session->enviroment());
auto services = eedb::auth::Services();
auto & login = _session->login();
return make_unique< eedb::DefaultAuthPage >(services, std::move(userDatabase), login);
};
auto homePageFactory = [_session = session.get()]()->std::unique_ptr< eedb::HomePage > {
auto navigationBar = std::make_unique< eedb::DefaultNavigationBar >();
return make_unique< eedb::DefaultHomePage >(*_session, std::move(navigationBar));
};
return make_unique< eedb::EEDB >(std::move(session), authPageFactory, homePageFactory);
} catch(const sqlpp::postgresql::broken_connection & e) {
std::cout << "sql exception: " << e.what();
return std::make_unique< ErrorWindow >(env);
}
}
int main(int argc, char ** argv) {
static auto _createSinks() {
std::vector< spdlog::sink_ptr > sinks;
auto stdout_sink = spdlog::sinks::stdout_sink_mt::instance();
auto color_sink = std::make_shared< spdlog::sinks::ansicolor_sink >(stdout_sink);
sinks.push_back(color_sink);
sinks.push_back(std::make_shared< spdlog::sinks::daily_file_sink_st >("logfile", 23, 59));
return sinks;
}
static void initializeLogs() {
std::vector< spdlog::sink_ptr > sinks = _createSinks();
auto combined_logger = std::make_shared< spdlog::logger >("default", begin(sinks), end(sinks));
combined_logger->set_level(spdlog::level::trace);
spdlog::register_logger(combined_logger);
}
static auto createDbConnection(std::function< bool(const std::string &, std::string &) > propRead) {
using std::make_unique;
using std::move;
using std::unique_ptr;
auto dbConfig = make_unique< eedb::db::PgConfig >(propRead);
try {
Wt::WServer server(argc, argv, WTHTTP_CONFIGURATION);
server.addEntryPoint(Wt::EntryPointType::Application, createApplication);
eedb::auth::Services::configureAuth();
server.run();
} catch(Wt::WServer::Exception & e) {
std::cerr << e.what() << std::endl;
} catch(std::exception & e) {
std::cerr << "exception: " << e.what() << std::endl;
return make_unique< eedb::db::PgConnection >(std::move(dbConfig));
} catch(const sqlpp::postgresql::broken_connection & e) {
std::cout << "sql exception: " << e.what();
// return std::make_unique< ErrorWindow >(env)
}
}
int main(int argc, char ** argv) {
initializeLogs();
std::set< std::unique_ptr< eedb::db::PgConnection > > activeConnections;
eedb::WebServer server{argc, argv};
server.run([&activeConnections, &server](const auto & env) {
// in order to extend the lifetime of new connection to the lifetime of web application, we need to
// hold it in external container
auto dbIt = activeConnections.emplace(createDbConnection(server.getPropertiesReader())).first;
eedb::WebApplicationFactory factory;
return factory.create(
[&activeConnections, dbIt]() {
// remove connection hold by application from container
spdlog::get("default")->info("Removing database connection from connection list");
activeConnections.erase(dbIt);
},
// users factory
[db = dbIt->get()]() { //
return std::make_unique< eedb::PgUsers >(*db);
},
// categories factory
[db = dbIt->get()](eedb::User * owner) { //
return std::make_unique< eedb::PgCategoriesRepository >(*db, owner);
},
env);
});
return 0;
}

View File

@ -3,6 +3,7 @@ set(LIB app)
file(GLOB_RECURSE app_SOURCE src/*)
# find packages
find_package(wt)
find_package(nlohmann_json CONFIG REQUIRED)
# create library
@ -14,10 +15,10 @@ target_include_directories(${LIB}
)
target_link_libraries(${LIB}
PUBLIC eedb-api
PRIVATE wthttp # or {Wt_HTTP_DEBUG_LIBRARY}
PRIVATE wt # or {Wt_DEBUG_LIBRARY}
PUBLIC auth
PUBLIC widgets
PUBLIC postgres_connector
PUBLIC Boost::system
PUBLIC Boost::filesystem
PUBLIC Boost::thread
@ -31,4 +32,4 @@ set_target_properties(${LIB} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
cotire(${LIB})
# add tests
#add_subdirectory(test)
add_subdirectory(test)

View File

@ -1,3 +1,4 @@
#pragma once
#include <functional>
#include <memory>
@ -11,7 +12,7 @@ class WTheme;
namespace eedb {
class AuthPage;
class HomePage;
class Session;
class WebSession;
class User;
@ -21,7 +22,7 @@ using HomePageFactory = std::function< std::unique_ptr< HomePage >(/*std::shared
class EEDB : public Wt::WApplication {
public:
enum class LoginState { weak, strong };
EEDB(std::unique_ptr< eedb::Session > session, AuthPageFactory authPageFactory, HomePageFactory homePageFactory);
EEDB(std::unique_ptr< eedb::WebSession > session, AuthPageFactory authPageFactory, HomePageFactory homePageFactory);
void authEventLogin(LoginState state);
@ -29,7 +30,7 @@ class EEDB : public Wt::WApplication {
private:
// application session
std::unique_ptr< eedb::Session > _session;
std::unique_ptr< eedb::WebSession > _session;
AuthPageFactory _authPageFactory;
std::unique_ptr< eedb::AuthPage > _authPage;

View File

@ -4,18 +4,14 @@ namespace eedb::auth {
class UserDatabase;
}
namespace eedb::db {
class PgConnection;
};
namespace Wt{
namespace Wt {
class WEnvironment;
}
namespace Wt::Auth {
class AbstractUserDatabase;
class Login;
}
} // namespace Wt::Auth
namespace eedb {
@ -23,8 +19,6 @@ class Session {
public:
virtual ~Session() = default;
virtual eedb::db::PgConnection & db() = 0;
virtual const Wt::WEnvironment & enviroment() const = 0;
virtual Wt::Auth::Login & login() = 0;
};

View File

@ -0,0 +1,29 @@
#pragma once
#include <functional>
#include <memory>
namespace eedb {
class CategoriesRepository;
class Users;
class User;
} // namespace eedb
namespace Wt {
class WApplication;
class WEnvironment;
} // namespace Wt
namespace eedb {
class WebApplicationFactory {
public:
using UsersFactory = std::function< std::unique_ptr< eedb::Users >() >;
using CategoriesFactory = std::function< std::unique_ptr< eedb::CategoriesRepository >(eedb::User *) >;
using DbHolder = std::function< void() >;
public:
std::unique_ptr< Wt::WApplication >
create(DbHolder db, UsersFactory users, CategoriesFactory categories, const Wt::WEnvironment & env) const;
};
} // namespace eedb

View File

@ -0,0 +1,27 @@
#pragma once
#include <functional>
#include <utils/spimpl.hpp>
namespace Wt {
class WApplication;
class WEnvironment;
class WServer;
} // namespace Wt
namespace eedb {
class WebServer {
public:
using AppCreator = std::function< std::unique_ptr< Wt::WApplication >(const Wt::WEnvironment &) >;
WebServer(int argc, char ** argv);
std::function<bool(const std::string &, std::string& )> getPropertiesReader() const;
void run(AppCreator creator);
private:
spimpl::unique_impl_ptr< Wt::WServer > _server;
};
} // namespace eedb

View File

@ -20,15 +20,14 @@ namespace eedb {
class WebSession final : public Session {
public:
explicit WebSession(std::unique_ptr< eedb::db::PgConnection > dbConnection, const Wt::WEnvironment & env);
explicit WebSession(const Wt::WEnvironment & env, std::function<void()> dbCloser);
~WebSession() override;
eedb::db::PgConnection & db() override;
const Wt::WEnvironment & enviroment() const override;
const Wt::WEnvironment & enviroment() const;
Wt::Auth::Login & login() override;
private:
std::unique_ptr< eedb::db::PgConnection > _dbConnection;
std::function<void()> _dbCloser;
Wt::Auth::Login _login;
const Wt::WEnvironment & _env;
};

View File

@ -1,8 +1,8 @@
#include <eedb/EEDB.hpp>
#include <eedb/Session.hpp>
#include <eedb/WebSession.hpp>
#include <eedb/auth/PgUserAuth.hpp>
#include <eedb/db/pg/connection.hpp>
#include <widget/AuthPage.hpp>
#include <widget/BootstrapTheme.hpp>
#include <widget/HomePage.hpp>
@ -30,7 +30,7 @@ using std::move;
namespace eedb {
EEDB::EEDB(std::unique_ptr< Session > session, AuthPageFactory authPageFactory, HomePageFactory homePageFactory)
EEDB::EEDB(std::unique_ptr< WebSession > session, AuthPageFactory authPageFactory, HomePageFactory homePageFactory)
: Wt::WApplication(session->enviroment()),
_session(move(session)),
_authPageFactory(move(authPageFactory)),

View File

@ -0,0 +1,49 @@
#include <eedb/WebApplicationFactory.hpp>
#include <eedb/EEDB.hpp>
#include <eedb/WebSession.hpp>
#include <eedb/auth/PgUserAuth.hpp>
#include <eedb/auth/Services.hpp>
#include <widget/BootstrapTheme.hpp>
#include <widget/DefaultAuthPage.hpp>
#include <widget/DefaultHomePage.hpp>
#include <widget/DefaultNavigationBar.hpp>
#include <eedb/db/Category.hpp>
#include <eedb/db/User.hpp>
#include <eedb/db/Users.hpp>
#include <Wt/WApplication.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WServer.h>
#include <Wt/WText.h>
namespace eedb {
std::unique_ptr< Wt::WApplication > WebApplicationFactory::create(DbHolder db,
UsersFactory users,
CategoriesFactory categories,
const Wt::WEnvironment & env) const {
using std::make_unique;
using std::move;
using std::unique_ptr;
auto session = std::make_unique< eedb::WebSession >(env, std::move(db));
auto authPageFactory = [ usersRegistry = std::move(users), session = session.get() ]()->std::unique_ptr< eedb::AuthPage > {
auto userDatabase = make_unique< eedb::auth::UserDatabase >(usersRegistry());
auto services = eedb::auth::Services();
auto & login = session->login();
return make_unique< eedb::DefaultAuthPage >(services, std::move(userDatabase), login);
};
auto homePageFactory = [session = session.get()]()->std::unique_ptr< eedb::HomePage > {
auto navigationBar = std::make_unique< eedb::DefaultNavigationBar >();
return make_unique< eedb::DefaultHomePage >(*session, std::move(navigationBar));
};
return make_unique< eedb::EEDB >(std::move(session), std::move(authPageFactory), std::move(homePageFactory));
}
} // namespace eedb

View File

@ -0,0 +1,36 @@
#include <eedb/WebServer.hpp>
#include <eedb/EEDB.hpp>
#include <eedb/auth/Services.hpp>
#include <spdlog/spdlog.h>
#include <Wt/WServer.h>
namespace eedb {
WebServer::WebServer(int argc, char ** argv) : _server{spimpl::make_unique_impl< Wt::WServer >(argc, argv, WTHTTP_CONFIGURATION)} {}
std::function< bool(const std::string &, std::string &) > WebServer::getPropertiesReader() const {
return [server = _server.get()](const auto & name, auto & val) {
return server->readConfigurationProperty(name, val);
};
}
void WebServer::run(WebServer::AppCreator creator) {
try {
auto _run = [&creator](const auto & env) {
auto application = creator(env);
return application;
};
_server->addEntryPoint(Wt::EntryPointType::Application, _run);
eedb::auth::Services::configureAuth();
_server->run();
} catch(Wt::WServer::Exception & e) {
std::cerr << e.what() << std::endl;
} catch(std::exception & e) {
std::cerr << "exception: " << e.what() << std::endl;
}
}
} // namespace eedb

View File

@ -1,16 +1,12 @@
#include <eedb/WebSession.hpp>
#include <eedb/auth/PgUserAuth.hpp>
#include <eedb/db/pg/connection.hpp>
namespace eedb {
WebSession::WebSession(std::unique_ptr< eedb::db::PgConnection > dbConnection, const Wt::WEnvironment & env)
: _dbConnection(std::move(dbConnection)), _env(env) {}
WebSession::WebSession(const Wt::WEnvironment & env, std::function< void() > dbCloser) : _dbCloser{std::move(dbCloser)}, _env(env) {}
WebSession::~WebSession() =default;
db::PgConnection & WebSession::db() {
return *_dbConnection;
WebSession::~WebSession() {
_dbCloser();
}
const Wt::WEnvironment & WebSession::enviroment() const {

View File

@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.0.2)
#find packages
find_package(GMock CONFIG REQUIRED)
set(TEST_EXECUTABLE_NAME test-eedb_app)
#add test files
file(GLOB_RECURSE TEST_FILES test_*.cpp )
add_executable( ${TEST_EXECUTABLE_NAME} ${TEST_FILES})
target_link_libraries(${TEST_EXECUTABLE_NAME}
PRIVATE eedb-api
PRIVATE app
PRIVATE GMock::main
)
add_test( ${TEST_EXECUTABLE_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_EXECUTABLE_NAME})

View File

@ -0,0 +1 @@
#include <eedb/WebServer.hpp>

View File

View File

@ -8,10 +8,6 @@ namespace eedb {
class Users;
}
namespace Wt {
class WEnvironment;
}
namespace Wt::Auth {
class AuthService;
}
@ -20,7 +16,7 @@ namespace eedb::auth {
class UserDatabase : public Wt::Auth::AbstractUserDatabase {
public:
UserDatabase(std::unique_ptr< eedb::Users > users, const Wt::WEnvironment & env);
UserDatabase(std::unique_ptr< eedb::Users > users);
Transaction * startTransaction() override;

View File

@ -11,7 +11,6 @@
#include <eedb/db/Users.hpp>
#include <Wt/Auth/AuthService.h>
#include <Wt/WEnvironment.h>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
@ -43,7 +42,7 @@ static const std::string registration_id = "registration";
namespace eedb::auth {
struct UserDatabase::UserAuthPriv {
UserAuthPriv(std::unique_ptr< eedb::Users > users, const Wt::WEnvironment & env) : _users{std::move(users)}, _env{env} {
UserAuthPriv(std::unique_ptr< eedb::Users > users) : _users{std::move(users)} {
this->setAuthService(eedb::auth::Services::authService());
}
@ -66,13 +65,12 @@ struct UserDatabase::UserAuthPriv {
std::optional< int > _emailTokenRole;
bool _registration;
const Wt::WEnvironment & _env;
const Wt::Auth::AuthService * _authService;
int _in_transaction{0};
};
UserDatabase::UserDatabase(std::unique_ptr< eedb::Users > users, const Wt::WEnvironment & env)
: _priv{spimpl::make_unique_impl< UserDatabase::UserAuthPriv >(std::move(users), env)} {}
UserDatabase::UserDatabase(std::unique_ptr< eedb::Users > users)
: _priv{spimpl::make_unique_impl< UserDatabase::UserAuthPriv >(std::move(users))} {}
Wt::Auth::User UserDatabase::findWithId(const std::string & id) const {
spdlog::get("default")->debug("searching user by id: '{}'...", id);

View File

@ -9,29 +9,28 @@ find_package(Sqlpp-connector-postgresql REQUIRED)
add_library(${LIB} ${postgres_connector_SOURCE})
# link all
target_include_directories ( ${LIB}
target_include_directories (${LIB}
PRIVATE ${CMAKE_BINARY_DIR}/external/include SYSTEM
PRIVATE ${PostgreSQL_INCLUDE_DIRS}
)
target_include_directories( ${LIB}
target_include_directories(${LIB}
PUBLIC include
)
target_link_libraries( ${LIB}
PRIVATE eedb-api
PRIVATE Boost::filesystem
target_link_libraries(${LIB}
PUBLIC eedb-api
PRIVATE sqlpp11-connector-postgresql
PRIVATE pq
PRIVATE Boost::system
PUBLIC stdc++fs
PUBLIC sqlpp11-connector-postgresql
PUBLIC pq
PRIVATE Boost::filesystem
PRIVATE stdc++fs
)
# add cotire
set_target_properties( ${LIB}
set_target_properties(${LIB}
PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE
)
cotire(${LIB})
add_subdirectory(mock)

View File

@ -12,4 +12,4 @@ target_include_directories(${LIB}
)
# add tests
add_subdirectory(test)
add_subdirectory(mock)