Skip to content

Commit 4b66682

Browse files
authored
feat(projectsADM): add possibility to get project and members by UUID (DEV-1408) (#2272)
1 parent c59e3e9 commit 4b66682

42 files changed

Lines changed: 993 additions & 627 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/03-apis/api-admin/projects.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
- `POST: /admin/projects` : create a new project
1515

16-
- `GET: /admin/projects/[iri | shortname | shortcode]/<identifier>` : returns a single project identified either through iri, shortname, or shortcode
16+
- `GET: /admin/projects/[iri | shortname | shortcode | uuid]/<identifier>` : returns a single project identified either through iri, shortname, shortcode or UUID
1717

1818
- `PUT: /admin/projects/iri/<identifier>` : update a project identified by iri
1919

@@ -23,7 +23,7 @@
2323

2424
**Project Member Operations:**
2525

26-
- `GET: /admin/projects/[iri | shortname | shortcode]/<identifier>/members` : returns all members part of a project identified through iri, shortname or shortcode
26+
- `GET: /admin/projects/[iri | shortname | shortcode | uuid]/<identifier>/members` : returns all members part of a project identified through iri, shortname, shortcode or UUID
2727

2828
**Project Admin Member Operations:**
2929

‎dsp-shared/src/main/scala/dsp/valueobjects/Iri.scala‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,24 @@ object Iri {
132132
}
133133
}
134134

135+
/**
136+
* Base64Uuid value object.
137+
* This is base64 encoded UUID version without paddings.
138+
*
139+
* @param value to validate.
140+
*/
141+
sealed abstract case class Base64Uuid private (value: String)
142+
object Base64Uuid {
143+
def make(value: String): Validation[ValidationException, Base64Uuid] =
144+
if (value.isEmpty) {
145+
Validation.fail(ValidationException(IriErrorMessages.UuidMissing))
146+
} else if (!V2UuidValidation.hasUuidLength(value)) {
147+
Validation.fail(ValidationException(IriErrorMessages.UuidInvalid(value)))
148+
} else if (!V2UuidValidation.isUuidVersion4Or5(value)) {
149+
Validation.fail(ValidationException(IriErrorMessages.UuidVersionInvalid))
150+
} else Validation.succeed(new Base64Uuid(value) {})
151+
}
152+
135153
/**
136154
* RoleIri value object.
137155
*/
@@ -221,6 +239,8 @@ object IriErrorMessages {
221239
val RoleIriInvalid = (iri: String) => s"Role IRI: $iri is invalid."
222240
val UserIriMissing = "User IRI cannot be empty."
223241
val UserIriInvalid = (iri: String) => s"User IRI: $iri is invalid."
242+
val UuidMissing = "UUID cannot be empty"
243+
val UuidInvalid = (uuid: String) => s"'$uuid' is not a UUID"
224244
val UuidVersionInvalid = "Invalid UUID used to create IRI. Only versions 4 and 5 are supported."
225245
val PropertyIriMissing = "Property IRI cannot be empty."
226246
}

