def __init__(self): """Adds arguements to the request. Verify a user's key, and connects to the database.""" password = Database.getPassword() parser = reqparse.RequestParser() parser.add_argument("con1", type=str) parser.add_argument("key", type=str, location="headers") parser.add_argument("user", type=str, location="headers") self.parsed = parser.parse_args() key, user = self.parsed["key"], self.parsed["user"] if key == None or user == None: abort(406, message="Either the key, or user field is left blank.") Key().verifyKey(user, key) """A redirect table of some sort is needed. Refer to testing.redirect for a guide.""" try: self.conn, self.cursor = Database.connect("localhost", "root", password[0], "testing") self.schema = "testing" except Exception: self.conn, self.cursor = Database.connect("localhost", "root", password[1], "tsc_office") self.schema = "tsc_office"
def __init__(self): """Handles initialization, and connects to the database""" password = Database.getPassword() try: self.conn, self.cursor = Database.connect("localhost", "root", password[0], "testing") self.schema = "testing" self.table = "images" except Exception: self.conn, self.cursor = Database.connect("localhost", "root", password[1], "tsc_office") self.schema = "tsc_office" self.table = "timages" parser = reqparse.RequestParser() parser.add_argument("image", type=FileStorage, location="files") self.parsed = parser.parse_args() try: path = "../src/images/" os.chdir(path) print("CHANGED PATH") except Exception: pass
def __init__(self): """Connects to the MySQL database""" try: self.tap, self.cursor = Database.connect("localhost", "root", "8811967", "tsc_office") except NotFound: self.tap, self.cursor = Database.connect("localhost", "root", "YJH030412yjh_g", "tsc_office")
def get(self, user, hash): """ GET request works perfectly well. GET requests are done via the url. Take a look at the adding resources section for more information --- # Parameters ### user The user's name ### hash The string of characters to-be encrypted. """ hashed = Hash.encrypt(hash) tableColumns = "fid, fuser, fpassword, flocation, finvoice, fcomplaint, ffinance, fpersonnel, femail, fcc, ffunction, fleave, fhr, froadtax, ftr, forder, fsalesman, ftele, fwarehouse, fpotato, fcsr, fconnect, fdriver, fdo, fcollection, femp, fic, DATE_FORMAT(findate, \"%Y-%m-%d\") AS findate, DATE_FORMAT(findate, \"%Y-%m-%d\") AS fconfirmdate, fpic, fplace, fname, fwarehouselog, fdsr, fvvip" sqlQuery = f"SELECT {tableColumns} FROM {self.schema}.tap WHERE fuser=\'{user}\' AND fpassword=\'{hashed}\'" self.cursor.execute(sqlQuery) res = self.cursor.fetchall() # Formatted to give the text output, a tuple of data. Previous a list of a tuple. if len(res) == 0: return {404: {"error": "Either the username, or password is incorrect."}} keyValuePairs = Database().keyValuePairing(self.cursor, res) return [{"success": keyValuePairs}]
def __dataProcessing(self) -> Union[list, None]: """Fetchs all entries that are at most 3 days old from the current date.""" sqlString = f"SELECT * FROM {self.schema}.{self.table} WHERE salesperson = '{self.person}' and fbydate >= CURDATE() - INTERVAL 3 day" # This causes an extra element in a tuple in a list self.sqlCursor.execute(sqlString) resSql = self.sqlCursor.fetchall() try: liteString = f"SELECT * FROM `transaction` WHERE salesperson = '{self.person}' and fbydate >= date('now', '-3 days')" self.liteCursor.execute(liteString) resLite = self.liteCursor.fetchall() except Exception as e: print(e) abort(404, message="SQLite3 table not found.") if len(resSql) == len(resLite) and (len(resLite) != 0): abort(403, message="Cannot make duplicate entries.") elif len(resLite) == 0: abort(403, message="You have zero entries.") resSql = Database().formatEntries(resSql) valid = [lite for lite in resLite if lite not in resSql] return valid
def __init__(self): """ Handles initilization, and connects to a MySQL database on the server, as well as, a local SQLite database. """ password = Database().getPassword() try: self.sqlConn, self.sqlCursor = Database.connect( "localhost", "root", password[0], self.schema) self.schema = "testing" self.table = "trans" except TYPE_INTERFACE_ERROR: self.sqlConn, self.sqlCursor = Database().connect( "localhost", "root", password[1], "tsc_office") self.schema = "tsc_office" self.table = "" """ These are the arguments the Sync endpoint will accept. If a request is sent through postman (Google it if you don't know what it is), it doesn't matter if its from the 'Params' tab or a 'Body' tab. The only difference is the parameters will show up in the url if you choose 'Params', and it won't shop up if you choose 'Body' """ parser = reqparse.RequestParser() parser.add_argument("key", type=str, location='headers') parser.add_argument("user", type=str, location='headers') parsed = parser.parse_args() key, user = parsed["key"], parsed["user"] verified = Key().verifyKey(user, key) # add key, user abort(406, message="Invalid credentials", code=406, inside="sync.py") if verified == False else "" try: sqliteDb = "env-api\\endpoints\\databases\\syncDb.db" # Path to the local SQLite database stored in the device. self.liteCon = sqlite3.connect(sqliteDb) print("connecting to sqlite3") os.chdir("..\\env-api\\endpoints\\databases") PATH = os.getcwd() + "\\syncDb.db" self.liteCon = sqlite3.connect(PATH) self.liteCursor = self.liteCon.cursor() except FileNotFoundError as e: error = e.strerror abort(400, message=f"{error}. One should be created now. Try again.")
def __init__(self): """Handles initilization, and connects to a MySQL database.""" self.schema = "tsc_office" try: self.mydb, self.cursor = Database().connect("localhost", "root", "YJH030412yjh_g", self.schema) except ProgrammingError: self.mydb, self.cursor = Database().connect("localhost", "root", "8811967", self.schema) # abort(503, message="Unable to connect to database.") parser = reqparse.RequestParser() parser.add_argument("key", type=str, location='headers') parser.add_argument("user", type=str, location='headers') parsed = parser.parse_args() key, user = parsed["key"], parsed["user"] verified = Key().verifyKey(user, key) abort(404, message="Invalid credentials.") if verified == False else ""
def __init__(self): password = Database.getPassword() self.schema = "tsc_office" try: self.conn, self.cursor = Database.connect("localhost", "root", password[0], self.schema) except Exception: self.conn, self.cursor = Database.connect("localhost", "root", password[1], self.schema) parser = reqparse.RequestParser() parser.add_argument("key", type=str, location='headers') parser.add_argument("user", type=str, location='headers') parsed = parser.parse_args() key, user = parsed["key"], parsed["user"] Key().verifyKey(user, key)
def get(self): """Processes the GET request""" self.__info() try: self.conn, self.cursor = Database.connect("localhost", "root", "YJH030412yjh_g", "tsc_office") except Exception: self.conn, self.cursor = Database.connect("localhost", "root", "8811967", "tsc_office") except Exception: abort(404, "The table tlocations is not found. Please create it.") sql_query = f"SELECT * FROM tsc_office.tlocations" self.cursor.execute(sql_query) results = self.cursor.fetchall() if len(results) == 0: abort(404, message=f"Location does not exist", code="404") names = [] lat_one = [] lon_one = [] lat_two = [] lon_two = [] for result in results: names.append(result[0]) lat_one.append(result[1]) lon_one.append(result[2]) lat_two.append(result[3]) lon_two.append(result[4]) response = { "name": names, "lat_one": lat_one, "lon_one": lon_one, "lat_two": lat_two, "lon_two": lon_two } return response
def __init__(self): self.schema = "testing" self.table = "creds" try: self.keyTable, self.keyCursor = Database.connect( "localhost", "root", "YJH030412yjh_g", self.schema) except ProgrammingError as err: abort( 503, message="Unable to connect to database. Check your credentials." )
def get(self, invoiceNumber: str): """Processes the GET request. Gets all information of a specific invoice by referencing via invoice number. --- # Parameteres ### invoiceNumber Invoice number of an invoice. """ if invoiceNumber.lower() == "all": sqlQuery = f"SELECT * FROM {self.schema}.tinvoicehistory LIMIT 10" self.cursor.execute(sqlQuery) res = self.cursor.fetchall() formattedRes = Database().formatEntries(res) return {200: {"success": formattedRes}} columnOne = "fno, finvoiceno, DATE_FORMAT(fdate, \"%Y-%m-%d\") AS fdate, fdesc, frefno, fterm, DATE_FORMAT(fduedate, \"%Y-%m-%d\") AS fduedate, fnettotal, fpaymentamt, foutstanding, fcancelled, DATE_FORMAT(ftimestamp, \"%Y-%m-%d %H:%i:%s\") AS ftimestamp, fuserid" columnTwo = f"{columnOne}, fusername, fdebtorcode, fcompanyname, ftype, fsalesagent, fsalesagentdesc, fcreditlimit" columnThree = f"{columnTwo}, fpendingdelivery, DATE_FORMAT(fdeliverydate, \"%Y-%m-%d\") AS fdeliverydate, florryno, fdriver, fhelper1, fhelper2, fhelper3, froute, fpod" columnFour = f"{columnThree}, fcomment, fstatus, fextraattempt, fverified, DATE_FORMAT(fverifiedtimestamp, \"%Y-%m-%d %H:%i:%s\") AS fverifiedtimestamp, fverifiedby, tinvoicehistorycol, fcrates, ftimeout, ftimein, fcycletime, fcollection" columnName = columnFour sqlQuery = f"SELECT {columnName} FROM {self.schema}.tinvoicehistory WHERE finvoiceno = '{invoiceNumber}'" self.cursor.execute(sqlQuery) res = self.cursor.fetchall() if len(res) == 0: abort(404, message= f"Entry with invoice number: '{invoiceNumber}' not found") elif len(res) > 1: formattedRes = Database().toSerialisable(res) return {200: formattedRes} formattedRes = Database().formatEntries(res) keyValuePairOfFormattedRes = Database().keyValuePairing( self.cursor, formattedRes) return {200: keyValuePairOfFormattedRes}
def __init__(self): """Handles initialization and connects to a MySQL database.""" password = Database().getPassword() try: self.conn, self.cursor = Database.connect("localhost", "root", password[0], "testing") self.schema = "testing" except Exception: self.conn, self.cursor = Database.connect("localhost", "root", password[1], "tsc_office") self.schema = "tsc_office" parser = reqparse.RequestParser() parser.add_argument("key", type=str, location="headers") parser.add_argument("user", type=str, location="headers") parsed = parser.parse_args() key, user = parsed["key"], parsed["user"] Key().verifyKey(user, key) self.BASE_QUERY = f"SELECT * FROM {self.schema}.spec" """
def __init__(self): """Handles initialization, connects to database""" password = Database().getPassword() self.schema = "testing" parser = reqparse.RequestParser() parser.add_argument("user", type=str, location="headers") parser.add_argument("key", type=str, location="headers") parser.add_argument("change", type=str) parser.add_argument("previous", type=str) self.parsed = parser.parse_args() user, key = self.parsed["user"], self.parsed["key"] """Verify user""" K = Key() K.verifyKey(user, key) try: self.conn, self.cursor = Database().connect( "localhost", "root", password[0], self.schema) except Exception: self.conn, self.cursor = Database().connect( "localhost", "root", password[1], self.schema)
def __insertStatement(self, values: list) -> None: """Creates an insert statement from a list of values, and with the column names with a sql cursor --- # Parameters ### values The list of values to be used in the insert statement. --- # Example ```python3 values = ["one", "two", "three"] result = self.__insertStatement(values) print(result) # "INSERT INTO schema.table (`number1`, `number2`, `number3`) VALUES ("one", "two", "three")" ``` Again this is a private method, and cannot be used outside of the class. """ columns = Database.columnNamesForInsert(self.sqlCursor) quotedValues = self.__join(*values) sqlQuery = f"INSERT INTO {self.schema}.{self.table} ({columns}) VALUES ({quotedValues})" self.sqlCursor.execute(sqlQuery) self.sqlConn.commit()
class Sync(Resource): """This class handles syncing data between a MySQL database hosted on the server, and a local SQLite3 database hosted on the mobile application. --- # Functions ### public - __init__ - put ### private - __join - __dataProcessing - __updateCounter - __insertStatement """ def __init__(self): """ Handles initilization, and connects to a MySQL database on the server, as well as, a local SQLite database. """ password = Database().getPassword() try: self.sqlConn, self.sqlCursor = Database.connect( "localhost", "root", password[0], self.schema) self.schema = "testing" self.table = "trans" except TYPE_INTERFACE_ERROR: self.sqlConn, self.sqlCursor = Database().connect( "localhost", "root", password[1], "tsc_office") self.schema = "tsc_office" self.table = "" """ These are the arguments the Sync endpoint will accept. If a request is sent through postman (Google it if you don't know what it is), it doesn't matter if its from the 'Params' tab or a 'Body' tab. The only difference is the parameters will show up in the url if you choose 'Params', and it won't shop up if you choose 'Body' """ parser = reqparse.RequestParser() parser.add_argument("key", type=str, location='headers') parser.add_argument("user", type=str, location='headers') parsed = parser.parse_args() key, user = parsed["key"], parsed["user"] verified = Key().verifyKey(user, key) # add key, user abort(406, message="Invalid credentials", code=406, inside="sync.py") if verified == False else "" try: sqliteDb = "env-api\\endpoints\\databases\\syncDb.db" # Path to the local SQLite database stored in the device. self.liteCon = sqlite3.connect(sqliteDb) print("connecting to sqlite3") os.chdir("..\\env-api\\endpoints\\databases") PATH = os.getcwd() + "\\syncDb.db" self.liteCon = sqlite3.connect(PATH) self.liteCursor = self.liteCon.cursor() except FileNotFoundError as e: error = e.strerror abort(400, message=f"{error}. One should be created now. Try again.") def __join(self, *values: list) -> Union[str, int]: """ Strips all whitespace in front, and after the conditions. To make it cleaner, spaces between words will not be stripped. Add quotes to all values, then joins them all with ", " between each word. --- # Parameters ### values The list of values that you wish to form into a string. --- # Example ```python3 values = ["one", "two", "three"] result = self.__join(values) print(result) # "one, two, three" ``` Keep in mind that this is a private method, so you cannot call it outside of the class. """ strippedValues = [ str(value).strip() for value in values if len(str(value).strip()) != 0 ] quotedValues = [f"'{value}'" for value in strippedValues] joinedValues = (", ").join(quotedValues) return joinedValues def put(self, salesperson): """Processes the PUT request. And syncs the data between the user's sqlite table, and the server's MySQL table. --- # Parameters ### salesperson The client's id. This id is used to sync entries for that specific client. """ self.person = salesperson valid = self.__dataProcessing() list(map(self.__insertStatement, valid)) self.__updateCounter() return [{201: f"Successfully synced."}] def __dataProcessing(self) -> Union[list, None]: """Fetchs all entries that are at most 3 days old from the current date.""" sqlString = f"SELECT * FROM {self.schema}.{self.table} WHERE salesperson = '{self.person}' and fbydate >= CURDATE() - INTERVAL 3 day" # This causes an extra element in a tuple in a list self.sqlCursor.execute(sqlString) resSql = self.sqlCursor.fetchall() try: liteString = f"SELECT * FROM `transaction` WHERE salesperson = '{self.person}' and fbydate >= date('now', '-3 days')" self.liteCursor.execute(liteString) resLite = self.liteCursor.fetchall() except Exception as e: print(e) abort(404, message="SQLite3 table not found.") if len(resSql) == len(resLite) and (len(resLite) != 0): abort(403, message="Cannot make duplicate entries.") elif len(resLite) == 0: abort(403, message="You have zero entries.") resSql = Database().formatEntries(resSql) valid = [lite for lite in resLite if lite not in resSql] return valid def __updateCounter(self) -> None: """Updates the hidden element `counter` from 0 to 1 then to 2. When `counter` is set from 0 to 1, nothing seems wrong on the surface. If it goes to 2 from 1, it's absolutely valid.""" liteQuery = f"UPDATE `transaction` SET counter = '1' WHERE counter = '0' AND salesperson = '{self.person}' AND fbydate >= date('now', '-3 day')" self.liteCursor.execute(liteQuery) self.liteCon.commit() sqlQuery = f"UPDATE {self.schema}.{self.table} SET counter = '1' WHERE counter = '0' AND salesperson = '{self.person}' AND fbydate >= CURDATE() - INTERVAL 3 day" self.sqlCursor.execute(sqlQuery) self.sqlConn.commit() liteQuery = f"UPDATE `transaction` SET counter = '2' WHERE counter = '1' AND salesperson = '{self.person}' AND fbydate >= date('now', '-3 day')" self.liteCursor.execute(liteQuery) self.liteCon.commit() sqlQuery = f"UPDATE {self.schema}.{self.table} SET counter = '2' WHERE counter = '1' AND salesperson = '{self.person}' AND fbydate >= CURDATE() - INTERVAL 3 day" self.sqlCursor.execute(sqlQuery) self.sqlConn.commit() def __insertStatement(self, values: list) -> None: """Creates an insert statement from a list of values, and with the column names with a sql cursor --- # Parameters ### values The list of values to be used in the insert statement. --- # Example ```python3 values = ["one", "two", "three"] result = self.__insertStatement(values) print(result) # "INSERT INTO schema.table (`number1`, `number2`, `number3`) VALUES ("one", "two", "three")" ``` Again this is a private method, and cannot be used outside of the class. """ columns = Database.columnNamesForInsert(self.sqlCursor) quotedValues = self.__join(*values) sqlQuery = f"INSERT INTO {self.schema}.{self.table} ({columns}) VALUES ({quotedValues})" self.sqlCursor.execute(sqlQuery) self.sqlConn.commit()
class Update(Resource): """ # Important This endpoint has not been used or maintained in a long time due to lack of use. Updates the MySQL database to reflect changes # Functions - __init__ - post """ def __init__(self): """Handles initialization, connects to database""" password = Database().getPassword() self.schema = "testing" parser = reqparse.RequestParser() parser.add_argument("user", type=str, location="headers") parser.add_argument("key", type=str, location="headers") parser.add_argument("change", type=str) parser.add_argument("previous", type=str) self.parsed = parser.parse_args() user, key = self.parsed["user"], self.parsed["key"] """Verify user""" K = Key() K.verifyKey(user, key) try: self.conn, self.cursor = Database().connect( "localhost", "root", password[0], self.schema) except Exception: self.conn, self.cursor = Database().connect( "localhost", "root", password[1], self.schema) def post(self, salesperson): """Handles the POST request --- # Parameters ### salesperson The id of the salesperson """ self.cursor.execute( f"SELECT * FROM {self.schema}.trans WHERE salesperson = {salesperson}" ) res = self.cursor.fetchall() if len(res) == 0: abort( 404, message= f"The entry with the id of {salesperson} doesnt not exist. Check if you had a typo." ) self.change, self.prev = self.parsed["change"], self.parsed["previous"] try: sqlQuery = f"UPDATE {self.schema}.trans SET fbydate = '{self.change}' WHERE fbydate = '{self.prev}'" self.cursor.execute(sqlQuery) self.conn.commit() except (TYPE_DATA_ERROR, TYPE_PROGRAMMING_ERROR): abort( 400, message= "Make sure your date format is in YYYY-MM-DD. i.e. 2021-01-01 not 2021-1-1" ) return {200: "New Entry Added"}
def put(self, table: str, invoiceno: str) -> dict: """Takes your role into account. If your role is not within the dictionary, a forbidden error is thrown. --- # Parameters ### table The name of the table you wish to make edits to ### Invoiceno (temporary) The invoice number to reference whcih invoice you wish to edit. --- # Exceptions - ProgrammingError: Occurs when trying to connect to a database with invalid credentials """ wheres = { "tinvoicehistory": "`finvoiceno`", "tdebtordetail": "`debtorcode`" } if table not in wheres: abort(404, message=f"table with the name of {table} not found.") con1 = self.parsed["con1"] conditionals = con1.split("|") values = self.__validateDatabase(self.cursor, table) columnNames = values.split("(")[1].split(",") numberOfColumns = len(columnNames) formattedColumnNames = [ columnName.strip(")").strip() for columnName in columnNames ] joinedColumnNames = (", ").join(formattedColumnNames) try: redirConn, redirCursor = Database.connect( "localhost", "root", "YJH030412yjh_g", self.schema) # Change database except Exception: redirConn, redirCursor = Database.connect("localhost", "root", "8811967", self.schema) silentQuery = f"SELECT * FROM testing.{table} LIMIT 1" redirCursor.execute(silentQuery) res = redirCursor.fetchall() if len(res) == 0: abort( 404, message= f"The table {table} does not exist, check your spelling, and try again." ) lengthOfGivenValues, quotedValues = self.__join(*conditionals) if numberOfColumns > lengthOfGivenValues: abort( 406, message= f"You are required to fill a total of {numberOfColumns} but you have only entered in {lengthOfGivenValues}. Please fill up all the fields and then try again." ) if invoiceno != "n": formattedColumnNamesForUpdate = Database.forUpdate( joinedColumnNames, quotedValues) sqlQuery = f"UPDATE {self.schema}.{table} SET {formattedColumnNamesForUpdate} WHERE {wheres[table]} = '{invoiceno}'" else: sqlQuery = f"INSERT INTO {self.schema}.{table} ({joinedColumnNames}) VALUES ({quotedValues})" """Uncomment (remove the hashtags from) the next two lines when the prerequisites have been setup.""" redirCursor.execute(sqlQuery) redirConn.commit() return {201: "successfully added a new entry.", "query": sqlQuery}
def get(self, table: str, o1: Union[str, int], o2: Union[str, int], o3: Union[str, int], o4: Union[str, int], o5: Union[str, int]) -> str: """Collects all the parameters into a list. Then filters out unwanted values. --- # Parameters ### o1 - o5 The parameters you want to use in the SQL statement. """ initialParams = [o1, o2, o3, o4, o5] filteredParams = list(filter(self.removeNone, initialParams)) # removes all empty values ("n") noneIndices = [i for i, v in enumerate(initialParams) if v == "n"] noneIndices.sort(reverse=True) # Reverse it so that when deleting values from lists, via indices the program won't throw an IndexError exception """Makes a request to the SQL database which returns None intentionally, as this is required in order to get the column names""" silent = f"{self.BASE_QUERY} WHERE table_name = 'silent'" self.cursor.execute(silent) _ = self.cursor.fetchall() """The actual query to be made, to get the associated SQL query to get data for that specific table.""" sqlQuery = f"{self.BASE_QUERY} WHERE table_name = '{table}'" self.cursor.execute(sqlQuery) res = self.cursor.fetchall() desc = self.cursor.description """Starts from the 2nd index, because the first two column names are: table_name and sql. Which is not needed.""" names = [des[0] for des in desc][2:] parameters = {k: v for k, v in zip(names, filteredParams)} if len(res) == 0: abort(404, message = f"Table with the name {table} does not exist. Check your spelling, and try again.") formattedRes = Database().toSerialisable(res) conditionals = list(filter(self.removeNone, formattedRes[0]))[2:] """Deletes unneeded parameters from the list so it won't be added into a SQL query.""" for i in noneIndices: del conditionals[i] keyValuePairs = {k: v for k, v in zip(filteredParams, conditionals)} whereQuerySnippets = [] for value, k in zip(filteredParams, parameters): con, v = keyValuePairs[value], parameters[k] whereQuerySnippets.append(f"{con} = '{v}'") stitchedWhereQuery= (" AND ").join(whereQuerySnippets) stitchedQuery = f"SELECT * FROM {self.schema}.{table} WHERE {stitchedWhereQuery}" """The part where the api makes another SQL query on your behalf""" _ , redirCursor = Database.connect("localhost", "root", "YJH030412yjh_g", "{self.schema}") redirCursor.execute(stitchedQuery) redirRes = redirCursor.fetchall() lengthOfRedirRes = len(redirRes) """Handles the part with more than one result""" if lengthOfRedirRes > 1: tempConn, tempCursor = Database.connect("localhost", "root", "YJH030412yjh_g", "{self.schema}") silent = tempCursor.execute(f"SELECT * FROM {self.schema}.trans LIMIT 1") res = tempCursor.fetchall() if len(res) == 0: abort(404, message = "Table not found.") serialisedRedirRes = Database().formatEntries(redirRes) return serialisedRedirRes elif lengthOfRedirRes == 0: abort(404, message = "No entries with the specified information found.") serialisedRedirRes = Database().formatEntries(redirRes) """Makes a key value pair to the appriroiate value. For it to be clearer.""" keyValuePairOfSerialisedRedirRes = Database().keyValuePairing(redirCursor, serialisedRedirRes) return keyValuePairOfSerialisedRedirRes