Skip to content

Commit

Permalink
Merge pull request #209 from tejash-jl/support_view_template_for_get_api
Browse files Browse the repository at this point in the history
added view template support for get apis
  • Loading branch information
tejash-jl authored Jun 30, 2023
2 parents 5b2864d + 27333e6 commit 3723bbe
Show file tree
Hide file tree
Showing 28 changed files with 525 additions and 164 deletions.
45 changes: 6 additions & 39 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,60 +28,27 @@ java/registry/target/registry.jar: $(SOURCES)
cd java && ./mvnw clean install

test: build
@echo "VIEW_DIR=java/apitest/src/test/resources/views" >> .env || echo "no permission to append to file"
@docker-compose down
@rm -rf db-data* || echo "no permission to delete"
# test with ES & standard definition manager
@RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-1 docker-compose up -d db es keycloak registry certificate-signer certificate-api
# test with distributed definition manager and native search
@SEARCH_PROVIDER_NAME=dev.sunbirdrc.registry.service.NativeSearchService RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 MANAGER_TYPE=DistributedDefinitionsManager DB_DIR=db-data-1 docker-compose up -d db keycloak registry certificate-signer certificate-api redis
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-1 || echo "no permission to delete"
# test with distributed definition manager
@RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 MANAGER_TYPE=DistributedDefinitionsManager DB_DIR=db-data-2 docker-compose up -d db es keycloak registry certificate-signer certificate-api redis
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-2 || echo "no permission to delete"
# test with native search service
@RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-3 SEARCH_PROVIDER_NAME=dev.sunbirdrc.registry.service.NativeSearchService docker-compose up -d db keycloak registry certificate-signer certificate-api
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-3 || echo "no permission to delete"
# test with kafka(async)
@ASYNC_ENABLED=true RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-4 docker-compose up -d db es keycloak registry certificate-signer certificate-api kafka zookeeper
# test with kafka(async), events, notifications,
@NOTIFICATION_ENABLED=true NOTIFICATION_URL=http://notification-ms:8765/notification-service/v1/notification TRACK_NOTIFICATIONS=true EVENT_ENABLED=true ASYNC_ENABLED=true RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-2 docker-compose up -d db es keycloak registry certificate-signer certificate-api kafka zookeeper notification-ms metrics
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && MODE=async ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-4 || echo "no permission to delete"
@RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources EVENT_ENABLED=true KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-5 SEARCH_PROVIDER_NAME=dev.sunbirdrc.registry.service.NativeSearchService docker-compose up -d db keycloak kafka zookeeper keycloak clickhouse registry certificate-signer certificate-api metrics redis
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && MODE=events ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-5 || echo "no permission to delete"
@NOTIFICATION_URL=http://notification-ms:8765/notification-service/v1/notification TRACK_NOTIFICATIONS=true KAFKA_BOOTSTRAP_SERVERS=kafka:9092 NOTIFICATION_ENABLED=true NOTIFICATION_ASYNC_ENABLED=false RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-6 docker-compose up -d db es keycloak registry certificate-signer certificate-api notification-ms kafka
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && MODE=notification ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-6 || echo "no permission to delete"
@rm -rf db-data-2 || echo "no permission to delete"
make -C services/certificate-signer test
make -C services/public-key-service test
make -C services/context-proxy-service test
Expand Down
7 changes: 4 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ services:
registry:
image: dockerhub/sunbird-rc-core:${RELEASE_VERSION}
volumes:
- ${PWD}/${SCHEMA_DIR-java/registry/src/main/resources/public/_schemas}:/home/sunbirdrc/config/public/_schemas
- ./${SCHEMA_DIR-java/registry/src/main/resources/public/_schemas}:/home/sunbirdrc/config/public/_schemas
- ./${VIEW_DIR-java/registry/src/main/resources/views}:/home/sunbirdrc/config/views/
environment:
- connectionInfo_uri=jdbc:postgresql://db:5432/registry
- connectionInfo_username=postgres
Expand Down Expand Up @@ -96,7 +97,7 @@ services:
keycloak:
image: dockerhub/sunbird-rc-keycloak:latest
volumes:
- ${PWD}/${KEYCLOAK_IMPORT_DIR-imports}:/opt/jboss/keycloak/imports
- ./${KEYCLOAK_IMPORT_DIR-imports}:/opt/jboss/keycloak/imports
environment:
- KEYCLOAK_LOGO=https://svgshare.com/i/hCs.svg
- DB_VENDOR=postgres
Expand Down Expand Up @@ -291,7 +292,7 @@ services:
digilocker-certificate-api:
image: dockerhub/sunbird-rc-digilocker-certificate-api
volumes:
- ${PWD}/services/digilocker-certificate-api/config/:/go/config/
- ./services/digilocker-certificate-api/config/:/go/config/
ports:
- "8087:8087"
environment:
Expand Down
14 changes: 11 additions & 3 deletions java/apitest/src/test/java/e2e/registry/registry.feature
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,14 @@ Feature: Registry api tests
When method get
Then status 200
And response.osid.length > 0
# get student info with view template
Given url registryUrl
And path 'api/v1/StudentWithPassword/' + studentOsid
And header Authorization = student_token
And header viewTemplateId = 'student_view_template.json'
When method get
Then status 200
* match response.contactDetails == { mobile: '#notpresent', email: '#present', osid: '#present' }

