Ejemplo n.º 1
0
    def post(self):
        """
            Pushes a new job to be tracked under a specific board owned by a user
            Parameters:
                - user_id
                - board_id
                - job_to_track
        """
        printColoured(" * Tracking a new job", colour="yellow")
        request_params = dict(request.get_json())
        try:
            board_id = request_params["board_id"]
            user_id = request_params["user_id"]
            job_to_track = request_params["job_to_track"]
        except KeyError as err:
            raise InvalidUserInput(
                description="Missing mandatory fields: {}".format(err))

        job_id = add_job(board_id, user_id, job_to_track)

        push_stat(
            board_id, {
                "timestamp": int(time.time() - OFFSET),
                "activity": "application",
                "job_id": job_id
            })

        return job_to_track
Ejemplo n.º 2
0
    def put(self):
        """
            Updates a tracked job
            Parameters:
                - user_id
                - board_id
                - job_id
                - updated_job
        """
        printColoured(" * Updating an existing tracked job", colour="yellow")
        requests_params = dict(request.get_json())
        user_id = requests_params["user_id"]
        board_id = requests_params["board_id"]
        job_id = requests_params["job_id"]
        updated_job = requests_params["updated_job"]

        # Push stat and eliminate duplicates if they occur after pushing
        push_stat(
            board_id, {
                "timestamp": time.time() - OFFSET,
                "activity": updated_job["current_status"],
                "job_id": job_id
            })
        eliminate_stat_duplicates(board_id, job_id,
                                  updated_job["current_status"])

        return update_job(user_id, board_id, job_id, updated_job)
Ejemplo n.º 3
0
def pretty_print_dict(d, indent=1):
    """ Pretty print a dictionary """
    for key, value in d.items():
        printColoured('\t' * indent + str(key) + ":", colour="yellow")
        if isinstance(value, dict):
            pretty_print_dict(value, indent+1)
        else:
            printColoured('\t' * (indent+1) + str(value), colour="blue")
Ejemplo n.º 4
0
 def get(self):
     """
         Fetches a list of all users on the platform
         Parameters:
             - Nothing so far. TODO
     """
     printColoured(" * Getting a list of all user", colour="yellow")
     return get_users()
Ejemplo n.º 5
0
 def post(self):
     printColoured(" * Logging in a user", colour="yellow")
     request_params = dict(request.form)
     email = request_params["email"]
     password = request_params["password"]
     user_id = login_user(email, password)
     return {
         "user_id": user_id,
         "token": "EMPTY",
     }
Ejemplo n.º 6
0
 def delete(self):
     """
         Removes a tracked job and all its associated data
     """
     printColoured(" * Removing a tracked job")
     request_params = dict(request.form)
     user_id = request_params["user_id"]
     board_id = request_params["board_id"]
     job_id = request_params["job_id"]
     return delete_job(user_id, board_id, job_id)
Ejemplo n.º 7
0
 def get(self):
     """
         Gets the comments SENT TO a given user
         Parameters:
             - user_id
     """
     printColoured(" * Fetching list of all comments for a user", colour="yellow")
     request_params = dict(request.args)
     user_id = request_params["user_id"]
     return get_comments(user_id)
Ejemplo n.º 8
0
 def delete(self):
     """
         Removes a vote for a given comment
         Parameters:
             - user_id
             - comment_id
     """
     printColoured(" * Removing a vote for a comment", colour="yellow")
     request_params = dict(request.get_json())
     user_id = request_params["user_id"]
     comment_id = request_params["comment_id"]
     clear_vote(user_id, comment_id)
Ejemplo n.º 9
0
    def delete(self):
        """
            Deletes a comment.

            Parameters:
                - comment_id
        """
        printColoured(" * Deleting a comment", colour="yellow")
        request_params = dict(request.get_json())
        comment_id = request_params["comment_id"]
        delete_comment(comment_id)
        return comment_id
