Skip to content

Commit

Permalink
Merge branch 'aci.main' into hantkovskyi/aci-892/allow-only-relevant-…
Browse files Browse the repository at this point in the history
…requirements-for-penalty
  • Loading branch information
andrii-hantkovskyi authored Apr 10, 2024
2 parents 9109d74 + 1562958 commit b8aba5a
Show file tree
Hide file tree
Showing 25 changed files with 641 additions and 323 deletions.
11 changes: 9 additions & 2 deletions credentials/apps/badges/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _

from .admin_forms import BadgePenaltyForm, BadgeRequirementForm, CredlyOrganizationAdminForm, DataRuleForm, PenaltyDataRuleForm
from .admin_forms import (
BadgePenaltyForm,
BadgeRequirementForm,
CredlyOrganizationAdminForm,
DataRuleForm,
PenaltyDataRuleForm,
)

from .models import (
BadgePenalty,
Expand Down Expand Up @@ -37,7 +43,7 @@ class BadgePenaltyInline(admin.TabularInline):
extra = 0
form = BadgePenaltyForm


class FulfillmentInline(admin.TabularInline):
model = Fulfillment
extra = 0
Expand Down Expand Up @@ -168,6 +174,7 @@ class BadgePenaltyAdmin(admin.ModelAdmin):
"""
Badge requirement penalty setup admin.
"""

inlines = [
DataRulePenaltyInline,
]
Expand Down
12 changes: 6 additions & 6 deletions credentials/apps/badges/admin_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ def _ensure_organization_exists(self, api_client):
raise forms.ValidationError(message=str(err))



class BadgePenaltyForm(forms.ModelForm):
class Meta:
model = BadgePenalty
Expand All @@ -85,18 +84,19 @@ def clean(self):
return cleaned_data



class PenaltyDataRuleForm(forms.ModelForm):
class Meta:
model = PenaltyDataRule
fields = "__all__"

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and hasattr(self.instance, 'penalty') and self.instance.penalty.template.is_active:
if self.instance and hasattr(self.instance, "penalty") and self.instance.penalty.template.is_active:
for field_name in self.fields:
if field_name in ("data_path", "operator", "value"):
self.fields[field_name].disabled = True


class BadgeRequirementForm(forms.ModelForm):
class Meta:
Expand All @@ -105,9 +105,9 @@ class Meta:

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and hasattr(self.instance, 'template') and self.instance.template.is_active:
if self.instance and hasattr(self.instance, "template") and self.instance.template.is_active:
for field_name in self.fields:
if field_name in ("template", "event_type", "description"):
if field_name in ("template", "event_type", "description", "group"):
self.fields[field_name].disabled = True


Expand All @@ -118,7 +118,7 @@ class Meta:

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and hasattr(self.instance, 'requirement') and self.instance.requirement.template.is_active:
if self.instance and hasattr(self.instance, "requirement") and self.instance.requirement.template.is_active:
for field_name in self.fields:
if field_name in ("data_path", "operator", "value"):
self.fields[field_name].disabled = True
18 changes: 6 additions & 12 deletions credentials/apps/badges/credly/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ def __init__(self, organization_id, api_key=None):
self.api_key = api_key
self.organization_id = organization_id

self.base_api_url = urljoin(
get_credly_api_base_url(settings), f"organizations/{self.organization_id}/"
)
self.base_api_url = urljoin(get_credly_api_base_url(settings), f"organizations/{self.organization_id}/")

def _get_organization(self, organization_id):
"""
Expand Down Expand Up @@ -93,9 +91,7 @@ def perform_request(self, method, url_suffix, data=None):
"""
url = urljoin(self.base_api_url, url_suffix)
logger.debug(f"Credly API: {method.upper()} {url}")
response = requests.request(
method.upper(), url, headers=self._get_headers(), data=data
)
response = requests.request(method.upper(), url, headers=self._get_headers(), json=data)
self._raise_for_error(response)
return response.json()

Expand All @@ -112,9 +108,7 @@ def _raise_for_error(self, response):
try:
response.raise_for_status()
except HTTPError:
logger.error(
f"Error while processing Credly API request: {response.status_code} - {response.text}"
)
logger.error(f"Error while processing Credly API request: {response.status_code} - {response.text}")
raise CredlyAPIError(f"Credly API:{response.text}({response.status_code})")

def _get_headers(self):
Expand Down Expand Up @@ -167,14 +161,14 @@ def issue_badge(self, issue_badge_data):
"""
return self.perform_request("post", "badges/", asdict(issue_badge_data))

def revoke_badge(self, badge_id):
def revoke_badge(self, badge_id, data):
"""
Revoke a badge with the given badge ID.
Args:
badge_id (str): ID of the badge to revoke.
"""
return self.perform_request("put", f"badges/{badge_id}/revoke/")
return self.perform_request("put", f"badges/{badge_id}/revoke/", data=data)

def sync_organization_badge_templates(self, site_id):
"""
Expand Down Expand Up @@ -209,4 +203,4 @@ def sync_organization_badge_templates(self, site_id):
},
)

