Skip to content

Commit e0e0ffa

Browse files
authored
ID-1270 create_with_parent Action (#1441)
* ID-1270 create_with_parent Action
1 parent aa1fe36 commit e0e0ffa

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

src/main/scala/org/broadinstitute/dsde/workbench/sam/api/SecurityDirectives.scala

+4-2
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@ trait SecurityDirectives {
7474
maybeParent match {
7575
case None => Directives.pass // no parent specified, proceed
7676
case Some(parent) =>
77-
// parents are allowed for a resource type if the owner role contains the SamResourceActions.setParent action
78-
val parentAllowed = resourceType.roles.find(_.roleName == resourceType.ownerRoleName).exists(_.actions.contains(SamResourceActions.setParent))
77+
// parents are allowed for a resource type if the owner role contains the SamResourceActions.setParent or SamResourceActions.createWithParent action
78+
val parentAllowed = resourceType.roles
79+
.find(_.roleName == resourceType.ownerRoleName)
80+
.exists(role => role.actions.contains(SamResourceActions.setParent) || role.actions.contains(SamResourceActions.createWithParent))
7981
if (!parentAllowed) {
8082
Directives.failWith(
8183
new WorkbenchExceptionWithErrorReport(

src/main/scala/org/broadinstitute/dsde/workbench/sam/model/SamModel.scala

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ object SamResourceActions {
3131
val testAnyActionAccess = ResourceAction("test_any_action_access")
3232
val getParent = ResourceAction("get_parent")
3333
val setParent = ResourceAction("set_parent")
34+
val createWithParent = ResourceAction("create_with_parent")
3435
val addChild = ResourceAction("add_child")
3536
val removeChild = ResourceAction("remove_child")
3637
val listChildren = ResourceAction("list_children")

src/test/scala/org/broadinstitute/dsde/workbench/sam/api/ResourceRoutesV2Spec.scala

+55
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,37 @@ class ResourceRoutesV2Spec extends RetryableAnyFlatSpec with Matchers with TestS
213213
}
214214
}
215215

216+
it should "204 create resource with content with parent with create_with_parent action" in {
217+
val resourceType = ResourceType(
218+
ResourceTypeName("rt"),
219+
Set(ResourceActionPattern(SamResourceActions.setParent.value, "", false)),
220+
Set(ResourceRole(ResourceRoleName("owner"), Set(SamResourceActions.createWithParent, SamResourceActions.addChild))),
221+
ResourceRoleName("owner")
222+
)
223+
val samRoutes = TestSamRoutes(Map(resourceType.name -> resourceType))
224+
225+
val createParentResourceRequest = CreateResourceRequest(
226+
ResourceId("parent"),
227+
Map(AccessPolicyName("goober") -> AccessPolicyMembershipRequest(Set(defaultUserInfo.email), Set.empty, Set(resourceType.ownerRoleName))),
228+
Set.empty,
229+
Some(false)
230+
)
231+
Post(s"/api/resources/v2/${resourceType.name}", createParentResourceRequest) ~> samRoutes.route ~> check {
232+
status shouldEqual StatusCodes.NoContent
233+
}
234+
235+
val createResourceRequest = CreateResourceRequest(
236+
ResourceId("foo"),
237+
Map(AccessPolicyName("goober") -> AccessPolicyMembershipRequest(Set(defaultUserInfo.email), Set.empty, Set(resourceType.ownerRoleName))),
238+
Set.empty,
239+
Some(false),
240+
Some(FullyQualifiedResourceId(resourceType.name, createParentResourceRequest.resourceId))
241+
)
242+
Post(s"/api/resources/v2/${resourceType.name}", createResourceRequest) ~> samRoutes.route ~> check {
243+
status shouldEqual StatusCodes.NoContent
244+
}
245+
}
246+
216247
it should "400 with parent when parents not allowed" in {
217248
val resourceType = ResourceType(
218249
ResourceTypeName("rt"),
@@ -2036,6 +2067,30 @@ class ResourceRoutesV2Spec extends RetryableAnyFlatSpec with Matchers with TestS
20362067
}
20372068
}
20382069

2070+
it should "403 if user only has create_with_parent on child resource" in {
2071+
val fullyQualifiedChildResource = FullyQualifiedResourceId(defaultResourceType.name, ResourceId("child"))
2072+
val newParentResource = FullyQualifiedResourceId(defaultResourceType.name, ResourceId("newParent"))
2073+
val currentParentResource = FullyQualifiedResourceId(defaultResourceType.name, ResourceId("currentParent"))
2074+
val samRoutes = createSamRoutes()
2075+
2076+
setupParentRoutes(
2077+
samRoutes,
2078+
fullyQualifiedChildResource,
2079+
currentParentOpt = Option(currentParentResource),
2080+
newParentOpt = Option(newParentResource),
2081+
actionsOnChild = Set(SamResourceActions.readPolicies, SamResourceActions.createWithParent),
2082+
actionsOnCurrentParent = Set(SamResourceActions.removeChild),
2083+
actionsOnNewParent = Set(SamResourceActions.addChild)
2084+
)
2085+
2086+
Put(
2087+
s"/api/resources/v2/${defaultResourceType.name}/${fullyQualifiedChildResource.resourceId.value}/parent",
2088+
newParentResource
2089+
) ~> samRoutes.route ~> check {
2090+
status shouldEqual StatusCodes.Forbidden
2091+
}
2092+
}
2093+
20392094
it should "403 if user is missing add_child on new parent resource" in {
20402095
val fullyQualifiedChildResource = FullyQualifiedResourceId(defaultResourceType.name, ResourceId("child"))
20412096
val newParentResource = FullyQualifiedResourceId(defaultResourceType.name, ResourceId("newParent"))

0 commit comments

Comments
 (0)