Ejemplo n.º 10
0
    def put(self):
        """
            Sets a new comment for an existing comment document

            Parameters:
                - comment_id
                - new_comment
        """
        printColoured(" * Updating a comment", colour="yellow")
        request_params = dict(request.get_json())
        comment_id = request_params["comment_id"]
        new_comment = request_params["new_comment"]
        edit_comment(comment_id, new_comment)
        return new_comment 
Ejemplo n.º 11
0
def login_handler():
    printColoured(" * Attempting Google login", colour="yellow")
    # Find out what URL to hit for Google login
    google_provider_cfg = get_google_provider_cfg()
    authorization_endpoint = google_provider_cfg["authorization_endpoint"]

    # Use library to construct the request for Google login and provide
    # scopes that let you retrieve user's profile from Google
    request_uri = client.prepare_request_uri(
        authorization_endpoint,
        redirect_uri=REDIRECT_URI,
        scope=["openid", "email", "profile"],
    )
    return redirect(request_uri)
Ejemplo n.º 12
0
def get_job_postings(location, query, results_per_page, page, sort_criteria):
    """ 
        Gets job postings
    """
    cj = CareerjetAPIClient("en_AU")
    jobs_json = cj.search({
        "location":
        location,
        "keywords":
        query,
        "affid":
        "213e213hd12344552",
        "pagesize":
        results_per_page,
        "page":
        page,
        "sort":
        sort_criteria,
        "user_ip":
        "11.22.33.44",
        "url":
        "http://www.example.com/jobsearch",
        "user_agent":
        "Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0"
    })
    try:
        for each_job in jobs_json["jobs"]:
            # Strip all leading non-alphanumeric characters
            each_job["description"] = re.sub(
                "^[^A-Za-z0-9]*", "", each_job["description"]).capitalize()
            # Truncate duplicate whitespaces
            each_job["description"] = re.sub("\s+", " ",
                                             each_job["description"])
            each_job["description"] = re.sub("<b>", "",
                                             each_job["description"])
            each_job["description"] = re.sub("</b>", "",
                                             each_job["description"])
            # Capitalise all words occurring after punctuation such as . or !
            p = re.compile(r'(?<=[\.\?!]\s)(\w+)')
            each_job["description"] = p.sub(
                lambda match: match.group().capitalize(),
                each_job["description"])
    except Exception as err:
        printColoured("Failed to fetch jobs '{}'. Error: {}".format(
            query, err),
                      colour="red")
        raise InvalidUserInput(
            description="Failed to find jobs for '{}'".format(query))
    return dict(jobs_json)
Ejemplo n.º 13
0
    def get(self):
        """
            Getting company info [using opencorporates or wikipedia]

            Parameters:
                - company
                - disable_jobs (optional param)
        """
        # Filter for the jobs that actually belong to company_name
        printColoured(" * Fetching company details", colour="yellow")
        request_params = dict(request.args)
        company_name = request_params["company"]
        if company_name == "":
            # Returns nothing if given nothing
            return {
                "company_info": {
                    "company_details": "",
                    "company_name": company_name
                },
            }

        company_details = get_company_details(company_name)

        if "disable_jobs" in request_params and request_params[
                "disable_jobs"] == 'true':
            return {
                "company_info": {
                    "company_details": company_details,
                    "company_name": company_name
                },
            }

        job_resp = get_job_postings("Sydney", company_name, 10, 1, "relevance")

        job_list = job_resp["jobs"]
        job_list = list(
            filter(lambda x: x["company"].lower() == company_name.lower(),
                   job_list))

        print(len(job_list))
        return {
            "company_info": {
                "company_details": company_details,
                "company_name": company_name
            },
            "jobs": [*job_list]
        }
Ejemplo n.º 14
0
    def post(self):
        """
            Upvotes or downvotes a given comment.

            Parameters:
                - user_id            (the ID of the user attempting to vote the comment)
                - comment_id
                - increment_amount   (negative values indicate decrement)
        """
        printColoured(" * Voting a comment", colour="yellow")
        request_params = dict(request.get_json())
        user_id = request_params["user_id"]
        comment_id = request_params["comment_id"]
        increment_amount = request_params["increment_amount"]

        # TODO: Check if the user is authorised to vote this comment`
        vote_comment(user_id, comment_id, increment_amount)
