Skip to content

Commit fd4bb2c

Browse files
committed
Merge branch 'ld/java-sdk-upgrade-s3' into ld/java-sdk-iam
2 parents 22d50ea + af000a1 commit fd4bb2c

File tree

22 files changed

+221
-81
lines changed

22 files changed

+221
-81
lines changed

app/controllers/IconikController.scala

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ import com.gu.pandahmac.HMACAuthActions
66
import com.typesafe.config.Config
77
import data.{DataStores, UnpackedDataStores}
88
import play.api.libs.json.Json
9-
import play.api.mvc.{Action, AnyContent, BaseController, ControllerComponents}
9+
import play.api.mvc.{
10+
Action,
11+
AnyContent,
12+
BaseController,
13+
ControllerComponents,
14+
Cookie
15+
}
1016
import util.AWSConfig
1117

1218
class IconikController(
@@ -20,7 +26,15 @@ class IconikController(
2026
with JsonRequestParsing
2127
with Logging {
2228

23-
import authActions.{APIAuthAction, APIHMACAuthAction}
29+
import authActions.{APIAuthAction, APIHMACAuthAction, AuthAction}
30+
31+
def switchShowIconikUiOn(): Action[AnyContent] = AuthAction { implicit req =>
32+
Redirect("/", FOUND).withCookies(Cookie("showIconik", "true"))
33+
}
34+
35+
def switchShowIconikUiOff(): Action[AnyContent] = AuthAction { implicit req =>
36+
Redirect("/", FOUND).withCookies(Cookie("showIconik", "false"))
37+
}
2438

2539
def getWorkingGroup(groupId: String): Action[AnyContent] = APIAuthAction {
2640
stores.iconikDataStore.getWorkingGroup(groupId) match {

app/controllers/VideoUIApp.scala

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ import com.gu.pandomainauth.model.User
88
import model.{ClientConfig, Presence}
99
import play.api.Configuration
1010
import play.api.libs.json.Json
11-
import play.api.mvc.{Action, AnyContent, BaseController, ControllerComponents}
11+
import play.api.mvc.{
12+
Action,
13+
AnyContent,
14+
BaseController,
15+
ControllerComponents,
16+
Cookie
17+
}
1218
import util.{AWSConfig, TrainingMode}
1319
import views.html.helper.CSRF
1420

@@ -30,6 +36,11 @@ class VideoUIApp(
3036

3137
def index(id: String = ""): Action[AnyContent] = AuthAction { implicit req =>
3238
val isTrainingMode = isInTrainingMode(req)
39+
val shouldShowIconikUi = req.cookies.get("showIconik") match {
40+
case Some(cookie) if cookie.value == "true" => true
41+
case Some(cookie) if cookie.value == "false" => false
42+
case None => conf.get[String]("stage") != "PROD"
43+
}
3344

3445
val jsFileName = "video-ui/build/app.js"
3546

@@ -61,7 +72,7 @@ class VideoUIApp(
6172
workflowUrl = awsConfig.workflowUrl,
6273
targetingUrl = awsConfig.targetingUrl,
6374
tagManagerUrl = awsConfig.tagManagerUrl,
64-
showIconik = conf.get[String]("stage") != "PROD"
75+
showIconik = shouldShowIconikUi
6576
)
6677

6778
Ok(

app/model/commands/UpdateAtomCommand.scala

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import com.gu.contentatom.thrift.{
88
EventType,
99
ChangeRecord => ThriftChangeRecord
1010
}
11+
import com.gu.media.iconik.{
12+
IconikProjectAssignedToAtomMessage,
13+
IconikUploadActions
14+
}
1115
import com.gu.media.logging.Logging
1216
import com.gu.media.model.{
1317
AtomAssignedProjectMessage,
@@ -20,7 +24,10 @@ import com.gu.media.util.MediaAtomImplicits
2024
import com.gu.pandomainauth.model.{User => PandaUser}
2125
import data.DataStores
2226
import model.commands.CommandExceptions._
23-
import model.commands.UpdateAtomCommand.createDiffString
27+
import model.commands.UpdateAtomCommand.{
28+
createDiffString,
29+
shouldNotifyThirdPartyServices
30+
}
2431
import org.joda.time.DateTime
2532
import util.AWSConfig
2633

@@ -131,8 +138,7 @@ case class UpdateAtomCommand(
131138

132139
val existingMediaAtom = MediaAtom.fromThrift(existingAtom)
133140
val updatedMediaAtom = MediaAtom.fromThrift(thrift)
134-
processPlutoData(existingMediaAtom, updatedMediaAtom)
135-
141+
updateThirdPaties(existingMediaAtom, updatedMediaAtom)
136142
AuditMessage(
137143
atom.id,
138144
"Update",
@@ -157,16 +163,31 @@ case class UpdateAtomCommand(
157163
)
158164
}
159165

160-
private def processPlutoData(oldAtom: MediaAtom, newAtom: MediaAtom) = {
161-
(
162-
oldAtom.plutoData.flatMap(_.projectId),
163-
newAtom.plutoData.flatMap(_.projectId)
164-
) match {
165-
case (Some(oldProject), Some(newProject)) if oldProject != newProject =>
166-
notifyPluto(newAtom)
167-
case (None, Some(_)) => notifyPluto(newAtom)
168-
case (_, _) => None
166+
private def updateThirdPaties(oldAtom: MediaAtom, newAtom: MediaAtom) = {
167+
val oldIconikId = oldAtom.iconikData.flatMap(_.projectId)
168+
val newIconikId = newAtom.iconikData.flatMap(_.projectId)
169+
if (shouldNotifyThirdPartyServices(oldIconikId, newIconikId)) {
170+
notifyIconik(newAtom)
169171
}
172+
173+
val oldPlutoId = oldAtom.plutoData.flatMap(_.projectId)
174+
val newPlutoId = newAtom.plutoData.flatMap(_.projectId)
175+
if (shouldNotifyThirdPartyServices(oldPlutoId, newPlutoId)) {
176+
notifyPluto(newAtom)
177+
}
178+
}
179+
180+
private def notifyIconik(newAtom: MediaAtom) = {
181+
val iconikUploadActions = new IconikUploadActions(awsConfig)
182+
newAtom.iconikData.foreach(iconikData =>
183+
iconikUploadActions.sendMessage(
184+
IconikProjectAssignedToAtomMessage(
185+
newAtom.id,
186+
newAtom.assets,
187+
iconikData
188+
)
189+
)
190+
)
170191
}
171192

172193
private def notifyPluto(newAtom: MediaAtom) = {
@@ -202,4 +223,16 @@ object UpdateAtomCommand {
202223
"Updated atom fields"
203224
} else s"Updated atom fields (${changedFields.mkString(", ")})"
204225
}
226+
227+
def shouldNotifyThirdPartyServices(
228+
oldProjectId: Option[String],
229+
newProjectId: Option[String]
230+
): Boolean = {
231+
(oldProjectId, newProjectId) match {
232+
case (Some(oldProject), Some(newProject)) if oldProject != newProject =>
233+
true
234+
case (None, Some(_)) => true
235+
case (_, _) => false
236+
}
237+
}
205238
}

app/util/PlutoMessageConsumer.scala

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,9 @@ case class PlutoMessageConsumer(val stores: DataStores, awsConfig: AWSConfig)
7171

7272
(bodyJson \ "Message").validate[PlutoMessage] match {
7373
case JsSuccess(plutoMessage, _) => {
74-
75-
awsConfig.s3Client.deleteObject(
76-
DeleteObjectRequest
77-
.builder()
78-
.bucket(awsConfig.userUploadBucket)
79-
.key(plutoMessage.s3Key)
80-
.build()
74+
log.info(
75+
s"Processing Pluto message to delete asset for s3Key: ${plutoMessage.s3Key}. nb. Deletion is currently disabled so this is a no-op."
8176
)
82-
83-
stores.pluto.get(plutoMessage.s3Key) match {
84-
case Some(upload) => stores.pluto.delete(plutoMessage.s3Key)
85-
case _ =>
86-
}
87-
8877
}
8978
case undefined =>
9079
log.error(

app/util/UploadBuilder.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ object UploadBuilder {
3030
region = aws.awsV2Region.id(),
3131
title = atom.title,
3232
pluto = plutoData,
33+
iconikData = atom.iconikData,
3334
selfHost = request.selfHost,
3435
runtime = getRuntimeMetadata(request.selfHost, atom.channelId),
3536
asset = getAsset(

common/src/main/scala/com/gu/media/aws/SQSAccess.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import com.gu.media.Settings
66
trait SQSAccess { this: Settings with AwsAccess =>
77

88
lazy val plutoQueueUrl: String = getMandatoryString("aws.sqs.plutoQueueUrl")
9+
lazy val iconikQueueUrl: String = getMandatoryString("aws.sqs.iconikQueueUrl")
910

1011
lazy val sqsClient =
1112
SqsClient
1213
.builder()
1314
.credentialsProvider(credentials.instance.awsV2Creds)
15+
.region(awsV2Region)
1416
.build()
1517
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.gu.media.iconik
2+
3+
import com.gu.media.Settings
4+
import com.gu.media.aws.SQSAccess
5+
import com.gu.media.model.{Asset, IconikData}
6+
import play.api.libs.json.{Json, OFormat}
7+
import com.gu.media.logging.Logging
8+
import software.amazon.awssdk.services.sqs.model.SendMessageRequest
9+
10+
sealed trait IconikMessage {
11+
def atomId: String
12+
def toJsonString: String
13+
}
14+
15+
case class IconikProjectAssignedToAtomMessage(
16+
atomId: String,
17+
assets: List[Asset],
18+
iconikData: IconikData
19+
) extends IconikMessage {
20+
override def toJsonString: String =
21+
Json.stringify(Json.toJson(this))
22+
}
23+
24+
object IconikProjectAssignedToAtomMessage {
25+
implicit val format: OFormat[IconikProjectAssignedToAtomMessage] =
26+
Json.format[IconikProjectAssignedToAtomMessage]
27+
}
28+
29+
case class AssetUploadedToAtomMessage(
30+
atomId: String,
31+
uploadS3Key: String,
32+
iconikData: Option[IconikData]
33+
) extends IconikMessage {
34+
override def toJsonString: String =
35+
Json.stringify(Json.toJson(this))
36+
}
37+
38+
object AssetUploadedToAtomMessage {
39+
implicit val format: OFormat[AssetUploadedToAtomMessage] =
40+
Json.format[AssetUploadedToAtomMessage]
41+
}
42+
43+
class IconikUploadActions(config: Settings with SQSAccess) extends Logging {
44+
def sendMessage(message: IconikMessage) = {
45+
val payload = message.toJsonString
46+
log.info(
47+
s"Updating Iconik with latest change for atom: $payload"
48+
)
49+
config.sqsClient.sendMessage(
50+
SendMessageRequest
51+
.builder()
52+
.queueUrl(config.iconikQueueUrl)
53+
.messageBody(payload)
54+
.build()
55+
)
56+
}
57+
58+
}

common/src/main/scala/com/gu/media/upload/model/UploadMetadata.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,20 @@ package com.gu.media.upload.model
33
import com.gu.ai.x.play.json.Jsonx
44
import com.gu.ai.x.play.json.Encoders._
55
import play.api.libs.json.Format
6-
import com.gu.media.model.{PlutoSyncMetadataMessage, VideoAsset, VideoSource}
6+
import com.gu.media.model.{
7+
IconikData,
8+
PlutoSyncMetadataMessage,
9+
VideoAsset,
10+
VideoSource
11+
}
712

813
case class UploadMetadata(
914
user: String,
1015
bucket: String,
1116
region: String,
1217
title: String,
1318
pluto: PlutoSyncMetadataMessage,
19+
iconikData: Option[IconikData],
1420
runtime: RuntimeUploadMetadata,
1521
version: Option[Long] = None,
1622
selfHost: Boolean = false,

common/src/main/scala/com/gu/media/youtube/package.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ package object youtube {
4747
"science" -> "gdnpfpscience",
4848
"athletics" -> "gdnpfpsportother",
4949
"basketball" -> "gdnpfpsportus",
50-
"sport-2-0" -> "gdnpfpsport20"
50+
"sport-2-0" -> "gdnpfpsport20",
51+
"full-story-podcast" -> "gdnpfpausfullstorypodcast"
5152
)
5253

5354
case class YouTubeVideoCategory(id: Int, title: String)

common/src/test/scala/com/gu/media/upload/UploadTest.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class UploadTest
116116
region = "local",
117117
title = "my-video",
118118
pluto = plutoMessage,
119+
iconikData = None,
119120
runtime = SelfHostedUploadMetadata(Nil),
120121
subtitleVersion = Some(12),
121122
subtitleSource =
@@ -128,6 +129,7 @@ class UploadTest
128129
region = "local",
129130
title = "my-video",
130131
pluto = plutoMessage,
132+
iconikData = None,
131133
runtime = SelfHostedUploadMetadata(Nil)
132134
)
133135
}

0 commit comments

Comments
 (0)