From 4fc87f8e37e11af305c7d5436dee74adbb3ce2ed Mon Sep 17 00:00:00 2001 From: Cristian-Adrian Frasineanu Date: Mon, 28 Nov 2016 12:20:09 +0200 Subject: [PATCH] Handle input after the action passed and check for user's existence. --- app/Bootstrap.cpp | 3 +- app/Console.cpp | 5 +-- app/Controller.cpp | 31 +++++++++++------- app/Controller.h | 5 +-- app/Helpers.cpp | 2 +- app/Helpers.h | 2 +- app/Model.cpp | 10 +++++- app/UserModel.cpp | 31 +++++++++++++++++- app/UserModel.h | 1 + app/UserRepository.cpp | 27 +++++++++++----- database/users.store | Bin 4648 -> 2656 bytes database/users.txt | 69 +++++++++++------------------------------ views/login.view | 4 ++- views/signup.view | 2 ++ 14 files changed, 110 insertions(+), 82 deletions(-) diff --git a/app/Bootstrap.cpp b/app/Bootstrap.cpp index c84ee53..52e9cfa 100644 --- a/app/Bootstrap.cpp +++ b/app/Bootstrap.cpp @@ -20,13 +20,14 @@ void main() { toast(string(e.what()), string("error")); - sleepAndClearBuffer(console.getDelay()); + sleepAndFlushInput(console.getDelay()); clearPreviousLines(0); } } while (!console.shouldExit()); } catch (const invalid_argument &e) { + clearScreen(); toast(string(e.what()), string("error")); } catch (const system_error &e) diff --git a/app/Console.cpp b/app/Console.cpp index f0b1f8d..0964b51 100644 --- a/app/Console.cpp +++ b/app/Console.cpp @@ -287,10 +287,7 @@ Console::~Console() wbkgd(stdscr, COLOR_PAIR(1)); printString("Program exited the main console.\n"); - // This or use the windows Sleep. - // Maybe better Sleep. - //timeout(this->delay); - getch(); + sleepAndFlushInput(this->delay); endwin(); refresh(); diff --git a/app/Controller.cpp b/app/Controller.cpp index 76dbc6d..b993f35 100644 --- a/app/Controller.cpp +++ b/app/Controller.cpp @@ -5,6 +5,7 @@ // Well, just a general controller... not much to see here. string Controller::userInputString = "@input-"; string Controller::outputString = "@output-"; +string Controller::actionString = "@action-"; vector Controller::errorBag = {}; @@ -22,6 +23,9 @@ void Controller::prepareView() if (this->hasInput(copyChunk)) { this->controllerAttributions.push_back("input"); + + // Pass the corresposing action to userInputs. + this->prepareAction(copyChunk); } if (this->hasOutput(copyChunk)) { @@ -80,39 +84,41 @@ void Controller::prepareViewInput(const string &subChunk, const string &inputAli const char backspace = 8; unsigned char ch = 0; - + noecho(); while ((ch = getch()) != carriage_return) { if (ch == backspace && userInput.size()) { - printw("\b \b"); - refresh(); + // Otherwise the previous character will still remain on the screen if not replaced with a whitespace. + printString("\b \b"); userInput.resize(userInput.size() - 1); } else if (ch != backspace) { userInput += ch; - printw("*"); - refresh(); + printString("*"); } } - - // Re-enable input and render the previous carriage return. echo(); - printString("\n"); } else { - //getline(cin, userInput); getString(userInput); } - printString("\n"); - this->userInputs[inputAlias] = userInput; } +void Controller::prepareAction(string &chunk) +{ + this->userInputs["action"] = chunk.substr(chunk.find(Controller::actionString) + Controller::actionString.size(), + chunk.find("\n", chunk.find(Controller::actionString)) - chunk.find(Controller::actionString) - Controller::actionString.size()); + + chunk.erase(chunk.find(Controller::actionString), + (Controller::actionString + this->userInputs["action"]).size() + 1); +} + void Controller::pushError(string &error) { if (error == "") @@ -145,6 +151,7 @@ Controller::Controller(char *viewName, string &viewChunk, string &ViewExtension) string controllerName = viewName; controllerName.erase(controllerName.find(ViewExtension), ViewExtension.size()).append("Controller"); + // Enable input echoing when typing. echo(); this->controllerName = new char[controllerName.size() + 1]; @@ -175,7 +182,7 @@ void Controller::chopChunkAndGetAlias(string &chunk) this->prepareViewInput(chunk.substr(0, chunk.find(Controller::userInputString) - 1), inputAlias); - chunk.erase(0, chunk.find(inputAlias) + inputAlias.size() + 2); + chunk.erase(0, chunk.find(inputAlias) + inputAlias.size() + 1); } // Don't assign it multiple times, stupid. diff --git a/app/Controller.h b/app/Controller.h index 2dd8b25..121dc68 100644 --- a/app/Controller.h +++ b/app/Controller.h @@ -11,6 +11,7 @@ class Controller { private: static string userInputString; static string outputString; + static string actionString; static vector errorBag; @@ -23,6 +24,8 @@ class Controller { void justShow(); void prepareView(); void prepareViewInput(const string &, const string &); + void prepareAction(string &); + void chopChunkAndGetAlias(string &); public: static void pushError(string &); static vector getErrorBag(); @@ -36,8 +39,6 @@ class Controller { vector &getControllerAttributions(); char *getControllerName(); - void chopChunkAndGetAlias(string &); - void operator=(const Controller &); ~Controller(); diff --git a/app/Helpers.cpp b/app/Helpers.cpp index f653a1e..e995f40 100644 --- a/app/Helpers.cpp +++ b/app/Helpers.cpp @@ -6,7 +6,7 @@ void toLowerCase(string &input) [](unsigned char ch) { return tolower(ch); }); } -void sleepAndClearBuffer(unsigned delay) +void sleepAndFlushInput(unsigned delay) { Sleep(delay); flushinp(); diff --git a/app/Helpers.h b/app/Helpers.h index 446ded8..45e9a6e 100644 --- a/app/Helpers.h +++ b/app/Helpers.h @@ -28,7 +28,7 @@ inline bool isInMap(map &haystack, FirstT needle) void printVector(vector &); void toast(string &, string &); void toLowerCase(string &); -void sleepAndClearBuffer(unsigned); +void sleepAndFlushInput(unsigned); void clearScreen(); void getString(string &); void printString(const char *); diff --git a/app/Model.cpp b/app/Model.cpp index 6960a95..a3c4054 100644 --- a/app/Model.cpp +++ b/app/Model.cpp @@ -34,7 +34,7 @@ void Model::confirmInput(const map &payLoad) { this->rawInput = payLoad; - string entityName = this->parseEntityName(this->rawInput.begin()->first), + string entityName = this->parseEntityName((++this->rawInput.begin())->first), inputAlias; if (this->repository == NULL) @@ -44,6 +44,14 @@ void Model::confirmInput(const map &payLoad) for (map::iterator it = this->rawInput.begin(); it != this->rawInput.end(); it++) { + // Skip truncation for action. + if (it->first == "action") + { + this->truncatedInput["action"] = it->second; + + continue; + } + inputAlias = it->first; inputAlias.erase(0, entityName.size() + 1); diff --git a/app/UserModel.cpp b/app/UserModel.cpp index 63b2281..1ef9785 100644 --- a/app/UserModel.cpp +++ b/app/UserModel.cpp @@ -12,6 +12,9 @@ User UserModel::getAfterUser(string &username) } } + // Otherwise if we reach the end of the file, the eof flag will be set and write will fail. + this->io.clear(); + throw invalid_argument("Username not found!"); } @@ -20,6 +23,8 @@ User UserModel::getAfterId(int id) this->io.seekg((id - 1) * sizeof(User), this->io.beg); this->io.read(reinterpret_cast(&this->user), sizeof(User)); + this->io.clear(); + return this->user; } @@ -35,9 +40,30 @@ User UserModel::getActive() } } + this->io.clear(); + throw exception("No active user!"); } +bool UserModel::userExists(string &username) +{ + User user; + + this->io.seekg(0, this->io.beg); + + while (this->io.read(reinterpret_cast(&user), sizeof(User))) + { + if (user.username == username) + { + return true; + } + } + + this->io.clear(); + + return false; +} + void UserModel::markAs(string &status, int id) { this->getAfterId(id); @@ -51,6 +77,7 @@ void UserModel::markAs(string &status, int id) void UserModel::save() { this->io.seekp((this->user.id - 1) * sizeof(User), this->io.beg); + this->io.write(reinterpret_cast(&this->user), sizeof(User)); } @@ -81,7 +108,7 @@ void UserModel::setAttributes(map &cleanInputs) } // If there's a new user, assign created_at with the current date. - if (strlen(this->user.full_name) != 0) + if (cleanInputs.find("action")->second == "signup") { time_t t = time(nullptr); strftime(this->user.created_at, sizeof(this->user.created_at), "%c", localtime(&t)); @@ -149,6 +176,8 @@ void UserModel::setLastId() this->io.seekg((this->fileSize / sizeof(User) - 1) * sizeof(User), this->io.beg); this->io.read(reinterpret_cast(&this->user), sizeof(User)); + this->io.clear(); + this->lastId = this->user.id; } } diff --git a/app/UserModel.h b/app/UserModel.h index c8e0a1b..0b7c7d9 100644 --- a/app/UserModel.h +++ b/app/UserModel.h @@ -42,6 +42,7 @@ class UserModel : public ModelInterface { User getAfterId(int); User getActive(); + bool userExists(string &); void markAs(string &, int); void save(); void setAttributes(map &); diff --git a/app/UserRepository.cpp b/app/UserRepository.cpp index 1e6ed2a..91d2cd7 100644 --- a/app/UserRepository.cpp +++ b/app/UserRepository.cpp @@ -10,7 +10,8 @@ void UserRepository::defineValidation() { "fullname", "^(?=.*(?:[\\s\\-])([a-zA-Z]+\\s?)+)([a-zA-Z]+)(?:[\\s\\-]).*$" }, { "email", "^(?!.*[._]{2})[a-z0-9._]+@[a-z0-9]+(\\.[a-z]{1,3}){1,2}$" }, { "username", "^(?=.{7,19}$)(?![^a-zA-Z0-9])(?!.*[!_\\-\\.]{2})[a-zA-Z0-9\\.\\-_]+$" }, - { "password", "^(?=.{5,16}$)(?=.*[A-Z])(?=.*[0-9])(?=.*[!\\-_@.$#])[a-zA-Z0-9!\\-_@.$#]+$" } + { "password", "^(?=.{5,16}$)(?=.*[A-Z])(?=.*[0-9])(?=.*[!\\-_@.$#])[a-zA-Z0-9!\\-_@.$#]+$" }, + { "action", "^(?!.*\\W+)(?!.*[A-Z]+)[a-z]+$" } }; this->ValidationErrors = { @@ -34,7 +35,9 @@ void UserRepository::receiveCleanInput(map &cleanInput) { this->model.setAttributes(cleanInput); - if (cleanInput.find("fullname") == cleanInput.end()) + string action = cleanInput.find("action")->second; + + if (action == "login") { try { @@ -57,14 +60,24 @@ void UserRepository::receiveCleanInput(map &cleanInput) Controller::pushError(string(e.what())); } } + else if (action == "signup") + { + // Try finding the user and validate the request. + if (this->model.userExists(cleanInput.find("username")->second)) { + Controller::pushError(string("The username already exists!")); + } + else { + toast(string("Account created successfully! Please press -c- confirm your access to the dashboard."), string("success")); + printString("\n"); + + this->model.save(); + } + } else { - // TODO: check for user uniqueness when creating an account. - toast(string("Account created successfully! Please press -c- confirm your access to the dashboard."), string("success")); - printString("\n"); + Controller::pushError(string("Please provide a valid action!")); } - - this->model.save(); + // TODO: for a ban action, check if the current user has the according privilegies. } string &UserRepository::getAlias() diff --git a/database/users.store b/database/users.store index 14564634ba13c937e29cec004b9b504317a549d6..bbc8338d8814d2de4e92008517f9e63200c60c20 100644 GIT binary patch literal 2656 zcmeIz%?^Sv3;8SLa0 zZ~+WCV;m81%I3`@-$zBBsQNAUK1Jj*PczUw>l+RojY|uqgDxwTtu99f!kf#0`^#=! z4qh%3Y7khfG`~=*j7`Tlq4PN~EST=iOQdBLyP22mE@vFWZe0%lF3BbRE~>V)Xj(=3 U@ldxV&C9^b^OMVvuSO<6ae7t{u=QGMw(i6`Bmo-24li}f~cuR+62;O;zRD8c9LFn?DA{}p zl*(zpo^x`65SklaN+r0mcxGf-NvIXndCVbYlQP zI_yGAtMIFS$8?MdVR6Ee7*i6Bx(oi{#FoOexB0k)v**3U-X;ptrQFM!=CmzKY+Qf{|43pos3TupCWO(XUzb<#ze`<+YA4kezj3vJiV;@5G(PDxYszJ4C9^EG zt{=gvX2S0$UC;sg#pQ%05B<8l2A5N%tDP`-p#%!hWo2~k_D*J4tsK5bz2e59?0UJ2 zJ#rWPp