Skip to content

Commit

Permalink
Accredible integration init
Browse files Browse the repository at this point in the history
  • Loading branch information
amirtds committed Dec 4, 2019
0 parents commit 575a386
Show file tree
Hide file tree
Showing 13 changed files with 691 additions and 0 deletions.
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2019 Noderabbit Inc., d.b.a. Appsembler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include LICENSE
include README.md
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
![Accredible Logo](https://s3.amazonaws.com/accredible-cdn/accredible_logo_sm.png)

# Accredible OpenEdX Module

## Overview
The Accredible platform enables organizations to create, manage and distribute digital credentials as digital certificates or open badges.

An example digital certificate and badge can be viewed here: https://www.credential.net/10000005

This module enables you to issue dynamic, digital certificates using the [Accredible](https://accredible.com) API on your OpenEdx LMS instance. They act as a replacement for the PDF certificates normally generated for your courses.

The module has been tested in edx-platform v0.1+.

## Example Output
![Example Digital Certificate](https://s3.amazonaws.com/accredible-cdn/example-digital-certificate.png)

![Example Open Badge](https://s3.amazonaws.com/accredible-cdn/example-digital-badge.png)

### Pre-installation
Before installing the module please visit [https://accredible.com](https://accredible.com) and obtain a API key.

### Installation
To install the git submodule onto your OpenEdx instance please ensure you have your API key and then follow these steps:

1. Locate your OpenEdx platform and navigate to **edx-platform**.
2. Run `sudo git submodule add https://github.com/accredible/accredible_certificate /edx/app/edxapp/edx-platform/lms/djangoapps/accredible_certificate`
3. Still within **edx-platform**, edit lms/envs/common.py. Around line 1326 you will the *INSTALLED_APPS* section, include accredible_certificate there by adding the line: `'accredible_certificate',` and saving the updated file.

Now we can check the installation by running shell commands to see if our additional functions are available. Within the **edx-plaform** directory run `sudo -u www-data /edx/bin/python.edxapp ./manage.py lms --settings=aws help`

Within the long list you should see the following output:

> [accredible_certificates]
> change_accredible_certs_status
> generate_accredible_certs
### Issuing Certificates
Your account has a default template for how your certificates will appear which you can edit from your dashboard.

If you'd like to issue certificates and update their appearance *before* they are published (sent to your students) then please follow the instructions in **Method A**. If you'd like to issue certificates and have them delivered directly to students without amending their appearance then please follow the instructions in **Method B**. Both methods issue certificates for every student in the course.

####Method A
To issue certificates and update their appearance *before* they are published (sent to your students):

1. Login to your server and navigate to your **edx-platform** directory to use manage.py
2. Run the command: `sudo -u www-data /edx/bin/python.edxapp ./manage.py lms --settings aws generate_accredible_certs -c edX/DemoX/Demo_Course -a <API_KEY> -s True` where < API_KEY > is replaced with the API key provided by Accredible and where edX/DemoX/Demo_Course is replaced by the course key that you'd like to generate certificates for.
3. Go to the Accredible management console and in your account amend the certificate design to meet your requirements.
4. In the Accredible management console publish the certificates and they will be delivered to your students.
5. Back in your console within the **edx-platform** directory, run the command: `sudo -u www-data /edx/bin/python.edxapp ./manage.py lms --settings aws change_accredible_certs_status -c edX/DemoX/Demo_Course -a <API_KEY>`. This command pull data from the Accredible API to change the status of the certificates from *generating* to *available for download*. Your students can now view their certificates through the LMS and via their email.

####Method B
To issue certificates and have them delivered directly to students without amending their appearance:

1. From the **edx-platform** directory run the command `sudo -u www-data /edx/bin/python.edxapp ./manage.py lms --settings aws generate_accredible_certs -c edX/DemoX/Demo_Course -a <API_KEY>` where < API_KEY > is replaced with the API key provided by Accredible and where edX/DemoX/Demo_Course is replaced by the course key that you'd like to generate certificates for.

### Support
If you have any issues, suggestions or questions then please send an email to [email protected] or submit an issue to https://github.com/accredible/acms-php-api/issues


Empty file.
35 changes: 35 additions & 0 deletions accredible_certificate/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
Provides application configuration for Accredible.
As well as default values for running Accredible along with functions to
add entries to the Django conf settings needed to run Accredible.
"""

from django.apps import AppConfig
from openedx.core.djangoapps.plugins.constants import (
ProjectType, SettingsType, PluginURLs, PluginSettings
)

class AccredibleConfig(AppConfig):
"""
Provides application configuration for Accredible.
"""

name = 'accredible_certificate'
verbose_name = 'accredible_certificate'

plugin_app = {
PluginURLs.CONFIG: {
ProjectType.LMS: {
PluginURLs.NAMESPACE: u'accredible_certificate',
PluginURLs.REGEX: u'request_certificate',
PluginURLs.RELATIVE_PATH: u'accredible_certificate.views.request_certificate',
}
},

PluginSettings.CONFIG: {
ProjectType.LMS: {
SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: u'settings.common'},
SettingsType.AWS: {PluginSettings.RELATIVE_PATH: u'settings.aws'},
}
},
}
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from django.core.management.base import BaseCommand, CommandError
from certificates.models import certificate_status_for_student
from accredible_certificate.queue import CertificateGeneration
from django.contrib.auth.models import User
from optparse import make_option
from django.conf import settings
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.django import modulestore
from certificates.models import CertificateStatuses
from certificates.models import GeneratedCertificate
import datetime
from pytz import UTC
import requests
import json



class Command(BaseCommand):

help = """
Find all students that need certificates for courses that have finished and
put their cert requests on the accredible API.
Other commands can be private: true or not?
Per use need to think about it as when I completed that Edx Linux course now the certificate generated at that time so might be in use
"""

option_list = BaseCommand.option_list + (
make_option('-c', '--course',
metavar='COURSE_ID',
dest='course',
default=False,
help='Grade and generate certificates '
'for a specific course'),
make_option('-a', '--api_key',
metavar='API_KEY',
dest='api_key',
default=None,
help='API key for accredible Certificate, if don\'t have one'
'Visit https://accredible.com/issuer/sign_up and get one')
)

def handle(self, *args, **options):

# Will only generate a certificate if the current
# status is in the unavailable state, can be set
# to something else with the force flag


if options['course']:
# try to parse out the course from the serialized form
try:
course = CourseKey.from_string(options['course'])
except InvalidKeyError:
print("Course id {} could not be parsed as a CourseKey; falling back to SSCK.from_dep_str".format(options['course']))
course = SlashSeparatedCourseKey.from_deprecated_string(options['course'])
course_id = course
else:
raise CommandError("You must specify a course")

if options['api_key']:
api_key = options['api_key']
else:
raise CommandError("You must give a api_key, if don't have one visit: https://accredible.com/issuer/sign_up")

user_emails = []
r = requests.get("https://api.accredible.com/v1/credentials?achievement_id="+ course_id.to_deprecated_string() + "&&full_view=true",headers={'Authorization':'Token token=' + api_key, 'Content-Type':'application/json'})
for certificate in r.json()["credentials"]:
if certificate["approve"] == True:
user_emails.append(certificate["recipient"]["email"])


for certificate in GeneratedCertificate.objects.filter(course_id=course_id, status="generating"):
if certificate.user.email in user_emails:
certificate.status = "downloadable"
certificate.save()
print certificate.name
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
"""
from management command to find all students that need certificates for
courses that have finished, and put their cert requests to the Accredible API.
"""
from django.core.management.base import BaseCommand, CommandError
from certificates.models import certificate_status_for_student
from accredible_certificate.queue import CertificateGeneration
from django.contrib.auth.models import User
from optparse import make_option
from django.conf import settings
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.django import modulestore
from certificates.models import CertificateStatuses
import datetime
from pytz import UTC



class Command(BaseCommand):

help = """
Find all students that need certificates for courses that have finished and
put their cert requests on the accredible API.
Other commands can be private: true or not?
Per use need to think about it as when I completed that Edx Linux course now the certificate generated at that time so might be in use
"""

option_list = BaseCommand.option_list + (
make_option('-c', '--course',
metavar='COURSE_ID',
dest='course',
default=False,
help='Grade and generate certificates '
'for a specific course'),
make_option('-a', '--api_key',
metavar='API_KEY',
dest='api_key',
default=None,
help='API key for accredible Certificate, if don\'t have one'
'Visit https://accredible.com/issuer/sign_up and get one'),
make_option('-f', '--force-gen',
metavar='STATUS',
dest='force',
default=False,
help='Will generate new certificates for only those users '
'whose entry in the certificate table matches STATUS. '
'STATUS can be generating, unavailable, deleted, error '
'or notpassing.'),
make_option('-s', '--styling',
metavar='STYLING',
dest='styling',
default=False,
help='Pass True to styling if you want to desgin credentials after generating them'
'Visit Accredible Management Console for editing it.'
'Then Run xyz command after that student will be informed and can certificate on their dashboard'),
)

def handle(self, *args, **options):

# Will only generate a certificate if the current
# status is in the unavailable state, can be set
# to something else with the force flag

if options['force']:
valid_statuses = getattr(CertificateStatuses, options['force'])
else:
valid_statuses = [CertificateStatuses.unavailable]

if options['course']:
# try to parse out the course from the serialized form
try:
course = CourseKey.from_string(options['course'])
except InvalidKeyError:
print("Course id {} could not be parsed as a CourseKey; falling back to SSCK.from_dep_str".format(options['course']))
course = SlashSeparatedCourseKey.from_deprecated_string(options['course'])
ended_courses = [course]
else:
raise CommandError("You must specify a course")

if options['api_key']:
api_key = options['api_key']
else:
raise CommandError("You must give a api_key, if don't have one visit: https://accredible.com/issuer/sign_up")

if options['styling']:
if options['styling'] == 'True':
new_status = "generating"
else:
raise CommandError("You must give true if want to do styling, no any other argument")
else:
new_status = "downloadable"


for course_key in ended_courses:
# prefetch all chapters/sequentials by saying depth=2
course = modulestore().get_course(course_key, depth=2)

print "Fetching enrolled students for {0}".format(course_key.to_deprecated_string())
enrolled_students = User.objects.filter(
courseenrollment__course_id=course_key)

xq = CertificateGeneration(api_key=api_key)
total = enrolled_students.count()
print "Total number of students: " + str(total)
for student in enrolled_students:
if certificate_status_for_student(
student, course_key)['status'] in valid_statuses:
ret = xq.add_cert(student, course_key, new_status, course=course)
print ret




Loading

0 comments on commit 575a386

Please sign in to comment.