* feat: added python apis to agreements models * feat: add python apis to agreements app * feat: updated pyton apis and rest api * feat: fixed python apis and added tests * test: Added error handling and updated test functions * style: fixed test formatting * style: fixed test formatting * style: fixed test formatting * feat: Fixed error handling for python APIs * feat: Fixed error handling for python APIs * fix: edited python api for agreements app * style: quality revisions for python apis
243 lines
7.3 KiB
Python
243 lines
7.3 KiB
Python
"""
|
|
Agreements API
|
|
"""
|
|
|
|
import logging
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
from opaque_keys.edx.keys import CourseKey
|
|
|
|
from openedx.core.djangoapps.agreements.models import IntegritySignature
|
|
from openedx.core.djangoapps.agreements.models import LTIPIITool
|
|
from openedx.core.djangoapps.agreements.models import LTIPIISignature
|
|
|
|
from .data import LTIToolsReceivingPIIData
|
|
from .data import LTIPIISignatureData
|
|
|
|
log = logging.getLogger(__name__)
|
|
User = get_user_model()
|
|
|
|
|
|
def create_integrity_signature(username, course_id):
|
|
"""
|
|
Create an integrity signature. If a signature already exists, do not create a new one.
|
|
|
|
Arguments:
|
|
* username (str)
|
|
* course_id (str)
|
|
|
|
Returns:
|
|
* IntegritySignature object
|
|
"""
|
|
user = User.objects.get(username=username)
|
|
course_key = CourseKey.from_string(course_id)
|
|
signature, created = IntegritySignature.objects.get_or_create(user=user, course_key=course_key)
|
|
if not created:
|
|
log.warning(
|
|
'Integrity signature already exists for user_id={user_id} and '
|
|
'course_id={course_id}'.format(user_id=user.id, course_id=course_id)
|
|
)
|
|
return signature
|
|
|
|
|
|
def get_integrity_signature(username, course_id):
|
|
"""
|
|
Get an integrity signature.
|
|
|
|
Arguments:
|
|
* username (str)
|
|
* course_id (str)
|
|
|
|
Returns:
|
|
* An IntegritySignature object, or None if one does not exist for the
|
|
user + course combination.
|
|
"""
|
|
user = User.objects.get(username=username)
|
|
course_key = CourseKey.from_string(course_id)
|
|
try:
|
|
return IntegritySignature.objects.get(user=user, course_key=course_key)
|
|
except ObjectDoesNotExist:
|
|
return None
|
|
|
|
|
|
def get_integrity_signatures_for_course(course_id):
|
|
"""
|
|
Get all integrity signatures for a given course.
|
|
|
|
Arguments:
|
|
* course_id (str)
|
|
|
|
Returns:
|
|
* QuerySet of IntegritySignature objects (can be empty).
|
|
"""
|
|
course_key = CourseKey.from_string(course_id)
|
|
return IntegritySignature.objects.filter(course_key=course_key)
|
|
|
|
|
|
def create_lti_pii_signature(username, course_id, lti_tools):
|
|
"""
|
|
Creates an lti pii tool signature. If the signature already exist, do not create a new one.
|
|
|
|
Arguments:
|
|
* course_key (str)
|
|
* lti_tools (dict)
|
|
* lti_tools_hash (int)
|
|
Returns:
|
|
* An LTIPIISignature, or None if a signature already exists.
|
|
"""
|
|
course_key = CourseKey.from_string(course_id)
|
|
lti_tools_hash = hash(str(lti_tools))
|
|
|
|
# if user and course exists, update, otherwise create a new signature
|
|
try:
|
|
user = User.objects.get(username=username)
|
|
LTIPIISignature.objects.get(user=user, course_key=course_key)
|
|
except User.DoesNotExist:
|
|
return None
|
|
except LTIPIISignature.DoesNotExist:
|
|
signature = LTIPIISignature.objects.create(
|
|
user=user,
|
|
course_key=course_key,
|
|
lti_tools=lti_tools,
|
|
lti_tools_hash=lti_tools_hash)
|
|
else:
|
|
signature = LTIPIISignature.objects.update(
|
|
user=user,
|
|
course_key=course_key,
|
|
lti_tools=lti_tools,
|
|
lti_tools_hash=lti_tools_hash)
|
|
|
|
return signature
|
|
|
|
|
|
def get_lti_pii_signature(username, course_id):
|
|
"""
|
|
Get the lti pii signature of a user in a course.
|
|
|
|
Arguments:
|
|
* username (str)
|
|
* course_id (str)
|
|
|
|
Returns:
|
|
* An LTIPIISignature object, or None if one does not exist for the
|
|
user + course combination.
|
|
"""
|
|
course_key = CourseKey.from_string(course_id)
|
|
try:
|
|
user = User.objects.get(username=username)
|
|
signature = LTIPIISignature.objects.get(user=user, course_key=course_key)
|
|
except (User.DoesNotExist, LTIPIISignature.DoesNotExist):
|
|
return None
|
|
else:
|
|
return LTIPIISignatureData(user=signature.user, course_id=str(signature.course_key),
|
|
lti_tools=signature.lti_tools, lti_tools_hash=signature.lti_tools_hash)
|
|
|
|
|
|
def get_pii_receiving_lti_tools(course_id):
|
|
"""
|
|
Get a course's LTI tools that share PII.
|
|
|
|
Arguments:
|
|
* course_id (str)
|
|
|
|
Returns:
|
|
* A List of LTI tools sharing PII.
|
|
"""
|
|
|
|
course_key = CourseKey.from_string(course_id)
|
|
try:
|
|
course_ltipiitools = LTIPIITool.objects.get(course_key=course_key).lti_tools
|
|
except LTIPIITool.DoesNotExist:
|
|
return None
|
|
|
|
return LTIToolsReceivingPIIData(lii_tools_receiving_pii=course_ltipiitools)
|
|
|
|
|
|
def user_lti_pii_signature_needed(username, course_id):
|
|
"""
|
|
Determines if a user needs to acknowledge the LTI PII Agreement.
|
|
|
|
Arguments:
|
|
* username (str)
|
|
|
|
Returns:
|
|
* True if the user needs to sign a new acknowledgement.
|
|
* False if the acknowledgements are up to date.
|
|
"""
|
|
course_has_lti_pii_tools = _course_has_lti_pii_tools(course_id)
|
|
signature_exists = _user_lti_pii_signature_exists(username, course_id)
|
|
signature_out_of_date = _user_signature_out_of_date(username, course_id)
|
|
|
|
return ((course_has_lti_pii_tools and (not signature_exists)) or
|
|
(course_has_lti_pii_tools and signature_exists and signature_out_of_date))
|
|
|
|
|
|
def _course_has_lti_pii_tools(course_id):
|
|
"""
|
|
Determines if a specifc course has lti tools sharing pii.
|
|
|
|
Arguments:
|
|
* course_id (str)
|
|
|
|
Returns:
|
|
* True if the course does have a list.
|
|
* False if the course does not.
|
|
"""
|
|
course_key = CourseKey.from_string(course_id)
|
|
try:
|
|
course_lti_pii_tools = LTIPIITool.objects.get(course_key=course_key)
|
|
except LTIPIITool.DoesNotExist:
|
|
# no entry in the database
|
|
return False
|
|
else:
|
|
# returns True if there are entries, and False if the list is empty
|
|
return bool(course_lti_pii_tools.lti_tools)
|
|
|
|
|
|
def _user_lti_pii_signature_exists(username, course_id):
|
|
"""
|
|
Determines if a user's lti pii signature exists for a specfic course
|
|
|
|
Arguments:
|
|
* username (str)
|
|
* course_id (str)
|
|
|
|
Returns:
|
|
* True if user has a signature for the given course.
|
|
* False if the user does not have a signature for the given course.
|
|
"""
|
|
course_key = CourseKey.from_string(course_id)
|
|
|
|
try:
|
|
user = User.objects.get(username=username)
|
|
LTIPIISignature.objects.get(user=user, course_key=course_key)
|
|
except (User.DoesNotExist, LTIPIISignature.DoesNotExist):
|
|
return False
|
|
else:
|
|
return True # signature exist
|
|
|
|
|
|
def _user_signature_out_of_date(username, course_id):
|
|
"""
|
|
Determines if a user's existing lti pii signature is out-of-date for a given course.
|
|
|
|
Arguments:
|
|
* username (str)
|
|
* course_id (str)
|
|
|
|
Returns:
|
|
* True if signature is out-of-date and needs a new signature.
|
|
* False if the user has an up-to-date signature.
|
|
"""
|
|
course_key = CourseKey.from_string(course_id)
|
|
|
|
try:
|
|
user = User.objects.get(username=username)
|
|
user_lti_pii_signature_hash = LTIPIISignature.objects.get(course_key=course_key, user=user).lti_tools_hash
|
|
course_lti_pii_tools_hash = LTIPIITool.objects.get(course_key=course_key).lti_tools_hash
|
|
except (User.DoesNotExist, LTIPIISignature.DoesNotExist, LTIPIITool.DoesNotExist):
|
|
return False
|
|
else:
|
|
return user_lti_pii_signature_hash != course_lti_pii_tools_hash
|