Ejemplo n.º 15
0
    def get(self):
        """
            Given the job post URL, scrapes the given URL and returns extracted fields and an 
            HTML body to render 

            Parameters:
                - job_post_url
            Returns:
                {
                    post_details: "",
                    fields: {}
                }
        """
        printColoured(" * Getting job post details", colour="yellow")
        request_params = dict(request.args)
        url = request_params["url"]
        return get_content(url)
Ejemplo n.º 16
0
 def post(self):
     """
         Parameters:
             - sender_user_id   
             - receiver_user_id
             - comment
     """
     printColoured(" * Posting a comment", colour="yellow")
     request_params = dict(request.get_json())
     sender_user_id = request_params["sender_user_id"]
     receiver_user_id = request_params["receiver_user_id"]
     comment = request_params["comment"]
     post_comment(
         sender_user_id,
         receiver_user_id,
         comment
     )
     return "TODO: successful request data"
Ejemplo n.º 17
0
 def post(self):
     printColoured(" * Registering a new user", colour="yellow")
     request_params = dict(request.form)
     try:
         username = request_params["username"]
         email = request_params["email"]
         password = request_params["password"]
         user_id = add_user(
             username, email, password,
             "https://t4.ftcdn.net/jpg/02/15/84/43/360_F_215844325_ttX9YiIIyeaR7Ne6EaLLjMAmy4GvPC69.jpg"
         )
         return {
             "user_id": user_id,
             "token": "EMPTY",
         }
     except Exception as err:
         printColoured(err, colour="red")
         raise err
Ejemplo n.º 18
0
def error_handler(err):
    """
        Returns JSON containing details of the failure event including the
        status code, name and message. This JSON message is returned to the client
        everytime the route handlers encounter a problem, for example, invalid user 
        input.
    """
    response = err.get_response()
    try:
        printColoured(" ➤ Error: {} {}".format(err, err.description),
                      colour="red")
        response.data = dumps({
            "code": err.code,
            "name": "System Error",
            "message": err.description
        })
        response.content_type = 'application/json'
        return response
    except:
        printColoured(" ➤ Error: {}".format(err), colour="red")
        response.data = dumps({"code": err.code, "name": "System Error"})
        response.content_type = 'application/json'
        return response
Ejemplo n.º 19
0
def get_company_details(company):
    """
        Params: 
            - company (str)
        Returns:
            - company_description (str)
    """
    wiki_wiki = Wikipedia('en')

    try:
        # try different methods for searching  for the company until something good is returned
        page = wiki_wiki.page(company + " (company)")

        if not page.exists():
            page = wiki_wiki.page(company)
    except Exception as err:
        printColoured(err, colour="red")
        raise InvalidUserInput(
            description="Connection timed out. Please try again later")

    company_data = page.text
    company_description = company_data.split("\n")[0]
    return company_description
Ejemplo n.º 20
0
    def get(self):
        """
            Parameters:
                - location           (str)
                - query              (str)
                - results_per_page   (int)
                - page               (int)
                - sort_criteria      (str - "relevance", "date", "salary")
            Returns a JSON object: 
                {
                    jobs: [
                        {
                            company,
                            title,
                            locations,
                            url,
                            date,
                            description,
                            salary,
                            salary_type,
                            salary_currency_code,
                            salary_min,
                            salary_max,
                            site,
                        },
                        ...
                    ]
                }
        """
        # Run `pydoc careerjet_api` to see documentation.
        printColoured(" * Getting a list of jobs")
        request_params = dict(request.args)
        pretty_print_dict(request_params)

        # TODO: Checking if all mandatory requests parameters have been sent through
        if not all(
                param in request_params and request_params for param in
            ["location", "query", "results_per_page", "page", "sort_criteria"
             ]):
            printColoured(" * Missing mandatory fields", colour="red")
            raise InvalidUserInput(
                description="Request parameter is missing mandatory fields")

        try:
            return get_job_postings(request.args.get("location"),
                                    request.args.get("query"),
                                    request.args.get("results_per_page"),
                                    request.args.get("page"),
                                    request.args.get("sort_criteria"))
        except Exception as err:
            printColoured(
                " * CareerJet API Client failed to fetch jobs. Error: {}".
                format(err),
                colour="red")
            raise InvalidUserInput(
                description="Couldn't find any jobs. Try a different query")
