From 0248dc01d1bfeac0c25ed119766490bca05a1a10 Mon Sep 17 00:00:00 2001 From: Brennan Holzer Date: Fri, 4 Oct 2019 13:14:05 -0500 Subject: [PATCH 1/2] Add user_id to every authenticated request --- bundle_lambda_layer | 2 +- main.tf | 20 +++++--------- src/api/bake_tasks/create.rb | 1 + src/api/projects/create.rb | 26 +++++++++++------- src/api/projects/destroy.rb | 14 +++++++++- src/api/projects/index.rb | 1 + src/api/projects/show.rb | 7 ++++- src/api/render_tasks/create.rb | 1 + src/api/render_tasks/index.rb | 1 + src/api/render_tasks/show.rb | 1 + src/lambda_layer/ruby/.DS_Store | Bin 6148 -> 6148 bytes src/lambda_layer/ruby/lib/shared.rb | 9 ++++-- .../ruby/lib/shared/authenticated_user.rb | 9 ++++++ src/lambda_layer/ruby/lib/shared/model.rb | 2 +- .../ruby/lib/shared/models/project.rb | 9 ++++++ 15 files changed, 74 insertions(+), 29 deletions(-) create mode 100644 src/lambda_layer/ruby/lib/shared/authenticated_user.rb create mode 100644 src/lambda_layer/ruby/lib/shared/models/project.rb diff --git a/bundle_lambda_layer b/bundle_lambda_layer index ecc9d9e..6cb8e21 100755 --- a/bundle_lambda_layer +++ b/bundle_lambda_layer @@ -1,4 +1,4 @@ -!#/bin/bash +#!/bin/bash cd ./src/lambda_layer/ruby diff --git a/main.tf b/main.tf index 5c44883..b8c53a1 100644 --- a/main.tf +++ b/main.tf @@ -177,24 +177,19 @@ module "bpi_emitter" { # project_init_queue = aws_sqs_queue.project_init_queue.id # } -resource "aws_dynamodb_table" "projects_table" { - name = "FarmProjects" +resource "aws_dynamodb_table" "farm_table" { + name = "FarmTable" billing_mode = "PAY_PER_REQUEST" - hash_key = "ProjectId" + hash_key = "hk" + range_key = "rk" attribute { - name = "ProjectId" + name = "hk" type = "S" } -} - -resource "aws_dynamodb_table" "application_settings" { - name = "FarmApplicationSettings" - billing_mode = "PAY_PER_REQUEST" - hash_key = "SettingName" attribute { - name = "SettingName" + name = "rk" type = "S" } } @@ -209,8 +204,7 @@ module "api" { client_endpoint = "https://${aws_s3_bucket.client_bucket.website_endpoint}" dynamo_tables = { - projects = aws_dynamodb_table.projects_table.name, - application_settings = aws_dynamodb_table.application_settings.name + projects = aws_dynamodb_table.farm_table.name } } diff --git a/src/api/bake_tasks/create.rb b/src/api/bake_tasks/create.rb index c08cd11..2b844cd 100644 --- a/src/api/bake_tasks/create.rb +++ b/src/api/bake_tasks/create.rb @@ -7,6 +7,7 @@ def lambda_handler(event:, context:) db = Aws::DynamoDB::Client.new(region: ENV['REGION']) bake_q = Aws::SQS::Queue.new(ENV["PROJECT_INIT_QUEUE"]) request_body = event["body"] ? JSON.parse(event["body"]) : nil + user_id = event.dig("requestContext", "authorizer", "claims", "sub") project_id = event["pathParameters"]["project_id"] puts event.inspect diff --git a/src/api/projects/create.rb b/src/api/projects/create.rb index 4c3e80c..612f03a 100644 --- a/src/api/projects/create.rb +++ b/src/api/projects/create.rb @@ -3,21 +3,27 @@ require 'securerandom' require 'shared' -include Shared - def lambda_handler(event:, context:) # Get all projects for this user from dynamo - db = Aws::DynamoDB::Client.new(region: ENV['REGION']) - s3_client = Aws::S3::Client.new() - bucket = Aws::S3::Bucket.new(ENV["BUCKET"], client: s3_client) + user_id = event.dig("requestContext", "authorizer", "claims", "sub") + database = Aws::DynamoDB::Client.new(region: ENV['REGION']) + request_body = event["body"] ? JSON.parse(event["body"]) : nil - item = { - "ProjectName" => request_body["name"], - "ProjectId" => SecureRandom.uuid + new_project_id = SecureRandom.uuid + project_item = { + "hk" => new_project_id, + "rk" => "PROJECT", + "data" => request_body["name"] + } + + user_project_item = { + "hk" => new_project_id, + "rk" => user_id } begin - db.put_item(table_name: ENV['PROJECTS_TABLE'], item: item) - { statusCode: 200, body: JSON.generate(item) } + database.put_item(table_name: ENV['PROJECTS_TABLE'], item: project_item) + database.put_item(table_name: ENV['PROJECTS_TABLE'], item: user_project_item) + { statusCode: 200, body: JSON.generate(project_item) } rescue Aws::DynamoDB::Errors::ServiceError => error puts 'Unable to create project:' puts error.message diff --git a/src/api/projects/destroy.rb b/src/api/projects/destroy.rb index 36a6904..6001a02 100644 --- a/src/api/projects/destroy.rb +++ b/src/api/projects/destroy.rb @@ -4,10 +4,22 @@ def lambda_handler(event:, context:) # Get all projects for this user from dynamo + user_id = event.dig("requestContext", "authorizer", "claims", "sub") project_id = event["pathParameters"]["project_id"] db = Aws::DynamoDB::Client.new(region: ENV['REGION']) + + project = { + "hk" => project_id, + "rk" => "PROJECT" + } + + user_project = { + "hk" => project_id, + "rk" => user_id + } begin - db.delete_item(table_name: ENV['PROJECTS_TABLE'], key: {"ProjectId" => project_id}) + db.delete_item(table_name: ENV['PROJECTS_TABLE'], key: project) + db.delete_item(table_name: ENV['PROJECTS_TABLE'], key: user_project) { statusCode: 200, body: JSON.generate(item) } rescue Aws::DynamoDB::Errors::ServiceError => error puts 'Unable to delete project:' diff --git a/src/api/projects/index.rb b/src/api/projects/index.rb index e719d72..0331e99 100644 --- a/src/api/projects/index.rb +++ b/src/api/projects/index.rb @@ -3,6 +3,7 @@ def lambda_handler(event:, context:) # Get all projects for this user from dynamo + user_id = event.dig("requestContext", "authorizer", "claims", "sub") db = Aws::DynamoDB::Client.new(region: ENV['REGION']) begin diff --git a/src/api/projects/show.rb b/src/api/projects/show.rb index 9da3622..7bdcedf 100644 --- a/src/api/projects/show.rb +++ b/src/api/projects/show.rb @@ -4,12 +4,17 @@ def lambda_handler(event:, context:) # Get all projects for this user from dynamo + user_id = event.dig("requestContext", "authorizer", "claims", "sub") project_id = event["pathParameters"]["project_id"] db = Aws::DynamoDB::Client.new(region: ENV['REGION']) s3_client = Aws::S3::Client.new() bucket = Aws::S3::Bucket.new(ENV["BUCKET"], client: s3_client) - project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"ProjectId" => project_id}).item + user_project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"hk" => project_id, "rk" => user_id}).item + + project_id = user_project["hk"]["ProjectId"] + + project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"hk" => project_id, "rk" => "PROJECT"}).item { statusCode: 200, body: JSON.generate(project) } end diff --git a/src/api/render_tasks/create.rb b/src/api/render_tasks/create.rb index ecdde5e..74391a7 100644 --- a/src/api/render_tasks/create.rb +++ b/src/api/render_tasks/create.rb @@ -6,6 +6,7 @@ def lambda_handler(event:, context:) # Get all projects for this user from dynamo db = Aws::DynamoDB::Client.new(region: ENV['REGION']) sqs = Aws::SQS::Client.new(region: ENV["REGION"]) + user_id = event.dig("requestContext", "authorizer", "claims", "sub") request_body = event["body"] ? JSON.parse(event["body"]) : nil diff --git a/src/api/render_tasks/index.rb b/src/api/render_tasks/index.rb index e687f1d..4971bd4 100644 --- a/src/api/render_tasks/index.rb +++ b/src/api/render_tasks/index.rb @@ -6,6 +6,7 @@ def lambda_handler(event:, context:) # Get all projects for this user from dynamo db = Aws::DynamoDB::Client.new(region: ENV['REGION']) sqs = Aws::SQS::Client.new(region: ENV["REGION"]) + user_id = event.dig("requestContext", "authorizer", "claims", "sub") begin project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"ProjectId" => event["pathParameters"]["project_id"]}).item diff --git a/src/api/render_tasks/show.rb b/src/api/render_tasks/show.rb index 42fcd19..6945635 100644 --- a/src/api/render_tasks/show.rb +++ b/src/api/render_tasks/show.rb @@ -6,6 +6,7 @@ def lambda_handler(event:, context:) # Get all projects for this user from dynamo db = Aws::DynamoDB::Client.new(region: ENV['REGION']) sqs = Aws::SQS::Client.new(region: ENV["REGION"]) + user_id = event.dig("requestContext", "authorizer", "claims", "sub") begin project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"ProjectId" => event["pathParameters"]["project_id"]}).item diff --git a/src/lambda_layer/ruby/.DS_Store b/src/lambda_layer/ruby/.DS_Store index 309ed3220d7b58041c839c26b0c447fbc65d90da..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 100644 GIT binary patch delta 68 zcmZoMXfc=|&Zs)EP;8=}A}a$BFiuR=+W0`7ed2?p&FmZk9E_?PFMem9%rBxS$Ox29 Q0I2~25W8WsqsU=q0A^Yb_5c6? delta 148 zcmZoMXfc=|&e%RNQEZ}~q9_vs0|O%ig8+kPPJVJyPJR-QFEBAt-3}zd!cfFe%8 Date: Fri, 4 Oct 2019 18:36:36 -0500 Subject: [PATCH 2/2] Restructure dynamo table --- main.tf | 5 +++- src/api/bake_tasks/create.rb | 30 +++++++++-------------- src/api/projects/create.rb | 4 +-- src/api/projects/destroy.rb | 6 ++--- src/api/projects/index.rb | 11 +++++++-- src/api/projects/show.rb | 21 ++++++++-------- src/api/render_tasks/create.rb | 45 +++++++++++++++------------------- src/api/render_tasks/index.rb | 12 +++++++-- src/api/render_tasks/show.rb | 6 +++-- 9 files changed, 75 insertions(+), 65 deletions(-) diff --git a/main.tf b/main.tf index b8c53a1..32da28a 100644 --- a/main.tf +++ b/main.tf @@ -179,7 +179,9 @@ module "bpi_emitter" { resource "aws_dynamodb_table" "farm_table" { name = "FarmTable" - billing_mode = "PAY_PER_REQUEST" + billing_mode = "PROVISIONED" + write_capacity = 10 + read_capacity = 10 hash_key = "hk" range_key = "rk" @@ -192,6 +194,7 @@ resource "aws_dynamodb_table" "farm_table" { name = "rk" type = "S" } + } module "api" { diff --git a/src/api/bake_tasks/create.rb b/src/api/bake_tasks/create.rb index 2b844cd..01920ac 100644 --- a/src/api/bake_tasks/create.rb +++ b/src/api/bake_tasks/create.rb @@ -9,30 +9,24 @@ def lambda_handler(event:, context:) request_body = event["body"] ? JSON.parse(event["body"]) : nil user_id = event.dig("requestContext", "authorizer", "claims", "sub") project_id = event["pathParameters"]["project_id"] + bake_task_id = SecureRandom.uuid puts event.inspect - new_task = { - "StartedAt" => Time.now.strftime('%Y-%m-%dT%H:%M:%S.%L%z'), - "BakeTaskId" => SecureRandom.uuid + bake_task = { + "hk" => bake_task_id, + "rk" => "BAKE_TASK", + "started_at" => Time.now.strftime('%Y-%m-%dT%H:%M:%S.%L%z'), + } + + project_bake_task = { + "hk" => "project##{project_id}", + "rk" => "bake_task##{render_task_id}", } begin - res = db.update_item({ - table_name: ENV['PROJECTS_TABLE'], - key: { - "ProjectId" => project_id - }, - return_values: "ALL_NEW", - update_expression: "set #BakeTasks = list_append(if_not_exists(#BakeTasks, :EmptyList), :BakeTask)", - expression_attribute_names: { - "#BakeTasks" => "BakeTasks" - }, - expression_attribute_values: { - ":EmptyList" => [], - ":BakeTask" => [new_task] - } - }) + task = db.put_item(table_name: ENV['PROJECTS_TABLE'], item: bake_task) + project_task = db.put_item(table_name: ENV['PROJECTS_TABLE'], item: project_bake_task) bake_q.send_message( message_body: 'Body', diff --git a/src/api/projects/create.rb b/src/api/projects/create.rb index 612f03a..02f47da 100644 --- a/src/api/projects/create.rb +++ b/src/api/projects/create.rb @@ -17,8 +17,8 @@ def lambda_handler(event:, context:) } user_project_item = { - "hk" => new_project_id, - "rk" => user_id + "hk" => "user##{user_id}", + "rk" => "project##{new_project_id}" } begin database.put_item(table_name: ENV['PROJECTS_TABLE'], item: project_item) diff --git a/src/api/projects/destroy.rb b/src/api/projects/destroy.rb index 6001a02..a533a19 100644 --- a/src/api/projects/destroy.rb +++ b/src/api/projects/destroy.rb @@ -14,13 +14,13 @@ def lambda_handler(event:, context:) } user_project = { - "hk" => project_id, - "rk" => user_id + "hk" => "user##{project_id}", + "rk" => "project##{project_id}" } begin db.delete_item(table_name: ENV['PROJECTS_TABLE'], key: project) db.delete_item(table_name: ENV['PROJECTS_TABLE'], key: user_project) - { statusCode: 200, body: JSON.generate(item) } + { statusCode: 200, body: project_id } rescue Aws::DynamoDB::Errors::ServiceError => error puts 'Unable to delete project:' puts error.message diff --git a/src/api/projects/index.rb b/src/api/projects/index.rb index 0331e99..5c16869 100644 --- a/src/api/projects/index.rb +++ b/src/api/projects/index.rb @@ -7,8 +7,15 @@ def lambda_handler(event:, context:) db = Aws::DynamoDB::Client.new(region: ENV['REGION']) begin - resp = db.scan(table_name: ENV['PROJECTS_TABLE']) - { statusCode: 200, body: JSON.generate(resp[:items]) } + projects = db.query( + table_name: ENV['PROJECTS_TABLE'], + key_condition_expression: "hk = :user and begins_with(rk, :project)", + expression_attribute_values: { + ":user" => "user##{user_id}", + ":project" => 'project' + } + ).items + { statusCode: 200, body: JSON.generate(projects) } rescue Aws::DynamoDB::Errors::ServiceError => error puts 'Unable to create project:' puts error.message diff --git a/src/api/projects/show.rb b/src/api/projects/show.rb index 7bdcedf..48a4aa3 100644 --- a/src/api/projects/show.rb +++ b/src/api/projects/show.rb @@ -3,18 +3,19 @@ require 'securerandom' def lambda_handler(event:, context:) - # Get all projects for this user from dynamo - user_id = event.dig("requestContext", "authorizer", "claims", "sub") - project_id = event["pathParameters"]["project_id"] - db = Aws::DynamoDB::Client.new(region: ENV['REGION']) - s3_client = Aws::S3::Client.new() - bucket = Aws::S3::Bucket.new(ENV["BUCKET"], client: s3_client) + # Get all projects for this user from dynamo + user_id = event.dig("requestContext", "authorizer", "claims", "sub") + project_id = event["pathParameters"]["project_id"] + db = Aws::DynamoDB::Client.new(region: ENV['REGION']) + s3_client = Aws::S3::Client.new() + bucket = Aws::S3::Bucket.new(ENV["BUCKET"], client: s3_client) - user_project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"hk" => project_id, "rk" => user_id}).item - - project_id = user_project["hk"]["ProjectId"] + user_project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"hk" => "user##{user_id}", "rk" => "project##{project_id}" }).item + if user_project project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"hk" => project_id, "rk" => "PROJECT"}).item - { statusCode: 200, body: JSON.generate(project) } + else + { statusCode: 400, body: "" } + end end diff --git a/src/api/render_tasks/create.rb b/src/api/render_tasks/create.rb index 74391a7..64c01b1 100644 --- a/src/api/render_tasks/create.rb +++ b/src/api/render_tasks/create.rb @@ -13,37 +13,32 @@ def lambda_handler(event:, context:) puts event.inspect render_task_id = SecureRandom.uuid + project_id = event["pathParameters"]["project_id"] + status = 'started' - new_task = { - "Status" => "started", - "StartedAt" => Time.now.strftime('%Y-%m-%dT%H:%M:%S.%L%z'), - "StartFrame" => request_body["start_frame"], - "EndFrame" => request_body["end_frame"], - "RenderTaskId" => render_task_id, - "QueueUrl" => sqs.create_queue(queue_name: "RenderTask#{render_task_id}").queue_url + render_task = { + "hk" => render_task_id, + "rk" => "RENDER_TASK", + "data" => status, + "started_at" => Time.now.strftime('%Y-%m-%dT%H:%M:%S.%L%z'), + "start_frame" => request_body["start_frame"], + "end_frame" => request_body["end_frame"] + } + + project_render_task = { + "hk" => "project##{project_id}", + "rk" => "render_task##{render_task_id}", } begin - res = db.update_item({ - table_name: ENV['PROJECTS_TABLE'], - key: { - "ProjectId" => event["pathParameters"]["project_id"] - }, - return_values: "ALL_NEW", - update_expression: "set #RenderTasks = list_append(if_not_exists(#RenderTasks, :EmptyList), :RenderTask)", - expression_attribute_names: { - "#RenderTasks" => "RenderTasks" - }, - expression_attribute_values: { - ":EmptyList" => [], - ":RenderTask" => [new_task] - } - }) + task = db.put_item(table_name: ENV['PROJECTS_TABLE'], item: render_task) + project_task = db.put_item(table_name: ENV['PROJECTS_TABLE'], item: project_render_task) + new_queue_url = sqs.create_queue(queue_name: "RenderTask#{render_task_id}").queue_url - if new_task["StartFrame"] && new_task["EndFrame"] + if render_task["start_frame"] && render_task["end_frame"] puts "Sending render messages..." - (new_task["StartFrame"]..new_task["EndFrame"]).each do |frame| - frame_q = Aws::SQS::Queue.new(new_task["QueueUrl"]) + (render_task["start_frame"]..render_task["end_frame"]).each do |frame| + frame_q = Aws::SQS::Queue.new(new_queue_url) frame_q.send_message( message_body: 'Render Frame Triggered By Render Task', message_attributes: { diff --git a/src/api/render_tasks/index.rb b/src/api/render_tasks/index.rb index 4971bd4..4660ade 100644 --- a/src/api/render_tasks/index.rb +++ b/src/api/render_tasks/index.rb @@ -7,10 +7,18 @@ def lambda_handler(event:, context:) db = Aws::DynamoDB::Client.new(region: ENV['REGION']) sqs = Aws::SQS::Client.new(region: ENV["REGION"]) user_id = event.dig("requestContext", "authorizer", "claims", "sub") + project_id = event["pathParameters"]["project_id"] begin - project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"ProjectId" => event["pathParameters"]["project_id"]}).item - { statusCode: 200, body: JSON.generate(project["RenderTasks"]) } + render_tasks = db.query( + table_name: ENV['PROJECTS_TABLE'], + key_condition_expression: "hk = :project_id AND begins_with(rk, :render_task)", + expression_attribute_values: { + ":project_id" => "project##{project_id}", + ":render_task" => 'render_task' + } + ).items + { statusCode: 200, body: JSON.generate(render_tasks) } rescue Aws::DynamoDB::Errors::ServiceError => error puts error.message { statusCode: 400, body: JSON.generate(error.message) } diff --git a/src/api/render_tasks/show.rb b/src/api/render_tasks/show.rb index 6945635..8e1120f 100644 --- a/src/api/render_tasks/show.rb +++ b/src/api/render_tasks/show.rb @@ -7,10 +7,12 @@ def lambda_handler(event:, context:) db = Aws::DynamoDB::Client.new(region: ENV['REGION']) sqs = Aws::SQS::Client.new(region: ENV["REGION"]) user_id = event.dig("requestContext", "authorizer", "claims", "sub") + project_id = event["pathParameters"]["project_id"] + render_task_id = event["pathParameters"]["render_task_id"] begin - project = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"ProjectId" => event["pathParameters"]["project_id"]}).item - render_task = project["RenderTasks"].find{|rt| rt["RenderTaskId"] == event["pathParameters"]["render_task_id"]} + user_project = db.get_item(table_name: ENV['PROJECTS_TABLE'],key: {"hk" => "user##{user_id}", "rk" => "project##{project_id}"}).item + render_task = db.get_item(table_name: ENV['PROJECTS_TABLE'], key: {"hk" => "project##{project_id}", "rk" => "render_task##{render_task_id}"}).item { statusCode: 200, body: JSON.generate(render_task) } rescue Aws::DynamoDB::Errors::ServiceError => error