Working on User authentication

This commit is contained in:
kdeng00
2019-09-22 23:57:14 -04:00
parent 89ed9f9252
commit 4bd794c288
19 changed files with 627 additions and 11 deletions
+14 -2
View File
@@ -15,6 +15,7 @@
#include "controller/CoverArtController.hpp"
#include "controller/GenreController.hpp"
#include "controller/LoginController.hpp"
#include "controller/RegisterController.hpp"
#include "controller/SongController.hpp"
#include "controller/YearController.hpp"
#include "model/Models.h"
@@ -33,6 +34,7 @@ void run(const model::BinaryPath& bConf)
auto coverArtController = std::make_shared<controller::CoverArtController>(bConf);
auto gnrController = std::make_shared<controller::GenreController>(bConf);
auto logController = std::make_shared<controller::LoginController>(bConf);
auto regController = std::make_shared<controller::RegisterController>(bConf);
auto sngController = std::make_shared<controller::SongController>(bConf);
auto yearController = std::make_shared<controller::YearController>(bConf);
@@ -41,6 +43,7 @@ void run(const model::BinaryPath& bConf)
coverArtController->addEndpointsToRouter(router);
gnrController->addEndpointsToRouter(router);
logController->addEndpointsToRouter(router);
regController->addEndpointsToRouter(router);
sngController->addEndpointsToRouter(router);
yearController->addEndpointsToRouter(router);
@@ -59,8 +62,17 @@ int main(int argc, char **argv)
{
oatpp::base::Environment::init();
model::BinaryPath bConf(argv[0]);
verify::Initialization::checkIcarus(bConf);
model::BinaryPath bConf(std::move(argv[0]));
if (argc > 1) {
if (!verify::Initialization::skipVerification(argv[1])) {
verify::Initialization::checkIcarus(bConf);
} else {
std::cout << "skiping verifyication" << std::endl;
}
} else {
verify::Initialization::checkIcarus(bConf);
}
run(bConf);
+277
View File
@@ -0,0 +1,277 @@
#include "database/UserRepository.h"
#include <string>
#include <sstream>
#include <cstring>
namespace database {
UserRepository::UserRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) { }
model::User UserRepository::retrieveUserRecord(model::User& user,
type::UserFilter filter = type::UserFilter::username)
{
std::stringstream qry;
auto conn = setupMysqlConnection();
auto stmt = mysql_stmt_init(conn);
qry << "SELECT * FROM User WHERE ";
MYSQL_BIND params[1];
std::memset(params, 0, sizeof(params));
auto userLength = user.username.size();
switch (filter) {
case type::UserFilter::id:
break;
case type::UserFilter::username:
qry << "Username = ?";
params[0].buffer_type = MYSQL_TYPE_LONG;
params[0].buffer = (char*)user.username.c_str();
params[0].length = &userLength;
params[0].is_null = 0;
break;
default:
break;
}
const auto query = qry.str();
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
status = mysql_stmt_bind_param(stmt, params);
status = mysql_stmt_execute(stmt);
user = parseRecord(stmt);
mysql_stmt_close(stmt);
mysql_close(conn);
return user;
}
void UserRepository::saveUserRecord(const model::User& user)
{
std::cout << "inserting user record" << std::endl;
auto conn = setupMysqlConnection();
auto stmt = mysql_stmt_init(conn);
std::stringstream qry;
qry << "INSERT INTO User(Firstname, Lastname, Phone, Email, Username, Password) ";
qry << "VALUES(?, ?, ?, ?, ?, ?)";
const auto query = qry.str();
auto sizes = fetchUserLengths(user);
auto params = insertUserValues(user, sizes);
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
status = mysql_stmt_bind_param(stmt, params.get());
status = mysql_stmt_execute(stmt);
mysql_stmt_close(stmt);
mysql_close(conn);
}
std::shared_ptr<MYSQL_BIND> UserRepository::insertUserValues(const model::User& user,
std::shared_ptr<UserRepository::UserLengths> lengths)
{
std::shared_ptr<MYSQL_BIND> values((MYSQL_BIND*) std::calloc(6, sizeof(MYSQL_BIND)));
values.get()[0].buffer_type = MYSQL_TYPE_STRING;
values.get()[0].buffer = (char*)user.firstname.c_str();
values.get()[0].length = &(lengths->firstnameLength);
values.get()[0].is_null = 0;
values.get()[1].buffer_type = MYSQL_TYPE_STRING;
values.get()[1].buffer = (char*)user.lastname.c_str();
values.get()[1].length = &(lengths->lastnameLength);
values.get()[1].is_null = 0;
values.get()[2].buffer_type = MYSQL_TYPE_STRING;
values.get()[2].buffer = (char*)user.phone.c_str();
values.get()[2].length = &(lengths->phoneLength);
values.get()[2].is_null = 0;
values.get()[3].buffer_type = MYSQL_TYPE_STRING;
values.get()[3].buffer = (char*)user.email.c_str();
values.get()[3].length = &(lengths->emailLength);
values.get()[3].is_null = 0;
values.get()[4].buffer_type = MYSQL_TYPE_STRING;
values.get()[4].buffer = (char*)user.username.c_str();
values.get()[4].length = &(lengths->usernameLength);
values.get()[4].is_null = 0;
values.get()[5].buffer_type = MYSQL_TYPE_STRING;
values.get()[5].buffer = (char*)user.password.c_str();
values.get()[5].length = &(lengths->passwordLength);
values.get()[5].is_null = 0;
return values;
}
std::shared_ptr<MYSQL_BIND> UserRepository::valueBind(model::User& user, std::shared_ptr<UserVals> userVal)
{
std::shared_ptr<MYSQL_BIND> values((MYSQL_BIND*) std::calloc(7, sizeof(MYSQL_BIND)));
constexpr auto strLen = 1024;
values.get()[0].buffer_type = MYSQL_TYPE_LONG;
values.get()[0].buffer = (char*)&user.id;
values.get()[1].buffer_type = MYSQL_TYPE_STRING;
values.get()[1].buffer = (char*)userVal->firstname;
values.get()[1].buffer_length = strLen;
values.get()[2].buffer_type = MYSQL_TYPE_STRING;
values.get()[2].buffer = (char*)userVal->lastname;
values.get()[2].buffer_length = strLen;
values.get()[3].buffer_type = MYSQL_TYPE_STRING;
values.get()[3].buffer = (char*)userVal->phone;
values.get()[3].buffer_length = strLen;
values.get()[4].buffer_type = MYSQL_TYPE_STRING;
values.get()[4].buffer = (char*)userVal->email;
values.get()[4].buffer_length = strLen;
values.get()[5].buffer_type = MYSQL_TYPE_STRING;
values.get()[5].buffer = (char*)userVal->username;
values.get()[5].buffer_length = strLen;
values.get()[6].buffer_type = MYSQL_TYPE_STRING;
values.get()[6].buffer = (char*)userVal->password;
values.get()[6].buffer_length = strLen;
return values;
}
std::shared_ptr<MYSQL_BIND> UserRepository::valueBind(model::User& user, UserVals& userVal)
{
std::shared_ptr<MYSQL_BIND> values((MYSQL_BIND*) std::calloc(7, sizeof(MYSQL_BIND)));
constexpr auto strLen = 1024;
values.get()[0].buffer_type = MYSQL_TYPE_LONG;
values.get()[0].buffer = (char*)&user.id;
values.get()[1].buffer_type = MYSQL_TYPE_STRING;
values.get()[1].buffer = (char*)userVal.firstname;
values.get()[1].buffer_length = strLen;
values.get()[2].buffer_type = MYSQL_TYPE_STRING;
values.get()[2].buffer = (char*)userVal.lastname;
values.get()[2].buffer_length = strLen;
values.get()[3].buffer_type = MYSQL_TYPE_STRING;
values.get()[3].buffer = (char*)userVal.phone;
values.get()[3].buffer_length = strLen;
values.get()[4].buffer_type = MYSQL_TYPE_STRING;
values.get()[4].buffer = (char*)userVal.email;
values.get()[4].buffer_length = strLen;
values.get()[5].buffer_type = MYSQL_TYPE_STRING;
values.get()[5].buffer = (char*)userVal.username;
values.get()[5].buffer_length = strLen;
values.get()[6].buffer_type = MYSQL_TYPE_STRING;
values.get()[6].buffer = (char*)userVal.password;
values.get()[6].buffer_length = strLen;
return values;
}
std::shared_ptr<MYSQL_BIND> UserRepository::valueBind(model::User& user)
{
std::shared_ptr<MYSQL_BIND> values((MYSQL_BIND*) std::calloc(7, sizeof(MYSQL_BIND)));
constexpr auto strLen = 1024;
values.get()[0].buffer_type = MYSQL_TYPE_LONG;
values.get()[0].buffer = (char*)&user.id;
values.get()[1].buffer_type = MYSQL_TYPE_STRING;
values.get()[1].buffer = (char*)user.firstname.data();
values.get()[1].buffer_length = strLen;
values.get()[2].buffer_type = MYSQL_TYPE_STRING;
values.get()[2].buffer = (char*)user.lastname.data();
values.get()[2].buffer_length = strLen;
values.get()[3].buffer_type = MYSQL_TYPE_STRING;
values.get()[3].buffer = (char*)user.phone.data();
values.get()[3].buffer_length = strLen;
values.get()[4].buffer_type = MYSQL_TYPE_STRING;
values.get()[4].buffer = (char*)user.email.data();
values.get()[4].buffer_length = strLen;
values.get()[5].buffer_type = MYSQL_TYPE_STRING;
values.get()[5].buffer = (char*)user.username.data();
values.get()[5].buffer_length = strLen;
values.get()[6].buffer_type = MYSQL_TYPE_STRING;
values.get()[6].buffer = (char*)user.password.data();
values.get()[6].buffer_length = strLen;
return values;
}
std::shared_ptr<UserRepository::UserLengths> UserRepository::fetchUserLengths(const model::User& user)
{
auto userLen = std::make_shared<UserLengths>();
userLen->firstnameLength = user.firstname.size();
userLen->lastnameLength = user.lastname.size();
userLen->phoneLength = user.phone.size();
userLen->emailLength = user.email.size();
userLen->usernameLength = user.username.size();
userLen->passwordLength = user.password.size();
return userLen;
}
std::shared_ptr<UserRepository::UserVals> UserRepository::fetchUserVals()
{
constexpr auto strLen = 1024;
auto userVal = std::make_shared<UserVals>();
/**
userVal->firstname = std::make_shared<char*>(new char[strLen]);
userVal->lastname = std::make_shared<char*>(new char[strLen]);
userVal->email = std::make_shared<char*>(new char[strLen]);
userVal->phone = std::make_shared<char*>(new char[strLen]);
userVal->username = std::make_shared<char*>(new char[strLen]);
userVal->password = std::make_shared<char*>(new char[strLen]);
*/
return userVal;
}
model::User UserRepository::parseRecord(MYSQL_STMT *stmt)
{
// TODO : parse user record
model::User user;
auto userVal = fetchUserVals();
UserVals uv;
//auto bindedValues = valueBind(user, userVal);
auto bindedValues = valueBind(user, uv);
//auto bindedValues = valueBind(user);
auto status = mysql_stmt_bind_result(stmt, bindedValues.get());
status = mysql_stmt_fetch(stmt);
std::cout << user.id << std::endl;
//std::cout << "binded firstname: " << userVal->firstname << std::endl;
//std::cout << "binded lastname: " << uv.lastname << std::endl;
//user.firstname = userVal->firstname;
/**
user.lastname = *userVal->lastname.get();
user.email = *userVal->email.get();
user.phone = *userVal->phone.get();
user.username = *userVal->username.get();
user.password = *userVal->password.get();
*/
return user;
}
}
+59
View File
@@ -0,0 +1,59 @@
#include "manager/UserManager.h"
#include "database/UserRepository.h"
#include "type/UserFilter.h"
#include "utility/MetadataRetriever.h"
#include "utility/PasswordEncryption.h"
namespace manager {
UserManager::UserManager(const model::BinaryPath& bConf) : m_bConf(bConf) { }
model::User UserManager::userDtoConv(dto::UserDto::ObjectWrapper& userDto)
{
model::User user;
user.id = (userDto->userId.getPtr() == nullptr) ? 0 : userDto->userId->getValue();
user.firstname = (userDto->firstname == nullptr) ? "" : userDto->firstname->c_str();
user.lastname = (userDto->lastname == nullptr) ? "" : userDto->lastname->c_str();
user.phone = (userDto->phone == nullptr) ? "" : userDto->phone->c_str();
user.email = (userDto->email == nullptr) ? "" : userDto->email->c_str();
user.username = (userDto->username == nullptr) ? "" : userDto->username->c_str();
user.password = (userDto->password == nullptr) ? "" : userDto->password->c_str();
return user;
}
void UserManager::printUser(const model::User& user)
{
std::cout << "\nuser info" << std::endl;
std::cout << "id: " << user.id << std::endl;
std::cout << "firstname: " << user.firstname << std::endl;
std::cout << "lastname: " << user.lastname << std::endl;
std::cout << "phone: " << user.phone << std::endl;
std::cout << "email: " << user.email << std::endl;
std::cout << "username: " << user.username << std::endl;
std::cout << "password: " << user.password<< std::endl;
}
void UserManager::registerUser(model::User& user)
{
printUser(user);
utility::PasswordEncryption passEnc;
auto hashed = passEnc.hashPassword(user);
user.password = hashed.hashPassword;
database::UserRepository usrRepo(m_bConf);
usrRepo.saveUserRecord(user);
model::User usr;
usr.username = user.username;
std::cout << usr.username << std::endl;
usr = usrRepo.retrieveUserRecord(usr, type::UserFilter::username);
printUser(usr);
}
}
+37
View File
@@ -0,0 +1,37 @@
#include "utility/PasswordEncryption.h"
#include <iostream>
#include <memory>
#include <bcrypt.h>
namespace utility {
model::PassSec PasswordEncryption::hashPassword(const model::User& user)
{
model::PassSec passSec;
std::unique_ptr<char[]> salt(new char[BCRYPT_HASHSIZE]);
std::unique_ptr<char[]> hash(new char[BCRYPT_HASHSIZE]);
std::cout << "generating salt" << std::endl;
bcrypt_gensalt(saltSize(), salt.get());
std::cout << "hashing password" << std::endl;
bcrypt_hashpw(user.password.c_str(), salt.get(), hash.get());
passSec.salt = salt.get();
passSec.hashPassword = hash.get();
std::cout << "hash: " << passSec.hashPassword << std::endl;
std::cout << "salt: " << passSec.salt << std::endl;
return passSec;
}
int PasswordEncryption::saltSize()
{
constexpr auto size = 10000;
return size;
}
}
+15 -5
View File
@@ -10,8 +10,16 @@
namespace fs = std::filesystem;
namespace verify {
bool Initialization::skipVerification(const std::string& argument)
{
return argument.compare("--noverify") == 0;
}
// verifies if the configuration settings are valid
void verify::Initialization::checkIcarus(const model::BinaryPath& bConf)
void Initialization::checkIcarus(const model::BinaryPath& bConf)
{
auto auth = confirmConfigAuth(bConf);
auto database = confirmConfigDatabase(bConf);
@@ -26,7 +34,7 @@ void verify::Initialization::checkIcarus(const model::BinaryPath& bConf)
// verifies that the authorization settings are not the default values
bool verify::Initialization::confirmConfigAuth(const model::BinaryPath& bConf)
bool Initialization::confirmConfigAuth(const model::BinaryPath& bConf)
{
manager::TokenManager tokMgr;
@@ -34,7 +42,7 @@ bool verify::Initialization::confirmConfigAuth(const model::BinaryPath& bConf)
}
// verifies if database connectivity can be established
bool verify::Initialization::confirmConfigDatabase(const model::BinaryPath& bConf)
bool Initialization::confirmConfigDatabase(const model::BinaryPath& bConf)
{
database::BaseRepository baseRepo(bConf);
@@ -42,7 +50,7 @@ bool verify::Initialization::confirmConfigDatabase(const model::BinaryPath& bCon
}
// verifies if the paths found in the config files exists
bool verify::Initialization::confirmConfigPaths(const model::BinaryPath& bConf)
bool Initialization::confirmConfigPaths(const model::BinaryPath& bConf)
{
auto pathConfig = manager::DirectoryManager::pathConfigContent(bConf);
@@ -96,8 +104,10 @@ bool verify::Initialization::confirmConfigPaths(const model::BinaryPath& bConf)
// confirmation failed
void verify::Initialization::failedConfirmation()
void Initialization::failedConfirmation()
{
std::cout << "configuration confirmation failed. check your settings" << std::endl;
std::exit(-1);
}
}