Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add export of assets (DEV-2106) #2668

Merged
merged 92 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
891d512
refactor: Separate rest and permission logic from ProjectsResponderADM
seakayone May 2, 2023
b1291fe
refactor: Separate rest and permission logic from ProjectsResponderADM
seakayone May 2, 2023
b08d8a2
Move response classe to api.model package
seakayone May 2, 2023
efbbd5b
fix test
seakayone May 2, 2023
3d71716
fmt
seakayone May 2, 2023
aac7524
no need for call by name
seakayone May 2, 2023
1ead141
add test
seakayone May 2, 2023
de7cfc1
add tests and include check for active user in ensure methods
seakayone May 2, 2023
6eac0d5
clarify error message
seakayone May 2, 2023
1041abe
scaladoc
seakayone May 2, 2023
5596588
import
seakayone May 2, 2023
1d41193
formatting
seakayone May 2, 2023
f80a0ab
add save and delete to in memory implementation for KnoraProjectRepoI…
seakayone May 2, 2023
e68daa6
Add AbstractInMemoryCrudRepository
seakayone May 2, 2023
29aab43
fmt
seakayone May 2, 2023
7069429
move classes to correct packages
seakayone May 2, 2023
c550063
Replace MessageRelay with direct TriplestoreService call in ProjectEx…
seakayone May 3, 2023
d20a5be
remove unused parameter from method
seakayone May 3, 2023
1c435c5
return trait, organize import
seakayone May 3, 2023
3ff2dfe
extract methods
seakayone May 3, 2023
1904821
Replace CombiningRdfProcessor and unsafe resource handling with TriGC…
seakayone May 3, 2023
6f56837
Merge branch 'main' into refactor/organize-packages
seakayone May 3, 2023
643138f
fixup!
seakayone May 3, 2023
dc46e91
fmt
seakayone May 3, 2023
dc98dcc
Merge branch 'main' into refactor/organize-packages
seakayone May 4, 2023
d0f6565
cleanup
seakayone May 3, 2023
5687b11
fmt
seakayone May 4, 2023
6407f08
Add license headers
seakayone May 4, 2023
a4f356b
Rename method
seakayone May 4, 2023
14be5b2
fmt fixup
seakayone May 4, 2023
860c9bb
Improve temp file handling, ensure that temp files are remove by the …
seakayone May 4, 2023
498b9f9
Replace OntologyConstants with named graph constants from AdminConstants
seakayone May 4, 2023
73c6bda
Add zio-nio to dependencies
seakayone May 4, 2023
23e3e2a
Merge branch 'main' into feat/add-permanent-export
seakayone May 4, 2023
828303f
Add ZipUtility
seakayone May 4, 2023
026707e
wip // add routes and zip project triples
seakayone May 4, 2023
e03b579
fmt
seakayone May 5, 2023
5f9a60c
add exportAsset method
seakayone May 5, 2023
3142368
Port ProjectExportService to zio.nio
seakayone May 5, 2023
66fd8f0
scaladoc
seakayone May 5, 2023
908ade2
Merge branch 'main' into feat/add-export-of-assets
seakayone May 15, 2023
9183e5f
wip add sparql query
seakayone May 15, 2023
4ea60a0
align sipi authorization for all endpoints
seakayone May 15, 2023
5b46f03
Add assets to project export
seakayone May 16, 2023
d4d8a8d
rm test data
seakayone May 16, 2023
e32a40b
fmt
seakayone May 16, 2023
2ecd7f7
header
seakayone May 16, 2023
124552d
doc
seakayone May 16, 2023
ed06c34
logging
seakayone May 16, 2023
bef6451
fixup authentication.lua provide raw and decoded token
seakayone May 16, 2023
243055e
fmt
seakayone May 16, 2023
78e05bd
improve error handling and logging
seakayone May 16, 2023
02b07b8
inline auth_get_jwt_raw to get_permission_on_file
seakayone May 16, 2023
adee970
fmt
seakayone May 16, 2023
b1371c1
reduce visibility and make final AssetService
seakayone May 16, 2023
d69dce9
use sipiConf.internalBaseUrl
seakayone May 16, 2023
80e76d6
log finetuning
seakayone May 16, 2023
d7fcf49
Merge branch 'main' into feat/add-export-of-assets
seakayone May 16, 2023
773c2e1
get the login token lazy as a val so that individual test can be run …
seakayone May 17, 2023
b77d71d
get jwt early in sipi lua
seakayone May 22, 2023
eaabc46
change signature for createJwt to accept a UserADM only
seakayone May 22, 2023
5106724
Merge branch 'main' into feat/add-export-of-assets
seakayone May 22, 2023
f4fe78f
Align authorization for all endpoints of knora-sipi
seakayone May 22, 2023
a957f55
Add documentation
seakayone May 22, 2023
e49579f
add error handling to authentication
seakayone May 22, 2023
53ff9ee
Merge branch 'main' into feat/align-sipi-auth-support
seakayone May 22, 2023
6f0796b
rm useless comment
seakayone May 22, 2023
91e41a4
Revert "rm useless comment"
seakayone May 22, 2023
1d327fb
rm useless comment
seakayone May 22, 2023
d7534d3
Merge branch 'feat/align-sipi-auth-support' into feat/add-export-of-a…
seakayone May 22, 2023
51c4c6a
fmt
seakayone May 22, 2023
f9b652a
reset timeout
seakayone May 22, 2023
dbcf5b7
Merge branch 'main' into feat/add-export-of-assets
seakayone May 22, 2023
2d54ba5
Merge branch 'main' into feat/add-export-of-assets
seakayone May 23, 2023
65d87f0
add scoverage dependency to build.sbt, fix intellij run IT
seakayone May 23, 2023
3d345ad
remove unused field
seakayone May 23, 2023
3f4dd56
ignore missing token in preflight function, log decoding success with…
seakayone May 23, 2023
0c1803f
change only necessary parts of IIFServiceSipiImpl
seakayone May 23, 2023
4d02a9a
update app to latest stable release
seakayone May 23, 2023
d4307ef
add more info to debug logging
seakayone May 24, 2023
a033d1d
download knora.json along with the asset
seakayone May 24, 2023
5690ef6
Merge branch 'main' into feat/add-export-of-assets
seakayone May 24, 2023
02cb3f3
Merge branch 'main' into feat/add-export-of-assets
seakayone May 25, 2023
59a335f
fmt
seakayone May 25, 2023
cbe3cce
improve logging
seakayone May 25, 2023
75f7993
only download knora.json if asset was downloaded
seakayone May 25, 2023
20702db
remove redundant braces
seakayone May 25, 2023
c131c0a
Merge branch 'main' into feat/add-export-of-assets
seakayone May 25, 2023
964ea63
Update project/Dependencies.scala
seakayone May 25, 2023
8e031b7
Update webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/…
seakayone May 25, 2023
03476ae
Update webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/…
seakayone May 25, 2023
1a16c68
Merge branch 'main' into feat/add-export-of-assets
seakayone May 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: '3.7'
services:

