Skip to content

Commit

Permalink
Fix many DynamoDB and JsonX compilation errors
Browse files Browse the repository at this point in the history
  • Loading branch information
rtyley committed Jan 30, 2024
1 parent b51e086 commit b798185
Show file tree
Hide file tree
Showing 40 changed files with 134 additions and 150 deletions.
2 changes: 1 addition & 1 deletion app/controllers/AtomController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ trait AtomController extends BaseController with UnpackedDataStores {
override def invokeBlock[A](request: Request[A], block: UploadUserRequest[A] => Future[Result]): Future[Result] = {
APIAuthAction.invokeBlock(request, { req: UserRequest[A] =>
permissions.getAll(req.user).flatMap { p =>
block(new UploadUserRequest(req.user, request, p))
block(UploadUserRequest(req.user, request, p))
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion app/di.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class MediaAtomMaker(context: Context)
private val capi = new Capi(config)

private val stores = new DataStores(aws, capi)
private val permissions = new MediaAtomMakerPermissionsProvider(aws.stage, aws.credentials.instance)
private val permissions = new MediaAtomMakerPermissionsProvider(aws.stage, aws.region.getName, aws.credentials.instance)

private val reindexer = buildReindexer()

Expand Down
1 change: 1 addition & 0 deletions app/util/ActivateAssetRequest.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package util

import ai.x.play.json.Encoders.encoder
import ai.x.play.json.Jsonx
import play.api.libs.json._

Expand Down
17 changes: 6 additions & 11 deletions app/util/UploadDecorator.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package util

import com.gu.media.aws.{DynamoAccess, UploadAccess}
import com.gu.media.model.{ClientAsset, ClientAssetMetadata}
import com.gu.media.upload.model.Upload
import org.scanamo.{Scanamo, Table}
import org.scanamo.generic.auto._
import org.scanamo.syntax._
import org.scanamo.auto._
import org.scanamo.{Scanamo, Table}

class UploadDecorator(aws: DynamoAccess with UploadAccess, stepFunctions: StepFunctions) {
private val table = Table[Upload](aws.cacheTableName)
class UploadDecorator(scanamo: Scanamo, cacheTableName: String, stepFunctions: StepFunctions) {
private val table = Table[Upload](cacheTableName)

def addMetadata(atomId: String, video: ClientAsset): ClientAsset = {
val id = s"$atomId-${video.id}"
Expand All @@ -28,10 +27,6 @@ class UploadDecorator(aws: DynamoAccess with UploadAccess, stepFunctions: StepFu
}
}

private def getUpload(id: String): Option[Upload] = {
val op = table.get('id -> id)
val result = Scanamo.exec(aws.dynamoDB)(op).flatMap(_.right.toOption)

result orElse { stepFunctions.getById(id) }
}
private def getUpload(id: String): Option[Upload] =
scanamo.exec(table.get("id" === id)).flatMap(_.toOption) orElse { stepFunctions.getById(id) }
}
57 changes: 21 additions & 36 deletions common/src/main/scala/com/gu/media/Permissions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ package com.gu.media
import com.amazonaws.auth.AWSCredentialsProvider
import com.gu.permissions._
import ai.x.play.json.Jsonx
import ai.x.play.json.Encoders._
import com.gu.media.Permissions.setVideosOnAllChannelsPublic
import play.api.libs.json.Format
import com.gu.pandomainauth.model.{User => PandaUser}
import com.gu.permissions.PermissionDefinition

import scala.concurrent.Future

case class Permissions(
deleteAtom: Boolean,
addSelfHostedAsset: Boolean,
setVideosOnAllChannelsPublic: Boolean,
pinboard: Boolean
deleteAtom: Boolean = false,
addSelfHostedAsset: Boolean = false,
setVideosOnAllChannelsPublic: Boolean = false,
pinboard: Boolean = false
)
object Permissions {
implicit val format: Format[Permissions] = Jsonx.formatCaseClass[Permissions]
Expand All @@ -25,42 +27,25 @@ object Permissions {
val pinboard = PermissionDefinition("pinboard", "pinboard")
}

class MediaAtomMakerPermissionsProvider(stage: String, credsProvider: AWSCredentialsProvider) extends PermissionsProvider {
class MediaAtomMakerPermissionsProvider(stage: String, region: String, credsProvider: AWSCredentialsProvider) {
import Permissions._

implicit def config = PermissionsConfig(
app = "media-atom-maker",
all = Seq(deleteAtom, addSelfHostedAsset, setVideosOnAllChannelsPublic, pinboard),
s3BucketPrefix = if(stage == "PROD") "PROD" else "CODE",
awsCredentials = credsProvider
)
private val permissions: PermissionsProvider = PermissionsProvider(PermissionsConfig(stage, region, credsProvider))

def getAll(user: PandaUser): Future[Permissions] = for {
deleteAtom <- hasPermission(deleteAtom, user)
selfHostedMediaAtom <- hasPermission(addSelfHostedAsset, user)
publicStatusPermissions <- hasPermission(setVideosOnAllChannelsPublic, user)
pinboard <- hasPermission(pinboard, user)
} yield Permissions(deleteAtom, selfHostedMediaAtom, publicStatusPermissions, pinboard)
def getAll(user: PandaUser): Permissions = Permissions(
deleteAtom = hasPermission(deleteAtom, user),
addSelfHostedAsset = hasPermission(addSelfHostedAsset, user),
setVideosOnAllChannelsPublic = hasPermission(setVideosOnAllChannelsPublic, user),
pinboard = hasPermission(pinboard, user)
)

def getStatusPermissions(user: PandaUser): Future[Permissions] = for {
publicStatus <- hasPermission(setVideosOnAllChannelsPublic, user)
} yield {
Permissions(deleteAtom = false, addSelfHostedAsset = false, publicStatus, pinboard = false)
}
def getStatusPermissions(user: PandaUser): Permissions =
Permissions(setVideosOnAllChannelsPublic = hasPermission(setVideosOnAllChannelsPublic, user))

private def hasPermission(permission: PermissionDefinition, user: PandaUser): Future[Boolean] = {
user.email match {
// TODO be better
// HACK: HMAC authenticated users are a `PandaUser` without an email
case "" if user.firstName == "media-atom-scheduler-lambda" => {
Future.successful(true)
}
case _ => {
get(permission)(PermissionsUser(user.email)).map {
case PermissionGranted => true
case _ => false
}
}
}
private def hasPermission(permission: PermissionDefinition, user: PandaUser): Boolean = user.email match {
// TODO be better
// HACK: HMAC authenticated users are a `PandaUser` without an email
case "" if user.firstName == "media-atom-scheduler-lambda" => true
case _ => permissions.hasPermission(permission, user.email)
}
}
21 changes: 9 additions & 12 deletions common/src/main/scala/com/gu/media/PlutoDataStore.scala
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package com.gu.media

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB
import com.amazonaws.services.dynamodbv2.model.DeleteItemResult
import com.gu.media.model.PlutoSyncMetadataMessage
import org.scanamo.error.DynamoReadError
import org.scanamo.generic.auto._
import org.scanamo.syntax._
import org.scanamo.{Scanamo, Table}
import org.scanamo.auto._

class PlutoDataStore(client: AmazonDynamoDB, dynamoTableName: String) {
class PlutoDataStore(scanamo: Scanamo, dynamoTableName: String) {

val table = Table[PlutoSyncMetadataMessage](dynamoTableName)

def getUploadsWithAtomId(id: String): List[PlutoSyncMetadataMessage] = {
val atomIdIndex = table.index("atom-id")
val results = Scanamo.exec(client)(atomIdIndex.query('atomId -> id))
val results = scanamo.exec(atomIdIndex.query("atomId" === id))

val errors = results.collect { case Left(err) => err }
if (errors.nonEmpty) {
Expand All @@ -25,21 +22,21 @@ class PlutoDataStore(client: AmazonDynamoDB, dynamoTableName: String) {
}

def get(id: String): Option[PlutoSyncMetadataMessage] = {
val operation = table.get('id -> id)
val result = Scanamo.exec(client)(operation)
val operation = table.get("id" === id)
val result = scanamo.exec(operation)

result.map {
case Right(item) => item
case Left(err) => throw DynamoPlutoTableException(err.toString)
}
}

def put(item: PlutoSyncMetadataMessage): Option[Either[DynamoReadError, PlutoSyncMetadataMessage]] = {
Scanamo.exec(client)(table.put(item))
def put(item: PlutoSyncMetadataMessage): Unit = {
scanamo.exec(table.put(item))
}

def delete(id: String): DeleteItemResult = {
Scanamo.exec(client)(table.delete('id -> id))
def delete(id: String): Unit = {
scanamo.exec(table.delete("id" === id))
}

case class DynamoPlutoTableException(err: String) extends RuntimeException(err)
Expand Down
3 changes: 3 additions & 0 deletions common/src/main/scala/com/gu/media/aws/DynamoAccess.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.gu.media.aws

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder
import com.gu.media.Settings
import org.scanamo.Scanamo

trait DynamoAccess { this: Settings with AwsAccess =>
lazy val dynamoTableName: String = sys.env.getOrElse("ATOM_TABLE_NAME",
Expand All @@ -24,4 +25,6 @@ trait DynamoAccess { this: Settings with AwsAccess =>
.withCredentials(credsProvider)
.withRegion(region.getName)
.build()

lazy val scanamo = Scanamo(???) // TODO dynamoDB
}
4 changes: 3 additions & 1 deletion common/src/main/scala/com/gu/media/model/Asset.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.gu.media.model

import ai.x.play.json.Encoders.encoder
import com.gu.contentatom.thrift.atom.media.{Asset => ThriftAsset}
import ai.x.play.json.Jsonx
import play.api.libs.json.{Format, OFormat}

case class Asset(assetType: AssetType,
version: Long,
Expand All @@ -12,6 +14,6 @@ case class Asset(assetType: AssetType,
}

object Asset {
implicit val assetFormat = Jsonx.formatCaseClass[Asset]
implicit val assetFormat: Format[Asset] = Jsonx.formatCaseClass[Asset]
def fromThrift(asset: ThriftAsset) = Asset(AssetType.fromThrift(asset.assetType), asset.version, asset.id, Platform.fromThrift(asset.platform), asset.mimeType)
}
4 changes: 2 additions & 2 deletions common/src/main/scala/com/gu/media/model/AssetType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ object AssetType {
}
})

val assetTypeWrites = Writes[AssetType] (cat => {
val assetTypeWrites: Writes[AssetType] = Writes[AssetType] (cat => {
JsString(cat.name)
})

implicit val assetTypeFormat = Format(assetTypeReads, assetTypeWrites)
implicit val assetTypeFormat: Format[AssetType] = Format(assetTypeReads, assetTypeWrites)

private val types = List(Audio, Video)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import scala.collection.JavaConverters._

case class AuditMessage(atomId: String, auditType: String, user: String, description: Option[String] = None) extends Logging{

def logMessage() {
def logMessage(): Unit = {
log.info(createMarkers(), "Media Atom Audit")
}

Expand Down
2 changes: 1 addition & 1 deletion common/src/main/scala/com/gu/media/model/Category.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ object Category {
JsString(cat.name)
})

implicit val categoryFormat = Format(categoryReads, categoryWrites)
implicit val categoryFormat: Format[Category] = Format(categoryReads, categoryWrites)

private val types = List(Documentary, Explainer, Feature, Hosted, News, Paid, Livestream)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gu.media.model

import ai.x.play.json.Encoders.encoder
import com.gu.contentatom.thrift.{ChangeRecord => ThriftChangeRecord}
import com.gu.pandomainauth.model.{User => PandaUser}
import ai.x.play.json.Jsonx
Expand Down
1 change: 1 addition & 0 deletions common/src/main/scala/com/gu/media/model/ClientAsset.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gu.media.model

import ai.x.play.json.Encoders.encoder
import com.gu.media.upload.model.Upload
import com.gu.media.youtube.YouTubeProcessingStatus
import ai.x.play.json.Jsonx
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.gu.media.model

import ai.x.play.json.Encoders.encoder
import com.gu.contentatom.thrift.{ContentChangeDetails => ThriftContentChangeDetails}
import ai.x.play.json.Jsonx
import play.api.libs.json.{Format, OFormat}

case class ContentChangeDetails(
lastModified: Option[ChangeRecord],
Expand All @@ -16,7 +18,7 @@ case class ContentChangeDetails(
}

object ContentChangeDetails {
implicit val contentChangeDetailsFormat = Jsonx.formatCaseClass[ContentChangeDetails]
implicit val contentChangeDetailsFormat: Format[ContentChangeDetails] = Jsonx.formatCaseClass[ContentChangeDetails]

def fromThrift(ccd: ThriftContentChangeDetails) = ContentChangeDetails(
ccd.lastModified.map(ChangeRecord.fromThrift),
Expand Down
8 changes: 5 additions & 3 deletions common/src/main/scala/com/gu/media/model/Image.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package com.gu.media.model

import ai.x.play.json.Encoders.encoder
import com.gu.contentatom.thrift.{Image => ThriftImage, ImageAsset => ThriftImageAsset, ImageAssetDimensions => ThriftImageAssetDimensions}
import ai.x.play.json.Jsonx
import play.api.libs.json.{Format, OFormat}

case class ImageAssetDimensions(height: Int, width: Int) {
def asThrift = ThriftImageAssetDimensions(height, width)
}

object ImageAssetDimensions {
implicit val imageAssetDimensionsFormat = Jsonx.formatCaseClass[ImageAssetDimensions]
implicit val imageAssetDimensionsFormat: Format[ImageAssetDimensions] = Jsonx.formatCaseClass[ImageAssetDimensions]

def fromThrift(dim: ThriftImageAssetDimensions) = ImageAssetDimensions(dim.height, dim.width)
}
Expand All @@ -19,7 +21,7 @@ case class ImageAsset(mimeType: Option[String], file: String, dimensions: Option
}

object ImageAsset {
implicit val imageAssetFormat = Jsonx.formatCaseClass[ImageAsset]
implicit val imageAssetFormat: Format[ImageAsset] = Jsonx.formatCaseClass[ImageAsset]

def fromThrift(imgAsset: ThriftImageAsset) = ImageAsset(imgAsset.mimeType, imgAsset.file,
imgAsset.dimensions.map(ImageAssetDimensions.fromThrift), imgAsset.size, imgAsset.aspectRatio)
Expand All @@ -30,7 +32,7 @@ case class Image(assets: List[ImageAsset], master: Option[ImageAsset], mediaId:
}

object Image {
implicit val imageFormat = Jsonx.formatCaseClass[Image]
implicit val imageFormat: Format[Image] = Jsonx.formatCaseClass[Image]

def fromThrift(img: ThriftImage) =
Image(img.assets.map(ImageAsset.fromThrift).toList, img.master.map(ImageAsset.fromThrift), img.mediaId, img.source)
Expand Down
5 changes: 3 additions & 2 deletions common/src/main/scala/com/gu/media/model/MediaAtom.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.gu.media.model

import com.gu.contentatom.thrift.atom.media.{MediaAtom => ThriftMediaAtom, Metadata => ThriftMetadata, YoutubeData => ThriftYoutubeData}
import play.api.libs.json.Format
import play.api.libs.json.{Format, OFormat}
import com.gu.contentatom.thrift.{AtomData, Atom => ThriftAtom, AtomType => ThriftAtomType, Flags => ThriftFlags}
import com.gu.media.util.MediaAtomImplicits
import com.gu.media.youtube.{MediaAtomYoutubeDescriptionHandler, YoutubeDescription}
import ai.x.play.json.Jsonx
import ai.x.play.json.Encoders._

abstract class MediaAtomBase {
//generic metadata
Expand Down Expand Up @@ -231,7 +232,7 @@ case class MediaAtom(
}

object MediaAtom extends MediaAtomImplicits {
implicit val mediaAtomFormat = Jsonx.formatCaseClass[MediaAtom]
implicit val mediaAtomFormat: Format[MediaAtom] = Jsonx.formatCaseClass[MediaAtom]

def fromThrift(atom: ThriftAtom) = {
val data = atom.tdata
Expand Down
4 changes: 2 additions & 2 deletions common/src/main/scala/com/gu/media/model/Platform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ object Platform {
}
})

val platformWrites = Writes[Platform] (cat => {
val platformWrites: Writes[Platform] = Writes[Platform] (cat => {
JsString(cat.name)
})

implicit val platformFormat = Format(platformReads, platformWrites)
implicit val platformFormat: Format[Platform] = Format(platformReads, platformWrites)

private val types = List(Youtube, Facebook, Dailymotion, Mainstream, Url)

Expand Down
1 change: 1 addition & 0 deletions common/src/main/scala/com/gu/media/model/PlutoData.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gu.media.model

import ai.x.play.json.Encoders.encoder
import com.gu.contentatom.thrift.atom.media.{PlutoData => ThriftPlutoData}
import ai.x.play.json.Jsonx
import play.api.libs.json.Format
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.amazonaws.services.s3.model.PutObjectRequest
import com.gu.media.aws.{AwsAccess, UploadAccess}
import com.gu.media.upload.CompleteUploadKey
import ai.x.play.json.Jsonx
import ai.x.play.json.Encoders._
import play.api.libs.json.Format

sealed trait PlutoIntegrationMessage {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ object PrivacyStatus {

val writes: Writes[PrivacyStatus] = Writes[PrivacyStatus](p => JsString(p.name))

implicit val format = Format(reads, writes)
implicit val format: Format[PrivacyStatus] = Format(reads, writes)

val all: Set[PrivacyStatus] = Set(Private, Unlisted, Public)

Expand Down
1 change: 1 addition & 0 deletions common/src/main/scala/com/gu/media/model/User.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gu.media.model

import ai.x.play.json.Encoders.encoder
import com.gu.contentatom.thrift.{User => ThriftUser}
import ai.x.play.json.Jsonx
import play.api.libs.json.Format
Expand Down
1 change: 1 addition & 0 deletions common/src/main/scala/com/gu/media/model/VideoAsset.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gu.media.model

import ai.x.play.json.Encoders.encoder
import ai.x.play.json.Jsonx
import play.api.libs.json.Format

Expand Down
Loading

0 comments on commit b798185

Please sign in to comment.