diff --git a/lambda/deletePass/index.js b/lambda/deletePass/index.js index 4e06123f..98991e3c 100644 --- a/lambda/deletePass/index.js +++ b/lambda/deletePass/index.js @@ -15,6 +15,10 @@ exports.handler = async (event, context) => { if (!event.queryStringParameters) { return sendResponse(400, { msg: 'Invalid Request' }, context); } + + const currentPSTDateTime = DateTime.now().setZone(TIMEZONE); + const currentTimeISO = currentPSTDateTime.toUTC().toISO(); + if (event.queryStringParameters.code) { logger.debug('Get the specific pass, this person is NOT authenticated but has a code'); @@ -53,12 +57,32 @@ exports.handler = async (event, context) => { sk: { S: decodedToken.passId } }, ExpressionAttributeValues: { - ':cancelled': { S: 'cancelled' } + ':cancelled': { S: 'cancelled' }, + ':dateUpdated': { S: currentTimeISO }, + ':empty_list': { "L": [] }, // For pass objects which do not have an audit property. + ':audit_val': { + "L": [ + { + "M": { + "by": { + "S": "public" + }, + "passStatus": { + "S": 'cancelled' + } + , + "dateUpdated": { + "S": currentTimeISO + } + } + } + ] + } }, // If the pass is already cancelled, error so that we don't decrement the available // count multiple times. ConditionExpression: 'attribute_exists(pk) AND attribute_exists(sk) AND (NOT passStatus = :cancelled)', - UpdateExpression: 'SET passStatus = :cancelled', + UpdateExpression: 'SET passStatus = :cancelled, audit = list_append(if_not_exists(audit, :empty_list), :audit_val), dateUpdated = :dateUpdated', TableName: TABLE_NAME }; transactionObj.TransactItems.push({ @@ -93,8 +117,12 @@ exports.handler = async (event, context) => { const res = await dynamodb.transactWriteItems(transactionObj).promise(); logger.debug('res:', res); + // Prune audit + delete passNoAuth.audit; + return sendResponse(200, { msg: 'Cancelled', pass: passNoAuth }, context); } else if (event.queryStringParameters.passId && event.queryStringParameters.park) { + // ADMIN const token = await decodeJWT(event); const permissionObject = resolvePermissions(token); if (permissionObject.isAdmin !== true) { @@ -129,12 +157,32 @@ exports.handler = async (event, context) => { sk: { S: event.queryStringParameters.passId } }, ExpressionAttributeValues: { - ':cancelled': { S: 'cancelled' } + ':cancelled': { S: 'cancelled' }, + ':dateUpdated': { S: currentTimeISO }, + ':empty_list': { "L": [] }, // For pass objects which do not have an audit property. + ':audit_val': { + "L": [ + { + "M": { + "by": { + "S": "admin" + }, + "passStatus": { + "S": 'cancelled' + } + , + "dateUpdated": { + "S": currentTimeISO + } + } + } + ] + } }, // If the pass is already cancelled, error so that we don't decrement the available // count multiple times. ConditionExpression: 'attribute_exists(pk) AND attribute_exists(sk) AND (NOT passStatus = :cancelled)', - UpdateExpression: 'SET passStatus = :cancelled', + UpdateExpression: 'SET passStatus = :cancelled, audit = list_append(if_not_exists(audit, :empty_list), :audit_val), dateUpdated = :dateUpdated', TableName: TABLE_NAME }; transactionObj.TransactItems.push({ diff --git a/lambda/dynamoUtil.js b/lambda/dynamoUtil.js index 35c43bee..1cede755 100644 --- a/lambda/dynamoUtil.js +++ b/lambda/dynamoUtil.js @@ -1,5 +1,6 @@ const AWS = require('aws-sdk'); const { logger } = require('./logger'); +const { DateTime } = require('luxon'); const TABLE_NAME = process.env.TABLE_NAME || 'parksreso'; const options = { @@ -30,6 +31,9 @@ exports.dynamodb = new AWS.DynamoDB(); async function setStatus(passes, status) { + const currentPSTDateTime = DateTime.now().setZone(TIMEZONE); + const currentTimeISO = currentPSTDateTime.toUTC().toISO(); + for (let i = 0; i < passes.length; i++) { let updateParams = { Key: { @@ -37,9 +41,29 @@ async function setStatus(passes, status) { sk: { S: passes[i].sk } }, ExpressionAttributeValues: { - ':statusValue': { S: status } + ':statusValue': { S: status }, + ':empty_list': { "L": [] }, // For pass objects which do not have an audit property. + ':dateUpdated': { S: currentTimeISO }, + ':audit_val': { + "L": [ + { + "M": { + "by": { + "S": "system" + }, + "passStatus": { + "S": status + } + , + "dateUpdated": { + "S": currentTimeISO + } + } + } + ] + } }, - UpdateExpression: 'SET passStatus = :statusValue', + UpdateExpression: 'SET passStatus = :statusValue, audit = list_append(if_not_exists(audit, :empty_list), :audit_val), dateUpdated = :dateUpdated', ReturnValues: 'ALL_NEW', TableName: TABLE_NAME }; diff --git a/lambda/writePass/index.js b/lambda/writePass/index.js index 5dfb13ab..7c2550fa 100644 --- a/lambda/writePass/index.js +++ b/lambda/writePass/index.js @@ -198,8 +198,28 @@ exports.handler = async (event, context) => { passObject.Item['passStatus'] = { S: status }; passObject.Item['phoneNumber'] = AWS.DynamoDB.Converter.input(phoneNumber); passObject.Item['facilityType'] = { S: facilityData.type }; - passObject.Item['creationDate'] = { S: currentPSTDateTime.toUTC().toISO() }; passObject.Item['isOverbooked'] = { BOOL: false }; + // Audit + passObject.Item['creationDate'] = { S: currentPSTDateTime.toUTC().toISO() }; + passObject.Item['dateUpdated'] = { S: currentPSTDateTime.toUTC().toISO() }; + passObject.Item['audit'] = { + "L": [ + { + "M": { + "by": { + "S": "system" + }, + "passStatus": { + "S": status + } + , + "dateUpdated": { + "S": currentPSTDateTime.toUTC().toISO() + } + } + } + ] + } const cancellationLink = process.env.PUBLIC_FRONTEND + @@ -410,6 +430,10 @@ exports.handler = async (event, context) => { } }); logger.debug('GCNotify email sent.'); + + // Prune audit + delete passObject.Item['audit']; + return sendResponse(200, AWS.DynamoDB.Converter.unmarshall(passObject.Item)); } catch (err) { logger.error('GCNotify error:', err);