app:
image: daschswiss/dsp-app:latest
image: daschswiss/dsp-app:v10.19.2
seakayone marked this conversation as resolved.
Show resolved Hide resolved
ports:
- "4200:4200"
networks:
Expand Down Expand Up @@ -41,7 +41,10 @@ services:
- SIPI_EXTERNAL_PROTOCOL=http
- SIPI_EXTERNAL_HOSTNAME=0.0.0.0
- SIPI_EXTERNAL_PORT=1024
- SIPI_WEBAPI_HOSTNAME=api
# Use the following line if you start the api as a docker container from this docker-compose.yml
# - SIPI_WEBAPI_HOSTNAME=api
# Use the following line if you start the api from your IDE
- SIPI_WEBAPI_HOSTNAME=host.docker.internal
- SIPI_WEBAPI_PORT=3333
- KNORA_WEBAPI_KNORA_API_EXTERNAL_HOST=0.0.0.0
- KNORA_WEBAPI_KNORA_API_EXTERNAL_PORT=3333
Expand Down
19 changes: 13 additions & 6 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,18 @@ object Dependencies {
val xmlunitCore = "org.xmlunit" % "xmlunit-core" % "2.9.1"

// test
val akkaHttpTestkit = "com.typesafe.akka" %% "akka-http-testkit" % AkkaHttpVersion // Scala 3 incompatible
val akkaStreamTestkit = "com.typesafe.akka" %% "akka-stream-testkit" % AkkaActorVersion // Scala 3 compatible
val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % AkkaActorVersion // Scala 3 compatible
val scalaTest = "org.scalatest" %% "scalatest" % "3.2.15" // Scala 3 compatible
val testcontainers = "org.testcontainers" % "testcontainers" % "1.18.0"
val wiremock = "com.github.tomakehurst" % "wiremock-jre8" % "2.35.0"
val akkaHttpTestkit = "com.typesafe.akka" %% "akka-http-testkit" % AkkaHttpVersion // Scala 3 incompatible
val akkaStreamTestkit = "com.typesafe.akka" %% "akka-stream-testkit" % AkkaActorVersion // Scala 3 compatible
val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % AkkaActorVersion // Scala 3 compatible
val scalaTest = "org.scalatest" %% "scalatest" % "3.2.15" // Scala 3 compatible
// The scoverage plugin actually adds its dependencies automatically.
// Add it redundantly to the IT dependencies in order to fix build issues with IntelliJ
// Fixes error message when running IT in IntelliJ
// A needed class was not found. This could be due to an error in your runpath.Missing class: scoverage / Invoker$
// java.lang.NoClassDefFoundError: scoverage / Invoker$
val scoverage = "org.scoverage" %% "scalac-scoverage-runtime" % "2.0.7"
val testcontainers = "org.testcontainers" % "testcontainers" % "1.18.0"
val wiremock = "com.github.tomakehurst" % "wiremock-jre8" % "2.35.0"

// found/added by the plugin but deleted anyway
val commonsLang3 = "org.apache.commons" % "commons-lang3" % "3.12.0"
Expand All @@ -118,6 +124,7 @@ object Dependencies {
akkaTestkit,
rdf4jClient,
scalaTest,
scoverage,
testcontainers,
wiremock,
xmlunitCore,
Expand Down
11 changes: 6 additions & 5 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ addSbtPlugin("io.kamon" % "sbt-aspectj-runner" % "1.1.2")
addSbtPlugin("com.typesafe.play" % "sbt-twirl" % "1.5.2")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.1")
addSbtPlugin("com.lightbend.sbt" % "sbt-javaagent" % "0.1.6")
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.7")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.10.4")
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.9.0")
// also update the scalac-scoverage-runtime version in build.sbt
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.7")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.10.4")
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.9.0")

