Skip to content

Commit

Permalink
initial updates for leases based on rights category
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyKilmory committed Oct 21, 2024
1 parent 4853417 commit b49d578
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 7 deletions.
34 changes: 32 additions & 2 deletions common-lib/src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,32 @@ usageRights.applicable = [
#-----------------------------------------------------------------------------------------
usageRights.stdUserExcluded = []

#--------------------------------------------------------------------------------------------
# List of leases that should be associated with an image when a rights category is selected
# (on upload or image edit)
# Format should be:
# usageRights.leases = [ (array)
# {
# category: "<<category-id>>",
# type: "allow-use | deny-use | allow-syndication | deny-syndication",
# startDate: "TODAY | UPLOAD | TAKEN | TXDATE", <- other than today all entries map to image metadata field
# duration: <<int nos years>>, <- optional and will be indefinite if excluded
# notes: "<<text string>>" <- optional
# },
# ...
# ]
#--------------------------------------------------------------------------------------------
usageRights.leases = [
{
category: "screengrab",
type: "allow-use",
startDate: "UPLOAD",
duration: 5,
notes: "test lease"
}
]


usageRightsConfigProvider = {
className: "com.gu.mediaservice.lib.config.RuntimeUsageRightsConfig"
config {
Expand Down Expand Up @@ -123,9 +149,13 @@ usageRightsConfigProvider = {
# }
# can be left blank or excluded if not required
# -------------------------------------------------------
usageInstructions {
}
usageRestrictions {
contract-photographer = "This image has restrictions - see special instructions for details"
handout = "This image can only be used in that context from which it originates - or you'll get told off!"
}
usageInstructions {
contract-photographer = "You'll need to ask the photographer nicely if you want to use this image"
obituary = "Make sure the person is dead before you use this image"
}

# -------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import com.sksamuel.elastic4s.http.JavaClient
import com.sksamuel.elastic4s.requests.common.HealthStatus
import com.sksamuel.elastic4s.requests.indexes.CreateIndexResponse
import com.sksamuel.elastic4s.requests.indexes.admin.IndexExistsResponse
import org.apache.http.conn.ssl.NoopHostnameVerifier
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback

import javax.net.ssl.HostnameVerifier
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
Expand Down Expand Up @@ -40,7 +44,11 @@ trait ElasticSearchClient extends ElasticSearchExecutions with GridLogging {

lazy val client = {
logger.info("Connecting to Elastic 8: " + url)
val client = JavaClient(ElasticProperties(url))
//val client = JavaClient(ElasticProperties(url))
val client = JavaClient(
props = ElasticProperties(url),
httpClientConfigCallback = (httpClientBuilder: HttpAsyncClientBuilder) => httpClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
)
ElasticClient(client)
}

Expand Down
51 changes: 51 additions & 0 deletions kahuna/public/js/common/usageRightsUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// -using config lease definitions to create leases for image based on chosen rights category-
export function createCategoryLeases(leaseDefs, image) {
const leaseTypes = ["allow-use", "deny-use", "allow-syndication", "deny-syndication"];
const leases = [];
leaseDefs.forEach((leaseDef) => {
//-establish start date: TODAY | UPLOAD | TAKEN | TXDATE-
const startDteType = leaseDef.startDate ?? "NONE";
let startDate = undefined;
switch (startDteType) {
case ("TODAY"):
startDate = new Date();
break;
case ("UPLOAD"):
startDate = new Date(image.data.uploadTime);
break;
case ("TAKEN"):
if (image.data.metadata.dateTaken) {
startDate = new Date(image.data.metadata.dateTaken);
}
break;
case ("TXDATE"):
if (image.data.metadata.domainMetadata &&
image.data.metadata.domainMetadata.programmes &&
image.data.metadata.domainMetadata.programmes.originalTxDate) {
startDate = new Date(image.data.metadata.domainMetadata.programmes.originalTxDate);
}
break;
default:
startDate = undefined;
break;
}
// -check we have acceptable type and startDate-
if (leaseTypes.includes(leaseDef.type ?? "") && startDate) {
const lease = {};
lease["access"] = leaseDef.type;
lease["createdAt"] = (new Date()).toISOString();
lease["leasedBy"] = "Usage_Rights_Category";
lease["startDate"] = startDate.toISOString();
lease["notes"] = leaseDef.notes ?? "";

if (leaseDef.duration) {
let endDate = startDate;
endDate.setFullYear(endDate.getFullYear() + leaseDef.duration);
lease["endDate"] = endDate.toISOString();
}
lease["mediaId"] = image.data.id;
leases.push(lease);
}
});
return leases;
}
22 changes: 19 additions & 3 deletions kahuna/public/js/edits/image-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {imageService} from '../image/service';
import '../services/label';
import {imageAccessor} from '../services/image-accessor';
import {usageRightsEditor} from '../usage-rights/usage-rights-editor';
import { createCategoryLeases } from '../common/usageRightsUtils.js';
import {metadataTemplates} from "../metadata-templates/metadata-templates";
import {leases} from '../leases/leases';
import {archiver} from '../components/gr-archiver-status/gr-archiver-status';
Expand Down Expand Up @@ -317,9 +318,24 @@ imageEditor.controller('ImageEditorCtrl', [
}

function batchApplyUsageRights() {
$rootScope.$broadcast(batchApplyUsageRightsEvent, {
data: ctrl.usageRights.data
});
$rootScope.$broadcast(batchApplyUsageRightsEvent, {
data: ctrl.usageRights.data
});

//-rights category derived leases-
const mtchingRightsCats = ctrl.categories.filter(c => c.value == ctrl.usageRights.data.category);
if (mtchingRightsCats.length > 0) {
const rightsCat = mtchingRightsCats[0];
if (rightsCat.leases.length > 0) {
const catLeases = createCategoryLeases(rightsCat.leases, ctrl.image);
if (catLeases.length > 0) {
$rootScope.$broadcast('events:rights-category:add-leases', {
catLeases: catLeases,
batch: true
});
}
}
}
}

function openCollectionTree() {
Expand Down
9 changes: 9 additions & 0 deletions kahuna/public/js/leases/leases.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ leases.controller('LeasesCtrl', [
// which also isn't ideal, but isn't quadratic either.
const batchAddLeasesEvent = 'events:batch-apply:add-leases';
const batchRemoveLeasesEvent = 'events:batch-apply:remove-leases';
const rightsCatAddLeasesEvent = 'events:rights-category:add-leases';

//-handle rights cat assigned lease-
$scope.$on(rightsCatAddLeasesEvent,
(e, payload) => {
if (payload.catLeases[0].mediaId === ctrl.images[0].data.id || payload.batch) {
leaseService.replace(ctrl.images[0], payload.catLeases);
}
});

if (Boolean(ctrl.withBatch)) {
$scope.$on(batchAddLeasesEvent,
Expand Down
17 changes: 17 additions & 0 deletions kahuna/public/js/usage-rights/usage-rights-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {List} from 'immutable';

import '../services/image-list';

import { createCategoryLeases } from '../common/usageRightsUtils.js';

import template from './usage-rights-editor.html';
import './usage-rights-editor.css';

Expand Down Expand Up @@ -202,6 +204,7 @@ usageRightsEditor.controller(
const resource = image.data.userMetadata.data.usageRights;
return editsService.update(resource, data, image, true);
},
({ image }) => setLeasesFromUsageRights(image),
({ image }) => setMetadataFromUsageRights(image, true),
({ image }) => image.get()
],'images-updated');
Expand All @@ -227,6 +230,20 @@ usageRightsEditor.controller(
'Unexpected error';
}

function setLeasesFromUsageRights(image) {
if (ctrl.category.leases.length === 0) {
return;
}
const catLeases = createCategoryLeases(ctrl.category.leases, image);
if (catLeases.length === 0) {
return;
}
$rootScope.$broadcast('events:rights-category:add-leases', {
catLeases: catLeases,
batch: false
});
}

// HACK: This should probably live somewhere else, but it's the least intrusive
// here. This updates the metadata based on the usage rights to stop users having
// to enter content twice.
Expand Down
3 changes: 3 additions & 0 deletions metadata-editor/app/controllers/EditsApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.gu.mediaservice.lib.config.{RuntimeUsageRightsConfig, UsageRightsConf
import com.gu.mediaservice.model._
import lib.EditsConfig
import model.UsageRightsProperty
import model.UsageRightsLease
import play.api.libs.json._
import play.api.mvc.Security.AuthenticatedRequest
import play.api.mvc.{AnyContent, BaseController, ControllerComponents}
Expand Down Expand Up @@ -75,6 +76,7 @@ case class CategoryResponse(
defaultRestrictions: Option[String],
caution: Option[String],
properties: List[UsageRightsProperty] = List(),
leases: Seq[UsageRightsLease] = Seq(),
usageRestrictions: Option[String],
usageSpecialInstructions: Option[String]
)
Expand All @@ -90,6 +92,7 @@ object CategoryResponse {
defaultRestrictions = u.defaultRestrictions,
caution = u.caution,
properties = UsageRightsProperty.getPropertiesForSpec(u, config.usageRightsConfig),
leases = UsageRightsLease.getLeasesForSpec(u, config.usageRightsLeases),
usageRestrictions = config.customUsageRestrictions.get(u.category),
usageSpecialInstructions = config.customSpecialInstructions.get(u.category)
)
Expand Down
4 changes: 3 additions & 1 deletion metadata-editor/app/lib/EditsConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package lib

import com.amazonaws.regions.{Region, RegionUtils}
import com.gu.mediaservice.lib.config.{CommonConfig, GridConfigResources}

import model.UsageRightsLease

class EditsConfig(resources: GridConfigResources) extends CommonConfig(resources) {
val dynamoRegion: Region = RegionUtils.getRegion(string("aws.region"))
Expand All @@ -19,6 +19,8 @@ class EditsConfig(resources: GridConfigResources) extends CommonConfig(resources
val kahunaUri: String = services.kahunaBaseUri
val loginUriTemplate: String = services.loginUriTemplate

val usageRightsLeases: Seq[UsageRightsLease] = configuration.getOptional[Seq[UsageRightsLease]]("usageRights.leases").getOrElse(Seq.empty)

val customSpecialInstructions: Map[String, String] =
configuration.getOptional[Map[String, String]]("usageInstructions").getOrElse(Map.empty)

Expand Down
59 changes: 59 additions & 0 deletions metadata-editor/app/model/UsageRightsLease.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package model

import com.gu.mediaservice.model._
import play.api.ConfigLoader
import play.api.libs.json._
import scala.collection.JavaConverters._
import scala.util.{Failure, Success, Try}
import java.time.{LocalDate, Period}

case class UsageRightsLease(
category: String,
`type`: String,
startDate: String,
duration: Option[Int],
notes: Option[String]
)

object UsageRightsLease {

def getLeasesForSpec(u: UsageRightsSpec, leases: Seq[UsageRightsLease]): Seq[UsageRightsLease] = leases.filter(_.category == u.category)

implicit val writes: Writes[UsageRightsLease] = Json.writes[UsageRightsLease]

implicit val configLoader: ConfigLoader[Seq[UsageRightsLease]] = {
ConfigLoader(_.getConfigList).map(
_.asScala.map(config => {

val categoryId = if (config.hasPath("category")) {
config.getString("category")
} else ""

val leaseType = if (config.hasPath("type")) {
config.getString("type")
} else ""

val startDate = if (config.hasPath("startDate")) {
config.getString("startDate")
} else ""

val duration = if (config.hasPath("duration")) {
Some(config.getInt("duration"))
} else None

val notes = if (config.hasPath("notes")) {
Some(config.getString("notes"))
} else None

UsageRightsLease (
category = categoryId,
`type` = leaseType,
startDate = startDate,
duration = duration,
notes = notes
)

}))
}

}

0 comments on commit b49d578

Please sign in to comment.