Skip to content
Open
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
28 changes: 27 additions & 1 deletion .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,31 @@ jobs:
run: |
npm run test

# layer build
buid-js-layer-deps:
timeout-minutes: 15
runs-on: ubuntu-latest
name: Build SLS Layer - Prod
container:
image: "node:14-buster"
steps:
- uses: actions/checkout@v2
- run: |
npm install --production
mkdir nodejs
mv node_modules nodejs
apt update -y && apt install zip -y
zip -r nodejs.zip nodejs/

- uses: actions/upload-artifact@v2
with:
name: nodejsdeps
path: nodejs.zip

deploy-env:
name: Deploy Lambda
runs-on: ubuntu-latest
needs: testing-changes
needs: [testing-changes, buid-js-layer-deps]
steps:
- uses: actions/checkout@v2.0.0

Expand All @@ -37,6 +58,11 @@ jobs:
if: steps.cached-npm-dependencies.outputs.cache-hit != 'true'
run: 'npm install'

- uses: actions/download-artifact@v2
with:
name: nodejsdeps
path: app/

- name: Deploy using sls
run: 'npx sls deploy'
env:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
.dynamodb/
.serverless
venv
venv
nodejs.zip
4,208 changes: 3,709 additions & 499 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
"devDependencies": {
"aws-sdk": "^2.1343.0",
"serverless": "^3.29.0",
"serverless-offline": "^12.0.4"
"serverless-offline": "^12.0.4",
"serverless-s3-local": "^0.7.1",
"serverless-dynamodb-local": "^0.2.40"
},
"dependencies": {
"serverless-dynamodb-local": "^0.2.40"
"sharp": "^0.32.0"
}
}
26 changes: 26 additions & 0 deletions schemas/user-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "User",
"type": "object",
"required": ["name", "age", "email"],
"properties": {
"name": {
"type": "string",
"description": "The person's first name."
},
"lastname": {
"type": "string",
"description": "The person's last name."
},
"age": {
"description": "Age in years which must be equal to or greater than 18.",
"type": "integer",
"minimum": 18
},
"email": {
"type": "string",
"format": "email",
"description": "The user's email"
}
}
}
107 changes: 99 additions & 8 deletions serverless.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
service: api-crud
service: project-api

provider:
name: aws
runtime: nodejs14.x
apiGateway:
apiKeys:
- project-api-key
iam:
role:
statements:
- Effect: Allow
Action: "dynamodb:*"
Resource: arn:aws:dynamodb:us-east-1:536729514546:table/usersTable


