Moving Avatars into ORM

This commit is contained in:
stephb9959
2021-12-27 23:19:14 -08:00
parent 2c513d8374
commit 784fc3256b
13 changed files with 167 additions and 321 deletions

View File

@@ -90,8 +90,6 @@ add_executable( owsec
src/RESTAPI/RESTAPI_avatar_handler.cpp src/RESTAPI/RESTAPI_avatar_handler.h
src/RESTAPI/RESTAPI_email_handler.cpp src/RESTAPI/RESTAPI_email_handler.h
src/RESTAPI/RESTAPI_sms_handler.cpp src/RESTAPI/RESTAPI_sms_handler.h
src/storage/storage_avatar.cpp src/storage/storage_avatar.h
src/storage/storage_tables.cpp
src/RESTAPI/RESTAPI_suboauth2_handler.h src/RESTAPI/RESTAPI_suboauth2_handler.cpp
src/RESTAPI/RESTAPI_subuser_handler.h src/RESTAPI/RESTAPI_subuser_handler.cpp
src/RESTAPI/RESTAPI_subusers_handler.h src/RESTAPI/RESTAPI_subusers_handler.cpp
@@ -111,7 +109,7 @@ add_executable( owsec
src/framework/OpenWifiTypes.h
src/RESTAPI/RESTAPI_submfa_handler.cpp src/RESTAPI/RESTAPI_submfa_handler.h
src/storage/orm_users.cpp src/storage/orm_users.h
src/storage/orm_tokens.cpp src/storage/orm_tokens.h src/storage/orm_preferences.cpp src/storage/orm_preferences.h src/storage/orm_actionLinks.cpp src/storage/orm_actionLinks.h)
src/storage/orm_tokens.cpp src/storage/orm_tokens.h src/storage/orm_preferences.cpp src/storage/orm_preferences.h src/storage/orm_actionLinks.cpp src/storage/orm_actionLinks.h src/storage/orm_avatar.cpp src/storage/orm_avatar.h)
if(NOT SMALL_BUILD)
target_link_libraries(owsec PUBLIC

2
build
View File

@@ -1 +1 @@
144
149

View File

@@ -36,7 +36,7 @@ namespace OpenWifi {
}
// if there is an avatar, just remove it...
StorageService()->DeleteAvatar(UserInfo_.userinfo.email,Id);
StorageService()->AvatarDB().DeleteAvatar(UserInfo_.userinfo.email,Id);
Poco::TemporaryFile TmpFile;
AvatarPartHandler partHandler(Id, Logger_, TmpFile);
@@ -47,7 +47,7 @@ namespace OpenWifi {
Answer.set(RESTAPI::Protocol::AVATARID, Id);
Answer.set(RESTAPI::Protocol::ERRORCODE, 0);
Logger_.information(Poco::format("Uploaded avatar: %s Type: %s", partHandler.Name(), partHandler.ContentType()));
StorageService()->SetAvatar(UserInfo_.userinfo.email,
StorageService()->AvatarDB().SetAvatar(UserInfo_.userinfo.email,
Id, TmpFile, partHandler.ContentType(), partHandler.Name());
} else {
Answer.set(RESTAPI::Protocol::AVATARID, Id);
@@ -64,7 +64,7 @@ namespace OpenWifi {
}
Poco::TemporaryFile TempAvatar;
std::string Type, Name;
if (!StorageService()->GetAvatar(UserInfo_.userinfo.email, Id, TempAvatar, Type, Name)) {
if (!StorageService()->AvatarDB().GetAvatar(UserInfo_.userinfo.email, Id, TempAvatar, Type, Name)) {
return NotFound();
}
SendFile(TempAvatar, Type, Name);
@@ -75,7 +75,7 @@ namespace OpenWifi {
if (Id.empty()) {
return NotFound();
}
if (!StorageService()->DeleteAvatar(UserInfo_.userinfo.email, Id)) {
if (!StorageService()->AvatarDB().DeleteAvatar(UserInfo_.userinfo.email, Id)) {
return NotFound();
}
OK();

View File

@@ -63,7 +63,7 @@ namespace OpenWifi {
// nothing to do
}
StorageService()->DeleteAvatar(UserInfo_.userinfo.email,Id);
StorageService()->AvatarDB().DeleteAvatar(UserInfo_.userinfo.email,Id);
StorageService()->PreferencesDB().DeletePreferences(UserInfo_.userinfo.email,Id);
Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email));

View File

@@ -11,6 +11,8 @@
#include <string>
#include "framework/OpenWifiTypes.h"
#include "Poco/JSON/Object.h"
#include "Poco/Data/LOB.h"
#include "Poco/Data/LOBStream.h"
namespace OpenWifi {
namespace SecurityObjects {
@@ -280,5 +282,13 @@ namespace OpenWifi {
bool from_json(Poco::JSON::Object::Ptr &Obj);
};
struct Avatar {
std::string id;
std::string type;
uint64_t created=0;
std::string name;
Poco::Data::LOB<char> avatar;
};
}
}

View File

@@ -14,7 +14,6 @@ namespace OpenWifi {
std::lock_guard Guard(Mutex_);
StorageClass::Start();
Create_Tables();
UserDB_ = std::make_unique<OpenWifi::BaseUserDB>("Users", "usr", dbType_,*Pool_, Logger());
SubDB_ = std::make_unique<OpenWifi::BaseUserDB>("Subscribers", "sub", dbType_,*Pool_, Logger());
@@ -22,6 +21,7 @@ namespace OpenWifi {
SubTokenDB_ = std::make_unique<OpenWifi::BaseTokenDB>("SubTokens", "stk", dbType_,*Pool_, Logger());
PreferencesDB_ = std::make_unique<OpenWifi::PreferencesDB>("Preferences", "pre", dbType_,*Pool_, Logger());
ActionLinksDB_ = std::make_unique<OpenWifi::ActionLinkDB>("Actions", "act", dbType_,*Pool_, Logger());
AvatarDB_ = std::make_unique<OpenWifi::AvatarDB>("Avatars", "ava", dbType_,*Pool_, Logger());
UserDB_->Create();
SubDB_->Create();
@@ -29,6 +29,7 @@ namespace OpenWifi {
SubTokenDB_->Create();
PreferencesDB_->Create();
ActionLinksDB_->Create();
AvatarDB_->Create();
UserDB_->InitializeDefaultUser();

View File

@@ -19,6 +19,7 @@
#include "storage/orm_tokens.h"
#include "storage/orm_preferences.h"
#include "storage/orm_actionLinks.h"
#include "storage/orm_avatar.h"
namespace OpenWifi {
@@ -45,24 +46,9 @@ namespace OpenWifi {
OpenWifi::BaseTokenDB & SubTokenDB() { return *SubTokenDB_; }
OpenWifi::PreferencesDB & PreferencesDB() { return *PreferencesDB_; }
OpenWifi::ActionLinkDB & ActionLinksDB() { return *ActionLinksDB_; }
/*
* All user management functions
*/
bool SetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name);
bool GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name);
bool DeleteAvatar(const std::string & Admin, std::string &Id);
OpenWifi::AvatarDB & AvatarDB() { return *AvatarDB_; }
private:
int Create_Tables();
int Create_AvatarTable();
// int Create_ActionLinkTable();
// int Create_Preferences();
// int Create_UserTable();
// int Create_TokensTable();
// int Create_SubTokensTable();
// int Create_SubscriberTable();
std::unique_ptr<OpenWifi::BaseUserDB> UserDB_;
std::unique_ptr<OpenWifi::BaseUserDB> SubDB_;
@@ -70,6 +56,7 @@ namespace OpenWifi {
std::unique_ptr<OpenWifi::BaseTokenDB> SubTokenDB_;
std::unique_ptr<OpenWifi::PreferencesDB> PreferencesDB_;
std::unique_ptr<OpenWifi::ActionLinkDB> ActionLinksDB_;
std::unique_ptr<OpenWifi::AvatarDB> AvatarDB_;
Poco::Timer Timer_;
Archiver Archiver_;

View File

@@ -94,10 +94,10 @@ namespace ORM {
inline std::string FieldTypeToChar(OpenWifi::DBType Type, FieldType T, int Size=0) {
switch(T) {
case FT_INT: return "INT";
case FT_BIGINT: return "BIGINT";
case FT_TEXT: return "TEXT";
case FT_BOOLEAN: return "BOOLEAN";
case FT_INT: return "INT";
case FT_BIGINT: return "BIGINT";
case FT_TEXT: return "TEXT";
case FT_BOOLEAN: return "BOOLEAN";
case FT_VARCHAR:
if(Size)
return std::string("VARCHAR(") + std::to_string(Size) + std::string(")");

101
src/storage/orm_avatar.cpp Normal file
View File

@@ -0,0 +1,101 @@
//
// Created by stephane bourque on 2021-12-27.
//
#include "orm_avatar.h"
/*
std::string id;
std::string type;
uint64_t created=0;
std::string name;
Poco::Data::LOB<char> avatar;
*/
namespace OpenWifi {
static ORM::FieldVec AvatarDB_Fields{
ORM::Field{"id", 36, true},
ORM::Field{"type", ORM::FieldType::FT_BIGINT},
ORM::Field{"created", ORM::FieldType::FT_BIGINT},
ORM::Field{"name", ORM::FieldType::FT_TEXT},
ORM::Field{"avatar", ORM::FieldType::FT_BLOB}
};
AvatarDB::AvatarDB(const std::string &Name, const std::string &ShortName, OpenWifi::DBType T,
Poco::Data::SessionPool &P, Poco::Logger &L) :
DB(T, Name.c_str(), AvatarDB_Fields,{}, P, L, ShortName.c_str()) {
}
bool AvatarDB::SetAvatar(const std::string &Admin, std::string &Id, Poco::TemporaryFile &FileName,
std::string &Type, std::string &Name) {
try {
std::stringstream ss;
std::ifstream ifs(FileName.path().c_str(), std::ios_base::in | std::ios_base::binary);
Poco::StreamCopier::copyStream(ifs, ss);
SecurityObjects::Avatar A;
A.id = Id;
A.type = Type;
A.name = Name;
A.created = std::time(nullptr);
A.avatar.assignRaw(ss.str().c_str(), ss.str().size());
if (Exists("id", Id)) {
return UpdateRecord("id", Id, A);
}
return CreateRecord(A);
} catch (const Poco::Exception &E) {
Logger().log(E);
} catch (...) {
}
return false;
}
bool AvatarDB::GetAvatar(const std::string &Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type,
std::string &Name) {
SecurityObjects::Avatar A;
try {
if(GetRecord("id",Id,A)) {
Type = A.type;
Name = A.name;
Poco::Data::LOBInputStream IL(A.avatar);
std::ofstream f(FileName.path(), std::ios::binary);
Poco::StreamCopier::copyStream(IL, f);
return true;
}
} catch (const Poco::Exception &E) {
Logger().log(E);
} catch (...) {
}
return false;
}
bool AvatarDB::DeleteAvatar(const std::string &Admin, std::string &Id) {
return DeleteRecord("id",Id);
}
}
template<> void ORM::DB<OpenWifi::AvatarRecordTuple,
OpenWifi::SecurityObjects::Avatar>::Convert(OpenWifi::AvatarRecordTuple &T, OpenWifi::SecurityObjects::Avatar &U) {
U.id = T.get<0>();
U.type = T.get<1>();
U.created = T.get<2>();
U.name = T.get<3>();
U.avatar = T.get<4>();
}
template<> void ORM::DB<OpenWifi::AvatarRecordTuple,
OpenWifi::SecurityObjects::Avatar>::Convert(OpenWifi::SecurityObjects::Avatar &U, OpenWifi::AvatarRecordTuple &T) {
T.set<0>(U.id);
T.set<1>(U.type);
T.set<2>(U.created);
T.set<3>(U.name);
T.set<4>(U.avatar);
}

40
src/storage/orm_avatar.h Normal file
View File

@@ -0,0 +1,40 @@
//
// Created by stephane bourque on 2021-12-27.
//
#pragma once
#include "framework/orm.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
namespace OpenWifi {
/*
std::string id;
std::string type;
uint64_t created=0;
std::string name;
Poco::Data::LOB<char> avatar;
*/
typedef Poco::Tuple <
std::string, // id
std::string, // type
uint64_t, // created
std::string, // name
Poco::Data::LOB<char> // avatar
> AvatarRecordTuple;
typedef std::vector <AvatarRecordTuple> AvatarRecordTupleList;
class AvatarDB : public ORM::DB<AvatarRecordTuple, SecurityObjects::Avatar> {
public:
AvatarDB( const std::string &name, const std::string &shortname, OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L);
bool SetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name);
bool GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name);
bool DeleteAvatar(const std::string & Admin, std::string &Id);
private:
};
}

View File

@@ -1,104 +0,0 @@
//
// Created by stephane bourque on 2021-07-15.
//
#include <iostream>
#include <fstream>
#include "storage_avatar.h"
#include "../StorageService.h"
#include "Poco/File.h"
#include "Poco/Data/LOBStream.h"
#include "../Daemon.h"
namespace OpenWifi {
/*
"Id VARCHAR(36) PRIMARY KEY, "
"Type VARCHAR, "
"Created BIGINT, "
"Name VARCHAR, "
"Avatar BLOB"
*/
bool StorageService::SetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
Poco::Data::LOB<char> L;
Poco::Data::LOBOutputStream OL(L);
std::ifstream f(FileName.path(), std::ios::binary);
Poco::StreamCopier::copyStream(f, OL);
uint64_t Now = std::time(nullptr);
std::string St2{"INSERT INTO Avatars (" + AllAvatarFieldsForSelect + ") VALUES( " + AllAvatarValuesForSelect + " )"};
Insert << ConvertParams(St2),
Poco::Data::Keywords::use(Id),
Poco::Data::Keywords::use(Type),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Name),
Poco::Data::Keywords::use(L);
Insert.execute();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool StorageService::GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string & Type, std::string & Name) {
try {
Poco::Data::LOB<char> L;
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string St2{"SELECT " + AllAvatarFieldsForSelect + " FROM Avatars WHERE Id=?"};
Poco::Data::Statement Select2(Sess);
std::string TId;
uint64_t Created;
Select2 << ConvertParams(St2),
Poco::Data::Keywords::into(TId),
Poco::Data::Keywords::into(Type),
Poco::Data::Keywords::into(Created),
Poco::Data::Keywords::into(Name),
Poco::Data::Keywords::into(L),
Poco::Data::Keywords::use(Id);
Select2.execute();
Poco::Data::LOBInputStream IL(L);
std::ofstream f(FileName.path(), std::ios::binary);
Poco::StreamCopier::copyStream(IL, f);
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool StorageService::DeleteAvatar(const std::string & Admin, std::string &Id) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Delete(Sess);
std::string St1{"delete from avatars where id=?"};
Delete << ConvertParams(St1),
Poco::Data::Keywords::use(Id);
Delete.execute();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
}

View File

@@ -1,38 +0,0 @@
//
// Created by stephane bourque on 2021-07-15.
//
#pragma once
namespace OpenWifi {
static const std::string AllAvatarFieldsForCreation_sqlite{
"Id VARCHAR(36) PRIMARY KEY, "
"Type VARCHAR, "
"Created BIGINT, "
"Name VARCHAR, "
"Avatar BLOB"
};
static const std::string AllAvatarFieldsForCreation_mysql{
"Id VARCHAR(36) PRIMARY KEY, "
"Type VARCHAR, "
"Created BIGINT, "
"Name VARCHAR, "
"Avatar LONGBLOB"
};
static const std::string AllAvatarFieldsForCreation_pgsql{
"Id VARCHAR(36) PRIMARY KEY, "
"Type VARCHAR, "
"Created BIGINT, "
"Name VARCHAR, "
"Avatar BYTEA"
};
static const std::string AllAvatarFieldsForSelect{ " Id,Type,Created,Name,Avatar " };
static const std::string AllAvatarValuesForSelect{ "?,?,?,?,?" };
}

View File

@@ -1,149 +0,0 @@
//
// Created by stephane bourque on 2021-06-13.
//
#include "StorageService.h"
#include "storage_avatar.h"
namespace OpenWifi {
int StorageService::Create_Tables() {
Create_AvatarTable();
// Create_ActionLinkTable();
// Create_Preferences();
// Create_UserTable();
// Create_TokensTable();
// Create_SubTokensTable();
// Create_SubscriberTable();
return 0;
}
/*
int StorageService::Create_UserTable() {
Poco::Data::Session Sess = Pool_->get();
try {
if (dbType_ == mysql) {
Sess << "CREATE TABLE IF NOT EXISTS Users (" +
AllUsersFieldsForCreation +
" ,INDEX emailindex (email ASC)"
" ,INDEX nameindex (name ASC))",
Poco::Data::Keywords::now;
} else {
Sess << "CREATE TABLE IF NOT EXISTS Users (" +
AllUsersFieldsForCreation +
")",
Poco::Data::Keywords::now;
Sess << "CREATE INDEX IF NOT EXISTS emailindex ON Users (email ASC)", Poco::Data::Keywords::now;
Sess << "CREATE INDEX IF NOT EXISTS nameindex ON Users (name ASC)", Poco::Data::Keywords::now;
}
return 0;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return 1;
}
int StorageService::Create_SubscriberTable() {
Poco::Data::Session Sess = Pool_->get();
try {
if (dbType_ == mysql) {
Sess << "CREATE TABLE IF NOT EXISTS Subscribers (" +
AllUsersFieldsForCreation +
" ,INDEX emailindex (email ASC)"
" ,INDEX nameindex (name ASC))",
Poco::Data::Keywords::now;
} else {
Sess << "CREATE TABLE IF NOT EXISTS Subscribers (" +
AllUsersFieldsForCreation +
")",
Poco::Data::Keywords::now;
Sess << "CREATE INDEX IF NOT EXISTS emailindex ON Subscribers (email ASC)", Poco::Data::Keywords::now;
Sess << "CREATE INDEX IF NOT EXISTS nameindex ON Subscribers (name ASC)", Poco::Data::Keywords::now;
}
return 0;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return 1;
}
int StorageService::Create_ActionLinkTable() {
try {
Poco::Data::Session Sess = Pool_->get();
Sess << "CREATE TABLE IF NOT EXISTS ActionLinks ( "
+ AllActionLinksFieldsForCreation + " ) ",
Poco::Data::Keywords::now;
return 0;
} catch(const Poco::Exception &E) {
Logger().log(E);
}
return 1;
}
*/
int StorageService::Create_AvatarTable() {
try {
Poco::Data::Session Sess = Pool_->get();
if(dbType_==sqlite) {
Sess << "CREATE TABLE IF NOT EXISTS Avatars (" + AllAvatarFieldsForCreation_sqlite +
") ", Poco::Data::Keywords::now;
} else if(dbType_==mysql) {
Sess << "CREATE TABLE IF NOT EXISTS Avatars (" + AllAvatarFieldsForCreation_mysql +
") ", Poco::Data::Keywords::now;
} else if(dbType_==pgsql) {
Sess << "CREATE TABLE IF NOT EXISTS Avatars (" + AllAvatarFieldsForCreation_pgsql +
") ", Poco::Data::Keywords::now;
}
return 0;
} catch(const Poco::Exception &E) {
Logger().log(E);
}
return 1;
}
/*
int StorageService::Create_TokensTable() {
try {
Poco::Data::Session Sess = Pool_->get();
Sess << "CREATE TABLE IF NOT EXISTS Tokens (" +
AllTokensFieldsForCreation +
") ", Poco::Data::Keywords::now;
return 0;
} catch(const Poco::Exception &E) {
Logger().log(E);
}
return 1;
}
int StorageService::Create_SubTokensTable() {
try {
Poco::Data::Session Sess = Pool_->get();
Sess << "CREATE TABLE IF NOT EXISTS SubTokens (" +
AllTokensFieldsForCreation +
") ", Poco::Data::Keywords::now;
return 0;
} catch(const Poco::Exception &E) {
Logger().log(E);
}
return 1;
}
int StorageService::Create_Preferences() {
try {
Poco::Data::Session Sess = Pool_->get();
Sess << "CREATE TABLE IF NOT EXISTS Preferences (" +
AllPreferencesFieldsForCreation +
") ", Poco::Data::Keywords::now;
return 0;
} catch(const Poco::Exception &E) {
Logger().log(E);
}
return 1;
}
*/
}