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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
 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
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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
Exemplo n.º 8
0
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
Exemplo n.º 9
0
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
Exemplo n.º 10
0
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, "")
Exemplo n.º 11
0
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, "")
Exemplo n.º 12
0
  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)
Exemplo n.º 14
0
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')
Exemplo n.º 15
0
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')
Exemplo n.º 16
0
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
Exemplo n.º 17
0
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
Exemplo n.º 18
0
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