Skip to content

Commit

Permalink
Functional login and logout, thank God.
Browse files Browse the repository at this point in the history
Added custom view handler and some model methods.
Added DB dump when the console is destroyed.
  • Loading branch information
cristianfrasineanu committed Nov 26, 2016
1 parent b8efd56 commit 1ba8dc8
Show file tree
Hide file tree
Showing 16 changed files with 131 additions and 67 deletions.
11 changes: 3 additions & 8 deletions app/Bootstrap.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "Console.h"
#include <vld.h>

using namespace std;

Expand All @@ -19,7 +18,7 @@ void main()
}
catch (const invalid_argument &e)
{
cout << e.what();
toast(e.what(), string("error"));

sleepAndClearBuffer(console.getDelay());
console.reloadView();
Expand All @@ -28,16 +27,12 @@ void main()
}
catch (const invalid_argument &e)
{
cout << e.what()
<< endl;
toast(e.what(), string("error"));
}
catch (const system_error &e)
{
clearScreen();

cout << e.code()
<< " "
<< e.what()
<< endl;
toast(e.what(), string("error"));
}
}
38 changes: 29 additions & 9 deletions app/Console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

//---Console---
//-------------
// We need an initial state, because we don't have any means like mapping views to HTTP routes.
// The Console class represents an entry point for all the other components, like View.
// An initial state and a synchronous processing of the views is necessary due to the lack of console.
// It acts like a glue between all other components of the framework.
string Console::initialView = "home.view";
string Console::viewsFolder = "..\\views";

Expand Down Expand Up @@ -110,7 +110,7 @@ void Console::loadViews(const fs::path &viewsFolder)
void Console::loadActions()
{
// TODO: load actions via config file
vector<char> actions = { 'q', 'b', 'n' };
vector<char> actions = { 'q', 'b', 'n', 'y' };

this->actions = actions;
}
Expand All @@ -129,39 +129,52 @@ void Console::handleView()
buffer << viewFile.rdbuf();
this->currentView.setRawFormat(buffer.str());

// If there's any validation error catch it and reload the view.
this->theController = Controller(this->currentView.getViewName(), buffer.str(), View::getViewExtension());
if (!Controller::getErrorBag().empty()) {
if (!Controller::getErrorBag().empty())
{
toast(string("There were some issues:"), string("error"));
printVector(Controller::getErrorBag());

sleepAndClearBuffer(3 * this->delay);
this->reloadView();
}
// TODO: provide an option to the users to cancel what they want to do.
// i.e. show the errors and ask if they want to try again or go back.

buffer.clear();
viewFile.close();
}
else
{
string error_message = "The input stream from the view couldn't be opened.";
throw system_error(error_code(3, system_category()), error_message);
throw system_error(error_code(3, system_category()), string("The input stream from the view couldn't be opened."));
}
}

// Prepare the next view and also cache the current one.
void Console::renderNextView()
{
string nextView = this->currentView.getAvailableOptions().find(this->getLastInput())->second;
map<char, string> nextOptions = View::getViewsOptions().find(nextView)->second;

// Cache the current view
this->previousViews.push_back(this->currentView);
this->currentView = View(nextView, nextOptions);

clearScreen();
this->handleView();
}

// Render a custom view without caching the previous one as it breaks the normal flow.
void Console::renderNextView(string &viewName)
{
map<char, string> nextOptions = View::getViewsOptions().find(viewName)->second;

this->previousViews.erase(this->previousViews.begin(), this->previousViews.end());
this->currentView = View(viewName, nextOptions);

clearScreen();
this->handleView();
}

