add predefined_token in initial_datas #6

Merged
pedro merged 11 commits from predefined_token into release 2025-01-29 17:09:50 +00:00
13 changed files with 142 additions and 43 deletions

View file

@ -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'

View file

@ -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}

View file

@ -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

View file

@ -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
View file

@ -0,0 +1 @@
{"label": "DEMO", "key_material": "{\"kty\": \"OKP\", \"crv\": \"Ed25519\", \"x\": \"IRqDfIumhbKKHhqMjOngikQmGoT1cZ6LPP-JjXa8CsY\", \"d\": \"AZXUEnJYFbGcn3Ebzy3vQWYFzx6rdnoHKilaMYUWuHA\", \"kid\": \"Generated\"}"}

View file

@ -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)

View file

@ -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)

View file

@ -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')

View file

@ -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

View file

@ -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

View file

@ -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)