forked from appsembler/accredible
-
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.
- Loading branch information
0 parents
commit 575a386
Showing
13 changed files
with
691 additions
and
0 deletions.
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,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. |
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,2 @@ | ||
include LICENSE | ||
include README.md |
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,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.
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,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.
80 changes: 80 additions & 0 deletions
80
accredible_certificate/management/commands/change_accredible_certs_status.py
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,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 |
117 changes: 117 additions & 0 deletions
117
accredible_certificate/management/commands/generate_accredible_certs.py
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,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 | ||
|
||
|
||
|
||
|
Oops, something went wrong.