plugins:
- serverless-offline
- serverless-dynamodb-local
- Effect: Allow
Action: "S3:*"
Resource: arn:aws:s3:::bucket-api-serverless-js/*

environment:
BUCKET: bucket-api-serverless-js
EXPIRES_TIME: 300

package:
individually: true
patterns:
Expand All @@ -30,6 +36,10 @@ custom:
inMemory: true
migrate: true

s3:
host: localhost
directory: /tmp

functions:
get-users:
handler: getUsers/handler.getUsers
Expand All @@ -38,8 +48,14 @@ functions:
- "getUsers/handler.js"
events:
- http:
# con la instrucción private habilitamos para usar apikey
private: true
path: users/{id}
method: GET
request:
parameters:
paths:
id: true

get-all-users:
handler: getAllUsers/handler.getAllUsers
Expand All @@ -59,7 +75,10 @@ functions:
events:
- http:
path: users
method: POST
method: POST
request:
schemas:
application/json: ${file(schemas/user-schema.json)}

update-users:
handler: updateUsers/handler.updateUsers
Expand All @@ -70,6 +89,12 @@ functions:
- http:
path: users/{id}
method: PATCH
request:
parameters:
paths:
id: true
schemas:
application/json: ${file(schemas/user-schema.json)}

delete-users:
handler: deleteUsers/handler.deleteUsers
Expand All @@ -80,7 +105,50 @@ functions:
events:
- http:
path: users/{id}
method: DELETE
method: DELETE
request:
parameters:
paths:
id: true

signed-url:
handler: signedUrl/handler.signedS3URL
package:
patterns:
- "signedUrl/handler.js"
events:
- http:
path: signedurl
method: GET
request:
parameters:
querystrings:
filename: true

thumbnail-generator:
handler: thumbnail/handler.thumbnailGenerator
layers:
- { Ref: BaseLambdaLayer }
package:
patterns:
- "thumbnail/handler.js"
events:
- s3:
bucket: bucket-api-serverless-js
event: s3:ObjectCreated:*
existing: true
rules:
- prefix: upload/

# automatizar la subida de una layer
layers:
base:
name: "dev-thumbnail-layer"
compatibleRuntimes:
- "nodejs14.x"
package:
artifact: app/nodejs.zip


resources:
Resources:
Expand All @@ -96,4 +164,27 @@ resources:
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
WriteCapacityUnits: 1

S3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
AccessControl: PublicRead
BucketName: bucket-api-serverless-js

SampleBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref S3Bucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- 's3:GetObject'
Effect: Allow
Resource: !Join
- ''
- - 'arn:aws:s3:::'
- !Ref S3Bucket
- /*
Principal: '*'
31 changes: 31 additions & 0 deletions signedUrl/handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const AWS = require("aws-sdk")

let params = {
signatureVersion: 'v4',
}
if (process.env.IS_OFFLINE) {
params = {
accessKeyId: "S3RVER",
secretAccessKey: "S3RVER",
}
}

const s3 = new AWS.S3(params)

const signedS3URL = async(event, context) => {
const filename = event.queryStringParameters.filename
const signedURL = await s3.getSignedUrlPromise("putObject", {
Key: `upload/${filename}`,
Bucket: process.env.BUCKET,
Expires: parseInt(process.env.EXPIRES_TIME),
});

return {
"statusCode": 200,
"body": JSON.stringify({ signedURL })
}
}

module.exports = {
signedS3URL
}
80 changes: 80 additions & 0 deletions thumbnail/handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const AWS = require("aws-sdk");
const util = require("util");
const sharp = require("sharp")

const s3 = new AWS.S3();

const thumbnailGenerator = async (event, context) => {
const srcBucket = event.Records[0].s3.bucket.name;
const srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g," "));

const typeMatch = srcKey.match(/\.([^.]*)$/);
if (!typeMatch) {
console.log("Could not determine the image type.");
return;
}

const imageType = typeMatch[1].toLowerCase();
if (imageType != "jpg" && imageType != "png") {
console.log(`Unsupported image type: ${imageType}`);
return;
}

let origimage = null
try {
const params = {
Bucket: srcBucket,
Key: srcKey
};

origimage = await s3.getObject(params).promise();

} catch (error) {
console.log(error);
return;
}

const widths = [50,100,200];

for (const w of widths) {
await resizer(origimage.Body, w, srcBucket, srcKey)
}
};

const resizer = async (imgBody, newSize, dstBucket, fileKey ) => {

const nameFile = fileKey.split('/')[1]
const dstKey = `resized/${newSize}-${nameFile}`;
let buffer = null
try {
buffer = await sharp(imgBody).resize(newSize).toBuffer();

} catch (error) {
console.log(error);
return;
}


try {
const destparams = {
Bucket: dstBucket,
Key: dstKey,
Body: buffer,
ContentType: "image"
};

await s3.putObject(destparams).promise();

} catch (error) {
console.log(error);
return;
}

console.log('Successfully resized ' + dstBucket + '/' + fileKey +
' and uploaded to ' + dstBucket + '/' + dstKey);

}

module.exports = {
thumbnailGenerator
}
6 changes: 3 additions & 3 deletions updateUsers/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ const updateUsers = async(event, context) => {
const params = {
TableName: 'usersTable',
Key: { pk: userId },
UpdateExpression: "set #name = :name, #telefono = :telefono",
ExpressionAttributeNames : {"#name":"name", "#telefono": "telefono"},
ExpressionAttributeValues: { ':name': body.name, ":telefono": body.telefono },
UpdateExpression: "set #name = :name, #lastname = :lastname, #age = :age, #email = :email",
ExpressionAttributeNames : {"#name":"name", "#lastname": "lastname", "#age": "age", "#email":"email"},
ExpressionAttributeValues: { ':name': body.name, ":lastname": body.lastname, ":age": body.age, ":email": body.email },
ReturnValues: "ALL_NEW"
}

Expand Down