From bbc80fb542a5d22278e98bf45a777e2748e46632 Mon Sep 17 00:00:00 2001
From: bertrand <bpinel@ippon.fr>
Date: Fri, 4 Jan 2019 18:29:24 +0100
Subject: [PATCH] add support for simple query

---
 cloud/lambda-jsonapi-test.js   | 136 ++++++++++++++++++++++++++++-----
 cloud/lambda/lambda-jsonapi.js | 115 +++++++++++++++++-----------
 2 files changed, 188 insertions(+), 63 deletions(-)

diff --git a/cloud/lambda-jsonapi-test.js b/cloud/lambda-jsonapi-test.js
index 2c78e8a..b9e8b5b 100644
--- a/cloud/lambda-jsonapi-test.js
+++ b/cloud/lambda-jsonapi-test.js
@@ -66,7 +66,7 @@ function generateRowId(subid) {
             objout[(attr==='ObjectType')?'type':'id'] = obj[attr];
         }
     }
-    console.log('Return object is '+JSON.stringify(objout));
+    //console.log('Return object is '+JSON.stringify(objout));
     return objout;
 }
 
@@ -92,7 +92,7 @@ function generateRowId(subid) {
   }
   
   const createResponse = (statusCode, body) => {
-      console.log("Body is "+JSON.stringify(body));
+      //console.log("Body is "+JSON.stringify(body));
       return {
           'statusCode': statusCode,
           'data': handlingData(body),
@@ -100,12 +100,34 @@ function generateRowId(subid) {
       }
   };
   
+const buildQuery = (queryParams, type) => {
+    let filterExpression = [];
+    let params = {
+        TableName: tableName,
+        KeyConditionExpression: 'ObjectType = :objectType',
+        FilterExpression: "",
+        ExpressionAttributeValues: {':objectType': type}
+    }
+    for (var filter in queryParams) {
+        //"filter[email]": "klaroutte@yopmail.com",
+        if (filter.startsWith('filter')){
+            let attr = filter.substring(7, filter.length-1);
+            let value = queryParams[filter];
+            filterExpression.push(attr+" = :"+attr);
+            params["ExpressionAttributeValues"][":"+attr] = value;
+        }
+        params["FilterExpression"] = filterExpression.join(' and ');
+    }
+    console.log('Query is '+JSON.stringify(params));
+    return params;
+}
+
   const getMethod = (event, context, callback) => {
-  
       let params = {
           TableName: tableName,
       },
       type = event.params.path.type,
+      query = event.params.querystring,
       id = Number(event.params.path.id),
       dbGet = {};
   
@@ -115,17 +137,22 @@ function generateRowId(subid) {
               'Id': id
           };
           dbGet = (params) => { return dynamo.get(params).promise() };
-          console.log('EmberDataServerless lambda GET single value with params: ', params);
-  
-      } else {
+          console.log('Ehipster lambda GET single value with params: ', params);
+      } else if (Object.keys(query).length === 0) {
+          // No filter expression
           params.KeyConditionExpression = 'ObjectType = :objectType';
           params.ExpressionAttributeValues = { ':objectType': type };
           dbGet = (params) => { return dynamo.query(params).promise() };
-          console.log('EmberDataServerless lambda GET multiple values with params: ', params);
+          console.log('Ehipster lambda GET multiple values with params: ', params);
+      } else {
+          // Use filter expression
+        params = buildQuery(query, type);
+        dbGet = (params) => { return dynamo.query(params).promise() };
+        console.log('Ehipster lambda GET query values with params: ', params);
       }
   
       dbGet(params).then( (data) => {
-          console.log('EmberDataServerless lambda GET data received: ', data);
+          //console.log('Ehipster lambda GET data received: ', data);
   
           if (id && !data.Item) {
               callback(null, createResponse(404, "ITEM NOT FOUND"));
@@ -206,17 +233,28 @@ function generateRowId(subid) {
   };
   
 const patchMethod = (event, context, callback) => {
-    let type = event.params.path.type,
-        id = Number(event.params.path.id),
-        params = {
-            'TableName': tableName,
-            'Key': {
-                'ObjectType': type,
-                'Id': id
-            },
-            'ReturnValues': 'ALL_OLD'
-        };
+
     const body=event['body-json'];
+    const attrs = body.data.attributes;
+    let updateExpressionList = [];
+    let expressionAttributeList = [];
+    for (var attr in attrs) {
+        updateExpressionList.push(attr+' = :'+attr); 
+        expressionAttributeList[':'+attr] = attrs[attr];
+    }
+    let updateExpression = 'set '+updateExpressionList.join(',');
+    let type = event.params.path.type,
+    id = Number(event.params.path.id),
+    params = {
+        'TableName': tableName,
+        'Key': {
+            'ObjectType': type,
+            'Id': id
+        },
+        'UpdateExpression': updateExpression,
+        'ExpressionAttributeValues': expressionAttributeList,
+        'ReturnValues': 'UPDATED_NEW'
+    };
     let dbUpdate = (params) => { return dynamo.update(params).promise() };
     dbUpdate(params).then( (data) => {
         if (!data.Attributes) {
@@ -258,6 +296,7 @@ const patchMethod = (event, context, callback) => {
       });
   };
   
+  
 
 const callback = (evt, msg) => {console.log(msg);};
 
@@ -291,6 +330,65 @@ const msgGet = {
     }
 };
 
+const msgGetQuery = {
+    "body-json": {},
+    "params": {
+        "path": {
+            "type": "users"
+        },
+        "querystring": {
+            "filter[email]": "klaroutte@yopmail.com"
+        },
+        "header": {
+            "Accept": "application/vnd.api+json",
+            "Accept-Encoding": "gzip, deflate, br",
+            "Accept-Language": "fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7",
+            "cache-control": "no-cache",
+            "CloudFront-Forwarded-Proto": "https",
+            "CloudFront-Is-Desktop-Viewer": "true",
+            "CloudFront-Is-Mobile-Viewer": "false",
+            "CloudFront-Is-SmartTV-Viewer": "false",
+            "CloudFront-Is-Tablet-Viewer": "false",
+            "CloudFront-Viewer-Country": "FR",
+            "content-type": "application/json; charset=utf-8",
+            "Cookie": "remember-me=MGJGZnNQS3dOOURwczJsU01XcVg6czJPYVUwVEViRnZZb2I3MU9uVUs",
+            "Host": "dcftkivcqe.execute-api.us-east-1.amazonaws.com",
+            "pragma": "no-cache",
+            "Referer": "http://localhost:4200/entity-factory/user",
+            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
+            "Via": "1.1 c03df46dd14077b7e27646bae1647fb4.cloudfront.net (CloudFront)",
+            "X-Amz-Cf-Id": "BXJ8PIGP0o96HpT3KfHpOy3hdQg94UkC-J6gdoqixkQfcaMhNmp9sQ==",
+            "X-Amzn-Trace-Id": "Root=1-5c2f7554-9d3c6efa7785f9b665dee096",
+            "x-broccoli": "[object Object]",
+            "X-Forwarded-For": "::1, 195.5.224.170, 54.239.156.82",
+            "x-forwarded-host": "localhost:4200",
+            "X-Forwarded-Port": "443",
+            "X-Forwarded-Proto": "https",
+            "x-requested-with": "XMLHttpRequest"
+        }
+    },
+    "context": {
+        "httpMethod": "GET",
+        "account-id": "",
+        "api-id": "dcftkivcqe",
+        "api-key": "",
+        "authorizer-principal-id": "",
+        "caller": "",
+        "cognito-authentication-provider": "",
+        "cognito-authentication-type": "",
+        "cognito-identity-id": "",
+        "cognito-identity-pool-id": "",
+        "stage": "staging",
+        "source-ip": "195.5.224.170",
+        "user": "",
+        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
+        "user-arn": "",
+        "request-id": "a41433ba-1031-11e9-9052-832dbc024b91",
+        "resource-id": "cmo3pj",
+        "resource-path": "/{type}"
+    }
+}
+
 const msgPost = {
     "body-json": {
         "data": {
@@ -378,5 +476,5 @@ const msgPost = {
     }
 };
 
-getMethod(msgGet, {}, callback);
+getMethod(msgGetQuery, {}, callback);
 //putMethod(msgPost, {}, callback);
\ No newline at end of file
diff --git a/cloud/lambda/lambda-jsonapi.js b/cloud/lambda/lambda-jsonapi.js
index bdb02e1..bc6ed2b 100644
--- a/cloud/lambda/lambda-jsonapi.js
+++ b/cloud/lambda/lambda-jsonapi.js
@@ -92,50 +92,77 @@ function generateRowId(subid) {
       }
   };
   
-  const getMethod = (event, context, callback) => {
-  
-      let params = {
-          TableName: tableName,
-      },
-      type = event.params.path.type,
-      id = Number(event.params.path.id),
-      dbGet = {};
-  
-      if (id) {
-          params.Key = {
-              'ObjectType': type,
-              'Id': id
-          };
-          dbGet = (params) => { return dynamo.get(params).promise() };
-          console.log('EmberDataServerless lambda GET single value with params: ', params);
-  
-      } else {
-          params.KeyConditionExpression = 'ObjectType = :objectType';
-          params.ExpressionAttributeValues = { ':objectType': type };
-          dbGet = (params) => { return dynamo.query(params).promise() };
-          console.log('EmberDataServerless lambda GET multiple values with params: ', params);
-      }
-  
-      dbGet(params).then( (data) => {
-          console.log('EmberDataServerless lambda GET data received: ', data);
-  
-          if (id && !data.Item) {
-              callback(null, createResponse(404, "ITEM NOT FOUND"));
-              return;
-          } else if (id && data.Item) {
-              console.log(`RETRIEVED ITEM SUCCESSFULLY WITH doc = ${data.Item}`);
-              callback(null, createResponse(200, data.Item));
-          } else {
-              console.log('SCANNING TABLE');
-              console.log(`RETRIEVED ITEMS SUCCESSFULLY WITH doc = ${data.Items}`);
-              callback(null, createResponse(200, data.Items));
-          }
-          
-      }).catch( (err) => { 
-          console.log(`GET ITEM FAILED FOR Entry = ${params}, WITH ERROR: ${err}`);
-          callback(null, createResponse(500, err));
-      });
-  };
+  const buildQuery = (queryParams, type) => {
+    let filterExpression = [];
+    let params = {
+        TableName: tableName,
+        KeyConditionExpression: 'ObjectType = :objectType',
+        FilterExpression: "",
+        ExpressionAttributeValues: {':objectType': type}
+    }
+    for (var filter in queryParams) {
+        //"filter[email]": "klaroutte@yopmail.com",
+        if (filter.startsWith('filter')){
+            let attr = filter.substring(7, filter.length-1);
+            let value = queryParams[filter];
+            filterExpression.push(attr+" = :"+attr);
+            params["ExpressionAttributeValues"][":"+attr] = value;
+        }
+        params["FilterExpression"] = filterExpression.join(' and ');
+    }
+    console.log('Query is '+JSON.stringify(params));
+    return params;
+}
+
+const getMethod = (event, context, callback) => {
+    let params = {
+        TableName: tableName,
+    },
+    type = event.params.path.type,
+    query = event.params.querystring,
+    id = Number(event.params.path.id),
+    dbGet = {};
+
+    if (id) {
+        params.Key = {
+            'ObjectType': type,
+            'Id': id
+        };
+        dbGet = (params) => { return dynamo.get(params).promise() };
+        console.log('Ehipster lambda GET single value with params: ', params);
+    } else if (Object.keys(query).length === 0) {
+        // No filter expression
+        params.KeyConditionExpression = 'ObjectType = :objectType';
+        params.ExpressionAttributeValues = { ':objectType': type };
+        dbGet = (params) => { return dynamo.query(params).promise() };
+        console.log('Ehipster lambda GET multiple values with params: ', params);
+    } else {
+        // Use filter expression
+      params = buildQuery(query, type);
+      dbGet = (params) => { return dynamo.query(params).promise() };
+      console.log('Ehipster lambda GET query values with params: ', params);
+    }
+
+    dbGet(params).then( (data) => {
+        //console.log('Ehipster lambda GET data received: ', data);
+
+        if (id && !data.Item) {
+            callback(null, createResponse(404, "ITEM NOT FOUND"));
+            return;
+        } else if (id && data.Item) {
+            console.log(`RETRIEVED ITEM SUCCESSFULLY WITH doc = ${data.Item}`);
+            callback(null, createResponse(200, data.Item));
+        } else {
+            console.log('SCANNING TABLE');
+            console.log(`RETRIEVED ITEMS SUCCESSFULLY WITH doc = ${data.Items}`);
+            callback(null, createResponse(200, data.Items));
+        }
+        
+    }).catch( (err) => { 
+        console.log(`GET ITEM FAILED FOR Entry = ${params}, WITH ERROR: ${err}`);
+        callback(null, createResponse(500, err));
+    });
+};
   
   const putMethod = (event, context, callback) => {
       const body=event['body-json'];
-- 
GitLab