Example #1
0
def reset():
    """ POST complete a password reset request.

        Parameters
        ----------
        secret: str
            secret sent in email
        password: str
            new password

        Notes
        -----
        returns an empty response body on success.

        Raises
        ------
        BadRequest
            Some part of the required parameters is missing.
        NoRecovery
            No recovery has been requested.
    """
    redis_client = current_app.config['RDSCXN']
    try:
        d = request.get_json(force=True)
        secret, password = d['secret'], d['password']
    except:
        return errorResponse('Bad request')

    for uid in redis_client.keys("user*"):
        if secret == redis_client.get(f"recovery{uid}"):
            redis_client.hset(uid, 'password',
                              generate_password_hash(password))
            redis_client.delete(f"recovery{uid}")
            return jsonResponse()
    return errorResponse('No recovery requested, or recovery expired')
Example #2
0
def pictureDownload():
    """ POST download the profile picture for the given user.

        Parameters
        ----------
        uid: str
            uid of requested profile

        Returns
        -------
        profilePicUrl: str
            base64 encoded data string or None

        Raises
        ------
        BadRequest
            Some part of the required parameters is missing.
        UidNotFound
            Could not find the user in the database.
    """
    redis_client = current_app.config['RDSCXN']
    if request.method == 'POST':
        data = request.get_json()
        if not data:
            error = 'Data Body Required'
            return errorResponse(error)
        uid = data['uid'] if 'uid' in data.keys() else None
        if uid is None:
            error = 'uid is required.'
            return errorResponse(error)
        profilePicUrl = redis_client.get("picture{}".format(uid)) or ""
        return jsonResponse({'profilePicUrl': profilePicUrl})
    return jsonResponse()
Example #3
0
def login():
    """ POST login as a user.

    Parameters
    ------
    email: str
    password: str

    Returns
    ------
    uid: int
        unique ID that idenfies this user.

    Raises
    ------
    InvalidEmail
        Email does not exist in system.
    InvalidPassword
        Password does not exist in system.

    Notes
    -----
    This function also sets a encrypted session cookie which can only be
    decrypted server-side.

    See Also
    --------
    backend.auth.getuid : getuid from session cookie.
    """
    redis_client = current_app.config['RDSCXN']
    if request.method == 'POST':
        data = request.get_json(force=True)
        email = data['email']
        password = data['password']
        error = None
        user = None

        for uid in redis_client.keys("user*"):
            u = redis_client.hgetall(uid)
            if u is not None and 'email' in u.keys() and u['email'] == email:
                user = u
                break

        if user is None or 'uid' not in user.keys():
            error = 'Invalid email.'
        elif not check_password_hash(user['password'], password):
            error = 'Incorrect password.'

        if error is None:
            session.clear()
            session['user_id'] = user['uid']

            return jsonResponse({'uid': user['uid']})

        return errorResponse(error)
    return errorResponse('POST to this endpoint')
Example #4
0
def edit():
    """ POST change attributes of a user profile.

        Parameters
        ----------
        firstName: str
        lastName: str
        major: str
        year: int
        classes: list(str)
        uid: str

        Notes
        -----
        returns empty json object on success.

        Raises
        ------
        BadRequest
            Some part of the required parameters is missing.
        UidNotFound
            Could not find the user in the database.
    """
    redis_client = current_app.config['RDSCXN']
    if request.method == 'POST':
        data = request.get_json()
        if not data:
            error = 'Data Body Required'
            return errorResponse(error)
        fname = data['firstName'] if 'firstName' in data.keys() else ""
        lname = data['lastName'] if 'lastName' in data.keys() else ""
        major = data['major'] if 'major' in data.keys() else ""
        year = data['year'] if 'year' in data.keys() else ""
        classes = data['classes'] if 'classes' in data.keys() else []
        uid = data['uid'] if 'uid' in data.keys() else None
        error = None
        if uid is None:
            error = "uid required"
            return errorResponse(error)
        if not redis_client.keys("user{}".format(uid)):
            error = "User with UID {} not found".format(uid)

        if error is None:
            redis_client.hset("user{}".format(uid), key="fname", value=fname)
            redis_client.hset("user{}".format(uid), key="lname", value=lname)
            redis_client.hset("user{}".format(uid), key="major", value=major)
            redis_client.hset("user{}".format(uid), key="year", value=year)
            redis_client.delete("classes{}".format(uid))
            for c in classes:
                redis_client.rpush("classes{}".format(uid), c)
            return jsonResponse()

        return errorResponse(error)
    return errorResponse('POST to this endpoint')
Example #5
0
def forgot():
    """ POST submit a password reset request. Emails the user a recovery link.

        Parameters
        ----------
        email: str
            email to reset to

        Notes
        -----
        returns an empty response body on success.

        Raises
        ------
        BadRequest
            Some part of the required parameters is missing.
        EmailNotFound
            no user associated with email.
        ServerBad
            Mailserver is not functioning.
    """

    redis_client = current_app.config['RDSCXN']
    try:
        email = request.get_json(force=True)['email']
    except:
        return errorResponse('Bad request')

    for uid in redis_client.keys("user*"):
        if email == redis_client.hget(uid, 'email'):
            secret = ''.join(random.choices(string.ascii_letters, k=20))
            try:
                subprocess.call(recoverystr.format(email=email,
                                                   secret=secret,
                                                   baseurl=baseurl),
                                shell=True)
                redis_client.setex(f"recovery{uid}", 600, secret)
                return jsonResponse()
            except:
                return errorResponse('Server bad')

    return errorResponse('Email not found')