// ad-hoc plugins - uncomment on demenad and keep it commented out in main branch

Expand Down
6 changes: 5 additions & 1 deletion sipi/scripts/authentication.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ require "send_response"
require "strings"
require "util"

local NO_TOKEN_FOUND_ERROR = "No token found"

--- Extracts a JSON web token (JWT) from the HTTP request: header ('Authorization' and 'Cookie') or query param 'token'.
-- If present decodes token and validates claims exp, aud, iss.
-- Sends an HTTP error if the token is invalid.
Expand All @@ -22,7 +24,7 @@ function _token()
local nil_token = { raw = nil, decoded = nil }
local jwt_raw = _get_jwt_string_from_header_params_or_cookie()
if jwt_raw == nil then
return nil_token, "No token found"
return nil_token, NO_TOKEN_FOUND_ERROR
else
local decoded, error = _decode_jwt(jwt_raw)
if decoded == nil then
Expand Down Expand Up @@ -81,6 +83,8 @@ function _decode_jwt(token_str)
if decoded_token["iss"] ~= token_issuer then
return _send_unauthorized_error(401, "Invalid 'iss' (issuer) in token, expected: " .. token_issuer .. ".")
end

log("authentication: decoded jwt token for 'sub' " .. decoded_token["sub"], server.loglevel.LOG_DEBUG)
return decoded_token
end

Expand Down
5 changes: 5 additions & 0 deletions webapi/src/it/scala/org/knora/webapi/core/LayersTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ import org.knora.webapi.testcontainers.FusekiTestContainer
import org.knora.webapi.testcontainers.SipiTestContainer
import org.knora.webapi.testservices.TestClientService
import org.knora.webapi.messages.util.search.gravsearch.transformers.ConstructTransformer
import org.knora.webapi.slice.admin.domain.service.AssetService
import org.knora.webapi.slice.admin.domain.service.AssetServiceLive

