Skip to content

Commit 99bef6f

Browse files
authored
Elide 5.x Async Create Permission Fix (#1425)
* NCreate Permission Check on AsyncQuery * Create Permission Check on AsyncQuery * Updating test case * Cleanup
1 parent 1d8d944 commit 99bef6f

File tree

7 files changed

+73
-2
lines changed

7 files changed

+73
-2
lines changed

elide-async/src/main/java/com/yahoo/elide/async/models/AsyncQuery.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package com.yahoo.elide.async.models;
77

88
import com.yahoo.elide.annotation.ComputedAttribute;
9+
import com.yahoo.elide.annotation.CreatePermission;
910
import com.yahoo.elide.annotation.DeletePermission;
1011
import com.yahoo.elide.annotation.Exclude;
1112
import com.yahoo.elide.annotation.Include;
@@ -56,6 +57,7 @@ public class AsyncQuery extends AsyncBase implements PrincipalOwned {
5657
private String requestId; //Client provided
5758

5859
@UpdatePermission(expression = "Principal is Owner AND value is Cancelled")
60+
@CreatePermission(expression = "value is Queued")
5961
private QueryStatus status = QueryStatus.QUEUED;
6062

6163
@Embedded

elide-async/src/main/java/com/yahoo/elide/async/models/security/AsyncQueryOperationChecks.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,13 @@ public boolean ok(AsyncQuery object, RequestScope requestScope, Optional<ChangeS
4949
return changeSpec.get().getModified().toString().equals(QueryStatus.CANCELLED.name());
5050
}
5151
}
52+
53+
@SecurityCheck(AsyncQueryStatusQueuedValue.VALUE_IS_QUEUED)
54+
public static class AsyncQueryStatusQueuedValue extends OperationCheck<AsyncQuery> {
55+
public static final String VALUE_IS_QUEUED = "value is Queued";
56+
@Override
57+
public boolean ok(AsyncQuery object, RequestScope requestScope, Optional<ChangeSpec> changeSpec) {
58+
return changeSpec.get().getModified().toString().equals(QueryStatus.QUEUED.name());
59+
}
60+
}
5261
}

