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

Feat: Consent Module where a entity can ask for consent to access some fields of another entity #194

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ build: java/registry/target/registry.jar
rm -rf java/claim/target/*.jar
cd target && rm -rf * && jar xvf ../java/registry/target/registry.jar && cp ../java/Dockerfile ./ && docker build -t dockerhub/sunbird-rc-core .
make -C java/claim
make -C java/consent
make -C services/certificate-api docker
make -C services/certificate-signer docker
make -C services/notification-service docker
Expand Down
20 changes: 20 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ services:
- sunbird_sso_client_id=${KEYCLOAK_CLIENT_ID-registry-frontend}
- sunbird_sso_admin_client_secret=${KEYCLOAK_SECRET}
- claims_url=http://claim-ms:8082
- consent_url=http://consent-ms:8083
- sign_url=http://certificate-signer:8079/sign
- sign_health_check_url=http://certificate-signer:8079/health
- signature_enabled=true
Expand Down Expand Up @@ -132,6 +133,25 @@ services:
interval: 30s
timeout: 10s
retries: 4
consent-ms:
image: dockerhub/sunbird-rc-consent-ms:${RELEASE_VERSION}
environment:
- connectionInfo_uri=jdbc:postgresql://db:5432/registry
- connectionInfo_username=postgres
- connectionInfo_password=postgres
- sunbirdrc_url=http://registry:8081
ports:
- "8083:8083"
depends_on:
db:
condition: service_started
registry:
condition: service_started
healthcheck:
test: [ "CMD-SHELL", "wget -nv -t1 --spider http://localhost:8083/health || exit 1" ]
interval: 30s
timeout: 10s
retries: 4
certificate-signer:
image: dockerhub/sunbird-rc-certificate-signer:${RELEASE_VERSION}
environment:
Expand Down
10 changes: 10 additions & 0 deletions java/apitest/src/test/java/e2e/registry/ConsentRequest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"entityName": "Place",
"entityId": "1-eab84a8b-72f2-448e-af65-d2082bee589d",
"requestorName": "Random",
"consentFieldsPath": {
"name": "$.name"
},
"osOwner": ["c8211527-9d2f-4e08-8d8a-b57ef8be6eba","anonymous"],
"consentExpiryTime": "1000"
}
11 changes: 11 additions & 0 deletions java/apitest/src/test/java/e2e/registry/FailingConsentRequest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"entityName": "Place",
"entityId": "1-eab84a8b-72f2-448e-af65-d2082bee589d",
"requestorName": "Random",
"consentFieldsPath": {
"name": "$.name",
"country": ""
},
"osOwner": ["c8211527-9d2f-4e08-8d8a-b57ef8be6eba","anonymous"],
"consentExpiryTime": "1000"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"status": "GRANTED"
}
8 changes: 8 additions & 0 deletions java/apitest/src/test/java/e2e/registry/PlaceRequest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "Aurangabad",
"city": "Aurangabad",
"country": "India",
"email": "[email protected]",
"contact": "1234567890",
"addressRegion": "Marathwada"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "place",
"schema": "{\"$schema\": \"http://json-schema.org/draft-07/schema\", \"type\": \"object\", \"properties\": { \"Place\": { \"$ref\": \"#/definitions/Place\" } }, \"required\": [ \"Place\" ], \"title\": \"Place\", \"definitions\": { \"Place\": { \"$id\": \"#/properties/Place\", \"type\": \"object\", \"title\": \"The Place Schema\", \"required\": [ \"name\", \"city\", \"addressRegion\", \"country\" ], \"properties\": { \"name\": { \"type\": \"string\" }, \"city\": { \"type\": \"string\" }, \"addressLocality\": { \"type\": \"string\" }, \"addressRegion\": { \"type\": \"string\" }, \"country\": { \"type\": \"string\" }, \"postalCode\": { \"type\": \"string\" }, \"contact\": { \"type\": \"string\" }, \"email\": { \"type\": \"string\" } } } }, \"_osConfig\": { \"privateFields\": [ \"name\" ], \"signedFields\": [ \"country\" ], \"roles\": [ ], \"inviteRoles\": [ \"anonymous\"], \"ownershipAttributes\": [{\n \"email\": \"/email\",\n \"mobile\": \"/email\",\n \"userId\": \"/email\"\n }], \"attestationPolicies\": [ { \"name\": \"schemaAttestation\", \"conditions\": \"(ATTESTOR#$.[*]#.contains('board-cbse'))\", \"type\": \"AUTOMATED\", \"attestorPlugin\": \"did:internal:ClaimPluginActor?entity=board-cbse\", \"attestationProperties\": { \"country\": \"$.country\", \"contact\": \"$.contact\" } } ], \"credentialTemplate\": { \"@context\": [ \"https://www.w3.org/2018/credentials/v1\", \"https://gist.githubusercontent.com/varadeth/c781559f8d3954fda040d1be0fb2187d/raw/7e951447b3aaf670d407068274fe3ace814c55a4/gistfile1.json\" ], \"type\": [ \"VerifiableCredential\", \"AttestationCertificate\" ], \"issuer\": \"http://www.india.gov.in\", \"issuanceDate\": \"2022-08-08T12:00:00Z\", \"credentialSubject\": { \"type\": \"Place\", \"name\": \"{{name}}\", \"country\": \"{{country}}\" }, \"evidence\": { \"type\": \"Affiliation\", \"postalCode\": \"{{postalCode}}\", \"contact\": \"{{contact}}\" } } }}",
"status": "PUBLISHED"

}
111 changes: 109 additions & 2 deletions java/apitest/src/test/java/e2e/registry/registry.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Feature: Registry api tests
* def admin_token = ""
* def client_secret = 'a52c5f4a-89fd-40b9-aea2-3f711f14c889'
* def sleep = function(millis){ java.lang.Thread.sleep(millis) }
* def placeOsid = ""
* def placeOwner = ""

Scenario: health check
Given path 'health'
Expand Down Expand Up @@ -191,6 +193,112 @@ Feature: Registry api tests
When method get
Then status 404

Scenario: Create consent and verify its apis
# get admin token
* url authUrl
* path 'auth/realms/sunbird-rc/protocol/openid-connect/token'
* header Content-Type = 'application/x-www-form-urlencoded; charset=utf-8'
* header Host = 'keycloak:8080'
* form field grant_type = 'client_credentials'
* form field client_id = 'admin-api'
* form field client_secret = 'a52c5f4a-89fd-40b9-aea2-3f711f14c889'
* method post
Then status 200
And print response.access_token
* def admin_token = 'Bearer ' + response.access_token

# create place schema
Given url registryUrl
And path 'api/v1/Schema'
And header Authorization = admin_token
And request read('PlaceSchemaRequest.json')
When method post
Then status 200
And response.params.status == "SUCCESSFUL"

# create entity for place
Given url registryUrl
And path 'api/v1/Place'
And header Authorization = admin_token
* def placeRequest = read('PlaceRequest.json')
And request placeRequest
When method post
Then status 200
And def placeOsid = response.result.Place.osid

# fetch token for place entity's owners token
* url authUrl
* path 'auth/realms/sunbird-rc/protocol/openid-connect/token'
* header Content-Type = 'application/x-www-form-urlencoded; charset=utf-8'
* header Host = 'keycloak:8080'
* form field grant_type = 'password'
* form field client_id = 'registry-frontend'
* form field username = placeRequest.email
* form field password = 'abcd@123'
* method post
Then status 200
And print response.access_token
* def place_token = 'Bearer ' + response.access_token
* sleep(3000)

# get entity by id
Given url registryUrl
And path 'api/v1/Place/' + placeOsid
And header Authorization = place_token
When method get
Then status 200
And def placeOwner = response.osOwner

# create consent for entity Place
Given url registryUrl
And path 'api/v1/consent'
And header Authorization = admin_token
* def consentRequest = read('ConsentRequest.json')
* consentRequest.entityId = placeOsid
* consentRequest.osOwner = placeOwner
And request consentRequest
When method post
Then status 200
* sleep(3000)

# create consent for entity Place but without private fields
Given url registryUrl
And path 'api/v1/consent'
And header Authorization = admin_token
* def consentRequest = read('FailingConsentRequest.json')
* consentRequest.entityId = placeOsid
* consentRequest.osOwner = placeOwner
And request consentRequest
When method post
Then status 500
* sleep(3000)

# fetch consent by owner
Given url registryUrl
And path 'api/v1/consent/'
And header Authorization = place_token
When method get
Then status 200
And print response
And def consentId = response[0].id
And print consentId

# grant consent
Given url registryUrl
And path 'api/v1/consent/' + consentId
And header Authorization = place_token
* def grantConsentRequest = read('GrantConsentRequest.json')
And request grantConsentRequest
When method put
Then status 200
* sleep(3000)

# fetch consent by id
Given url registryUrl
And path 'api/v1/consent/' + consentId
And header Authorization = admin_token
When method get
Then status 200
@env=async
Scenario: Create a teacher schema and create teacher entity asynchronously
# get admin token
Expand Down Expand Up @@ -323,5 +431,4 @@ Feature: Registry api tests
And header Authorization = institute_token
When method get
Then status 200
And response[0].osid.length > 0

And response[0].osid.length > 0
4 changes: 4 additions & 0 deletions java/consent/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
9 changes: 9 additions & 0 deletions java/consent/HELP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Getting Started

### Reference Documentation
For further reference, please consider the following sections:

* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.4.5/maven-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.4.5/maven-plugin/reference/html/#build-image)

9 changes: 9 additions & 0 deletions java/consent/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
SOURCES := $(call rwildcard,java/,*.java)
build: target/consent-0.0.1-SNAPSHOT.jar
echo ${SOURCES}
cd target && docker build -t dockerhub/sunbird-rc-consent-ms ..

target/claim-0.0.1-SNAPSHOT.jar: $(SOURCES)
echo $(SOURCES)
../mvnw -DskipTests clean install
95 changes: 95 additions & 0 deletions java/consent/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>dev.sunbirdrc</groupId>
<artifactId>consent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consent</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>dev.sunbirdrc</groupId>
<artifactId>pojos</artifactId>
<version>2.0.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.12.0</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dev.sunbirdrc.consent;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConsentApplication {

public static void main(String[] args) {
SpringApplication.run(ConsentApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dev.sunbirdrc.consent.constants;

public enum ConstentStatus {
GRANTED, DENIED
}
Loading