-
Notifications
You must be signed in to change notification settings - Fork 18
/
SipiResponderADM.scala
144 lines (124 loc) · 6.31 KB
/
SipiResponderADM.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* Copyright © 2021 - 2023 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors.
* SPDX-License-Identifier: Apache-2.0
*/
package org.knora.webapi.responders.admin
import com.typesafe.scalalogging.LazyLogging
import zio.*
import dsp.errors.InconsistentRepositoryDataException
import dsp.errors.NotFoundException
import org.knora.webapi.core.MessageHandler
import org.knora.webapi.core.MessageRelay
import org.knora.webapi.messages.ResponderRequest
import org.knora.webapi.messages.SmartIri
import org.knora.webapi.messages.StringFormatter
import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.ShortcodeIdentifier
import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsADM
import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsGetADM
import org.knora.webapi.messages.admin.responder.sipimessages.SipiFileInfoGetRequestADM
import org.knora.webapi.messages.admin.responder.sipimessages.SipiFileInfoGetResponseADM
import org.knora.webapi.messages.admin.responder.sipimessages.SipiResponderRequestADM
import org.knora.webapi.messages.store.triplestoremessages.IriSubjectV2
import org.knora.webapi.messages.store.triplestoremessages.LiteralV2
import org.knora.webapi.messages.twirl.queries.sparql
import org.knora.webapi.messages.util.PermissionUtilADM
import org.knora.webapi.responders.Responder
import org.knora.webapi.store.triplestore.api.TriplestoreService
import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Construct
/**
* Responds to requests for information about binary representations of resources, and returns responses in Knora API
* ADM format.
*/
trait SipiResponderADM {
/**
* Returns a [[SipiFileInfoGetResponseADM]] containing the permissions and path for a file.
*
* @param request the request.
* @return a [[SipiFileInfoGetResponseADM]].
*/
def getFileInfoForSipiADM(request: SipiFileInfoGetRequestADM): Task[SipiFileInfoGetResponseADM]
}
final case class SipiResponderADMLive(
private val messageRelay: MessageRelay,
private val triplestoreService: TriplestoreService
) extends SipiResponderADM
with MessageHandler
with LazyLogging {
override def isResponsibleFor(message: ResponderRequest): Boolean =
message.isInstanceOf[SipiResponderRequestADM]
/**
* Receives a message of type [[SipiResponderRequestADM]], and returns an appropriate response message, or
* [[Status.Failure]]. If a serious error occurs (i.e. an error that isn't the client's fault), this
* method first returns `Failure` to the sender, then throws an exception.
*/
override def handle(msg: ResponderRequest): Task[Any] = msg match {
case sipiFileInfoGetRequestADM: SipiFileInfoGetRequestADM => getFileInfoForSipiADM(sipiFileInfoGetRequestADM)
case other => Responder.handleUnexpectedMessage(other, this.getClass.getName)
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Methods for generating complete responses.
/**
* Returns a [[SipiFileInfoGetResponseADM]] containing the permissions and path for a file.
*
* @param request the request.
* @return a [[SipiFileInfoGetResponseADM]].
*/
override def getFileInfoForSipiADM(request: SipiFileInfoGetRequestADM): Task[SipiFileInfoGetResponseADM] =
for {
queryResponse <-
triplestoreService
.query(Construct(sparql.admin.txt.getFileValue(request.filename)))
.flatMap(_.asExtended(StringFormatter.getGeneralInstance))
_ = if (queryResponse.statements.isEmpty)
throw NotFoundException(s"No file value was found for filename ${request.filename}")
fileValueIriSubject = queryResponse.statements.keys.head match {
case iriSubject: IriSubjectV2 => iriSubject
case _ =>
throw InconsistentRepositoryDataException(
s"The subject of the file value with filename ${request.filename} is not an IRI"
)
}
assertions = queryResponse.statements(fileValueIriSubject).toSeq.flatMap {
case (predicate: SmartIri, values: Seq[LiteralV2]) =>
values.map { value =>
predicate.toString -> value.toString
}
}
maybeEntityPermission = PermissionUtilADM.getUserPermissionFromAssertionsADM(
entityIri = fileValueIriSubject.toString,
assertions = assertions,
requestingUser = request.requestingUser
)
_ =
logger.debug(
s"SipiResponderADM - getFileInfoForSipiADM - maybePermissionCode: $maybeEntityPermission, requestingUser: ${request.requestingUser.username}"
)
permissionCode: Int = maybeEntityPermission
.map(_.toInt)
.getOrElse(0) // Sipi expects a permission code from 0 to 8
response <- permissionCode match {
case 1 =>
for {
maybeRVSettings <-
messageRelay
.ask[Option[ProjectRestrictedViewSettingsADM]](
ProjectRestrictedViewSettingsGetADM(ShortcodeIdentifier.from(request.projectID))
)
} yield SipiFileInfoGetResponseADM(permissionCode = permissionCode, maybeRVSettings)
case _ =>
ZIO.succeed(
SipiFileInfoGetResponseADM(permissionCode = permissionCode, restrictedViewSettings = None)
)
}
_ = logger.info(s"filename ${request.filename}, permission code: $permissionCode")
} yield response
}
object SipiResponderADMLive {
val layer: URLayer[TriplestoreService & MessageRelay, SipiResponderADM] = ZLayer.fromZIO {
for {
mr <- ZIO.service[MessageRelay]
ts <- ZIO.service[TriplestoreService]
handler <- mr.subscribe(SipiResponderADMLive(mr, ts))
} yield handler
}
}