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')
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()
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')
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')
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')
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')
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()
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')
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')