refactoring

This commit is contained in:
Bartosz Wieczorek 2018-02-08 13:16:45 +01:00
parent 481e505c08
commit 9ca4d2f257
11 changed files with 272 additions and 162 deletions

View File

@ -97,9 +97,9 @@ create table "auth_info" (
create trigger "update_auth_info_updated" before update on "auth_info" FOR EACH ROW EXECUTE PROCEDURE last_update_column();
comment on table "auth_info" is '';
comment on column "auth_info"."id" is '';
comment on column "auth_info"."group" is '';
comment on column "auth_info"."created" is '';
comment on column "auth_info"."config" is '';
comment on column "auth_info"."group" is 'default user group';
comment on column "auth_info"."created" is 'time of created';
comment on column "auth_info"."config" is 'user configuration';
create table "auth_identity" (
@ -108,7 +108,7 @@ create table "auth_identity" (
"provider" varchar(64) not null,
"identity" varchar(512) not null,
constraint "pk_auth_identity_id" primary key("id"),
constraint "fk_auth_identity_auth_info" foreign key ("auth_info_id") references "auth_info" ("id") on delete cascade deferrable initially deferred
constraint "fk_auth_identity_auth_info_id" foreign key ("auth_info_id") references "auth_info" ("id") on delete cascade deferrable initially immediate
);
comment on table "auth_identity" is '';
comment on column "auth_identity"."id" is '';
@ -124,7 +124,7 @@ create table "auth_token" (
"expires" timestamp not null,
"role" smallint not null,
constraint "pk_auth_token_id" primary key("id"),
constraint "fk_auth_token_auth_info_id" foreign key ("auth_info_id") references "auth_info" ("id") on delete cascade deferrable initially deferred
constraint "fk_auth_token_auth_info_id" foreign key ("auth_info_id") references "auth_info" ("id") on delete cascade deferrable initially immediate
);
create index "ix_auth_token_value" ON "auth_token" ("value");
comment on table "auth_token" is '';
@ -153,8 +153,8 @@ create table "user_audit" (
"data" jsonb,
"when_happened" timestamp DEFAULT(now()),
constraint "pk_user_history_id" primary key ("id"),
constraint "fk_user_history_auth_info_id" foreign key ("auth_info_id") references "auth_info"("id") on delete cascade deferrable initially deferred,
constraint "fk_user_history_user_action" foreign key ("action_id") references "user_audit_action"("id") on delete cascade deferrable initially deferred
constraint "fk_user_history_auth_info_id" foreign key ("auth_info_id") references "auth_info"("id") on delete cascade deferrable initially immediate,
constraint "fk_user_history_user_action" foreign key ("action_id") references "user_audit_action"("id") on delete cascade deferrable initially immediate
);
create index "ix_user_history_data" ON "user_audit" ((("data" ->> 'status')::text)) WHERE ("data" ->> 'status') IS not null;
comment on table "user_audit" IS 'saves user actions like login/logout';
@ -183,8 +183,8 @@ create table "stat"(
"created" timestamp DEFAULT now() not null,
"updated" timestamp,
constraint "pk_stat" primary key ("id"),
constraint "fk_stat_user" foreign key ("owner") references "auth_info" ("id") on delete cascade deferrable initially deferred,
constraint "fk_stat_primary_group" foreign key ("group") references "group" ("gid") on delete cascade deferrable initially deferred
constraint "fk_stat_user" foreign key ("owner") references "auth_info" ("id") on delete cascade deferrable initially immediate,
constraint "fk_stat_primary_group" foreign key ("group") references "group" ("gid") on delete cascade deferrable initially immediate
);
create trigger update_stat_last_update before update on stat FOR EACH ROW EXECUTE PROCEDURE last_update_column();
comment on table "stat" is '';
@ -220,26 +220,26 @@ comment on column "implemented_action"."action" is '';
comment on column "implemented_action"."status" is '';
create table "privilege" (
"role" varchar(30) not null, -- TODO change to enum
"who" int not null default 0,
"action" text not null,
"type" varchar(30) not null, -- TODO change to enum
"related_table_name" varchar(100) not null,
"related_object_uid" int not null default 0,
constraint "pk_privilege" primary key("role", "who", "action", "type", "related_table_name", "related_object_uid")
);
create index "ix_privilege_action_type" on "privilege" ( "action", "type") with ( FILLFACTOR=100 );
create index "ix_privilege_related_table" on "privilege" ( "related_table_name" ) with ( FILLFACTOR=100 );
create index "ix_privilege_action" on "privilege" ( "action" ) with ( FILLFACTOR=100 );
create index "ix_privilege_type" on "privilege" ( "type" ) with ( FILLFACTOR=100 );
comment on table "privilege" is '';
comment on column "privilege"."role" is 'specifies whether the privilege is granted to a user, a group, or in the case of an “object” privilege, the objects owner or owner_group. A further special case, in my system, is “self.”';
comment on column "privilege"."who" is 'is needed if role is user or group, and holds the user or group ID to which the privilege is granted.';
comment on column "privilege"."action" is 'is the action the privilege grants. This is always required.';
comment on column "privilege"."type" is 'specifies whether the privilege is “object”, “table”, or “global.”';
comment on column "privilege"."related_table_name" is 'holds the name of the table to which the privilege applies. This is always required, though in the case of a “self” privilege its redundant because a “self” privilege always applies to the t_user table.';
comment on column "privilege"."related_object_uid" is 'stores the ID of the object to which the privilege applies, if its an object privilege. This has no meaning for table and global privileges, of course. The one applies to a table, not an object, and the second applies to all rows in a table, so an ID is immaterial. This is also not used for self privileges, because by definition a self privilege has to apply to the user requesting permission to do something.';
--create table "privilege" (
-- "role" varchar(30) not null, -- TODO change to enum
-- "who" int not null default 0,
-- "action" text not null,
-- "type" varchar(30) not null, -- TODO change to enum
-- "related_table_name" varchar(100) not null,
-- "related_object_uid" int not null default 0,
-- constraint "pk_privilege" primary key("role", "who", "action", "type", "related_table_name", "related_object_uid")
--);
--create index "ix_privilege_action_type" on "privilege" ( "action", "type") with ( FILLFACTOR=100 );
--create index "ix_privilege_related_table" on "privilege" ( "related_table_name" ) with ( FILLFACTOR=100 );
--create index "ix_privilege_action" on "privilege" ( "action" ) with ( FILLFACTOR=100 );
--create index "ix_privilege_type" on "privilege" ( "type" ) with ( FILLFACTOR=100 );
--comment on table "privilege" is '';
--comment on column "privilege"."role" is 'specifies whether the privilege is granted to a user, a group, or in the case of an “object” privilege, the objects owner or owner_group. A further special case, in my system, is “self.”';
--comment on column "privilege"."who" is 'is needed if role is user or group, and holds the user or group ID to which the privilege is granted.';
--comment on column "privilege"."action" is 'is the action the privilege grants. This is always required.';
--comment on column "privilege"."type" is 'specifies whether the privilege is “object”, “table”, or “global.”';
--comment on column "privilege"."related_table_name" is 'holds the name of the table to which the privilege applies. This is always required, though in the case of a “self” privilege its redundant because a “self” privilege always applies to the t_user table.';
--comment on column "privilege"."related_object_uid" is 'stores the ID of the object to which the privilege applies, if its an object privilege. This has no meaning for table and global privileges, of course. The one applies to a table, not an object, and the second applies to all rows in a table, so an ID is immaterial. This is also not used for self privileges, because by definition a self privilege has to apply to the user requesting permission to do something.';
create or replace function update_category_parent_path() returns trigger as $$
@ -264,7 +264,7 @@ create table "category"(
"description" text check(length(description) < 100000 ),
"parent_path" ltree,
constraint "pk_category_uid" primary key ("id"),
constraint "fk_category_parent_id" foreign key ("parent_id") references "category"("id") on delete cascade deferrable initially deferred,
constraint "fk_category_parent_id" foreign key ("parent_id") references "category"("id") on delete cascade deferrable initially immediate,
constraint "fk_category_stat_owner" foreign key ("owner") references "auth_info"("id") deferrable initially immediate
) INHERITS (stat);
create index "ix_category_parent_path" on "category" using GIST ("parent_path");
@ -277,18 +277,18 @@ comment on column "category"."description" is '';
comment on column "category"."parent_path" is '';
create table "measurands"(
"id" serial not null unique primary key,
"name" text not null unique,
"description" text,
"dimension_symbol" text
);
--create table "measurands"(
-- "id" serial not null unique primary key,
-- "name" text not null unique,
-- "description" text,
-- "dimension_symbol" text
--);
create table "metric_systems"(
"id" serial not null primary key,
"name" VARCHAR(32) not null unique,
"description" text
);
--create table "metric_systems"(
-- "id" serial not null primary key,
-- "name" VARCHAR(32) not null unique,
-- "description" text
--);
--comment on table measurands IS 'Information about measured quantity length, time etc.';
@ -314,8 +314,8 @@ create table "metric_systems"(
-- equation TEXT not null,
-- constraint unit_conversions_unique primary key (from_unit, to_unit)
--);
--comment on table units_conversions IS 'This table contains a mathematical equation for converting one unitl to other, more info available at http://www.partow.net/programming/exprtk/index.html';
--comment on column units_conversions.equation IS 'this equation should be a proper exprtk equation';
--comment on table units_conversions IS 'This table contains a mathematical equation for converting one unitl to other';
--comment on column units_conversions.equation IS 'this equation should be a proper script (mayby chaiscript?)';
--create table pointed_values(
-- id serial primary key,
@ -341,45 +341,45 @@ create table "metric_systems"(
--create table "item_namespaces"(
--);
create table "item"(
"category_id" int not null,
"symbol" text not null,
"original_symbol" text,
"producer" text,
"visibility" VARCHAR(64) DEFAULT 'global' not null,
"attributes" jsonb not null DEFAULT('{}'),
"description" TEXT,
constraint "pk_items" primary key ("id"),
constraint "fk_item_category" foreign key ("category_id") references "category"("id") on delete cascade deferrable initially deferred,
constraint "fk_item_auth_info" foreign key ("owner") REFERENCES "auth_info"("id") deferrable initially IMMEDIATE
) INHERITS (stat);
create index "ix_item_attributes" on "item" USING GIN ("attributes");
create unique index "ux_item" on "item"("name", "symbol");
create trigger update_item_last_update before update on item FOR EACH ROW EXECUTE PROCEDURE last_update_column();
comment on table "item" is '';
comment on column "item"."category_id" is '';
comment on column "item"."symbol" is '';
comment on column "item"."original_symbol" is '';
comment on column "item"."producer" is '';
comment on column "item"."visibility" is '';
comment on column "item"."attributes" is '';
comment on column "item"."description" is '';
--create table "item"(
-- "category_id" int not null,
-- "symbol" text not null,
-- "original_symbol" text,
-- "producer" text,
-- "visibility" VARCHAR(64) DEFAULT 'global' not null,
-- "attributes" jsonb not null DEFAULT('{}'),
-- "description" TEXT,
-- constraint "pk_items" primary key ("id"),
-- constraint "fk_item_category" foreign key ("category_id") references "category"("id") on delete cascade deferrable initially immediate,
-- constraint "fk_item_auth_info" foreign key ("owner") REFERENCES "auth_info"("id") deferrable initially immediate
--) INHERITS (stat);
--create index "ix_item_attributes" on "item" USING GIN ("attributes");
--create unique index "ux_item" on "item"("name", "symbol");
--create trigger update_item_last_update before update on item FOR EACH ROW EXECUTE PROCEDURE last_update_column();
--comment on table "item" is '';
--comment on column "item"."category_id" is '';
--comment on column "item"."symbol" is '';
--comment on column "item"."original_symbol" is '';
--comment on column "item"."producer" is '';
--comment on column "item"."visibility" is '';
--comment on column "item"."attributes" is '';
--comment on column "item"."description" is '';
create table "inventory"(
"description" TEXT check(length(description)< 100000),
constraint "pk_inventory" primary key ("id"),
constraint "fk_inventory_owner" foreign key ("owner") REFERENCES "auth_info" ("id") deferrable initially IMMEDIATE,
constraint "chk_inventory_name_length" check (length(name) < 100)
) INHERITS (stat);
create trigger update_inventory_last_update before update on inventory FOR EACH ROW EXECUTE PROCEDURE last_update_column();
--create table "inventory"(
-- "description" TEXT check(length(description)< 100000),
-- constraint "pk_inventory" primary key ("id"),
-- constraint "fk_inventory_owner" foreign key ("owner") REFERENCES "auth_info" ("id") deferrable initially immediate,
-- constraint "chk_inventory_name_length" check (length(name) < 100)
--) INHERITS (stat);
--create trigger update_inventory_last_update before update on inventory FOR EACH ROW EXECUTE PROCEDURE last_update_column();
create table "user_inventory"(
"auth_info_id" INTEGER not null REFERENCES "auth_info" on DELETE CASCADE,
"inventory_id" INTEGER not null REFERENCES "inventory" on DELETE CASCADE,
constraint user_inventory_pk primary key ("inventory_id", "auth_info_id")
);
--create table "user_inventory"(
-- "auth_info_id" INTEGER not null REFERENCES "auth_info" on DELETE CASCADE,
-- "inventory_id" INTEGER not null REFERENCES "inventory" on DELETE CASCADE,
-- constraint user_inventory_pk primary key ("inventory_id", "auth_info_id")
--);
--create table in_stock(
@ -419,11 +419,3 @@ create table "user_inventory"(
-- create trigger update_items_last_update before update on items FOR EACH ROW EXECUTE PROCEDURE last_update_column();
-- create trigger update_shelfs_last_update before update on shelfs FOR EACH ROW EXECUTE PROCEDURE last_update_column();
-- create trigger update_inventory_operations_lats_update before update on inventory_operations FOR EACH ROW EXECUTE PROCEDURE last_update_column();
DO
$$
DECLARE lastid int;
BEGIN
END $$;

View File

@ -4,7 +4,8 @@
#include <eedb/data/AuthIdentities.hpp>
#include <eedb/data/AuthIdentityConst.hpp>
#include <eedb/data/AuthInfoConst.hpp>
#include <eedb/data/AuthToken.hpp>
#include <eedb/data/AuthTokenConst.hpp>
#include <eedb/data/AuthTokens.hpp>
#include <eedb/data/Email.hpp>
#include <eedb/data/Password.hpp>
#include <eedb/data/Users.hpp>
@ -306,10 +307,11 @@ void PgUserAuth::removeAuthToken(const Wt::Auth::User & user, const std::string
}
Wt::Auth::User PgUserAuth::findWithAuthToken(const std::string & hash) const {
// auto u = _userAuth.findWithAuthToken(hash);
// if(!u)
// return {};
// return {u->id(), *this};
spdlog::get("default")->debug("searching user by auth token: '{}'...", hash);
auto u = _priv->_users->findWith(eedb::AuthTokenConst(hash));
if(!u)
return {};
return {std::to_string(u->uid()), *this};
}
int PgUserAuth::updateAuthToken(const Wt::Auth::User & user, const std::string & oldhash, const std::string & newhash) {

View File

@ -2,7 +2,6 @@
#include <chrono>
#include <string>
#include <variant>
namespace eedb {
@ -27,14 +26,4 @@ class AuthToken {
virtual void update(std::string newHash) = 0;
};
class AuthTokens {
public:
virtual ~AuthTokens() = default;
virtual AuthToken * find(std::variant< std::string_view, AuthTokenRole > token) const = 0;
virtual void removeToken(std::string_view token) = 0;
virtual AuthToken * addToken(std::string token, AuthTokenRole role) = 0;
};
} // namespace eedb

View File

@ -0,0 +1,30 @@
#pragma once
#include <eedb/data/AuthToken.hpp>
namespace eedb {
class AuthTokenConst final : public AuthToken {
public:
AuthTokenConst(std::string hash) : _hash{std::move(hash)} {}
std::string_view token() const override {
return _hash;
}
us_point expireTimepoint() const override {
throw;
}
bool expired() const override {
throw;
}
void update(std::string newHash) override {
throw;
}
private:
std::string _hash;
};
} // namespace eedb

View File

@ -0,0 +1,19 @@
#pragma once
#include <eedb/data/AuthToken.hpp>
#include <variant>
namespace eedb {
class AuthTokens {
public:
virtual ~AuthTokens() = default;
virtual AuthToken * find(std::variant< std::string_view, AuthTokenRole > token) const = 0;
virtual void removeToken(std::string_view token) = 0;
virtual AuthToken * addToken(std::string token, AuthTokenRole role) = 0;
};
} // namespace eedb

View File

@ -5,7 +5,14 @@
namespace eedb {
class EmailToken {
public:
explicit EmailToken(std::string) {}
explicit EmailToken(std::string token) : _token{std::move(token)} {}
std::string_view token() const {
return _token;
}
private:
std::string _token;
};
class Email {

View File

@ -30,12 +30,12 @@ class Users {
virtual unique_ptr< User > findWith(const AuthIdentity & name) const = 0;
virtual unique_ptr< User > findWith(const Email & email) const = 0;
virtual unique_ptr< User > findWith(const EmailToken & token) const = 0;
// virtual unique_ptr< User > findWith(const AuthToken & token) const = 0;
virtual unique_ptr< User > findWith(const AuthToken & token) const = 0;
// adds new user into users
virtual unique_ptr< User > addUser(unique_ptr< AuthInfo >, unique_ptr< AuthIdentity >) = 0;
// remove user from database
virtual void removeUser(std::unique_ptr< AuthInfo > user) const = 0;
virtual void removeUser(std::unique_ptr< User > user) const = 0;
};
} // namespace eedb

View File

@ -1,6 +1,7 @@
#pragma once
#include <eedb/data/AuthToken.hpp>
#include <eedb/data/AuthTokens.hpp>
#include <utils/spimpl.hpp>

View File

@ -3,6 +3,7 @@
#include <eedb/db/data/PgUser.hpp>
#include <eedb/data/AuthIdentity.hpp>
#include <eedb/data/AuthToken.hpp>
#include <eedb/data/Email.hpp>
#include <eedb/data/Password.hpp>
@ -28,70 +29,125 @@ struct PgUsers::PgUsersPriv {
PgUsersPriv(eedb::db::PgConnection & db) : _db{db} {}
eedb::db::PgConnection & _db;
private:
// select
auto userData() const {
return t_auth_info.id;
}
// where
auto tokenNotExpired() const {
return t_auth_token.expires < std::chrono::system_clock::now();
}
auto tokenRole(AuthTokenRole role) const {
return t_auth_token.role == static_cast< int >(role);
}
template < typename TokenType >
auto tokenValueEq(TokenType && token) const {
return t_auth_token.value == std::string{token.token()};
}
auto statusIsValid() const {
return t_auth_info.status == 10;
}
auto idEq(const int64_t id) const {
return t_auth_info.id == id;
}
auto identityEq(const AuthIdentity & identity) const {
return t_auth_identity.provider == std::string{identity.identity()} and
t_auth_identity.identity == std::string{identity.identity()};
}
auto emailEq(const Email & email) const {
return t_auth_info.email == std::string{email.address()};
}
auto emailTokenEq(const EmailToken & token) const {
return tokenValueEq(token) and tokenNotExpired() and tokenRole(AuthTokenRole::EmailToken);
}
auto authTokenEq(const AuthToken & token) const {
return tokenValueEq(token) and tokenNotExpired() and tokenRole(AuthTokenRole::Auth);
}
// from
auto allAuthData() const {
return t_auth_info //
.inner_join(t_auth_identity)
.on(t_auth_info.id == t_auth_identity.auth_info_id)
.inner_join(t_auth_token)
.on(t_auth_info.id == t_auth_token.auth_info_id);
}
public:
auto by(const int64_t id) const {
return select(userData()) //
.from(allAuthData())
.where(idEq(id) and statusIsValid());
}
auto by(const AuthIdentity & identity) const {
return select(userData()) //
.from(allAuthData())
.where(identityEq(identity) and statusIsValid());
}
auto by(const Email & email) const {
return select(t_auth_info.id) //
.from(allAuthData())
.where(emailEq(email) and statusIsValid());
}
auto by(const EmailToken & token) const {
return select(userData()) //
.from(allAuthData())
.where(emailTokenEq(token) and statusIsValid());
}
auto by(const AuthToken & authToken) const {
return select(userData()) //
.from(allAuthData())
.where(authTokenEq(authToken) and statusIsValid());
}
template < typename Key >
auto find(Key && key) -> std::unique_ptr< PgUser > {
auto & db = _db;
auto result = db(by(key));
if(result.empty()) {
return {};
}
return std::make_unique< PgUser >(_db, result.front().id);
}
};
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 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 {};
}
return std::make_unique< PgUser >(_priv->_db, result.front().id);
return _priv->find(uid);
}
unique_ptr< User > PgUsers::findWith(const AuthIdentity & identity) const {
const auto identity_eq = t_auth_identity.identity == std::string{identity.identity()};
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) //
.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));
if(result.empty()) {
return {};
}
return std::make_unique< PgUser >(_priv->_db, result.front().id);
return _priv->find(identity);
}
unique_ptr< User > PgUsers::findWith(const Email & email) const {
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()}));
if(result.empty()) {
return {};
}
return std::make_unique< PgUser >(_priv->_db, result.front().id);
return _priv->find(email);
}
unique_ptr< User > PgUsers::findWith(const EmailToken & token) const {
assert(false);
return _priv->find(token);
}
// unique_ptr< User > PgUsers::findWith(const Users::AuthToken & token) const {
// return {};
//}
unique_ptr< User > PgUsers::findWith(const AuthToken & token) const {
return _priv->find(token);
}
unique_ptr< User > PgUsers::addUser(unique_ptr< AuthInfo > authInfo, unique_ptr< AuthIdentity > authIdentity) {
assert(authInfo);
@ -105,9 +161,9 @@ unique_ptr< User > PgUsers::addUser(unique_ptr< AuthInfo > authInfo, unique_ptr<
auto auth_info_id = //
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.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) /// TODO status->UserWaitingForVerification
.returning(t_auth_info.id))
@ -123,4 +179,10 @@ unique_ptr< User > PgUsers::addUser(unique_ptr< AuthInfo > authInfo, unique_ptr<
return std::make_unique< eedb::PgUser >(_priv->_db, auth_info_id);
}
void PgUsers::removeUser(std::unique_ptr< User > user) const {
auto & db = _priv->_db;
// db()
}
} // namespace eedb

View File

@ -18,10 +18,10 @@ class PgUsers : public Users {
unique_ptr< User > findWith(const AuthIdentity & name) const override;
unique_ptr< User > findWith(const Email & email) const override;
unique_ptr< User > findWith(const EmailToken & token) const override;
// unique_ptr< User > findWith(const AuthToken & token) const override;
unique_ptr< User > findWith(const AuthToken & token) const override;
unique_ptr< User > addUser(unique_ptr< AuthInfo >, unique_ptr< AuthIdentity >) override;
void removeUser(std::unique_ptr< AuthInfo > user) const override{}
void removeUser(std::unique_ptr< User > user) const override;
private:
struct PgUsersPriv;

View File

@ -128,3 +128,11 @@ TEST_F(PgUsersTest, findByEmail) {
auto u = sut->findWith(eedb::Email{"test_user_5@eedb.pl"});
EXPECT_EQ(idMap().at("test_user_5"), u->uid());
}
TEST_F(PgUsersTest, removeUser) {
createTestUsers();
auto u = sut->findWith(eedb::AuthIdentityConst{"test_user_1", "loginname"});
sut->removeUser(std::move(u));
EXPECT_FALSE(sut->findWith(eedb::AuthIdentityConst{"test_user_1", "loginname"}));
}