Exemplo n.º 1
0
def add_analytics_wishlist(type_of_wishlist, email, first_name, last_name,
                           os_info, ip_addr):
    """
    Helper method that takes in all parameters and inserts analytics in db.
    """
    timestamp = get_current_time()

    # write calls to analytics for google signup
    analytics_to_add = {
        "type_of_call": "Wishlist",
        "type_of_wishlist": type_of_wishlist,
        "email": email,
        "first_name": first_name,
        "last_name": last_name,
        "timestamp": timestamp,
        "os_info": os_info,
        "ip_address": ip_addr,
        "location": get_location_info(ip_addr)
    }

    if not validate_analytics_auth(analytics_to_add):
        return False

    # add analytics to db
    grades_db.analytics_user_data.insert_one(analytics_to_add)
Exemplo n.º 2
0
def reset_wishlist():
    """
    Method to reset the wishlist to what the user inputted
    after deleting selected items.
    """
    #save data
    data = json.loads(request.get_data())

    #decode token and save new wishlist data
    new_wishlist = data["wishlist"]
    user_data = jwt.decode(data["token"], SECRET,
                           algorithms=["HS256"])["identity"]

    #use user_query as it removes wishlist and searches
    #for the correct user whose info was provided
    user_query = {
        "first_name": user_data["first_name"],
        "last_name": user_data["last_name"],
        "email": user_data["email"]
    }

    if not validate_analytics_auth(user_query):
        return json.dumps({"success": False}), 400, {
            "ContentType": "application/json"
        }

    #update db with new wishlist
    update_wishlist = grades_db.users.update_one(
        user_query, {"$set": {
            "wishlist": new_wishlist
        }})

    return json.dumps({"success": True}), 200, {
        "ContentType": "application/json"
    }
Exemplo n.º 3
0
def save_user_major():
    """
    Method to save a user's chosen major in the database for future use.
    """
    #save token from headers
    token = request.headers["Token"]
    user_data = jwt.decode(token, SECRET, algorithms=['HS256'])["identity"]

    user_query = {
        "first_name": user_data["first_name"],
        "last_name": user_data["last_name"],
        "email": user_data["email"]
    }

    if not validate_analytics_auth(user_query):
        return json.dumps({"success": False}), 400, {
            "ContentType": "application/json"
        }

    #save new user major information
    major = request.headers["Major"]
    major_query = {"major": major}

    #update db for user with inputted major
    user_db_data = grades_db.users.update_one(user_query,
                                              {"$set": major_query})

    return json.dumps({"success": True}), 200, {
        "ContentType": "application/json"
    }
Exemplo n.º 4
0
def view_wishlist():
    """
    Method to display the wishlist for a particular user whose 
    token is sent by the frontend.
    """
    token = request.headers["Token"]
    ip_addr = request.access_route[0]

    # get user agent
    user_agent = str(request.headers.get("User-Agent"))
    try:
        os_info = user_agent.split(')')[0].split('(')[1].strip()
    except:
        os_info = "Unknown"

    user_data = jwt.decode(token, SECRET, algorithms=['HS256'])["identity"]

    user_query = {
        "first_name": user_data["first_name"],
        "last_name": user_data["last_name"],
        "email": user_data["email"]
    }

    if not validate_analytics_auth(user_query):
        return json.dumps({"success": False}), 400, {
            "ContentType": "application/json"
        }

    #find wishlist for user
    user_db_data = grades_db.users.find_one(user_query)

    #collect wishlist from data
    wishlist = user_db_data["wishlist"]

    #go through each term and ensure that
    #it has courses
    for term in list(wishlist):

        #if term is empty, remove it from the items
        #to be rendered to the user.
        if len(wishlist[term]) == 0:
            del wishlist[term]

    # write calls to analytics for google signup
    add_analytics_wishlist("View", user_data["email"], user_data["first_name"],
                           user_data["last_name"], os_info, ip_addr)

    #print(wishlist)
    return json.dumps(wishlist), 200, {'ContentType': 'application/json'}
