-
Notifications
You must be signed in to change notification settings - Fork 38
Issue permits as vc with mdt #1634
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
Changes from 26 commits
ee7aa78
03ab7a8
eae7068
33e847b
5ca44bf
f8a9bd0
71bd131
a94a773
d3a3a35
71b76a3
010127e
a17bfb2
0fe7792
bc7c8be
2bcc281
9eab05b
15568b7
c0dcc8c
423a687
7e6c8cb
681fea5
42db885
a199aff
48269a4
667b2b2
c06ba70
329a23c
1aa67f5
e42c5f8
8d8720b
0711f68
da9208f
5be8d8d
8caecdc
4ea2e34
76f7662
13353d7
ff1c65b
46ed333
adee719
462fc45
d49781a
8e09bc6
603a203
b1c3427
6aa0b5f
ea3fb2c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
from app.api.mines.permits.permit.resources.permit_status_code import PermitStatusCodeResource | ||
from app.api.mines.permits.permit_amendment.resources.permit_amendment import PermitAmendmentResource, PermitAmendmentListResource | ||
from app.api.mines.permits.permit_amendment.resources.permit_amendment_document import PermitAmendmentDocumentListResource, PermitAmendmentDocumentResource | ||
from app.api.mines.permits.permit_amendment.resources.permit_amendment_issue_vc import PermitAmendmentIssueVCResource | ||
from app.api.mines.permits.permit.resources.permit_document_upload import PermitDocumentUploadInitializationResource | ||
from app.api.mines.region.resources.region import MineRegionResource | ||
from app.api.mines.reports.resources.mine_report_document import MineReportDocumentListResource | ||
|
@@ -111,6 +112,11 @@ | |
PermitAmendmentResource, | ||
'/<string:mine_guid>/permits/<string:permit_guid>/amendments/<string:permit_amendment_guid>') | ||
|
||
api.add_resource( | ||
PermitAmendmentIssueVCResource, | ||
'/<string:mine_guid>/permits/<string:permit_guid>/amendments/<string:permit_amendment_guid>/issue-vc-to-orgbook' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really care if this is POC land, but this should probably be something named more like "/credential" instead of "issue-vc-to-orgbook" which seems super not restful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did make some reversals of making some of the names more generic vs specific. I'll take another pass at this one. |
||
) | ||
|
||
api.add_resource( | ||
PermitAmendmentDocumentListResource, | ||
'/<string:mine_guid>/permits/<string:permit_guid>/amendments/<string:permit_amendment_guid>/documents', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from datetime import datetime | ||
from flask import request, current_app | ||
from flask_restplus import Resource, reqparse | ||
from werkzeug.exceptions import BadRequest | ||
|
||
from app.api.mines.permits.permit_amendment.models.permit_amendment import PermitAmendment | ||
|
||
from app.extensions import api | ||
from app.api.utils.access_decorators import requires_role_mine_admin | ||
from app.api.utils.resources_mixins import UserMixin | ||
|
||
from app.api.services.issue_to_orgbook_service import OrgBookIssuerService | ||
|
||
|
||
class PermitAmendmentIssueVCResource(Resource, UserMixin): | ||
@requires_role_mine_admin | ||
@api.response(200, "VC Issued to OrgBook, no local data created") | ||
def post(self, mine_guid, permit_guid, permit_amendment_guid): | ||
permit_amendment = PermitAmendment.find_by_permit_amendment_guid(permit_amendment_guid) | ||
|
||
response = OrgBookIssuerService().issue_permit_amendment_vc(permit_amendment) | ||
if not response: | ||
raise BadRequest( | ||
"Credential Not Issued, ensure permittee is associated with OrgBook Entity") | ||
return |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,8 @@ | |
from app.api.mines.permits.permit_amendment.models.permit_amendment import PermitAmendment | ||
from app.api.mines.permits.permit_amendment.models.permit_amendment_document import PermitAmendmentDocument | ||
from app.api.parties.party_appt.models.mine_party_appt import MinePartyAppointment | ||
|
||
from app.api.services.issue_to_orgbook_service import OrgBookIssuerService | ||
from werkzeug.exceptions import BadRequest, NotFound, NotImplemented | ||
|
||
|
||
|
@@ -141,6 +143,17 @@ def put(self, application_guid): | |
|
||
permit_amendment.save() | ||
|
||
#Issue Permit as Verifiable Credential to OrgBook | ||
try: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should any possible exceptions be blocking? Do we just want to log the messages? |
||
OrgBookIssuerService().issue_permit_amendment_vc(permit_amendment) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to check the return value of this here, i.e. the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't want this code to effect this method at all. I could be talked into not modifying this at all. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Up to you guys on this one. |
||
except AssertionError as e: | ||
#non-blocking failure | ||
current_app.logger.info('VC Not issued due to non-200 status code') | ||
current_app.logger.debug(str(e)) | ||
except Exception as ex: | ||
current_app.logger.warning('VC Not issued due to unknown error') | ||
current_app.logger.info(str(e)) | ||
|
||
#create contacts | ||
for contact in now_application_identity.now_application.contacts: | ||
if contact.mine_party_appt_type_code == 'PMT' or contact.mine_party_appt_type_code == 'MMG': | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import requests, json, pprint, time, threading | ||
|
||
from dateutil.relativedelta import relativedelta | ||
from datetime import datetime, timedelta | ||
from flask import request, current_app | ||
from app.config import Config | ||
|
||
|
||
class OrgBookIssuerService(): | ||
"""This class is used to connect to an issuer controller, which handles the nuance and handshakes involved with issuing | ||
verifiable credentials to a Verifiable Credential Registry (VRC), OrgBook is an instance of aries-vrc (https://github.com/bcgov/aries-vcr). | ||
Mines-Digital-Trust has stood up an Issuer Controller API (https://github.com/bcgov/aries-vcr-issuer-controller) to serve CORE to issue | ||
Mines Act Permits as VC's.""" | ||
|
||
issuer_controller_url = Config.VCR_ISSUER_URL #FROM DeployConfig | ||
issuer_secret_key = Config.VCR_ISSUER_SECRET_KEY #FROM SECRET | ||
vc_schema_name = "bcgov-mines-act-permit.bcgov-mines-permitting" | ||
vc_schema_version = "0.2.0" | ||
issuer_controller_ready = False | ||
|
||
def __init__(self): | ||
retry_count = 0 | ||
while retry_count < 5: | ||
retry_count += 1 | ||
response = requests.get(self.issuer_controller_url + 'liveness') | ||
if response.status_code != 200: | ||
current_app.logger.warning('Issuer Controller not live: ' + | ||
str(response.status_code)) | ||
time.sleep(.500 * retry_count) | ||
continue | ||
#check api key | ||
response = requests.get( | ||
self.issuer_controller_url + 'status', | ||
headers={ | ||
'issuer_secret_key': self.issuer_secret_key, | ||
}) | ||
if response.status_code == 200: | ||
self.issuer_controller_ready = True | ||
current_app.logger.info('Issuer Controller ready and secret-key correct!') | ||
return | ||
elif response.status_code != 503: | ||
current_app.logger.error('Livenesscheck failed: ' + str(response.status_code)) | ||
time.sleep(.500 * retry_count) | ||
current_app.logger.error('Issuer Controller liveness check failed, nothing will be issued') | ||
|
||
def publish_schema(self, new_schema, new_schema_version): | ||
raise NotImplementedError( | ||
"""The MDT issuer controller publishes schema on init, to update your VC schema, | ||
send them a message. This can be done dynamically in the future once MDT implements it""" | ||
) | ||
|
||
def inspect_current_schema(self): | ||
raise NotImplementedError( | ||
"""Hopefully this exists, the MDT issuer controller should be able to inspect | ||
and return the current schema it is expecting/allowing. | ||
|
||
Inspecting old schemas can be done by looking at the hyperledger directly | ||
production -> http://prod.bcovrin.vonx.io/browse/domain?page=1&query=&txn_type=101 | ||
test - http://test.bcovrin.vonx.io/browse/domain?page=1&query=&txn_type=101 | ||
dev - http://dev.bcovrin.vonx.io/browse/domain?page=1&query=&txn_type=101 | ||
""") | ||
|
||
def issue_permit_amendment_vc(self, permit_amendment): | ||
if not self.issuer_controller_ready: | ||
current_app.logger.warning( | ||
'Issuer Controller liveness check failed on init, this call did nothing') | ||
permittee_orgbook_entity = permit_amendment.permit.permittee_appointments[ | ||
0].party.party_orgbook_entity | ||
if not permittee_orgbook_entity: | ||
current_app.logger.warning( | ||
'skipping issue_permit_amendment_vc, permittee not link to orgbook business') | ||
return | ||
|
||
payload = json.dumps([{ | ||
"schema": self.vc_schema_name, | ||
"version": self.vc_schema_version, | ||
"attributes": { | ||
"permit_id": str(permit_amendment.permit_guid), | ||
"registration_id": permittee_orgbook_entity.registration_id, | ||
"permit_no": permit_amendment.permit.permit_no, | ||
"mine_no": permit_amendment.mine.mine_no, | ||
"mine_class": 'major' if permit_amendment.mine.major_mine_ind else 'regional', | ||
"latitude": str(permit_amendment.mine.latitude), | ||
"longitude": str(permit_amendment.mine.longitude), | ||
"issued_date": str(permit_amendment.issue_date), | ||
"effective_date": str(permit_amendment.issue_date), | ||
"authorization_end_date": str(permit_amendment.authorization_end_date), | ||
"inspector_name": "Best Inspector" | ||
Jsyro marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
}]) | ||
current_app.logger.debug('issuing-credential to OrgBook business \'' + | ||
permittee_orgbook_entity.registration_id + ',' + | ||
permittee_orgbook_entity.name_text + '\'') | ||
response = requests.post( | ||
self.issuer_controller_url + 'issue-credential', | ||
data=payload, | ||
headers={ | ||
'issuer_secret_key': self.issuer_secret_key, | ||
'Content-Type': 'application/json' | ||
}) | ||
current_app.logger.debug('issue-credential call returned successfully') | ||
return response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this better, thanks