object LayersTest {

/**
Expand All @@ -134,6 +137,7 @@ object LayersTest {
ApiRoutes
with AppRouter
with Authenticator
with AssetService
with CacheService
with CacheServiceRequestMessageHandler
with CardinalityHandler
Expand Down Expand Up @@ -200,6 +204,7 @@ object LayersTest {
AuthenticationMiddleware.layer,
AuthenticatorLive.layer,
AuthenticatorService.layer,
AssetServiceLive.layer,
CacheServiceInMemImpl.layer,
CacheServiceRequestMessageHandlerLive.layer,
CardinalityHandlerLive.layer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,27 +182,25 @@ class KnoraSipiIntegrationV1ITSpec
}
}

private def getLoginToken() = {
val params =
s"""
|{
| "email": "$userEmail",
| "password": "$password"
|}
""".stripMargin
val loginResponse: HttpResponse = singleAwaitingRequest(
Post(baseApiUrl + s"/v2/authentication", HttpEntity(ContentTypes.`application/json`, params))
)
assert(loginResponse.status == StatusCodes.OK)
Await.result(Unmarshal(loginResponse.entity).to[LoginResponse], 1.seconds).token
}

"Knora and Sipi" should {
var loginToken: String = ""
lazy val loginToken: String = getLoginToken()

"log in as a Knora user" in {
/* Correct username and correct password */

val params =
s"""
|{
| "email": "$userEmail",
| "password": "$password"
|}
""".stripMargin

val request = Post(baseApiUrl + s"/v2/authentication", HttpEntity(ContentTypes.`application/json`, params))
val response: HttpResponse = singleAwaitingRequest(request)
assert(response.status == StatusCodes.OK)

val lr: LoginResponse = Await.result(Unmarshal(response.entity).to[LoginResponse], 1.seconds)
loginToken = lr.token

loginToken.nonEmpty should be(true)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ import org.knora.webapi.util.MutableTestIri
*/
class StandoffRouteV2ITSpec extends ITKnoraLiveSpec with AuthenticationV2JsonProtocol {

private implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance
val validationFun: (String, => Nothing) => String = (s, e) => Iri.validateAndEscapeIri(s).getOrElse(e)
val validationFun: (String, => Nothing) => String = (s, e) => Iri.validateAndEscapeIri(s).getOrElse(e)

private val anythingUser = SharedTestDataADM.anythingUser1
private val anythingUserEmail = anythingUser.email
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ package org.knora.webapi.routing
import akka.testkit.ImplicitSender
import akka.util.Timeout
import org.scalatest.PrivateMethodTester

import dsp.errors.BadCredentialsException
import dsp.errors.BadRequestException

import org.knora.webapi._
import org.knora.webapi.messages.StringFormatter
import org.knora.webapi.messages.admin.responder.usersmessages.UserADM
import org.knora.webapi.messages.admin.responder.usersmessages.UserIdentifierADM
import org.knora.webapi.messages.v2.routing.authenticationmessages.KnoraCredentialsV2.KnoraJWTTokenCredentialsV2
import org.knora.webapi.messages.v2.routing.authenticationmessages.KnoraCredentialsV2.KnoraPasswordCredentialsV2
Expand All @@ -32,6 +33,8 @@ class AuthenticatorSpec extends CoreSpec with ImplicitSender with PrivateMethodT

implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance

private def testUserAdmFromIri(iri: String) = UserADM(iri, "", "", "", "", false, "")

"During Authentication" when {
"called, the 'getUserADMByEmail' method " should {
"succeed with the correct 'email' " in {
Expand Down Expand Up @@ -89,7 +92,8 @@ class AuthenticatorSpec extends CoreSpec with ImplicitSender with PrivateMethodT
"succeed with correct token" in {
val resF = UnsafeZioRun.runToFuture(
for {
token <- JwtService.createToken("http://rdfh.ch/users/X-T8IkfQTKa86UWuISpbOA")
token <-
JwtService.createJwt(testUserAdmFromIri("http://rdfh.ch/users/X-T8IkfQTKa86UWuISpbOA")).map(_.jwtString)
tokenCreds = KnoraJWTTokenCredentialsV2(token)
result <- Authenticator.authenticateCredentialsV2(Some(tokenCreds))
} yield result
Expand All @@ -101,7 +105,8 @@ class AuthenticatorSpec extends CoreSpec with ImplicitSender with PrivateMethodT
assertThrows[BadCredentialsException] {
throw UnsafeZioRun
.run(for {
token <- JwtService.createToken("http://rdfh.ch/users/X-T8IkfQTKa86UWuISpbOA")
token <-
JwtService.createJwt(testUserAdmFromIri("http://rdfh.ch/users/X-T8IkfQTKa86UWuISpbOA")).map(_.jwtString)
tokenCreds = KnoraJWTTokenCredentialsV2(token)
_ = CacheUtil.put(AUTHENTICATION_INVALIDATION_CACHE_NAME, tokenCreds.jwtToken, tokenCreds.jwtToken)
result <- Authenticator.authenticateCredentialsV2(Some(tokenCreds))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class JwtServiceSpec extends CoreSpec with ImplicitSender {

"create a token" in {
val runZio = for {
token <- JwtService.createToken(SharedTestDataADM.anythingUser1.id, Map("foo" -> JsString("bar")))
token <- JwtService.createJwt(SharedTestDataADM.anythingUser1, Map("foo" -> JsString("bar"))).map(_.jwtString)
useriri <- JwtService.extractUserIriFromToken(token)
} yield useriri

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
package org.knora.webapi.store.iiif.impl

import zio._
import zio.nio.file.Path

import org.knora.webapi.messages.admin.responder.usersmessages.UserADM
import org.knora.webapi.messages.store.sipimessages._
import org.knora.webapi.messages.v2.responder.SuccessResponseV2
import org.knora.webapi.slice.admin.domain.service.Asset
import org.knora.webapi.store.iiif.api.IIIFService
import org.knora.webapi.store.iiif.errors.SipiException

Expand Down Expand Up @@ -56,6 +59,8 @@ case class IIIFServiceMockImpl() extends IIIFService {
override def getTextFileRequest(textFileRequest: SipiGetTextFileRequest): Task[SipiGetTextFileResponse] = ???

override def getStatus(): Task[IIIFServiceStatusResponse] = ZIO.succeed(IIIFServiceStatusOK)

override def downloadAsset(asset: Asset, targetDir: Path, user: UserADM): Task[Option[Path]] = ???
}

object IIIFServiceMockImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ import org.knora.webapi.routing.admin.AuthenticatorService
import org.knora.webapi.routing.admin.ProjectsRouteZ
import org.knora.webapi.slice.admin.api.service.ProjectADMRestService
import org.knora.webapi.slice.admin.api.service.ProjectsADMRestServiceLive
import org.knora.webapi.slice.admin.domain.service.AssetService
import org.knora.webapi.slice.admin.domain.service.AssetServiceLive
import org.knora.webapi.slice.admin.domain.service.KnoraProjectRepo
import org.knora.webapi.slice.admin.domain.service.ProjectADMService
import org.knora.webapi.slice.admin.domain.service.ProjectADMServiceLive
Expand Down Expand Up @@ -129,6 +131,7 @@ object LayersLive {
with ApiRoutes
with AppConfig
with AppRouter
with AssetService
with Authenticator
with CacheService
with CacheServiceRequestMessageHandler
Expand Down Expand Up @@ -200,6 +203,7 @@ object LayersLive {
ApiRoutes.layer,
AppConfig.layer,
AppRouter.layer,
AssetServiceLive.layer,
AuthenticationMiddleware.layer,
AuthenticatorLive.layer,
AuthenticatorService.layer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,15 @@
val credentials: Option[KnoraCredentialsV2] = extractCredentialsV2(requestContext)

for {
userADM <- getUserADMThroughCredentialsV2(credentials)
userProfile = userADM.asUserProfileV1
cookieDomain = Some(appConfig.cookieDomain)
sessionToken <- jwtService.createToken(userProfile.userData.user_id.get)
userADM <- getUserADMThroughCredentialsV2(credentials)
cookieDomain = Some(appConfig.cookieDomain)
jwt <- jwtService.createJwt(userADM)

Check warning on line 203 in webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala

View check run for this annotation

Codecov / codecov/patch

webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala#L201-L203

Added lines #L201 - L203 were not covered by tests
httpResponse = HttpResponse(
headers = List(
headers.`Set-Cookie`(
HttpCookie(
calculateCookieName(),
sessionToken,
jwt.jwtString,

Check warning on line 209 in webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala

View check run for this annotation

Codecov / codecov/patch

webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala#L209

Added line #L209 was not covered by tests
domain = cookieDomain,
path = Some("/"),
httpOnly = true
Expand All @@ -220,8 +219,8 @@
JsObject(
"status" -> JsNumber(0),
"message" -> JsString("credentials are OK"),
"sid" -> JsString(sessionToken),
"userProfile" -> userProfile.ofType(UserProfileTypeV1.RESTRICTED).toJsValue
"sid" -> JsString(jwt.jwtString),
"userProfile" -> userADM.asUserProfileV1.ofType(UserProfileTypeV1.RESTRICTED).toJsValue

Check warning on line 223 in webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala

View check run for this annotation

Codecov / codecov/patch

webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala#L222-L223

Added lines #L222 - L223 were not covered by tests
).compactPrint
)
)
Expand All @@ -240,14 +239,14 @@
_ <- authenticateCredentialsV2(credentials = Some(credentials))
userADM <- getUserByIdentifier(credentials.identifier)
cookieDomain = Some(appConfig.cookieDomain)
token <- jwtService.createToken(userADM.id)
jwtString <- jwtService.createJwt(userADM).map(_.jwtString)

Check warning on line 242 in webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala

View check run for this annotation

Codecov / codecov/patch

webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala#L242

Added line #L242 was not covered by tests

httpResponse = HttpResponse(
headers = List(
headers.`Set-Cookie`(
HttpCookie(
calculateCookieName(),
token,
jwtString,
domain = cookieDomain,
path = Some("/"),
httpOnly = true
Expand All @@ -258,7 +257,7 @@
entity = HttpEntity(
ContentTypes.`application/json`,
JsObject(
"token" -> JsString(token)
"token" -> JsString(jwtString)

Check warning on line 260 in webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala

View check run for this annotation

Codecov / codecov/patch

webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala#L260

Added line #L260 was not covered by tests
).compactPrint
)
)
Expand Down Expand Up @@ -753,6 +752,8 @@
ZLayer.fromFunction(AuthenticatorLive.apply _)
}

case class Jwt(jwtString: String, expiration: Long)

/**
* Provides functions for creating, decoding, and validating JWT tokens.
*/
Expand All @@ -762,11 +763,11 @@
/**
* Creates a JWT.
*
* @param userIri the user IRI that will be encoded into the token.
* @param user the user IRI that will be encoded into the token.
* @param content any other content to be included in the token.
* @return a [[String]] containing the JWT.
*/
def createToken(userIri: IRI, content: Map[String, JsValue] = Map.empty): Task[String]
def createJwt(user: UserADM, content: Map[String, JsValue] = Map.empty): UIO[Jwt]

/**
* Validates a JWT, taking the invalidation cache into account. The invalidation cache holds invalidated
Expand Down Expand Up @@ -797,13 +798,7 @@

private val logger = Logger(LoggerFactory.getLogger(this.getClass))

/**
* Creates a JWT.
*
* @param userIri the user IRI that will be encoded into the token.
* @return a [[String]] containing the JWT.
*/
override def createToken(userIri: IRI, content: Map[String, JsValue] = Map.empty): Task[String] =
override def createJwt(user: UserADM, content: Map[String, JsValue] = Map.empty): UIO[Jwt] =
for {
now <- Clock.instant
uuid <- ZIO.random.flatMap(_.nextUUID)
Expand All @@ -812,13 +807,13 @@
claim = JwtClaim(
content = JsObject(content).compactPrint,
issuer = Some(issuer),
subject = Some(userIri),
subject = Some(user.id),

Check warning on line 810 in webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala

View check run for this annotation

Codecov / codecov/patch

webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala#L810

Added line #L810 was not covered by tests
audience = Some(Set("Knora", "Sipi")),
issuedAt = Some(now.getEpochSecond),
expiration = Some(exp),
jwtId = jwtId
).toJson
} yield JwtSprayJson.encode(header, claim, secret, algorithm)
} yield Jwt(JwtSprayJson.encode(header, claim, secret, algorithm), exp)

Check warning on line 816 in webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala

View check run for this annotation

Codecov / codecov/patch

webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala#L816

Added line #L816 was not covered by tests

/**
* Validates a JWT, taking the invalidation cache into account. The invalidation cache holds invalidated
Expand Down Expand Up @@ -866,7 +861,7 @@
).contains(false)

if (!missingRequiredContent) {
claim.subject.flatMap(iri => Iri.validateAndEscapeIri(iri).toOption.map(_ => (header, claim)))

Check warning on line 864 in webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala

View check run for this annotation

Codecov / codecov/patch

webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala#L864

Added line #L864 was not covered by tests
} else {
logger.debug("Missing required content in JWT")
None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@
projectIri <-
IriIdentifier.fromString(projectIri).toZIO.orElseFail(BadRequestException(s"Invalid project IRI: $projectIri"))
project <- projectRepo.findById(projectIri).someOrFail(NotFoundException(s"Project $projectIri not found."))
zipFile <- projectExportService.exportProject(project)
zipFile <- projectExportService.exportProject(project, requestingUser)

Check warning on line 241 in webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala

View check run for this annotation

Codecov / codecov/patch

webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala#L241

Added line #L241 was not covered by tests
} yield ProjectExportResponse(zipFile.toString)
}

Expand Down