Ejemplo n.º 1
0
class User(object):
    def __init__(self, email: str):
        self._db = Database()
        self._email = email
        self._cipher = AESCipher()
        self._init_tables()

    def _init_tables(self) -> None:
        sql = "CREATE TABLE IF NOT EXISTS"
        tables = ['users', 'login', 'user_security']
        #with self._db as _db:
        #TODO: create tables on init for all classes/tables
        print('hi')

    def exists_user(self) -> bool:
        sql = "SELECT id FROM users WHERE unique_id=%s"

        with self._db as _db:
            result = _db.select_with_params(sql, [
                self._email,
            ])
        if result and result[0][0]:
            return True
        return False

    def get_user_id(self) -> any:
        sql = "SELECT id FROM users WHERE unique_id=%s"

        with self._db as _db:
            result = _db.select_with_params(sql, [
                self._email,
            ])

        if result:
            return result[0][0]
        return None

    def login(self, password: str) -> any:
        user_id = self.get_user_id()

        if user_id:
            user_pwd = self._get_user_password(user_id)

            if user_pwd:
                decrypted_pwd = self._cipher.decrypt(user_pwd)

                if decrypted_pwd == password:
                    return self._update_login(user_id)
                return 0, 'Invalid Password'
        return 0, "Invalid User ID"

    def _get_user_password(self, user_id: str) -> any:
        sql = "SELECT password_hash FROM login WHERE user_id=%s"

        with self._db as _db:
            result = _db.select_with_params(sql, [
                user_id,
            ])

        if result[0][0]:
            return result[0][0]
        else:
            return None

    def _update_login(self, user_id: str) -> any:
        sql = "UPDATE login SET active=1 WHERE user_id=%s"

        with self._db as _db:
            _db.update(sql, [
                user_id,
            ])
        return 1, 'Success'

    def _logged_in_check(self, user_id: str) -> bool:
        sql = "SELECT active FROM login WHERE user_id=%s"

        with self._db as _db:
            result = _db.select_with_params(sql, [
                user_id,
            ])

        if result:
            if result[0][0] == '1' or result[0][0] == 1:
                return True
        return False

    def logout(self) -> None:
        user_id = self.get_user_id()
        sql = "UPDATE login SET active=0 WHERE user_id=%s"

        with self._db as _db:
            _db.update(sql, [
                user_id,
            ])

    def create_new_user(self, user_obj: any) -> any:
        params = [
            user_obj.get('email'),
            user_obj.get('name'),
            user_obj.get('lastname'),
            user_obj.get('address'),
            user_obj.get('address2'),
            user_obj.get('city'),
            user_obj.get('state'),
            user_obj.get('zip'),
        ]
        password = user_obj.get('password')

        sql = """INSERT INTO users (unique_id, first_name, last_name, address, address2,
                                    city, state, zip_code)
                  VALUES(%s, %s, %s, %s, %s, %s, %s, %s)"""

        with self._db as _db:
            new_id = _db.insert(sql, params)

        if new_id:
            self._create_login(new_id, password)
            return 1, new_id
        return 0, 'Unable to Create User'

    def _create_login(self, user_id: str, password: str) -> any:
        pwd_hash = self._cipher.encrypt(password)
        sql = """INSERT INTO login (user_id, password_hash, active)
                 VALUES(%s, %s, 1)"""

        with self._db as _db:
            _db.insert(sql, [
                user_id,
                pwd_hash,
            ])

    def insert_security_questions(self, question_obj: any) -> None:
        sql = """INSERT INTO user_security (user_id, question_id, answer_text)
                 VALUES(%s, %s, %s)"""
        user_id = self.get_user_id()
        with self._db as _db:
            for obj in question_obj:
                _db.insert(sql, [
                    user_id,
                    obj[0],
                    obj[1],
                ])