void Console::renderPreviousView()
{
if (!this->previousViews.empty())
Expand Down Expand Up @@ -192,8 +205,12 @@ void Console::takeActionOrNext()
this->renderPreviousView();
break;
case 'n':
// TODO: implement pagination for the questions index view
// TODO: implement pagination
break;
case 'y':
UserRepository::logOutUser();
// TODO: Decouple this somehow
this->renderNextView(string(Console::initialView));
default:
break;
}
Expand Down Expand Up @@ -223,6 +240,9 @@ Console::~Console()
{
delete[] this->mode;

// Dump all the records...
UserModel::dumpFile();

clearScreen();
cout << "Program exited the main console."
<< endl;
Expand Down
7 changes: 6 additions & 1 deletion app/Console.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Console {
char lastInput;
unsigned delay;
bool exit;

View currentView;
Controller theController;
vector<View> previousViews;
Expand All @@ -29,9 +30,12 @@ class Console {

void loadViews(const fs::path &);
void loadActions();

void renderNextView();
void handleView();
void renderNextView(string &);

void renderPreviousView();
void handleView();
public:
Console();
Console(char *);
Expand All @@ -44,6 +48,7 @@ class Console {

void showPrompt();
unsigned getDelay();

void reloadView();

~Console();
Expand Down
6 changes: 4 additions & 2 deletions app/Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

//---Controller---
//----------------
// Well, just a general controller... not much to see here.
string Controller::userInputString = "@input-";
string Controller::outputString = "@output-";
string Controller::middlewareString = "@guard-";

vector<string> Controller::errorBag = {};

Expand All @@ -14,6 +14,7 @@ void Controller::justShow()
<< endl;
}

// Determine the order of the input/output from the user.
void Controller::prepareView()
{
string copyChunk = this->viewChunk;
Expand All @@ -27,7 +28,6 @@ void Controller::prepareView()
this->controllerAttributions.push_back("output");
}

// Determine the order of the input/output from the user.
while (this->hasInput(copyChunk) || this->hasOutput(copyChunk))
{
if (!this->hasOutput(copyChunk))
Expand Down Expand Up @@ -99,6 +99,7 @@ Controller::Controller()
{
this->controllerName = new char[strlen("NO_CONTROLLER") + 1];
strcpy(this->controllerName, "NO_CONTROLLER");

this->viewChunk = "";
this->controllerAttributions = {};
this->userInputs = {};
Expand All @@ -111,6 +112,7 @@ Controller::Controller(char *viewName, string &viewChunk, string &ViewExtension)

this->controllerName = new char[controllerName.size() + 1];
strcpy(this->controllerName, controllerName.c_str());

this->viewChunk = viewChunk;
this->controllerAttributions = {};
this->userInputs = {};
Expand Down
2 changes: 0 additions & 2 deletions app/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class Controller {
private:
static string userInputString;
static string outputString;
static string middlewareString;

static vector<string> errorBag;

Expand All @@ -24,7 +23,6 @@ class Controller {
void justShow();
void prepareView();
void prepareViewInput(const string &, const string &);
// TODO: take the chunk one by one for output and request output from model for each output variable
public:
static void pushError(string &);
static vector<string> getErrorBag();
Expand Down
3 changes: 1 addition & 2 deletions app/Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ void sleepAndClearBuffer(unsigned delay)
{
Sleep(delay);

// Clear the keyboard buffer during the sleep cycle (if there are any keys pressed),
// so whatever keys are hit are discarded.
// Clear the keyboard buffer during the sleep cycle (if there are any keys pressed).
while (_kbhit())
{
_getch();
Expand Down
2 changes: 1 addition & 1 deletion app/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ inline void printVector(vector<V> &v)
template<typename T>
inline void toast(T content, string &status)
{
cout << endl << endl;
cout << endl;

if (status == "success")
{
Expand Down
2 changes: 1 addition & 1 deletion app/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ Model::Model()
this->truncatedInput = {};
}

// Pass the payload along to the repository in order to be validated.
void Model::confirmInput(const map<string, string> &payLoad)
{
this->rawInput = payLoad;

// There's interaction with only one model on the view.
string entityName = this->parseEntityName(this->rawInput.begin()->first),
inputAlias;

Expand Down
61 changes: 51 additions & 10 deletions app/UserModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@ User UserModel::getAfterUser(string &username)
{
this->io.seekg(0, this->io.beg);

do
while (this->io.read(reinterpret_cast<char *>(&this->user), sizeof(User)))
{
this->io.read(reinterpret_cast<char *>(&this->user), sizeof(User));

if (this->user.username == username)
{
return this->user;
}
} while (!this->io.eof());
}

throw("Username not found!");
throw invalid_argument("Username not found!");
}

User UserModel::getAfterId(int id)
Expand All @@ -25,6 +23,21 @@ User UserModel::getAfterId(int id)
return this->user;
}

User UserModel::getActive()
{
this->io.seekg(0, this->io.beg);

while (this->io.read(reinterpret_cast<char *>(&this->user), sizeof(User)))
{
if (this->user.active == true)
{
return this->user;
}
}

throw exception("No active user!");
}

void UserModel::markAs(string &status, int id)
{
this->getAfterId(id);
Expand All @@ -34,7 +47,7 @@ void UserModel::markAs(string &status, int id)
this->save();
}

// Serialize the object when saving a user.
// Serialize the object.
void UserModel::save()
{
this->io.seekp((this->user.id - 1) * sizeof(User), this->io.beg);
Expand Down Expand Up @@ -77,6 +90,36 @@ void UserModel::setAttributes(map<string, string> &cleanInputs)
this->user.id = ++this->lastId;
}

void UserModel::dumpFile()
{
User user;

ifstream db(UserModel::pathToFile, ios::in | ios::binary);
ofstream dump((UserModel::pathToFile.substr(0, UserModel::pathToFile.find(".store")).append(".txt")), ios::out | ios::trunc);

if (db.is_open() && dump.is_open())
{
db.seekg(0, db.beg);

while (db.read(reinterpret_cast<char *>(&user), sizeof(User)))
{
dump << user.id << endl
<< user.full_name << endl
<< user.email << endl
<< user.username << endl
<< user.password << endl
<< user.created_at << endl
<< user.deleted_at << endl
<< user.role << endl
<< user.active << endl
<< user.banned << endl << endl;
}

db.close();
dump.close();
}
}

UserModel::~UserModel()
{
this->io.close();
Expand All @@ -103,12 +146,10 @@ void UserModel::setLastId()
}
else
{
User lastUser;

this->io.seekg((this->fileSize / sizeof(User) - 1) * sizeof(User), this->io.beg);
this->io.read(reinterpret_cast<char *>(&lastUser), sizeof(lastUser));
this->io.read(reinterpret_cast<char *>(&this->user), sizeof(User));

this->lastId = lastUser.id;
this->lastId = this->user.id;
}
}

Expand Down
7 changes: 4 additions & 3 deletions app/UserModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ class UserModel : public ModelInterface {
void openIOStream();
void setLastId();

int fileSize;
long long fileSize;
int lastId;
public:
// Open the IOStream and assign the protected attributes that shouldn't be changed by the user
static void dumpFile();
UserModel();

//vector<User> getAll();
User getAfterUser(string &);
User getAfterId(int);
User getActive();

void markAs(string &, int);
void save();
void setAttributes(map<string, string> &);
Expand Down
Loading

0 comments on commit 1ba8dc8

Please sign in to comment.