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

[MDS-6165] - add object types to jsonld and reference untp context files #3241

Merged
merged 7 commits into from
Sep 13, 2024
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
24 changes: 13 additions & 11 deletions services/core-api/app/api/services/traction_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,22 +188,24 @@ def fetch_current_public_did(self):

def sign_jsonld_credential_deprecated(
self,
did,
verkey,
did: str,
verkey: str,
credential: BaseModel,
) -> dict:
# #verkey suffix is indy's default, but could be aparameter later.
options = {"verificationMethod": did + "#verkey", "proofPurpose": "assertionMethod"}
payload = {
"doc": {
"options": options,
"credential": credential.dict(by_alias=True, exclude_none=True)
},
"verkey": verkey,
}

class Payload(BaseModel):
doc: dict
verkey: str

payload = Payload(doc={"options": options, "credential": credential}, verkey=verkey)

post_resp = requests.post(
traction_deprecated_jsonld_sign, json=payload, headers=self.get_headers())
assert post_resp.status_code == 200, f"post_resp={post_resp.json()}"
traction_deprecated_jsonld_sign,
json=payload.model_dump(by_alias=True, exclude_none=True, mode="json"),
headers=self.get_headers())
assert post_resp.status_code == 200, f"post_resp={post_resp.__dict__}"
return post_resp.json()

def fetch_a_random_did_key(self):
Expand Down
103 changes: 60 additions & 43 deletions services/core-api/app/api/verifiable_credentials/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,13 @@ def process_all_untp_map_for_orgbook():
inner join mine_party_appt mpa on p.party_guid = mpa.party_guid
inner join permit pmt on pmt.permit_id = mpa.permit_id
inner join permit_amendment pa on pa.permit_id = pmt.permit_id

inner join mine m on pa.mine_guid = m.mine_guid

where mpa.permit_id is not null
and mpa.mine_party_appt_type_code = 'PMT'
and mpa.deleted_ind = false

and m.major_mine_ind = true

group by pa.permit_amendment_guid, pa.description, pa.issue_date, pa.permit_amendment_status_code, mpa.deleted_ind, pmt.permit_no, mpa.permit_id, poe.party_guid, p.party_name, poe.name_text, poe.registration_id
order by pmt.permit_no, pa.issue_date;

Expand All @@ -143,7 +145,7 @@ def process_all_untp_map_for_orgbook():
assert public_did.startswith(
"did:web:"
), f"Config.CHIEF_PERMITTING_OFFICER_DID_WEB = {Config.CHIEF_PERMITTING_OFFICER_DID_WEB} is not a did:web"
current_app.logger.warning("public did: " + public_did)
task_logger.info("public did: " + public_did)

records: List[Tuple[W3CCred,
PermitAmendmentOrgBookPublish]] = [] # list of tuples [payload, record]
Expand Down Expand Up @@ -186,13 +188,12 @@ def process_all_untp_map_for_orgbook():
try:
record.save()
except IntegrityError:
current_app.logger.warning(f"ignoring duplicate={str(record.unsigned_payload_hash)}")
task_logger.warning(f"ignoring duplicate={str(record.unsigned_payload_hash)}")
continue
current_app.logger.warning(
"bcreg_uri=" +
str(cred_payload.credentialSubject.issuedTo.identifiers[0].identifierURI) +
", for permit_amendment_guid=" + str(row[0]))
current_app.logger.warning("unsigned_hash=" + str(record.unsigned_payload_hash))
task_logger.info("bcreg_uri=" +
str(cred_payload.credentialSubject.issuedTo.identifiers[0].identifierURI) +
", for permit_amendment_guid=" + str(row[0]))
task_logger.warning("unsigned_hash=" + str(record.unsigned_payload_hash))

task_logger.info("num of records created: " + str(len(records or [])))

Expand Down Expand Up @@ -336,51 +337,61 @@ def produce_untp_cc_map_payload(cls, did: str, permit_amendment: PermitAmendment
current_app.logger.warning("No Orgbook Entity, do not produce Mines Act Permit UNTP CC")
return None

untp_party_cpo = base.Party(
untp_party_cpo = base.Entity(
id="did:web:untp.traceability.site:parties:regulators:CHIEF-PERMITTING-OFFICER",
name="Chief Permitting Officer of Mines",
identifiers=[
base.Identifier(
identifierValue=
"did:web:untp.traceability.site:parties:regulators:CHIEF-PERMITTING-OFFICER")
])
registeredId=
"did:web:untp.traceability.site:parties:regulators:CHIEF-PERMITTING-OFFICER",
idScheme=base.IdentifierScheme(
id="https://w3c-ccg.github.io/did-method-web/", name="DID Web"))
orgbook_cred_url = f"https://orgbook.gov.bc.ca/entity/{orgbook_entity.registration_id}/credential/{orgbook_entity.credential_id}"

#this should have a did:web reference ideally, but orgbook doesn't have those yet.
untp_party_business = base.Party(
untp_party_business = base.Entity(
id=orgbook_cred_url,
name=orgbook_entity.name_text,
identifiers=[
base.Identifier(
scheme=ANONCRED_SCHEME,
identifierValue=str(orgbook_entity.registration_id),
identifierURI=orgbook_cred_url)
])
idScheme=base.IdentifierScheme(id=ANONCRED_SCHEME, name="anoncred"),
registeredId=str(orgbook_entity.registration_id))

facility = cc.Facility(
id="https://mines.nrs.gov.bc.ca/PLACEHOLDER",
name=permit_amendment.mine.mine_name,
geolocation=
f'https://plus.codes/{plus_code_encode(permit_amendment.mine.latitude, permit_amendment.mine.longitude)}',
verifiedByCAB=True)
registeredId="mine_no",
idScheme=base.IdentifierScheme(
id="https://www2.gov.bc.ca/PLACEHOLDER", name="FACILITY_PLACEHOLDER"),
IDverifiedByCAB=True)

