Ejemplo n.º 1
0
def authenticate(password, email=None, account_id=None):
    """
    Authenticate user's email and password with database.
    Has to have email or account_id to find account information. Only one of them is required.
    :param email: email of user
    :param password: password of user
    :param account_id: user's account_id
    return tuple of account information if succeeded else return error message
    """
    if not password or (not email and not account_id):
        return 'Incorrect input.'
    db = Database(db_path)
    try:
        if email:
            acc = db.select('*', account_table, f'Email = \"{email}\"')
        elif account_id:
            acc = db.select('*', account_table,
                            f'User_Account_ID = \"{account_id}\"')
        else:
            acc = None

        if not acc:  # account was not found with this email
            return 'Account was not found.'
        if acc:  # account with this email is in our database
            # handle incorrect input
            db_password, db_salt = b64decode(acc[0][1]), b64decode(acc[0][3])
            hashed_pass, _ = generate_hash(password=password, salt=db_salt)
            if hmac.compare_digest(hashed_pass, db_password):  # login
                return acc[0]
            else:
                return 'Password did not match'

    finally:
        db.close_connection()
Ejemplo n.º 2
0
def __account(first, last, middle_i, hospital, acc_id):
    """
    Make account from given information.
    :param first: string of first name in string
    :param last: string of last name in string
    :param middle_i: string of middle initial
    :param hospital: string of hospital name
    :param acc_id: int of account id for this account
    :return: combined single-line string for this account
    """
    user_account_id = str(acc_id)  # store acc_id in string
    domain = '@abc.com'  # sample domain for email address
    email = first.lower() + '.' + last.lower() + domain
    password = first.lower() + last.lower()
    hashed_pass, temp_salt = generate_hash(
        password)  # get hashed_pass and salt for this password
    hashed_pass = b64encode(hashed_pass).decode('utf-8')
    salt = b64encode(temp_salt).decode('utf-8')
    patient_num = str(random.randint(1000, 9999))  # randomly chosen patient id

    # capitalize names
    last_name = last.capitalize()
    first_name = first.capitalize()

    # if middle_i is empty, set middle to None
    middle = middle_i if middle_i else 'None'
    dob = str(__get_random_date(OLDEST_DOB, TODAY))
    hospital = hospital + random.choice(('MedicalCenter', 'Hospital'))

    vaccine_name1 = vaccine_name2 = __vaccine_name()
    first_dose_latest = TODAY - datetime.timedelta(days=RECOMMENDED_INTERVAL)
    vaccine_date1 = __get_random_date(VACCINE_START, first_dose_latest)
    day_after_first_dose = vaccine_date1 + datetime.timedelta(days=1)
    # ideally second dose should be taked within 42 days from first dose.
    vaccine_date2 = __get_random_date(day_after_first_dose, TODAY)
    vaccine_date1 = str(vaccine_date1)
    vaccine_date2 = str(vaccine_date2)

    temp_prev_hash = None

    prev_hash = temp_prev_hash or os.environ['hash_0']
    items = [
        prev_hash, user_account_id, patient_num, last_name, first_name, middle,
        dob, vaccine_name1, vaccine_date1, hospital, vaccine_name2,
        vaccine_date2, prev_hash
    ]
    block_hash = generate_block_hash(items, temp_salt)

    # return all information in string
    return DELIM.join([
        user_account_id, email, hashed_pass, salt, patient_num, last_name,
        first_name, middle, dob, hospital, vaccine_name1, vaccine_date1,
        vaccine_name2, vaccine_date2, block_hash
    ])
Ejemplo n.º 3
0
def generate_account(session, profile_data):
    """
    Generate account for registration.
    :param session: dict of session from flask.
    :param profile_data: dict of profile data from flask.
    :return: True if successfully generated.
    """
    db = Database(db_path)
    try:
        # Get cur_hash from last record in database
        last_record_hash = \
        db.select('Block_Hash', profile_table, 'User_Account_ID = (SELECT max(User_Account_ID) FROM profile)')[0][0]

        # Get largest account_id in database and increment account_id by 1
        new_account_id = db.select(values='max(User_Account_ID)',
                                   table_name=account_table)[0][0] + 1

        hashed_pass, temp_hashed_salt = generate_hash(session['password'])
        hashed_pass = b64encode(hashed_pass).decode('utf-8')
        hashed_salt = b64encode(temp_hashed_salt).decode('utf-8')
        username = profile_data['first_name'] + ' ' + profile_data['last_name']
        account_value = (session['email'], hashed_pass, new_account_id,
                         hashed_salt, username)

        items = [
            last_record_hash, new_account_id, profile_data['patient_num'],
            profile_data['last_name'], profile_data['first_name'],
            profile_data['mid_initial'], profile_data['dob'],
            profile_data['first_dose'], profile_data['date_first'],
            profile_data['clinic_site'], profile_data['second_dose'],
            profile_data['date_second'], last_record_hash
        ]
        new_hash = generate_block_hash(items, temp_hashed_salt)
        with open(HISTORY_LOG_PATH, 'a') as hist_log_file:
            hist_log_file.write(f'{new_account_id}\t{new_hash}\n')

        items.pop(len(items) - 1)
        items.pop(0)
        items.append(new_hash)

        profile_value = tuple(items)

        db.insert(account_value, account_table)
        db.insert(profile_value, profile_table)
        return new_account_id
    finally:
        db.close_connection()
Ejemplo n.º 4
0
def generate_block_hash(items: list, salt):
    """ Generate hash for each block in the database

    Args:
        items (list): list of items that need to be converted to hash
        salt (bytes): unique salt to generate hash

    Returns:
        cur_hash (str): hash that converted to string to stored into database and written to file
    """
    string = ""
    for element in items:
        string += str(element)

    cur_hash, _ = generate_hash(string, salt)
    cur_hash = b64encode(cur_hash).decode("utf-8")

    return cur_hash
Ejemplo n.º 5
0
def update_password(new_password, email=None, acc=None):
    """
    Update account's password.
    :param email: email
    :param new_password: new password
    :param acc: account id
    :return: True if succeeded else False.
    """
    db = Database(db_path)

    try:
        if acc:
            salt = db.select('Salt', account_table,
                             f'''User_Account_ID = {acc}''')
        elif email:
            salt = db.select('Salt', account_table, f'Email = \"{email}\"')
        else:
            salt = None

        if not salt:  # account was not found with this email
            return 'Account was not found.'

        salt = b64decode(salt[0][0])
        hashed_pass, _ = generate_hash(new_password, salt)
        hashed_pass = b64encode(hashed_pass).decode('utf-8')
        if acc:
            db.update((hashed_pass, ), ('Password', ), account_table,
                      f'User_Account_ID = \"{acc}\"')
        elif email and type(is_user(email)) == tuple:
            db.update((hashed_pass, ), ('Password', ), account_table,
                      f'Email = \"{email}\"')
        else:
            return False
        return True

    finally:
        db.close_connection()