Skip to content

Feature/task03/completeUserId/tasks_function #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ dist
# TernJS port file
.tern-port

#VsCode Configs
.vscode
.idea

#artillery report output
test/artillery/report.json
Expand All @@ -116,3 +115,4 @@ DS_Store

# ignore .vscode
.vscode/

4 changes: 4 additions & 0 deletions functions/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,12 @@ appsettings.json
local.settings.json
.python_packages

.idea


# Vscode
.vscode
vscode
.DS_Store
DS_Store

167 changes: 117 additions & 50 deletions functions/HttpTriggerAPIUsersIdTask/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import json
import pyodbc
import logging
import pypyodbc
import os
import azure.functions as func
import datetime
import json


# to handle datetime with JSON
# It serialize datetime by converting it into string
def default(dateHandle):
if isinstance(dateHandle, (datetime.datetime, datetime.date)):
return dateHandle.isoformat()

# to handle datetime with JSON
# It serialize datetime by converting it into string
Expand All @@ -12,52 +19,112 @@ def default(o):
return o.isoformat()

def main(req: func.HttpRequest) -> func.HttpResponse:
# define the server and database names
server = os.environ["ENV_DATABASE_SERVER"]
database = os.environ["ENV_DATABASE_NAME"]
username = os.environ["ENV_DATABASE_USERNAME"]
password = os.environ["ENV_DATABASE_PASSWORD"]

# define the connection string
driver = '{ODBC Driver 17 for SQL Server}'
cnxn = "Driver={};Server={};Database={};Uid={};Pwd={};Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;".format(
driver, server, database, username, password)

user_id = req.route_params.get('userId')

if not user_id:
return func.HttpResponse('Bad Request', status_code=400 )
else:
logging.info(
'Python HTTP trigger for /users/userId endpoint.')

method = req.method
user_id = req.route_params.get('userId')

try:
conn = connect_to_db()
except (pyodbc.DatabaseError, pyodbc.InterfaceError) as e:
logging.critical("connection failed: " + e.args[0])
logging.debug("Error: " + e.args[1])
return func.HttpResponse(status_code=500)
logging.debug("Connected to DB successfuly!")

try:
with pypyodbc.connect(cnxn) as conn:
return tasks_query(conn, user_id)
except pypyodbc.DatabaseError as err:
if err.args[0] == '28000':
return func.HttpResponse(
"Unauthorized User",
status_code=403
)

# create the connection cursor
def tasks_query(conn, user_id):
# create the query
with conn.cursor() as cursor:
cursor.execute(
"SELECT * FROM tasks WHERE userId={}".format(user_id))
tasks = list(cursor.fetchall())

if len(tasks) == 0:
return func.HttpResponse(
"no task found for this user!",
status_code=200
)
else:
tasks = [tuple(task) for task in tasks]
# Empty data list
data = []
columns = [column[0] for column in cursor.description]

for task in tasks:
data.append(dict(zip(columns, task)))

return func.HttpResponse(json.dumps(data, default=default), status_code=200, mimetype="application/json")
if method == "GET":
logging.debug("trying to get one user with id {} all tasks".format(user_id))
all_tasks_by_userId = get_user_tasks(conn, user_id)
logging.debug("tasks retrieved successfully!")
return all_tasks_by_userId

elif method == "POST":
logging.debug("trying to add one task to tasks")
task_req_body = req.get_json()
new_task_id = add_tasks(conn, task_req_body, user_id)
logging.debug("task added successfully!")
return new_task_id

else:
logging.warn(f"{method} method is not allowed for this endpoint")
return func.HttpResponse(status_code=405)

#displays erros encountered when API methods were called
except Exception as e:
return func.HttpResponse("Error: %s" % str(e), status_code=500)
finally:
conn.close()
logging.debug('Connection to DB closed')


def connect_to_db():
# Database credentials.
server = os.environ["ENV_DATABASE_SERVER"]
database = os.environ["ENV_DATABASE_NAME"]
username = os.environ["ENV_DATABASE_USERNAME"]
password = os.environ["ENV_DATABASE_PASSWORD"]
driver = '{ODBC Driver 17 for SQL Server}'

connection_string = "Driver={};Server={};Database={};Uid={};Pwd={};Encrypt=yes;TrustServerCertificate=yes;Connection Timeout=30;".format(
driver, server, database, username, password)
return pyodbc.connect(connection_string)


def get_user_tasks(conn, userId):
with conn.cursor() as cursor:
logging.debug("execute query")
cursor.execute("SELECT * FROM tasks WHERE userId=?", userId)

logging.debug("Fetching all records")
tasks = list(cursor.fetchall())

# Clean up to put them in JSON.
task_data = [tuple(task) for task in tasks]
# Empty data list
tasks = []
columns = [column[0] for column in cursor.description]

for task in task_data:
tasks.append(dict(zip(columns, task)))

logging.debug("tasks received!!")

return func.HttpResponse(json.dumps(tasks, default=default), status_code=200, mimetype="application/json")


def add_tasks(conn, task_req_body, user_id):
# First we want to ensure that the request has all the necessary fields
logging.debug("Testing the add new user request body for necessary fields...")
try:
assert "title" in task_req_body, "New user request body did not contain field: 'title'"
assert "description" in task_req_body, "New user request body did not contain field: 'description'"
except AssertionError as task_req_body_content_error:
logging.error("New user request body did not contain the necessary fields!")
return func.HttpResponse(task_req_body_content_error.args[0], status_code=400)
logging.debug("New task request body contains all the necessary fields!")

with conn.cursor() as cursor:
# get task data
userId = user_id
title = task_req_body["title"]
description = task_req_body["description"]
createdDate = datetime.datetime.now()
task_params = (userId, title, description, createdDate)
# Create the query
add_task_query = """
SET NOCOUNT ON;
DECLARE @NEWID TABLE(ID INT);
INSERT INTO tasks (userId, title, description, createdDate)
OUTPUT inserted.taskId INTO @NEWID(ID)
VALUES(?, ?, ?, ?);
SELECT ID FROM @NEWID
"""
logging.debug("execute query")
cursor.execute(add_task_query, task_params)
# Get the user id from cursor
task_id = cursor.fetchval()
logging.info(task_id)
logging.debug("task with id {} added!".format(task_id))
return func.HttpResponse(json.dumps({task_id}, default=default), status_code=200, mimetype="application/json")
2 changes: 1 addition & 1 deletion functions/HttpTriggerAPIUsersIdTask/function.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"get",
"post"
],
"route":"{userId:int?}/tasks"
"route": "users/{userId:int?}/tasks"
},
{
"type": "http",
Expand Down