add auth identity
This commit is contained in:
parent
0d351b4daa
commit
07d568c4bf
@ -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));
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace eedb {
|
||||
|
||||
@ -48,11 +49,39 @@ class AuthIdentities {
|
||||
* @param identity
|
||||
* @return non owning pointer to newly added identity
|
||||
*/
|
||||
virtual AuthIdentity * addIdentity(std::unique_ptr<AuthIdentity>identity);
|
||||
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
|
||||
|
||||
@ -3,6 +3,7 @@ set(SOURCE
|
||||
data/PgUser.cpp
|
||||
data/PgUsers.cpp
|
||||
data/PgAuthToken.cpp
|
||||
data/PgAuthIdentity.cpp
|
||||
|
||||
connection.cpp
|
||||
config.cpp
|
||||
|
||||
107
src/eedb/db/data/PgAuthIdentity.cpp
Normal file
107
src/eedb/db/data/PgAuthIdentity.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include <eedb/db/data/PgAuthIdentity.hpp>
|
||||
|
||||
#include <eedb/data/User.hpp>
|
||||
#include <eedb/db/connection.hpp>
|
||||
#include <eedb/db/model/auth_identity.h>
|
||||
|
||||
#include <sqlpp11/postgresql/exception.h>
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
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
|
||||
44
src/eedb/db/data/PgAuthIdentity.hpp
Normal file
44
src/eedb/db/data/PgAuthIdentity.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <eedb/data/AuthIdentity.hpp>
|
||||
#include <utils/spimpl.hpp>
|
||||
|
||||
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
|
||||
@ -47,8 +47,5 @@ class PgAuthTokens final : public AuthTokens {
|
||||
private:
|
||||
struct PgAuthTokensPriv;
|
||||
spimpl::unique_impl_ptr< PgAuthTokensPriv > _priv;
|
||||
|
||||
// AuthTokens interface
|
||||
public:
|
||||
};
|
||||
} // namespace eedb
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
#include <eedb/db/data/PgUser.hpp>
|
||||
|
||||
#include <eedb/db/data/PgAuthToken.hpp>
|
||||
//#include <eedb/db/data/Pg
|
||||
|
||||
#include <eedb/db/connection.hpp>
|
||||
#include <eedb/db/data/PgAuthIdentity.hpp>
|
||||
#include <eedb/db/data/PgAuthToken.hpp>
|
||||
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
@ -12,12 +11,6 @@
|
||||
#include <eedb/db/model/auth_token.h>
|
||||
#include <eedb/db/model/user_audit.h>
|
||||
|
||||
#include <Wt/WString.h>
|
||||
|
||||
#include <boost/spirit/home/support/char_class.hpp>
|
||||
|
||||
#include <eedb/data/AuthIdentity.hpp>
|
||||
|
||||
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
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include <eedb/data/User.hpp>
|
||||
|
||||
|
||||
#include <eedb/data/AuthInfo.hpp>
|
||||
|
||||
#include <utils/spimpl.hpp>
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
101
tests/unit/db/test_eedb_data_PgAuthIdentities.cpp
Normal file
101
tests/unit/db/test_eedb_data_PgAuthIdentities.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <eedb/db/data/PgAuthIdentity.hpp>
|
||||
|
||||
#include <eedb/data/AuthIdentity.hpp>
|
||||
#include <eedb/data/Users.hpp>
|
||||
|
||||
#include <eedb/db/model/auth_identity.h>
|
||||
#include <eedb/db/model/auth_info.h>
|
||||
#include <eedb/db/model/auth_token.h>
|
||||
#include <eedb/db/model/user_action.h>
|
||||
#include <eedb/db/model/user_audit.h>
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
#include <utils/DbTestBase.hpp>
|
||||
|
||||
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"));
|
||||
}
|
||||
40
tests/unit/db/test_eedb_data_PgAuthIdentity.cpp
Normal file
40
tests/unit/db/test_eedb_data_PgAuthIdentity.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <eedb/db/data/PgAuthIdentity.hpp>
|
||||
|
||||
#include <utils/DbTestBase.hpp>
|
||||
|
||||
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");
|
||||
}
|
||||
@ -12,6 +12,8 @@
|
||||
|
||||
#include <utils/DbTestBase.hpp>
|
||||
|
||||
#include <sqlpp11/postgresql/insert.h>
|
||||
|
||||
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) {
|
||||
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user