Exemplo n.º 5
0
def check_user_major():
    """
    Method to check whether a given user in the DB has selected
    a major. If not, it returns false and the frontend prompts 
    the user to select a major. If so, it returns true and the
    frontend gives back information for the major to the user.
    """
    #save token from headers
    token = request.headers["Token"]
    user_data = jwt.decode(token, SECRET, algorithms=['HS256'])["identity"]
    
    user_query = {
        "first_name": user_data["first_name"],
        "last_name": user_data["last_name"],
        "email": user_data["email"]
    }

    if not validate_analytics_auth(user_query):
        return json.dumps({"success":False}),400,{"ContentType":"application/json"}

    #find wishlist for user
    user_db_data = grades_db.users.find_one(
        user_query
    )
    #check for major
    try:
        #save major name
        user_major = user_db_data["major"]

        #save major query
        major_query = {
            "major": user_major
        }
        #save major courses
        major_courses = grades_db.majordatancsu.find_one(major_query)["courses"]

        return_json = {
            "major": user_major,
            "courses": major_courses,
            "success": True
        }
            
        #return info on user major and courses
        return json.dumps(return_json), 200, {'ContentType':'application/json'}
        
    #if the user does not have a major
    except:

        return json.dumps({"success": False}), 500, {"ContentType":"application/json"}
Exemplo n.º 6
0
def add_course_to_wishlist():
    """
    Method to process input from frontend containing course
    to add to wishlist and which user the course is for.
    """
    #save data
    data = json.loads(request.get_data())
    ip_addr = request.access_route[0]

    # get user agent
    user_agent = str(request.headers.get("User-Agent"))
    try:
        os_info = user_agent.split(')')[0].split('(')[1].strip()
    except:
        os_info = "Unknown"

    #decode token and save course to add to wishlist
    wishlist_course_data = data["course_data"]
    user_data = jwt.decode(data["token"], SECRET,
                           algorithms=['HS256'])["identity"]

    user_query = {
        "first_name": user_data["first_name"],
        "last_name": user_data["last_name"],
        "email": user_data["email"]
    }

    if not validate_analytics_auth(user_query):
        return json.dumps({"success": False}), 400, {
            "ContentType": "application/json"
        }

    #current wishlist
    current_wishlist = grades_db.users.find_one(user_query)["wishlist"]

    #check for duplicates in wishlist
    for wishlist_term in current_wishlist.keys():
        for wishlist_item in current_wishlist[wishlist_term]:
            if wishlist_item == wishlist_course_data:
                return json.dumps({
                    "success": False,
                    "duplicate": True
                }), 404, {
                    "ContentType": "application/json"
                }

    #term_to_update
    term_to_update = wishlist_course_data["Semester"]

    try:
        current_wishlist[term_to_update].append(wishlist_course_data)
    except:
        current_wishlist[term_to_update] = [wishlist_course_data]
    #update db with wishlist course
    add_wishlist = grades_db.users.update_one(
        user_query, {"$set": {
            "wishlist": current_wishlist
        }}, upsert=True)

    # write calls to analytics for google signup
    add_analytics_wishlist("Add", user_data["email"], user_data["first_name"],
                           user_data["last_name"], os_info, ip_addr)

    #return true if successful
    return json.dumps({'success': True}), 200, {
        'ContentType': 'application/json'
    }
