diff --git a/src/eedb/auth/PgUserAuth.cpp b/src/eedb/auth/PgUserAuth.cpp index ea33e35..13cbfb7 100644 --- a/src/eedb/auth/PgUserAuth.cpp +++ b/src/eedb/auth/PgUserAuth.cpp @@ -63,6 +63,7 @@ struct PgUserAuth::UserAuthPriv { std::optional< std::string > _identity; std::optional< std::string > provider; std::optional< int > _emailTokenRole; + bool _registration; const Wt::WEnvironment & _env; const Wt::Auth::AuthService * _authService; @@ -150,9 +151,12 @@ Wt::WString PgUserAuth::identity(const Wt::Auth::User & user, const std::string if(user.id() == registration_id) { return Wt::WString{_priv->_identity.value_or("")}; } else { - auto opt_identity = _priv->user(user)->authIdentities().byProvider(provider); - if(opt_identity) - return Wt::WString::fromUTF8(std::string{opt_identity.value()->identity()}); + auto u = _priv->user(user); + auto opt_identity = u->authIdentities().byProvider(provider); + if(opt_identity){ + auto id = opt_identity->identity(); + return Wt::WString::fromUTF8(id.data()); + } } return Wt::WString::Empty; @@ -165,6 +169,7 @@ void PgUserAuth::removeIdentity(const Wt::Auth::User & user, const std::string & Wt::Auth::User PgUserAuth::registerNew() { spdlog::get("default")->debug("registering new user"); + _priv->_registration = true; return Wt::Auth::User(registration_id, *this); } @@ -269,7 +274,8 @@ Token PgUserAuth::emailToken(const Wt::Auth::User & user) const { if(user.id() == registration_id) { assert(false); } else { - auto tok = _priv->user(user)->authTokens().find(AuthTokenRole::EmailToken); + auto u = _priv->user(user); + auto tok = u->authTokens().find(AuthTokenRole::EmailToken); if(!tok) return {}; @@ -278,6 +284,7 @@ Token PgUserAuth::emailToken(const Wt::Auth::User & user) const { } EmailTokenRole PgUserAuth::emailTokenRole(const Wt::Auth::User & user) const { + spdlog::get("default")->trace("user{} get email token role", user.id()); auto & tokens = _priv->_users->findWith(std::atoi(user.id().c_str()))->authTokens(); if(tokens.find(AuthTokenRole::EmailToken)) { return EmailTokenRole::VerifyEmail; @@ -288,13 +295,13 @@ EmailTokenRole PgUserAuth::emailTokenRole(const Wt::Auth::User & user) const { } void PgUserAuth::addAuthToken(const Wt::Auth::User & user, const Token & token) { - auto & tokens = _priv->_users->findWith(std::atoi(user.id().c_str()))->authTokens(); - tokens.addToken(token.hash(), AuthTokenRole::Auth); + spdlog::get("default")->trace("user{} adding auth token", user.id()); + _priv->user(user)->authTokens().addToken(token.hash(), AuthTokenRole::Auth); } void PgUserAuth::removeAuthToken(const Wt::Auth::User & user, const std::string & hash) { - auto & tokens = _priv->_users->findWith(std::atoi(user.id().c_str()))->authTokens(); - tokens.removeToken(hash); + spdlog::get("default")->trace("user{} removing auth token", user.id()); + _priv->user(user)->authTokens().removeToken(hash); } Wt::Auth::User PgUserAuth::findWithAuthToken(const std::string & hash) const { @@ -305,8 +312,8 @@ Wt::Auth::User PgUserAuth::findWithAuthToken(const std::string & hash) const { } int PgUserAuth::updateAuthToken(const Wt::Auth::User & user, const std::string & oldhash, const std::string & newhash) { - // method called only after successful login -// return _userAuth.updateAuthToken({user.id()}, oldhash, newhash); + spdlog::get("default")->trace("user{} updating auth token", user.id()); + _priv->user(user)->authTokens().find(oldhash)->update(newhash); } void PgUserAuth::setFailedLoginAttempts(const Wt::Auth::User & user, int count) { @@ -332,23 +339,25 @@ void PgUserAuth::logout(const Wt::Auth::User & user) { } AbstractUserDatabase::Transaction * PgUserAuth::startTransaction() { - auto commit_create_user = [priv=_priv.get()](){ - assert(priv->_email.has_value() || priv->_unverifiedEmail.has_value()); - assert(priv->_emailToken.has_value()); - assert(priv->_identity.has_value()); - assert(priv->_password.has_value()); + auto commit_create_user = [priv = _priv.get()]() { + if(priv->_registration) { + assert(priv->_email.has_value() || priv->_unverifiedEmail.has_value()); + assert(priv->_emailToken.has_value()); + assert(priv->_identity.has_value()); + assert(priv->_password.has_value()); - assert(priv->_emailTokenExpire.has_value()); -// assert(priv->_emailTokenRole.has_value()); + assert(priv->_emailTokenExpire.has_value()); + // assert(priv->_emailTokenRole.has_value()); - auto identity = std::make_unique< eedb::AuthIdentityConst >(priv->_identity.value(), priv->provider.value()); + auto identity = std::make_unique< eedb::AuthIdentityConst >(priv->_identity.value(), priv->provider.value()); - auto password = eedb::Password{priv->_password->function(), priv->_password->salt(), priv->_password->value()}; - auto email = eedb::Email{priv->_email.value_or(priv->_unverifiedEmail.value())}; + auto password = eedb::Password{priv->_password->function(), priv->_password->salt(), priv->_password->value()}; + auto email = eedb::Email{priv->_email.value_or(priv->_unverifiedEmail.value())}; - auto info = std::make_unique< AuthInfoConst >(std::move(password), std::move(email)); + auto info = std::make_unique< AuthInfoConst >(std::move(password), std::move(email)); - priv->_users->addUser(std::move(info), std::move(identity)); + priv->_users->addUser(std::move(info), std::move(identity)); + } }; return new TransactionGuard(_priv->_in_transaction, std::move(commit_create_user)); } diff --git a/src/eedb/data/AuthIdentity.hpp b/src/eedb/data/AuthIdentity.hpp index 61494dd..a6322d5 100644 --- a/src/eedb/data/AuthIdentity.hpp +++ b/src/eedb/data/AuthIdentity.hpp @@ -1,9 +1,10 @@ #pragma once -#include -#include - +#include +#include #include +#include +#include namespace eedb { @@ -48,11 +49,39 @@ class AuthIdentities { * @param identity * @return non owning pointer to newly added identity */ - virtual AuthIdentity * addIdentity(std::unique_ptridentity); + virtual AuthIdentity * addIdentity(std::unique_ptr< AuthIdentity > identity) = 0; - virtual std::optional< AuthIdentity * > byProvider(std::string_view provider) const = 0; + /// TODO add Nulllable<> or CanBeNull<> + virtual AuthIdentity * byProvider(std::string_view provider) const = 0; - virtual void removeProvider(std::string_view provider) const = 0; + virtual void removeProvider(std::string_view provider) = 0; }; +//class AuthIdentitiesConst final : public AuthIdentities { +// public: +// AuthIdentitiesConst(std::initializer_list< AuthIdentityConst > identities) { +// for(auto & identity : identities) { +// _identities.emplace(std::make_pair(identity.identity(), std::move(identity))); +// } +// } + +// AuthIdentity * addIdentity(std::unique_ptr< AuthIdentity >) override { +// assert(false); // adding to const structure +// } + +// std::optional< std::reference_wrapper< AuthIdentity > > byProvider(std::string_view provider) const override { +// if(auto it = _identities.find(std::string{provider}); it != _identities.end()) { +// return {const_cast< AuthIdentity & >(it->second)}; +// } +// return {}; +// } + +// void removeProvider(std::string_view) override { +// assert(false); // remove from const structure +// } + +// private: +// std::map< std::string, AuthIdentityConst > _identities; +//}; + } // namespace eedb diff --git a/src/eedb/db/CMakeLists.txt b/src/eedb/db/CMakeLists.txt index 3847e7f..5a8f398 100644 --- a/src/eedb/db/CMakeLists.txt +++ b/src/eedb/db/CMakeLists.txt @@ -3,6 +3,7 @@ set(SOURCE data/PgUser.cpp data/PgUsers.cpp data/PgAuthToken.cpp + data/PgAuthIdentity.cpp connection.cpp config.cpp diff --git a/src/eedb/db/data/PgAuthIdentity.cpp b/src/eedb/db/data/PgAuthIdentity.cpp new file mode 100644 index 0000000..4188bdd --- /dev/null +++ b/src/eedb/db/data/PgAuthIdentity.cpp @@ -0,0 +1,107 @@ +#include + +#include +#include +#include + +#include +#include + +constexpr eedb::auth_identity t_auth_identity; + +namespace eedb { + +struct PgAuthIdentity::PgAuthIdentityPriv { + PgAuthIdentityPriv(db::PgConnection & d, std::string id, std::string prov) + : db{d}, identity{std::move(id)}, provider{std::move(prov)} {} + db::PgConnection & db; + std::string identity; + std::string provider; +}; + +PgAuthIdentity::PgAuthIdentity(db::PgConnection & db, std::string identity, std::string provider) + : _priv{spimpl::make_unique_impl< PgAuthIdentityPriv >(db, identity, provider)} {} + +AuthIdentity::string_view PgAuthIdentity::identity() const { + return _priv->identity; +} + +AuthIdentity::string_view PgAuthIdentity::provider() const { + return _priv->provider; +} + +struct PgAuthIdentities::PgAuthIdentitysPriv { + PgAuthIdentitysPriv(db::PgConnection & d, const User * o) : db{d}, owner{o} {} + + db::PgConnection & db; + const User * owner; + + std::map< std::string, std::unique_ptr< PgAuthIdentity > > _identities; + + auto userUidEq() { + return t_auth_identity.auth_info_id == owner->uid(); + } + + AuthIdentity * byProvider(std::string_view provider) { + AuthIdentity * ptr{nullptr}; + + if(auto it = _identities.find(std::string{provider}); it != _identities.end()) { + ptr = it->second.get(); + } + + return ptr; + } + + void update() { + for(auto & identity : db(select(t_auth_identity.identity, t_auth_identity.provider) // + .from(t_auth_identity) // + .where(userUidEq()))) { + if(auto it = _identities.find(identity.provider); it == _identities.end()) { + if(!byProvider(identity.provider.value())) { + _identities.emplace( + std::make_pair(identity.provider, std::make_unique< PgAuthIdentity >(db, identity.identity, identity.provider))); + } + } + } + } +}; + +PgAuthIdentities::PgAuthIdentities(db::PgConnection & db, const User * owner) + : _priv{spimpl::make_unique_impl< PgAuthIdentitysPriv >(db, owner)} {} + +AuthIdentity * PgAuthIdentities::addIdentity(std::unique_ptr< AuthIdentity > identity) { + try { + _priv->db(insert_into(t_auth_identity) // + .set( // + t_auth_identity.auth_info_id = _priv->owner->uid(), + t_auth_identity.identity = std::string{identity->identity()}, + t_auth_identity.provider = std::string{identity->provider()})); + + auto cacheEntry = _priv->_identities.emplace(std::make_pair(std::string{identity->provider()}, + std::make_unique< PgAuthIdentity >(_priv->db, std::string{identity->identity()}, std::string{identity->provider()}))); + + return cacheEntry.first->second.get(); + + } catch(const sqlpp::postgresql::unique_violation &) { + return nullptr; /// TODO rethrow exception? + } +} + +AuthIdentity * PgAuthIdentities::byProvider(std::string_view provider) const { + AuthIdentity * ptr = _priv->byProvider(provider); + if(!ptr) { + _priv->update(); + ptr = _priv->byProvider(provider); + } + return ptr; +} + +void PgAuthIdentities::removeProvider(std::string_view provider) { + /// TODO removeProviderSignal for rest of PgAuthUdentities objects? + _priv->db(remove_from(t_auth_identity) // + .where(t_auth_identity.auth_info_id == _priv->owner->uid() // + and t_auth_identity.provider == std::string{provider})); + _priv->_identities.erase(std::string{provider}); +} + +} // namespace eedb diff --git a/src/eedb/db/data/PgAuthIdentity.hpp b/src/eedb/db/data/PgAuthIdentity.hpp new file mode 100644 index 0000000..c0dd183 --- /dev/null +++ b/src/eedb/db/data/PgAuthIdentity.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +namespace eedb { +class User; +} + +namespace eedb::db { +class PgConnection; +} + +namespace eedb { +class PgAuthIdentity final : public AuthIdentity { + public: + PgAuthIdentity(db::PgConnection & db, std::string identity, std::string provider); + // PgAuthIdentity(db::PgConnection & db, nlohmann::json data); + + string_view identity() const override; + + string_view provider() const override; + + private: + struct PgAuthIdentityPriv; + spimpl::unique_impl_ptr< PgAuthIdentityPriv > _priv; +}; + +class PgAuthIdentities final : public AuthIdentities { + public: + PgAuthIdentities(db::PgConnection & db, const User * owner); + // PgAuthIdentities(db::PgConnection & db, nlohmann::json data); + + AuthIdentity * addIdentity(std::unique_ptr< AuthIdentity > identity) override; + + AuthIdentity * byProvider(std::string_view provider) const override; + + void removeProvider(std::string_view provider) override; + + private: + struct PgAuthIdentitysPriv; + spimpl::unique_impl_ptr< PgAuthIdentitysPriv > _priv; +}; +} // namespace eedb diff --git a/src/eedb/db/data/PgAuthToken.hpp b/src/eedb/db/data/PgAuthToken.hpp index 30df650..b76fcdf 100644 --- a/src/eedb/db/data/PgAuthToken.hpp +++ b/src/eedb/db/data/PgAuthToken.hpp @@ -47,8 +47,5 @@ class PgAuthTokens final : public AuthTokens { private: struct PgAuthTokensPriv; spimpl::unique_impl_ptr< PgAuthTokensPriv > _priv; - - // AuthTokens interface - public: }; } // namespace eedb diff --git a/src/eedb/db/data/PgUser.cpp b/src/eedb/db/data/PgUser.cpp index 97226b6..9047495 100644 --- a/src/eedb/db/data/PgUser.cpp +++ b/src/eedb/db/data/PgUser.cpp @@ -1,9 +1,8 @@ #include -#include -//#include +#include +#include #include @@ -12,12 +11,6 @@ #include #include -#include - -#include - -#include - namespace { SQLPP_ALIAS_PROVIDER(fk_auth_info_id); SQLPP_ALIAS_PROVIDER(user_status); @@ -25,6 +18,7 @@ SQLPP_ALIAS_PROVIDER(user_status); constexpr eedb::auth_identity t_identity; constexpr eedb::auth_info t_info; constexpr eedb::auth_token t_auth_token; +constexpr eedb::auth_identity t_auth_identity; auto auth_info_identity = t_info.join(t_identity).on(t_info.id == t_identity.auth_info_id); auto auth_token_info = t_info.join(t_auth_token).on(t_auth_token.auth_info_id == t_info.id); @@ -39,12 +33,33 @@ struct PgUser::PgUserPriv { _authTokens = std::make_unique< PgAuthTokens >(_db, self); } + void initAuthInfo() { + auto info = _db(select(sqlpp::all_of(t_info)) // + .from(t_info) // + .where(t_info.id == self->uid())); + + assert(!info.empty()); + + auto & row = info.front(); + + Password pass{row.password_method, row.password_salt, row.password_hash}; + Email email{row.email}; + + authInfo = std::make_unique< AuthInfoConst >(std::move(pass), std::move(email)); + } + + void initAuthIdentities() { + _authIdentities = std::make_unique< PgAuthIdentities >(_db, self); + } + db::PgConnection & _db; int id; - PgUser *self; + PgUser * self; UserConfig config; std::unique_ptr< PgAuthTokens > _authTokens; + std::unique_ptr< AuthInfoConst > authInfo; + std::unique_ptr< PgAuthIdentities > _authIdentities; }; PgUser::PgUser(db::PgConnection & db, int uid) : _priv{spimpl::make_unique_impl< PgUserPriv >(db, uid, this)} {} @@ -58,8 +73,9 @@ const UserConfig & PgUser::config() const { } void PgUser::logout() { - // + assert(false); } + AuthTokens & PgUser::authTokens() const { if(!_priv->_authTokens) _priv->initAuthTokens(); @@ -67,11 +83,15 @@ AuthTokens & PgUser::authTokens() const { } AuthIdentities & PgUser::authIdentities() const { - assert(false); + if(!_priv->_authIdentities) + _priv->initAuthIdentities(); + return *(_priv->_authIdentities.get()); } AuthInfo & PgUser::authInfo() const { - assert(false); + if(!_priv->authInfo) + _priv->initAuthInfo(); + return *(_priv->authInfo.get()); } } // namespace eedb diff --git a/src/eedb/db/data/PgUser.hpp b/src/eedb/db/data/PgUser.hpp index 61119d2..a804d9d 100644 --- a/src/eedb/db/data/PgUser.hpp +++ b/src/eedb/db/data/PgUser.hpp @@ -2,7 +2,6 @@ #include - #include #include @@ -25,9 +24,9 @@ class PgUser : public User { AuthTokens & authTokens() const override; - AuthIdentities &authIdentities() const override; + AuthIdentities & authIdentities() const override; - AuthInfo &authInfo() const override; + AuthInfo & authInfo() const override; private: struct PgUserPriv; diff --git a/src/eedb/db/data/PgUsers.cpp b/src/eedb/db/data/PgUsers.cpp index 77c175b..5e04b43 100644 --- a/src/eedb/db/data/PgUsers.cpp +++ b/src/eedb/db/data/PgUsers.cpp @@ -15,6 +15,8 @@ constexpr eedb::auth_identity t_auth_identity; constexpr eedb::auth_info t_auth_info; constexpr eedb::auth_token t_auth_token; +SQLPP_ALIAS_PROVIDER(sub); + namespace eedb { template < typename T > @@ -29,11 +31,25 @@ struct PgUsers::PgUsersPriv { PgUsers::PgUsers(eedb::db::PgConnection & db) : _priv{spimpl::make_unique_impl< PgUsersPriv >(db)} {} unique_ptr< User > PgUsers::findWith(int64_t uid) const { - auto & db = *(_priv->_db.native()); + auto & db = *(_priv->_db.native()); auto result = db(select(t_auth_info.id) // .from(t_auth_info) // .where(t_auth_info.id == uid)); + +// const auto inner_select = select(t_auth_identity.id, t_auth_identity) // +// .from(t_auth_identity) // +// .where(t_auth_identity.auth_info_id == 6); + +// auto userdata = db(sqlpp::custom_query()); + +// select(t_auth_info.id, sub) // +// .from(auth_info +// .inner_join( // +// // +// ) +// .on(t_auth_identity.auth_info_id == t_auth_info.id))); + if(result.empty()) { return {}; } @@ -45,7 +61,7 @@ unique_ptr< User > PgUsers::findWith(const AuthIdentity & identity) const { const auto provider_eq = t_auth_identity.provider == std::string{identity.provider()}; auto & db = *(_priv->_db.native()); - auto result = db(select(t_auth_info.id) // + auto result = db(select(t_auth_info.id) // .from(t_auth_info.inner_join(t_auth_identity).on(t_auth_info.id == t_auth_identity.auth_info_id)) // .where(provider_eq and identity_eq)); @@ -56,10 +72,10 @@ unique_ptr< User > PgUsers::findWith(const AuthIdentity & identity) const { } unique_ptr< User > PgUsers::findWith(const Email & email) const { - auto & db = _priv->_db; + auto & db = _priv->_db; const auto & result = db(select(t_auth_info.id) // - .from(t_auth_info) // - .where(t_auth_info.email == std::string{email.address()})); + .from(t_auth_info) // + .where(t_auth_info.email == std::string{email.address()})); if(result.empty()) { return {}; @@ -91,7 +107,7 @@ unique_ptr< User > PgUsers::addUser(unique_ptr< AuthInfo > authInfo, unique_ptr< t_auth_info.password_method = pass.function(), // t_auth_info.password_salt = pass.salt(), // t_auth_info.email = std::string{email.address()}, - t_auth_info.status = 0) ///TODO status->UserWaitingForVerification + t_auth_info.status = 0) /// TODO status->UserWaitingForVerification .returning(t_auth_info.id)) .front() .id; diff --git a/tests/unit/db/test_eedb_data_PgAuthIdentities.cpp b/tests/unit/db/test_eedb_data_PgAuthIdentities.cpp new file mode 100644 index 0000000..733924f --- /dev/null +++ b/tests/unit/db/test_eedb_data_PgAuthIdentities.cpp @@ -0,0 +1,101 @@ +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +constexpr eedb::user_audit t_user_audit; +constexpr eedb::user_action t_user_action; +constexpr eedb::auth_identity t_auth_identity; +constexpr eedb::auth_info t_auth_info; +constexpr eedb::auth_token t_auth_token; + +namespace { +class UserMock : public eedb::User { + public: + MOCK_CONST_METHOD0(uid, int()); + const eedb::UserConfig & config() const override {} + eedb::AuthTokens & authTokens() const override {} + void logout() override {} + eedb::AuthIdentities & authIdentities() const {} + int64_t _uid; + + // User interface + public: + eedb::AuthInfo & authInfo() const override {} +}; +} // namespace + +class PgAuthIdentitiesTest : public DbTestBase< PgAuthIdentitiesTest > { + public: + PgAuthIdentitiesTest() { + using namespace testing; + db().native()->start_transaction(); + + authInfoId = db()(sqlpp::postgresql::insert_into(t_auth_info) + .set( // + t_auth_info.password_hash = "$2y$07$RyytUhDhLDbAPjf0b0r2Y.dsg.FlQ7L.xzWHMmoelI81u0MfBrW7q", + t_auth_info.password_method = "bcrypt", + t_auth_info.password_salt = "OM/Z1c4WBFXvwkxh", + t_auth_info.email = "none@eedb.pl", // + t_auth_info.status = 0) + .returning(t_auth_info.id)) + .front() + .id; + + EXPECT_CALL(user, uid()).WillRepeatedly(testing::Return(authInfoId)); + sut = std::make_unique< eedb::PgAuthIdentities >(db(), &user); + } + + void createIdentity(const eedb::AuthIdentityConst id) { + db()(insert_into(t_auth_identity) // + .set(t_auth_identity.auth_info_id = authInfoId, + t_auth_identity.provider = std::string{id.provider()}, + t_auth_identity.identity = std::string{id.identity()})); + } + + ~PgAuthIdentitiesTest() { + db().native()->rollback_transaction(false); + } + + protected: + UserMock user; + int64_t authInfoId{0}; + std::unique_ptr< eedb::PgAuthIdentities > sut; +}; + +template <> +std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgAuthIdentitiesTest >::_test_db = {}; + +using namespace sqlpp; +using namespace eedb; + +TEST_F(PgAuthIdentitiesTest, searchForFalseIdentity) { + EXPECT_FALSE(sut->byProvider("nonexisting")); +} + +TEST_F(PgAuthIdentitiesTest, findIdentity) { + createIdentity({"identity", "provider"}); + EXPECT_TRUE(sut->byProvider("provider")); +} + +TEST_F(PgAuthIdentitiesTest, addProvider) { + sut->addIdentity(std::make_unique< AuthIdentityConst >("identity2", "provider")); + EXPECT_TRUE(sut->byProvider("provider")); +} + +TEST_F(PgAuthIdentitiesTest, removeIdentity) { + createIdentity({"identity", "provider"}); + sut->removeProvider("provider"); + EXPECT_FALSE(sut->byProvider("provider")); +} diff --git a/tests/unit/db/test_eedb_data_PgAuthIdentity.cpp b/tests/unit/db/test_eedb_data_PgAuthIdentity.cpp new file mode 100644 index 0000000..12a4aa1 --- /dev/null +++ b/tests/unit/db/test_eedb_data_PgAuthIdentity.cpp @@ -0,0 +1,40 @@ +#include + +#include + +#include + +class PgAuthIdentityTest : public DbTestBase< PgAuthIdentityTest > { + public: + PgAuthIdentityTest() { + using namespace testing; + db().native()->start_transaction(); + } + + void initCached() { + sut = std::make_unique< eedb::PgAuthIdentity >(db(), "identity", "provider"); + } + + ~PgAuthIdentityTest() { + db().native()->rollback_transaction(false); + } + + protected: + std::unique_ptr< eedb::PgAuthIdentity > sut; +}; + +template <> +std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgAuthIdentityTest >::_test_db = {}; + +using namespace sqlpp; +using namespace std::chrono; + +TEST_F(PgAuthIdentityTest, hasIdentity) { + initCached(); + EXPECT_TRUE(sut->identity() == "identity"); +} + +TEST_F(PgAuthIdentityTest, hasProvider) { + initCached(); + EXPECT_TRUE(sut->provider() == "provider"); +} diff --git a/tests/unit/db/test_eedb_data_PgUser.cpp b/tests/unit/db/test_eedb_data_PgUser.cpp index 9a0b653..198093b 100644 --- a/tests/unit/db/test_eedb_data_PgUser.cpp +++ b/tests/unit/db/test_eedb_data_PgUser.cpp @@ -12,6 +12,8 @@ #include +#include + constexpr eedb::user_audit t_user_audit; constexpr eedb::user_action t_user_action; constexpr eedb::auth_identity t_auth_identity; @@ -22,6 +24,34 @@ class PgUserTest : public DbTestBase< PgUserTest > { public: PgUserTest() { db().native()->start_transaction(); + + auto info_ = std::make_unique< eedb::AuthInfoConst >( + eedb::Password{"bcrypt", "OM/Z1c4WBFXvwkxh", "$2y$07$RyytUhDhLDbAPjf0b0r2Y.dsg.FlQ7L.xzWHMmoelI81u0MfBrW7q"}, + eedb::Email{"email@eedb.pl"}); + auto identity_ = std::make_unique< eedb::AuthIdentityConst >("name", "loginname"); + + const auto & pass = info_->password(); + const auto & email = info_->email(); + + uid = // + db()(sqlpp::postgresql::insert_into(t_auth_info) + .set( // + t_auth_info.password_hash = pass.value(), // + t_auth_info.password_method = pass.function(), // + t_auth_info.password_salt = pass.salt(), // + t_auth_info.email = std::string{email.address()}, + t_auth_info.status = 0) + .returning(t_auth_info.id)) + .front() + .id; + + db()(insert_into(t_auth_identity) + .set( // + t_auth_identity.auth_info_id = uid, // + t_auth_identity.identity = std::string{identity_->identity()}, + t_auth_identity.provider = std::string{identity_->provider()})); + + sut = std::make_unique< eedb::PgUser >(db(), uid); } ~PgUserTest() { @@ -29,6 +59,7 @@ class PgUserTest : public DbTestBase< PgUserTest > { } protected: + int64_t uid; std::unique_ptr< eedb::PgUser > sut; }; @@ -37,6 +68,14 @@ std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgUserTest >::_test_db = {} using namespace sqlpp; -TEST_F(PgUserTest, initial) { +TEST_F(PgUserTest, readAllAuthInfoData) { + EXPECT_EQ(sut->uid(), uid); +} + +TEST_F(PgUserTest, getIdentities){ + EXPECT_TRUE(sut->authIdentities().byProvider("loginname")); +} + +TEST_F(PgUserTest, getTokens) { } diff --git a/tests/utils/DbTestBase.hpp b/tests/utils/DbTestBase.hpp index d709cb6..6153454 100644 --- a/tests/utils/DbTestBase.hpp +++ b/tests/utils/DbTestBase.hpp @@ -109,7 +109,10 @@ class DbTestBase : public testing::Test { public: static void SetUpTestCase() { _test_db = std::make_unique< PgTestDatabasePrepare >(); + _test_db->db().native()->start_transaction(); + _test_db->db().native()->execute("SET synchronous_commit=off;"); eedb::db::exec_file(_test_db->db(), "/home/bwieczor/src/eedb/sql/schema.sql"); + _test_db->db().native()->commit_transaction(); } static void TearDownTestCase() {