From cc4d30587c4c4700b52bd6436d35c8f0bc35e15b Mon Sep 17 00:00:00 2001 From: Dileep Bapat Date: Fri, 13 Aug 2021 12:41:09 +0530 Subject: [PATCH] Adding the ndear schema cnofigurations (tested on demo instance) --- README.md | 16 ++ docker-compose.yml | 68 +++++++ schemas/BaseAttestationField.json | 20 +++ schemas/Common.json | 287 ++++++++++++++++++++++++++++++ schemas/Institute.json | 174 ++++++++++++++++++ schemas/Student.json | 88 +++++++++ schemas/Teacher.json | 97 ++++++++++ 7 files changed, 750 insertions(+) create mode 100644 docker-compose.yml create mode 100644 schemas/BaseAttestationField.json create mode 100644 schemas/Common.json create mode 100644 schemas/Institute.json create mode 100644 schemas/Student.json create mode 100644 schemas/Teacher.json diff --git a/README.md b/README.md index 63386ef..2edace2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,18 @@ # ndear-core-registries NDEAR Core Registries + +## Running +1. Clone the repository +2. Start docker compose, schema configuration from the repository are mounted on registry with this. + ``` + docker-compose up + ``` +3. Verify the api + ``` + curl -v localhost:8081/health + + .... + < HTTP/1.1 200 + ... + {"id":"open-saber.registry.health","ver":"1.0","ets":1628838471525,"params":{"resmsgid":"","msgid":"fe01f054-5c6e-4f16-887c-9f1b15cee937","err":"","status":"SUCCESSFUL","errmsg":""},"responseCode":"OK","result":{"name":"opensaber-registry-api","healthy":true,"checks":[{"name":"opensaber.database","healthy":true,"err":"","errmsg":""}]}} + ``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e15b286 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,68 @@ +version: "2.4" + +services: + redis: + image: redis + ports: + - "6379:6379" + es: + image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1 + environment: + - discovery.type=single-node + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + ports: + - "9200:9200" + - "9300:9300" + healthcheck: + test: ["CMD", "curl", "-f", "localhost:9200/_cluster/health"] + interval: 30s + timeout: 10s + retries: 4 + db: + image: postgres +# ports: +# - "5432:5432" + environment: + - POSTGRES_DB=registry + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + registry: + image: dockerhub/opensaber-rc + environment: + - connectionInfo_uri=jdbc:postgresql://db:5432/registry + - connectionInfo_username=postgres + - connectionInfo_password=postgres + - elastic_search_connection_url=es:9200 + - search_provider=io.opensaber.registry.service.ElasticSearchService + ports: + - "8081:8081" + volumes: + - ./schemas:/home/opensaber/config/public/_schemas + depends_on: + es: + condition: service_healthy + db: + condition: service_started + keycloak: + image: dockerhub/keycloak + environment: + - DB_VENDOR=postgres + - DB_ADDR=db + - DB_PORT=5432 + - DB_DATABASE=registry + - DB_USER=postgres + - DB_PASSWORD=postgres + - KEYCLOAK_USER=admin + - KEYCLOAK_PASSWORD=admin + healthcheck: + test: + ["CMD-SHELL", "curl -f http://localhost:9990/ || exit 1"] + interval: 30s + timeout: 10s + retries: 5 + ports: + - "8080:8080" + - "9990:9990" + depends_on: + db: + condition: service_started \ No newline at end of file diff --git a/schemas/BaseAttestationField.json b/schemas/BaseAttestationField.json new file mode 100644 index 0000000..f3182f7 --- /dev/null +++ b/schemas/BaseAttestationField.json @@ -0,0 +1,20 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "BaseAttestationField", + "definitions": { + "baseAttestationField": { + "title": "BaseAttestationField", + "type": "object", + "properties": { + "state": { + "type": "string", + "description": "field state (draft, submitted, attested, invalid)" + }, + "signature": { + "type": "string", + "description": "digital signature after attestion. Contains attested data, attestorInfo and verification details" + } + } + } + } +} diff --git a/schemas/Common.json b/schemas/Common.json new file mode 100644 index 0000000..eec2087 --- /dev/null +++ b/schemas/Common.json @@ -0,0 +1,287 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "Common", + "definitions": { + "IdentityDetails": { + "type": "object", + "title": "Identity Details", + "description": "Identity Details", + "required": [], + "properties": { + "fullName": { + "$id": "#/properties/fullName", + "type": "string", + "title": "Full name" + }, + "gender": { + "$id": "#/properties/gender", + "type": "string", + "enum": [ + "Male", + "Female", + "Other" + ], + "title": "Gender" + }, + "dob": { + "$id": "#/properties/dob", + "type": "string", + "format": "date", + "title": "DOB" + }, + "identityType": { + "$id": "#/properties/identityType", + "type": "string", + "$comment": "Nationality", + "title": "ID Type" + }, + "identityValue": { + "$id": "#/properties/identityValue", + "type": "string", + "$comment": "Nationality", + "title": "ID Value" + } + } + }, + "ContactDetails": { + "type": "object", + "title": "Contact Details", + "description": "Contact Details", + "required": [], + "properties": { + "email": { + "$id": "#/properties/email", + "type": "string", + "title": "Email" + }, + "mobile": { + "$id": "#/properties/mobile", + "type": "string", + "title": "Mobile" + }, + "address": { + "$id": "#/properties/address", + "$ref": "#/definitions/Address", + "title": "Address" + } + } + }, + "AcademicQualification": { + "type": "object", + "properties": { + "institute": { + "$id": "#/properties/institute", + "type": "string", + "title": "Institute Full Name" + }, + "qualification": { + "$id": "#/properties/qualification", + "type": "string", + "title": "Qualification" + }, + "program": { + "$id": "#/properties/program", + "type": "string", + "title": "Program of Study" + }, + "graduationYear": { + "$id": "#/properties/graduationYear", + "type": "string", + "title": "Year of Graduation" + }, + "marks": { + "$id": "#/properties/marks", + "type": "string", + "title": "Marks / Ranking / GPA, etc" + } + } + }, + "ExperienceType": { + "type": "object", + "properties": { + "institute": { + "$id": "#/properties/institute", + "type": "string", + "title": "Institute Full Name" + }, + "employmentType": { + "$id": "#/properties/employmentType", + "type": "string", + "title": "Employment Type", + "enum": [ + "Permanent", + "Contract" + ] + }, + "start": { + "$id": "#/properties/start", + "type": "string", + "format": "date", + "title": "Start Date" + }, + "end": { + "$id": "#/properties/end", + "type": "string", + "format": "date", + "title": "End Date" + }, + "teacherType": { + "$id": "#/properties/teacherType", + "type": "string", + "title": "Teacher Type", + "enum": [ + "Head teacher", + "Principal", + "VicePrincipal", + "Lecture" + ] + }, + "subjects": { + "$id": "#/properties/subjects", + "type": "array", + "title": "Subjects teaching at this Institute", + "items": { + "type": "string" + } + }, + "grades": { + "$id": "#/properties/grades", + "type": "array", + "title": "Grades Taught (per subject taught)", + "items": { + "type": "string", + "enum": [ + "Pre-Pri.", + "Class I", + "Class II", + "Class III", + "Class IV", + "Class V", + "Class VI", + "Class VII", + "Class VIII", + "Class IX", + "Class X", + "Class XI", + "Class XII" + ] + } + } + } + }, + "EducationType": { + "type": "object", + "properties": { + "institute": { + "$id": "#/properties/institute", + "type": "string", + "title": "Institute Name" + }, + "board": { + "$id": "#/properties/board", + "type": "string", + "title": "Board of Education" + }, + "medium": { + "$id": "#/properties/program", + "type": "string", + "title": "Medium of Education" + }, + "class": { + "$id": "#/properties/graduationYear", + "type": "string", + "enum": [ + "Pre-Pri.", + "Class I", + "Class II", + "Class III", + "Class IV", + "Class V", + "Class VI", + "Class VII", + "Class VIII", + "Class IX", + "Class X", + "Class XI", + "Class XII" + ], + "title": "Current Enrollment Class / Std." + } + } + }, + "GuardianDetails": { + "type": "object", + "properties": { + "fullName": { + "$id": "#/properties/fullName", + "type": "string", + "title": "Full Name" + }, + "relation": { + "$id": "#/properties/relation", + "type": "string", + "title": "Relation type" + }, + "email": { + "$ref": "#/definitions/ContactDetails/properties/email" + } + } + }, + "CertificationType": { + "type": "object", + "properties": { + "institute": { + "type": "string" + }, + "start": { + "type": "string", + "format": "date" + }, + "end": { + "type": "string", + "format": "date" + } + } + }, + "Address": { + "type": "object", + "required": [ + + ], + "properties": { + "plot": { + "type": "string", + "title": "Plot" + }, + "street": { + "type": "string", + "title": "Street" + }, + "landmark": { + "type": "string", + "title": "Landmark" + }, + "locality": { + "type": "string", + "title": "Locality" + }, + "state": { + "type": "string", + "title": "State" + }, + "district": { + "type": "string", + "title": "District" + }, + "village": { + "type": "string", + "title": "Village/Town/City" + }, + "pincode": { + "type": "string", + "title": "Pincode" + } + } + } + } +} \ No newline at end of file diff --git a/schemas/Institute.json b/schemas/Institute.json new file mode 100644 index 0000000..a85f349 --- /dev/null +++ b/schemas/Institute.json @@ -0,0 +1,174 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "Institute": { + "$ref": "#/definitions/Institute" + } + }, + "required": [ + "Institute" + ], + "title": "Institute", + "definitions": { + "Institute": { + "$id": "#/properties/Institute", + "type": "object", + "title": "The Institute Schema", + "required": [], + "properties": { + "instituteName": { + "$id": "#/properties/instituteName", + "type": "string", + "title": "Institute Name" + }, + "address": { + "$ref": "Common.json/#/definitions/Address", + "title": "Address" + }, + "establishmentYear": { + "$id": "#/properties/establishmentYear", + "type": "string", + "title": "Year of establishment of institute" + }, + "gstnId": { + "$id": "#/properties/gstnId", + "type": "string", + "title": "GSTN ID" + }, + "contactNumber": { + "$id": "#/properties/contactNumber", + "type": "string", + "title": "Landline / Mobile" + }, + "email": { + "$id": "#/properties/email", + "type": "string", + "format": "email", + "title": "Email" + }, + "website": { + "$id": "#/properties/website", + "type": "string", + "format": "uri", + "title": "Website" + }, + "category": { + "$id": "#/properties/category", + "type": "string", + "title": "Institute Category (Primary/Secondary etc)", + "enum": [ + "Primary", + "Secondary" + ] + }, + "schoolType": { + "$id": "#/properties/schoolType", + "type": "string", + "title": "School Type ", + "enum": [ + "Boys", + "Girls", + "Co-ed" + ] + }, + "instituteManagement": { + "$id": "#/properties/instituteManagement", + "type": "string", + "title": "Management of institute" + }, + "committee": { + "$id": "#/properties/instituteManagement", + "type": "string", + "title": "Name of Trust / Society / Managing Committee" + }, + "adminName": { + "$id": "#/properties/adminName", + "type": "string", + "title": "Principal / Dean / Head - Full Name" + }, + "adminEmail": { + "$id": "#/properties/adminEmail", + "type": "string", + "title": "Principal / Dean / Head - Email" + }, + "adminMobile": { + "$id": "#/properties/adminMobile", + "type": "string", + "title": "Principal / Dean / Head - Mobile" + }, + "affiliation": { + "type": "array", + "items": { + "$ref": "#/definitions/Affiliation" + }, + "title": "Affiliation" + } + } + }, + "Affiliation": { + "type": "object", + "properties": { + "medium": { + "type": "string", + "title": "Medium of Education" + }, + "board": { + "type": "string", + "title": "Affiliations Board" + }, + "affiliationNumber": { + "type": "string", + "title": "Affiliation Number" + }, + "grantYear": { + "type": "string", + "title": "Grant year" + }, + "expiryYear": { + "type": "string", + "title": "Expiry Year" + }, + "classes": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Classes / Grades" + } + } + } + }, + "_osConfig": { + "osComment": [ + "This section contains the OpenSABER specific configuration information", + "privateFields: Optional; list of field names to be encrypted and stored in database", + "signedFields: Optional; list of field names that must be pre-signed", + "indexFields: Optional; list of field names used for creating index. Enclose within braces to indicate it is a composite index. In this definition, (serialNum, schoolCode) is a composite index and schoolName is a single column index.", + "uniqueIndexFields: Optional; list of field names used for creating unique index. Field names must be different from index field name", + "systemFields: Optional; list of fields names used for system standard information like created, updated timestamps and userid" + ], + "privateFields": [], + "signedFields": [], + "indexFields": [], + "uniqueIndexFields": [], + "systemFields": [ + "osCreatedAt", + "osUpdatedAt", + "osCreatedBy", + "osUpdatedBy" + ], + "attestationPolicies": [ + { + "property": "affiliation/[]", + "paths": [ + "affiliation", + "instituteName" + ], + "attestorEntity": "board-cbse", + "conditions": "(ATTESTOR#$.[*]#.contains('board-cbse'))" + } + ], + "subjectJsonPath": "email" + } +} \ No newline at end of file diff --git a/schemas/Student.json b/schemas/Student.json new file mode 100644 index 0000000..ce89b37 --- /dev/null +++ b/schemas/Student.json @@ -0,0 +1,88 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "Student": { + "$ref": "#/definitions/Student" + } + }, + "required": [ + "Student" + ], + "title":"Student", + "definitions": { + "Student": { + "$id": "#/properties/Student", + "type": "object", + "title": "The Student Schema", + "required": [ + + ], + "properties": { + "identityDetails": { + "$ref": "Common.json/#/definitions/IdentityDetails" + }, + "contactDetails": { + "$ref": "Common.json/#/definitions/ContactDetails" + }, + "educationDetails": { + "type": "array", + "items": { + "$ref": "Common.json/#/definitions/EducationType" + }, + "title": "Education Details" + }, + "guardianDetails": { + "$ref": "Common.json/#/definitions/GuardianDetails", + "title": "Guardian Details" + } + } + } + }, + "_osConfig": { + "osComment": ["This section contains the OpenSABER specific configuration information", + "privateFields: Optional; list of field names to be encrypted and stored in database", + "signedFields: Optional; list of field names that must be pre-signed", + "indexFields: Optional; list of field names used for creating index. Enclose within braces to indicate it is a composite index. In this definition, (serialNum, studentCode) is a composite index and studentName is a single column index.", + "uniqueIndexFields: Optional; list of field names used for creating unique index. Field names must be different from index field name", + "systemFields: Optional; list of fields names used for system standard information like created, updated timestamps and userid"], + + "privateFields": [ + "$.identityDetails.dob", + "$.identityDetails.identityType", + "$.identityDetails.identityValue", + "$.contactDetails.email", + "$.contactDetails.mobile", + "$.contactDetails.address.plot", + "$.contactDetails.address.street", + "$.contactDetails.address.landmark", + "$.contactDetails.address.locality" + ], + "signedFields": [], + "indexFields": ["studentName"], + "uniqueIndexFields": ["identityValue"], + "systemFields": [ + "_osCreatedAt", + "_osUpdatedAt", + "_osCreatedBy", + "_osUpdatedBy", + "_osAttestedData", + "_osClaimId", + "_osState" + ], + "attestationAttributes": [ + "educationDetails", + "nationalIdentifier" + ], + "attestationPolicies": [ + { + "property": "educationDetails/[]", + "paths": ["$.educationDetails[?(@.osid == 'PROPERTY_ID')]['institute', 'program', 'graduationYear', 'marks']", "$.identityDetails['fullName']"], + "type": "MANUAL", + "attestorEntity": "Teacher", + "conditions": "(ATTESTOR#$.experience.[*].institute#.contains(REQUESTER#$.institute#) && ATTESTOR#$.experience[?(@.institute == REQUESTER#$.institute#)]['_osState']#.contains('PUBLISHED'))" + } + ], + "subjectJsonPath": "mobile" + } +} \ No newline at end of file diff --git a/schemas/Teacher.json b/schemas/Teacher.json new file mode 100644 index 0000000..cac0b8e --- /dev/null +++ b/schemas/Teacher.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "Teacher": { + "$ref": "#/definitions/Teacher" + } + }, + "required": [ + "Teacher" + ], + "title": "Teacher", + "definitions": { + "Teacher": { + "$id": "#/properties/Teacher", + "type": "object", + "title": "The Teacher Schema", + "required": [ + + ], + "properties": { + "identityDetails": { + "$ref": "Common.json/#/definitions/IdentityDetails" + }, + "contactDetails": { + "$ref": "Common.json/#/definitions/ContactDetails" + }, + "academicQualifications": { + "type": "array", + "items": { + "$ref": "Common.json/#/definitions/AcademicQualification" + }, + "title": "Education Details" + }, + "experience": { + "type": "array", + "items": { + "$ref": "Common.json/#/definitions/ExperienceType" + }, + "title": "Professional Experience" + } + } + } + }, + "_osConfig": { + "osComment": [ + "This section contains the OpenSABER specific configuration information", + "privateFields: Optional; list of field names to be encrypted and stored in database", + "signedFields: Optional; list of field names that must be pre-signed", + "indexFields: Optional; list of field names used for creating index. Enclose within braces to indicate it is a composite index. In this definition, (serialNum, teacherCode) is a composite index and teacherName is a single column index.", + "uniqueIndexFields: Optional; list of field names used for creating unique index. Field names must be different from index field name", + "systemFields: Optional; list of fields names used for system standard information like created, updated timestamps and userid" + ], + "privateFields": [ + "$.identityDetails.dob", + "$.identityDetails.identityType", + "$.identityDetails.identityValue", + "$.contactDetails.email", + "$.contactDetails.mobile", + "$.contactDetails.address.plot", + "$.contactDetails.address.street", + "$.contactDetails.address.landmark", + "$.contactDetails.address.locality" + ], + "signedFields": [], + "indexFields": [], + "uniqueIndexFields": [ + "identityValue" + ], + "systemFields": [ + "osCreatedAt", + "osUpdatedAt", + "osCreatedBy", + "osUpdatedBy" + ], + "attestationPolicies": [ + { + "property": "experience/[]", + "paths": [ + "experience" + ], + "attestorEntity": "Institute", + "conditions": "(ATTESTOR#$.instituteName#.contains(REQUESTER#$.institute#))" + }, + { + "property": "academicQualifications/[]", + "paths": [ + "academicQualifications" + ], + "attestorEntity": "Institute", + "conditions": "(ATTESTOR#$.instituteName#.contains(REQUESTER#$.institute#))" + } + ], + "subjectJsonPath": "mobile", + "internalFields": [] + } +} \ No newline at end of file