Skip to content

Commit

Permalink
Add Python package target and examples
Browse files Browse the repository at this point in the history
Python package using C bindings

Add support for DIDKit errors; Automatically convert to and from utf8 strings

Signed-off-by: Tiago Nascimento <[email protected]>

Added symlink to the libdidkit.so

Added Makefile target

Build and install instructions for Python

Git ignore for __pycache__

Correct binary name for each OS

Django base scaffold

Fix free on python target

QRCode to generate VC, VC Issuance

Submit did functionality

Changes for working with credible

Python package build to Makefile and CI

Python package using C bindings

Added symlink to the libdidkit.so

Added Makefile target

Change author and email address

Add build instructions for django example

Remove sqlite file

Add django dependency

Add flask example

Remove library binary

Fix links to the libraries

Add install command for pip

Fix didkit build instruction

Replace unnecessary dependency

Automatically get the the current version

Add tests to python target
  • Loading branch information
w4ll3 authored and wyc committed Mar 17, 2021
1 parent ecd291c commit f5eded5
Show file tree
Hide file tree
Showing 44 changed files with 1,279 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,6 @@ jobs:

- name: Build Android Archive
run: make -C lib ../target/test/aar.stamp

- name: Test Python Package
run: make -C lib ../target/test/python.stamp
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
Cargo.lock
__pycache__/
1 change: 1 addition & 0 deletions examples/python-flask/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
key.jwk
46 changes: 46 additions & 0 deletions examples/python-flask/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Flask Example

This project demonstrates use of verifiable credentials and presentation for an
application.

## Dependencies

- Python 3
- Pip
- Python 3 virtual environment

```bash
$ sudo apt update
$ sudo apt install -y python3.6 python3-pip python3-virtualenv python3-venv
```

### Python dependencies

- flask-qrcode
- Flask
- didkit

```bash
$ python3 -m pip install flask-qrcode flask
```

### Building DIDKit

DIDKit is used to handle credentials and presentations, since it's not yet
publically available in PyPI manual installation is required.

To do so got to the root folder of this repository and run:
```bash
$ make -C lib ../target/test/python.stamp
```

## Running

For the first time running you will need to run the migrations,
this can be accomplished by running the following command:

To start the server just run:

```bash
$ FLASK_APP=didkit_flask.py python3 didkit_flask.py
```
63 changes: 63 additions & 0 deletions examples/python-flask/didkit_flask.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from socket import socket, AF_INET, SOCK_DGRAM
from flask import Flask, request, render_template, jsonify
from issue_credential import issueCredential
from flask_qrcode import QRcode
from didkit import generateEd25519Key
import errno
import os
import json

app = Flask(__name__)
qrcode = QRcode(app)


@app.route('/')
def index():
s = socket(AF_INET, SOCK_DGRAM)
try:
s.connect(("10.255.255.255", 1))
IP = s.getsockname()[0]
except Exception:
IP = "127.0.0.1"
finally:
s.close()

url = (request.is_secure and "https://" or "http://") + IP + \
":" + request.host.split(':')[-1] + "/wallet"

return render_template('index.html', url=url)


@app.route('/credential', methods=['GET', 'POST'])
def credential():
credential = json.dumps(issueCredential(request), indent=2, sort_keys=True)

return render_template('credential.html', credential=credential)


@app.route('/wallet', methods=['GET', 'POST'])
def wallet():
credential = issueCredential(request)
if request.method == 'GET':
return jsonify({
"type": "CredentialOffer",
"credentialPreview": credential
})

elif request.method == 'POST':
return jsonify(credential)


if __name__ == '__main__':
flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY
try:
file_handle = os.open('key.jwk', flags)
except OSError as e:
if e.errno == errno.EEXIST:
pass
else:
raise
else:
with os.fdopen(file_handle, 'w') as file_obj:
file_obj.write(generateEd25519Key())
app.run(host='0.0.0.0')
47 changes: 47 additions & 0 deletions examples/python-flask/issue_credential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from datetime import datetime, timedelta
import didkit
import json
import uuid


def issueCredential(request):
with open('key.jwk', "r") as f:
key = f.readline()
f.close()

did_key = request.form.get('subject_id', didkit.keyToDID("key", key))
verification_method = didkit.keyToVerificationMethod("key", key)
issuance_date = datetime.utcnow().replace(microsecond=0)
expiration_date = issuance_date + timedelta(weeks=24)

credential = {
"id": "urn:uuid:" + uuid.uuid4().__str__(),
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential"],
"issuer": did_key,
"issuanceDate": issuance_date.isoformat() + "Z",
"expirationDate": expiration_date.isoformat() + "Z",
"credentialSubject": {
"@context": [
{
"username": "https://schema.org/Text"
}
],
"id": "urn:uuid:" + uuid.uuid4().__str__(),
"username": "Someone",
},
}

didkit_options = {
"proofPurpose": "assertionMethod",
"verificationMethod": verification_method,
}

