forked from openedx/credentials
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: [AXM-1227, AXM-1235, AXM-1242] accredible models, client and sy…
…ncing groups
- Loading branch information
Showing
12 changed files
with
861 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import logging | ||
from django.conf import settings | ||
from django.contrib.sites.models import Site | ||
from attrs import asdict | ||
|
||
from credentials.apps.badges.models import AccredibleAPIConfig, AccredibleGroup | ||
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 | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class AccredibleAPIClient(BaseBadgeProviderClient): | ||
""" | ||
A client for interacting with the Accredible API. | ||
This class provides methods for performing various operations on the Accredible API. | ||
""" | ||
PROVIDER_NAME = "Accredible" | ||
|
||
def __init__(self, api_config: AccredibleAPIConfig): | ||
""" | ||
Initializes a AccredibleAPIClient object. | ||
Args: | ||
api_config (AccredibleAPIConfig): Configuration object for the Accredible API. | ||
""" | ||
self.api_config = api_config | ||
|
||
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. | ||
""" | ||
return { | ||
"Accept": "application/json", | ||
"Content-Type": "application/json", | ||
"Authorization": f"Bearer {self.api_config.api_key}", | ||
} | ||
|
||
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") | ||
|
||
def issue_badge(self, issue_badge_data: AccredibleBadgeData) -> dict: | ||
""" | ||
Issues a badge using the Accredible REST API. | ||
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: | ||
""" | ||
Revoke a badge with the given badge ID. | ||
Args: | ||
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: | ||
""" | ||
Pull all groups for a given Accredible API config. | ||
Args: | ||
site_id (int): ID of the site. | ||
Returns: | ||
int | None: processed items. | ||
""" | ||
try: | ||
site = Site.objects.get(id=site_id) | ||
except Site.DoesNotExist: | ||
logger.error(f"Site with the id {site_id} does not exist!") | ||
raise | ||
|
||
groups_data = self.fetch_all_groups() | ||
raw_groups = groups_data.get("groups", []) | ||
|
||
for raw_group in raw_groups: | ||
AccredibleGroup.objects.update_or_create( | ||
id=raw_group.get("id"), | ||
api_config=self.api_config, | ||
defaults={ | ||
"site": site, | ||
"name": raw_group.get("course_name"), | ||
"description": raw_group.get("course_description"), | ||
"icon": self.fetch_design_image(raw_group.get("primary_design_id")), | ||
}, | ||
) | ||
|
||
return len(raw_groups) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import attr | ||
from datetime import datetime | ||
|
||
|
||
@attr.s(auto_attribs=True, frozen=True) | ||
class AccredibleRecipient: | ||
""" | ||
Represents the recipient data in the credential. | ||
Attributes: | ||
name (str): The recipient's name. | ||
email (str): The recipient's email address. | ||
""" | ||
name: str | ||
email: str | ||
|
||
@attr.s(auto_attribs=True, frozen=True) | ||
class AccredibleCredential: | ||
""" | ||
Represents the credential data. | ||
Attributes: | ||
recipient (RecipientData): Information about the recipient. | ||
group_id (int): ID of the credential group. | ||
name (str): Title of the credential. | ||
description (str): Description of the credential. | ||
issued_on (datetime): Date when the credential was issued. | ||
complete (bool): Whether the credential process is complete. | ||
""" | ||
|
||
recipient: AccredibleRecipient | ||
group_id: int | ||
name: str | ||
description: str | ||
issued_on: datetime | ||
complete: bool | ||
|
||
@attr.s(auto_attribs=True, frozen=True) | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
def get_accredible_api_base_url(settings) -> str: | ||
""" | ||
Determines the base URL for the Accredible service based on application settings. | ||
Parameters: | ||
- settings: A configuration object containing the application's settings. | ||
Returns: | ||
- str: The base URL for the Accredible service (web site). | ||
This will be the URL for the sandbox environment if `USE_SANDBOX` is | ||
set to a truthy value in the configuration; | ||
otherwise, it will be the production environment's URL. | ||
""" | ||
|
||
accredible_config = settings.BADGES_CONFIG["accredible"] | ||
|
||
if accredible_config.get("USE_SANDBOX"): | ||
return accredible_config["ACCREDIBLE_SANDBOX_API_BASE_URL"] | ||
|
||
return accredible_config["ACCREDIBLE_API_BASE_URL"] | ||
|
||
|
||
def get_accredible_base_url(settings) -> str: | ||
""" | ||
Determines the base URL for the Accredible service based on application settings. | ||
Parameters: | ||
- settings: A configuration object containing the application's settings. | ||
Returns: | ||
- str: The base URL for the Accredible service (web site). | ||
This will be the URL for the sandbox environment if `USE_SANDBOX` is | ||
set to a truthy value in the configuration; | ||
otherwise, it will be the production environment's URL. | ||
""" | ||
|
||
credly_config = settings.BADGES_CONFIG["accredible"] | ||
|
||
if credly_config.get("USE_SANDBOX"): | ||
return credly_config["ACCREDIBLE_SANDBOX_BASE_URL"] | ||
|
||
return credly_config["ACCREDIBLE_BASE_URL"] |
Oops, something went wrong.