Ejemplo n.º 2
0
class User:
    def __init__(self, email: str):
        self._user_id = None
        self._email = email
        self._pwd = None
        self.cipher = AESCipher()
        self.advisor = 0
        self._logger = logging.getLogger('progress_tracker_api')

    def login(self, pwd: str):
        try:
            self._pwd = pwd
            user_id = self._fetch_user_id()
            if not user_id:
                self._logger.error('Login user error missing user_id')
                return 0, 'Unauthorized- Invalid username', 401

            self._user_id = user_id
            success, msg = self.fetch_user_login()

            if not success:
                return success, 'Forbidden- ' + msg, 403
            return success, 'success', 200
        except Exception as e:
            return 0, 'Internal Server Error: Please Come Back Later', 500

    def sign_up(self, pwd: str, firstname: str, lastname: str):
        self._pwd = pwd
        exists = self.check_if_user_exists()

        if exists:
            self._logger.error('Sign UP error, user already exists! email: {}'.format(self._email))
            return 0, 'Account already exists for this email', 200

        return self.create_user(firstname, lastname)

    def _fetch_user_id(self) -> int:
        self._logger.info('_fetch_user_id for email: {}'.format(self._email))
        sql = """SELECT user_id FROM user WHERE email = %s"""

        with Database() as _db:
            user_id = _db.select_with_params(sql, [self._email, ])
        if user_id:
            return user_id[0][0]
        else:
            return 0

    def fetch_user_login(self) -> any:
        self._logger.info('Fetching user login for email: {}'.format(self._email))
        with Database() as _db:
            sql = """SELECT pwd_hash FROM login WHERE email = %s"""
            result = _db.select_with_params(sql, [self._email, ])

        decrypted_pwd = self.cipher.decrypt(result[0][0])

        if decrypted_pwd != self._pwd:
            self._logger.error('fetch_user_login password mismatch for email: {}'.format(self._email))
            return 0, 'invalid_password'
        else:
            return 1, 'success'

    def create_user(self, firstname: str, lastname: str):
        self._logger.info('creating new user first name: {}, last name: {}'.format(firstname, lastname))
        try:
            with Database() as _db:
                self._logger.info('Creating new user: '******'success', 200

                return 0, 'Internal server error: unable to create user', 500
        except Exception as e:
            self._logger.info('create_user error: {}'.format(e))
            return 0, 'Internal Server Error: Unable to create user', 500

    def get_user_id(self):
        return self._user_id

    def get_user_email(self):
        return self._email

    def check_if_advisor_user(self):
        email = self._email.lower()
        with open('advisors.json') as f:
            data = json.load(f)
        if email in data:
            self._logger.info('check_if_advisor_user email: {}, result=True'.format(email))
            college_id = data[email]
            return 1, college_id
        return 0, None

    def get_user_role(self):
        self._logger.info('get_user_role for email: {}'.format(self._email))
        sql = """SELECT advisor FROM user WHERE email=%s"""
        with Database() as _db:
            result = _db.select_with_params(sql, [self._email])
        return result[0][0]

    def check_if_user_exists(self) -> bool:
        sql = """SELECT user_id FROM user WHERE email=%s"""
        with Database() as _db:
            result = _db.select_with_params(sql, [self._email, ])
        if result:
            return True
        return False

    def get_program_id(self, degree: str) -> str:
        self._logger.info('Get Program ID method for degree: {}'.format(degree))
        sql = "SELECT degree_prog_id FROM degree_prog WHERE program_code=%s"
        with Database() as _db:
            prog_id = _db.select_with_params(sql, [degree, ])
        return prog_id[0][0]

    def get_all_courses(self, program_id: str)-> any:
        self._logger.info('get_all_courses for program_id: {}'.format(program_id))
        sql = """SELECT c.course_id,
                    c.course_number,
                    c.course_name
                 FROM degree_req dr
                    JOIN course c
                        ON c.course_id = dr.course_id
                 WHERE dr.degree_prog_id = %s;"""
        with Database() as _db:
            result = _db.select_with_params(sql, [program_id, ])
        return_obj = []
        if result:
            for res in result:
                tmp_obj = {
                    "course_id": res[0],
                    "course_number": res[1],
                    "course_name": res[2]
                }
                return_obj.append(tmp_obj)
            return 1, return_obj

    def initial_update_schedule(self, data: any):
        self._logger.info('initial_update_schedule')
        try:
            user_id = self._fetch_user_id()

            sql = """INSERT INTO student_sched (user_id, class_id, course_code,
                        approved, class_status)
                     VALUES(%s,%s,%s,%s,%s)"""

            with Database() as _db:
                for item in data:
                    class_id = item.get('course_id')
                    course_code = item.get('value')
                    approval_status = 1
                    class_status = 'complete'

                    _db.execute_sql(sql, [user_id, class_id, course_code,
                                          approval_status, class_status, ])

            return 1, 'Success', 201
        except:
            return 0, 'Internal Server Error', 500

    def update_student_details(self, prog_id: str, advisor: str):
        self._logger.info('update_student_details for email: {}'.format(self._email))
        try:
            advisor_id = self._get_advisor_id(advisor)
            sql = """UPDATE student SET
                        degree_program_id= %s, advisor_id= %s, last_updated= %s 
                      WHERE user_id = %s"""
            student_id = self._fetch_user_id()
            now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

            with Database() as _db:
                _db.execute_sql(sql, [prog_id, advisor_id, now, student_id])
            return 1
        except:
            return 0

    def _get_advisor_id(self, advisor=None):
        self._get_student_info('get_advisor_id for advisor: {}'.format(self._email))
        if advisor:
            advisor_email = advisor
        else:
            advisor_email = self._email

        sql = "SELECT user_id FROM user WHERE email= %s"
        with Database() as _db:
            result = _db.select_with_params(sql, [advisor_email, ])

        if result:
            return result[0][0]
        else:
            return None

    def get_current_flowchart(self):
        self._logger.info('get_current_flowchart for user: {}'.format(self._email))
        user_id = self._fetch_user_id()
        degree_prog = self._get_student_degree_prog(user_id)
        success, data, code = self._get_student_progress(user_id, degree_prog)

        return success, data, code

    def _get_student_progress(self, user_id: str, degree_prog: str):
        sql = """
                 select
                    d.course_id,
                    c.course_number,
                    c.course_name,
                    c.credits
                 from degree_req d
                 join course c
                    on d.course_id = c.course_id
                where d.degree_prog_id = %s
                """
        with Database() as _db:
            courses = _db.select_into_list(sql, [degree_prog, ])

            sql = """SELECT
                        s.class_id,
                        s.course_code,
                        s.approved,
                        s.class_status
                      FROM student_sched s
                      WHERE s.user_id = %s;
                    """
            schedule = _db.select_into_list(sql, [user_id, ])

        return_obj = self.process_flowchart_results(courses, schedule)

        return 1, return_obj, 200

    def process_flowchart_results(self, courses: list, schedule: list):
        self._logger.info('process_flowchart_results')
        return_list = []
        tmp_list = []

        for item in schedule:
            tmp_list.append(item[0])

        index = 0
        for course in courses:
            course_id = course[0]
            course_num = course[1]
            course_name = course[2]
            credits = course[3]
            approved = 0
            class_status = 'required'

            if course_id in tmp_list:
                sched_index = 0
                for cls in schedule:
                    if cls and cls[0] == course_id:
                        course_num = cls[1]
                        approved = cls[2]
                        class_status = cls[3]
                        sched_index += 1
                        cls.clear()
                        break

                tmp_list.remove(course_id)

            return_list.append(
                {
                    'course_id': course_id,
                    'course_number': course_num,
                    'credits': credits,
                    'course_name': course_name,
                    'class_status': class_status,
                    'approved': approved
                }
            )

            index += 1

        return return_list

    def _get_student_degree_prog(self, user_id: str):
        self._logger.info('_get_student_dregree_prog student: {}'.format(self._email))
        sql = """SELECT degree_program_id FROM student
                  WHERE user_id= %s"""

        try:
            with Database() as _db:
                result = _db.select_with_params(sql, [user_id, ])
            if result:
                return result[0][0]
            else:
                return None
        except:
            return None

    @staticmethod
    def _update_result(result: any) -> any:
        tmp_list = []
        return_list = []
        for res in result:
            if res[4]:
                if res[4] in tmp_list:
                    course_code = None
                    approved = 0
                    class_status = 'required'
                else:
                    course_code = res[4]
                    tmp_list.append(res[4])
                    approved = 1
                    class_status = res[6] if res[6] else 'complete'
            else:
                course_code = res[4]
                approved = res[5] if res[5] else 0
                class_status = res[6] if res[6] else 'required'
            data_dict = {
                'course_id': res[0],
                'course_number': res[1],
                'course_name': res[2],
                'credits': res[3],
                'course_code': course_code,
                'approved': approved,
                'class_status': class_status
            }
            return_list.append(data_dict)
        return return_list

    def get_all_students(self) -> any:
        self._logger.info('get_all_students for advisor: {}'.format(self._email))
        advisor_id = self._get_advisor_id()
        sql = """
                SELECT 
                    user.user_id, 
                    user.email 
                FROM student
                JOIN degree_prog 
                    ON degree_prog.degree_prog_id = student.degree_program_id
                JOIN user
                    ON user.user_id = student.user_id
                JOIN advisor
                    ON advisor.college_id = degree_prog.college_id
                WHERE advisor.user_id = %s"""

        with Database() as _db:
            result = _db.select_into_list(sql, [advisor_id, ])

        if result:
            return 1, result, 200
        else:
            return 0, 'Internal Server Error', 500

    def admin_get_student_info(self, student_id: str) -> any:
        self._logger.info('admin_get_student_info for student email: {}'.format(self._email))
        return self._get_student_info(student_id)

    def _get_student_info(self, student_id: str) -> any:
        sql = """
                SELECT 
                    u.user_id,
                    u.email,
                    CONCAT(u.first_name, ' ', u.last_name) AS name,
                    d.program_name
                FROM user u
                JOIN student s 
                    ON s.user_id = u.user_id
                JOIN degree_prog d
                    ON s.degree_program_id = d.degree_prog_id
                WHERE u.user_id = %s;
            """
        with Database() as _db:
            user_info = _db.select_into_list(sql, [student_id, ])

        if user_info:
            degree_prog = self._get_student_degree_prog(student_id)
            success, data, code = self._get_student_progress(student_id, degree_prog)

            if success:
                return_object = self._process_student_admin_info(user_info, data)
                response = {
                    'success': success,
                    'return_obj': return_object,
                    'code': code
                }
                return success, response, code
        return 0, 'Internal Server Error', 500

    @staticmethod
    def _process_student_admin_info(student_info: any, data: any) -> any:
        return_obj = {}

        for info in student_info:
            return_obj['user_id'] = info[0]
            return_obj['email'] = info[1]
            return_obj['name'] = info[2]
            return_obj['program'] = info[3]

        return_obj['complete'] = []
        return_obj['required'] = []
        return_obj['waiting_approval'] = []
        return_obj['in_progress'] = []

        for course in data:
            status = course.get('class_status')
            del course['approved']

            if status == 'required':
                return_obj['required'].append(course)
            elif status == 'waiting_approval':
                return_obj['waiting_approval'].append(course)
            elif status == 'in_progress':
                return_obj['in_progress'].append(course)
            else:
                return_obj['complete'].append(course)

        return return_obj

    def update_student_progress(self, data: any) -> any:
        self._logger.info('update_student_progress for email: {}'.format(self._email))
        user_id = self._fetch_user_id()
        sql = """SELECT course_number FROM course WHERE course_id=%s"""
        insert_sql = """INSERT INTO student_sched (user_id, class_id, course_code,
                            approved, class_status)
                        VALUES(%s, %s, %s, %s, %s)
                     """
        selected_courses = []
        try:
            with Database() as _db:
                for course in data:
                    course_id = course.get('id')
                    course_name = course.get('value')
                    approved = course.get('approved')
                    status = course.get('status')

                    if course_name is None:
                        result = _db.select_into_list(sql, [course_id, ])
                        course_name = result[0][0]

                    if status == 'complete':
                        insert_sql = """UPDATE student_sched
                                        SET class_status=%s
                                        WHERE user_id=%s 
                                            AND class_id=%s
                                            AND course_code=%s
                                      """
                        params = [status, user_id, course_id, course_name, ]
                    else:
                        selected_courses.append(course_name)
                        params = [user_id, course_id, course_name, approved, status, ]
                    _db.execute_sql(insert_sql, params)

                message = "Attention Advisors:\n\n{} has requested approval to take the following courses:\n".format(self._email)
                for c in selected_courses:
                    message = message + "\t" + c + "\n"

                message = message + 'Please address this request at your earliest convenience.\n\n'
                message = message + "Sincerely,\n\nLTU Progress Tracker"

                email_handler = EmailHandler('*****@*****.**')
                email_handler.send_email(message)

                response = {
                    'code': 201,
                    'success': 1,
                    'message': 'success'
                }
            return 1, response , 201
        except Exception as e:
            return 0, 'Internal Server Error', 500

    def admin_update_student_progress(self, student_id: str, approved: any, denied: any, new_status: str) -> any:
        self._logger.info('admin_update_student_info student_id: {}'.format(student_id))
        for k, v, in approved.items():
            course_code = k
            course_id = v

            sql = """UPDATE student_sched 
                     SET approved=1, class_status=%s
                     WHERE user_id=%s
                        AND class_id=%s
                        AND course_code=%s"""

            try:
                with Database() as _db:
                    _db.execute_sql(sql, [new_status, student_id, course_id, course_code, ])

            except Exception as e:
                self._logger.error('admin_update_student_info error: {}'.format(e))
                return 0, 'Internal Server Error', 500

        for k, v in denied.items():
            course_code = k
            course_id = v

            sql = """DELETE FROM student_sched 
                     WHERE user_id=%s
                        AND class_id=%s
                        AND course_code=%s"""

            try:
                with Database() as _db:
                    _db.execute_sql(sql, [student_id, course_id, course_code, ])

            except Exception as e:
                self._logger.error('admin_update_student_info error: {}'.format(e))
                return 0, 'Internal Server Error', 500

        response = {
            'code': 201,
            'success': 1,
            'message': 'success'
        }

        return 1, response, 201
Ejemplo n.º 3
0
def serve():
    sess = request.values.get('sess')
    if not (type(sess) is str):
        return "Invalid parameter: sess", 400
    ach = request.values.get('achievments');
    if not (type(ach) is str):
        return "Invalid parameter: achievments", 400
    cipher = AESCipher(enc_key)
    new = False
    if ach == "":
        achievments = set()
    else:
        decr = cipher.decrypt(ach)
        if not decr:
            return "Invalid parameter: achievments", 400
        achievments = pickle.loads(decr)
    if sess == "":
        session = {
            "current_location": "",
            "previous_location": "",
            "visited_locations": set(),  # index
            "completed_actions": set(),  # index
            "items": set(),
            'current_events': {},
            'current_action': {},
            "log": "",
            "log_here": True,
            "started": False,
            "facts": set(),
            "flamethrower_count": 0,
            "ending": 0,
            "result": GameResult.CONTINUE
        }
        new = True
    else:
        decr = cipher.decrypt(sess)
        if not decr:
            return "Invalid parameter: sess", 400
        session = pickle.loads(decr)
    session['log'] = ''
    game = Game(True)
    game.achievments = achievments
    game.started = session['started']
    for key in session:
        setattr(game, key, session[key])

    inp = request.values.get('input')
    if not (type(inp) is str):
        return "Invalid parameter: input", 400
    if inp == "unload":
        return "", 200
    inp = inp.strip()
    if inp == "" and session['started']:
        return "> ", 200
    try:
        width = int(request.values.get('width'))
    except:
        width = 100
    game._drawer.set_term_width(width)
    if new:
        game.draw_logo()
        game.write_intro()
        game._drawer.log += "\n\nНажмите ENTER для продолжения..."
    elif game.started:
        if game.get_result() == GameResult.CONTINUE:
            game.apply_user_event(inp)
        elif game.get_result() == GameResult.NEED_INPUT:
            game.apply_user_input(inp)
        if game.get_result() == GameResult.WIN:
            game.logging("")
            game.logging("Поздравляем, Вы прошли игру и выжили!")
            game.logging("")
            game.logging("Концовка {} из {}".format(game.ending, game.total_endings))
            game.logging("")
            game._drawer.log = "\\cmd::quit" + game._drawer.log
            do_award = ("Ending_%d" % game.ending) not in game.achievments
            game.achievments.add("Ending_%d" % game.ending)
            if do_award:
                game.award_achievments("Ending_%d" % game.ending)
        elif game.get_result() == GameResult.LOSE:
            game.logging("")
            game.logging("К сожалению, Вы проиграли!")
            game.logging("")
            game.logging("Концовка {} из {}".format(game.ending, game.total_endings))
            game.logging("")
            game._drawer.log = "\\cmd::quit" + game._drawer.log
            do_award = ("Ending_%d" % game.ending) not in game.achievments
            game.achievments.add("Ending_%d" % game.ending)
            if do_award:
                game.award_achievments("Ending_%d" % game.ending)
        else:
            game.award_achievments()
            game._drawer.log += "> "
        game.award_achievments()
    else:
        game.start_game()
        game._drawer.log += "> "
        game.started = True
        session['started'] = True
    log = game._drawer.log
    for key in session:
        if hasattr(game, key):
            session[key] = getattr(game, key)
    del session['log']
    ret = cipher.encrypt(pickle.dumps(session))
    ach = cipher.encrypt(pickle.dumps(game.achievments))
    return ret + "~~SEPARATOR~~" + ach + "~~SEPARATOR~~" + log