From b357eccc80cf9eb686a79d1be4d9a316326a2688 Mon Sep 17 00:00:00 2001 From: Elijah Date: Sun, 3 Mar 2024 22:09:50 +0100 Subject: [PATCH 01/12] Added DOMAIN variable to CI pipeline --- .gitea/workflows/ci-pipeline.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitea/workflows/ci-pipeline.yaml b/.gitea/workflows/ci-pipeline.yaml index c67fadc..c850e25 100644 --- a/.gitea/workflows/ci-pipeline.yaml +++ b/.gitea/workflows/ci-pipeline.yaml @@ -20,6 +20,7 @@ jobs: SECRET_KEY: "t3st-dummy-s3cr3t-k3y" STATIC_ROOT: "tmp/static/" MEDIA_ROOT: "tmp/media/" + DOMAIN: "localhost" steps: - uses: actions/checkout@v4 From 30742ded1cc526a2d88500fc99080fbc3994be0e Mon Sep 17 00:00:00 2001 From: Elijah Date: Sun, 3 Mar 2024 22:17:44 +0100 Subject: [PATCH 02/12] Try to match domain to testserver --- .gitea/workflows/ci-pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/ci-pipeline.yaml b/.gitea/workflows/ci-pipeline.yaml index c850e25..28512e3 100644 --- a/.gitea/workflows/ci-pipeline.yaml +++ b/.gitea/workflows/ci-pipeline.yaml @@ -20,7 +20,7 @@ jobs: SECRET_KEY: "t3st-dummy-s3cr3t-k3y" STATIC_ROOT: "tmp/static/" MEDIA_ROOT: "tmp/media/" - DOMAIN: "localhost" + DOMAIN: "testserver" steps: - uses: actions/checkout@v4 From 5f2106ce53edbf6c2e2e4c9abe21f5198a0a3298 Mon Sep 17 00:00:00 2001 From: Elijah Date: Sun, 3 Mar 2024 22:31:56 +0100 Subject: [PATCH 03/12] edited domain var to localhost --- .gitea/workflows/ci-pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/ci-pipeline.yaml b/.gitea/workflows/ci-pipeline.yaml index 28512e3..c850e25 100644 --- a/.gitea/workflows/ci-pipeline.yaml +++ b/.gitea/workflows/ci-pipeline.yaml @@ -20,7 +20,7 @@ jobs: SECRET_KEY: "t3st-dummy-s3cr3t-k3y" STATIC_ROOT: "tmp/static/" MEDIA_ROOT: "tmp/media/" - DOMAIN: "testserver" + DOMAIN: "localhost" steps: - uses: actions/checkout@v4 From b7846fa2588011506a655cb2156b16fa97a3e134 Mon Sep 17 00:00:00 2001 From: Elijah Date: Sun, 3 Mar 2024 22:40:02 +0100 Subject: [PATCH 04/12] add checks to see if domain var correctly loads --- .gitea/workflows/ci-pipeline.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitea/workflows/ci-pipeline.yaml b/.gitea/workflows/ci-pipeline.yaml index c850e25..d6d647a 100644 --- a/.gitea/workflows/ci-pipeline.yaml +++ b/.gitea/workflows/ci-pipeline.yaml @@ -65,9 +65,14 @@ jobs: pip install -r requirements.txt if: steps.didkit.outcome == 'success' + - name: Check correct env vars + run: | + echo $DOMAIN + - name: Run tests run: | source venv/bin/activate + echo $DOMAIN python manage.py test ssikit-tests: From d0ecbf071630da68699a1c689e50308b3f89a120 Mon Sep 17 00:00:00 2001 From: Elijah Date: Sun, 3 Mar 2024 23:06:21 +0100 Subject: [PATCH 05/12] Changed domain var to testserver --- .gitea/workflows/ci-pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/ci-pipeline.yaml b/.gitea/workflows/ci-pipeline.yaml index d6d647a..dcb4343 100644 --- a/.gitea/workflows/ci-pipeline.yaml +++ b/.gitea/workflows/ci-pipeline.yaml @@ -20,7 +20,7 @@ jobs: SECRET_KEY: "t3st-dummy-s3cr3t-k3y" STATIC_ROOT: "tmp/static/" MEDIA_ROOT: "tmp/media/" - DOMAIN: "localhost" + DOMAIN: "testserver" steps: - uses: actions/checkout@v4 From 03c4dbae65c80b6d7b409c5d807e65f4b1d23b24 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 4 Mar 2024 09:44:53 +0100 Subject: [PATCH 06/12] remove RESPONSE_URI --- examples/organizations.csv | 10 ++-- idhub/management/commands/initial_datas.py | 47 ++++++++++++++----- idhub/management/commands/send_mail_admins.py | 5 +- idhub/models.py | 4 +- idhub/user/forms.py | 5 +- oidc4vp/models.py | 3 +- promotion/forms.py | 5 +- trustchain_idhub/settings.py | 18 ++++--- 8 files changed, 63 insertions(+), 34 deletions(-) diff --git a/examples/organizations.csv b/examples/organizations.csv index 2f447ef..8396d42 100644 --- a/examples/organizations.csv +++ b/examples/organizations.csv @@ -1,5 +1,5 @@ -"pangea.org";"https://idhub1.demo.pangea.org/oidc4vp/" -"somconnexio.coop";"https://idhub2.demo.pangea.org/oidc4vp/" -"exo.cat";"https://verify.exo.cat" -"local 9000";"http://localhost:9000/oidc4vp/" -"local 8000";"http://localhost:8000/oidc4vp/" +"pangea.org";"https://idhub1.demo.pangea.org/oidc4vp/";"idhub1.demo.pangea.org" +"somconnexio.coop";"https://idhub2.demo.pangea.org/oidc4vp/";"idhub2.demo.pangea.org" +"exo.cat";"https://verify.exo.cat";"verify.exo.cat" +"local 8000";"http://localhost/oidc4vp/";"localhost" +"local 9000";"http://localhost1/oidc4vp/";"localhost1" diff --git a/idhub/management/commands/initial_datas.py b/idhub/management/commands/initial_datas.py index da3539e..dfc0be8 100644 --- a/idhub/management/commands/initial_datas.py +++ b/idhub/management/commands/initial_datas.py @@ -17,6 +17,8 @@ User = get_user_model() class Command(BaseCommand): help = "Insert minimum datas for the project" + DOMAIN = settings.DOMAIN + OIDC_ORGS = settings.OIDC_ORGS def handle(self, *args, **kwargs): ADMIN_EMAIL = config('ADMIN_EMAIL', 'admin@example.org') @@ -28,16 +30,15 @@ class Command(BaseCommand): user = 'user{}@example.org'.format(u) self.create_users(user, '1234') - BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent - ORGANIZATION = os.path.join(BASE_DIR, settings.ORG_FILE) - with open(ORGANIZATION, newline='\n') as csvfile: - f = csv.reader(csvfile, delimiter=';', quotechar='"') - for r in f: - self.create_organizations(r[0].strip(), r[1].strip()) + self.org = Organization.objects.create( + name=self.DOMAIN, + domain=self.DOMAIN, + main=True + ) + + if self.OIDC_ORGS: + self.create_organizations() - if settings.SYNC_ORG_DEV == 'y': - self.sync_credentials_organizations("pangea.org", "somconnexio.coop") - self.sync_credentials_organizations("local 8000", "local 9000") self.create_schemas() def create_admin_users(self, email, password): @@ -50,12 +51,32 @@ class Command(BaseCommand): u.set_password(password) u.save() + def create_organizations(self): + BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent + ORGANIZATION = os.path.join(BASE_DIR, self.OIDC_ORGS) + DOMAIN = self.DOMAIN - def create_organizations(self, name, url): - if url == settings.RESPONSE_URI: - Organization.objects.create(name=name, response_uri=url, main=True) + with open(ORGANIZATION, newline='\n') as csvfile: + f = csv.reader(csvfile, delimiter=';', quotechar='"') + exist_main_domain = False + for r in f: + if DOMAIN == r[2].strip(): + exist_main_domain = True + self.create_one_organization(r[0].strip(), r[1].strip(), r[2].strip()) + + assert exist_main_domain, f"{DOMAIN} is not in {ORGANIZATION}" + + if settings.SYNC_ORG_DEV == 'y': + self.sync_credentials_organizations("pangea.org", "somconnexio.coop") + self.sync_credentials_organizations("local 8000", "local 9000") + + def create_one_organization(self, name, url, domain): + if self.DOMAIN == domain: + self.org.name = name + self.org.response_uri = url + self.org.save() else: - Organization.objects.create(name=name, response_uri=url) + Organization.objects.create(name=name, response_uri=url, domain=domain) def sync_credentials_organizations(self, test1, test2): org1 = Organization.objects.get(name=test1) diff --git a/idhub/management/commands/send_mail_admins.py b/idhub/management/commands/send_mail_admins.py index 0ef24f8..eae3e41 100644 --- a/idhub/management/commands/send_mail_admins.py +++ b/idhub/management/commands/send_mail_admins.py @@ -27,10 +27,9 @@ class Command(BaseCommand): """ Send a email when a user is activated. """ - parsed_url = urlparse(settings.RESPONSE_URI) - domain = f"{parsed_url.scheme}://{parsed_url.netloc}/" + url_domain = f"https://{}/".format(settings.DOMAIN) context = { - "domain": domain, + "domain": url_domain, } subject = loader.render_to_string(self.subject_template_name, context) # Email subject *must not* contain newlines diff --git a/idhub/models.py b/idhub/models.py index 1072e26..2eae07f 100644 --- a/idhub/models.py +++ b/idhub/models.py @@ -670,7 +670,7 @@ class VerificableCredential(models.Model): credential_subject = ujson.loads(data).get("credentialSubject", {}) return credential_subject.items() - def issue(self, did, domain=settings.DOMAIN.strip("/")): + def issue(self, did, domain): if self.status == self.Status.ISSUED: return @@ -704,7 +704,7 @@ class VerificableCredential(models.Model): cred_path = 'public/credentials' sid = self.hash - url_id = "{}/{}/{}".format( + url_id = "https://{}/{}/{}".format( domain, cred_path, sid diff --git a/idhub/user/forms.py b/idhub/user/forms.py index 81c36a7..654a936 100644 --- a/idhub/user/forms.py +++ b/idhub/user/forms.py @@ -132,8 +132,9 @@ class DemandAuthorizationForm(forms.Form): self.user = kwargs.pop('user', None) super().__init__(*args, **kwargs) self.fields['organization'].choices = [ - (x.id, x.name) for x in Organization.objects.filter() - if x.response_uri != settings.RESPONSE_URI + (x.id, x.name) for x in Organization.objects.exclude( + domain=settings.DOMAIN + ) ] def save(self, commit=True): diff --git a/oidc4vp/models.py b/oidc4vp/models.py index 8cfdfaf..d3a454f 100644 --- a/oidc4vp/models.py +++ b/oidc4vp/models.py @@ -51,6 +51,7 @@ class Organization(models.Model): main is a field which indicates the organization of this idhub """ name = models.CharField(max_length=250) + domain = models.CharField(max_length=250, null=True, default=None) main = models.BooleanField(default=False) client_id = models.CharField( max_length=24, @@ -94,7 +95,7 @@ class Organization(models.Model): """ url = "{url}/verify?demand_uri={redirect_uri}".format( url=self.response_uri.strip("/"), - redirect_uri=settings.RESPONSE_URI + redirect_uri=self.response_uri ) auth = (self.my_client_id, self.my_client_secret) return requests.get(url, auth=auth) diff --git a/promotion/forms.py b/promotion/forms.py index 30dce87..b9f9e1a 100644 --- a/promotion/forms.py +++ b/promotion/forms.py @@ -23,8 +23,9 @@ class WalletForm(forms.Form): self.presentation_definition = kwargs.pop('presentation_definition', []) super().__init__(*args, **kwargs) self.fields['organization'].choices = [ - (x.id, x.name) for x in Organization.objects.filter() - if x.response_uri != settings.RESPONSE_URI + (x.id, x.name) for x in Organization.objects.exclude( + domain=settings.DOMAIN + ) ] def save(self, commit=True): diff --git a/trustchain_idhub/settings.py b/trustchain_idhub/settings.py index 090be76..a37b737 100644 --- a/trustchain_idhub/settings.py +++ b/trustchain_idhub/settings.py @@ -32,12 +32,14 @@ SECRET_KEY = config('SECRET_KEY') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = config('DEBUG', default=False, cast=bool) -ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='', cast=Csv()) -CSRF_TRUSTED_ORIGINS = config('CSRF_TRUSTED_ORIGINS', default='', cast=Csv()) - DOMAIN = config("DOMAIN") assert DOMAIN not in [None, ''], "DOMAIN var is MANDATORY" +ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=DOMAIN, cast=Csv()) +assert DOMAIN in ALLOWED_HOSTS, "DOMAIN is not ALLOWED_HOST" + +CSRF_TRUSTED_ORIGINS = config('CSRF_TRUSTED_ORIGINS', default=f'https://{DOMAIN}', cast=Csv()) + DEFAULT_FROM_EMAIL = config( 'DEFAULT_FROM_EMAIL', default='webmaster@localhost') @@ -201,8 +203,12 @@ USE_I18N = True USE_L10N = True AUTH_USER_MODEL = 'idhub_auth.User' -RESPONSE_URI = config('RESPONSE_URI', default="") -ALLOW_CODE_URI= config('ALLOW_CODE_URI', default="") + +ALLOW_CODE_URI= config( + 'ALLOW_CODE_URI', + default=f"https://{DOMAIN}/allow_code" +) + SUPPORTED_CREDENTIALS = config( 'SUPPORTED_CREDENTIALS', default='[]', @@ -222,7 +228,7 @@ LOGGING = { } SYNC_ORG_DEV = config('SYNC_ORG_DEV', 'y') -ORG_FILE = config('ORG_FILE', 'examples/organizations.csv') +OIDC_ORGS = config('OIDC_ORGS', 'examples/organizations.csv') ENABLE_EMAIL = config('ENABLE_EMAIL', default=True, cast=bool) CREATE_TEST_USERS = config('CREATE_TEST_USERS', default=False, cast=bool) ENABLE_2FACTOR_AUTH = config('ENABLE_2FACTOR_AUTH', default=True, cast=bool) From c3db60dbf459e438251ef9c0d5784c163a161553 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 4 Mar 2024 10:30:42 +0100 Subject: [PATCH 07/12] OIDC_REDIRECT --- oidc4vp/models.py | 2 +- trustchain_idhub/settings.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/oidc4vp/models.py b/oidc4vp/models.py index d3a454f..916e1d6 100644 --- a/oidc4vp/models.py +++ b/oidc4vp/models.py @@ -285,7 +285,7 @@ class OAuth2VPToken(models.Model): return response def get_redirect_url(self): - if not settings.ALLOW_CODE_URI: + if not settings.OIDC_REDIRECT: return data = { diff --git a/trustchain_idhub/settings.py b/trustchain_idhub/settings.py index a37b737..b782bdf 100644 --- a/trustchain_idhub/settings.py +++ b/trustchain_idhub/settings.py @@ -204,7 +204,8 @@ USE_L10N = True AUTH_USER_MODEL = 'idhub_auth.User' -ALLOW_CODE_URI= config( +OIDC_REDIRECT = config('OIDC_REDIRECT', default=False, cast=bool) +ALLOW_CODE_URI = config( 'ALLOW_CODE_URI', default=f"https://{DOMAIN}/allow_code" ) From da4eaf4aa94e9ad5736033c7bb2633b8a697181f Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 4 Mar 2024 18:56:28 +0100 Subject: [PATCH 08/12] add migrations --- oidc4vp/migrations/0004_organization_domain.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 oidc4vp/migrations/0004_organization_domain.py diff --git a/oidc4vp/migrations/0004_organization_domain.py b/oidc4vp/migrations/0004_organization_domain.py new file mode 100644 index 0000000..fda0103 --- /dev/null +++ b/oidc4vp/migrations/0004_organization_domain.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.5 on 2024-03-01 14:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('oidc4vp', '0003_organization_main'), + ] + + operations = [ + migrations.AddField( + model_name='organization', + name='domain', + field=models.CharField(default=None, max_length=250, null=True), + ), + ] From f7bb2bc99119ddce86508e2ca38178d1e8ed10e6 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 4 Mar 2024 19:00:44 +0100 Subject: [PATCH 09/12] fix tests --- idhub/tests/test_credentials.py | 3 +-- idhub/tests/test_views.py | 6 ++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/idhub/tests/test_credentials.py b/idhub/tests/test_credentials.py index c6a76ab..659c5ba 100644 --- a/idhub/tests/test_credentials.py +++ b/idhub/tests/test_credentials.py @@ -2,7 +2,7 @@ import os import json from pathlib import Path -from django.test import TestCase, RequestFactory +from django.test import TestCase from django.core.files.uploadedfile import SimpleUploadedFile from django.core.cache import cache from django.urls import reverse @@ -11,7 +11,6 @@ from django.conf import settings from idhub_auth.models import User from idhub.models import DID, Schemas from oidc4vp.models import Organization -from idhub.admin.views import PeopleListView class AdminDashboardViewTest(TestCase): diff --git a/idhub/tests/test_views.py b/idhub/tests/test_views.py index 10e5b24..37a6df1 100644 --- a/idhub/tests/test_views.py +++ b/idhub/tests/test_views.py @@ -1,9 +1,11 @@ from django.test import TestCase, RequestFactory from django.core.cache import cache from django.urls import reverse +from django.conf import settings from idhub_auth.models import User from idhub.models import Event +from oidc4vp.models import Organization from idhub.admin.views import PeopleListView @@ -23,6 +25,10 @@ class AdminDashboardViewTest(TestCase): password='adminpass12') self.admin_user.accept_gdpr=True self.admin_user.save() + self.org = Organization.objects.create(name="testserver", main=True) + + settings.DOMAIN = self.org.name + settings.ENABLE_EMAIL = False def test_view_url_exists_at_desired_location(self): response = self.client.get('/admin/dashboard/', follow=True) From d8303596334b4f1e282fafa590eba6142eb61cd6 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Tue, 5 Mar 2024 10:56:41 +0100 Subject: [PATCH 10/12] OIDC_ORGS as OIDC_SETUP --- trustchain_idhub/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trustchain_idhub/settings.py b/trustchain_idhub/settings.py index b782bdf..ed19a4c 100644 --- a/trustchain_idhub/settings.py +++ b/trustchain_idhub/settings.py @@ -229,7 +229,7 @@ LOGGING = { } SYNC_ORG_DEV = config('SYNC_ORG_DEV', 'y') -OIDC_ORGS = config('OIDC_ORGS', 'examples/organizations.csv') +OIDC_ORGS = config('OIDC_ORGS', '') ENABLE_EMAIL = config('ENABLE_EMAIL', default=True, cast=bool) CREATE_TEST_USERS = config('CREATE_TEST_USERS', default=False, cast=bool) ENABLE_2FACTOR_AUTH = config('ENABLE_2FACTOR_AUTH', default=True, cast=bool) From 5d45a6eefe8ed32528ba80fb3f4f86f93b3e9629 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Tue, 5 Mar 2024 11:45:12 +0100 Subject: [PATCH 11/12] fix send_mail_admins --- idhub/management/commands/send_mail_admins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idhub/management/commands/send_mail_admins.py b/idhub/management/commands/send_mail_admins.py index eae3e41..a878456 100644 --- a/idhub/management/commands/send_mail_admins.py +++ b/idhub/management/commands/send_mail_admins.py @@ -27,7 +27,7 @@ class Command(BaseCommand): """ Send a email when a user is activated. """ - url_domain = f"https://{}/".format(settings.DOMAIN) + url_domain = "https://{}/".format(settings.DOMAIN) context = { "domain": url_domain, } From be68feed622fb105d313014e7405cdacd292b4d6 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Tue, 5 Mar 2024 12:16:14 +0100 Subject: [PATCH 12/12] fix 158 --- schemas/course-credential.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas/course-credential.json b/schemas/course-credential.json index f5fed93..b5dc490 100644 --- a/schemas/course-credential.json +++ b/schemas/course-credential.json @@ -1,5 +1,5 @@ { - "$id": "https://idhub.pangea.org/vc_schemas/course-credential", + "$id": "https://idhub.pangea.org/vc_schemas/course-credential.json", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "NGO Course Credential Schema", "description": "A NGO Course Credential Schema awarded by a NGO federation and their NGO members, as proposed by Lafede.cat",