return len(raw_badge_templates)
return len(raw_badge_templates)
11 changes: 5 additions & 6 deletions credentials/apps/badges/credly/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
class BadgesError(Exception):
"""
Generic Badges functionality error.
"""
"""
Specific for Credly exceptions.
"""

pass
from credentials.apps.badges.exceptions import BadgesError


class CredlyError(BadgesError):
"""
Badges error that is specific to the Credly backend.
Credly backend generic error.
"""

pass
Expand Down
4 changes: 1 addition & 3 deletions credentials/apps/badges/credly/webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ def post(self, request):
"""
credly_api_client = CredlyAPIClient(request.data.get("organization_id"))

event_info_response = credly_api_client.fetch_event_information(
request.data.get("id")
)
event_info_response = credly_api_client.fetch_event_information(request.data.get("id"))
event_type = request.data.get("event_type")

if event_type == "badge_template.created":
Expand Down
27 changes: 27 additions & 0 deletions credentials/apps/badges/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
Badges exceptions.
"""


class BadgesError(Exception):
"""
Badges generic exception.
"""

pass


class BadgesProcessingError(BadgesError):
"""
Exception raised for errors that occur during badge processing.
"""

pass


class StopEventProcessing(BadgesProcessingError):
"""
Exception raised to stop processing an event due to a specific condition.
"""

pass
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ class Command(BaseCommand):

def add_arguments(self, parser):
parser.add_argument("--site_id", type=int, help="Site ID.")
parser.add_argument(
"--organization_id", type=str, help="UUID of the organization."
)
parser.add_argument("--organization_id", type=str, help="UUID of the organization.")

def handle(self, *args, **options):
"""
Expand All @@ -33,16 +31,12 @@ def handle(self, *args, **options):
organization_id = options.get("organization_id")

if site_id is None:
logger.warning(
f"Side ID wasn't provided: assuming site_id = {DEFAULT_SITE_ID}"
)
logger.warning(f"Side ID wasn't provided: assuming site_id = {DEFAULT_SITE_ID}")
site_id = DEFAULT_SITE_ID

if organization_id:
organizations_to_sync.append(organization_id)
logger.info(
f"Syncing badge templates for the single organization: {organization_id}"
)
logger.info(f"Syncing badge templates for the single organization: {organization_id}")
else:
organizations_to_sync = CredlyOrganization.get_all_organization_ids()
logger.info(
Expand All @@ -55,4 +49,4 @@ def handle(self, *args, **options):

logger.info(f"Organization {organization_id}: got {processed_items} badge templates.")

logger.info("...completed!")
logger.info("...completed!")
19 changes: 19 additions & 0 deletions credentials/apps/badges/migrations/0010_auto_20240409_1326.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.2.20 on 2024-04-09 13:26

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('badges', '0009_auto_20240408_1316'),
]

operations = [
migrations.AddField(
model_name='badgepenalty',
name='event_type',
field=models.CharField(choices=[('org.openedx.learning.course.passing.status.updated.v1', 'org.openedx.learning.course.passing.status.updated.v1'), ('org.openedx.learning.ccx.course.passing.status.updated.v1', 'org.openedx.learning.ccx.course.passing.status.updated.v1')], default='org.openedx.learning.course.passing.status.updated.v1', help_text='Public signal type. Use namespaced types, e.g: "org.openedx.learning.student.registration.completed.v1"', max_length=255),
preserve_default=False,
),
]
Loading

0 comments on commit b8aba5a

Please sign in to comment.