Exemplo n.º 7
0
def google_auth():
    """
    Method to handle user signing in via Google.
    This method will either connect the user to their account in the database,
    or create a new account for them.
    """
    google_user_data = json.loads(request.get_data())

    try:
        token = google_user_data['token']
        idinfo = {}
        
         # Specify the CLIENT_ID of the app that accesses the backend:
        for client_id in CLIENT_IDS:
            try:
                idinfo = id_token.verify_token(token, requests.Request(), client_id)
                break
            except: pass
    
        # save information based on token
        user_email = idinfo['email']
        user_first = idinfo['given_name']
        user_last = idinfo['family_name']

    except:
        return 'Invalid token', 400
     
    user_query = {
        "email": google_user_data["email"]
    }
    
    # check that the user email is equivalent to the token
    if user_query['email'] != user_email:
    
        return 'Account does not match token', 400
    
    ip_addr = request.access_route[0]
    # get user agent
    user_agent = str(request.headers.get("User-Agent"))
    try:
        os_info = user_agent.split(')')[0].split('(')[1].strip()
    except:
        os_info = "Unknown"
    
    # protects against noSQL injection
    if not is_clean_email(user_query['email']):
    
        #return that user made invalid email
        return json.dumps({"success":False, "message": "email was not clean."}), 400, {"ContentType":"application/json"}
    
    #attempt to find user with information given
    google_user = grades_db.users.find_one(user_query)
    
    if google_user == None:
        """
        Options:  
            - here we can add a user to the database with no password, and 
            thus no one can access their account unless they sign in with their Google account

            - alternatively, we could redirect a user to a signup page on the frontend
            where they can enter a password
        """
        #save user information
        user = {
                "first_name": google_user_data["first_name"],
                "last_name": "",
                "email": google_user_data["email"],
                "hashed_pw":"",
                "wishlist": {},
                "os_info": [os_info],
                "ip_address_list": [ip_addr],
                "timestamp": get_current_time(),
                "location": get_location_info(ip_addr),
                "account_type": "Google"
            }
        
        try:
            user["last_name"] = google_user_data["last_name"]
        except:
            pass

        # check that user info is valid
        if not validate_analytics_auth(user):
            return json.dumps({"success":False}), 400, {"ContentType":"application/json"}

        #add user to db
        grades_db.users.insert_one(user)

        #send the user an email
        send_signup_email(google_user_data["first_name"], google_user_data["email"])

        #try to find existing user
        current_user = grades_db.users.find_one(user)

        #get user info
        user_info = get_user_token(current_user)
        user_info["type"] = "SignUp"

        # write calls to analytics for google signup
        analytics = add_analytics_auth("SignUp", "Google", google_user_data["email"], google_user_data["first_name"], google_user_data["last_name"], os_info, ip_addr)
        
        # if analytics was malicious, return false
        if not analytics:
            return json.dumps({"success":False}), 400, {"ContentType":'application/json'}

        #return that user was signed up
        return json.dumps(user_info), 200, {"ContentType":"application/json"}

    else:
        """
        Send user to their homepage
        """
        user_info = get_user_token(google_user)
        
        # ensure that os and ip are clean
        if not is_clean_query(os_info) or not is_clean_query(ip_addr):
        
            return json.dumps({"success":False, "message": "IP/OS was not clean."}), 400, {"ContentType":"application/json"}
        
        # update os and ip address in db
        update_os_ip(google_user, os_info, ip_addr)

        # write calls to analytics for google signup
        analytics = add_analytics_auth("Login", "Google", google_user_data["email"], google_user_data["first_name"], google_user_data["last_name"], os_info, ip_addr)
        
        # if analytics was malicious, return false
        if not analytics:
        
            return json.dumps({"success":False, "message": "Analytics was not clean."}), 400, {"ContentType":'application/json'}
        
        return json.dumps(user_info), 200,
        {'ContentType':'application/json'}


    return json.dumps({'success':False}), 404, {"ContentType":"application/json"}
Exemplo n.º 8
0
def sign_up():
    """
    Method to enter new user information in the 
    database and hash authenticated password.
    """
    #get user data
    user_data = json.loads(request.get_data())
    ip_addr = request.access_route[0]
    # get user agent
    user_agent = str(request.headers.get("User-Agent"))
    try:
        os_info = user_agent.split(')')[0].split('(')[1].strip()
    except:
        os_info = "Unknown"

    #use hash library to hash the password
    # generate new salt, and hash a password
    custom_algo = pbkdf2_sha256.using(rounds=NUM_ROUNDS)
    hashed_pw = custom_algo.hash(user_data["password"].encode("utf-8"))

    # remove dollar sign and save indices
    dollar_sign_indices = [i for i,j in enumerate(list(hashed_pw)) if j=='$']    
    hashed_pw = hashed_pw.replace('$', '')

    #save user information
    user = {
        "first_name":user_data["first_name"],
        "last_name":user_data["last_name"],
        "email":user_data["email"],
        "hashed_pw":hashed_pw,
        "wishlist": {},
        "os_info": [os_info],
        "ip_address_list": [ip_addr],
        "timestamp": get_current_time(),
        "location": get_location_info(ip_addr),
        "account_type": "PackRanks"
    }

    # check that user info is valid
    if not validate_analytics_auth(user):
        return json.dumps({"success":False}), 400, {"ContentType":"application/json"}

    #try to find existing user
    current_user = grades_db.users.find_one({"email":user["email"]})
    if current_user != None:
        return json.dumps({'success':False}), 404, {"ContentType":"application/json"}

    #if no existing user, add to db
    else:
        
        # save dollar sign indices and save in db
        user['dollar_sign_indices'] = dollar_sign_indices
        grades_db.users.insert_one(user)

        #send user confirmation email!
        first_name = user["first_name"]
        last_name = user["last_name"]
        email = user["email"]

        #send an email to user who signed up
        send_signup_email(first_name, email)

        # write calls to analytics
        analytics = add_analytics_auth("SignUp", "PackRanks", user_data["email"], user_data["first_name"], user_data["last_name"], os_info, ip_addr)

        # if analytics was malicious, return false
        if not analytics:
            return json.dumps({"success":False}), 400, {"ContentType":'application/json'}

        return json.dumps({'success':True}), 200, {'ContentType':'application/json'} 
