Skip to content

Commit

Permalink
refactor: [AXM-1227, AXM-1235, AXM-1242] small changes
Browse files Browse the repository at this point in the history
  • Loading branch information
kyrylo-kh committed Dec 20, 2024
1 parent 7439aba commit eec0606
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 170 deletions.
29 changes: 26 additions & 3 deletions credentials/apps/badges/accredible/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from credentials.apps.badges.base_api_client import BaseBadgeProviderClient
from credentials.apps.badges.accredible.data import AccredibleBadgeData, AccredibleExpireBadgeData
from credentials.apps.badges.accredible.utils import get_accredible_api_base_url
from credentials.apps.badges.accredible.exceptions import AccredibleError


logger = logging.getLogger(__name__)
Expand All @@ -18,24 +19,38 @@ class AccredibleAPIClient(BaseBadgeProviderClient):
This class provides methods for performing various operations on the Accredible API.
"""

PROVIDER_NAME = "Accredible"

def __init__(self, api_config: AccredibleAPIConfig):
def __init__(self, api_config_id: int):
"""
Initializes a AccredibleAPIClient object.
Args:
api_config (AccredibleAPIConfig): Configuration object for the Accredible API.
"""
self.api_config = api_config

self.api_config_id = api_config_id
self.api_config = self.get_api_config()

def get_api_config(self) -> AccredibleAPIConfig:
"""
Returns the API configuration object for the Accredible API.
"""
try:
api_config = AccredibleAPIConfig.objects.get(id=self.api_config_id)
return api_config
except AccredibleAPIConfig.DoesNotExist:
raise AccredibleError(f"AccredibleAPIConfig with the id {self.api_config_id} does not exist!")

def _get_base_api_url(self) -> str:
return get_accredible_api_base_url(settings)

def _get_headers(self) -> dict:
"""
Returns the headers for making API requests to Credly.
Returns the headers for making API requests to Accredible.
"""

return {
"Accept": "application/json",
"Content-Type": "application/json",
Expand All @@ -46,12 +61,14 @@ def fetch_all_groups(self) -> dict:
"""
Fetch all groups.
"""

return self.perform_request("get", "issuer/all_groups")

def fetch_design_image(self, design_id: int) -> str:
"""
Fetches the design and return the URL of image.
"""

design_raw = self.perform_request("get", f"designs/{design_id}")
return design_raw.get("design", {}).get("rasterized_content_url")

Expand All @@ -62,6 +79,7 @@ def issue_badge(self, issue_badge_data: AccredibleBadgeData) -> dict:
Args:
issue_badge_data (IssueBadgeData): Data required to issue the badge.
"""

return self.perform_request("post", "credentials", asdict(issue_badge_data))

def revoke_badge(self, badge_id, data: AccredibleExpireBadgeData) -> dict:
Expand All @@ -72,6 +90,7 @@ def revoke_badge(self, badge_id, data: AccredibleExpireBadgeData) -> dict:
badge_id (str): ID of the badge to revoke.
data (dict): Additional data for the revocation.
"""

return self.perform_request("patch", f"credentials/{badge_id}", asdict(data))

def sync_groups(self, site_id: int) -> int:
Expand All @@ -84,6 +103,7 @@ def sync_groups(self, site_id: int) -> int:
Returns:
int | None: processed items.
"""

try:
site = Site.objects.get(id=site_id)
except Site.DoesNotExist:
Expand All @@ -93,6 +113,9 @@ def sync_groups(self, site_id: int) -> int:
groups_data = self.fetch_all_groups()
raw_groups = groups_data.get("groups", [])

all_group_ids = [group.get("id") for group in raw_groups]
AccredibleGroup.objects.exclude(id__in=all_group_ids).delete()

for raw_group in raw_groups:
AccredibleGroup.objects.update_or_create(
id=raw_group.get("id"),
Expand Down
4 changes: 4 additions & 0 deletions credentials/apps/badges/accredible/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class AccredibleRecipient:
name (str): The recipient's name.
email (str): The recipient's email address.
"""

name: str
email: str

Expand Down Expand Up @@ -40,18 +41,21 @@ class AccredibleExpiredCredential:
"""
Represents the data required to expire a credential.
"""

expired_on: datetime

@attr.s(auto_attribs=True, frozen=True)
class AccredibleBadgeData:
"""
Represents the data required to issue a badge.
"""

credential: AccredibleCredential

@attr.s(auto_attribs=True, frozen=True)
class AccredibleExpireBadgeData:
"""
Represents the data required to expire a badge.
"""

credential: AccredibleExpiredCredential
11 changes: 11 additions & 0 deletions credentials/apps/badges/accredible/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""
Specific for Accredible exceptions.
"""

from credentials.apps.badges.exceptions import BadgesError


class AccredibleError(BadgesError):
"""
Accredible backend generic error.
"""
4 changes: 4 additions & 0 deletions credentials/apps/badges/accredible/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
Accredible utility functions.
"""

def get_accredible_api_base_url(settings) -> str:
"""
Determines the base URL for the Accredible service based on application settings.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
import logging

from django.core.management.base import BaseCommand

from credentials.apps.badges.accredible.api_client import AccredibleAPIClient
from credentials.apps.badges.models import AccredibleAPIConfig


logger = logging.getLogger(__name__)
class Command(BaseCommand):
"""
Sync groups for a specific accredible api config or all configs.
Usage:
site_id=1
api_config_id=1
class Command(BaseCommand):
help = "Sync badge templates for a specific organization or all organizations"
./manage.py sync_accredible_groups --site_id $site_id
./manage.py sync_accredible_groups --site_id $site_id --api_config_id $api_config_id
"""
help = "Sync accredible groups for a specific api config or all api configs"

def add_arguments(self, parser):
parser.add_argument("--site_id", type=int, help="Site ID.")
parser.add_argument("--api_config_id", type=str, help="ID of the API config.")

def handle(self, *args, **options):
"""
Sync groups for a specific accredible api config or all configs.
Usage:
site_id=1
api_config_id=1
./manage.py sync_organization_badge_templates --site_id $site_id
./manage.py sync_organization_badge_templates --site_id $site_id --api_config_id $api_config_id
Handle the command.
"""
DEFAULT_SITE_ID = 1
api_configs_to_sync = []
Expand All @@ -34,24 +32,23 @@ def handle(self, *args, **options):
api_config_id = options.get("api_config_id")

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

if api_config_id:
api_configs_to_sync.append(api_config_id)
logger.info(f"Syncing groups for the single config: {api_config_id}")
self.stdout.write(f"Syncing groups for the single config: {api_config_id}")
else:
api_configs_to_sync = AccredibleAPIConfig.get_all_api_config_ids()
logger.info(
self.stdout.write(
"API Config ID wasn't provided: syncing groups for all configs - "
f"{api_configs_to_sync}",
)

for api_config_id in api_configs_to_sync:
api_config = AccredibleAPIConfig.objects.get(id=api_config_id)
accredible_api_client = AccredibleAPIClient(api_config)
for api_config in AccredibleAPIConfig.objects.filter(id__in=api_configs_to_sync):
accredible_api_client = AccredibleAPIClient(api_config.id)
processed_items = accredible_api_client.sync_groups(site_id)

logger.info(f"API Config {api_config_id}: got {processed_items} groups.")
self.stdout.write(f"API Config {api_config_id}: got {processed_items} groups.")

logger.info("...completed!")
self.stdout.write("...completed!")

This file was deleted.

Loading

0 comments on commit eec0606

Please sign in to comment.