class SignUp(Resource): signup_marshaller = { "success": fields.Integer, } def __init__(self, bcrypt): self.db = Database() self.db.connect() self.bcrypt = bcrypt def get(self): headers = {"Content-Type": "text/html"} return make_response(render_template("signup.html"), 200, headers) @marshal_with(signup_marshaller) def post(self ): # NOTE that this is actually using username and not userId... print( "POOOOSTTTTTTTTTTTT TOOOOOOOOOOOO SIIIIIIIIGGGGGGGGGGGGGNNNNNNNNUUUUUUUUUPPPPPPP" ) # define args to accepts from post parser = reqparse.RequestParser() parser.add_argument("username", type=str) parser.add_argument("password", type=str) parser.add_argument("email", type=str) parser.add_argument("name", type=str) args = parser.parse_args() # check if user exists and verify their password username = args["username"] userId = self.db.nameToId(username) password = args["password"] email = args["email"] name = args["name"] if self.db.userExists(userId): #userId belongs to someone else return {"success": 0} hashword = self.bcrypt.generate_password_hash(password) user = self.db.addUser(name, username, email, hashword.decode("utf-8")) if user is not None: return {"success": 1} return {"success": 0} # something went wrong
class Backend: """ Class that contains all the logistics of manipulating widgets and data. TODO: FINISH DOCUMENTATION """ def __init__(self, app, window): # Application (front end) instance self.app = app # Root window instance from the main app self.window = window # Instantiate database object self.db = Database('Database1.db') # Connect to utilities self.utils = Utils() # Get access to scripts self.scripts = Scripts.Scripts(self.db) # The limit to number of records in the Customer table # Warning: If you increase limit, need to add more names in names.txt self.recordLimit = 1000 # Current user username self.user = '' # Current user's permissions in the application self.permissions = {} # Email setting self.email = False def login(self, user_username, user_password, response_msg): """ Function to validate user credentials and allow access if they exist and match in the user Table in the database. :param user_username: Entered username as string :param user_password: Entered password as string :param response_msg: The label instance to provide feedback to user :return: Successfulness of function """ # No input if user_username == '' and user_password == '': return # Check username and password response = self.db.validateUserLoginCredentials( user_username, user_password) # Username and password did not match if len(response) == 0: response_msg.set('That username and password did not match.') return False # Get permissions of user self.permissions = self.db.getPermissions(user_username) # User has a record in user table but permissions have not been set if len(self.permissions) < 1: response_msg.set('Please contact the administrator') return False # If its admin, go to admin menu if user_username == 'admin': self.user = user_username self.app.adminMenu() return True else: # Allow login if user has permission if self.permissions['login'] == 1: self.user = user_username self.app.customerMenu() else: response_msg.set('Cannot log you in.') return False return True def checkEmailExists(self, email, check_msg): """ This function takes in the StringVar() object from the email label and checks if there exists such an email in the database. It then returns the response by manipulating the check_msg StringVar() object. :param email: :param check_msg: :return: """ if email.get() == '': check_msg.set('Enter an email.') return False data = self.db.getCustomerInfo(email.get()) if len(data) < 1: output = "Email OK" check_msg.set(output) return False else: output = "That email already exists." check_msg.set(output) return True def getCustomerInfo(self, email, cust_list, delete_btn): """ Function to get customer data from the Customer Relation using the primary key, email. :param email: The customer's unique email -> str :param cust_list :param delete_btn :return: Successfulness of function -> boolean """ if email is '': return False delete_btn['state'] = 'disabled' data = self.db.getCustomerInfo(email) # Clear widget of any text cust_list.delete(0, 'end') if data is False: output = "Something went wrong." cust_list.insert(1, output) return False # Check if email exists in db if len(data) < 1: output = "That email does not exist." cust_list.insert(1, output) return False # Convert all data to strings stringData = self.utils.convertToStrings(list(data[0])) customerTableAttributes = [ 'Email: ', 'Password: '******'First name: ', 'Last name: ', 'Country: ', 'Region: ', 'Address: ', 'Postal Code: ', 'Balance: ', 'Preferred card: ', 'Rating: ', 'Status: ', 'Cycle date: ', 'Subscription Type: ', 'Birthday: ' ] for i, value in enumerate(stringData): if value is None: continue if customerTableAttributes[i] is 'Region: ': value = self.db.getErnameFromEruid(value)[0][0] output = customerTableAttributes[i] + value cust_list.insert(i, output) delete_btn['state'] = 'normal' return True def addCustomer(self, email, pword, fname, lname, country, region, address, feedback_msg, dob, check_msg, limit_current_msg): """ This function takes in the StringVar() objects, and Combobox() object, from the root window and uses them to get the values stored inside. If entries are valid, customer record is added and entry fields are then made empty to clean up the window. if entries are invalid, feedback_msg is updated with corresponding issues. True = Success False = Issue :param email: :param pword: :param fname: :param lname: :param country: :param region: :param address: :param feedback_msg: :param dob: :param check_msg: :param limit_current_msg: :return: Successivefulness of function """ supportedCountries = ['Canada'] inputList = [email, pword, fname, lname, country, region, address, dob] inputIntoListOfStrings = [ email.get(), pword.get(), fname.get(), lname.get(), country.get(), region.get(), address.get(), dob.get() ] data = self.db.getEruidFromErname(region.get()) if data is False: feedback_msg.set('Something wrong with region name') return False nbCurrentCustomers = self.db.selectNumberOfCustomerRecords()[0][0] outputIssue = 'Issues:\n\n' outputIssue1 = '' outputIssue2 = '' outputIssue3 = '' outputIssue4 = '' outputIssue5 = '' outputIssue6 = '' issues = 0 if nbCurrentCustomers >= self.recordLimit: issues += 1 outputIssue1 = ' ' + str(issues) + '. ' + str( self.recordLimit) + ' Record limit reached.\n' if self.checkEmailExists(email, feedback_msg): issues += 1 outputIssue2 = ' ' + str( issues) + '. That email already exists.\n' if self.utils.checkForEmptyStrings(inputIntoListOfStrings): issues += 1 outputIssue3 = ' ' + str( issues) + '. There cannot be an empty field.\n' if country.get() not in supportedCountries: issues += 1 outputIssue4 = ' ' + str(issues) + '. Country not selected.\n' if len(data) == 0: issues += 1 outputIssue5 = ' ' + str(issues) + '. Region not selected.\n' else: eruid = data[0][0] if not self.utils.isValidDate(dob.get()): issues += 1 outputIssue6 = ' ' + str( issues) + '. Not a valid date (yyyy-mm-dd).\n' # If no issues, insert into db, provide success message, and clear text fields. if issues == 0: if self.db.insertCustomer(email.get(), pword.get(), fname.get(), lname.get(), country.get(), eruid, address.get(), dob.get()): for strvar in inputList: strvar.set('') check_msg.set('') feedback_msg.set('Customer successively added.') nbCurrentCustomers = self.db.selectNumberOfCustomerRecords( )[0][0] limit_current_msg.set('Limit: ' + str(self.recordLimit) + ' ' + 'Current: ' + str(nbCurrentCustomers)) return True else: feedback_msg.set(outputIssue + outputIssue1 + outputIssue2 + outputIssue3 + outputIssue4 + outputIssue5 + outputIssue6) return False def deleteCustomer(self, cust_list, confirmWindow): """ Function to delete the selected customer in cust_list listbox. :param cust_list: The listbox() object with the customer data :return: Successfulness of function """ valueInCustList = cust_list.get(0) cust_list.delete(0, 'end') if 'Email' not in valueInCustList: cust_list.insert( 0, 'Search an existing customer first in order to delete') return False valueSplit = valueInCustList.split(': ') email = valueSplit[1] if self.db.deleteCustomer(email): cust_list.insert(0, 'Customer successively deleted') confirmWindow.destroy() return True else: cust_list.insert( 0, 'Something went wrong. Customer could not be deleted.') return False def deleteAllCustomers(self, cust_list, confirmWindow): """ Function to delete all customers in cust_list listbox. :param cust_list: The Listbox() object with customer data. :return: Successfulness of function """ cust_list.delete(0, 'end') if self.db.deleteAllCustomers(): cust_list.insert(0, 'All customers successively deleted') confirmWindow.destroy() return True else: cust_list.insert( 0, 'Something went wrong. Customers could not be deleted.') return False def autoCompleteEmail(self, autoCompleteList, user_input): """ Function to populate dropdown list with emails that begin with the string in user_input. :param autoCompleteList: A tkinter listbox :param user_input: The string given by the user :return: """ # Hide and clear widget of any text autoCompleteList.delete(0, 'end') autoCompleteList.place_forget() # Do nothing if input is empty if user_input is '': return # Get emails that begin with user_input string data = self.db.emailsBeginningWith(user_input) # If there are no emails. Do nothing if len(data) < 1: return # Populate list for i, email in enumerate(data): autoCompleteList.insert(i, email) # Display list autoCompleteList.place(x=230, y=90) return True def selectFromAutoComplete(self, autoCompleteList, user_input_field): """ Function to populate the user_input_field, which is an entry, with the email selected by the user. The email is selected from the autoCompleteList listbox object. :param autoCompleteList: A listbox containing emails :param user_input_field: The entry field for searching customers :return: """ # Ensure 1 and only 1 email is selected from list clicked_items = autoCompleteList.curselection() if len(clicked_items) > 1 or len(clicked_items) < 1: return False # Get email from list clicked_item_index = clicked_items[0] selected_email = autoCompleteList.get(clicked_item_index)[0] # Set entry value to email user_input_field.set(selected_email) # Hide listbox autoCompleteList.place_forget() return True def updateCustomer(self, attribute, user_input, email, editWindow, cust_list, delete_btn): """ Function to update customer record data that user has input through edit window. :param attribute: :param user_input: :param email: :param editWindow: :param cust_list: :param delete_btn: :return: """ if user_input == '': return # Dictionary mapping of the column names to their front end equivalent name attributes = { 'Email': 'email', 'Password': '******', 'First name': 'fname', 'Last name': 'lname', 'Country': 'country', 'Region': 'region', 'Address': 'address', 'Postal Code': 'postalcode', 'Balance': 'balance', 'Preferred card': 'preferredcard', 'Rating': 'rating', 'Status': 'status', 'Cycle date': 'cycledate', 'Subscription Type': 'typename', 'Birthday': 'bday', } # Get column name from front end equivalent name attribute = attributes[attribute] # Update customer data data = self.db.updateCustomer(attribute, user_input, email) if data is False: print('Could not update customer info.') return False self.getCustomerInfo(email, cust_list, delete_btn) self.app.confirmEditWindow(editWindow) return True def enableEditBtn(self): """ Function to enable edit button if user selects one and only one item in the list box. :return: """ edit_btn = self.window.nametowidget('edit_btn') list_box = self.window.nametowidget('datalist') # Check if selected more than 1 item or no items clicked_items = list_box.curselection() if len(clicked_items) > 1 or len(clicked_items) < 1: return False clicked_item_index = clicked_items[0] selected_info = list_box.get(clicked_item_index) if 'Email' in selected_info: return if ':' in selected_info: edit_btn['state'] = 'normal' self.window.update() return True def disableEditBtn(self): """ Function to disable edit button in customer menu :return: """ edit_btn = self.window.nametowidget('edit_btn') edit_btn['state'] = 'disabled' self.window.update() return def generateRandomCustomers(self, number_input, feedback_msg, limit_current_msg): """ Generates random customer records equal to the number_input argument. This uses the generateCustomers() script. :param number_input: The number of records to generate :param feedback_msg: The StringVar() object from the gui :param limit_current_msg: :return: Successfulness of function """ # Computation in progress feedback message feedback_msg.set('Generating...') self.window.update() number_input_String = number_input.get() number_input_String = number_input_String.lstrip('0') if number_input_String.isdigit(): number_input_Int = int(number_input.get()) else: feedback_msg.set('Please enter a number.') return False if number_input_Int < 1: feedback_msg.set('Please enter a value greater than 0.') return False response, currentRecords = self.scripts.generateCustomers( number_input_Int, self.recordLimit) if response == 'Success': feedback_msg.set(number_input_String + ' records successively generated.') number_input.set('') limit_current_msg.set('Limit: ' + str(self.recordLimit) + ' ' + 'Current: ' + str(currentRecords)) return True if response == 'Limit reached': feedback_msg.set("Customer Table limited to " + str(self.recordLimit) + " records.\n" "Can fit " + str(currentRecords) + " more records.") number_input.set('') return False if response == 'Error': feedback_msg.set('Error while generating customer records.\n' + number_input_String + ' customer records currently in the database.') number_input.set('') return False def plotCustomerAge(self, loading_msg): """ This function plots a bar graph on the frame with the age of customers in groups and their respective number of customers. :param loading_msg: The text label with the status of the page. :return: Success of function """ # Clear canvas before plotting anything else onto it for widget in self.window.winfo_children(): if 'canvas' in widget._name: widget.destroy() # Check if there are any records in the customer table first data = self.db.selectNumberOfCustomerRecords() if data[0][0] == 0: loading_msg.set('No data to visualize') return False loading_msg.set('Generating...') # Retrieve partitioned customer ages data = self.db.getCustomerAgeGroups() if data is False: loading_msg.set('Problem retrieving customer data') return False ageGroups = ['18 - 25', '26 - 40', '40 - 65', '65+'] numberOfCustomer = [0, 0, 0, 0] # Create different age intervals and populate them with the data for row in data: dob = row[0] year = dob.split('-')[0] age = datetime.now().year - int(year) if 18 <= age <= 25: numberOfCustomer[0] += 1 if 26 <= age <= 40: numberOfCustomer[1] += 1 if 41 <= age <= 65: numberOfCustomer[2] += 1 if 66 <= age: numberOfCustomer[3] += 1 try: # Figure fig = pyplot.Figure(figsize=(5, 5), dpi=100) ax1 = fig.add_subplot(111).bar(ageGroups, numberOfCustomer) fig.suptitle("Number of Customers by Age Group") # ax1.set_xlabel('Age') # ax1.set_ylabel('Number of customers') # Canvas canvas = FigureCanvasTkAgg(fig, master=self.window) # A tk.DrawingArea. canvas.get_tk_widget().grid(row=5, column=1) loading_msg.set('Graph Generated') except: print('Problem creating graph. Check matplotlib version.') loading_msg.set('Problem generating graph') return False return True def plotCustomerRegion(self, loading_msg): """ Function to plot a choropleth map.(https://en.wikipedia.org/wiki/Choropleth_map) Each region is shaded darker according to how many customers are from that region. A darker region indicates more customers, and vice versa. TO DO: Make toolbar available. :param loading_msg: A label from the GUI that typically represents the status. :return: Successfulness of function """ # Clear canvas before plotting anything else onto it for widget in self.window.winfo_children(): if 'canvas' in widget._name: widget.destroy() # Check if there are any records in the Customer Table first data = self.db.selectNumberOfCustomerRecords() if data[0][0] == 0: loading_msg.set('No data to visualize') return False # Feedback to inform user of progress loading_msg.set('Generating map...this may take a moment.') self.window.update() # Get .shp file data stored as pickle for faster retrieval # Source https://library.carleton.ca/find/gis/geospatial-data/shapefiles-canada-united-states-and-world try: with open('lib/map_data.pickle', 'rb') as handle: map_dataframe = pickle.load(handle) except: print('Problem retrieving data from pickle file') loading_msg.set('Problem generating map') return False data = self.db.getCustomerRegions() if data is False: loading_msg.set('Problem generating map') return False # Formatting region uids and their respective number of customers to place into a pandas DataFrame. eruids = [] nbCustomers = [] maxValue = 1 for val in data: eruids.append(val[0]) nbCustomers.append(val[1]) if val[1] > maxValue: maxValue = val[1] # Join region DataFrame with customer DataFrame try: tempDataFrame = pandas.DataFrame({ 'ERUID': eruids, 'nbCustomers': nbCustomers }) newDataFrame = map_dataframe.set_index('ERUID').join( tempDataFrame.set_index('ERUID')) except: print( 'Problem with pandas dataframe. Check version, or pickle files for corruption' ) return False # Figure fig, ax = pyplot.subplots(1, figsize=(5, 5)) ax.axis('off') ax.set_title('Number of Customers per Region') # Map sm = pyplot.cm.ScalarMappable(cmap='Blues', norm=pyplot.Normalize(vmin=0, vmax=maxValue)) sm._A = [] cbar = fig.colorbar(sm) newDataFrame.plot(column='nbCustomers', cmap='Blues', linewidth=0.8, ax=ax, edgecolor='0.8') # Canvas canvas = FigureCanvasTkAgg(fig, master=self.window) # A tk.DrawingArea. canvas.get_tk_widget().grid(row=5, column=1) # toolbar = NavigationToolbar2Tk(canvas, self.window) # toolbar.grid(row=5, column=1) loading_msg.set('Map generated') return True def getRegions(self): """ Function to get all the region names to provide in the Combobox() object in GUI. :return: Successfulness of function """ data = self.db.getRegions() if data is False: print('Problem retrieving regions') return regions = [] for val in data: regions.append(val[0]) return regions def getRequests(self, request_list, request_notification): """ Function to populate the request listbox with the emails of those who are requesting an account. Also update the request_notification label with the current number of requests. :param request_list: The request listbox :param request_notification: A tk label object that will display the number of current requests in the form of a string. :return: """ data = self.db.getRequests() numOfRequests = len(data) request_notification.set("There's " + str(numOfRequests) + " new request(s).") request_list.delete(0, 'end') for i, email in enumerate(data): request_list.insert(i, email) return True def enableApproveAndDeclineBtn(self, request_feedback): """ Function to enable approve button if user selects one and only one item (email) in the requests list box :return: """ # Clear feedback request_feedback.set('') # Get buttons approve_btn = self.window.nametowidget('approve_btn') decline_btn = self.window.nametowidget('decline_btn') # Get checkboxes login_checkbox = self.window.nametowidget('login_permission') edit_checkbox = self.window.nametowidget('edit_permission') delete_checkbox = self.window.nametowidget('delete_permission') delete_all_checkbox = self.window.nametowidget('delete_all_permission') add_checkbox = self.window.nametowidget('add_permission') analyze_checkbox = self.window.nametowidget('analyze_permission') # get requests listbox list_box = self.window.nametowidget('requests') # Check if selected 1 and only 1 item clicked_items = list_box.curselection() if len(clicked_items) > 1 or len(clicked_items) < 1: return False request_feedback.set('Choose permissions') # Enable buttons and checkboxes approve_btn['state'] = 'normal' decline_btn['state'] = 'normal' login_checkbox['state'] = 'normal' edit_checkbox['state'] = 'normal' delete_checkbox['state'] = 'normal' delete_all_checkbox['state'] = 'normal' add_checkbox['state'] = 'normal' analyze_checkbox['state'] = 'normal' return True def disableApproveAndDeclineBtn(self, request_feedback): """ Function to disable the buttons that can approve and decline the requests of new users. :return: """ # Clear feedback request_feedback.set('') # Get buttons approve_btn = self.window.nametowidget('approve_btn') decline_btn = self.window.nametowidget('decline_btn') # Get checkboxes login_checkbox = self.window.nametowidget('login_permission') edit_checkbox = self.window.nametowidget('edit_permission') delete_checkbox = self.window.nametowidget('delete_permission') delete_all_checkbox = self.window.nametowidget('delete_all_permission') add_checkbox = self.window.nametowidget('add_permission') analyze_checkbox = self.window.nametowidget('analyze_permission') # Enable buttons and checkboxes approve_btn['state'] = 'disable' decline_btn['state'] = 'disable' login_checkbox['state'] = 'disable' edit_checkbox['state'] = 'disable' delete_checkbox['state'] = 'disable' delete_all_checkbox['state'] = 'disable' add_checkbox['state'] = 'disable' analyze_checkbox['state'] = 'disable' return def approveUser(self, request_notification, request_feedback, login_var, edit_var, delete_var, delete_all_var, add_var, analyze_var): """ Function to add user to database. It is invoked by the approve button. It add a user using the email selected in the reqeuests listbox. Permissions are set according to their values selected by the admin. :return: """ # Get requests listbox requests_listbox = self.window.nametowidget('requests') # Get email selected clicked_items = requests_listbox.curselection() if len(clicked_items) > 1 or len(clicked_items) < 1: return False clicked_item_index = clicked_items[0] email = requests_listbox.get(clicked_item_index)[0] # Random password password = random.randint(1111111, 9999999) # Add email to users add_user_response = self.db.addUser(email, password) # Remove requests feedback = '' if add_user_response is True: dlt_respone = self.db.removeRequest(email) if dlt_respone is True: feedback += 'User approved. ' else: feedback += ' Unable to remove request. Contact db admin. ' # Set permissions permission_response = self.db.setPermissions(email, login_var.get(), edit_var.get(), delete_var.get(), delete_all_var.get(), add_var.get(), analyze_var.get()) if permission_response is True: feedback += 'Permissions successfully set. ' else: feedback += 'Failed to set permissions. ' # Refresh requests self.getRequests(requests_listbox, request_notification) # Reset and disable checkboxes and buttons # Get buttons approve_btn = self.window.nametowidget('approve_btn') decline_btn = self.window.nametowidget('decline_btn') # Get checkboxes login_checkbox = self.window.nametowidget('login_permission') edit_checkbox = self.window.nametowidget('edit_permission') delete_checkbox = self.window.nametowidget('delete_permission') delete_all_checkbox = self.window.nametowidget('delete_all_permission') add_checkbox = self.window.nametowidget('add_permission') analyze_checkbox = self.window.nametowidget('analyze_permission') # Disable approve_btn['state'] = 'disable' decline_btn['state'] = 'disable' login_checkbox['state'] = 'disable' edit_checkbox['state'] = 'disable' delete_checkbox['state'] = 'disable' delete_all_checkbox['state'] = 'disable' add_checkbox['state'] = 'disable' analyze_checkbox['state'] = 'disable' # Reset checkboxes login_var.set(0) edit_var.set(0) delete_var.set(0) delete_all_var.set(0) add_var.set(0) analyze_var.set(0) # Email new user with credentials if self.email is True: email_response = self.emailNewUserCredentials(email, password) if email_response is True: feedback += 'Email successfully sent. ' else: feedback += 'Failed to send email to user. ' else: feedback += 'Email setting turned off, email not sent.' # Respond to app user request_feedback.set(feedback) return True def declineUser(self, request_notification, request_feedback, login_var, edit_var, delete_var, delete_all_var, add_var, analyze_var): """ Function to decline an account request. The email selected by the admin within the requests listbox will be removed from the requests table. :param request_notification: :param request_feedback: :return: """ requests_listbox = self.window.nametowidget('requests') # Get selected request email clicked_items = requests_listbox.curselection() if len(clicked_items) > 1 or len(clicked_items) < 1: return False clicked_item_index = clicked_items[0] email = requests_listbox.get(clicked_item_index)[0] # Remove request response = self.db.removeRequest(email) # Respond to user if response is True: request_feedback.set('Request successfully declined.') else: request_feedback.set('Failed to remove request. Contact db admin.') return False # Refresh requests listbox self.getRequests(requests_listbox, request_notification) # Reset and disable checkboxes and buttons # Get buttons approve_btn = self.window.nametowidget('approve_btn') decline_btn = self.window.nametowidget('decline_btn') # Get checkboxes login_checkbox = self.window.nametowidget('login_permission') edit_checkbox = self.window.nametowidget('edit_permission') delete_checkbox = self.window.nametowidget('delete_permission') delete_all_checkbox = self.window.nametowidget('delete_all_permission') add_checkbox = self.window.nametowidget('add_permission') analyze_checkbox = self.window.nametowidget('analyze_permission') # Disable approve_btn['state'] = 'disable' decline_btn['state'] = 'disable' login_checkbox['state'] = 'disable' edit_checkbox['state'] = 'disable' delete_checkbox['state'] = 'disable' delete_all_checkbox['state'] = 'disable' add_checkbox['state'] = 'disable' analyze_checkbox['state'] = 'disable' # Reset checkboxes login_var.set(0) edit_var.set(0) delete_var.set(0) delete_all_var.set(0) add_var.set(0) analyze_var.set(0) return True def submitRequest(self, email, email_rsp): """ Function to submit request for an account. These requests will appear in the admin menu. :param email: The email of the user requesting an account :return: """ if email == '': return # Check if email already exists within requests data = self.db.checkReqeustExists(email) # Email already exists if len(data) > 0: email_rsp.set('Request already submitted with that email.') return False # Check if email is already used for a user data = self.db.checkUserExists(email) # Email already in use if len(data) > 0: email_rsp.set('Cannot use that email.') return False # Submit request response = self.db.submitRequest(email) # Resond to user if response is True: email_rsp.set( 'Account request submitted.\nIf approved you will receive an email with your login credentials.' ) else: email_rsp.set('There was a problem submitting the request.') return True def searchUser(self, username, login_var, edit_var, delete_var, delete_all_var, add_var, analyze_var, search_fdbk): """ Function to search for a particulart user in the database from the admin menu and update the checkboxes that represent their permissions. These permissions represent the user's access to particular functionalities/buttons within the application. :param username: The username of the user being searched for. :param login_var: A tk IntVar that represents the value of the login permission :param edit_var: A tk IntVar that represents the value of the edit_customer permission :param delete_var: A tk IntVar that represents the value of the delete_customer permission :param delete_all_var: A tk IntVar that represents the value of the delete_all_customer permission :param add_var: A tk IntVar that represents the value of the add_customer permission :param analyze_var: A tk IntVar that represents the value of the analyze_customer permission :param user_fdbk: The tk label object that will contain the system feedback for the user in the form of a string. :return: """ search_fdbk.set("") if username == '': return response = self.db.checkUserExists(username) if len(response) < 1: search_fdbk.set('No user with that username') return False # If user exists permissions = self.db.getPermissions(username) # Set checkbox values to user current permissions login_var.set(permissions['login']) edit_var.set(permissions['edit_customer_btn']) delete_var.set(permissions['delete_customer_btn']) delete_all_var.set(permissions['delete_all_customer_btn']) add_var.set(permissions['add_customer_btn']) analyze_var.set(permissions['analyze_customer_btn']) # Get checkboxes login_checkbox = self.window.nametowidget('login_permission') edit_checkbox = self.window.nametowidget('edit_permission') delete_checkbox = self.window.nametowidget('delete_permission') delete_all_checkbox = self.window.nametowidget('delete_all_permission') add_checkbox = self.window.nametowidget('add_permission') analyze_checkbox = self.window.nametowidget('analyze_permission') # Get buttons change_perm_btn = self.window.nametowidget('change_permissions_btn') delete_user_btn = self.window.nametowidget('delete_user_btn') # Set checkbox states to normal login_checkbox['state'] = 'normal' edit_checkbox['state'] = 'normal' delete_checkbox['state'] = 'normal' delete_all_checkbox['state'] = 'normal' add_checkbox['state'] = 'normal' analyze_checkbox['state'] = 'normal' # Set button states to normal change_perm_btn['state'] = 'normal' delete_user_btn['state'] = 'normal' return True def emailNewUserCredentials(self, user_email, user_password): """ Function to send an email to the new approved user containing their login credentials. :return: """ sender_email = '*****@*****.**' sender_password = '******' message = "Your Customer Management System account has been approved. Here are your credentials.\n\n"\ "Username: "******"Password: "******""" Function to change the permissions of a user. The permissions typically represent access to buttons/functionalities of the application that can manipulate customers/data. :param username: The username of the user :param login_var: A tk IntVar that represents the value of the login permission :param edit_var: A tk IntVar that represents the value of the edit_customer permission :param delete_var: A tk IntVar that represents the value of the delete_customer permission :param delete_all_var: A tk IntVar that represents the value of the delete_all_customer permission :param add_var: A tk IntVar that represents the value of the add_customer permission :param analyze_var: A tk IntVar that represents the value of the analyze_customer permission :param user_fdbk: The tk label object that will contain the system feedback for the user in the form of a string. :return: """ response = self.db.changeUserPermissions(username, login_var.get(), edit_var.get(), delete_var.get(), delete_all_var.get(), add_var.get(), analyze_var.get()) if response is True: user_fdbk.set('Successfully set permissions.') else: user_fdbk.set('Failed to set permissions. Contact db admin.') return True def deleteUser(self, username, user_fdbk): """ Function to delete the user from the database. This function is only accessed from the admin menu. :param username: The username of the user to be deleted :param user_fdbk: The tk label object that will contain the system feedback for the user in the form of a string. :return: """ # The feedback string feedback = '' response = self.db.deleteUser(username) if response is True: feedback += 'User successively deleted.\n' else: feedback += 'User could not be deleted. Contact db admin.\n' response = self.db.deletePermissions(username) if response is True: feedback += 'Permissions successively deleted.\n' else: feedback += 'Permissions could not be deleted. Contact db admin.\n' # Set the feedback user_fdbk.set(feedback) # Disable buttons and checkboxes # Get checkboxes login_checkbox = self.window.nametowidget('login_permission') edit_checkbox = self.window.nametowidget('edit_permission') delete_checkbox = self.window.nametowidget('delete_permission') delete_all_checkbox = self.window.nametowidget('delete_all_permission') add_checkbox = self.window.nametowidget('add_permission') analyze_checkbox = self.window.nametowidget('analyze_permission') # Get buttons delete_user_btn = self.window.nametowidget('delete_user_btn') change_perm_btn = self.window.nametowidget('change_permissions_btn') # Set checkbox states to normal login_checkbox['state'] = 'disabled' edit_checkbox['state'] = 'disabled' delete_checkbox['state'] = 'disabled' delete_all_checkbox['state'] = 'disabled' add_checkbox['state'] = 'disabled' analyze_checkbox['state'] = 'disabled' # Set button states to normal delete_user_btn['state'] = 'disabled' change_perm_btn['state'] = 'disabled' return True def autoCompleteUser(self, autoCompleteList, user_input, user_fdbk, login_var, edit_var, delete_var, delete_all_var, add_var, analyze_var): """ Function to populate a dropdown listbox that contains all usernames in teh datatbase that start with the user_input string. This listbox is initialized in the GUI and hidden. It will only be revealed when there are 1 or more greater usernames that begin with the user_input string. :param auto_complete_list: The listbox that will hold and display the usernames. :param user_input: The string that represents the username the user is looking for. :return: """ # Clear feedback user_fdbk.set('') # Clear widget of any text and hide autoCompleteList.delete(0, 'end') autoCompleteList.place_forget() # Get checkboxes login_checkbox = self.window.nametowidget('login_permission') edit_checkbox = self.window.nametowidget('edit_permission') delete_checkbox = self.window.nametowidget('delete_permission') delete_all_checkbox = self.window.nametowidget('delete_all_permission') add_checkbox = self.window.nametowidget('add_permission') analyze_checkbox = self.window.nametowidget('analyze_permission') # Get buttons delete_user_btn = self.window.nametowidget('delete_user_btn') change_perm_btn = self.window.nametowidget('change_permissions_btn') # Set checkbox states to normal login_checkbox['state'] = 'disabled' edit_checkbox['state'] = 'disabled' delete_checkbox['state'] = 'disabled' delete_all_checkbox['state'] = 'disabled' add_checkbox['state'] = 'disabled' analyze_checkbox['state'] = 'disabled' # Reset checkbox values login_var.set(0) edit_var.set(0) delete_var.set(0) delete_all_var.set(0) add_var.set(0) analyze_var.set(0) # Set button states to normal delete_user_btn['state'] = 'disabled' change_perm_btn['state'] = 'disabled' if user_input is '': return False data = self.db.usernameContaining(user_input) if len(data) < 1: return False for i, username in enumerate(data): autoCompleteList.insert(i, username) autoCompleteList.place(x=500, y=416) return True def selectFromAutoCompleteUser(self, autoCompleteList, user_input_field): """ This function will take the selected item from the autocomplete listbox and set the entry value equal to the selected item. The listbox will then be cleared and hidden. :return: """ clicked_items = autoCompleteList.curselection() if len(clicked_items) > 1 or len(clicked_items) < 1: return False clicked_item_index = clicked_items[0] selected_email = autoCompleteList.get(clicked_item_index)[0] user_input_field.set(selected_email) autoCompleteList.place_forget() return True