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

Lock LDP #171

Merged
merged 6 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions deploy/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,13 @@ ds_writer.write({
Repo: {
crud: {
...H_CRUD_DEFAULT,
Update: {
implies: [
'ReadRepo',
'UpdateBranch', // PATCH for updating repo metadata
'UpdateLock', // PATCH for updating repo metadata
],
},
Delete: {
implies: [
'UpdateRepo',
Expand All @@ -446,13 +453,7 @@ ds_writer.write({
},

Lock: {
crud: {
Create: {},
Read: {},
Delete: {
implies: ['ReadLock'],
},
},
crud: H_CRUD_DEFAULT,
},

AccessControlAny: {
Expand Down Expand Up @@ -521,4 +522,4 @@ ds_writer.write({
}),
},
},
})
})
5 changes: 5 additions & 0 deletions src/main/kotlin/org/openmbee/flexo/mms/Conditions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ val LOCK_CRUD_CONDITIONS = REPO_CRUD_CONDITIONS.append {
}
}

val LOCK_UPDATE_CONDITIONS = LOCK_CRUD_CONDITIONS.append {
// require that the user has the ability to update locks on a lock-level scope
permit(Permission.UPDATE_LOCK, Scope.LOCK)
}

enum class ConditionType {
INSPECT,
REQUIRE,
Expand Down
4 changes: 4 additions & 0 deletions src/main/kotlin/org/openmbee/flexo/mms/Errors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,7 @@ open class Http500Excpetion(msg: String): HttpException(msg, HttpStatusCode.Inte

class ServerBugException(msg: String?=null): Http500Excpetion("Possible server implementation bug: ${msg?: "(no description)"}")


open class Http501Exception(msg: String): HttpException(msg, HttpStatusCode.NotImplemented)

class NotImplementedException(msg: String): Http501Exception("That action is not yet implemented. $msg")
14 changes: 14 additions & 0 deletions src/main/kotlin/org/openmbee/flexo/mms/General.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.openmbee.flexo.mms

import io.ktor.http.*
import io.ktor.server.response.*
import org.openmbee.flexo.mms.server.GenericResponse
import org.openmbee.flexo.mms.server.LdpDcLayer1Context

suspend fun LdpDcLayer1Context<GenericResponse>.notImplemented() {
call.respondText(
"That operation is not yet implemented",
ContentType.Text.Plain,
HttpStatusCode.NotImplemented
)
}
20 changes: 17 additions & 3 deletions src/main/kotlin/org/openmbee/flexo/mms/Namespaces.kt
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ fun prefixesFor(
)
}
}
else {
add("morl" to MMS_URNS.never)
}

if(null !== diffId) {
with("$this/diffs/$diffId") {
Expand All @@ -164,6 +167,9 @@ fun prefixesFor(
)
}
}
else {
add("morl" to MMS_URNS.never)
}

if(null != lockId) {
with("$this/locks/$lockId") {
Expand All @@ -172,6 +178,9 @@ fun prefixesFor(
)
}
}
else {
add("morl" to MMS_URNS.never)
}

if(null != commitId) {
with("$this/commits/$commitId") {
Expand All @@ -181,6 +190,9 @@ fun prefixesFor(
)
}
}
else {
add("morl" to MMS_URNS.never)
}
}
}
}
Expand All @@ -202,7 +214,7 @@ fun prefixesFor(
object MMS {
private val BASE = SPARQL_PREFIXES["mms"]!!
val uri = BASE

private fun res(id: String): Resource {
return ResourceFactory.createResource("${BASE}${id}")
}
Expand Down Expand Up @@ -234,7 +246,7 @@ object MMS {

// object properties
val id = ResourceFactory.createProperty(BASE, "id")

private fun prop(id: String): Property {
return ResourceFactory.createProperty(BASE, id)
}
Expand Down Expand Up @@ -343,6 +355,8 @@ object MMS_OBJECT {
object MMS_URNS {
private val mms = "urn:mms"

val never = "$mms:never"

object SUBJECT {
val aggregator = "$mms:aggregator"
val auth = "$mms:auth"
Expand All @@ -354,4 +368,4 @@ object MMS_URNS {
val pass = "$mms:pass"
val policy = "$mms:policy"
}
}
}
14 changes: 13 additions & 1 deletion src/main/kotlin/org/openmbee/flexo/mms/routes/Branches.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.openmbee.flexo.mms.routes
import io.ktor.server.routing.*
import org.openmbee.flexo.mms.BRANCH_UPDATE_CONDITIONS
import org.openmbee.flexo.mms.guardedPatch
import org.openmbee.flexo.mms.notImplemented
import org.openmbee.flexo.mms.routes.ldp.createBranch
import org.openmbee.flexo.mms.routes.ldp.getBranches
import org.openmbee.flexo.mms.routes.ldp.headBranches
Expand Down Expand Up @@ -44,6 +45,9 @@ fun Route.crudBranches() {
// create new branch
createBranch(usedPost=true)
}

// method not allowed
otherwiseNotAllowed()
}

// specific branch
Expand Down Expand Up @@ -80,5 +84,13 @@ fun Route.crudBranches() {
preconditions = BRANCH_UPDATE_CONDITIONS,
)
}

// delete not yet implemented
delete {
notImplemented()
}

// method not allowed
otherwiseNotAllowed()
}
}
}
48 changes: 47 additions & 1 deletion src/main/kotlin/org/openmbee/flexo/mms/routes/Locks.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package org.openmbee.flexo.mms.routes