Exemplo n.º 9
0
def upvote_course():
    """
    Method that attempts to upvote course for given user.
    """
    #save data
    data = eval(request.get_data())
    ip_addr = request.access_route[0]

    # get user agent
    user_agent = str(request.headers.get("User-Agent"))
    try:
        os_info = user_agent.split(')')[0].split('(')[1].strip()
    except:
        os_info = "Unknown"

    #decode token and save course to add to wishlist
    course_data = data["course_data"]
    user_data = jwt.decode(data["token"], SECRET,
                           algorithms=['HS256'])["identity"]

    user_query = {
        "first_name": user_data["first_name"],
        "last_name": user_data["last_name"],
        "email": user_data["email"]
    }

    if not validate_analytics_auth(user_query):
        return json.dumps({"success": False}), 400, {
            "ContentType": "application/json"
        }

    # save information to uniquely identify course
    course_query = {
        "course_name": course_data['Catalog Link'][0],
        "semester": course_data['Semester'],
        "section": course_data['Section'],
        "professor": course_data['RateMyProfessor Link'][0]
    }

    # get user information on whether they have upvoted this course
    user = grades_db.users.find_one(user_query)
    user_has_upvoted = False

    # get current upvotes
    try:
        current_upvotes = grades_db.catalogncsu.find_one(
            course_query)['user_upvotes']
    except:
        current_upvotes = 0

    try:
        user_upvoted_courses = user['user_upvoted_courses']
    except:
        user_upvoted_courses = []

    for course in user_upvoted_courses:
        course_info = {
            "course_name": course_data['Catalog Link'][0],
            "semester": course_data['Semester'],
            "section": course_data['Section'],
            "professor": course_data['RateMyProfessor Link'][0]
        }
        if course_info == course_query:
            user_has_upvoted = True
            break

    # add analytics for the upvote
    analytics = add_analytics_upvote(course_query, user_data['email'],
                                     user_data['first_name'],
                                     user_data['last_name'], os_info, ip_addr)

    if not analytics:
        return json.dumps({"success": False}), 400, {
            "ContentType": "application/json"
        }

    if not user_has_upvoted:
        # add course to list of courses user has upvoted
        grades_db.users.update_one(
            user_query, {"$push": {
                "user_upvoted_courses": course_data
            }})

        # upvote course
        grades_db.catalogncsu.update_one(
            course_query, {"$set": {
                "user_upvotes": current_upvotes + 1
            }})

    else:
        return json.dumps({"success": False}), 200, {
            "ContentType": "application/json"
        }

    return json.dumps({"success": True}), 200, {
        "ContentType": "application/json"
    }
Exemplo n.º 10
0
def deptRoute():
    """
    This function receives a call from the Dept component of 
    the ReactJS and returns a JSON of the top 5 courses from the 
    database based on the metrics calculated.
    It takes into account the level, department, and term that 
    the course is offered in.
    """
    # set valid coures types
    VALID_COURSE_TYPES = ["Lecture", "Problem Session"]

    #access MongoDb database
    crowdsourced = MongoClient(DBSTR)
    grades_db = crowdsourced.Coursesnc

    #get which GEP was requested
    #print(request.headers)
    dept_requested = request.headers.get("Dept")
    term_requested = request.headers.get("term")
    level_min = request.headers.get("level_min")
    level_max = request.headers.get("level_max")
    num_to_show = int(request.headers.get("num_courses"))
    ip_addr = request.access_route[0]
    loc_info = get_location_info(ip_addr)

    # get user agent
    user_agent = str(request.headers.get("User-Agent"))
    try:
        os_info = user_agent.split(')')[0].split('(')[1].strip()
    except:
        os_info = "Unknown"

    # write calls to analytics
    analytics_to_add = {
        "type_of_call": "Dept",
        "dept_requested": dept_requested,
        "term_requested": term_requested,
        "level_min": level_min,
        "level_max": level_max,
        "num_courses": num_to_show,
        "timestamp": get_current_time(),
        "os_info": os_info,
        "ip_address": ip_addr,
        "location": loc_info
    }

    # check that analytics is clean
    if not validate_analytics_auth(analytics_to_add):
        return json.dumps({"success": False}), 400, {
            "ContentType": "application/json"
        }

    # add analytics to db
    grades_db.analytics_user_data.insert_one(analytics_to_add)

    if (not str.isnumeric(level_min)
            and level_min != "ANY") or (not str.isnumeric(level_max)
                                        and level_max != "ANY"):
        return ["NotNumeric"]

    if (level_min != "ANY" and level_max != "ANY"):
        level_l = [int(level_min), int(level_max)]
        if level_l[1] < level_l[0]:
            return ["Min>Max"]
        if len([i for i in level_l if i < 100 or i > 899 and i != "ANY"]) > 0:
            return ["NotNumeric"]

    # check if health
    if "HES" in dept_requested:
        course_types = ["Lecture", "Problem Session"]

    # temporary fix, still need to figure out which depts
    # should not show problem sessions
    elif 'ACC' in dept_requested:
        course_types = ["Lecture"]
    else:
        course_types = VALID_COURSE_TYPES

    course_type_search = '|'.join(course_types)

    # convert level min and max to valid
    if level_min == 'ANY':
        level_min = 100
    if level_max == 'ANY':
        level_max = 899

    level_min = int(level_min)
    level_max = int(level_max)

    #access  collection with the correct data
    catalog_data = grades_db.catalogncsu.aggregate([
        {
            "$match": {
                "department": dept_requested,
                "course_number": {
                    "$gte": level_min,
                    "$lte": level_max
                },
                "course_type": {
                    "$regex": course_type_search
                },
                "semester": {
                    "$regex": term_requested
                },
                "professor": {
                    "$ne": "Staff"
                }
            }
        },
        #group by professor and add unique sections and raw_official_scores
        #to aggregation
        {
            "$group": {
                "_id": {
                    "course_name": "$course_name",
                    "professor": "$professor",
                    "semester": "$semester"
                },
                "section": {
                    "$addToSet": "$section"
                },
                "raw_official_score": {
                    "$addToSet": "$raw_official_score"
                }
            }
        },
        {
            "$unwind": "$raw_official_score"
        },
        {
            "$sort": {
                "raw_official_score": -1
            }
        },
        {
            "$limit": NUM_COURSES
        }
    ])

    #save data to dictionary
    relevant_data = save_course_data(catalog_data, num_to_show)

    #del catalog_data["_id"]
    if len(relevant_data) == 0:
        return []
    return relevant_data
