Skip to content

Commit

Permalink
chore: maerge 'aci.main' into current branch
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrii committed May 20, 2024
2 parents 06fa0c7 + 419262d commit 6a47170
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 8 deletions.
17 changes: 16 additions & 1 deletion credentials/apps/badges/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,13 @@ class CredlyOrganizationAdmin(admin.ModelAdmin):
list_display = (
"name",
"uuid",
"api_key",
"api_key_hidden",
)
fields = [
"name",
"uuid",
"api_key_hidden",
]
readonly_fields = [
"name",
]
Expand Down Expand Up @@ -378,6 +383,11 @@ def template_link(self, instance):

template_link.short_description = _("badge template")

def response_change(self, request, obj):
if "_save" in request.POST:
return HttpResponseRedirect(reverse("admin:badges_credlybadgetemplate_change", args=[obj.template.pk]))
return super().response_change(request, obj)


class BadgePenaltyAdmin(admin.ModelAdmin):
"""
Expand Down Expand Up @@ -447,6 +457,11 @@ def template_link(self, instance):

template_link.short_description = _("badge template")

def response_change(self, request, obj):
if "_save" in request.POST:
return HttpResponseRedirect(reverse("admin:badges_credlybadgetemplate_change", args=[obj.template.pk]))
return super().response_change(request, obj)


class BadgeProgressAdmin(admin.ModelAdmin):
"""
Expand Down
7 changes: 7 additions & 0 deletions credentials/apps/badges/admin_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

from django import forms
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from model_utils import Choices

Expand Down Expand Up @@ -35,6 +36,12 @@ def clean(self):
uuid = cleaned_data.get("uuid")
api_key = cleaned_data.get("api_key")

if str(uuid) in CredlyOrganization.get_preconfigured_organizations().keys():
if api_key:
raise forms.ValidationError(_("You can't provide an API key for a configured organization."))

api_key = settings.BADGES_CONFIG["credly"]["ORGANIZATIONS"][str(uuid)]

credly_api_client = CredlyAPIClient(uuid, api_key)
self._ensure_organization_exists(credly_api_client)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.20 on 2024-05-17 17:35

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('badges', '0020_remove_badgepenalty_description'),
]

operations = [
migrations.AlterField(
model_name='credlyorganization',
name='api_key',
field=models.CharField(blank=True, help_text='Credly API shared secret for Credly Organization.', max_length=255),
),
]
19 changes: 17 additions & 2 deletions credentials/apps/badges/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class CredlyOrganization(TimeStampedModel):
"""

uuid = models.UUIDField(unique=True, help_text=_("Put your Credly Organization ID here."))
api_key = models.CharField(max_length=255, help_text=_("Credly API shared secret for Credly Organization."))
api_key = models.CharField(max_length=255, help_text=_("Credly API shared secret for Credly Organization."), blank=True)
name = models.CharField(
max_length=255,
null=True,
Expand All @@ -57,6 +57,21 @@ def get_all_organization_ids(cls):
Get all organization IDs.
"""
return list(cls.objects.values_list("uuid", flat=True))

@classmethod
def get_preconfigured_organizations(cls):
"""
Get preconfigured organizations.
"""
return settings.BADGES_CONFIG["credly"].get("ORGANIZATIONS", {})

@property
def is_preconfigured(self):
"""
Checks if the organization is preconfigured.
"""

return str(self.uuid) in CredlyOrganization.get_preconfigured_organizations().keys()


class BadgeTemplate(AbstractCredential):
Expand Down Expand Up @@ -213,7 +228,7 @@ def reset(self, username: str):
requirement=self,
progress__username=username,
).first()
deleted, __ = fulfillment.delete()
deleted, __ = fulfillment.delete() if fulfillment else (False, 0)
if deleted:
notify_requirement_regressed(
sender=self,
Expand Down
10 changes: 8 additions & 2 deletions credentials/apps/badges/signals/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,15 @@ def notify_requirement_fulfilled(*, sender, username, badge_template_id, **kwarg

def notify_requirement_regressed(*, sender, username, badge_template_id):
"""
FIXME: implement/use
Notifies about user's regression on the badge template.
"""

BADGE_REQUIREMENT_REGRESSED.send(
sender=sender,
username=username,
badge_template_id=badge_template_id,
)


def notify_progress_complete(sender, username, badge_template_id):
"""
Expand All @@ -55,7 +61,7 @@ def notify_progress_complete(sender, username, badge_template_id):

def notify_progress_incomplete(sender, username, badge_template_id):
"""
FIXME: implement/use
Notifies about user's regression on the badge template.
"""
BADGE_PROGRESS_INCOMPLETE.send(
sender=sender,
Expand Down
33 changes: 30 additions & 3 deletions credentials/apps/badges/tests/test_signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
CredlyOrganization,
)
from credentials.apps.badges.issuers import CredlyBadgeTemplateIssuer
from credentials.apps.badges.signals.signals import BADGE_PROGRESS_COMPLETE
from credentials.apps.badges.signals.signals import BADGE_PROGRESS_COMPLETE, BADGE_PROGRESS_INCOMPLETE


class BadgeSignalReceiverTestCase(TestCase):
Expand All @@ -24,7 +24,7 @@ def setUp(self):
name="test", site_id=1, organization=credly_organization
)

def test_signal_emission_and_receiver_execution(self):
def test_progression_signal_emission_and_receiver_execution(self):
# Emit the signal
with mock.patch("credentials.apps.badges.issuers.notify_badge_awarded"):
with mock.patch.object(CredlyBadgeTemplateIssuer, "issue_credly_badge"):
Expand All @@ -37,7 +37,9 @@ def test_signal_emission_and_receiver_execution(self):
# UserCredential object
user_credential = CredlyBadge.objects.filter(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(self.badge_template),
credential_content_type=ContentType.objects.get_for_model(
self.badge_template
),
credential_id=self.badge_template.id,
)

Expand All @@ -46,3 +48,28 @@ def test_signal_emission_and_receiver_execution(self):

# Check if user credential status is 'awarded'
self.assertTrue(user_credential[0].status == "awarded")

def test_regression_signal_emission_and_receiver_execution(self):
# Emit the signal
with mock.patch("credentials.apps.badges.issuers.notify_badge_revoked"):
with mock.patch.object(CredlyBadgeTemplateIssuer, "revoke_credly_badge"):
BADGE_PROGRESS_INCOMPLETE.send(
sender=self,
username="test_user",
badge_template_id=self.badge_template.id,
)

# UserCredential object
user_credential = CredlyBadge.objects.filter(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(
self.badge_template
),
credential_id=self.badge_template.id,
)

# Check if user credential is created
self.assertTrue(user_credential.exists())

# Check if user credential status is 'revoked'
self.assertTrue(user_credential[0].status == "revoked")

0 comments on commit 6a47170

Please sign in to comment.