products = [
cc.Product(
id="https://unstats.un.org/unsd/classifications/Econ/cpc/PLACEHOLDER",
name=c,
classifications=cc.Classification(
scheme="https://unstats.un.org/unsd/classifications/Econ/cpc",
classifierName=c),
verifiedByCAB=False) for c in permit_amendment.mine.commodities
registeredId=c,
idScheme=base.IdentifierScheme(
id="https://unstats.un.org/unsd/classifications/Econ/cpc",
name="Central Product Classification (UNCEFACT)"),
IDverifiedByCAB=False) for c in permit_amendment.mine.commodities
]

untp_assessments = [
cc.ConformityAssessment(
id="https://mines.nrs.gov.bc.ca/ASSESSMENT_ID_PLACEHOLDER",
referenceRegulation=cc.Regulation(
id="https://www.bclaws.gov.bc.ca/civix/document/id/complete/statreg/96293_01",
name="BC Mines Act",
issuingBody=base.Party(name="Government of British Columbia"),
jurisdictionCountry="CA",
administeredBy=base.Entity(
id="https://www2.gov.bc.ca/gov/content/home",
name="Government of British Columbia",
registeredId="BC-GOV",
idScheme=base.IdentifierScheme(
id="https://www2.gov.bc.ca/gov/content/home", name="BC-GOV")),
effectiveDate=datetime(2024, 5, 14, tzinfo=ZoneInfo("UTC")).isoformat()),
conformityTopic=codes.ConformityTopicCode.Governance_Compliance,
# Is there a did:web that attests to that legistlation?
subjectFacilities=[facility],
subjectProducts=products,
sustainabilityTopic=codes.SustainabilityTopic.Governance_Compliance)
assessedFacilities=[facility],
assessedProducts=products)
]
issue_date = permit_amendment.issue_date
issuance_date_str = datetime(
Expand All @@ -389,24 +400,30 @@ def produce_untp_cc_map_payload(cls, did: str, permit_amendment: PermitAmendment

cred = cc.ConformityAttestation(
id="http://example.com/govdomain/minesactpermit/123",
assessmentLevel=codes.AssessmentAssuranceCode.GovtApproval,
type=codes.AttestationType.Certification,
description=
"This is a conformity attestation for the existence of a mining permit under the Mines Act within British Columbia (a province of Canada).",
type="ConformityAttestation",
assessmentLevel=codes.AssessmentLevelCode.GovtApproval,
attestationType=codes.AttestationType.Certification,
scope=cc.ConformityAssessmentScheme(
id=
"https://github.com/bcgov/bc-vcpedia/blob/main/credentials/bc-mines-act-permit/1.1.1/governance.md",
"https://bcgov.github.io/digital-trust-toolkit/docs/governance/mining/bc-mines-act-permit/1.1.1/governance",
name="BC Mines Act Permit Credential (1.1.1) Governance Documentation"),
issuedBy=untp_party_cpo,
issuedTo=untp_party_business,
validFrom=issuance_date_str, #shouldn't this just be in the w3c wrapper
authorisations=base.Endorsement(
id=
"https://www2.gov.bc.ca/gov/content/industry/mineral-exploration-mining/permitting/mines-contact-info",
name="BC Chief Permitting Officer of Mines",
issuingAuthority=untp_party_cpo),
issuedToParty=untp_party_business,
validFrom=issuance_date_str, #shouldn't this just be in the w3c wrapper
assessments=untp_assessments)

w3c_cred = W3CCred(
context=["https://www.w3.org/2018/credentials/v1", {
"@vocab": "urn:bcgov:attributes#"
}],
type=["VerifiableCredential", "NonProductionCredential"],
context=[
"https://www.w3.org/2018/credentials/v1",
"https://test.uncefact.org/vocabulary/untp/dcc/0/untp-dcc-context-0.3.10.jsonld", {
"name": "https://schema.org/name"
}
],
type=["VerifiableCredential", "DigitalConformityCredential", "NonProductionCredential"],
issuer={"id": did},
issuanceDate=issuance_date_str,
credentialSubject=cred)
Expand Down
4 changes: 2 additions & 2 deletions services/core-api/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,5 @@ opentelemetry-instrumentation-sqlalchemy==0.43b0
opentelemetry-instrumentation-urllib3==0.43b0
Pillow==10.3.0
setuptools==65.5.1
urllib3==2.2.2
untp_models==0.0.1
untp_models==0.0.2
urllib3==2.2.2
11 changes: 1 addition & 10 deletions services/core-api/tests/verifiable_credentials/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,7 @@ def test_produce_untp_cc_map_payload_happy(self, db_session):
pa = permit.permit_amendments[0]

assert pa_cred
assert str(pa_cred.credentialSubject.issuedTo.identifiers[0].identifierValue) == str(
poe.registration_id)
assert pa_cred.credentialSubject.validFrom == datetime(
pa.issue_date.year,
pa.issue_date.month,
pa.issue_date.day,
0,
0,
0,
tzinfo=ZoneInfo("UTC")).isoformat()
assert str(pa_cred.credentialSubject.issuedToParty.registeredId) == str(poe.registration_id)

def test_produce_untp_cc_map_payload_null_if_no_orgbook(self, db_session):
mine, permit = create_mine_and_permit()
Expand Down
Loading