diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..4549ab9 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 7f2f268..06304c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .aws-sam/ +venv/ __pycache__ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 457f44d..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.analysis.typeCheckingMode": "basic" -} \ No newline at end of file diff --git a/code/api.py b/code/api.py index a1721d2..2f00da8 100644 --- a/code/api.py +++ b/code/api.py @@ -7,6 +7,6 @@ def lambda_handler(event, context): queryParams = {} print(f"INFO: Processing request: method {method}, path {path}.") try: - return mapper.execute(method, path, queryParams, event['requestContext']['authorizer']) + return mapper.execute(method, path, queryParams, event['requestContext']['authorizer'], event['body']) except KeyError: - return mapper.execute(method, path, queryParams, {}) \ No newline at end of file + return mapper.execute(method, path, queryParams, {}, "") \ No newline at end of file diff --git a/code/mapper.py b/code/mapper.py index 1230327..28c45c4 100644 --- a/code/mapper.py +++ b/code/mapper.py @@ -1,14 +1,15 @@ from student.upload import get_upload_url from recruiter.get import get_resume_url +from code.student.user import get_user, update_user, register_user import json import traceback -def healthzHandler(context, queryParams): +def healthzHandler(context, queryParams, body): return { "statusCode": 200, "body": "UP" } -def notImplemented(context, queryParams): +def notImplemented(context, queryParams, body): return { "statusCode": 404, "body": "Method not implemented." @@ -23,7 +24,7 @@ def badRequest(message): "statusCode": 400, "body": f"Bad request - {message}" } -def getUploadUrl(context, queryParams): +def getUploadUrl(context, queryParams, body): rval = {} try: url: str = get_upload_url(f"resume_{context['uid']}.pdf") @@ -38,7 +39,7 @@ def getUploadUrl(context, queryParams): traceback.print_exc() return rval -def getResumeUrl(context, queryParams): +def getResumeUrl(context, queryParams, body): rval = {} if not 'uid' in queryParams: return badRequest("Query parameter 'uid' is missing.") @@ -57,16 +58,46 @@ def getResumeUrl(context, queryParams): traceback.print_exc() return rval +def getUser(context, queryParams, body): + rval = {} + try: + user: str = get_user(queryParams['uid']) + rval = { + "statusCode": 200, + "body": json.dumps({ + "user": user + }) + } + except: + rval = serverError("Could not get user.") + traceback.print_exc() + return rval + +def updateUser(context, queryParams, body): + rval = {} + if body == "": + return + try: + update_user(queryParams['uid']) + except: + rval = serverError("Could not get user.") + traceback.print_exc() + return rval + find_handler = { "GET": { "/api/v1/healthz": healthzHandler, "/api/v1/student/getUploadURL": getUploadUrl, "/api/v1/recruiter/getResumeUrl": getResumeUrl, "/api/v1/recruiter/getResumeListings": notImplemented, - } + "/api/v1/student": getUser + }, + "PUT": { + "/api/v1/student": updateUser + }, } -def execute(method: str, path: str, queryParams: dict, context: dict) -> dict: +def execute(method: str, path: str, queryParams: dict, context: dict, body: str) -> dict: try: func: function = find_handler[method][path] return func(context, queryParams) diff --git a/code/student/user.py b/code/student/user.py new file mode 100644 index 0000000..142ca04 --- /dev/null +++ b/code/student/user.py @@ -0,0 +1,114 @@ +import boto3, os + +class Student: + uid: int + name: str + email: str + linkedin: str + degree: int + majors: list + minors: list + gpa: float + year: str + bio: str + skills: list + position: int + work_auth: bool + sponsor: bool + + def __init__(self, uid, name, email, linkedin, degree, majors, minors, gpa, year, bio, skills, position, work_auth, sponsor): + self.uid: uid + self.name: name + self.email: email + self.linkedin: linkedin + self.degree: degree + self.majors: majors + self.minors: minors + self.gpa: gpa + self.year: year + self.bio: bio + self.skills: skills + self.position: position + self.work_auth: work_auth + self.sponsor: sponsor + +client = boto3.client('dynamodb', region_name=os.environ.get('AWS_REGION', 'us-east-2')) +dynamo_table = 'infra-resume-book-users' + +def get_user(id: int) -> str | None: + response = client.get_item( + TableName=dynamo_table, + Key={ + 'id': id + } + ) + + +def update_user(id, body): + temp = {} + attributes = {"name", "email", "linkedin", "degree", "majors", "minors", "gpa", "year", "bio", "skills", "position", "sponsor"} + for key, value in body.items(): + if key in attributes: + temp[key] = value + + response = client.update_item( + TableName=dynamo_table, + Key={ + 'id': id + }, + AttributeUpdates = { + 'id': { + 'Value' : temp, + }, + }, + # ExpressionAttributeNames={ + # '#n': "name", + # '#e': "email", + # '#l': "linkedin", + # '#d': "degree", + # '#ma': "majors", + # '#mi': "minors", + # '#g': "gpa", + # '#y': "year", + # '#b': "bio", + # '#sk': "skills", + # '#p': "position", + # '#sp': "sponsor" + # }, + # ExpressionAttributeValues={ + # ':n': {'S': name}, + # ':e': {'S': email}, + # ':l': {'S': linkedin}, + # ':d': {'N': degree}, + # ':ma': {'SS': majors}, + # ':mi': {'SS': minors}, + # ':g': {'N': gpa}, + # ':y': {'S': year}, + # ':b': {'S': bio}, + # ':sk': {'SS': skills}, + # ':p': {'N': position}, + # ':w': {'BOOL': work_auth}, + # ':ma': {'BOOL': sponsor}, + # } +) + +def register_user(uid, name, email, linkedin, degree, majors, minors, gpa, year, bio, skills, position, work_auth, sponsor): + client.put_item( + TableName=dynamo_table, + Item={ + "uid": {'N': uid}, + "name": {'S': name}, + "email": {'S': email}, + "linkedin": {'S': linkedin}, + "degree": {'N': degree}, + "majors": {'SS': majors}, + "minors": {'SS': minors}, + "gpa": {'N': gpa}, + "year": {'S': year}, + "bio": {'S': bio}, + "skills": {'SS': skills}, + "position": {'N': position}, + "work_auth": {'BOOL': work_auth}, + "sponsor": {'BOOL': sponsor} + } + ) \ No newline at end of file diff --git a/create_table.py b/create_table.py new file mode 100644 index 0000000..458fec1 --- /dev/null +++ b/create_table.py @@ -0,0 +1,31 @@ +import boto3 + +def create_devices_table(dynamodb=None): + dynamodb = boto3.resource( + 'dynamodb', region_name='us-east-2') + table = dynamodb.create_table( + TableName='infra-resume-book-users', + KeySchema=[ + { + 'AttributeName': 'uin', + 'KeyType': 'HASH' # Partition key + } + ], + AttributeDefinitions=[ + { + 'AttributeName': 'uin', + 'AttributeType': 'N' + } + ], + ProvisionedThroughput={ + 'ReadCapacityUnits': 10, + 'WriteCapacityUnits': 10 + } + ) + return table + + +if __name__ == '__main__': + device_table = create_devices_table() + # Print tablle status + print("Status:", device_table.table_status) \ No newline at end of file diff --git a/test.json b/test.json new file mode 100644 index 0000000..6ea9aa5 --- /dev/null +++ b/test.json @@ -0,0 +1,18 @@ +{ + "resource": "/myresource", + "path": "/api/v1/healthz", + "httpMethod": "GET", + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8" + }, + "queryStringParameters": { + "param1": "value1", + "param2": "value2" + }, + "pathParameters": null, + "stageVariables": null, + "requestContext": {}, + "body": "request body goes here" +} \ No newline at end of file