some fixes

This commit is contained in:
Bartosz Wieczorek 2018-03-14 12:43:19 +01:00
parent c8dcb41f1b
commit c34f7c5a07
15 changed files with 145 additions and 90 deletions

View File

@ -9,7 +9,7 @@ create extension if not exists "uuid-ossp";
create OR REPLACE function perm_to_numeric ( m_owner INT, m_group INT, m_other INT ) create OR REPLACE function perm_to_numeric ( m_owner INT, m_group INT, m_other INT )
RETURNS INT AS $$ RETURNS INT AS $$
BEGIN RETURN cast((m_owner << 6) | (m_group << 3 | m_other << 0) AS INT); END $$ BEGIN RETURN cast((m_owner << 6) | (m_group << 3 | m_other << 0) AS INT); END $$
LANGUAGE plpgsql IMMUtable COST 1; LANGUAGE plpgsql immutable COST 1;
create OR REPLACE function unix_to_numeric (unixperm VARCHAR) create OR REPLACE function unix_to_numeric (unixperm VARCHAR)
@ -19,7 +19,7 @@ BEGIN
txt := right(unixperm, 3); txt := right(unixperm, 3);
RETURN perm_to_numeric(cast(substring(txt, 1, 1) AS INT), cast(substring(txt, 2, 1) AS INT), cast(substring(txt, 3, 1) AS INT)); RETURN perm_to_numeric(cast(substring(txt, 1, 1) AS INT), cast(substring(txt, 2, 1) AS INT), cast(substring(txt, 3, 1) AS INT));
END $$ END $$
LANGUAGE plpgsql IMMUtable COST 1; LANGUAGE plpgsql immutable cost 1;
-- set session "eedb.user.id" = '1234'; -- set session "eedb.user.id" = '1234';
@ -27,17 +27,16 @@ create or replace function app_current_user_id()
returns int as $$ returns int as $$
begin begin
return current_setting('eedb.user.id', TRUE)::int; return current_setting('eedb.user.id', TRUE)::int;
end $$ -- end $$ --$$
language plpgsql stable cost 1; language plpgsql stable cost 1;
-- set session "eedb.user.name" = 'user'; create or replace function app_current_user_group()
create or replace function app_current_user_name()
returns int as $$ returns int as $$
begin begin
return current_setting('eedb.user.name', TRUE)::text; return current_setting('eedb.user.id', TRUE)::int;
end $$ -- end $$ -- $$
language plpgsql stable cost 1; language plpgsql stable;
create OR REPLACE function last_update_column() create OR REPLACE function last_update_column()
@ -68,9 +67,6 @@ comment on column "system_info"."value"
create table "group" ( create table "group" (
"gid" serial not null, "gid" serial not null,
"name" text not null, "name" text not null,
"description" text,
"created" timestamp DEFAULT now() not null,
"updated" timestamp,
constraint "pk_group_gid" primary key ("gid"), constraint "pk_group_gid" primary key ("gid"),
constraint "ux_group_name" unique ("name") constraint "ux_group_name" unique ("name")
); );
@ -224,7 +220,7 @@ comment on column "user_audit"."when_happened"
create table "stat"( create table "stat"(
"id" serial not null, "id" serial not null,
"owner" int not null default 1, "owner" int not null default app_current_user_id(),
"group" int not null default default_group_id(), "group" int not null default default_group_id(),
"unixperms" int not null default unix_to_numeric('764'), "unixperms" int not null default unix_to_numeric('764'),
"status" int not null default 0, "status" int not null default 0,
@ -255,7 +251,6 @@ comment on column "stat"."created"
comment on column "stat"."updated" comment on column "stat"."updated"
is ''; is '';
--create table "action"( --create table "action"(
-- "title" text not null check( length(title) >= 3 AND length(title) < 100 ), -- "title" text not null check( length(title) >= 3 AND length(title) < 100 ),
-- "apply_object" boolean not null, -- "apply_object" boolean not null,
@ -299,6 +294,24 @@ comment on column "stat"."updated"
--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_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.'; --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 "file"(
"size" int,
"checksum" text,
"mimetype" text,
constraint "ix_file_id" primary key ("id"),
constraint "fk_category_stat_owner" foreign key ("owner") references "auth_info"("id") deferrable initially immediate
) inherits (stat);
create unique index "ux_file_data" on "file"("size", "checksum" );
comment on table "file"
is '';
comment on column "file"."size"
is 'size in bytes og file';
comment on column "file"."checksum"
is 'MD5 checksum of file';
comment on column "file"."mimetype"
is 'mime type of hold object';
--------------------------------------------- ---------------------------------------------
--- CATEGORIES --- CATEGORIES
--------------------------------------------- ---------------------------------------------
@ -386,9 +399,6 @@ comment on column "parameter"."description"
is ''; is '';
--create table "producer"(
--) inherits ("stat");
-- TODO create fulltext search on short_desc column -- TODO create fulltext search on short_desc column
-- TODO create "producer" table to save producers there insted in items table -- TODO create "producer" table to save producers there insted in items table
create table "item"( create table "item"(

View File

@ -29,8 +29,6 @@ class PgCategory : public Category {
std::unique_ptr< Categories > children() const override; std::unique_ptr< Categories > children() const override;
// bool detached() const override;
std::unique_ptr< Category > create(std::string name, std::string description) const override; std::unique_ptr< Category > create(std::string name, std::string description) const override;
}; };

View File

@ -6,10 +6,18 @@
namespace eedb::db::details { namespace eedb::db::details {
inline auto app_current_user_id() {
return sqlpp::verbatim< sqlpp::integer >("app_current_user_id()");
}
template < typename Table > template < typename Table >
auto insert_user_stat(const Table & table) { auto insert_user_stat(const Table & table) {
return std::tuple{// return std::tuple{table.owner = app_current_user_id()};
table.owner = sqlpp::verbatim< sqlpp::integer >("app_current_user_id()")}; }
template < typename Table >
auto owner_eq(const Table & table) {
return std::tuple{table.owner == app_current_user_id()};
} }
template < typename Db > template < typename Db >

View File

@ -14,7 +14,7 @@ struct PgParametersRepository::PgParametersRepositoryPriv {
void create(std::string name, std::optional< Unit > unit, parameter::Type type) { void create(std::string name, std::optional< Unit > unit, parameter::Type type) {
using namespace sqlpp; using namespace sqlpp;
_db(postgresql::insert_into(t_parameter) // _db(postgresql::insert_into(t_parameter) //
.set(t_parameter.owner = _user->uid(), t_parameter.name = name) .set(t_parameter.name = name)
.returning(t_parameter.id)); .returning(t_parameter.id));
} }

View File

@ -42,14 +42,6 @@ struct PgCategory::PgCategoryPrivate {
return t_category.parent_path == "root"; return t_category.parent_path == "root";
} }
// set
// auto set_stat() const {
// return std::tuple{//
// t_category.owner = _owner->uid(),
// t_category.status = 0,
// t_category.unixperms = sqlpp::verbatim< sqlpp::integer >(R"(unix_to_numeric("764"))")};
// }
public: public:
Category * _self{nullptr}; Category * _self{nullptr};
@ -147,10 +139,6 @@ std::unique_ptr< Categories > PgCategory::children() const {
return std::make_unique< PgCategories >(_priv->categories()); return std::make_unique< PgCategories >(_priv->categories());
} }
// bool PgCategory::detached() const {
// return _priv->detached();
//}
std::unique_ptr< Category > PgCategory::create(std::string name, std::string description) const { std::unique_ptr< Category > PgCategory::create(std::string name, std::string description) const {
return _priv->create(std::move(name), std::move(description)); return _priv->create(std::move(name), std::move(description));
} }

View File

@ -8,8 +8,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <sqlpp11/sqlpp11.h> #include <sqlpp11/sqlpp11.h>
#include <spdlog/spdlog.h>
#include <sqlpp11/in.h>
#include <eedb/db/pg/Stats.hpp> #include <eedb/db/pg/Stats.hpp>
@ -18,11 +17,19 @@ SQLPP_ALIAS_PROVIDER(_match);
namespace eedb { namespace eedb {
struct PgItemsRepository::PgItemsRepositoryPriv { struct PgItemsRepository::PgItemsRepositoryPriv {
private: private:
auto insert_item_data(item::Identyfier & id, Values & values, std::optional< item::Foto > & f) { auto insert_producer(std::string_view producer) {
return std::tuple{t_item.name = std::string{id.symbol()}, return std::tuple{t_item.producer = std::string{producer}};
t_item.symbol = std::string{id.producerSymbol()}, }
t_item.producer = "producer",
t_item.attributes = values.serialize().dump()}; auto insert(const Values & values) {
return std::tuple{t_item.attributes = values.serialize().dump()};
}
auto insert(item::Identyfier & id) {
return std::tuple{t_item.name = std::string{id.symbol()}, t_item.symbol = std::string{id.producerSymbol()}};
}
auto insert(const item::Attributes & attributes) {
return std::tuple_cat(insert(attributes.values()), insert_producer(attributes.producer()));
} }
public: public:
@ -30,36 +37,41 @@ struct PgItemsRepository::PgItemsRepositoryPriv {
bool parametersAvalible(const Values & values) { bool parametersAvalible(const Values & values) {
std::vector< std::string > _parameters; std::vector< std::string > _parameters;
_parameters.reserve(std::distance(values.begin(), values.end())); auto total_values = std::distance(values.begin(), values.end());
_parameters.reserve(total_values);
std::transform(values.begin(), values.end(), std::back_inserter(_parameters), [](const eedb::Value & value) { std::transform(values.begin(), values.end(), std::back_inserter(_parameters), [](const eedb::Value & value) {
return std::string{value.parameter()->name()}; return std::string{value.parameter()->name()};
}); });
using namespace sqlpp; using namespace sqlpp;
return _db(select((count(t_parameter.id) == 2).as(_match)) // return _db(select((count(t_parameter.id) == total_values).as(_match)) //
.from(t_parameter) // .from(t_parameter) //
.where(t_parameter.name.in(value_list(_parameters)))) .where(t_parameter.name.in(value_list(_parameters))))
.front() .front()
._match; ._match;
} }
void insert(item::Identyfier id, Values values, std::optional< item::Foto > f) { void insert(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) {
using namespace sqlpp; using namespace sqlpp;
_db(insert_into(t_item) //
// _db(insert_into(t_item) // .set(std::tuple_cat( //
// .set(std::tuple_cat(db::details::insert_user_stat(t_item), insert_item_data(id, values, f)))); insert(id),
insert(attributes))));
} }
void do_insert(item::Identyfier id, Values values, std::optional< item::Foto > f) { void do_insert(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) {
auto transaction = sqlpp::start_transaction(_db); auto transaction = sqlpp::start_transaction(_db);
if(not parametersAvalible(values)) { // spdlog::get("default")->info("checking parameters");
if(not parametersAvalible(attributes.values())) {
// spdlog::get("default")->info("parameters not avalible, reverting");
transaction.rollback(); transaction.rollback();
/// TODO throw exception /// TODO throw exception
} else { } else {
insert(std::move(id), std::move(values), std::move(f)); // spdlog::get("default")->info("parameters avalible trying to insert");
insert(std::move(id), std::move(attributes), std::move(f));
} }
transaction.commit(); transaction.commit();
} }
db::PgConnection & _db; db::PgConnection & _db;
}; };
@ -67,7 +79,7 @@ struct PgItemsRepository::PgItemsRepositoryPriv {
PgItemsRepository::PgItemsRepository(db::PgConnection & db) : _priv{spimpl::make_unique_impl< PgItemsRepositoryPriv >(db)} {} PgItemsRepository::PgItemsRepository(db::PgConnection & db) : _priv{spimpl::make_unique_impl< PgItemsRepositoryPriv >(db)} {}
void PgItemsRepository::create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) const { void PgItemsRepository::create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) const {
// _priv->insert(std::move(id), std::move(attributes), std::move(f)); _priv->do_insert(std::move(id), std::move(attributes), std::move(f));
} }
std::unique_ptr< Items > PgItemsRepository::search(const ItemQueryFilters & filer) const { std::unique_ptr< Items > PgItemsRepository::search(const ItemQueryFilters & filer) const {

View File

@ -80,7 +80,7 @@ class PgTestDatabasePrepare {
dbConfig->password = "postgres"; dbConfig->password = "postgres";
dbConfig->user = "postgres"; dbConfig->user = "postgres";
dbConfig->dbname = "eedb"; dbConfig->dbname = "eedb";
dbConfig->debug = false; dbConfig->debug = true;
bool conOk{false}; bool conOk{false};
int faild_attempts_count{0}; int faild_attempts_count{0};

View File

@ -18,10 +18,6 @@ class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > {
using namespace testing; using namespace testing;
user._init(); user._init();
category._init_simple("main"); category._init_simple("main");
numericParameter._init("numeric");
textParameter._init("text");
listParameter._init("list");
sut = std::make_unique< eedb::PgItemsRepository >(db()); sut = std::make_unique< eedb::PgItemsRepository >(db());
} }
@ -31,16 +27,35 @@ class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > {
auto some_val() { auto some_val() {
using namespace std::string_literals; using namespace std::string_literals;
using namespace testing; using namespace testing;
EXPECT_CALL(numericParameter, name()).WillRepeatedly(Return("numeric parameter"s));
EXPECT_CALL(textParameter, name()).WillRepeatedly(Return("text parameter"s)); _names.emplace_back("numeric parameter"s);
EXPECT_CALL(listParameter, name()).WillRepeatedly(Return("list parameter"s)); _names.emplace_back("text parameter"s);
_names.emplace_back("list parameter"s);
numericParameter._init(_names.at(0));
textParameter._init(_names.at(1));
listParameter._init(_names.at(2));
EXPECT_CALL(numericParameter, name()).WillRepeatedly(Return(_names.at(0)));
EXPECT_CALL(textParameter, name()).WillRepeatedly(Return(_names.at(1)));
EXPECT_CALL(listParameter, name()).WillRepeatedly(Return(_names.at(2)));
return eedb::Values(eedb::Value{5, &numericParameter}, return eedb::Values(eedb::Value{5, &numericParameter},
eedb::Value{"some text"s, &textParameter}, eedb::Value{"some text"s, &textParameter},
eedb::Value{std::vector{1.2, 3.4, 5.6, 7.8}, &listParameter}); eedb::Value{std::vector{1.2, 3.4, 5.6, 7.8}, &listParameter});
} }
auto some_attributes() {
// Values values, std::string producer, std::string unit = "szt", double weight = 0
using namespace boost::units;
using namespace boost::units::si;
quantity< mass > E = kilograms * 2; // quantity of energy
return eedb::item::Attributes{some_val(), std::string{"some producer"}};
}
protected: protected:
std::vector< std::string > _names;
eedb::db::pg::UserMock user; eedb::db::pg::UserMock user;
eedb::db::pg::CategoryMock category; eedb::db::pg::CategoryMock category;
eedb::db::pg::ParameterMock numericParameter, textParameter, listParameter; eedb::db::pg::ParameterMock numericParameter, textParameter, listParameter;
@ -53,7 +68,7 @@ template <>
std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgItemsRepositoryTest >::_test_db = {}; std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgItemsRepositoryTest >::_test_db = {};
TEST_F(PgItemsRepositoryTest, createItemDontFail) { TEST_F(PgItemsRepositoryTest, createItemDontFail) {
// EXPECT_NO_THROW(sut->create(some_id(), some_val(), {})); EXPECT_NO_THROW(sut->create(some_id(), some_attributes(), {}));
} }
// TEST_F(PgItemsRepositoryTest, createReturnsValidParameter) { // TEST_F(PgItemsRepositoryTest, createReturnsValidParameter) {

View File

@ -24,7 +24,7 @@ template <>
std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgParametersRepositoryTest >::_test_db = {}; std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgParametersRepositoryTest >::_test_db = {};
TEST_F(PgParametersRepositoryTest, searchForParameterByName){ TEST_F(PgParametersRepositoryTest, searchForParameterByName){
EXPECT_TRUE(sut->search("parameter")); // EXPECT_TRUE(sut->search("parameter"));
} }
TEST_F(PgParametersRepositoryTest, searchForBadName){ TEST_F(PgParametersRepositoryTest, searchForBadName){

View File

@ -7,6 +7,9 @@ namespace eedb {
class Email; class Email;
class Password; class Password;
/**
* @brief The AuthInfo class
*/
class AuthInfo { class AuthInfo {
protected: protected:
using string_view = std::string_view; using string_view = std::string_view;
@ -15,10 +18,22 @@ class AuthInfo {
public: public:
virtual ~AuthInfo() = default; virtual ~AuthInfo() = default;
/**
* @brief password
* @return
*/
virtual const Password & password() const = 0; virtual const Password & password() const = 0;
/**
* @brief email
* @return
*/
virtual const Email & email() const = 0; virtual const Email & email() const = 0;
/**
* @brief emailVerified
* @return
*/
virtual bool emailVerified() const = 0; virtual bool emailVerified() const = 0;
}; };

View File

@ -59,12 +59,6 @@ class Category {
*/ */
virtual Category * parent() const = 0; virtual Category * parent() const = 0;
// /**
// * @brief detached
// * @return true if category is in detached state (has no parent and is not root category)
// */
// virtual bool detached() const = 0;
/** /**
* @brief create * @brief create
* @return category in detached state (not connected to any root category) * @return category in detached state (not connected to any root category)

View File

@ -5,9 +5,12 @@
#include <optional> #include <optional>
#include <string_view> #include <string_view>
#include <boost/range/iterator_range.hpp>
#include <any_iterator/any_iterator.hpp> #include <any_iterator/any_iterator.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/units/systems/si/mass.hpp>
#include <boost/units/quantity.hpp>
#include <eedb/Value.hpp>
namespace eedb { namespace eedb {
@ -30,10 +33,9 @@ class ItemQueryFilters {
}; };
namespace item { namespace item {
class Identyfier { class Identyfier {
public: public:
Identyfier(std::string symbol, std::string producer_symbol={}) : _sym{std::move(symbol)}, _prod{std::move(producer_symbol)} {} Identyfier(std::string symbol, std::string producer_symbol = {}) : _sym{std::move(symbol)}, _prod{std::move(producer_symbol)} {}
std::string_view symbol() const { std::string_view symbol() const {
return _sym; return _sym;
@ -49,8 +51,29 @@ namespace item {
}; };
class Attributes { class Attributes {
Attributes(Values values, std::string producer, std::string unit = "szt", double weight = 0); public:
using Mass = boost::units::quantity< boost::units::si::mass >;
public:
Attributes(Values values, std::string producer, Mass mass = 0.01 * boost::units::si::kilogram)
: _values{std::move(values)}, _mass{std::move(mass)}, _producer{std::move(producer)} {}
const Values & values() const {
return _values;
}
Mass mass() const {
return _mass;
}
std::string_view producer() const {
return _producer;
}
private:
Values _values;
Mass _mass;
std::string _producer;
}; };
class Foto { class Foto {
@ -66,6 +89,7 @@ namespace item {
path _photo; path _photo;
path _thumbnail; path _thumbnail;
}; };
} // namespace item } // namespace item
/** /**
@ -138,7 +162,7 @@ class Item {
protected: protected:
using CategoryIterator = IteratorTypeErasure::any_iterator< Category *, std::random_access_iterator_tag, Category * >; using CategoryIterator = IteratorTypeErasure::any_iterator< Category *, std::random_access_iterator_tag, Category * >;
using CategoriesIt = boost::iterator_range< CategoryIterator >; using CategoriesIt = boost::iterator_range< CategoryIterator >;
public: public:
virtual ~Item() = default; virtual ~Item() = default;

View File

@ -13,7 +13,7 @@ class Parameter;
class Parameters; class Parameters;
namespace parameter { namespace parameter {
enum class Type { enum class Type : uint64_t {
Numeric = 0x1 << 0, Numeric = 0x1 << 0,
NumericList, NumericList,
NumericRange, NumericRange,

View File

@ -1,13 +0,0 @@
#pragma once
#include <string>
namespace eedb{
class StatInfo {
public:
StatInfo() : _id{} {}
private:
int _id;
};
}

View File

@ -22,16 +22,20 @@ class AuthTokens;
class AuthInfo; class AuthInfo;
class AuthIdentities; class AuthIdentities;
/**
* @brief The User class
*/
class User { class User {
public: public:
virtual ~User() = default; virtual ~User() = default;
virtual int uid() const = 0;
virtual const UserName & name() const = 0; virtual const UserName & name() const = 0;
virtual const UserConfig & config() const = 0; virtual const UserConfig & config() const = 0;
// MOVE To Different Class
virtual int uid() const = 0;
virtual AuthTokens & authTokens() const = 0; virtual AuthTokens & authTokens() const = 0;
virtual AuthIdentities & authIdentities() const = 0; virtual AuthIdentities & authIdentities() const = 0;