Ejemplo n.º 21
0
    def get(self):
        """
            Fetches user activity data for each date.
            Preprocesses it so that each date has a list of activities the user did.
            This makes it easy for the frontend to render graphically

            Parameters:
                - user_id
                - board_id
                - start time
                - end time
        """
        printColoured(" * Getting user activity stats", colour="yellow")
        request_params = dict(request.args)
        user_id = request_params["user_id"]
        board_id = request_params["board_id"]

        stats = fetch_stats(user_id, board_id)

        # Sort timestamps into ascending order
        stats.sort(key=lambda x: x["timestamp"])
        start_date = datetime.fromtimestamp(int(request_params["start_time"]))
        end_date = datetime.fromtimestamp(int(request_params["end_time"]))

        delta = end_date - start_date
        if (delta.days < 0):
            raise InvalidUserInput(
                description=
                "Invalid time range. Check that the start time is after end time"
            )

        date_list = {}

        # METHOD 1 - iterating through the entire stats array for each day
        #            takes longer but more confident that it is more accurate
        for i in range(delta.days + 2):
            day = start_date + timedelta(days=i)
            day = day.strftime('%d/%m/%Y')
            date_list[day] = []
            for j in range(len(stats)):
                curr_day = datetime.fromtimestamp(
                    stats[j]['timestamp']).strftime('%d/%m/%Y')
                if curr_day != day:
                    continue
                date_list[day].append((stats[j]['activity']))
                date_list[day].sort()

        # METHOD 2 - stop iterating through the stats array when dates no longer match
        #            keeps track of last position in stats array so no need to iterate through days that have already been matched
        #            takes shorter time but might be less accurate
        '''for i in range(delta.days + 2):
            day = (start_date + timedelta(days = i)).strftime('%d/%m/%Y')
            k = 0
            for j in range(k, len(stats)):
                curr_day = datetime.fromtimestamp(stats[j]['timestamp']).strftime('%d/%m/%Y')
                if curr_day < day:
                    continue
                elif curr_day > day:
                    k = j
                    break

                if day not in date_list.keys():
                    activity_list = []

                activity_list.append((stats[j]['activity']))
                activity_list.sort()
                date_list[day] = activity_list'''

        # For each day between start time and end time,
        return date_list
Ejemplo n.º 22
0
def print_pretty_json(struct, colour="yellow"):
    """ Pretty print a JSON-serialisable data structure """
    printColoured(json.dumps(struct, indent=4, sort_keys=True), colour=colour)
