Skip to content

Commit

Permalink
Add unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
hu-ahmed committed Oct 28, 2024
1 parent 8cb9cbd commit 7588065
Show file tree
Hide file tree
Showing 12 changed files with 537 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,10 @@ private Map<PolicyId, Map<String, ResourcePermissions>> groupPermissionsByPolicy
return groupedByEntityId.values().stream()
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.groupingBy(
entry -> entry.getValue().getPolicyId(),
entry -> entry.getValue().policyId(),
Collectors.toMap(
Map.Entry::getKey,
entry -> createResourcePermissions(entry.getValue().getPermissionCheck())
entry -> createResourcePermissions(entry.getValue().permissionCheck())
)
));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,6 @@ public int hashCode() {

@Override
public String toString() {
return "CheckPermissionsCommand[" + super.toString() + ", permissionChecks=" + permissionChecks + "]";
return getClass().getSimpleName() + "[" + super.toString() + ", permissionChecks=" + permissionChecks + "]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@
*/
package org.eclipse.ditto.gateway.service.endpoints.routes.checkpermissions;

import java.util.List;
import java.util.Objects;

import javax.annotation.concurrent.Immutable;

import org.eclipse.ditto.base.model.json.Jsonifiable;
import org.eclipse.ditto.json.JsonArray;
import org.eclipse.ditto.json.JsonFactory;
import org.eclipse.ditto.json.JsonFieldDefinition;
import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.json.JsonValue;
import org.eclipse.ditto.json.JsonFactory;
import org.eclipse.ditto.policies.model.PoliciesResourceType;
import org.eclipse.ditto.policies.model.ResourceKey;

import javax.annotation.concurrent.Immutable;

import java.util.List;

/**
* Immutable model representing a permission check for a resource and entity.
* <p>
Expand All @@ -39,22 +40,24 @@
@Immutable
public final class ImmutablePermissionCheck implements Jsonifiable<JsonObject> {

private final ResourceKey resourceKey;
private final ResourceKey resource;
private final String entityId;
private final boolean isPolicyResource;
private final List<String> hasPermissions;

private static final JsonFieldDefinition<String> RESOURCE_KEY_FIELD = JsonFactory.newStringFieldDefinition("resource");
private static final JsonFieldDefinition<String> RESOURCE_KEY_FIELD =
JsonFactory.newStringFieldDefinition("resource");
private static final JsonFieldDefinition<String> ENTITY_ID_FIELD = JsonFactory.newStringFieldDefinition("entityId");
private static final JsonFieldDefinition<JsonArray> PERMISSIONS_FIELD = JsonFactory.newJsonArrayFieldDefinition("hasPermissions");
private static final JsonFieldDefinition<JsonArray> PERMISSIONS_FIELD =
JsonFactory.newJsonArrayFieldDefinition("hasPermissions");


private ImmutablePermissionCheck(final ResourceKey resourceKey, final String entityId,
private ImmutablePermissionCheck(final ResourceKey resource, final String entityId,
final List<String> hasPermissions) {

this.resourceKey = resourceKey;
this.resource = resource;
this.entityId = entityId;
this.isPolicyResource = PoliciesResourceType.POLICY.equals(resourceKey.getResourceType());
this.isPolicyResource = PoliciesResourceType.POLICY.equals(resource.getResourceType());
this.hasPermissions = List.copyOf(hasPermissions);
}

Expand All @@ -75,10 +78,10 @@ public static ImmutablePermissionCheck of(final ResourceKey resourceKey, final S
/**
* Returns the resource for which permissions are being checked.
*
* @return the resourceKey ResourceKey.
* @return the resource ResourceKey.
*/
public ResourceKey getResourceKey() {
return resourceKey;
return resource;
}

/**
Expand Down Expand Up @@ -115,11 +118,13 @@ public List<String> getHasPermissions() {
*/
@Override
public JsonObject toJson() {
return JsonFactory.newObjectBuilder()
.set("resourceKey", resourceKey.toString())
return JsonObject.newBuilder()
.set("resource", resource.toString())
.set("entityId", entityId)
.set("isPolicyResource", isPolicyResource)
.set("hasPermissions", hasPermissions.toString())
.set("hasPermissions", JsonFactory.newArrayBuilder()
.addAll(hasPermissions.stream().map(JsonFactory::newValue).toList())
.build())
.build();
}

Expand All @@ -139,4 +144,31 @@ public static ImmutablePermissionCheck fromJson(final JsonObject jsonObject) {

return ImmutablePermissionCheck.of(resourceKey, entityId, permissions);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ImmutablePermissionCheck that = (ImmutablePermissionCheck) o;
return isPolicyResource == that.isPolicyResource &&
Objects.equals(resource, that.resource) &&
Objects.equals(entityId, that.entityId) &&
Objects.equals(hasPermissions, that.hasPermissions);
}


@Override
public int hashCode() {
return Objects.hash(resource, entityId, isPolicyResource, hasPermissions);
}

@Override
public String toString() {
return "ImmutablePermissionCheck{" +
"resourceKey=" + resource +
", entityId='" + entityId + '\'' +
", isPolicyResource=" + isPolicyResource +
", hasPermissions=" + hasPermissions +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,34 @@
import org.eclipse.ditto.policies.model.PolicyId;

/**
* Wrapper class for handling permission checks along with the associated {@link PolicyId}.
* Wrapper class for handling permission checks along with the associated {@link org.eclipse.ditto.policies.model.PolicyId}.
* <p>
* This class wraps an {@link ImmutablePermissionCheck} and provides an additional field to hold
* the {@link PolicyId} that is associated with the permission check. The {@link PermissionCheckWrapper}
* This class wraps an {@link org.eclipse.ditto.gateway.service.endpoints.routes.checkpermissions.ImmutablePermissionCheck} and provides an additional field to hold
* the {@link org.eclipse.ditto.policies.model.PolicyId} that is associated with the permission check. The {@link PermissionCheckWrapper}
* allows for flexible management of both the permission check and its related policy.
*
* @since 3.7.0
*/
public final class PermissionCheckWrapper {
private final ImmutablePermissionCheck permissionCheck;
private final PolicyId policyId;
public record PermissionCheckWrapper(ImmutablePermissionCheck permissionCheck, PolicyId policyId) {

/**
* Constructor to initialize the wrapper with a given {@link ImmutablePermissionCheck}.
*
* @param permissionCheck the permission check to wrap.
*/
public PermissionCheckWrapper(final ImmutablePermissionCheck permissionCheck, final PolicyId policyId) {
this.permissionCheck = permissionCheck;
this.policyId = policyId;
}

/**
* Retrieves the {@link ImmutablePermissionCheck} contained within this wrapper.
* Retrieves the {@link org.eclipse.ditto.gateway.service.endpoints.routes.checkpermissions.ImmutablePermissionCheck} contained within this wrapper.
*
* @return the wrapped permission check.
*/
public ImmutablePermissionCheck getPermissionCheck() {
@Override
public ImmutablePermissionCheck permissionCheck() {
return permissionCheck;
}


/**
* Retrieves the {@link PolicyId} associated with this permission check.
* Retrieves the {@link org.eclipse.ditto.policies.model.PolicyId} associated with this permission check.
*
* @return the associated policy ID, or {@code null} if not set.
*/
public PolicyId getPolicyId() {
@Override
public PolicyId policyId() {
return policyId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.ditto.gateway.service.endpoints.routes.checkpermissions;


import static org.eclipse.ditto.json.assertions.DittoJsonAssertions.assertThat;
import static org.junit.Assert.assertEquals;

import java.util.Map;

import org.eclipse.ditto.base.model.headers.DittoHeaders;
import org.eclipse.ditto.json.JsonFactory;
import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.base.model.common.HttpStatus;
import org.junit.Test;
import nl.jqno.equalsverifier.EqualsVerifier;

public final class CheckPermissionsResponseTest {

private static final DittoHeaders DITTO_HEADERS = DittoHeaders.newBuilder()
.correlationId("test-correlation-id")
.responseRequired(false)
.build();

private static final Map<String, Boolean> PERMISSION_RESULTS = Map.of("check1", true, "check2", false);
private static final JsonObject RESULTS_JSON = JsonObject.newBuilder().set("check1", true).set("check2", false).build();

private static final JsonObject KNOWN_JSON = JsonFactory.newObjectBuilder()
.set("type", CheckPermissionsResponse.TYPE)
.set("status", HttpStatus.OK.getCode())
.set("permissionResults", RESULTS_JSON)
.build();
private static CheckPermissionsResponse KNOWN_RESPONSE = CheckPermissionsResponse.of(PERMISSION_RESULTS, DITTO_HEADERS);
@Test
public void of() {
final CheckPermissionsResponse response = CheckPermissionsResponse.of(PERMISSION_RESULTS, DITTO_HEADERS);
assertEquals(DITTO_HEADERS, response.getDittoHeaders());
assertThat(response.getEntity()).isEqualTo(RESULTS_JSON);
}

@Test
public void toJsonReturnsExpected() {
final CheckPermissionsResponse response = CheckPermissionsResponse.of(PERMISSION_RESULTS, DITTO_HEADERS);
final JsonObject actualJson = response.toJson();
assertThat(actualJson).isEqualTo(KNOWN_JSON);
}

@Test
public void createInstanceFromValidJson() {
final CheckPermissionsResponse response = CheckPermissionsResponse.fromJson(KNOWN_RESPONSE.toJson(), DITTO_HEADERS);
assertEquals(DITTO_HEADERS, response.getDittoHeaders());
assertThat(response.getEntity()).isEqualTo(KNOWN_RESPONSE.getEntity().asObject());
}

@Test
public void testEqualsAndHashcode() {
EqualsVerifier.forClass(CheckPermissionsResponse.class)
.withRedefinedSuperclass()
.verify();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.ditto.gateway.service.endpoints.routes.checkpermissions;

import org.apache.pekko.http.javadsl.model.ContentTypes;
import org.apache.pekko.http.javadsl.model.HttpEntities;
import org.apache.pekko.http.javadsl.model.HttpRequest;
import org.apache.pekko.http.javadsl.model.StatusCodes;
import org.apache.pekko.http.javadsl.server.Route;
import org.apache.pekko.http.javadsl.testkit.TestRoute;
import org.eclipse.ditto.gateway.service.endpoints.EndpointTestBase;
import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.policies.model.ResourceKey;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

import static org.eclipse.ditto.json.assertions.DittoJsonAssertions.assertThat;

public final class CheckPermissionsRouteTest extends EndpointTestBase {

private CheckPermissionsRoute checkPermissionsRoute;
private TestRoute routeUnderTest;

@Before
public void setUp() {
checkPermissionsRoute = new CheckPermissionsRoute(routeBaseProperties);
final Route route = extractRequestContext(ctx -> checkPermissionsRoute.buildCheckPermissionsRoute(ctx, dittoHeaders));
routeUnderTest = testRoute(handleExceptions(() -> route));
}

@Test
public void postCheckPermissionsForwardCommand() {
final var permissionResource =
ImmutablePermissionCheck.of(ResourceKey.newInstance("policy:/"),
"org.eclipse.ditto:some-policy-1",
List.of("WRITE"));
final var jsonPayload = JsonObject.newBuilder().set("check1", permissionResource.toJson()).build();
final var request = HttpRequest.POST("/checkPermissions")
.withEntity(HttpEntities.create(ContentTypes.APPLICATION_JSON, jsonPayload.toString()));

final var result = routeUnderTest.run(request);
result.assertStatusCode(StatusCodes.OK);

assertThat(JsonObject.of(result.entityString()))
.isEqualTo(JsonObject.newBuilder().set("check1", false).build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.ditto.gateway.service.endpoints.routes.checkpermissions;

import static org.assertj.core.api.Assertions.assertThat;

import org.eclipse.ditto.base.model.headers.DittoHeaders;
import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.policies.model.ResourceKey;
import org.junit.Test;

import nl.jqno.equalsverifier.EqualsVerifier;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
* Unit tests for {@link CheckPermissions}.
*/
public final class CheckPermissionsTest {

@Test
public void fromJsonToJson() {
final DittoHeaders headers = DittoHeaders.newBuilder()
.correlationId("test-correlation-id")
.build();
var permissionResource =
ImmutablePermissionCheck.of(ResourceKey.newInstance("thing:/features/lamp/properties/on"),
"org.eclipse.ditto:some-thing-1",
List.of("WRITE"));
Map<String, ImmutablePermissionCheck> permissionChecks = new LinkedHashMap<>();
permissionChecks.put("check1", permissionResource);
final CheckPermissions command = CheckPermissions.of(permissionChecks, headers);

final CheckPermissions deserialized =
CheckPermissions.fromJson(JsonObject.newBuilder().set("check1", permissionResource.toJson()).build(),
headers);

assertThat(deserialized).isEqualTo(command);
}

@Test
public void testEqualsAndHashcode() {
EqualsVerifier.forClass(CheckPermissions.class)
.usingGetClass()
.verify();
}

@Test
public void testEmptyPermissionChecks() {
final DittoHeaders headers = DittoHeaders.newBuilder().build();
final Map<String, ImmutablePermissionCheck> emptyPermissionChecks = new LinkedHashMap<>();

final CheckPermissions command = CheckPermissions.of(emptyPermissionChecks, headers);

assertThat(command.getPermissionChecks()).isEmpty();
assertThat(command.getDittoHeaders()).isEqualTo(headers);
}

}
Loading

0 comments on commit 7588065

Please sign in to comment.