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

Send notifications when entity created, updated or invited #222

Merged
merged 16 commits into from
Jun 29, 2023
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
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ test: build
@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"
make -C services/certificate-signer test
make -C services/public-key-service test
make -C services/context-proxy-service test
Expand Down
11 changes: 10 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ services:
- redis_host=redis
- redis_port=6379
- manager_type=${MANAGER_TYPE-DefinitionsManager}
- notification_async_enabled=${NOTIFICATION_ASYNC_ENABLED-false}
- notification_enabled=${NOTIFICATION_ENABLED-false}
- notification_url=${NOTIFICATION_URL-http://notification-ms:8765/notification-service/v1/notification}
ports:
- "8081:8081"
depends_on:
Expand Down Expand Up @@ -188,6 +191,12 @@ services:
interval: 30s
timeout: 10s
retries: 10
environment:
- TRACK_NOTIFICATIONS=${TRACK_NOTIFICATIONS-false}
- KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS-kafka:9092}
depends_on:
kafka:
condition: service_started
zookeeper:
image: confluentinc/cp-zookeeper:latest
ports:
Expand All @@ -211,7 +220,7 @@ services:
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1"
healthcheck:
test:
[ "CMD", "kafka-topics", "--list", "--zookeeper", "zookeeper:2181" ]
[ "CMD", "kafka-topics", "--list", "--bootstrap-server", "localhost:9092" ]
interval: 30s
timeout: 10s
retries: 10
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "BirthCertificate39",
"schema": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema\",\n \"type\": \"object\",\n \"properties\": {\n \"BirthCertificate\": {\n \"$ref\": \"#/definitions/BirthCertificate\"\n }\n },\n \"required\": [\n \"BirthCertificate\"\n ],\n \"title\": \"BirthCertificate\",\n \"definitions\": {\n \"BirthCertificate\": {\n \"$id\": \"#/properties/BirthCertificate\",\n \"type\": \"object\",\n \"title\": \"The BirthCertificate Schema\",\n \"required\": [\n \"name\",\n \"gender\",\n \"date_of_birth\",\n \"place_of_birth\",\n \"contact\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"gender\": {\n \"type\": \"string\"\n },\n \"date_of_birth\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"hospital\": {\n \"type\": \"string\"\n },\n \"place_of_birth\": {\n \"type\": \"string\",\n \"enum\": [\"Bangalore\", \"Mysore\", \"Mandya\"]\n },\n \"name_of_mother\": {\n \"type\": \"string\"\n },\n \"name_of_father\": {\n \"type\": \"string\"\n },\n \"present_address\": {\n \"type\": \"string\",\n \"minLength\": 10,\n \"maxLength\": 50\n },\n \"contact\": {\n \"type\": \"string\"\n }\n }\n }\n },\n \"_osConfig\": {\n \"uniqueIndexFields\": [\n \"contact\"\n ],\n \"ownershipAttributes\": [],\n \"roles\": [],\n \"inviteRoles\": [\n \"anonymous\"\n ],\n \"credentialTemplate\": {\n \"@context\": [\n \"https://www.w3.org/2018/credentials/v1\",\n {\n \"@context\": {\n \"@version\": 1.1,\n \"@protected\": true,\n \"BirthCertificate\": {\n \"@id\": \"https://github.com/sunbird-specs/vc-specs#BirthCertificate\",\n \"@context\": {\n \"id\": \"@id\",\n \"@version\": 1.1,\n \"@protected\": true,\n \"skills\": \"schema:Text\",\n \"name\": \"schema:Text\",\n \"gender\": \"schema:Text\",\n \"date_of_birth\": \"schema:Text\",\n \"hospital\": \"schema:Text\",\n \"place_of_birth\": \"schema:Text\",\n \"name_of_mother\": \"schema:Text\",\n \"name_of_father\": \"schema:Text\",\n \"present_address\": \"schema:Text\",\n \"contact\": \"schema:Text\"\n }\n }\n }\n }\n ],\n \"type\": [\n \"VerifiableCredential\"\n ],\n \"issuanceDate\": \"2021-08-27T10:57:57.237Z\",\n \"credentialSubject\": {\n \"type\": \"BirthCertificate\",\n \"name\": \"{{name}}\",\n \"gender\": \"{{gender}}\",\n \"date_of_birth\": \"{{date_of_birth}}\",\n \"hospital\": \"{{hospital}}\",\n \"place_of_birth\": \"{{place_of_birth}}\",\n \"name_of_mother\": \"{{name_of_mother}}\",\n \"name_of_father\": \"{{name_of_father}}\",\n \"present_address\": \"{{present_address}}\",\n \"contact\": \"{{contact}}\"\n },\n \"issuer\": \"did:web:sunbirdrc.dev/vc/BirthCertificate\"\n },\n \"certificateTemplates\": {\n \"html\": \"https://gist.githubusercontent.com/tejash-jl/56b97ffcb99f93e2e1ec49e88c0c2c7f/raw/1242b9af7f58b9d5ca1e4f11d442aa4815598a31/BirthCertificate.html\"\n }\n }\n}",
"name": "BirthCertificate139",
"schema": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema\",\n \"type\": \"object\",\n \"properties\": {\n \"BirthCertificate1\": {\n \"$ref\": \"#/definitions/BirthCertificate1\"\n }\n },\n \"required\": [\n \"BirthCertificate1\"\n ],\n \"title\": \"BirthCertificate1\",\n \"definitions\": {\n \"BirthCertificate1\": {\n \"$id\": \"#/properties/BirthCertificate1\",\n \"type\": \"object\",\n \"title\": \"The BirthCertificate1 Schema\",\n \"required\": [\n \"name\",\n \"gender\",\n \"date_of_birth\",\n \"place_of_birth\",\n \"contact\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"gender\": {\n \"type\": \"string\"\n },\n \"date_of_birth\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"hospital\": {\n \"type\": \"string\"\n },\n \"place_of_birth\": {\n \"type\": \"string\",\n \"enum\": [\"Bangalore\", \"Mysore\", \"Mandya\"]\n },\n \"name_of_mother\": {\n \"type\": \"string\"\n },\n \"name_of_father\": {\n \"type\": \"string\"\n },\n \"present_address\": {\n \"type\": \"string\",\n \"minLength\": 10,\n \"maxLength\": 50\n },\n \"contact\": {\n \"type\": \"string\"\n }\n }\n }\n },\n \"_osConfig\": {\n \"uniqueIndexFields\": [\n \"contact\"\n ],\n \"ownershipAttributes\": [],\n \"roles\": [],\n \"inviteRoles\": [\n \"anonymous\"\n ],\n \"credentialTemplate\": {\n \"@context\": [\n \"https://www.w3.org/2018/credentials/v1\",\n {\n \"@context\": {\n \"@version\": 1.1,\n \"@protected\": true,\n \"BirthCertificate1\": {\n \"@id\": \"https://github.com/sunbird-specs/vc-specs#BirthCertificate1\",\n \"@context\": {\n \"id\": \"@id\",\n \"@version\": 1.1,\n \"@protected\": true,\n \"skills\": \"schema:Text\",\n \"name\": \"schema:Text\",\n \"gender\": \"schema:Text\",\n \"date_of_birth\": \"schema:Text\",\n \"hospital\": \"schema:Text\",\n \"place_of_birth\": \"schema:Text\",\n \"name_of_mother\": \"schema:Text\",\n \"name_of_father\": \"schema:Text\",\n \"present_address\": \"schema:Text\",\n \"contact\": \"schema:Text\"\n }\n }\n }\n }\n ],\n \"type\": [\n \"VerifiableCredential\"\n ],\n \"issuanceDate\": \"2021-08-27T10:57:57.237Z\",\n \"credentialSubject\": {\n \"type\": \"BirthCertificate1\",\n \"name\": \"{{name}}\",\n \"gender\": \"{{gender}}\",\n \"date_of_birth\": \"{{date_of_birth}}\",\n \"hospital\": \"{{hospital}}\",\n \"place_of_birth\": \"{{place_of_birth}}\",\n \"name_of_mother\": \"{{name_of_mother}}\",\n \"name_of_father\": \"{{name_of_father}}\",\n \"present_address\": \"{{present_address}}\",\n \"contact\": \"{{contact}}\"\n },\n \"issuer\": \"did:web:sunbirdrc.dev/vc/BirthCertificate1\"\n },\n \"certificateTemplates\": {\n \"html\": \"https://gist.githubusercontent.com/tejash-jl/56b97ffcb99f93e2e1ec49e88c0c2c7f/raw/1242b9af7f58b9d5ca1e4f11d442aa4815598a31/BirthCertificate1.html\"\n }\n }\n}",
"status": "PUBLISHED"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Student7",
"schema": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema\",\n \"type\": \"object\",\n \"properties\": {\n \"Student\": {\n \"$ref\": \"#/definitions/Student\"\n }\n },\n \"required\": [\n \"Student\"\n ],\n \"title\": \"Student\",\n \"definitions\": {\n \"Student\": {\n \"$id\": \"#/properties/Student\",\n \"type\": \"object\",\n \"title\": \"The Student Schema\",\n \"required\": [\n \"name\",\n \"gender\",\n \"contact\",\n \"email\"\n, \n \"favoriteSubject\" ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"gender\": {\n \"type\": \"string\"\n },\n \"contact\": {\n \"type\": \"string\"\n },\n \"email\": {\n \"type\": \"string\"\n }\n }\n }\n },\n \"_osConfig\": {\n\"privateFields\": [\"contact\"], \n\"internalFields\": [\"favoriteSubject\"],\n \"uniqueIndexFields\": [],\n \"ownershipAttributes\": [{\n \"email\": \"/email\",\n \"mobile\": \"/contact\",\n \"userId\": \"/contact\"\n }],\n \"roles\": [],\n \"inviteRoles\": [\n \"anonymous\"\n ]\n }\n}",
"schema": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema\",\n \"type\": \"object\",\n \"properties\": {\n \"Student\": {\n \"$ref\": \"#/definitions/Student\"\n }\n },\n \"required\": [\n \"Student\"\n ],\n \"title\": \"Student\",\n \"definitions\": {\n \"Student\": {\n \"$id\": \"#/properties/Student\",\n \"type\": \"object\",\n \"title\": \"The Student Schema\",\n \"required\": [\n \"name\",\n \"gender\",\n \"contact\",\n \"email\"\n,\n \"favoriteSubject\" ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"gender\": {\n \"type\": \"string\"\n },\n \"contact\": {\n \"type\": \"string\"\n },\n \"email\": {\n \"type\": \"string\"\n }\n }\n }\n },\n \"_osConfig\": {\n\"privateFields\": [\"contact\"],\n\"internalFields\": [\"favoriteSubject\"],\n \"uniqueIndexFields\": [],\n \"ownershipAttributes\": [{\n \"email\": \"/email\",\n \"mobile\": \"/contact\",\n \"userId\": \"/contact\"\n }],\n \"roles\": [],\n \"inviteRoles\": [\n \"anonymous\"\n ],\n \"notificationTemplates\": {\n \"invite\": [{\n \"subject\": \"Student\",\n \"body\": \"{\\\"sender\\\": \\\"AppName\\\",\\\"route\\\": \\\"4\\\",\\\"country\\\": \\\"91\\\",\\\"unicode\\\": 1,\\\"sms\\\": [{ \\\"message\\\": \\\"{{name}}, Your {{entityType}} credential has been created\\\", \\\"to\\\": [ \\\"{{contact}}\\\"]}]}\"\n }],\n \"create\": [{\n \"subject\": \"Student\",\n \"body\": \"{\\\"sender\\\": \\\"AppName\\\",\\\"route\\\": \\\"4\\\",\\\"country\\\": \\\"91\\\",\\\"unicode\\\": 1,\\\"sms\\\": [{ \\\"message\\\": \\\"{{name}}, Your {{entityType}} credential has been created\\\", \\\"to\\\": [ \\\"{{contact}}\\\"]}]}\"\n }]\n }\n }\n}",
"status": "PUBLISHED"
}
38 changes: 25 additions & 13 deletions java/apitest/src/test/java/e2e/registry/registry.feature
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Feature: Registry api tests
Background:
* string registryUrl = "http://localhost:8081"
* string metricsUrl = "http://localhost:8070"
* string notificationsUrl = "http://localhost:8765"
* string authUrl = "http://localhost:8080"
* url registryUrl
* def admin_token = ""
Expand Down Expand Up @@ -420,21 +421,21 @@ Scenario: Create birth certificate schema, issue credentials then revoke the cre
And response.params.status == "SUCCESSFUL"
# create entity for birth certificate
Given url registryUrl
And path 'api/v1/BirthCertificate'
And path 'api/v1/BirthCertificate1'
And request read('BirthCertificateRequest.json')
When method post
Then status 200
And def birthCertificateOsid = response.result.BirthCertificate.osid
And def birthCertificateOsid = response.result.BirthCertificate1.osid
# get entity by id
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid
And header Authorization = admin_token
When method get
Then status 200
And response._osSignedData.length > 0
# modify entity
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid
And header Authorization = admin_token
* def requestBody = read('BirthCertificateRequest.json')
* requestBody.name = "test"
Expand All @@ -444,15 +445,15 @@ Scenario: Create birth certificate schema, issue credentials then revoke the cre
And response.params.status == "SUCCESSFUL"
# get entity by id
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid
And header Authorization = admin_token
When method get
Then status 200
And response.name == "test"
And response._osSignedData.contains("test")
# get certificate for entity
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid
And header Authorization = admin_token
And header Accept = "text/html"
And header template-key = "html"
Expand All @@ -461,45 +462,45 @@ Scenario: Create birth certificate schema, issue credentials then revoke the cre
And response.length > 0
# get VC for entity
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid
And header Authorization = admin_token
And header Accept = "application/vc+ld+json"
When method get
Then status 200
And response.credentialSubject.name == "test"
# revoke entity by id
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid + '/revoke'
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid + '/revoke'
And header Authorization = admin_token
When method post
Then status 200
And response.params.status == "SUCCESSFUL"
# get entity by id and check whether signed data got removed and still we are able to fetch the data
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid
And header Authorization = admin_token
When method get
Then status 200
And response._osSignedData.length = 0
# Try to revoke the same entity again it should inform that the VC is already revoked
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid + '/revoke'
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid + '/revoke'
And header Authorization = admin_token
When method post
Then status 500
And response.params.status == "UNSUCCESSFUL"
And response.params.errmsg == "Credential is already revoked"
# Now try deleting the entity by id
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid
And header Authorization = admin_token
When method delete
Then status 200
And response.name == "test"
And response.params.status == "SUCCESSFUL"
# get entity by id and check for its status
Given url registryUrl
And path 'api/v1/BirthCertificate/' + birthCertificateOsid
And path 'api/v1/BirthCertificate1/' + birthCertificateOsid
And header Authorization = admin_token
When method get
Then status 404
Expand All @@ -518,4 +519,15 @@ Scenario: Create birth certificate schema, issue credentials then revoke the cre
And assert response.birthcertificate.READ == "5"
And assert response.birthcertificate.UPDATE == "1"
And assert response.birthcertificate.ADD == "1"
And assert response.birthcertificate.DELETE == "1"
And assert response.birthcertificate.DELETE == "1"