‎dsp-shared/src/main/scala/dsp/valueobjects/V2.scala‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,15 +225,22 @@ object V2UuidValidation {
225225
getUUIDVersion(s) == 4 || getUUIDVersion(s) == 5
226226

227227
/**
228-
* Gets the last segment of IRI, decodes UUID and gets the version.
229-
* @param s the string (IRI) to be checked.
228+
* Decodes Base64 encoded UUID and gets its version.
229+
* @param uuid the Base64 encoded UUID as [[String]] to be checked.
230230
* @return UUID version.
231231
*/
232-
def getUUIDVersion(s: String): Int = {
233-
val encodedUUID = s.split("/").last
232+
def getUUIDVersion(uuid: String): Int = {
233+
val encodedUUID = getUuidFromIri(uuid)
234234
decodeUuid(encodedUUID).version()
235235
}
236236

237+
/**
238+
* Gets the last IRI segment - Base64 encoded UUID.
239+
* @param iri the IRI [[String]] to get the UUID from.
240+
* @return Base64 encoded UUID as [[String]]
241+
*/
242+
def getUuidFromIri(iri: String): String = iri.split("/").last
243+
237244
/**
238245
* Calls `decodeUuidWithErr`, throwing [[InconsistentRepositoryDataException]] if the string cannot be parsed.
239246
*/

‎dsp-shared/src/test/scala/dsp/valueobjects/IriSpec.scala‎

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import zio.test._
1212
import dsp.errors.BadRequestException
1313
import dsp.errors.ValidationException
1414
import dsp.valueobjects.Iri._
15+
import dsp.valueobjects.V2UuidValidation._
1516

1617
/**
1718
* This spec is used to test the [[Iri]] value objects creation.
@@ -35,7 +36,11 @@ object IriSpec extends ZIOSpecDefault {
3536
val validUserIri = "http://rdfh.ch/users/jDEEitJESRi3pDaDjjQ1WQ"
3637
val userIriWithUUIDVersion3 = "http://rdfh.ch/users/cCmdcpn2MO211YYOplR1hQ"
3738

38-
def spec = (groupIriTest + listIriTest + projectIriTest + RoleIriTest + UserIriTest)
39+
val invalidUuid = "MAgdcpn2MO211YYOplR32v"
40+
val uuidVersion3 = getUuidFromIri(userIriWithUUIDVersion3)
41+
val supportedUuid = getUuidFromIri(validUserIri)
42+
43+
def spec = (groupIriTest + listIriTest + projectIriTest + uuidTest + roleIriTest + userIriTest)
3944

4045
private val groupIriTest = suite("IriSpec - GroupIri")(
4146
test("pass an empty value and return an error") {
@@ -190,7 +195,28 @@ object IriSpec extends ZIOSpecDefault {
190195
}
191196
)
192197

193-
private val RoleIriTest = suite("IriSpec - roleIri")(
198+
private val uuidTest = suite("IriSpec - Base64Uuid")(
199+
test("pass an empty value and return an error") {
200+
assertTrue(Base64Uuid.make("") == Validation.fail(ValidationException(IriErrorMessages.UuidMissing)))
201+
},
202+
test("pass an invalid UUID and return an error") {
203+
assertTrue(
204+
Base64Uuid.make(invalidIri) == Validation.fail(ValidationException(IriErrorMessages.UuidInvalid(invalidIri)))
205+
)
206+
},
207+
test("pass an valid UUID, which has not supported version 3") {
208+
assertTrue(
209+
Base64Uuid.make(uuidVersion3) == Validation.fail(ValidationException(IriErrorMessages.UuidVersionInvalid))
210+
)
211+
},
212+
test("pass valid UUID and successfully create value object") {
213+
(for {
214+
uuid <- Base64Uuid.make(supportedUuid)
215+
} yield assertTrue(uuid.value == supportedUuid)).toZIO
216+
}
217+
)
218+
219+
private val roleIriTest = suite("IriSpec - roleIri")(
194220
test("pass an empty value and return an error") {
195221
assertTrue(RoleIri.make("") == Validation.fail(BadRequestException(IriErrorMessages.RoleIriMissing)))
196222
},
@@ -213,7 +239,7 @@ object IriSpec extends ZIOSpecDefault {
213239
}
214240
)
215241

216-
private val UserIriTest = suite("IriSpec - UserIri")(
242+
private val userIriTest = suite("IriSpec - UserIri")(
217243
test("pass an empty value and return an error") {
218244
assertTrue(UserIri.make("") == Validation.fail(BadRequestException(IriErrorMessages.UserIriMissing)))
219245
},

‎test_data/e2e.v2.SearchRouteV2R2RSpec/gravsearchtest1-admin.ttl‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
@prefix knora-admin: <http://www.knora.org/ontology/knora-admin#> .
77
@prefix salsah-gui: <http://www.knora.org/ontology/salsah-gui#> .
88

9-
<http://rdfh.ch/projects/0666> a knora-admin:knoraProject ;
9+
<http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> a knora-admin:knoraProject ;
1010
knora-admin:projectShortname "test"^^xsd:string ;
1111
knora-admin:projectLongname "Test"^^xsd:string ;
1212
knora-admin:projectShortcode "0666"^^xsd:string ;
@@ -25,5 +25,5 @@
2525
knora-admin:familyName "test"^^xsd:string ;
2626
knora-admin:status "true"^^xsd:boolean ;
2727
knora-admin:preferredLanguage "en"^^xsd:string ;
28-
knora-admin:isInProject <http://rdfh.ch/projects/0666> ;
28+
knora-admin:isInProject <http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> ;
2929
knora-admin:isInSystemAdminGroup "true"^^xsd:boolean .

‎test_data/e2e.v2.SearchRouteV2R2RSpec/gravsearchtest1-data.ttl‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,19 +109,19 @@
109109

110110
<http://rdfh.ch/0666/tWxW7jM0S2uMYKifwF0mtQ/values/yK5vML4_Sc6QcTPrdfD1kQ> rdf:object <http://rdfh.ch/0666/tWf2vqMqQ_OcUMJSRj6e5w> .
111111

112-
<http://rdfh.ch/0666/tWf2vqMqQ_OcUMJSRj6e5w> :attachedToProject <http://rdfh.ch/projects/0666> .
112+
<http://rdfh.ch/0666/tWf2vqMqQ_OcUMJSRj6e5w> :attachedToProject <http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> .
113113

114-
<http://rdfh.ch/0666/1rK4ZevpT5eIxj48kgncsQ> :attachedToProject <http://rdfh.ch/projects/0666> .
114+
<http://rdfh.ch/0666/1rK4ZevpT5eIxj48kgncsQ> :attachedToProject <http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> .
115115

116-
<http://rdfh.ch/0666/NLe33EVtTKGozGJOqKT_2Q> :attachedToProject <http://rdfh.ch/projects/0666> .
116+
<http://rdfh.ch/0666/NLe33EVtTKGozGJOqKT_2Q> :attachedToProject <http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> .
117117

118-
<http://rdfh.ch/0666/wopH6GHOSpCyASdrsNqg_A> :attachedToProject <http://rdfh.ch/projects/0666> .
118+
<http://rdfh.ch/0666/wopH6GHOSpCyASdrsNqg_A> :attachedToProject <http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> .
119119

120-
<http://rdfh.ch/0666/xY8O4uSeQb-MDC4VtvQGdw> :attachedToProject <http://rdfh.ch/projects/0666> .
120+
<http://rdfh.ch/0666/xY8O4uSeQb-MDC4VtvQGdw> :attachedToProject <http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> .
121121

122-
<http://rdfh.ch/0666/yjOFfSKPR_uiw8KoJu5mQg> :attachedToProject <http://rdfh.ch/projects/0666> .
122+
<http://rdfh.ch/0666/yjOFfSKPR_uiw8KoJu5mQg> :attachedToProject <http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> .
123123

124-
<http://rdfh.ch/0666/tWxW7jM0S2uMYKifwF0mtQ> :attachedToProject <http://rdfh.ch/projects/0666> .
124+
<http://rdfh.ch/0666/tWxW7jM0S2uMYKifwF0mtQ> :attachedToProject <http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> .
125125

126126
<http://rdfh.ch/0666/tWf2vqMqQ_OcUMJSRj6e5w> :creationDate "2018-06-06T12:08:56.619Z"^^xsd:dateTime .
127127

‎test_data/e2e.v2.SearchRouteV2R2RSpec/gravsearchtest1-onto.ttl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
<http://www.knora.org/ontology/0666/gravsearchtest1> a owl:Ontology ;
1111
rdfs:label "Test ontology" ;
12-
knora-base:attachedToProject <http://rdfh.ch/projects/0666> ;
12+
knora-base:attachedToProject <http://rdfh.ch/projects/cXxbOh4xRce3uLUyXHujfg> ;
1313
knora-base:lastModificationDate "2012-12-12T12:12:12.12Z"^^xsd:dateTime .
1414

1515
gravsearchtest1:isInProjectValue rdf:type owl:ObjectProperty ;

0 commit comments

Comments
 (0)