Example #6
0
def class_list():
    """ POST Get the class list for a given subject.

    Parameters
    ------
    subjectArea: str

    Returns
    ------
    uid: list[str]
        list of all classes associated with the given subject area.

    Raises
    ------
    BadRequest
        Some part of the required parameters is missing.
    """
    response = None
    if request.method == 'POST':
        data = request.get_json()
        if not data:
            return errorResponse('Data Body Required')

        subjectArea = data.get('subjectArea')
        if not subjectArea:
            return errorResponse('Subject Area Required')

        this_folder = os.path.dirname(os.path.abspath(__file__))
        class_file = open(os.path.join(this_folder, 'resources/classes.csv'),
                          mode='r')
        reader = csv.reader(class_file)

        classes = []
        for row in reader:
            if row[0] == subjectArea:
                classes.append(row[0] + ' ' + row[2])

        class_file.close()
        return jsonResponse({"classList": classes})
    return errorResponse('POST to this endpoint')
Example #7
0
def pictureUpload():
    """ POST upload a picture for the given user.

        Parameters
        ----------
        uid: str
            uid of requested profile
        profilePicUrl: str
            base64 encoded data string

        Notes
        -----
        method returns empty json object on success.

        Raises
        ------
        BadRequest
            Some part of the required parameters is missing.
        UidNotFound
            Could not find the user in the database.
    """
    redis_client = current_app.config['RDSCXN']
    if request.method == 'POST':
        data = request.get_json()
        if not data:
            error = 'Data Body Required'
            return errorResponse(error)
        uid = data['uid'] if 'uid' in data.keys() else None
        profilePicUrl = data['profilePicUrl'] if 'profilePicUrl' in data.keys(
        ) else None
        if uid is None:
            error = 'uid is required.'
            return errorResponse(error)
        elif profilePicUrl is None:
            error = 'profilePicUrl is required.'
            return errorResponse(error)
        redis_client.set("picture{}".format(uid), profilePicUrl)
        return jsonResponse()
    return jsonResponse()
Example #8
0
def get():
    """ POST get attributes of a user profile.

        Parameters
        ----------
        uid: str
            uid of requested profile

        Returns
        -------
        firstName: str
        lastName: str
        major: str
        year: int
        classes: list(str)
        uid: str
        notifications: list(Notifications)
        Messages: list(Messages)
        isTutor: bool

        Raises
        ------
        BadRequest
            Some part of the required parameters is missing.
        UidNotFound
            Could not find the user in the database.

        See Also
        --------
        backend.message: messages module
        backend.notification: notifications modle
    """
    redis_client = current_app.config['RDSCXN']
    if request.method == 'POST':
        data = request.get_json()
        if not data:
            error = 'Data Body Required'
            return errorResponse(error)
        uid = data['uid'] if 'uid' in data.keys() else None
        error = None
        if uid is None:
            error = "uid required"
            return errorResponse(error)
        user = redis_client.hgetall("user{}".format(uid))
        if user is None:
            error = "User with UID {} not found".format(uid)

        if error is None:
            classes = redis_client.lrange("classes{}".format(uid), 0, -1)
            return jsonResponse({
                'error':
                False,
                'firstName':
                user['fname'] if 'fname' in user.keys() else None,
                'lastName':
                user['lname'] if 'lname' in user.keys() else None,
                'year':
                user['year'] if 'year' in user.keys() else None,
                'major':
                user['major'] if 'major' in user.keys() else None,
                'classes':
                classes,
                'isTutor':
                user['isTutor'] == "1" if 'isTutor' in user.keys() else None
            })

        return errorResponse(error)
    return errorResponse('POST to this endpoint')
Example #9
0
def register():
    """ POST Register a new user.

    Parameters
    ------
    firstName: str
    lastName: str
    email: str
    password: str
    isTutor: bool

    Returns
    ------
    uid: int
        unique ID that idenfies this user.

    Raises
    ------
    BadRequest
        Some part of the required parameters is missing.
    UsersExists
        User with the same email has already registered.
    """
    redis_client = current_app.config['RDSCXN']
    if request.method == 'POST':
        data = request.get_json(force=True)
        fname = data['firstName']
        lname = data['lastName']
        email = data['email']
        password = data['password']
        isTutor = int(data['isTutor'])
        error = None

        if not fname:
            error = 'First Name is required.'
        elif not lname:
            error = 'Last Name is required.'
        elif not email:
            error = 'Email is required.'
        elif not password:
            error = 'Password is required.'

        else:
            for uid in redis_client.keys("user*"):
                if email == redis_client.hget(uid, 'email'):
                    error = 'Email {} is already registered.'.format(email)

        if error is None:
            next_uid = redis_client.get('next_uid')
            redis_client.incr('next_uid')
            redis_client.hmset(
                "user{}".format(next_uid), {
                    'fname': fname,
                    'lname': lname,
                    'email': email,
                    'password': generate_password_hash(password),
                    'isTutor': isTutor,
                    'uid': next_uid
                })
            redis_client.bgsave()
            return jsonResponse({'uid': next_uid})

        return errorResponse(error)
    return errorResponse('POST to this endpoint')