Exemplo n.º 11
0
def gepRoute():
    """
    This function receives a call from the GEP component of 
    the ReactJS and returns a JSON of the top 5 courses from the 
    database based on the metrics calculated.
    """

    #access MongoDb database
    crowdsourced = MongoClient(DBSTR)
    grades_db = crowdsourced.Coursesnc

    #get which GEP was requested
    gep_requested = request.headers.get("GEP")
    term_requested = request.headers.get("term")
    num_to_show = int(request.headers.get("num_courses"))
    ip_addr = request.access_route[0]
    loc_info = get_location_info(ip_addr)

    # get user agent
    user_agent = str(request.headers.get("User-Agent"))
    try:
        os_info = user_agent.split(')')[0].split('(')[1].strip()
    except:
        os_info = "Unknown"
    # write calls to analytics
    analytics_to_add = {
        "type_of_call": "GEP",
        "gep_requested": gep_requested,
        "term_requested": term_requested,
        "num_courses": num_to_show,
        "timestamp": get_current_time(),
        "os_info": os_info,
        "ip_address": ip_addr,
        "location": loc_info
    }

    # check that analytics is clean
    if not validate_analytics_auth(analytics_to_add):
        return json.dumps({"success": False}), 400, {
            "ContentType": "application/json"
        }

    # add analytics to db
    grades_db.analytics_user_data.insert_one(analytics_to_add)

    course_types = ['Lecture']
    if gep_requested == "HES":
        course_types.append("Problem Session")
    course_type_s = '|'.join(course_types)
    #if additional breadth, either hum or ss
    if gep_requested == "ADDTL":
        #print("ADDLT")
        geps_req = ["HUM", "SS"]
        geps_regex = '|'.join(geps_req)
    else:
        geps_req = [gep_requested]
        geps_regex = "|".join(geps_req)

    #access  collection with the correct data
    catalog_data = grades_db.catalogncsu.aggregate([
        {
            "$match": {
                "gep": {
                    "$regex": geps_regex
                },
                "course_type": {
                    "$regex": course_type_s
                },
                "semester": {
                    "$regex": term_requested
                },
                "professor": {
                    "$ne": "Staff"
                }
            }
        },
        #group by professor and add unique sections and raw_official_scores
        #to aggregation
        {
            "$group": {
                "_id": {
                    "course_name": "$course_name",
                    "professor": "$professor",
                    "semester": "$semester"
                },
                "section": {
                    "$addToSet": "$section"
                },
                "raw_official_score": {
                    "$addToSet": "$raw_official_score"
                }
            }
        },
        {
            "$unwind": "$raw_official_score"
        },
        {
            "$sort": {
                "raw_official_score": -1
            }
        },
        {
            "$limit": NUM_COURSES
        }
    ])

    relevant_data = save_course_data(catalog_data, num_to_show)
    return relevant_data