Merge pull request 'new_credtools' (#127) from new_credtools into main
Reviewed-on: https://gitea.pangea.org/trustchain-oc1-orchestral/IdHub/pulls/127
This commit is contained in:
commit
73d015ddab
BIN
examples/excel_templates/course-credential.xlsx
Normal file
BIN
examples/excel_templates/course-credential.xlsx
Normal file
Binary file not shown.
BIN
examples/excel_templates/device-purchase.xlsx
Normal file
BIN
examples/excel_templates/device-purchase.xlsx
Normal file
Binary file not shown.
BIN
examples/excel_templates/e-operator-claim.xlsx
Normal file
BIN
examples/excel_templates/e-operator-claim.xlsx
Normal file
Binary file not shown.
BIN
examples/excel_templates/federation-membership.xlsx
Normal file
BIN
examples/excel_templates/federation-membership.xlsx
Normal file
Binary file not shown.
BIN
examples/excel_templates/financial-vulnerability.xlsx
Normal file
BIN
examples/excel_templates/financial-vulnerability.xlsx
Normal file
Binary file not shown.
BIN
examples/excel_templates/membership-card.xlsx
Normal file
BIN
examples/excel_templates/membership-card.xlsx
Normal file
Binary file not shown.
|
@ -46,7 +46,7 @@
|
||||||
class="btn btn-primary form-control" id="submit-id-submit">
|
class="btn btn-primary form-control" id="submit-id-submit">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div id="login-footer" class="mt-3">
|
<div id="login-footer" class="mt-3 d-none">
|
||||||
<a href="{% url 'idhub:password_reset' %}" data-toggle="modal" data-target="#forgotPasswordModal">{% trans "Forgot your password? Click here to recover" %}</a>
|
<a href="{% url 'idhub:password_reset' %}" data-toggle="modal" data-target="#forgotPasswordModal">{% trans "Forgot your password? Click here to recover" %}</a>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
<form role="form" method="post">
|
<form role="form" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4">
|
<div class="col">
|
||||||
{% bootstrap_form form %}
|
{% bootstrap_form form %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
<form role="form" method="post">
|
<form role="form" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4">
|
<div class="col">
|
||||||
{% bootstrap_form form %}
|
{% bootstrap_form form %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,4 +28,5 @@ fontTools==4.47.0
|
||||||
weasyprint==60.2
|
weasyprint==60.2
|
||||||
ujson==5.9.0
|
ujson==5.9.0
|
||||||
openpyxl==3.1.2
|
openpyxl==3.1.2
|
||||||
|
jsonpath_ng==1.6.1
|
||||||
./didkit-0.3.2-cp311-cp311-manylinux_2_34_x86_64.whl
|
./didkit-0.3.2-cp311-cp311-manylinux_2_34_x86_64.whl
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
|
import pandas as pd
|
||||||
import json
|
import json
|
||||||
#import jsonld
|
# import jsonld
|
||||||
import csv
|
import csv
|
||||||
import sys
|
import sys
|
||||||
import jsonschema
|
import jsonschema
|
||||||
from pyld import jsonld
|
# from jsonschema import validate, ValidationError
|
||||||
#from jsonschema import validate, ValidationError
|
|
||||||
import requests
|
import requests
|
||||||
from pyld import jsonld
|
from pyld import jsonld
|
||||||
import jsonref
|
import jsonref
|
||||||
|
from jsonpath_ng import jsonpath, parse
|
||||||
|
|
||||||
#def remove_null_values(dictionary):
|
|
||||||
|
# def remove_null_values(dictionary):
|
||||||
# return {k: v for k, v in dictionary.items() if v is not None}
|
# return {k: v for k, v in dictionary.items() if v is not None}
|
||||||
|
|
||||||
def _remove_null_values(dictionary):
|
def _remove_null_values(dictionary):
|
||||||
|
@ -17,6 +19,7 @@ def _remove_null_values(dictionary):
|
||||||
dictionary.clear()
|
dictionary.clear()
|
||||||
dictionary.update(filtered)
|
dictionary.update(filtered)
|
||||||
|
|
||||||
|
|
||||||
def validate_context(jsld):
|
def validate_context(jsld):
|
||||||
"""Validate a @context string through expanding"""
|
"""Validate a @context string through expanding"""
|
||||||
context = jsld["@context"]
|
context = jsld["@context"]
|
||||||
|
@ -30,6 +33,7 @@ def validate_context(jsld):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def compact_js(doc, context):
|
def compact_js(doc, context):
|
||||||
"""Validate a @context string through compacting, returns compacted context"""
|
"""Validate a @context string through compacting, returns compacted context"""
|
||||||
try:
|
try:
|
||||||
|
@ -40,6 +44,7 @@ def compact_js(doc, context):
|
||||||
return None
|
return None
|
||||||
return compacted
|
return compacted
|
||||||
|
|
||||||
|
|
||||||
def dereference_context_file(json_file):
|
def dereference_context_file(json_file):
|
||||||
"""Dereference and return json-ld context from file"""
|
"""Dereference and return json-ld context from file"""
|
||||||
json_text = open(json_file).read()
|
json_text = open(json_file).read()
|
||||||
|
@ -76,22 +81,36 @@ def dereference_context(jsonld_dict):
|
||||||
def validate_schema_file(json_schema_file):
|
def validate_schema_file(json_schema_file):
|
||||||
"""Validate standalone schema from file"""
|
"""Validate standalone schema from file"""
|
||||||
try:
|
try:
|
||||||
json_schema = open(json_schema_file).read()
|
json_schema = json.loads(open(json_schema_file).read())
|
||||||
validate_schema(json_schema)
|
validate_schema(json_schema)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error loading file {json_schema_file} or validating schema {json_schema}: {e}")
|
print(f"Error loading file {json_schema_file} or validating schema {json_schema}: {e}")
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def validate_schema(json_schema):
|
def validate_schema(json_schema):
|
||||||
"""Validate standalone schema, returns bool (uses Draft202012Validator, alt: Draft7Validator, alt: Draft4Validator, Draft6Validator )"""
|
"""Validate standalone schema, returns bool (uses Draft202012Validator, alt: Draft7Validator, alt: Draft4Validator, Draft6Validator )"""
|
||||||
try:
|
try:
|
||||||
jsonschema.validators.Draft202012Validator.check_schema(json_schema)
|
jsonschema.validators.Draft202012Validator.check_schema(json_schema)
|
||||||
# jsonschema.validators.Draft7Validator.check_schema(json_schema)
|
# jsonschema.validators.Draft7Validator.check_schema(json_schema)
|
||||||
return True
|
|
||||||
except jsonschema.exceptions.SchemaError as e:
|
except jsonschema.exceptions.SchemaError as e:
|
||||||
print(e)
|
print(e)
|
||||||
return False
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def validate_json_file(json_data_file, json_schema_file):
|
||||||
|
"""Validate standalone schema from file"""
|
||||||
|
try:
|
||||||
|
json_data = json.loads(open(json_data_file).read())
|
||||||
|
json_schema = json.loads(open(json_schema_file).read())
|
||||||
|
validate_json(json_data, json_schema)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading file {json_schema_file} or {json_data_file}: {e}")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def validate_json(json_data, json_schema):
|
def validate_json(json_data, json_schema):
|
||||||
"""Validate json string basic (no format) with schema, returns bool"""
|
"""Validate json string basic (no format) with schema, returns bool"""
|
||||||
|
@ -100,8 +119,10 @@ def validate_json(json_data, json_schema):
|
||||||
except jsonschema.exceptions.ValidationError as err:
|
except jsonschema.exceptions.ValidationError as err:
|
||||||
print('Validation error: ', json_data, '\n')
|
print('Validation error: ', json_data, '\n')
|
||||||
return False
|
return False
|
||||||
|
print("Successful validation")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def validate_json_format(json_data, json_schema):
|
def validate_json_format(json_data, json_schema):
|
||||||
"""Validate a json string basic (including format) with schema, returns bool"""
|
"""Validate a json string basic (including format) with schema, returns bool"""
|
||||||
try:
|
try:
|
||||||
|
@ -111,9 +132,29 @@ def validate_json_format(json_data, json_schema):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def schema_to_csv_file(sch_f, csv_f):
|
||||||
|
try:
|
||||||
|
json_schema = json.loads(open(sch_f).read())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading file {sch_f}: {e}\nSchema:\n{json_schema}.")
|
||||||
|
return False
|
||||||
|
schema_to_csv(json_schema, csv_f)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def schema_to_csv(schema, csv_file_path):
|
def schema_to_csv(schema, csv_file_path):
|
||||||
"""Extract headers from an schema and write to file, returns bool"""
|
"""Extract headers from an schema and write to file, returns bool"""
|
||||||
headers = list(schema['properties'].keys())
|
jsonpath_expr = parse('$..credentialSubject.properties')
|
||||||
|
# Use the JSONPath expression to select all properties under 'credentialSubject.properties'
|
||||||
|
matches = [match.value for match in jsonpath_expr.find(schema)]
|
||||||
|
# Get the keys of the matched objects
|
||||||
|
# headers = [match.keys() for match in matches]
|
||||||
|
# Use the JSONPath expression to select all properties under 'credentialSubject.properties'
|
||||||
|
|
||||||
|
# Get the keys of the matched objects
|
||||||
|
headers = [key for match in matches for key in match.keys()]
|
||||||
|
# print('\nHeaders: ', headers)
|
||||||
|
|
||||||
# Create a CSV file with the headers
|
# Create a CSV file with the headers
|
||||||
with open(csv_file_path, 'w', newline='') as csv_file:
|
with open(csv_file_path, 'w', newline='') as csv_file:
|
||||||
|
@ -121,6 +162,70 @@ def schema_to_csv(schema, csv_file_path):
|
||||||
writer.writerow(headers)
|
writer.writerow(headers)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def schema_to_xls_basic(schema, xls_file_path):
|
||||||
|
"""Extract headers from an schema and write to file, returns bool"""
|
||||||
|
jsonpath_expr = parse('$..credentialSubject.properties')
|
||||||
|
# Use the JSONPath expression to select all properties under 'credentialSubject.properties'
|
||||||
|
matches = [match.value for match in jsonpath_expr.find(schema)]
|
||||||
|
# Get the keys of the matched objects
|
||||||
|
# headers = [match.keys() for match in matches]
|
||||||
|
|
||||||
|
# Get the keys of the matched objects
|
||||||
|
headers = [key for match in matches for key in match.keys() if key != 'id']
|
||||||
|
|
||||||
|
# Create a DataFrame with the fields as columns
|
||||||
|
df = pd.DataFrame(columns=headers)
|
||||||
|
|
||||||
|
# Save the DataFrame as an Excel file
|
||||||
|
# df.to_excel(xls_file_path, index=False)
|
||||||
|
df.to_excel(xls_file_path, index=False, engine='openpyxl') # For .xlsx files, and pip install openpyxl
|
||||||
|
return True
|
||||||
|
|
||||||
|
def schema_to_xls_comment(schema, xls_file_path):
|
||||||
|
"""Extract headers from an schema and write to file, returns bool"""
|
||||||
|
jsonpath_expr = parse('$..credentialSubject.properties')
|
||||||
|
# Use the JSONPath expression to select all properties under 'credentialSubject.properties'
|
||||||
|
matches = [match.value for match in jsonpath_expr.find(schema)]
|
||||||
|
# Get the keys of the matched objects
|
||||||
|
# headers = [match.keys() for match in matches]
|
||||||
|
|
||||||
|
# Get the keys of the matched objects
|
||||||
|
headers = [key for match in matches for key in match.keys() if key != 'id']
|
||||||
|
|
||||||
|
jsonpath_expr_req = parse('$..credentialSubject.required')
|
||||||
|
req = [match.value for match in jsonpath_expr_req.find(schema)][0]
|
||||||
|
|
||||||
|
# Create a DataFrame with the fields as columns
|
||||||
|
df = pd.DataFrame(columns=headers)
|
||||||
|
|
||||||
|
writer = pd.ExcelWriter(xls_file_path, engine='xlsxwriter')
|
||||||
|
|
||||||
|
# Convert the dataframe to an xlsxwriter Excel object
|
||||||
|
df.to_excel(writer, sheet_name='Full1', index=False)
|
||||||
|
|
||||||
|
# Get the xlsxwriter workbook and worksheet objects
|
||||||
|
workbook = writer.book
|
||||||
|
worksheet = writer.sheets['Full1']
|
||||||
|
|
||||||
|
# Define a format for the required header cells
|
||||||
|
req_format = workbook.add_format({'border': 1})
|
||||||
|
# cell_format = workbook.add_format({'bold': True, 'font_color': 'red'})
|
||||||
|
|
||||||
|
# Write comments to the cells
|
||||||
|
for i, header in enumerate(headers):
|
||||||
|
if header in req:
|
||||||
|
worksheet.set_column(i,i, None, req_format)
|
||||||
|
# Get the description for the current field
|
||||||
|
if 'description' in matches[0][header]:
|
||||||
|
description = matches[0][header]['description']
|
||||||
|
if description is not None:
|
||||||
|
# Write the description as a comment to the corresponding cell
|
||||||
|
worksheet.write_comment(0, i, description)
|
||||||
|
|
||||||
|
# Close the Pandas Excel writer and output the Excel file
|
||||||
|
worksheet.autofit()
|
||||||
|
writer.close()
|
||||||
|
return True
|
||||||
|
|
||||||
def csv_to_json(csvFilePath, schema, jsonFilePath):
|
def csv_to_json(csvFilePath, schema, jsonFilePath):
|
||||||
"""Read from a csv file, check schema, write to json file, returns bool"""
|
"""Read from a csv file, check schema, write to json file, returns bool"""
|
||||||
|
@ -144,6 +249,7 @@ def csv_to_json(csvFilePath, schema, jsonFilePath):
|
||||||
jsonf.write(jsonString)
|
jsonf.write(jsonString)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def csv_to_json2(csv_file_path, json_file_path):
|
def csv_to_json2(csv_file_path, json_file_path):
|
||||||
"""Read from a csv file, write to json file (assumes a row 'No' is primary key), returns bool EXPERIMENT"""
|
"""Read from a csv file, write to json file (assumes a row 'No' is primary key), returns bool EXPERIMENT"""
|
||||||
# Create a dictionary
|
# Create a dictionary
|
||||||
|
@ -164,11 +270,18 @@ def csv_to_json2(csv_file_path, json_file_path):
|
||||||
jsonf.write(json.dumps(data, indent=4))
|
jsonf.write(json.dumps(data, indent=4))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
sch_name = sys.argv[1]
|
# sch_name = sys.argv[1]
|
||||||
sch_file = sch_name + '-schema.json'
|
schemas = sys.argv[1:]
|
||||||
sch = json.loads(open(sch_file).read())
|
|
||||||
if validate_json(d, sch):
|
# credtools.py course-credential device-purchase e-operator-claim federation-membership financial-vulnerability membership-card
|
||||||
generate_csv_from_schema(sch, sch_name + '-template.csv')
|
#sch_name = 'e-operator-claim'
|
||||||
|
|
||||||
|
for i, schema in enumerate(schemas):
|
||||||
|
print(schema)
|
||||||
|
sch = json.loads(open('vc_schemas/' + schema + '.json').read())
|
||||||
|
if schema_to_xls_comment(sch,'vc_excel/' + schema + '.xlsx'):
|
||||||
|
print('Success')
|
||||||
else:
|
else:
|
||||||
print("Validation error: ", sch_name)
|
print("Validation error: ", schema)
|
||||||
|
|
Loading…
Reference in a new issue