app/model/TagAudit.scala (143 lines of code) (raw):

package model import com.amazonaws.services.dynamodbv2.document.Item import com.gu.pandomainauth.model.User import helpers.JodaDateTimeFormat._ import org.joda.time.DateTime import play.api.Logging import play.api.libs.functional.syntax._ import play.api.libs.json.{Format, JsPath, Json} import repositories.SectionRepository import scala.util.control.NonFatal case class TagAudit( tagId: Long, operation: String, date: DateTime, user: String, description: String, tagSummary: TagSummary, secondaryTagSummary: Option[TagSummary] ) extends Audit { override def auditType = "tag" override def resourceId = Some(tagId.toString) override def message = Some(s"$description - Tag 1: ${tagSummary.toString} Tag 2: ${secondaryTagSummary.toString}") def toItem = Item.fromJSON(Json.toJson(this).toString()) } object TagAudit extends Logging { implicit val tagAuditFormat: Format[TagAudit] = ( (JsPath \ "tagId").format[Long] and (JsPath \ "operation").format[String] and (JsPath \ "date").format[DateTime] and (JsPath \ "user").format[String] and (JsPath \ "description").format[String] and (JsPath \ "tagSummary").format[TagSummary] and (JsPath \ "secondaryTagSummary").formatNullable[TagSummary] )(TagAudit.apply, unlift(TagAudit.unapply)) def fromItem(item: Item) = try { Json.parse(item.toJSON).as[TagAudit] } catch { case NonFatal(e) => { logger.error(s"failed to load tag Audit ${item.toJSON}", e) throw e } } def created(tag: Tag)(implicit username: Option[String]): TagAudit = { TagAudit(tag.id, "created", new DateTime(), username.getOrElse("unknown"), s"tag '${tag.internalName}' created", TagSummary(tag), None) } def updated(tag: Tag)(implicit username: Option[String]): TagAudit = { TagAudit(tag.id, "updated", new DateTime(), username.getOrElse("unknown"), s"tag '${tag.internalName}' updated", TagSummary(tag), None) } def deleted(tag: Tag, username: Option[String]): TagAudit = { TagAudit(tag.id, "deleted", new DateTime(), username.getOrElse("unknown"), s"tag '${tag.internalName}' deleted", TagSummary(tag), None) } def merged(removingTag: Tag, replacementTag: Tag, username: Option[String]): TagAudit = { TagAudit(removingTag.id, "merged" , new DateTime(), username.getOrElse("unknown"), s"tag '${removingTag.internalName}' merged with '${replacementTag.internalName}'", TagSummary(removingTag), Some(TagSummary(replacementTag)) ) } def batchTag(tag: Tag, operation: String, contentCount: Int)(implicit user: Option[String]): TagAudit = { val message = operation match { case "remove" => s"tag '${tag.internalName}' removed from $contentCount items(s)" case _ => s"tag '${tag.internalName}' added to $contentCount items(s)" } TagAudit(tag.id, "batchtag", new DateTime(), user.getOrElse("unknown"), message, TagSummary(tag), None) } } case class TagSummary( tagId: Long, internalName: String, externalName: String, slug: String, `type`: String, sectionName: String ) object TagSummary { implicit val tagAuditFormat: Format[TagSummary] = ( (JsPath \ "tagId").format[Long] and (JsPath \ "internalName").format[String] and (JsPath \ "externalName").format[String] and (JsPath \ "slug").format[String] and (JsPath \ "type").format[String] and (JsPath \ "sectionName").format[String] )(TagSummary.apply, unlift(TagSummary.unapply)) def apply(tag: Tag): TagSummary = new TagSummary( tagId = tag.id, internalName = tag.internalName, externalName = tag.externalName, slug = tag.slug, `type` = tag.`type`, sectionName = tag.section.flatMap{ sid => SectionRepository.getSection(sid).map(_.name)}.getOrElse("global") ) } case class Delete(tagId: Long, date: DateTime ) { def asExportedXml = { import helpers.XmlHelpers._ val el = createElem("delete") val id = createAttribute("id", Some(this.tagId)) val timestamp = createAttribute("timestamp", Some(this.date.getMillis)) val date = createAttribute("date", Some(this.date.toString("MM/dd/yyy HH:mm:ss"))) el % timestamp % date % id } } object Delete { def apply(audit: TagAudit): Delete = { Delete(audit.tagId, audit.date) } } case class Merge( tagId: Long, date: DateTime, targetTag: Option[TagSummary] ) { def asExportedXml = { import helpers.XmlHelpers._ val el = createElem("merge") val from = createAttribute("from", Some(this.tagId)) val to = createAttribute("to", this.targetTag.map(_.tagId)) val timestamp = createAttribute("timestamp", Some(this.date.getMillis)) val date = createAttribute("date", Some(this.date.toString("MM/dd/yyy HH:mm:ss"))) el % timestamp % date % to % from } } object Merge { def apply(audit: TagAudit): Merge = { Merge(audit.tagId, audit.date, audit.secondaryTagSummary) } } case class Create( tagId: Long, date: DateTime ) { } object Create { def apply(audit: TagAudit): Create = { Create(audit.tagId, audit.date) } }