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

use custom serializers for Entity and Schema #170

Merged
merged 1 commit into from
Jul 3, 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
6 changes: 6 additions & 0 deletions CedarJava/src/main/java/com/cedarpolicy/CedarJson.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@

package com.cedarpolicy;

import com.cedarpolicy.model.entity.Entity;
import com.cedarpolicy.model.schema.Schema;
import com.cedarpolicy.model.slice.Slice;
import com.cedarpolicy.serializer.EntitySerializer;
import com.cedarpolicy.serializer.SchemaSerializer;
import com.cedarpolicy.serializer.SliceSerializer;
import com.cedarpolicy.serializer.ValueDeserializer;
import com.cedarpolicy.serializer.ValueSerializer;
Expand Down Expand Up @@ -50,6 +54,8 @@ private static ObjectMapper createObjectMapper() {
final ObjectMapper mapper = new ObjectMapper();

final SimpleModule module = new SimpleModule();
module.addSerializer(Entity.class, new EntitySerializer());
module.addSerializer(Schema.class, new SchemaSerializer());
module.addSerializer(Slice.class, new SliceSerializer());
module.addSerializer(Value.class, new ValueSerializer());
module.addDeserializer(Value.class, new ValueDeserializer());
Expand Down
14 changes: 14 additions & 0 deletions CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ public Policy(
this.policyID = policyID;
}

/**
* Get the policy ID.
*/
public String getID() {
return policyID;
}

/**
* Get the policy source.
*/
public String getSource() {
return policySrc;
}

@Override
public String toString() {
return "// Policy ID: " + policyID + "\n" + policySrc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import java.util.stream.Collectors;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -67,6 +68,24 @@ public PolicySet(Set<Policy> policies, Set<Policy> templates, List<TemplateLink>
this.templateLinks = templateLinks;
}

/**
* Get the static policies in the policy set.
*
* @return A map from policy id to `Policy` object
*/
public Map<String, String> getStaticPolicies() {
return policies.stream().collect(Collectors.toMap(Policy::getID, Policy::getSource));
}

/**
* Get the templates in the policy set.
*
* @return A map from policy id to `Policy` object
*/
public Map<String, String> getTemplates() {
return templates.stream().collect(Collectors.toMap(Policy::getID, Policy::getSource));
}

/**
* Parse multiple policies and templates from a file into a PolicySet.
* @param filePath the path to the file containing the policies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@

import com.cedarpolicy.loader.LibraryLoader;
import com.cedarpolicy.model.exception.InternalException;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;

import java.util.Optional;
Expand All @@ -36,13 +34,12 @@ public final class Schema {
}

/** Is this schema in the JSON or human format */
@JsonIgnore
public final JsonOrHuman type;

/** This will be present if and only if `type` is `Json`. */
@JsonProperty("json")
private final Optional<JsonNode> schemaJson;
public final Optional<JsonNode> schemaJson;

/** This will be present if and only if `type` is `Human`. */
@JsonProperty("human")
public final Optional<String> schemaText;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.cedarpolicy.model.policy.Policy;
import com.cedarpolicy.model.policy.TemplateLink;
import com.cedarpolicy.value.Value;
import com.fasterxml.jackson.annotation.JsonProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

import java.util.*;
Expand All @@ -37,10 +36,8 @@ public class BasicSlice implements Slice {

private final Set<Entity> entities;

@JsonProperty("templatePolicies")
private final Map<String, String> templatePolicies;

@JsonProperty("templateInstantiations")
private final List<TemplateLink> templateLinks;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2022-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.cedarpolicy.serializer;

import com.cedarpolicy.model.entity.Entity;
import com.cedarpolicy.value.EntityUID;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.util.stream.Collectors;

/** Serialize an entity. */
public class EntitySerializer extends JsonSerializer<Entity> {

/** Serialize an entity. */
@Override
public void serialize(
Entity entity, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectField("uid", entity.getEUID().asJson());
jsonGenerator.writeObjectField("attrs", entity.attrs);
jsonGenerator.writeObjectField("parents",
entity.getParents().stream().map(EntityUID::asJson).collect(Collectors.toSet()));
jsonGenerator.writeEndObject();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,10 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.cedarpolicy.value.EntityUID;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/** Represent JSON format of Entity Unique Identifier. */
@JsonDeserialize
@JsonSerialize
public class JsonEUID {
/** euid (__entity is used as escape sequence in JSON). */
@JsonProperty("type")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2022-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.cedarpolicy.serializer;

import com.cedarpolicy.model.schema.Schema;
import com.cedarpolicy.model.schema.Schema.JsonOrHuman;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

/** Serialize a schema. */
public class SchemaSerializer extends JsonSerializer<Schema> {

/** Serialize a schema. */
@Override
public void serialize(
Schema schema, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
jsonGenerator.writeStartObject();
if (schema.type == JsonOrHuman.Json) {
jsonGenerator.writeObjectField("json", schema.schemaJson.get());
} else {
jsonGenerator.writeStringField("human", schema.schemaText.get());
}
jsonGenerator.writeEndObject();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,11 @@

package com.cedarpolicy.serializer;

import com.cedarpolicy.model.entity.Entity;
import com.cedarpolicy.model.slice.Slice;
import com.cedarpolicy.value.Value;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/** Serialize a slice. Only used internally by CedarJson */
public class SliceSerializer extends JsonSerializer<Slice> {
Expand All @@ -39,36 +32,10 @@ public void serialize(
throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectField("policies", slice.getPolicies());
jsonGenerator.writeObjectField(
"entities", convertEntitiesToJsonEntities(slice.getEntities()));
jsonGenerator.writeObjectField("entities", slice.getEntities());
jsonGenerator.writeObjectField("templates", slice.getTemplates());
jsonGenerator.writeObjectField(
"templateInstantiations", slice.getTemplateLinks());
jsonGenerator.writeEndObject();
}

private static class JsonEntity {
/** Entity uid for the entity. */
@SuppressFBWarnings public final JsonEUID uid;

/** Entity attributes, where the value string is a Cedar literal value. */
@SuppressFBWarnings public final Map<String, Value> attrs;

/** Set of direct parent entities of this entity. */
public final Set<JsonEUID> parents;

JsonEntity(Entity e) {
this.uid = e.getEUID().asJson();
this.attrs = e.attrs;
this.parents = e.getParents().stream().map(euid -> euid.asJson()).collect(Collectors.toSet());
}
}

Set<JsonEntity> convertEntitiesToJsonEntities(Set<Entity> entities) {
Set<JsonEntity> ret = new HashSet<JsonEntity>();
for (Entity entity : entities) {
ret.add(new JsonEntity(entity));
}
return ret;
}
}
10 changes: 5 additions & 5 deletions CedarJava/src/test/java/com/cedarpolicy/JSONTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public void testEntityUID() {
ObjectNode inner = JsonNodeFactory.instance.objectNode();
inner.put("id", "jakob");
inner.put("type", "silver");
n.put(ENTITY_ESCAPE_SEQ, inner);
n.replace(ENTITY_ESCAPE_SEQ, inner);
assertJSONEqual(n, uid);

String invalidNamespace = "Us,er::\"alice\"";
Expand All @@ -181,7 +181,7 @@ public void testEntityUID() {
inner = JsonNodeFactory.instance.objectNode();
inner.put("id", "ali\"ce");
inner.put("type", "User");
n.put(ENTITY_ESCAPE_SEQ, inner);
n.replace(ENTITY_ESCAPE_SEQ, inner);
assertJSONEqual(n, uid);

String weirdType = "a";
Expand All @@ -191,7 +191,7 @@ public void testEntityUID() {
inner = JsonNodeFactory.instance.objectNode();
inner.put("id", weirdId);
inner.put("type", weirdType);
n.put(ENTITY_ESCAPE_SEQ, inner);
n.replace(ENTITY_ESCAPE_SEQ, inner);
assertJSONEqual(n, uid);
}

Expand All @@ -200,7 +200,7 @@ private ObjectNode buildEuidObject(String type, String id) {
var inner = JsonNodeFactory.instance.objectNode();
inner.put("id", id);
inner.put("type", type);
n.put(ENTITY_ESCAPE_SEQ, inner);
n.replace(ENTITY_ESCAPE_SEQ, inner);
return n;
}

Expand All @@ -213,7 +213,7 @@ public void testLongEntityUID() {
ObjectNode inner = JsonNodeFactory.instance.objectNode();
inner.put("id", "donut");
inner.put("type", "long::john::silver");
n.put(ENTITY_ESCAPE_SEQ, inner);
n.replace(ENTITY_ESCAPE_SEQ, inner);
assertJSONEqual(n, uid);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import com.cedarpolicy.serializer.JsonEUID;
import com.cedarpolicy.value.Value;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

import java.io.FileInputStream;
Expand Down Expand Up @@ -91,7 +90,6 @@ private Path resolveIntegrationTestPath(String path) {
* populated by Jackson when the test files are deserialized.
*/
@SuppressWarnings("visibilitymodifier")
@JsonDeserialize
private static class JsonTest {
/**
* File name of the file containing policies. Path is relative to the integration tests
Expand Down Expand Up @@ -123,7 +121,6 @@ private static class JsonTest {

/** Directly corresponds to the structure of a request in the JSON formatted tests files. */
@SuppressWarnings("visibilitymodifier")
@JsonDeserialize
private static class JsonRequest {
/** Textual description of the request. */
public String description;
Expand Down Expand Up @@ -159,7 +156,6 @@ private static class JsonRequest {
* String, rather than String to Values.
*/
@SuppressWarnings("visibilitymodifier")
@JsonDeserialize
private static class JsonEntity {
/** Entity uid for the entity. */
@SuppressFBWarnings(
Expand Down