diff --git a/src/aap_eda/api/serializers/activation.py b/src/aap_eda/api/serializers/activation.py index 207f5b082..c8a23bf07 100644 --- a/src/aap_eda/api/serializers/activation.py +++ b/src/aap_eda/api/serializers/activation.py @@ -440,8 +440,8 @@ class Meta: ] organization_id = serializers.IntegerField( - required=False, - allow_null=True, + required=True, + allow_null=False, validators=[validators.check_if_organization_exists], ) rulebook_id = serializers.IntegerField( diff --git a/src/aap_eda/api/serializers/decision_environment.py b/src/aap_eda/api/serializers/decision_environment.py index a2e4b13c3..c11506760 100644 --- a/src/aap_eda/api/serializers/decision_environment.py +++ b/src/aap_eda/api/serializers/decision_environment.py @@ -41,8 +41,8 @@ class DecisionEnvironmentCreateSerializer(serializers.ModelSerializer): """Serializer for creating the DecisionEnvironment.""" organization_id = serializers.IntegerField( - required=False, - allow_null=True, + required=True, + allow_null=False, validators=[validators.check_if_organization_exists], ) eda_credential_id = serializers.IntegerField( diff --git a/src/aap_eda/api/serializers/eda_credential.py b/src/aap_eda/api/serializers/eda_credential.py index 485569707..57e5f87ec 100644 --- a/src/aap_eda/api/serializers/eda_credential.py +++ b/src/aap_eda/api/serializers/eda_credential.py @@ -107,8 +107,8 @@ class EdaCredentialCreateSerializer(serializers.ModelSerializer): validators=[validators.check_if_credential_type_exists], ) organization_id = serializers.IntegerField( - required=False, - allow_null=True, + required=True, + allow_null=False, validators=[validators.check_if_organization_exists], ) inputs = serializers.JSONField() diff --git a/src/aap_eda/api/serializers/project.py b/src/aap_eda/api/serializers/project.py index 1a9ff50fb..1cb99f590 100644 --- a/src/aap_eda/api/serializers/project.py +++ b/src/aap_eda/api/serializers/project.py @@ -71,8 +71,8 @@ class Meta: class ProjectCreateRequestSerializer(serializers.ModelSerializer): organization_id = serializers.IntegerField( - required=False, - allow_null=True, + required=True, + allow_null=False, validators=[validators.check_if_organization_exists], ) eda_credential_id = serializers.IntegerField( @@ -107,7 +107,7 @@ class Meta: class ProjectUpdateRequestSerializer(serializers.ModelSerializer): organization_id = serializers.IntegerField( - required=False, + required=True, allow_null=False, validators=[validators.check_if_organization_exists], ) diff --git a/src/aap_eda/api/serializers/team.py b/src/aap_eda/api/serializers/team.py index ec8aeebb8..14aee9005 100644 --- a/src/aap_eda/api/serializers/team.py +++ b/src/aap_eda/api/serializers/team.py @@ -44,6 +44,7 @@ class TeamCreateSerializer( ): organization_id = serializers.IntegerField( required=True, + allow_null=False, validators=[validators.check_if_organization_exists], ) diff --git a/src/aap_eda/api/serializers/webhook.py b/src/aap_eda/api/serializers/webhook.py index f97d76ac7..9b71ac188 100644 --- a/src/aap_eda/api/serializers/webhook.py +++ b/src/aap_eda/api/serializers/webhook.py @@ -21,7 +21,7 @@ class WebhookInSerializer(serializers.ModelSerializer): - organization_id = serializers.IntegerField(required=False, allow_null=True) + organization_id = serializers.IntegerField(required=True, allow_null=False) owner = serializers.HiddenField(default=serializers.CurrentUserDefault()) eda_credential_id = serializers.IntegerField( required=True, diff --git a/src/aap_eda/core/migrations/0046_alter_activation_organization_and_more.py b/src/aap_eda/core/migrations/0046_alter_activation_organization_and_more.py new file mode 100644 index 000000000..8cc77e49d --- /dev/null +++ b/src/aap_eda/core/migrations/0046_alter_activation_organization_and_more.py @@ -0,0 +1,87 @@ +# Generated by Django 4.2.7 on 2024-08-14 18:15 + +import django.db.models.deletion +from django.db import migrations, models + +import aap_eda.core.models.utils + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0045_activation_skip_audit_events"), + ] + + operations = [ + migrations.AlterField( + model_name="activation", + name="organization", + field=models.ForeignKey( + default=aap_eda.core.models.utils.get_default_organization_id, + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="auditrule", + name="organization", + field=models.ForeignKey( + default=aap_eda.core.models.utils.get_default_organization_id, + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="decisionenvironment", + name="organization", + field=models.ForeignKey( + default=aap_eda.core.models.utils.get_default_organization_id, + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="edacredential", + name="organization", + field=models.ForeignKey( + default=aap_eda.core.models.utils.get_default_organization_id, + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="project", + name="organization", + field=models.ForeignKey( + default=aap_eda.core.models.utils.get_default_organization_id, + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="rulebook", + name="organization", + field=models.ForeignKey( + default=aap_eda.core.models.utils.get_default_organization_id, + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="rulebookprocess", + name="organization", + field=models.ForeignKey( + default=aap_eda.core.models.utils.get_default_organization_id, + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="webhook", + name="organization", + field=models.ForeignKey( + default=aap_eda.core.models.utils.get_default_organization_id, + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + ] diff --git a/src/aap_eda/core/models/base.py b/src/aap_eda/core/models/base.py index 8887ce901..a5428be62 100644 --- a/src/aap_eda/core/models/base.py +++ b/src/aap_eda/core/models/base.py @@ -26,8 +26,9 @@ class Meta: organization = models.ForeignKey( "Organization", on_delete=models.CASCADE, + blank=False, + null=False, default=get_default_organization_id, - null=True, ) diff --git a/tests/integration/api/test_activation.py b/tests/integration/api/test_activation.py index 09b1e4444..9c9e55313 100644 --- a/tests/integration/api/test_activation.py +++ b/tests/integration/api/test_activation.py @@ -46,7 +46,7 @@ def test_create_activation( response = admin_client.post( f"{api_url_v1}/activations/", data=activation_payload ) - assert response.status_code == status.HTTP_201_CREATED + assert response.status_code == status.HTTP_201_CREATED, response.data data = response.data activation = models.Activation.objects.filter(id=data["id"]).first() assert_activation_base_data( diff --git a/tests/integration/api/test_activation_with_credential.py b/tests/integration/api/test_activation_with_credential.py index b193e692c..25baecb92 100644 --- a/tests/integration/api/test_activation_with_credential.py +++ b/tests/integration/api/test_activation_with_credential.py @@ -94,6 +94,7 @@ def kafka_credential_type() -> models.CredentialType: @pytest.mark.django_db def test_validate_for_aap_credential( default_activation: models.Activation, + default_organization: models.Organization, inputs, result, preseed_credential_types, @@ -106,6 +107,7 @@ def test_validate_for_aap_credential( inputs=inputs, managed=False, credential_type_id=aap_credential_type.id, + organization=default_organization, ) default_activation.eda_credentials.add(credential) @@ -120,6 +122,7 @@ def test_is_activation_valid_with_token_and_run_job_template( default_project: models.Project, default_user_awx_token: models.AwxToken, default_user: models.User, + default_organization: models.Organization, preseed_credential_types, ): activation = models.Activation.objects.create( @@ -130,6 +133,7 @@ def test_is_activation_valid_with_token_and_run_job_template( project_id=default_project.id, awx_token_id=default_user_awx_token.id, user_id=default_user.id, + organization=default_organization, ) valid, _ = is_activation_valid(activation) @@ -139,6 +143,7 @@ def test_is_activation_valid_with_token_and_run_job_template( @pytest.mark.django_db def test_is_activation_valid_with_aap_credential_and_run_job_template( default_activation: models.Activation, + default_organization: models.Organization, preseed_credential_types, ): aap_credential_type = models.CredentialType.objects.get( @@ -149,6 +154,7 @@ def test_is_activation_valid_with_aap_credential_and_run_job_template( inputs={"username": "adam", "password": "secret"}, managed=False, credential_type_id=aap_credential_type.id, + organization=default_organization, ) default_activation.eda_credentials.add(credential) @@ -163,6 +169,7 @@ def test_is_activation_valid_with_run_job_template_and_no_token_no_credential( default_rulebook_with_run_job_template: models.Rulebook, default_project: models.Project, default_user: models.User, + default_organization: models.Organization, preseed_credential_types, ): activation = models.Activation.objects.create( @@ -172,6 +179,7 @@ def test_is_activation_valid_with_run_job_template_and_no_token_no_credential( decision_environment_id=default_decision_environment.id, project_id=default_project.id, user_id=default_user.id, + organization=default_organization, ) valid, message = is_activation_valid(activation) @@ -247,6 +255,7 @@ def test_create_activation_with_eda_credentials( preseed_credential_types, credential_type, status_code, + default_organization: models.Organization, ): credential_type = models.CredentialType.objects.get(name=credential_type) @@ -257,6 +266,7 @@ def test_create_activation_with_eda_credentials( inputs=inputs_to_store( {"username": "dummy-user", "password": "dummy-password"} ), + organization=default_organization, ) kafka_eda_credential = models.EdaCredential.objects.create( name="kafka-eda-credential", @@ -264,6 +274,7 @@ def test_create_activation_with_eda_credentials( {"sasl_username": "adam", "sasl_password": "secret"}, ), credential_type=kafka_credential_type, + organization=default_organization, ) test_activation = { "name": "test_activation", @@ -272,6 +283,7 @@ def test_create_activation_with_eda_credentials( ], "rulebook_id": activation_payload["rulebook_id"], "eda_credentials": [credential.id, kafka_eda_credential.id], + "organization_id": default_organization.id, } response = admin_client.post( @@ -315,6 +327,7 @@ def test_create_activation_with_key_conflict( default_decision_environment: models.DecisionEnvironment, default_rulebook: models.Rulebook, kafka_credential_type: models.CredentialType, + default_organization: models.Organization, preseed_credential_types, ): test_activation = { @@ -322,12 +335,14 @@ def test_create_activation_with_key_conflict( "decision_environment_id": default_decision_environment.id, "rulebook_id": default_rulebook.id, "extra_var": OVERLAP_EXTRA_VAR, + "organization_id": default_organization.id, } test_eda_credential = models.EdaCredential.objects.create( name="eda-credential", inputs={"sasl_username": "adam", "sasl_password": "secret"}, credential_type_id=kafka_credential_type.id, + organization=default_organization, ) test_activation["eda_credentials"] = [test_eda_credential.id] @@ -347,6 +362,7 @@ def test_create_activation_with_conflict_credentials( admin_client: APIClient, activation_payload: Dict[str, Any], user_credential_type: models.CredentialType, + default_organization: models.Organization, preseed_credential_types, ): test_activation = { @@ -355,6 +371,7 @@ def test_create_activation_with_conflict_credentials( "decision_environment_id" ], "rulebook_id": activation_payload["rulebook_id"], + "organization_id": default_organization.id, } eda_credentials = models.EdaCredential.objects.bulk_create( @@ -392,6 +409,7 @@ def test_create_activation_without_extra_vars_single_credential( default_decision_environment: models.DecisionEnvironment, default_rulebook: models.Rulebook, user_credential_type: models.CredentialType, + default_organization: models.Organization, preseed_credential_types, ): test_activation = { @@ -399,12 +417,14 @@ def test_create_activation_without_extra_vars_single_credential( "decision_environment_id": default_decision_environment.id, "rulebook_id": default_rulebook.id, "extra_var": None, + "organization_id": default_organization.id, } eda_credential = models.EdaCredential.objects.create( name="credential-1", inputs={"sasl_username": "adam", "sasl_password": "secret"}, credential_type_id=user_credential_type.id, + organization=default_organization, ) eda_credential_ids = [eda_credential.id] @@ -427,12 +447,14 @@ def test_create_activation_without_extra_vars_duplicate_credentials( default_decision_environment: models.DecisionEnvironment, default_rulebook: models.Rulebook, user_credential_type: models.CredentialType, + default_organization: models.Organization, preseed_credential_types, ): test_activation = { "name": "test_activation", "decision_environment_id": default_decision_environment.id, "rulebook_id": default_rulebook.id, + "organization_id": default_organization.id, } eda_credentials = models.EdaCredential.objects.bulk_create( @@ -441,11 +463,13 @@ def test_create_activation_without_extra_vars_duplicate_credentials( name="credential-1", inputs={"sasl_username": "adam", "sasl_password": "secret"}, credential_type_id=user_credential_type.id, + organization=default_organization, ), models.EdaCredential( name="credential-2", inputs={"sasl_username": "bearny", "sasl_password": "demo"}, credential_type_id=user_credential_type.id, + organization=default_organization, ), ] ) diff --git a/tests/integration/api/test_activation_with_webhook.py b/tests/integration/api/test_activation_with_webhook.py index 2a2c194a1..3b2c3ac01 100644 --- a/tests/integration/api/test_activation_with_webhook.py +++ b/tests/integration/api/test_activation_with_webhook.py @@ -11,21 +11,26 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + +# TODO(doston): this entire test module needs to be updated to use fixtures + import secrets import uuid import pytest import yaml +from django.conf import settings from rest_framework import status from rest_framework.test import APIClient from aap_eda.api.constants import SOURCE_MAPPING_ERROR_KEY -from aap_eda.core import models +from aap_eda.core import enums, models from aap_eda.core.enums import ( ACTIVATION_STATUS_MESSAGE_MAP, ActivationStatus, RestartPolicy, ) +from aap_eda.core.utils.credentials import inputs_to_store from aap_eda.core.utils.rulebook import ( DEFAULT_SOURCE_NAME_PREFIX, get_rulebook_hash, @@ -167,18 +172,32 @@ def create_activation_related_data( token=TEST_AWX_TOKEN["token"], user=user, ) - credential_id = models.Credential.objects.create( - name="test-credential", - description="test credential", - credential_type="Container Registry", - username="dummy-user", - secret=secrets.token_hex(32), + organization = models.Organization.objects.get_or_create( + name=settings.DEFAULT_ORGANIZATION_NAME, + description="The default organization", + )[0] + registry_credential_type = models.CredentialType.objects.get( + name=enums.DefaultCredentialType.REGISTRY + ) + credential_id = models.EdaCredential.objects.create( + name="eda-credential", + description="Default Registry Credential", + credential_type=registry_credential_type, + inputs=inputs_to_store( + { + "username": "dummy-user", + "password": "dummy-password", + "host": "quay.io", + } + ), + organization=organization, ).pk decision_environment_id = models.DecisionEnvironment.objects.create( name=TEST_DECISION_ENV["name"], image_url=TEST_DECISION_ENV["image_url"], description=TEST_DECISION_ENV["description"], - credential_id=credential_id, + eda_credential_id=credential_id, + organization=organization, ).pk project_id = ( models.Project.objects.create( @@ -186,6 +205,7 @@ def create_activation_related_data( name=TEST_PROJECT["name"], url=TEST_PROJECT["url"], description=TEST_PROJECT["description"], + organization=organization, ).pk if with_project else None @@ -196,6 +216,7 @@ def create_activation_related_data( description=TEST_RULEBOOK["description"], rulesets=rulesets, project_id=project_id, + organization=organization, ).pk if with_project else None @@ -207,6 +228,7 @@ def create_activation_related_data( uuid=uuid.uuid4(), name=name, owner=user, + organization=organization, ) webhooks.append(webhook) @@ -218,6 +240,7 @@ def create_activation_related_data( "extra_var": TEST_EXTRA_VAR, "credential_id": credential_id, "webhooks": webhooks, + "organization_id": organization.id, } @@ -227,6 +250,7 @@ def create_activation(fks: dict): activation_data["project_id"] = fks["project_id"] activation_data["rulebook_id"] = fks["rulebook_id"] activation_data["user_id"] = fks["user_id"] + activation_data["organization_id"] = fks["organization_id"] activation = models.Activation(**activation_data) activation.save() for webhook in fks["webhooks"]: @@ -243,6 +267,7 @@ def test_create_activation_with_webhooks( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] source_mappings = [] for webhook in fks["webhooks"]: source_mappings.append( @@ -322,6 +347,7 @@ def test_create_activation_with_bad_format_in_mappings( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] test_activation["source_mappings"] = "bad_format" admin_client.post( @@ -344,6 +370,7 @@ def test_create_activation_with_corrupted_mappings( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] test_activation["source_mappings"] = "corrupted\n key: value\n" admin_client.post( @@ -366,6 +393,7 @@ def test_create_activation_with_missing_keys_in_mappings( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] source_mappings = [ { "webhook_name": "fake", @@ -395,6 +423,7 @@ def test_create_activation_with_bad_webhook( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] source_mappings = [ { "webhook_name": "fake", @@ -426,6 +455,7 @@ def test_create_activation_with_bad_webhook_name( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] source_mappings = [ { "webhook_name": "missing_name", @@ -457,6 +487,7 @@ def test_create_activation_with_bad_rulebook_hash( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] source_mappings = [ { "webhook_name": fks["webhooks"][0].name, @@ -490,6 +521,7 @@ def test_create_activation_with_duplicate_source_name( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] source_mappings = [ { "webhook_name": fks["webhooks"][0].name, @@ -531,6 +563,7 @@ def test_create_activation_with_duplicate_webhook_name( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] source_mappings = [ { "webhook_name": fks["webhooks"][0].name, @@ -630,6 +663,7 @@ def test_bad_src_activation_with_webhooks( test_activation = TEST_ACTIVATION.copy() test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] source_mappings = [] diff --git a/tests/integration/api/test_eda_credential.py b/tests/integration/api/test_eda_credential.py index f14de0f52..6833f4388 100644 --- a/tests/integration/api/test_eda_credential.py +++ b/tests/integration/api/test_eda_credential.py @@ -56,6 +56,7 @@ def test_create_eda_credential( admin_client: APIClient, credential_type: models.CredentialType, + default_organization: models.Organization, inputs, status_code, status_message, @@ -64,6 +65,7 @@ def test_create_eda_credential( "name": "eda-credential", "inputs": inputs, "credential_type_id": credential_type.id, + "organization_id": default_organization.id, } response = admin_client.post( f"{api_url_v1}/eda-credentials/", data=data_in @@ -98,6 +100,7 @@ def test_create_eda_credential( @pytest.mark.django_db def test_create_eda_credential_with_gpg_key_data( admin_client: APIClient, + default_organization: models.Organization, preseed_credential_types, key_file, status_code, @@ -113,6 +116,7 @@ def test_create_eda_credential_with_gpg_key_data( "name": "eda-credential", "inputs": {"gpg_public_key": key_data}, "credential_type_id": gpg_type.id, + "organization_id": default_organization.id, } response = admin_client.post( f"{api_url_v1}/eda-credentials/", data=data_in @@ -162,6 +166,7 @@ def test_create_eda_credential_with_gpg_key_data( @pytest.mark.django_db def test_create_eda_credential_with_empty_inputs_fields( admin_client: APIClient, + default_organization: models.Organization, preseed_credential_types, credential_type, status_code, @@ -174,6 +179,7 @@ def test_create_eda_credential_with_empty_inputs_fields( "name": f"eda-credential-{credential_type}", "inputs": {}, "credential_type_id": credential_type.id, + "organization_id": default_organization.id, } response = admin_client.post( f"{api_url_v1}/eda-credentials/", data=data_in @@ -185,13 +191,16 @@ def test_create_eda_credential_with_empty_inputs_fields( @pytest.mark.django_db def test_retrieve_eda_credential( - admin_client: APIClient, credential_type: models.CredentialType + admin_client: APIClient, + credential_type: models.CredentialType, + default_organization: models.Organization, ): obj = models.EdaCredential.objects.create( name="eda_credential", inputs={"username": "adam", "password": "secret"}, managed=False, credential_type_id=credential_type.id, + organization=default_organization, ) response = admin_client.get(f"{api_url_v1}/eda-credentials/{obj.id}/") assert response.status_code == status.HTTP_200_OK @@ -326,10 +335,13 @@ def test_list_eda_credentials_filter_name( @pytest.mark.django_db -def test_delete_eda_credential(admin_client: APIClient): +def test_delete_eda_credential( + admin_client: APIClient, default_organization: models.Organization +): obj = models.EdaCredential.objects.create( name="eda-credential", inputs={"username": "adam", "password": "secret"}, + organization=default_organization, ) response = admin_client.delete(f"{api_url_v1}/eda-credentials/{obj.id}/") assert response.status_code == status.HTTP_204_NO_CONTENT @@ -337,11 +349,15 @@ def test_delete_eda_credential(admin_client: APIClient): @pytest.mark.django_db -def test_delete_managed_eda_credential(admin_client: APIClient): +def test_delete_managed_eda_credential( + admin_client: APIClient, + default_organization: models.Organization, +): obj = models.EdaCredential.objects.create( name="eda-credential", inputs={"username": "adam", "password": "secret"}, managed=True, + organization=default_organization, ) response = admin_client.delete(f"{api_url_v1}/eda-credentials/{obj.id}/") assert response.status_code == status.HTTP_400_BAD_REQUEST @@ -352,13 +368,16 @@ def test_delete_managed_eda_credential(admin_client: APIClient): @pytest.mark.django_db def test_partial_update_eda_credential_without_inputs( - admin_client: APIClient, credential_type: models.CredentialType + admin_client: APIClient, + credential_type: models.CredentialType, + default_organization: models.Organization, ): obj = models.EdaCredential.objects.create( name="eda-credential", inputs={"username": "adam", "password": "secret", "key": "private"}, credential_type_id=credential_type.id, managed=True, + organization=default_organization, ) data = {"inputs": {"username": "bearny", "password": "demo"}} response = admin_client.patch( @@ -375,13 +394,16 @@ def test_partial_update_eda_credential_without_inputs( @pytest.mark.django_db def test_partial_update_eda_credential_with_invalid_inputs( - admin_client: APIClient, credential_type: models.CredentialType + admin_client: APIClient, + credential_type: models.CredentialType, + default_organization: models.Organization, ): obj = models.EdaCredential.objects.create( name="eda-credential", inputs={"username": "adam", "password": "secret"}, credential_type_id=credential_type.id, managed=True, + organization=default_organization, ) data = { "inputs": { @@ -430,6 +452,7 @@ def test_partial_update_eda_credential_with_invalid_inputs( @pytest.mark.django_db def test_partial_update_eda_credentials( admin_client: APIClient, + default_organization: models.Organization, preseed_credential_types, credential_type, inputs, @@ -440,6 +463,7 @@ def test_partial_update_eda_credentials( name="eda-credential", inputs=old_inputs, credential_type_id=credential_type.id, + organization=default_organization, ) new_name = "new-eda-credential" new_description = "new-eda-credential description" @@ -466,13 +490,16 @@ def test_partial_update_eda_credentials( @pytest.mark.django_db def test_partial_update_eda_credential_with_encrypted_output( - admin_client: APIClient, credential_type: models.CredentialType + admin_client: APIClient, + credential_type: models.CredentialType, + default_organization: models.Organization, ): obj = models.EdaCredential.objects.create( name="eda-credential", inputs={"username": "adam", "password": "secret", "key": "private"}, credential_type_id=credential_type.id, managed=True, + organization=default_organization, ) data = {"name": "demo2"} response = admin_client.patch( @@ -573,6 +600,7 @@ def test_delete_credential_used_by_activation_forced( @pytest.mark.django_db def test_delete_credential_used_by_project_with_gpg_credential( admin_client: APIClient, + default_organization, preseed_credential_types, ): gpg_credential_type = models.CredentialType.objects.get( @@ -582,11 +610,13 @@ def test_delete_credential_used_by_project_with_gpg_credential( name="test_gpg_credential", inputs={"gpg_public_key": "secret"}, credential_type=gpg_credential_type, + organization=default_organization, ) models.Project.objects.create( name="default-project", description="Default Project", url="https://git.example.com/acme/project-01", + organization=default_organization, git_hash="684f62df18ce5f8d5c428e53203b9b975426eed0", signature_validation_credential=eda_credential, scm_branch="main", @@ -637,7 +667,9 @@ def test_retrieve_eda_credential_with_refs( @pytest.mark.django_db def test_retrieve_eda_credential_with_empty_encrypted_fields( - admin_client: APIClient, preseed_credential_types + admin_client: APIClient, + preseed_credential_types, + default_organization: models.Organization, ): scm_type = models.CredentialType.objects.filter(name="Source Control")[0] data_in = { @@ -648,6 +680,7 @@ def test_retrieve_eda_credential_with_empty_encrypted_fields( "ssh_key_unlock": "", }, "credential_type_id": scm_type.id, + "organization_id": default_organization.id, } response = admin_client.post( f"{api_url_v1}/eda-credentials/", data=data_in diff --git a/tests/integration/api/test_k8s_activation.py b/tests/integration/api/test_k8s_activation.py index 24635869b..f1e1238fd 100644 --- a/tests/integration/api/test_k8s_activation.py +++ b/tests/integration/api/test_k8s_activation.py @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# TODO(doston): this entire test module needs to be updated to use fixtures + import pytest +from django.conf import settings from rest_framework import status from rest_framework.test import APIClient @@ -48,22 +51,29 @@ def create_activation_related_data(): email="luke.skywalker@example.com", password="secret", ) + organization = models.Organization.objects.get_or_create( + name=settings.DEFAULT_ORGANIZATION_NAME, + description="The default organization", + )[0] decision_environment = models.DecisionEnvironment.objects.create( name="test-de", image_url="quay.io/ansible/ansible-rulebook", description="test DecisionEnvironment", + organization=organization, ) project = models.Project.objects.create( git_hash="684f62df18ce5f8d5c428e53203b9b975426eed0", name="test_project", description="test project", url="https://git.example.com/acme/project-01", + organization=organization, ) rulebook = models.Rulebook.objects.create( name="test_rulebook.yaml", rulesets=TEST_RULESETS, description="test rulebook", project_id=project.id, + organization=organization, ) return { @@ -71,6 +81,7 @@ def create_activation_related_data(): "decision_environment_id": decision_environment.id, "project_id": project.id, "rulebook_id": rulebook.id, + "organization_id": organization.id, } @@ -136,6 +147,7 @@ def test_create_k8s_activation_with_service_name( test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["project_id"] = fks["project_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] test_activation["k8s_service_name"] = service_name response = admin_client.post( @@ -183,6 +195,7 @@ def test_create_podman_activation( test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["project_id"] = fks["project_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] response = admin_client.post( f"{api_url_v1}/activations/", data=test_activation @@ -204,6 +217,7 @@ def test_get_activations_with_service_name( test_activation["decision_environment_id"] = fks["decision_environment_id"] test_activation["project_id"] = fks["project_id"] test_activation["rulebook_id"] = fks["rulebook_id"] + test_activation["organization_id"] = fks["organization_id"] response = admin_client.post( f"{api_url_v1}/activations/", data=test_activation diff --git a/tests/integration/api/test_project.py b/tests/integration/api/test_project.py index 50786f071..41a5ea365 100644 --- a/tests/integration/api/test_project.py +++ b/tests/integration/api/test_project.py @@ -163,6 +163,7 @@ def test_create_or_update_project_with_right_signature_credential( new_project: models.Project, preseed_credential_types, default_gpg_credential, + default_organization: models.Organization, action, credential_type, status_code, @@ -170,14 +171,8 @@ def test_create_or_update_project_with_right_signature_credential( job_id = "3677eb4a-de4a-421a-a73b-411aa502484d" job = mock.Mock(id=job_id) import_project_task.delay.return_value = job - - cred_inputs = inputs_to_store({"user": "me"}) - credential_type = models.CredentialType.objects.get(name=credential_type) - credential = models.EdaCredential.objects.create( - name="credential", - description="Default Credential", - credential_type=credential_type, - inputs=cred_inputs, + credential = create_custom_credential( + credential_type=credential_type, organization=default_organization ) if action == "create": @@ -188,6 +183,7 @@ def test_create_or_update_project_with_right_signature_credential( "signature_validation_credential_id": default_gpg_credential.id, "scm_branch": "main", "scm_refspec": "ref1", + "organization_id": default_organization.id, } response = admin_client.post( @@ -313,6 +309,7 @@ def test_create_or_update_project_with_right_eda_credential( new_project: models.Project, preseed_credential_types, default_scm_credential, + default_organization: models.Organization, action, credential_type, status_code, @@ -320,14 +317,8 @@ def test_create_or_update_project_with_right_eda_credential( job_id = "3677eb4a-de4a-421a-a73b-411aa502484d" job = mock.Mock(id=job_id) import_project_task.delay.return_value = job - - cred_inputs = inputs_to_store({"user": "me"}) - credential_type = models.CredentialType.objects.get(name=credential_type) - credential = models.EdaCredential.objects.create( - name="credential", - description="Default Credential", - credential_type=credential_type, - inputs=cred_inputs, + credential = create_custom_credential( + credential_type=credential_type, organization=default_organization ) if action == "create": @@ -338,6 +329,7 @@ def test_create_or_update_project_with_right_eda_credential( "signature_validation_credential_id": credential.id, "scm_branch": "main", "scm_refspec": "ref1", + "organization_id": default_organization.id, } response = admin_client.post( @@ -751,3 +743,17 @@ def get_organization_details(organization: models.Organization) -> dict: "name": organization.name, "description": organization.description, } + + +def create_custom_credential( + credential_type: enums.CredentialType, organization: models.Organization +) -> models.EdaCredential: + cred_inputs = inputs_to_store({"user": "me"}) + credential_type = models.CredentialType.objects.get(name=credential_type) + return models.EdaCredential.objects.create( + name="custom-credential", + description="Custom Credential", + credential_type=credential_type, + inputs=cred_inputs, + organization=organization, + ) diff --git a/tests/integration/api/test_webhook.py b/tests/integration/api/test_webhook.py index 82ecca7b2..2c6e59a10 100644 --- a/tests/integration/api/test_webhook.py +++ b/tests/integration/api/test_webhook.py @@ -25,6 +25,7 @@ import pytest import requests_mock import yaml +from django.conf import settings from django.test import override_settings from ecdsa import SigningKey from ecdsa.util import sigencode_der @@ -76,11 +77,14 @@ def test_retrieve_webhook( @pytest.mark.django_db def test_create_webhook( - admin_client: APIClient, default_hmac_credential: models.EdaCredential + admin_client: APIClient, + default_hmac_credential: models.EdaCredential, + default_organization: models.Organization, ): data_in = { "name": "test_webhook", "eda_credential_id": default_hmac_credential.id, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) assert webhook.name == "test_webhook" @@ -88,9 +92,13 @@ def test_create_webhook( @pytest.mark.django_db -def test_create_webhook_without_credentials(admin_client: APIClient): +def test_create_webhook_without_credentials( + admin_client: APIClient, + default_organization: models.Organization, +): data_in = { "name": "test_webhook", + "organization_id": default_organization.id, } response = admin_client.post(f"{api_url_v1}/webhooks/", data=data_in) assert response.status_code == status.HTTP_400_BAD_REQUEST @@ -118,6 +126,7 @@ def test_post_webhook( preseed_credential_types, hash_algorithm, digestmod, + default_organization: models.Organization, ): secret = secrets.token_hex(32) signature_header_name = "My-Secret-Header" @@ -136,6 +145,7 @@ def test_post_webhook( data_in = { "name": "test-webhook-1", "eda_credential_id": obj["id"], + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) @@ -158,6 +168,7 @@ def test_post_webhook( def test_post_webhook_bad_secret( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, ): secret = secrets.token_hex(32) signature_header_name = "My-Secret-Header" @@ -176,6 +187,7 @@ def test_post_webhook_bad_secret( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) bad_secret = secrets.token_hex(32) @@ -202,6 +214,7 @@ def test_post_webhook_bad_secret( def test_post_webhook_with_prefix( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, ): secret = secrets.token_hex(32) signature_header_name = "My-Secret-Header" @@ -222,6 +235,7 @@ def test_post_webhook_with_prefix( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) data = {"a": 1, "b": 2} @@ -245,6 +259,7 @@ def test_post_webhook_with_prefix( def test_post_webhook_with_test_mode( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, ): secret = secrets.token_hex(32) signature_header_name = "My-Secret-Header" @@ -265,6 +280,7 @@ def test_post_webhook_with_test_mode( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) data = {"a": 1, "b": 2} @@ -338,6 +354,7 @@ def test_post_webhook_with_bad_uuid( def test_post_webhook_with_form_urlencoded( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, ): secret = secrets.token_hex(32) signature_header_name = "My-Secret-Header" @@ -358,6 +375,7 @@ def test_post_webhook_with_form_urlencoded( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) data = {"a": 1, "b": 2} @@ -385,6 +403,7 @@ def test_post_webhook_with_form_urlencoded( def test_post_webhook_with_base64_format( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, ): secret = secrets.token_hex(32) signature_header_name = "My-Secret-Header" @@ -405,6 +424,7 @@ def test_post_webhook_with_base64_format( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) data = {"a": 1, "b": 2} @@ -438,6 +458,7 @@ def test_post_webhook_with_base64_format( def test_post_webhook_with_basic_auth( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, auth_status, bogus_password, ): @@ -458,6 +479,7 @@ def test_post_webhook_with_basic_auth( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) if bogus_password: @@ -492,6 +514,7 @@ def test_post_webhook_with_basic_auth( @pytest.mark.django_db def test_post_webhook_with_token( admin_client: APIClient, + default_organization: models.Organization, preseed_credential_types, auth_status, bogus_token, @@ -512,6 +535,7 @@ def test_post_webhook_with_token( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) data = {"a": 1, "b": 2} @@ -536,6 +560,7 @@ def test_post_webhook_with_token( def test_post_webhook_with_test_mode_extra_headers( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, ): secret = secrets.token_hex(32) signature_header_name = "X-Gitlab-Token" @@ -557,6 +582,7 @@ def test_post_webhook_with_test_mode_extra_headers( "eda_credential_id": obj["id"], "test_mode": True, "additional_data_headers": additional_data_headers, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) data = {"a": 1, "b": 2} @@ -607,6 +633,7 @@ def test_post_webhook_with_test_mode_extra_headers( def test_post_webhook_with_ecdsa( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, auth_status, data, bogus_data, @@ -629,6 +656,7 @@ def test_post_webhook_with_ecdsa( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) content_type = "application/json" @@ -659,6 +687,7 @@ def test_post_webhook_with_ecdsa( def test_post_webhook_with_ecdsa_with_prefix( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, ): signature_header_name = "My-Ecdsa-Sig" prefix_header_name = "My-Ecdsa-Prefix" @@ -681,6 +710,7 @@ def test_post_webhook_with_ecdsa_with_prefix( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) @@ -752,6 +782,7 @@ def test_fetching_webhook_credential( def test_post_webhook_with_oauth2( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, auth_status, payload, post_status, @@ -779,6 +810,7 @@ def test_post_webhook_with_oauth2( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) @@ -812,6 +844,7 @@ def test_post_webhook_with_oauth2( def test_post_webhook_with_oauth2_jwt( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, auth_status, side_effect, ): @@ -834,6 +867,7 @@ def test_post_webhook_with_oauth2_jwt( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) @@ -869,6 +903,7 @@ def test_post_webhook_with_oauth2_jwt( def test_post_webhook_with_mtls( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, subject, auth_status, bogus_subject, @@ -888,6 +923,7 @@ def test_post_webhook_with_mtls( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } webhook = _create_webhook(admin_client, data_in) data = {"a": 1, "b": 2} @@ -913,6 +949,7 @@ def test_post_webhook_with_mtls( def test_post_webhook_with_mtls_missing_settings( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, ): header_key = "Subject" inputs = { @@ -929,6 +966,7 @@ def test_post_webhook_with_mtls_missing_settings( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } with override_settings(WEBHOOK_MTLS_BASE_URL=None): response = admin_client.post(f"{api_url_v1}/webhooks/", data=data_in) @@ -948,6 +986,7 @@ def test_post_webhook_with_mtls_missing_settings( def test_post_webhook_with_basic_auth_missing_settings( admin_client: APIClient, preseed_credential_types, + default_organization: models.Organization, ): secret = secrets.token_hex(32) username = "fred" @@ -966,6 +1005,7 @@ def test_post_webhook_with_basic_auth_missing_settings( "name": "test-webhook-1", "eda_credential_id": obj["id"], "test_mode": True, + "organization_id": default_organization.id, } with override_settings(WEBHOOK_BASE_URL=None): response = admin_client.post(f"{api_url_v1}/webhooks/", data=data_in) @@ -989,10 +1029,15 @@ def _create_webhook_credential( credential_type = models.CredentialType.objects.get( name=credential_type_name ) + organization = models.Organization.objects.get_or_create( + name=settings.DEFAULT_ORGANIZATION_NAME, + description="The default organization", + )[0] data_in = { "name": name, "inputs": inputs, "credential_type_id": credential_type.id, + "organization_id": organization.id, } response = client.post(f"{api_url_v1}/eda-credentials/", data=data_in) assert response.status_code == status.HTTP_201_CREATED diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index efffe5b28..892c2a634 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -301,7 +301,9 @@ def default_run_job_template_rulesets() -> str: @pytest.fixture def default_rulebook( - default_project: models.Project, default_rulesets: str + default_project: models.Project, + default_organization: models.Organization, + default_rulesets: str, ) -> models.Rulebook: """Return a default Rulebook""" return models.Rulebook.objects.create( @@ -309,6 +311,7 @@ def default_rulebook( rulesets=default_rulesets, description="test rulebook", project=default_project, + organization=default_organization, ) @@ -616,7 +619,7 @@ def activation_payload( "project_id": default_project.id, "rulebook_id": default_rulebook.id, "extra_var": default_extra_var_data, - "organization": default_organization.id, + "organization_id": default_organization.id, "user_id": admin_user.id, "restart_policy": enums.RestartPolicy.ON_FAILURE, "log_level": enums.RulebookProcessLogLevel.DEBUG, diff --git a/tests/integration/dab_rbac/test_organization.py b/tests/integration/dab_rbac/test_organization.py index e2e1a750c..4ee12d197 100644 --- a/tests/integration/dab_rbac/test_organization.py +++ b/tests/integration/dab_rbac/test_organization.py @@ -42,7 +42,6 @@ def test_create_with_default_org(cls_factory, model, admin_client, request): model_obj = cls_factory.get_fixture_object(request, model_name) post_data = cls_factory.get_post_data(model_obj) assert "organization_id" in post_data # sanity - post_data.pop("organization_id") if model._meta.model_name == "team": pytest.skip("Team model requires an organization") @@ -59,7 +58,6 @@ def test_create_with_default_org(cls_factory, model, admin_client, request): pytest.skip("Not testing model not allowing creation for now") assert response.status_code == 201, response.data - # organization_id is inconsistently given in response so not using that if model.objects.count() == 1: obj = model.objects.first()