elide-core/src/main/java/com/yahoo/elide/core/PersistentResource.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public static <T> PersistentResource<T> createObject(
147147

148148
// Keep track of new resources for non-transferable resources
149149
requestScope.getNewPersistentResources().add(newResource);
150-
checkPermission(CreatePermission.class, newResource);
150+
checkUserPermission(CreatePermission.class, obj, requestScope);
151151

152152
newResource.auditClass(Audit.Action.CREATE, new ChangeSpec(newResource, null, null, newResource.getObject()));
153153

@@ -1737,6 +1737,11 @@ private static <A extends Annotation> ExpressionResult checkPermission(
17371737
return resource.requestScope.getPermissionExecutor().checkPermission(annotationClass, resource);
17381738
}
17391739

1740+
private static <A extends Annotation> ExpressionResult checkUserPermission(
1741+
Class<A> annotationClass, Object obj, RequestScope requestScope) {
1742+
return requestScope.getPermissionExecutor().checkUserPermissions(obj.getClass(), annotationClass);
1743+
}
1744+
17401745
private <A extends Annotation> ExpressionResult checkFieldAwarePermissions(Class<A> annotationClass) {
17411746
return requestScope.getPermissionExecutor().checkPermission(annotationClass, this);
17421747
}

elide-integration-tests/src/test/java/com/yahoo/elide/async/integration/tests/AsyncIT.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,51 @@ public void graphQLHappyPath2() throws InterruptedException {
434434
assertEquals(expectedResponse, responseGraphQL);
435435
}
436436

437+
/**
438+
* Test for QueryStatus Set to PROCESSING instead of Queued
439+
*/
440+
@Test
441+
public void graphQLTestCreateFailOnQueryStatus() {
442+
443+
AsyncDelayStoreTransaction.sleep = true;
444+
AsyncQuery queryObj = new AsyncQuery();
445+
queryObj.setId("edc4a871-dff2-4054-804e-d80075cf839e");
446+
queryObj.setAsyncAfterSeconds(0);
447+
queryObj.setQueryType("GRAPHQL_V1_0");
448+
queryObj.setStatus("PROCESSING");
449+
queryObj.setQuery("{\"query\":\"{ book { edges { node { id title } } } }\",\"variables\":null}");
450+
String graphQLRequest = document(
451+
mutation(
452+
selection(
453+
field(
454+
"asyncQuery",
455+
arguments(
456+
argument("op", "UPSERT"),
457+
argument("data", queryObj, UNQUOTED_VALUE)
458+
),
459+
selections(
460+
field("id"),
461+
field("query"),
462+
field("queryType"),
463+
field("status")
464+
)
465+
)
466+
)
467+
)
468+
).toQuery();
469+
470+
JsonNode graphQLJsonNode = toJsonNode(graphQLRequest, null);
471+
ValidatableResponse response = given()
472+
.contentType(MediaType.APPLICATION_JSON)
473+
.accept(MediaType.APPLICATION_JSON)
474+
.body(graphQLJsonNode)
475+
.post("/graphQL")
476+
.then()
477+
.statusCode(org.apache.http.HttpStatus.SC_OK);
478+
479+
assertEquals(true, response.extract().body().asString().contains("errors"));
480+
}
481+
437482
/**
438483
* Various tests for an unknown collection (group) that does not exist JSONAPI query as a Async Request.
439484
* @throws InterruptedException

elide-integration-tests/src/test/java/com/yahoo/elide/async/integration/tests/framework/AsyncIntegrationTestApplicationResourceConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ protected void configure() {
5959
Map<String, Class<? extends Check>> checkMappings = new HashMap<>(TestCheckMappings.MAPPINGS);
6060
checkMappings.put(AsyncQueryOperationChecks.AsyncQueryOwner.PRINCIPAL_IS_OWNER, AsyncQueryOperationChecks.AsyncQueryOwner.class);
6161
checkMappings.put(AsyncQueryOperationChecks.AsyncQueryStatusValue.VALUE_IS_CANCELLED, AsyncQueryOperationChecks.AsyncQueryStatusValue.class);
62+
checkMappings.put(AsyncQueryOperationChecks.AsyncQueryStatusQueuedValue.VALUE_IS_QUEUED, AsyncQueryOperationChecks.AsyncQueryStatusQueuedValue.class);
6263

6364
EntityDictionary dictionary = new EntityDictionary(checkMappings, injector::inject);
6465

elide-integration-tests/src/test/java/example/NoCommitEntity.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
import com.yahoo.elide.security.RequestScope;
1313
import com.yahoo.elide.security.checks.OperationCheck;
1414

15+
import lombok.Getter;
16+
import lombok.Setter;
17+
1518
import java.util.Optional;
1619

1720
import javax.persistence.Entity;
@@ -27,6 +30,9 @@
2730
@Entity
2831
@Table(name = "nocommit")
2932
public class NoCommitEntity extends BaseId {
33+
@Getter @Setter
34+
private String value;
35+
3036
static public class NoCommitCheck<T> extends OperationCheck<T> {
3137
@Override
3238
public boolean ok(T record, RequestScope requestScope, Optional<ChangeSpec> changeSpec) {

elide-integration-tests/src/test/resources/ResourceIT/testPatchExtNoCommit.req.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
"path":"/nocommit",
55
"value":{
66
"type":"nocommit",
7-
"id":"12345678-1234-1234-1234-123456789ab1"
7+
"id":"12345678-1234-1234-1234-123456789ab1",
8+
"attributes":{
9+
"value":"value"
10+
}
811
}
912
}
1013
]

0 commit comments

Comments
 (0)