Ejemplo n.º 23
0
def login_callback_handler():
    printColoured(
        " * Entering Google login callback. Redirect URL: {}. Authorisation response: {}"
        .format(REDIRECT_URI, request.url),
        colour="yellow")
    # Get authorization code Google sent back to you
    code = request.args.get("code")

    # Find out what URL to hit to get tokens that allow you to ask for
    # things on behalf of a user
    google_provider_cfg = get_google_provider_cfg()
    token_endpoint = google_provider_cfg["token_endpoint"]

    # Prepare and send a request to get tokens! Yay tokens!
    token_url, headers, body = client.prepare_token_request(
        token_endpoint,
        authorization_response=substitute_https(request.url),
        redirect_url=REDIRECT_URI,
        code=code)
    token_response = requests.post(
        token_url,
        headers=headers,
        data=body,
        auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET),
    )

    printColoured(" * Parsing tokens: {}".format(token_response),
                  colour="yellow")

    # Parse the tokens!
    client.parse_request_body_response(json.dumps(token_response.json()))

    # Now that you have tokens (yay) let's find and hit the URL
    # from Google that gives you the user's profile information,
    # including their Google profile image and email
    userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
    uri, headers, body = client.add_token(userinfo_endpoint)

    userinfo_response = requests.get(uri, headers=headers, data=body)

    # You want to make sure their email is verified.
    # The user authenticated with Google, authorized your
    # app, and now you've verified their email through Google!
    if userinfo_response.json().get("email_verified"):
        # unique_id = userinfo_response.json()["sub"]
        users_email = userinfo_response.json()["email"]
        picture = userinfo_response.json()["picture"]
        users_name = userinfo_response.json()["given_name"]
    else:
        return "User email not available or not verified by Google.", 400

    # Register the user, or log them in
    # Workaround for Google auth: the callback in the Flask server redirects back
    # to the homepage and embeds the token and id in the URL like this:
    #     /home/user_id/token
    # The token and ID are extracted and removed out of the URL and saved to the
    # client's cookies
    try:
        printColoured(" * Signing them up", colour="yellow")
        # FIXME: Temporary password
        new_user_id = add_user(users_name, users_email, "asdfasdf", picture)
        # FIXME: No token
        return redirect("{}/home?user_id={}&token={}".format(
            CLIENT_HOME_URL, new_user_id, "EMPTY TOKEN"))
    except Exception as err:
        printColoured(err, color="red")
        printColoured(
            " * Failed. They are probably an existing user: {}".format(
                users_email),
            colour="yellow")
        existing_user_id = login_user(users_email, "asdfasdf")
        # FIXME: No token
        return redirect("{}/home?user_id={}&token={}".format(
            CLIENT_HOME_URL, existing_user_id, "EMPTY TOKEN"))
Ejemplo n.º 24
0
from pathlib import Path
from JobTracker.utils.colourisation import printColoured
from JobTracker.utils.debug import print_env_variables
from flask_pymongo import PyMongo
from JobTracker.exceptions import error_handler
from flask_cors import CORS
import pymongo
import os
from os.path import join, dirname

# Setting the environment variables:
env_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path=env_path)

# Creating the Flask app instance
printColoured(" * Initialising Flask application")
app = Flask(__name__, static_url_path="/static")
CORS(app)

app.config["RESUME_UPLOAD_PATH"] = 'resumes'

# ===== Debug and Testing =====
print_env_variables()

# This must be set to 1 to bypass InsecureTransportError when testing locally
# Source: https://stackoverflow.com/questions/27785375/testing-flask-oauthlib-locally-without-https/27785830
if os.getenv("ENV_TYPE") == "development":
    printColoured(" * Disabling secure transport for Google OAuth in development", colour="yellow")
    os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

# ===== App Configuration =====
Ejemplo n.º 25
0
def print_env_variables():
    """
        Lists out critical environment variables present in this project
    """
    printColoured(" * === Environment variables in .env ===", colour="red")
    printColoured(" * Google Client ID:      {}".format(os.getenv("GOOGLE_CLIENT_ID")), colour="red")
    printColoured(" * Google Client Secret:  {}".format(os.getenv("GOOGLE_CLIENT_SECRET")), colour="red")
    printColoured(" * MongoDB URI:           {}".format(os.getenv("DB_URI")), colour="red")
    printColoured(" * Environment type:      {}".format(os.getenv("ENV_TYPE")), colour="red")
    
    # These MUST match the URIs saved on https://console.cloud.google.com/ for this project
    printColoured(" * === Google Auth URIs ===", colour="red")
    printColoured(" * DEV_REQUEST_REDIRECT_URI:   {}".format(os.getenv("DEV_REQUEST_REDIRECT_URI")), colour="red")
    printColoured(" * PROD_REQUEST_REDIRECT_URI:  {}".format(os.getenv("PROD_REQUEST_REDIRECT_URI")), colour="red")