def add_member(self): """ Adds this member to the database. Assumes data has already been validated. Returns True if successful, otherwise False. """ # If the user is already in the database, skip this user. if validation_utils.check_uid_exists(self.uid): return False # Generate an account creation key. create_account_key = auth_utils.generate_create_account_key() query = sqlalchemy.text(""" INSERT INTO members (first_name, last_name, matriculation_year, graduation_year, uid, email, member_type, create_account_key) VALUES (:first_name, :last_name, :matriculation_year, :graduation_year, :uid, :email, :member_type, :create_account_key) """) flask.g.db.execute(query, first_name=self.first_name, last_name=self.last_name, matriculation_year=self.matriculation_year, graduation_year=self.graduation_year, uid=self.uid, email=self.email, member_type=self.member_type, create_account_key=create_account_key) # Email the user. subject = "Welcome to the Ruddock House website!" msg = email_templates.AddedToWebsiteEmail.format( self.name, flask.url_for('account.create_account', create_account_key=create_account_key, _external=True)) to = self.email email_utils.send_email(to, msg, subject) return True
def handle_password_reset(username, new_password, new_password2): """ Handles the submitted password reset request. Returns True if successful, False otherwise. Also handles all messages displayed to the user. """ if not validation_utils.validate_password(new_password, new_password2): return False auth_utils.set_password(username, new_password) # Clean up the password reset key, so that it cannot be used again. query = sqlalchemy.text(""" UPDATE users SET password_reset_key = NULL, password_reset_expiration = NULL WHERE username = :u """) flask.g.db.execute(query, u=username) # Get the user's email. query = sqlalchemy.text(""" SELECT name, email FROM members NATURAL JOIN members_extra NATURAL JOIN users WHERE username = :u """) result = flask.g.db.execute(query, u=username).first() # Send confirmation email to user. email = result['email'] name = result['name'] msg = email_templates.ResetPasswordSuccessfulEmail.format(name) subject = "Password reset successful" email_utils.send_email(email, msg, subject) return True
def updateFromList(results, lst): print("Updating list: " + lst) # write emails to flat file if len(results) <= 0: email_utils.send_email( IMSS_ADDR, 'Email list has no subscribers: {}\n\nFor list: {}'.format( query, lst), ERROR_SUBJ) else: try: f = tempfile.NamedTemporaryFile() for result in results: f.write(result[0].encode() + b'\n') for addition in getAdditionalEmails(lst): f.write(addition[0].encode() + b'\n') f.flush() # flush so file can be read by `sync_members` # update mailman list check_call("{} -w=no -g=no -a=yes -f '{}' {}".format( SYNC_MEMBERS_PATH, f.name, lst), shell=True) f.close() # this also deletes the tempfile except Exception as e: email_utils.send_email( IMSS_ADDR, 'Exception: {}\n\n For list: {}'.format(e, lst), ERROR_SUBJ)
def updateFromList(results, lst): print("Updating list: " + lst) # write emails to flat file if len(results) <= 0: email_utils.send_email( IMSS_ADDR, 'Email list has no subscribers: {}\n\nFor list: {}'.format(query, lst), ERROR_SUBJ) else: try: f = tempfile.NamedTemporaryFile() for result in results: f.write(result[0].encode() + b'\n') for addition in getAdditionalEmails(lst): f.write(addition[0].encode() + b'\n') f.flush() # flush so file can be read by `sync_members` # update mailman list check_call( "{} -w=no -g=no -a=yes -f '{}' {}".format(SYNC_MEMBERS_PATH, f.name, lst), shell=True) f.close() # this also deletes the tempfile except Exception as e: email_utils.send_email( IMSS_ADDR, 'Exception: {}\n\n For list: {}'.format(e, lst), ERROR_SUBJ)
def add_member(self): """ Adds this member to the database. Assumes data has already been validated. Returns True if successful, otherwise False. """ # If the user is already in the database, skip this user. if validation_utils.check_uid_exists(self.uid): return False # Generate an account creation key. create_account_key = auth_utils.generate_create_account_key() query = sqlalchemy.text(""" INSERT INTO members (first_name, last_name, matriculation_year, graduation_year, uid, email, member_type, create_account_key) VALUES (:first_name, :last_name, :matriculation_year, :graduation_year, :uid, :email, :member_type, :create_account_key) """) flask.g.db.execute(query, first_name=self.first_name, last_name=self.last_name, matriculation_year=self.matriculation_year, graduation_year=self.graduation_year, uid=self.uid, email=self.email, member_type=self.member_type, create_account_key=create_account_key) # Email the user. subject = "Welcome to the Ruddock House website!" msg = email_templates.AddedToWebsiteEmail.format(self.name, flask.url_for('account.create_account', create_account_key=create_account_key, _external=True)) to = self.email email_utils.send_email(to, msg, subject) return True
def internal_server_error(error): """Handles a 500 internal server error response. This error is usually the result of an improperly configured server or bugs in the actual codebase (user errors should be handled gracefully), so IMSS should be notified if this error occurs. """ msg = email_templates.ErrorCaughtEmail.format(traceback.format_exc()) subject = "Ruddock website error" to = "*****@*****.**" email_utils.send_email(to, msg, subject) return flask.render_template("500.html"), http.client.INTERNAL_SERVER_ERROR
def internal_server_error(error): """Handles a 500 internal server error response. This error is usually the result of an improperly configured server or bugs in the actual codebase (user errors should be handled gracefully), so IMSS should be notified if this error occurs. """ msg = email_templates.ErrorCaughtEmail.format(traceback.format_exc()) subject = "Ruddock website error" to = "*****@*****.**" email_utils.send_email(to, msg, subject) return flask.render_template("500.html"), httplib.INTERNAL_SERVER_ERROR
def handle_forgotten_password(username, email): """ Handles a forgotten password request. Takes a submitted (username, email) pair and checks that the email is associated with that username in the database. If successful, the user is emailed a reset key. Returns True on success, False if the (username, email) pair is not valid. """ # Check username, email pair. query = sqlalchemy.text(""" SELECT user_id, name, email FROM members NATURAL JOIN members_extra NATURAL JOIN users WHERE username = :u """) result = flask.g.db.execute(query, u=username).first() if result is not None and email == result['email']: name = result['name'] user_id = result['user_id'] # Generate a reset key for the user. reset_key = auth_utils.generate_reset_key() query = sqlalchemy.text(""" UPDATE users SET password_reset_key = :rk, password_reset_expiration = NOW() + INTERVAL :time MINUTE WHERE username = :u """) flask.g.db.execute(query, rk=reset_key, time=constants.PWD_RESET_KEY_EXPIRATION, u=username) # Determine if we want to say "your link expires in _ minutes" or # "your link expires in _ hours". if constants.PWD_RESET_KEY_EXPIRATION < 60: expiration_time_str = "{} minutes".format( constants.PWD_RESET_KEY_EXPIRATION) else: expiration_time_str = "{} hours".format( constants.PWD_RESET_KEY_EXPIRATION // 60) # Send email to user. msg = email_templates.ResetPasswordEmail.format( name, flask.url_for('auth.reset_password', reset_key=reset_key, _external=True), expiration_time_str) subject = "Password reset request" email_utils.send_email(email, msg, subject) return True return False
def handle_forgotten_password(username, email): """ Handles a forgotten password request. Takes a submitted (username, email) pair and checks that the email is associated with that username in the database. If successful, the user is emailed a reset key. Returns True on success, False if the (username, email) pair is not valid. """ # Check username, email pair. query = sqlalchemy.text( """ SELECT user_id, name, email FROM members NATURAL JOIN members_extra NATURAL JOIN users WHERE username = :u """ ) result = flask.g.db.execute(query, u=username).first() if result is not None and email == result["email"]: name = result["name"] user_id = result["user_id"] # Generate a reset key for the user. reset_key = auth_utils.generate_reset_key() query = sqlalchemy.text( """ UPDATE users SET password_reset_key = :rk, password_reset_expiration = NOW() + INTERVAL :time MINUTE WHERE username = :u """ ) flask.g.db.execute(query, rk=reset_key, time=constants.PWD_RESET_KEY_EXPIRATION, u=username) # Determine if we want to say "your link expires in _ minutes" or # "your link expires in _ hours". if constants.PWD_RESET_KEY_EXPIRATION < 60: expiration_time_str = "{} minutes".format(constants.PWD_RESET_KEY_EXPIRATION) else: expiration_time_str = "{} hours".format(constants.PWD_RESET_KEY_EXPIRATION // 60) # Send email to user. msg = email_templates.ResetPasswordEmail.format( name, flask.url_for("auth.reset_password", reset_key=reset_key, _external=True), expiration_time_str ) subject = "Password reset request" email_utils.send_email(email, msg, subject) return True return False
def handle_request_account(uid, last_name): """Handles a request to create an account. Checks that the email and UID match. If so, a create account link is sent to the user. Returns: Tuple (bool, string). The bool indicates success. If not successful, the string is an error message. """ query = sqlalchemy.text(""" SELECT name, last_name, email, username FROM members NATURAL JOIN members_extra NATURAL LEFT JOIN users WHERE uid = :uid """) result = flask.g.db.execute(query, uid=uid).first() if result is None or result["last_name"].lower() != last_name.lower(): return (False, "Incorrect UID and/or name.") if result["username"] is not None: return (False, "You already have an account. Try recovering it?") email = result["email"] name = result["name"] # Generate a new account creation key. create_account_key = auth_utils.generate_create_account_key() query = sqlalchemy.text(""" UPDATE members SET create_account_key = :create_account_key WHERE uid = :uid """) flask.g.db.execute(query, create_account_key=create_account_key, uid=uid) create_account_link = flask.url_for("account.create_account", create_account_key=create_account_key, _external=True) msg = email_templates.CreateAccountRequestEmail.format(name, create_account_link) subject = "Account creation request" email_utils.send_email(email, msg, subject) return (True, "")
def handle_request_account(uid, last_name): """Handles a request to create an account. Checks that the email and UID match. If so, a create account link is sent to the user. Returns: Tuple (bool, string). The bool indicates success. If not successful, the string is an error message. """ query = sqlalchemy.text(""" SELECT name, last_name, email, username FROM members NATURAL JOIN members_extra NATURAL LEFT JOIN users WHERE uid = :uid """) result = flask.g.db.execute(query, uid=uid).first() if result is None or result["last_name"].lower() != last_name.lower(): return (False, "Incorrect UID and/or name.") if result["username"] is not None: return (False, "You already have an account. Try recovering it?") email = result["email"] name = result["name"] # Generate a new account creation key. create_account_key = auth_utils.generate_create_account_key() query = sqlalchemy.text(""" UPDATE members SET create_account_key = :create_account_key WHERE uid = :uid """) flask.g.db.execute(query, create_account_key=create_account_key, uid=uid) create_account_link = flask.url_for("account.create_account", create_account_key=create_account_key, _external=True) msg = email_templates.CreateAccountRequestEmail.format( name, create_account_link) subject = "Account creation request" email_utils.send_email(email, msg, subject) return (True, "")
def add_members(self): """Adds all members to the database. Assumes data to be valid.""" # Keep track of which members were added and which were skipped. members_added = [] members_skipped = [] for new_member in self.new_member_list: if new_member.add_member(): members_added.append(new_member.name) else: members_skipped.append(new_member.name) flask.flash("{0} member(s) were successfully added and {1} member(s) were skipped.".format(len(members_added), len(members_skipped))) # Email admins about added members. to = "[email protected], [email protected]" msg = email_templates.MembersAddedEmail.format( '\n'.join(members_added) if len(members_added) > 0 else '(none)', '\n'.join(members_skipped) if len(members_skipped) > 0 else '(none)') subject = 'Members were added to the Ruddock Website' # Don't use prefix since this is being sent to IMSS/Secretary, which have # their own prefixes. email_utils.send_email(to, msg, subject, use_prefix=False)
def add_members(self): """Adds all members to the database. Assumes data to be valid.""" # Keep track of which members were added and which were skipped. members_added = [] members_skipped = [] for new_member in self.new_member_list: if new_member.add_member(): members_added.append(new_member.name) else: members_skipped.append(new_member.name) flask.flash( "{0} member(s) were successfully added and {1} member(s) were skipped." .format(len(members_added), len(members_skipped))) # Email admins about added members. to = "[email protected], [email protected]" msg = email_templates.MembersAddedEmail.format( '\n'.join(members_added) if len(members_added) > 0 else '(none)', '\n'.join(members_skipped) if len(members_skipped) > 0 else '(none)') subject = 'Members were added to the Ruddock Website' # Don't use prefix since this is being sent to IMSS/Secretary, which have # their own prefixes. email_utils.send_email(to, msg, subject, use_prefix=False)
def updateFromList(results, lst): print "Updating list: " + lst # write emails to flat file if len(results) <= 0: email_utils.send_email('*****@*****.**', 'Email list has no subscribers: ' + \ query + '\n\nFor list: ' + lst, '[RuddWeb] THE EMAIL SCRIPT IS BROKEN') else: try: f = tempfile.NamedTemporaryFile() for result in results: f.write(result[0] + '\n') for addition in getAdditionalEmails(lst): f.write(addition[0] + '\n') f.flush() # flush so file can be read by `sync_members` # update mailman list check_call("/usr/lib/mailman/bin/sync_members -w=no -g=no -a=yes -f " + \ "'" + f.name + "' " + lst, shell=True) f.close() # this also deletes the tempfile except Exception as e: email_utils.send_email('*****@*****.**', 'Exception: ' + str(e) + \ '\n\nFor list: ' + lst, '[RuddWeb] THE EMAIL SCRIPT IS BROKEN')
def handle_password_reset(username, new_password, new_password2): """ Handles the submitted password reset request. Returns True if successful, False otherwise. Also handles all messages displayed to the user. """ if not validation_utils.validate_password(new_password, new_password2): return False auth_utils.set_password(username, new_password) # Clean up the password reset key, so that it cannot be used again. query = sqlalchemy.text( """ UPDATE users SET password_reset_key = NULL, password_reset_expiration = NULL WHERE username = :u """ ) flask.g.db.execute(query, u=username) # Get the user's email. query = sqlalchemy.text( """ SELECT name, email FROM members NATURAL JOIN members_extra NATURAL JOIN users WHERE username = :u """ ) result = flask.g.db.execute(query, u=username).first() # Send confirmation email to user. email = result["email"] name = result["name"] msg = email_templates.ResetPasswordSuccessfulEmail.format(name) subject = "Password reset successful" email_utils.send_email(email, msg, subject) return True
def handle_create_account(user_id, username, password, password2, birthday): """Handles account creation. Creates account if all values provided are valid. Returns: bool indicating success. """ # Validate username and password. The validate_* functions will flash errors. # We want to check all fields and not just stop at the first error. is_valid = True if not validation_utils.validate_username(username): is_valid = False if not validation_utils.validate_password(password, password2): is_valid = False if not validation_utils.validate_date(birthday): is_valid = False if not is_valid: return False # Insert new values into the database. Because the password is updated in a # separate step, we must use a transaction to execute this query. transaction = flask.g.db.begin() try: # Insert the new row into users. query = sqlalchemy.text(""" INSERT INTO users (user_id, username, password_hash) VALUES (:user_id, :username, :password_hash) """) flask.g.db.execute(query, user_id=user_id, username=username, password_hash="") # Set the password. auth_utils.set_password(username, password) # Set the birthday and invalidate the account creation key. query = sqlalchemy.text(""" UPDATE members SET birthday = :birthday, create_account_key = NULL WHERE user_id = :user_id """) flask.g.db.execute(query, birthday=birthday, user_id=user_id) transaction.commit() except Exception: transaction.rollback() flask.flash("An unexpected error occurred. Please find an IMSS rep.") return False # Email the user. query = sqlalchemy.text(""" SELECT name, email FROM members NATURAL JOIN members_extra NATURAL JOIN users WHERE username = :u """) result = flask.g.db.execute(query, u=username).first() # Send confirmation email to user. email = result["email"] name = result["name"] msg = email_templates.CreateAccountSuccessfulEmail.format(name, username) subject = "Thanks for creating an account!" email_utils.send_email(email, msg, subject) return True