add predefined_token in initial_datas #6
|
@ -31,11 +31,14 @@ IDHUB_ADMIN_USER='admin'
|
||||||
IDHUB_ADMIN_PASSWD='admin'
|
IDHUB_ADMIN_PASSWD='admin'
|
||||||
IDHUB_ADMIN_EMAIL='admin@example.org'
|
IDHUB_ADMIN_EMAIL='admin@example.org'
|
||||||
|
|
||||||
|
IDHUB_SUPPORTED_CREDENTIALS="['CourseCredential', 'EOperatorClaim', 'FederationMembership', 'FinancialVulnerabilityCredential', 'MembershipCard', 'Snapshot']"
|
||||||
|
|
||||||
# this option needs to be set to 'n' to be able to make work idhub in docker
|
# this option needs to be set to 'n' to be able to make work idhub in docker
|
||||||
# by default it is set to 'y' to facilitate idhub dev when outside docker
|
# by default it is set to 'y' to facilitate idhub dev when outside docker
|
||||||
IDHUB_SYNC_ORG_DEV='n'
|
IDHUB_SYNC_ORG_DEV='n'
|
||||||
|
|
||||||
# TODO that is only for testing
|
# TODO that is only for testing/demo purposes
|
||||||
IDHUB_ENABLE_EMAIL=false
|
IDHUB_ENABLE_EMAIL=false
|
||||||
IDHUB_ENABLE_2FACTOR_AUTH=false
|
IDHUB_ENABLE_2FACTOR_AUTH=false
|
||||||
IDHUB_ENABLE_DOMAIN_CHECKER=false
|
IDHUB_ENABLE_DOMAIN_CHECKER=false
|
||||||
|
IDHUB_PREDEFINED_TOKEN='27f944ce-3d58-4f48-b068-e4aa95f97c95'
|
||||||
|
|
|
@ -15,6 +15,7 @@ services:
|
||||||
- ENABLE_EMAIL=${IDHUB_ENABLE_EMAIL:-true}
|
- ENABLE_EMAIL=${IDHUB_ENABLE_EMAIL:-true}
|
||||||
- ENABLE_2FACTOR_AUTH=${IDHUB_ENABLE_2FACTOR_AUTH:-true}
|
- ENABLE_2FACTOR_AUTH=${IDHUB_ENABLE_2FACTOR_AUTH:-true}
|
||||||
- ENABLE_DOMAIN_CHECKER=${IDHUB_ENABLE_DOMAIN_CHECKER:-true}
|
- ENABLE_DOMAIN_CHECKER=${IDHUB_ENABLE_DOMAIN_CHECKER:-true}
|
||||||
|
- PREDEFINED_TOKEN=${IDHUB_PREDEFINED_TOKEN:-}
|
||||||
- SECRET_KEY=${IDHUB_SECRET_KEY:-publicsecretisnotsecureVtmKBfxpVV47PpBCF2Nzz2H6qnbd}
|
- SECRET_KEY=${IDHUB_SECRET_KEY:-publicsecretisnotsecureVtmKBfxpVV47PpBCF2Nzz2H6qnbd}
|
||||||
- STATIC_ROOT=${IDHUB_STATIC_ROOT:-/static/}
|
- STATIC_ROOT=${IDHUB_STATIC_ROOT:-/static/}
|
||||||
- MEDIA_ROOT=${IDHUB_MEDIA_ROOT:-/media/}
|
- MEDIA_ROOT=${IDHUB_MEDIA_ROOT:-/media/}
|
||||||
|
@ -26,7 +27,7 @@ services:
|
||||||
- EMAIL_PORT=${IDHUB_EMAIL_PORT}
|
- EMAIL_PORT=${IDHUB_EMAIL_PORT}
|
||||||
- EMAIL_USE_TLS=${IDHUB_EMAIL_USE_TLS}
|
- EMAIL_USE_TLS=${IDHUB_EMAIL_USE_TLS}
|
||||||
- EMAIL_BACKEND=${IDHUB_EMAIL_BACKEND}
|
- EMAIL_BACKEND=${IDHUB_EMAIL_BACKEND}
|
||||||
- SUPPORTED_CREDENTIALS=['CourseCredential', 'EOperatorClaim', 'FederationMembership', 'FinancialVulnerabilityCredential', 'MembershipCard', 'Snapshot']
|
- SUPPORTED_CREDENTIALS=${IDHUB_SUPPORTED_CREDENTIALS:-}
|
||||||
- SYNC_ORG_DEV=${IDHUB_SYNC_ORG_DEV}
|
- SYNC_ORG_DEV=${IDHUB_SYNC_ORG_DEV}
|
||||||
ports:
|
ports:
|
||||||
- ${IDHUB_PORT:-9001}:${IDHUB_PORT:-9001}
|
- ${IDHUB_PORT:-9001}:${IDHUB_PORT:-9001}
|
||||||
|
|
|
@ -15,6 +15,7 @@ main() {
|
||||||
cp -v .env.example .env
|
cp -v .env.example .env
|
||||||
echo "WARNING: .env was not there, .env.example was copied, this only happens once"
|
echo "WARNING: .env was not there, .env.example was copied, this only happens once"
|
||||||
fi
|
fi
|
||||||
|
. ./.env
|
||||||
|
|
||||||
docker compose down -v
|
docker compose down -v
|
||||||
if [ "${DEV_DOCKER_ALWAYS_BUILD:-}" = 'true' ]; then
|
if [ "${DEV_DOCKER_ALWAYS_BUILD:-}" = 'true' ]; then
|
||||||
|
|
|
@ -45,8 +45,10 @@ deployment_strategy() {
|
||||||
echo "INFO detected NEW deployment"
|
echo "INFO detected NEW deployment"
|
||||||
./manage.py migrate
|
./manage.py migrate
|
||||||
|
|
||||||
printf "This is DEVELOPMENT/PILOTS_EARLY DEPLOYMENT: including demo hardcoded data\n creating initial Datas\n" >&2
|
printf "This is DEVELOPMENT/PILOTS_EARLY DEPLOYMENT: including demo hardcoded data\n" >&2
|
||||||
./manage.py initial_datas
|
|
||||||
|
PREDEFINED_TOKEN="${PREDEFINED_TOKEN:-}"
|
||||||
|
./manage.py demo_data "${PREDEFINED_TOKEN}"
|
||||||
|
|
||||||
if [ "${OIDC_ORGS:-}" ]; then
|
if [ "${OIDC_ORGS:-}" ]; then
|
||||||
config_oidc4vp
|
config_oidc4vp
|
||||||
|
|
1
examples/keys_did.json
Normal file
1
examples/keys_did.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"label": "DEMO", "key_material": "{\"kty\": \"OKP\", \"crv\": \"Ed25519\", \"x\": \"IRqDfIumhbKKHhqMjOngikQmGoT1cZ6LPP-JjXa8CsY\", \"d\": \"AZXUEnJYFbGcn3Ebzy3vQWYFzx6rdnoHKilaMYUWuHA\", \"kid\": \"Generated\"}"}
|
|
@ -7,34 +7,51 @@ from utils import credtools
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from decouple import config
|
from django.core.cache import cache
|
||||||
from idhub.models import Schemas
|
from django.urls import reverse
|
||||||
|
from pyvckit.did import (
|
||||||
|
generate_did,
|
||||||
|
gen_did_document,
|
||||||
|
)
|
||||||
|
|
||||||
|
from idhub.models import Schemas, DID
|
||||||
from oidc4vp.models import Organization
|
from oidc4vp.models import Organization
|
||||||
|
from webhook.models import Token
|
||||||
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Insert minimum datas for the project"
|
help = "Insert minimum data for the project"
|
||||||
DOMAIN = settings.DOMAIN
|
DOMAIN = settings.DOMAIN
|
||||||
OIDC_ORGS = settings.OIDC_ORGS
|
OIDC_ORGS = settings.OIDC_ORGS
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('predefined_token', nargs='?', default='', type=str, help='predefined token')
|
||||||
|
parser.add_argument('predefined_did', nargs='?', default='', type=str, help='predefined did')
|
||||||
|
|
||||||
def handle(self, *args, **kwargs):
|
def handle(self, *args, **kwargs):
|
||||||
ADMIN_EMAIL = settings.INITIAL_ADMIN_EMAIL
|
ADMIN_EMAIL = settings.INITIAL_ADMIN_EMAIL
|
||||||
ADMIN_PASSWORD = settings.INITIAL_ADMIN_PASSWORD
|
ADMIN_PASSWORD = settings.INITIAL_ADMIN_PASSWORD
|
||||||
|
self.predefined_token = kwargs['predefined_token']
|
||||||
self.create_admin_users(ADMIN_EMAIL, ADMIN_PASSWORD)
|
self.predefined_did = kwargs['predefined_did']
|
||||||
if settings.CREATE_TEST_USERS:
|
# on demo situation, encrypted vault is hardcoded with password DEMO
|
||||||
for u in range(1, 6):
|
cache.set("KEY_DIDS", "DEMO", None)
|
||||||
user = 'user{}@example.org'.format(u)
|
|
||||||
self.create_users(user, '1234')
|
|
||||||
|
|
||||||
self.org = Organization.objects.create(
|
self.org = Organization.objects.create(
|
||||||
name=self.DOMAIN,
|
name=self.DOMAIN,
|
||||||
domain=self.DOMAIN,
|
domain=self.DOMAIN,
|
||||||
main=True
|
main=True
|
||||||
)
|
)
|
||||||
|
self.org.set_encrypted_sensitive_data()
|
||||||
|
self.org.save()
|
||||||
|
|
||||||
|
self.create_admin_users(ADMIN_EMAIL, ADMIN_PASSWORD)
|
||||||
|
if settings.CREATE_TEST_USERS:
|
||||||
|
for u in range(1, 6):
|
||||||
|
user = 'user{}@example.org'.format(u)
|
||||||
|
self.create_users(user, '1234')
|
||||||
|
|
||||||
if self.OIDC_ORGS:
|
if self.OIDC_ORGS:
|
||||||
self.create_organizations()
|
self.create_organizations()
|
||||||
|
@ -45,6 +62,61 @@ class Command(BaseCommand):
|
||||||
su = User.objects.create_superuser(email=email, password=password)
|
su = User.objects.create_superuser(email=email, password=password)
|
||||||
su.save()
|
su.save()
|
||||||
|
|
||||||
|
if self.predefined_token:
|
||||||
|
tk = Token.objects.filter(token=self.predefined_token).first()
|
||||||
|
if not tk:
|
||||||
|
Token.objects.create(token=self.predefined_token)
|
||||||
|
|
||||||
|
self.create_default_did()
|
||||||
|
|
||||||
|
def create_default_did(self):
|
||||||
|
|
||||||
|
fdid = self.open_example_did()
|
||||||
|
if not fdid:
|
||||||
|
return
|
||||||
|
|
||||||
|
did = DID(type=DID.Types.WEB)
|
||||||
|
new_key_material = fdid.get("key_material", "")
|
||||||
|
label = fdid.get("label", "")
|
||||||
|
if not new_key_material:
|
||||||
|
return
|
||||||
|
|
||||||
|
did.set_key_material(new_key_material)
|
||||||
|
|
||||||
|
if label:
|
||||||
|
did.label = label
|
||||||
|
|
||||||
|
if did.type == did.Types.KEY:
|
||||||
|
did.did = generate_did(new_key_material)
|
||||||
|
elif did.type == did.Types.WEB:
|
||||||
|
url = "https://{}".format(settings.DOMAIN)
|
||||||
|
path = reverse("idhub:serve_did", args=["a"])
|
||||||
|
|
||||||
|
if path:
|
||||||
|
path = path.split("/a/did.json")[0]
|
||||||
|
url = "https://{}/{}".format(settings.DOMAIN, path)
|
||||||
|
|
||||||
|
did.did = generate_did(new_key_material, url)
|
||||||
|
key = json.loads(new_key_material)
|
||||||
|
url, did.didweb_document = gen_did_document(did.did, key)
|
||||||
|
|
||||||
|
did.save()
|
||||||
|
|
||||||
|
def open_example_did(self):
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent
|
||||||
|
didweb_path = os.path.join(BASE_DIR, "examples", "keys_did.json")
|
||||||
|
|
||||||
|
if self.predefined_did:
|
||||||
|
didweb_path = self.predefined_did
|
||||||
|
|
||||||
|
data = ''
|
||||||
|
with open(didweb_path) as _file:
|
||||||
|
try:
|
||||||
|
data = json.loads(_file.read())
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
def create_users(self, email, password):
|
def create_users(self, email, password):
|
||||||
u = User.objects.create(email=email, password=password)
|
u = User.objects.create(email=email, password=password)
|
|
@ -684,6 +684,14 @@ class VerificableCredential(models.Model):
|
||||||
if self.status == self.Status.ISSUED:
|
if self.status == self.Status.ISSUED:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
supported = False
|
||||||
|
for name in self.schema.get_schema.get("name"):
|
||||||
|
if name.get("value") in settings.SUPPORTED_CREDENTIALS:
|
||||||
|
supported = True
|
||||||
|
|
||||||
|
if not supported:
|
||||||
|
return
|
||||||
|
|
||||||
self.subject_did = did
|
self.subject_did = did
|
||||||
self.issued_on = datetime.datetime.now().astimezone(pytz.utc)
|
self.issued_on = datetime.datetime.now().astimezone(pytz.utc)
|
||||||
|
|
||||||
|
|
|
@ -179,8 +179,8 @@ class TermsAndConditionsView(UserView, FormView):
|
||||||
|
|
||||||
class WaitingView(UserView, TemplateView):
|
class WaitingView(UserView, TemplateView):
|
||||||
template_name = "idhub/user/waiting.html"
|
template_name = "idhub/user/waiting.html"
|
||||||
title = _("Comunication with admin")
|
title = _("Comunication with admin required")
|
||||||
subtitle = _('Service temporary close')
|
subtitle = _('Service temporarily closed')
|
||||||
section = ""
|
section = ""
|
||||||
icon = 'bi bi-file-earmark-medical'
|
icon = 'bi bi-file-earmark-medical'
|
||||||
success_url = reverse_lazy('idhub:user_dashboard')
|
success_url = reverse_lazy('idhub:user_dashboard')
|
||||||
|
|
|
@ -2796,11 +2796,11 @@ msgid "Data Protection"
|
||||||
msgstr "Protecció de dades"
|
msgstr "Protecció de dades"
|
||||||
|
|
||||||
#: idhub/user/views.py:183
|
#: idhub/user/views.py:183
|
||||||
msgid "Comunication with admin"
|
msgid "Comunication with admin required"
|
||||||
msgstr "Comunicació amb l'admin"
|
msgstr "Es requereix comunicació amb l'admin"
|
||||||
|
|
||||||
#: idhub/user/views.py:184
|
#: idhub/user/views.py:184
|
||||||
msgid "Service temporary close"
|
msgid "Service temporarily closed"
|
||||||
msgstr "Tancament temporal del servei"
|
msgstr "Tancament temporal del servei"
|
||||||
|
|
||||||
#: idhub/user/views.py:407
|
#: idhub/user/views.py:407
|
||||||
|
|
|
@ -2789,11 +2789,11 @@ msgid "Data Protection"
|
||||||
msgstr "Proteccion de datos"
|
msgstr "Proteccion de datos"
|
||||||
|
|
||||||
#: idhub/user/views.py:183
|
#: idhub/user/views.py:183
|
||||||
msgid "Comunication with admin"
|
msgid "Comunication with admin required"
|
||||||
msgstr "Comunicación con el admin"
|
msgstr "Se requiere comunicación con el admin"
|
||||||
|
|
||||||
#: idhub/user/views.py:184
|
#: idhub/user/views.py:184
|
||||||
msgid "Service temporary close"
|
msgid "Service temporarily closed"
|
||||||
msgstr "Cierre temporal del servicio"
|
msgstr "Cierre temporal del servicio"
|
||||||
|
|
||||||
#: idhub/user/views.py:407
|
#: idhub/user/views.py:407
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.views.generic.edit import DeleteView
|
from django.views.generic.edit import DeleteView
|
||||||
from django.views.generic.base import View
|
from django.views.generic.base import View
|
||||||
|
from django.core.cache import cache
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django_tables2 import SingleTableView
|
from django_tables2 import SingleTableView
|
||||||
from pyvckit.verify import verify_vp, verify_vc
|
from pyvckit.verify import verify_vp, verify_vc
|
||||||
|
@ -20,6 +21,10 @@ from webhook.tables import TokensTable
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def webhook_verify(request):
|
def webhook_verify(request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
user = User.objects.filter(is_admin=True).first()
|
||||||
|
if not cache.get("KEY_DIDS") or not user.accept_gdpr:
|
||||||
|
return JsonResponse({'error': 'Temporary out of service'}, status=400)
|
||||||
|
|
||||||
auth_header = request.headers.get('Authorization')
|
auth_header = request.headers.get('Authorization')
|
||||||
if not auth_header or not auth_header.startswith('Bearer '):
|
if not auth_header or not auth_header.startswith('Bearer '):
|
||||||
return JsonResponse({'error': 'Invalid or missing token'}, status=401)
|
return JsonResponse({'error': 'Invalid or missing token'}, status=401)
|
||||||
|
@ -56,6 +61,10 @@ def webhook_verify(request):
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def webhook_issue(request):
|
def webhook_issue(request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
user = User.objects.filter(is_admin=True).first()
|
||||||
|
if not cache.get("KEY_DIDS") or not user.accept_gdpr:
|
||||||
|
return JsonResponse({'error': 'Temporary out of service'}, status=400)
|
||||||
|
|
||||||
auth_header = request.headers.get('Authorization')
|
auth_header = request.headers.get('Authorization')
|
||||||
if not auth_header or not auth_header.startswith('Bearer '):
|
if not auth_header or not auth_header.startswith('Bearer '):
|
||||||
return JsonResponse({'error': 'Invalid or missing token'}, status=401)
|
return JsonResponse({'error': 'Invalid or missing token'}, status=401)
|
||||||
|
@ -89,7 +98,6 @@ def webhook_issue(request):
|
||||||
if not schema:
|
if not schema:
|
||||||
return JsonResponse({'error': 'Invalid credential'}, status=400)
|
return JsonResponse({'error': 'Invalid credential'}, status=400)
|
||||||
|
|
||||||
user = User.objects.filter(is_admin=True).first()
|
|
||||||
cred = VerificableCredential(
|
cred = VerificableCredential(
|
||||||
csv_data=vc,
|
csv_data=vc,
|
||||||
issuer_did=did,
|
issuer_did=did,
|
||||||
|
@ -100,6 +108,9 @@ def webhook_issue(request):
|
||||||
cred.set_type()
|
cred.set_type()
|
||||||
vc_signed = cred.issue(did, domain=request.get_host(), save=save)
|
vc_signed = cred.issue(did, domain=request.get_host(), save=save)
|
||||||
|
|
||||||
|
if not vc_signed:
|
||||||
|
return JsonResponse({'error': 'Invalid credential'}, status=400)
|
||||||
|
|
||||||
return JsonResponse({'status': 'success', "data": vc_signed}, status=200)
|
return JsonResponse({'status': 'success', "data": vc_signed}, status=200)
|
||||||
|
|
||||||
return JsonResponse({'status': 'fail'}, status=200)
|
return JsonResponse({'status': 'fail'}, status=200)
|
||||||
|
|
Loading…
Reference in a new issue