From e3451369e6105a9b4f688720b5a102cfd0783893 Mon Sep 17 00:00:00 2001 From: MassiveAtoms Date: Tue, 2 Jul 2019 15:40:37 -0300 Subject: [PATCH] Documentation added --- Park_time.cpp | 25 ++++++++++++++++++++--- data.cpp | 12 ++++++++++- encrypt.cpp | 10 +++++++-- headers/Customer.h | 33 +++++++++++++++++++----------- headers/Park_time.h | 22 ++++++++++++++++++++ headers/Query.h | 50 ++++++++++++++++++++++++++++++++++++++++----- headers/data.h | 7 ++++++- headers/encrypt.h | 12 +++++++++-- 8 files changed, 145 insertions(+), 26 deletions(-) diff --git a/Park_time.cpp b/Park_time.cpp index f2a4311..cd06a55 100644 --- a/Park_time.cpp +++ b/Park_time.cpp @@ -1,5 +1,13 @@ #include "headers/Park_time.h" +/* +initializes everything, id is auto incremented from what's stored in the db. +inmediately saves to db upon creation. +Also, this weird syntax is called an initializer list, and is the preffered +method of how to initialize members. It has a measurable performance increase +because it uses move semantics instead of copy semantics. +https://www.geeksforgeeks.org/when-do-we-use-initializer-list-in-c/ + */ Park_time::Park_time(int c_id, int s_id) : customer_id{c_id}, spot_id{s_id}, @@ -8,7 +16,9 @@ Park_time::Park_time(int c_id, int s_id) id{auto_increment_db() + 1} { save_db(); } - +/* +this one initializes with data from the database. should probably only be used in the query functions. + */ Park_time::Park_time(int id_, int customer_id_, int spot_id_, int start_, int duration_) : id{id_}, @@ -19,7 +29,12 @@ Park_time::Park_time(int id_, int customer_id_, int spot_id_, int start_, end = time_point(seconds(start_ + duration_)); } +/* +simple checking if customer is clocking out at the right spot. +sets end(time of clocking out) and calculates the duration. +updates the info in the database. + */ void Park_time::clock_out(int c_id, int s_id) { if (c_id != customer_id) { @@ -52,7 +67,8 @@ std::ostream& operator<<(std::ostream& os, const Park_time& pt) { os << "- - - - - - - - - - - - - - - - - - - -\n"; return os; } - +// mostly a helper function to ease the conversion from timepoint to int +// for storing in the db int Park_time::start_to_int() { auto start_to_epoch = start.time_since_epoch(); auto start_value = duration_cast(start_to_epoch); @@ -64,6 +80,9 @@ int Park_time::start_to_int() { // ----------------------------------------------------------------------------- void Park_time::save_db() { + /* + this creates a sql statement and then executes it + */ string statement{"insert into Park_time values ( , , , , , );"}; statement.insert(41, "NULL"); statement.insert(39, "NULL"); @@ -75,7 +94,7 @@ void Park_time::save_db() { data::db.exec(statement); transaction.commit(); } - +// same as above void Park_time::update_db() { string statement = "UPDATE Park_time SET end = , duration = where id = '';"; diff --git a/data.cpp b/data.cpp index 1cebaa3..f003491 100644 --- a/data.cpp +++ b/data.cpp @@ -3,15 +3,25 @@ namespace data { SQLite::Database start_db() { + /* + Opens the database, creates it if it can't find the file. + */ SQLite::Database db("test.db3", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); while (sodium_init() < 0) { std::cout << "SODIUM NOT WORKING"; + /* + This shouldn't be here, really, but I can't think of a better place + where it runs at least once. This seeds the random generator needed for + salts and other stuff, and needs to be run at least once when working + with any libsodium function. + */ } - + //sql syntax is surprisingly readable. db.exec( "create table if not exists Customer (id integer primary key, name " "text, password text, verhicle int)"); + // getting errors when using bool, so i used an int instead. db.exec( "create table if not exists Park_spot (id integer primary key, taken " "int, customer_id int)"); diff --git a/encrypt.cpp b/encrypt.cpp index 69362f9..591a2c4 100644 --- a/encrypt.cpp +++ b/encrypt.cpp @@ -1,16 +1,19 @@ #include "headers/encrypt.h" - string hash_password(string password) { /* Passing strings and converting to char* because I do not want to be forced to use char * whenever I want to call the function. Low level stuff in the function, the least possible low level stuff outside. + This uses the password hashing algorithm Argon2 implemented by libsodium. + DO NOT MODIFY memory_limit and cpu_limit after you add customers to the db. + When you do that, the hashed passwords can't be decrypted, and that would be + BAD */ const char* password_ = password.c_str(); char hashed_password_[crypto_pwhash_STRBYTES]; int memory_limit = 3.2e+7; // 3.2e7 = 32e6 = 32 mb - int cpu_limit = 1; // this is n_threads + int cpu_limit = 1; // this is n_threads int result = crypto_pwhash_str(hashed_password_, password_, @@ -23,6 +26,9 @@ string hash_password(string password) { } bool verify_password(string hashed_password, string unhashed_password) { + /* + this verifies the password. It's encryption magic and don't question it. + */ const char* password_ = unhashed_password.c_str(); const char* hashed_password_ = hashed_password.c_str(); diff --git a/headers/Customer.h b/headers/Customer.h index 6a7b072..eb91e95 100644 --- a/headers/Customer.h +++ b/headers/Customer.h @@ -9,17 +9,29 @@ using std::vector; -// will make it easy to represent it in the database while making it easy to use -// while programming +/* +enum classes make it easy to represent categories. +So you can use something like Verhicle_type::car instead of 2. but under the +hood, it's still an int. This is here so you won't have to have global variables +for these categories, or worse, use magic numbers in the code. + + */ enum class Verhicle_type { bike = 1, small_car = 2, suv = 3, pickup = 4 }; /* -card code is een randomly generated string moeten zijn, die je bv. op een nfc -card zou opslaan en zo zou authenticaten bij je parking spot. We kunnen dit ipv -of samen met een password gebruiken. clock in en out creeert en compleet een -park_time object. Voegt het toe aan een vector. +Customer constructors do the same stuff as all the other constructors. +clock_in and out create and modify park_time objects and store them to +park_instances. Technically, now that we have a working db, we don't need it. +TODO: fix this. -*/ +gen_monthly just prints out all the park_time objects in park_instances. +It should (and can safely) be removed, but it's here as a quick example of +report generation It has no logic to speak of that only generates report of +ptime objects of this month. +TODO: remove when have seperate report generation functions. + +save, update, delete and auto increment are the same as in park_time. + */ class Customer { public: @@ -27,9 +39,7 @@ class Customer { string name; string password; Customer(string name_, string password_, Verhicle_type verhicle_); - Customer(int id_, string name_, // needed to construct from db - string password_, - Verhicle_type verhicle_, // TODO: how init. p_time instances? + Customer(int id_, string name_, string password_, Verhicle_type verhicle_, vector instances); void clock_in(int s_id); void clock_out(int s_id); @@ -37,7 +47,7 @@ class Customer { void update_db(); void delete_db(); - void gen_monthly(); // remove, make it a function in data + void gen_monthly(); Verhicle_type verhicle; private: @@ -46,5 +56,4 @@ class Customer { int auto_increment_db(); }; - #endif // CUSTOMER_H \ No newline at end of file diff --git a/headers/Park_time.h b/headers/Park_time.h index 0c295d0..0b5551b 100644 --- a/headers/Park_time.h +++ b/headers/Park_time.h @@ -17,6 +17,28 @@ using std::to_string; Record of who parked at what park_spot and at what time. +public interface------------------------------------------- + +The constructors. one for creating new customers, the other one used by the +query functions to construct the object from information stored in the database. + +clock_out is the function that gets called from customer.clock_out(). +It verifies that the customer is clocking out at the correct parkspot, and saves +the current time of clocking out in end. It also calculates duration so it +doesn't have to be calculated more than once. + +operator<< is << overload, can(should) be used for report generation. + + +// implementation stuff------------------------ +start and end are time points representing when someone clocks in and out. they're from the chrono namespace. + +save and update save and update info in the database. +auto_increment pulls the highest id stored in the db, to be used in the constructor. + +start_to_int() is used to convert the start timepoint to an integer that can be saved in the database +SQL datetime and chrono datetime don't seem the most compatible. + */ class Park_time { diff --git a/headers/Query.h b/headers/Query.h index 9821878..6fb8a04 100644 --- a/headers/Query.h +++ b/headers/Query.h @@ -4,17 +4,57 @@ #include "Park_spot.h" -#include +/*these are the functions that search the database and create objects from it. + +query_parktimes_for_customer searches for the parktimes that are needed in +customer initialisaiton. generally, i see no use outside of that. + +query_customer_with_name searches for customer data by name. + +query_customer_with_id does what the above does, but with id. + + +populate_spots is used to query for all the park_spots and return them as +objects. + +The design desision to use vector instead of is for the following +reasons: + +1. some of these can potentially return more than one object. For example, 2 +customers who have the same name. + +2. I have no clue how many of you have done error handling in c++ +(try/catch/finally). +Ya boi is nice and doesn't want to bombard you with more new concepts than needed. +so now you'd do + +vector test = query_customer_with_name("Testman"); + +if (!test.size()) {print no customers found, do stuff} +else if (test.size() > 1) { do stuff to get the right one if you only need one +} + +instead of +try { + customer test = query_customer_with_name("Testman"); +} +catch(someException.probablycalled_not_found) {do_Stuff}; +catch(...) { + do stuff +} +finally{ + do more stuff +} + +3. Ya boi needs to brush up on how to create custom exceptions class, and it will complicate code furhter. + + */ vector query_parktimes_for_customer(int cid); vector query_customer_with_name(string name); Customer query_customer_with_id(int id); -// vector query_all_parking_spots(); // used for initializing the parking spots at start of the program vector populate_spots(); - - - #endif // CUSTOMER_H \ No newline at end of file diff --git a/headers/data.h b/headers/data.h index c6855b4..502106c 100644 --- a/headers/data.h +++ b/headers/data.h @@ -5,8 +5,13 @@ #include "encrypt.h" namespace data { -SQLite::Database start_db(); +/* +start_db is the function that opens the database, and +if the necesary tables are not there, creates them. +db is the database, and is static to avoid multiple redefinition errors. + */ +SQLite::Database start_db(); static SQLite::Database db = start_db(); } // namespace data diff --git a/headers/encrypt.h b/headers/encrypt.h index 40169b0..8377ddc 100644 --- a/headers/encrypt.h +++ b/headers/encrypt.h @@ -2,12 +2,20 @@ #define ENCRYPT_H #pragma once -#include #include -#include #include +#include +#include using std::string; +/* +hash_password takes the password, and encrypts it. This needs to be done, +because storing passwords in plaintext is BAD! + +verify_password takes in a password and the hashed password, and then does magic encryption stuff(no, not +really. It basically hashes the password with the same salt and other +parameters) and to see if the password stored and the given password match. + */ string hash_password(string password); bool verify_password(string hashed_password, string unhashed_password);