@env=notification
Scenario: Check if notifications are sent
Given url notificationsUrl
And path '/notification-service/v1/notification'
When method get
Then status 200
* def studentRequest = read('StudentRequest.json')
* def notificationStudent = studentRequest.contact
And print response[notificationStudent]
And assert response[notificationStudent] != null
6 changes: 5 additions & 1 deletion java/registry/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,11 @@
<artifactId>keycloak-spring-security-adapter</artifactId>
<version>14.0.0</version>
</dependency>

<dependency>
<groupId>com.github.jknack</groupId>
<artifactId>handlebars</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ public class Constants {
public static final String CLAIM_STATUS_SUBJECT_TEMPLATE = "CLAIM %s";
public static final String CLAIM_STATUS_BODY_TEMPLATE = "Your claim request has been %s";
public static final String INVITE = "INVITE";
public static final String CREATE = "CREATE";
public static final String UPDATE = "UPDATE";
public static final String DELETE = "DELETE";
public static final String REVOKE = "REVOKE";
public static final String CLAIM_GRANTED = "CLAIM_GRANTED";
public static final String CLAIM_REJECTED = "CLAIM_REJECTED";
public static final String USER_ANONYMOUS = "anonymous";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public ResponseEntity deleteAttestationPolicy(@PathVariable String entityName, @
if (attestationPolicyOptional.isPresent() && attestationPolicyOptional.get().getCreatedBy().equals(userId)) {
logger.info("Updating attestation policy status of id: {}", policyId);
AttestationPolicy attestationPolicy = attestationPolicyOptional.get();
registryHelper.deleteAttestationPolicy(attestationPolicy);
registryHelper.deleteAttestationPolicy(entityName, attestationPolicy);
response.setResult("deleted");
responseParams.setStatus(Response.Status.SUCCESSFUL);
return new ResponseEntity<>(response, HttpStatus.OK);
Expand Down
Loading