Scenario: Create birth certificate schema, issue credentials then revoke the credential and check for CRUD APIS
# get admin token
Expand Down Expand Up @@ -508,7 +516,7 @@ Scenario: Create birth certificate schema, issue credentials then revoke the cre
And response.params.errmsg == "entity status is inactive"


@env=events
@env=async
Scenario: Check if events are published
# should get metrics
* sleep(11000)
Expand All @@ -521,7 +529,7 @@ Scenario: Create birth certificate schema, issue credentials then revoke the cre
And assert response.birthcertificate.ADD == "1"
And assert response.birthcertificate.DELETE == "1"

@env=notification
@env=async
Scenario: Check if notifications are sent
Given url notificationsUrl
And path '/notification-service/v1/notification'
Expand All @@ -530,4 +538,4 @@ Scenario: Create birth certificate schema, issue credentials then revoke the cre
* def studentRequest = read('StudentRequest.json')
* def notificationStudent = studentRequest.contact
And print response[notificationStudent]
And assert response[notificationStudent] != null
And assert response[notificationStudent] != null
22 changes: 22 additions & 0 deletions java/apitest/src/test/resources/views/student_view_template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"id": "studentView",
"subject": "Student",
"fields": [
{
"name": "userDetails",
"title": "userDetails",
"display": true
},
{
"title": "contactDetails",
"function": "#/functionDefinitions/removePath($contactDetails, $.mobile)",
"$comment": "This is a virtual field not defined in the schema"
}
],
"functionDefinitions": [
{
"name": "removePath",
"provider": "dev.sunbirdrc.provider.RemovePathFunctionProvider"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ public class Constants {
public static final String FILE_URL = "fileUrl";

public static final String CREDENTIAL_TEMPLATE = "credentialTemplate";
public static final String VIEW_TEMPLATE_ID = "viewTemplateId";
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
import dev.sunbirdrc.registry.transform.Configuration;
import dev.sunbirdrc.registry.transform.Data;
import dev.sunbirdrc.registry.transform.ITransformer;
import dev.sunbirdrc.registry.util.ViewTemplateManager;
import dev.sunbirdrc.validators.ValidationException;
import org.agrona.Strings;
import org.apache.commons.lang3.StringUtils;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -62,6 +64,8 @@ public class RegistryEntityController extends AbstractController {
@Autowired
private AsyncRequest asyncRequest;

@Autowired
private ViewTemplateManager viewTemplateManager;


@Value("${authentication.enabled:true}") boolean securityEnabled;
Expand Down Expand Up @@ -434,7 +438,8 @@ private ArrayList<String> getConsentFields(HttpServletRequest request) {
{MediaType.APPLICATION_PDF_VALUE, MediaType.TEXT_HTML_VALUE, Constants.SVG_MEDIA_TYPE})
public ResponseEntity<Object> getEntityType(@PathVariable String entityName,
@PathVariable String entityId,
HttpServletRequest request) {
HttpServletRequest request,
@RequestHeader(required = false) String viewTemplateId) {
if (registryHelper.doesEntityOperationRequireAuthorization(entityName) && securityEnabled) {
try {
registryHelper.authorize(entityName, entityId, request);
Expand All @@ -448,7 +453,8 @@ public ResponseEntity<Object> getEntityType(@PathVariable String entityName,
}
try {
String readerUserId = getUserId(entityName, request);
JsonNode node = registryHelper.readEntity(readerUserId, entityName, entityId, false, null, false)
JsonNode node = registryHelper.readEntity(readerUserId, entityName, entityId, false,
viewTemplateManager.getViewTemplateById(viewTemplateId), false)
.get(entityName);
JsonNode signedNode = objectMapper.readTree(node.get(OSSystemFields._osSignedData.name()).asText());
return new ResponseEntity<>(certificateService.getCertificate(signedNode,
Expand Down Expand Up @@ -491,7 +497,8 @@ private String getTemplateUrlFromRequest(HttpServletRequest request, String enti
public ResponseEntity<Object> getEntity(
@PathVariable String entityName,
@PathVariable String entityId,
@RequestHeader HttpHeaders header, HttpServletRequest request) {
@RequestHeader HttpHeaders header, HttpServletRequest request,
@RequestHeader(required = false) String viewTemplateId) {
boolean requireLDResponse = false;
boolean requireVCResponse = false;
for (MediaType t: header.getAccept()) {
Expand All @@ -517,7 +524,7 @@ public ResponseEntity<Object> getEntity(
Response response = new Response(Response.API_ID.READ, "OK", responseParams);
try {
String readerUserId = getUserId(entityName, request);
JsonNode node = getEntityJsonNode(entityName, entityId, requireLDResponse, readerUserId);
JsonNode node = getEntityJsonNode(entityName, entityId, requireLDResponse, readerUserId, viewTemplateId);
if(requireLDResponse) {
addJsonLDSpec(node);
} else if (requireVCResponse) {
Expand Down Expand Up @@ -546,8 +553,10 @@ private void addJsonLDSpec(JsonNode node) {

}

private JsonNode getEntityJsonNode(@PathVariable String entityName, @PathVariable String entityId, boolean requireLDResponse, String userId) throws Exception {
JsonNode resultNode = registryHelper.readEntity(userId, entityName, entityId, false, null, false);
private JsonNode getEntityJsonNode(@PathVariable String entityName, @PathVariable String entityId,
boolean requireLDResponse, String userId, String viewTemplateId) throws Exception {
JsonNode resultNode = registryHelper.readEntity(userId, entityName, entityId, false,
viewTemplateManager.getViewTemplateById(viewTemplateId), false);
// Transformation based on the mediaType
Data<Object> data = new Data<>(resultNode);
Configuration config = configurationHelper.getResponseConfiguration(requireLDResponse);
Expand All @@ -564,16 +573,24 @@ private JsonNode getEntityJsonNode(@PathVariable String entityName, @PathVariabl
}

@RequestMapping(value = "/api/v1/{entityName}", method = RequestMethod.GET)
public ResponseEntity<Object> getEntityByToken(@PathVariable String entityName, HttpServletRequest request) {
public ResponseEntity<Object> getEntityByToken(@PathVariable String entityName, HttpServletRequest request,
@RequestHeader(required = false) String viewTemplateId) {
ResponseParams responseParams = new ResponseParams();
Response response = new Response(Response.API_ID.SEARCH, "OK", responseParams);
try {
JsonNode result = registryHelper.getRequestedUserDetails(request, entityName);
if (result.get(entityName).size() > 0) {
ArrayNode responseFromDb = registryHelper.fetchFromDBUsingEsResponse(entityName, (ArrayNode) result.get(entityName));
return new ResponseEntity<>(responseFromDb, HttpStatus.OK);
String userId = registryHelper.getUserId(request, entityName);
if (!Strings.isEmpty(userId)) {
JsonNode responseFromDb = registryHelper.searchEntitiesByUserId(entityName, userId, viewTemplateId);
JsonNode entities = responseFromDb.get(entityName);
if (entities.size() > 0) {
return new ResponseEntity<>(entities, HttpStatus.OK);
} else {
responseParams.setErrmsg("No record found");
responseParams.setStatus(Response.Status.UNSUCCESSFUL);
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
}
} else {
responseParams.setErrmsg("Entity not found");
responseParams.setErrmsg("User id is empty");
responseParams.setStatus(Response.Status.UNSUCCESSFUL);
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
}
Expand Down Expand Up @@ -761,7 +778,7 @@ public ResponseEntity<Object> revokeACredential (
try {
String tag = "RegistryController.revokeAnExistingCredential " + entityName;
watch.start(tag);
JsonNode existingEntityNode = getEntityJsonNode(entityName, entityId,false, userId);
JsonNode existingEntityNode = getEntityJsonNode(entityName, entityId,false, userId, null);
String signedData = existingEntityNode.get(OSSystemFields._osSignedData.name()).asText();
if (signedData.equals(new String()) || signedData.equals(null)) {
throw new RecordNotFoundException("Credential is already revoked");
Expand Down
Loading

0 comments on commit 3723bbe

Please sign in to comment.