app/aws/AuditTrailDB.scala (93 lines of code) (raw):

package aws import com.gu.janus.model.AuditLog import logic.AuditTrail import software.amazon.awssdk.services.dynamodb.DynamoDbClient import software.amazon.awssdk.services.dynamodb.model.ComparisonOperator._ import software.amazon.awssdk.services.dynamodb.model._ import java.time.Instant import scala.jdk.CollectionConverters._ object AuditTrailDB { import AuditTrail._ def insert(auditLog: AuditLog)(implicit dynamoDB: DynamoDbClient): Unit = { val auditLogDbAttrs = AuditLogDbEntryAttrs.fromAuditLog(auditLog) val item = auditLogDbAttrs.toMap.asJava val request = PutItemRequest.builder().tableName(tableName).item(item).build() dynamoDB.putItem(request) } def getAccountLogs( account: String, startDate: Instant, endDate: Instant )(implicit dynamoDB: DynamoDbClient): Seq[Either[String, AuditLog]] = { val request = QueryRequest .builder() .tableName(tableName) .keyConditions( Map( attrEqualCondition( accountPartitionKeyName, AttributeValue.fromS(account) ), dateRangeCondition(startDate, endDate) ).asJava ) .scanIndexForward(false) .build() queryResult(dynamoDB, request) } def getUserLogs( username: String, startDate: Instant, endDate: Instant )(implicit dynamoDB: DynamoDbClient): Seq[Either[String, AuditLog]] = { val request = QueryRequest .builder() .tableName(tableName) .indexName(secondaryIndexName) .keyConditions( Map( attrEqualCondition(userNameAttrName, AttributeValue.fromS(username)), dateRangeCondition(startDate, endDate) ).asJava ) .scanIndexForward(false) .build() queryResult(dynamoDB, request) } private def attrEqualCondition( attrName: String, attrValue: AttributeValue ) = attrName -> Condition .builder() .comparisonOperator(EQ) .attributeValueList(attrValue) .build() private def dateRangeCondition( startDate: Instant, endDate: Instant ): (String, Condition) = { timestampSortKeyName -> Condition .builder() .comparisonOperator(BETWEEN) .attributeValueList( AttributeValue.fromN(startDate.toEpochMilli.toString), AttributeValue.fromN(endDate.toEpochMilli.toString) ) .build() } private def queryResult( dynamoDB: DynamoDbClient, request: QueryRequest ): Seq[Either[String, AuditLog]] = { val result = dynamoDB.query(request) result .items() .asScala .map(attrs => auditLogFromAttrs(attrs.asScala.toMap)) .map(logDbResultErrs) .map(errorStrings) .toSeq } }