credential = didkit.issueCredential(
credential.__str__().replace("'", '"'),
didkit_options.__str__().replace("'", '"'),
key)
return json.loads(credential)
11 changes: 11 additions & 0 deletions examples/python-flask/templates/credential.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<title>DIDKit Django</title>
</head>
<body class="h-screen w-screen flex">
<pre class="whitespace-pre-wrap m-auto">{{ credential }}</pre>
</body>
</html>
30 changes: 30 additions & 0 deletions examples/python-flask/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<title>DIDKit Django</title>
</head>
<body class="flex flex-col items-center justify-center h-screen w-screen">
<form class="flex items-center justify-center mb-4" method="post" action="/credential">
<input type="text" placeholder="Enter your DID:" class="h-12 p-4 border border-blue-900 rounded mr-4" name="subject_id" />
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Get credential
</button>
</form>
<p>or scan the QRCode bellow with your wallet. i.e: Credible</p>
<div class="my-8"><img src={{ qrcode(url) }} class="w-32 h-32"></div>
<p>or</p>
<a href="/credential">
<button
class="h-12 p-2 border mt-6 border-blue-900 rounded"
type="submit"
>
Get server issued credential
</button>
</a>
</body>
</html>
2 changes: 2 additions & 0 deletions examples/python_django/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
key.jwk
db.sqlite3
49 changes: 49 additions & 0 deletions examples/python_django/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Django Example

This project demonstrates use of verifiable credentials and presentation for an
application.

## Dependencies

- Python 3
- Pip

```bash
$ sudo apt update
$ sudo apt install -y python3.6 python3-pip
```

### Python dependencies

- django-qr-code
- didkit
- Django

```bash
$ python3 -m pip install django-qr-code django
```

### Building DIDKit

DIDKit is used to handle credentials and presentations, since it's not yet
publically available in PyPI manual installation is required.

To do so got to the root folder of this repository and run:
```bash
$ make -C lib ../target/test/python.stamp
```

## Running

For the first time running you will need to run the migrations,
this can be accomplished by running the following command:

```bash
$ python3 manage.py migrate
```

To start the server just run:

```bash
$ python3 manage.py runserver
```
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions examples/python_django/didkit_django/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
5 changes: 5 additions & 0 deletions examples/python_django/didkit_django/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class DidkitDjangoConfig(AppConfig):
name = 'didkit_django'
50 changes: 50 additions & 0 deletions examples/python_django/didkit_django/issue_credential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from python_django.settings import KEY_PATH
from django.core.files import File
from datetime import datetime, timedelta
import didkit
import json
import uuid


def issueCredential(request):
with open(KEY_PATH, "r") as f:
key_file = File(f)
key = key_file.readline()
key_file.close()

did_key = request.POST.get('subject_id', didkit.keyToDID("key", key))
verification_method = didkit.keyToVerificationMethod("key", key)
issuance_date = datetime.utcnow().replace(microsecond=0)
expiration_date = issuance_date + timedelta(weeks=24)

credential = {
"id": "urn:uuid:" + uuid.uuid4().__str__(),
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential"],
"issuer": did_key,
"issuanceDate": issuance_date.isoformat() + "Z",
"expirationDate": expiration_date.isoformat() + "Z",
"credentialSubject": {
"@context": [
{
"username": "https://schema.org/Text"
}
],
"id": "urn:uuid:" + uuid.uuid4().__str__(),
"username": "Someone",
},
}

didkit_options = {
"proofPurpose": "assertionMethod",
"verificationMethod": verification_method,
}

credential = didkit.issueCredential(
credential.__str__().replace("'", '"'),
didkit_options.__str__().replace("'", '"'),
key)
return json.loads(credential)
Empty file.
3 changes: 3 additions & 0 deletions examples/python_django/didkit_django/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.db import models

# Create your models here.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
{% load extras %}
<html>
<head>
<meta charset="utf-8">
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<title>DIDKit Django</title>
</head>
<body class="h-screen w-screen flex">
<pre class="whitespace-pre-wrap m-auto">{{ credential | pretty_json }}</pre>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
{% load qrcode %}
<html>
<head>
<meta charset="utf-8">
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<title>DIDKit Django</title>
</head>
<body class="flex flex-col items-center justify-center h-screen w-screen">
<form class="flex items-center justify-center mb-4" method="post" action="/didkit/credential/">
{% csrf_token %}
<input type="text" placeholder="Enter your DID:" class="h-12 p-4 border border-blue-900 rounded mr-4" name="subject_id" />
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Get credential
</button>
</form>
<p>or scan the QRCode bellow with your wallet. i.e: Credible</p>
<div>{% qr_from_text url size="S" image_format="svg" %}</div>
<p>or</p>
<a href="/didkit/credential">
<button
class="h-12 p-2 border mt-6 border-blue-900 rounded"
type="submit"
>
Get server issued credential
</button>
</a>
</body>
</html>
Empty file.
10 changes: 10 additions & 0 deletions examples/python_django/didkit_django/templatetags/extras.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import json

from django import template

register = template.Library()


@register.filter
def pretty_json(value):
return json.dumps(value, indent=2, sort_keys=True)
Loading

0 comments on commit f5eded5

Please sign in to comment.