import io.ktor.server.routing.*
import org.openmbee.flexo.mms.LOCK_UPDATE_CONDITIONS
import org.openmbee.flexo.mms.NotImplementedException
import org.openmbee.flexo.mms.guardedPatch
import org.openmbee.flexo.mms.reindent
import org.openmbee.flexo.mms.routes.ldp.createOrReplaceLock
import org.openmbee.flexo.mms.routes.ldp.deleteLock
import org.openmbee.flexo.mms.routes.ldp.getLocks
Expand All @@ -22,6 +26,16 @@ fun Route.crudLocks() {
}
}

// state of a lock
head {
headLocks(true)
}

// get all locks
get {
getLocks(true)
}

// create new lock
post { slug ->
// set policy id on context
Expand All @@ -30,6 +44,9 @@ fun Route.crudLocks() {
// create new lock
createOrReplaceLock()
}

// method not allowed
otherwiseNotAllowed("locks")
}

// specific lock
Expand Down Expand Up @@ -57,9 +74,38 @@ fun Route.crudLocks() {
createOrReplaceLock()
}

// update lock metadata
patch {
// build conditions
val localConditions = LOCK_UPDATE_CONDITIONS.append {
// enforce preconditions if present
appendPreconditions { values ->
"""
graph mor-graph:Metadata {
morl: mms:etag ?__mms_etag .

${values.reindent(6)}
}
"""
}
}

// handle all varieties of accepted PATCH request formats
guardedPatch(
updateRequest = it,
objectKey = "morl",
graph = "mor-graph:Metadata",
preconditions = localConditions,
)
}

// delete a lock
delete {
deleteLock()
// deleteLock()
throw NotImplementedException("DELETE Lock")
}

// method not allowed
otherwiseNotAllowed("lock")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.apache.jena.vocabulary.RDF
import org.openmbee.flexo.mms.*
import org.openmbee.flexo.mms.server.LdpDcLayer1Context
import org.openmbee.flexo.mms.server.LdpMutateResponse
import org.openmbee.flexo.mms.server.LdpPatchResponse


// require that the given lock does not exist (before attempting to create it)
Expand Down Expand Up @@ -180,7 +181,7 @@ suspend fun <TResponseContext: LdpMutateResponse> LdpDcLayer1Context<TResponseCo

// resource is being replaced
if(replaceExisting) {
// require that the user has the ability to create locks on a repo-level scope
// require that the user has the ability to update locks on a repo-level scope
permit(Permission.UPDATE_LOCK, Scope.REPO)
}
// resource is being created
Expand Down
35 changes: 33 additions & 2 deletions src/test/kotlin/org/openmbee/flexo/mms/BranchUpdate.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.openmbee.flexo.mms


import io.ktor.http.*
import org.apache.jena.sparql.vocabulary.FOAF
import org.apache.jena.vocabulary.DCTerms
import org.apache.jena.vocabulary.RDF
Expand All @@ -13,14 +14,18 @@ class BranchUpdate : RefAny() {

withTest {
httpPatch(demoBranchPath) {
setSparqlUpdateBody(withAllTestPrefixes("""
setSparqlUpdateBody(
withAllTestPrefixes(
"""
insert {
<> foaf:homepage <https://www.openmbee.org/> .
}
where {
<> dct:title "$demoBranchName"@en .
}
""".trimIndent()))
""".trimIndent()
)
)
}.apply {
response includesTriples {
subject(localIri(demoBranchPath)) {
Expand All @@ -35,5 +40,31 @@ class BranchUpdate : RefAny() {
}
}
}

"all branches rejects other methods" {
createBranch(demoRepoPath, "master", demoBranchId, demoBranchName)

withTest {
onlyAllowsMethods("$demoRepoPath/branches", setOf(
HttpMethod.Head,
HttpMethod.Get,
HttpMethod.Post,
))
}
}

"branch rejects other methods" {
createBranch(demoRepoPath, "master", demoBranchId, demoBranchName)

withTest {
onlyAllowsMethods(demoBranchPath, setOf(
HttpMethod.Head,
HttpMethod.Get,
HttpMethod.Put,
HttpMethod.Patch,
HttpMethod.Delete,
))
}
}
}
}
14 changes: 8 additions & 6 deletions src/test/kotlin/org/openmbee/flexo/mms/LockAny.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@ import io.kotest.matchers.string.shouldNotBeBlank
import io.ktor.http.*
import io.ktor.server.testing.*
import org.apache.jena.vocabulary.RDF
import org.openmbee.flexo.mms.util.TriplesAsserter
import org.openmbee.flexo.mms.util.exactly
import org.openmbee.flexo.mms.util.iri
import org.openmbee.flexo.mms.util.startsWith
import org.openmbee.flexo.mms.util.*
import org.slf4j.LoggerFactory

// validates response triples for a lock
fun TriplesAsserter.validateLockTriples(lockId: String, etag: String) {
fun TriplesAsserter.validateLockTriples(
lockId: String,
etag: String?=null,
extraPatterns: List<PairPattern> = listOf()
) {
// lock triples
subjectTerse("mor-lock:$lockId") {
exclusivelyHas(
RDF.type exactly MMS.Lock,
MMS.id exactly lockId,
MMS.etag exactly etag,
if(etag != null) MMS.etag exactly etag else MMS.etag startsWith "",
MMS.commit startsWith model.expandPrefix("mor-commit:").iri,
MMS.snapshot startsWith model.expandPrefix("mor-snapshot:Model.").iri,
MMS.createdBy exactly model.expandPrefix("mu:").iri,
*extraPatterns.toTypedArray(),
)
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/test/kotlin/org/openmbee/flexo/mms/LockLdpDc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class LockLdpDc : LockAny() {
// // validate
// validateCreatedLockTriples(demoLockId, etag, demoOrgPath)
// }

patch()
}
}
}
}
Loading