├── apps ├── __init__.py ├── health │ ├── __init__.py │ └── urls.py ├── issuer │ ├── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0022_merge.py │ │ ├── 0036_merge_20171101_0815.py │ │ ├── 0006_remove_badgeinstance_email.py │ │ ├── 0021_remove_badgeinstance_evidence_url.py │ │ ├── 0034_badgeinstance_hashed.py │ │ ├── 0025_badgeinstance_issued_on.py │ │ ├── 0016_auto_20170214_0749.py │ │ ├── 0048_auto_20190812_1229.py │ │ ├── 0037_auto_20171113_1015.py │ │ ├── 0038_badgeinstance_expires_at.py │ │ ├── 0044_auto_20180713_0658.py │ │ ├── 0051_auto_20190826_1604.py │ │ ├── 0027_auto_20170801_1636.py │ │ ├── 0049_auto_20190812_1232.py │ │ ├── 0042_auto_20180220_1150.py │ │ ├── 0028_auto_20170802_1035.py │ │ ├── 0029_badgeinstance_recipient_type.py │ │ ├── 0014_issuerstaff_role.py │ │ ├── 0002_auto_20150409_1200.py │ │ ├── 0018_auto_20170413_1054.py │ │ ├── 0009_badgeinstance_acceptance.py │ │ ├── 0010_auto_20170120_1724.py │ │ ├── 0020_auto_20170413_1139.py │ │ ├── 0033_auto_20171002_1413.py │ │ ├── 0005_auto_20150915_1723.py │ │ ├── 0031_auto_20170918_0735.py │ │ ├── 0003_auto_20150512_0657.py │ │ ├── 0023_auto_20170531_1044.py │ │ ├── 0035_issuer_badgrapp.py │ │ ├── 0024_auto_20170609_0845.py │ │ ├── 0047_badgeinstance_user.py │ │ ├── 0043_auto_20180614_0949.py │ │ ├── 0008_auto_20160322_1404.py │ │ ├── 0050_auto_20190813_1945.py │ │ ├── 0026_auto_20170726_1409.py │ │ ├── 0045_auto_20181104_1847.py │ │ ├── 0032_badgeclasstag.py │ │ ├── 0052_auto_20200106_1621.py │ │ ├── 0046_auto_20181114_1517.py │ │ ├── 0015_auto_20170214_0738.py │ │ ├── 0020_auto_20170420_0811.py │ │ ├── 0039_badgeclassextension.py │ │ ├── 0021_auto_20170424_1427.py │ │ ├── 0007_auto_20151117_1555.py │ │ ├── 0041_badgeinstancebakedimage.py │ │ ├── 0019_auto_20170420_0810.py │ │ └── 0013_auto_20170214_0711.py │ ├── tests │ │ └── __init__.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ └── verify_get_json.py │ └── testfiles │ │ ├── 300x300.png │ │ ├── 400x400.png │ │ ├── 450x450.png │ │ ├── 500x300.png │ │ ├── test_jpeg.jpeg │ │ ├── test_jpeg_no_extension │ │ ├── guinea_pig_testing_badge.png │ │ ├── test_badge_png_with_no_extension │ │ ├── test_badgeclass.svg │ │ └── test_badgeclass_with_no_svg_extension ├── backpack │ ├── tests │ │ ├── __init__.py │ │ └── testfiles │ │ │ ├── bad_image.png │ │ │ ├── 1_0_basic_issuer.json │ │ │ ├── baked_image.png │ │ │ ├── unbaked_image.png │ │ │ ├── 1_0_basic_issuer_invalid_json.json │ │ │ ├── 1_0_basic_badgeclass.json │ │ │ ├── 1_0_basic_instance_missing_badge_prop.json │ │ │ ├── 1_0_basic_instance.json │ │ │ ├── 1_0_basic_instance2.json │ │ │ ├── 1_0_basic_instance3.json │ │ │ ├── 1_0_basic_instance_with_bad_date.json │ │ │ ├── 0_5_basic_instance.json │ │ │ └── 2_0_assertion_embedded_badgeclass.json │ ├── migrations │ │ ├── __init__.py │ │ ├── 0012_auto_20200106_1621.py │ │ ├── 0011_auto_20181102_1438.py │ │ ├── 0004_auto_20170711_1326.py │ │ ├── 0003_backpackcollection_assertions.py │ │ ├── 0006_backpackcollectionbadgeinstance_badgeuser.py │ │ ├── 0007_auto_20171027_0837.py │ │ ├── 0008_auto_20171204_1236.py │ │ ├── 0010_auto_20180802_1026.py │ │ └── 0005_auto_20171025_1020.py │ ├── __init__.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ └── emit_old_share_events.py │ ├── share_urls.py │ ├── admin.py │ └── v2_api_urls.py ├── badgrsocialauth │ ├── __init__.py │ ├── tests │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ └── 0002_saml2configuration_cached_metadata.py │ ├── providers │ │ ├── __init__.py │ │ ├── kony │ │ │ ├── __init__.py │ │ │ ├── urls.py │ │ │ ├── tests.py │ │ │ └── provider.py │ │ ├── tests │ │ │ └── __init__.py │ │ ├── facebook │ │ │ ├── __init__.py │ │ │ └── provider.py │ │ └── twitter │ │ │ ├── __init__.py │ │ │ └── provider.py │ ├── permissions.py │ ├── admin.py │ ├── v1_api_urls.py │ ├── v2_api_urls.py │ ├── models.py │ └── serializers_v1.py ├── recipient │ ├── tests │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0012_auto_20181102_1438.py │ │ ├── 0013_auto_20200106_1621.py │ │ ├── 0007_auto_20170509_1529.py │ │ ├── 0003_recipientgroup_pathways.py │ │ ├── 0009_auto_20170509_1937.py │ │ ├── 0008_auto_20170509_1531.py │ │ ├── 0011_auto_20171025_1020.py │ │ ├── 0002_auto_20160331_1418.py │ │ └── 0005_auto_20170413_1054.py │ ├── __init__.py │ ├── v2_api_urls.py │ └── v1_api_urls.py ├── badgeuser │ ├── migrations │ │ ├── __init__.py │ │ ├── 0004_merge.py │ │ ├── 0010_merge.py │ │ ├── 0008_auto_20170427_1508.py │ │ ├── 0023_delete_badgraccesstoken.py │ │ ├── 0003_auto_20160210_0313.py │ │ ├── 0003_auto_20160309_0820.py │ │ ├── 0011_auto_20170619_2301.py │ │ ├── 0009_auto_20170427_1509.py │ │ ├── 0018_termsversion_short_description.py │ │ ├── 0022_auto_20190405_1344.py │ │ ├── 0002_cachedemailaddress.py │ │ ├── 0014_badgraccesstoken.py │ │ ├── 0006_auto_20161128_0938.py │ │ ├── 0021_auto_20190405_0921.py │ │ ├── 0015_badgeuser_badgrapp.py │ │ ├── 0024_auto_20200106_1621.py │ │ ├── 0017_auto_20180611_0819.py │ │ ├── 0019_auto_20181102_1438.py │ │ ├── 0013_auto_20170725_1305.py │ │ ├── 0012_auto_20170711_1326.py │ │ ├── 0007_auto_20170427_0957.py │ │ └── 0020_userrecipientidentifier.py │ ├── tests │ │ └── __init__.py │ ├── __init__.py │ ├── account_forms.py │ ├── permissions.py │ ├── backends.py │ ├── signals.py │ ├── forms.py │ ├── middleware.py │ ├── v1_api_urls.py │ ├── v2_api_urls.py │ └── apps.py ├── mainsite │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ ├── clear_cache.py │ │ │ ├── testserver.py │ │ │ ├── dist.py │ │ │ └── generate_token_scopes.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0006_merge.py │ │ ├── 0003_auto_20160901_1537.py │ │ ├── 0005_auto_20170427_0724.py │ │ ├── 0007_badgrapp_ui_connect_success_redirect.py │ │ ├── 0018_auto_20190723_1532.py │ │ ├── 0021_auto_20191230_1752.py │ │ ├── 0022_badgrapp_is_default.py │ │ ├── 0012_badgrapp_public_pages_redirect.py │ │ ├── 0013_badgrapp_oauth_authorization_redirect.py │ │ ├── 0015_badgrapp_use_auth_code_exchange.py │ │ ├── 0014_applicationinfo_trust_email_verification.py │ │ ├── 0011_auto_20171019_0634.py │ │ ├── 0019_auto_20190710_0805.py │ │ ├── 0001_initial.py │ │ ├── 0005_auto_20170616_1406.py │ │ ├── 0020_auto_20191114_1056.py │ │ ├── 0004_auto_20170120_1724.py │ │ ├── 0017_accesstokenscope.py │ │ ├── 0010_auto_20171004_1510.py │ │ ├── 0008_auto_20170711_1326.py │ │ └── 0009_applicationinfo.py │ ├── version.py │ ├── tests │ │ ├── __init__.py │ │ └── test_api_throttle.py │ ├── static │ │ ├── robots.txt │ │ ├── badgr-ui │ │ │ └── images │ │ │ │ ├── screenshots │ │ │ │ └── badgebook-setup │ │ │ │ │ ├── external-apps-all.png │ │ │ │ │ ├── external-apps-badgr.png │ │ │ │ │ ├── external-apps-installed.png │ │ │ │ │ ├── add-app.png │ │ │ │ │ └── add-app-configuration-type.png │ │ │ │ ├── favicon.ico │ │ │ │ ├── favicon.png │ │ │ │ ├── 500-badgr.png │ │ │ │ ├── add-badge.png │ │ │ │ ├── ajax-loader.gif │ │ │ │ ├── logo_large.png │ │ │ │ ├── 500-badgr-2x.png │ │ │ │ ├── concentricsky.png │ │ │ │ ├── info-addapps.png │ │ │ │ ├── canvas-settings.png │ │ │ │ ├── info-addappform.png │ │ │ │ ├── issuer-placeholder.png │ │ │ │ ├── issuer-placeholder-2x.png │ │ │ │ ├── badgr-canvas-instructions.png │ │ │ │ ├── markdown-mark.svg │ │ │ │ ├── markdown-mark-solid.svg │ │ │ │ ├── image-failed.svg │ │ │ │ ├── image-placeholder.svg │ │ │ │ ├── badge-loading.svg │ │ │ │ ├── badge-failed.svg │ │ │ │ └── placeholderavatar-failed.svg │ │ ├── images │ │ │ ├── logo.png │ │ │ ├── logo-large.png │ │ │ ├── emailtwitter.png │ │ │ ├── emailfacebook.png │ │ │ ├── emaillinkedin.png │ │ │ ├── emailpinterest.png │ │ │ ├── emailtwitter-2x.png │ │ │ ├── icon-twitter@2x.png │ │ │ ├── emailfacebook-2x.png │ │ │ ├── emaillinkedin-2x.png │ │ │ ├── emailpinterest-2x.png │ │ │ ├── icon-facebook@2x.png │ │ │ ├── icon-linkedin@2x.png │ │ │ ├── icon-pinterest@2x.png │ │ │ └── image-bg-graphic-1.png │ │ └── swagger-ui │ │ │ ├── API_DESCRIPTION_v1.md │ │ │ └── API_DESCRIPTION_v2.md │ ├── templates │ │ ├── error │ │ │ ├── 500.html │ │ │ ├── 404.html │ │ │ └── base.html │ │ ├── account │ │ │ └── email │ │ │ │ ├── password_reset_key_subject.txt │ │ │ │ ├── email_confirmation_subject.txt │ │ │ │ ├── email_confirmation_signup_subject.txt │ │ │ │ ├── password_reset_confirmation_subject.txt │ │ │ │ ├── email_confirmation_signup_message.txt │ │ │ │ ├── email_confirmation_message.txt │ │ │ │ ├── password_reset_key_message.txt │ │ │ │ └── password_reset_confirmation_message.txt │ │ ├── issuer │ │ │ └── email │ │ │ │ ├── notify_earner_subject.txt │ │ │ │ ├── notify_account_holder_subject.txt │ │ │ │ ├── notify_account_holder_message.html │ │ │ │ ├── notify_earner_message.html │ │ │ │ └── notify_account_holder_message.txt │ │ ├── admin │ │ │ ├── sitewide_actions.html │ │ │ └── base_site.html │ │ ├── pingdom │ │ │ └── embed.html │ │ ├── public │ │ │ └── bot_openbadge.html │ │ └── rest_framework │ │ │ └── api.html │ ├── signals.py │ ├── context_processors.py │ ├── celery.py │ ├── testrunner.py │ ├── formatters.py │ ├── settings_tests.py │ ├── __init__.py │ ├── settings_testserver.py │ ├── middleware.py │ └── pagination.py ├── pathway │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0004_pathway_is_active.py │ │ ├── 0005_auto_20170217_1104.py │ │ ├── 0003_auto_20160415_1030.py │ │ ├── 0006_auto_20170413_1054.py │ │ ├── 0007_fix_children_of_deleted.py │ │ └── 0002_auto_20160331_1443.py │ ├── __init__.py │ ├── tests │ │ └── __init__.py │ ├── public_api_urls.py │ ├── renderers.py │ └── api_urls.py ├── composition │ ├── migrations │ │ ├── __init__.py │ │ ├── 0004_auto_20150915_1057.py │ │ ├── 0012_localbadgeinstance_badgeclass.py │ │ ├── 0011_auto_20170227_0847.py │ │ ├── 0003_auto_20150914_1447.py │ │ ├── 0006_auto_20160928_0648.py │ │ ├── 0015_auto_20170420_0649.py │ │ ├── 0005_auto_20151117_1555.py │ │ ├── 0002_auto_20150914_1421.py │ │ └── 0013_auto_20170227_0847.py │ └── __init__.py ├── externaltools │ ├── migrations │ │ ├── __init__.py │ │ ├── 0004_auto_20180411_0653.py │ │ ├── 0007_auto_20190319_1111.py │ │ ├── 0005_auto_20180802_1026.py │ │ ├── 0003_auto_20180411_0650.py │ │ ├── 0008_auto_20200106_1621.py │ │ └── 0006_auto_20181102_1438.py │ ├── __init__.py │ ├── v1_api_urls.py │ ├── v2_api_urls.py │ └── admin.py ├── entity │ ├── __init__.py │ ├── db │ │ ├── __init__.py │ │ └── migrations.py │ └── authentication.py └── badgrlog │ ├── __init__.py │ ├── urls.py │ ├── events │ ├── __init__.py │ ├── email.py │ ├── base.py │ └── backpack.py │ └── badgrlogger.py ├── .docker ├── etc │ ├── init.sql │ ├── uwsgi.ini │ ├── wsgi.py │ ├── site.conf │ └── nginx.conf ├── Dockerfile.nginx ├── Dockerfile.prod.api ├── Dockerfile.dev.api └── Dockerfile.api ├── MANIFEST.in ├── .travis.yml ├── .gitignore ├── manage.py ├── .github └── ISSUE_TEMPLATE.md ├── wsgi.py ├── docker-compose.yml └── tox.ini /apps/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/health/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/issuer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/backpack/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/recipient/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/backpack/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/issuer/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/mainsite/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/pathway/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/pathway/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/recipient/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/composition/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/externaltools/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/kony/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/mainsite/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/mainsite/version.py: -------------------------------------------------------------------------------- 1 | VERSION = (3, 0, 0) 2 | -------------------------------------------------------------------------------- /apps/pathway/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/facebook/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/twitter/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/mainsite/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import * -------------------------------------------------------------------------------- /.docker/etc/init.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS badgr; -------------------------------------------------------------------------------- /apps/badgeuser/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | -------------------------------------------------------------------------------- /apps/backpack/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/entity/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/entity/db/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/externaltools/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/issuer/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/issuer/management/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/mainsite/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /staff/ 3 | -------------------------------------------------------------------------------- /apps/issuer/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/mainsite/templates/error/500.html: -------------------------------------------------------------------------------- 1 | {% extends "error/base.html" %} 2 | 3 | -------------------------------------------------------------------------------- /apps/pathway/__init__.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 3/30/16. 2 | -------------------------------------------------------------------------------- /apps/recipient/__init__.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 3/31/16. 2 | -------------------------------------------------------------------------------- /apps/badgeuser/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = 'badgeuser.apps.BadgeUserConfig' 2 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/screenshots/badgebook-setup/external-apps-all.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/screenshots/badgebook-setup/external-apps-badgr.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/pathway/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 4/16/16. 2 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/screenshots/badgebook-setup/external-apps-installed.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/mainsite/templates/account/email/password_reset_key_subject.txt: -------------------------------------------------------------------------------- 1 | Confirm Password Reset Request -------------------------------------------------------------------------------- /apps/mainsite/templates/issuer/email/notify_earner_subject.txt: -------------------------------------------------------------------------------- 1 | Congratulations, you earned a badge! -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/bad_image.png: -------------------------------------------------------------------------------- 1 | { 2 | "some":"bad", 3 | "stuff": "to-leak" 4 | } 5 | -------------------------------------------------------------------------------- /apps/mainsite/templates/issuer/email/notify_account_holder_subject.txt: -------------------------------------------------------------------------------- 1 | Congratulations, you earned a badge! -------------------------------------------------------------------------------- /apps/backpack/management/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from __future__ import unicode_literals 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/composition/__init__.py: -------------------------------------------------------------------------------- 1 | # this app has been deprecated but sticks around for migrations dependencies 2 | -------------------------------------------------------------------------------- /apps/backpack/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from __future__ import unicode_literals 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/1_0_basic_issuer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Basic Issuer", 3 | "url": "http://a.com/issuer/website" 4 | } -------------------------------------------------------------------------------- /apps/issuer/testfiles/300x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/issuer/testfiles/300x300.png -------------------------------------------------------------------------------- /apps/issuer/testfiles/400x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/issuer/testfiles/400x400.png -------------------------------------------------------------------------------- /apps/issuer/testfiles/450x450.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/issuer/testfiles/450x450.png -------------------------------------------------------------------------------- /apps/issuer/testfiles/500x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/issuer/testfiles/500x300.png -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.md 2 | include requirements.txt 3 | recursive-include apps/*/templates * 4 | recursive-include apps/*/static * 5 | -------------------------------------------------------------------------------- /apps/issuer/testfiles/test_jpeg.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/issuer/testfiles/test_jpeg.jpeg -------------------------------------------------------------------------------- /apps/mainsite/static/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/logo.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/logo-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/logo-large.png -------------------------------------------------------------------------------- /apps/issuer/testfiles/test_jpeg_no_extension: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/issuer/testfiles/test_jpeg_no_extension -------------------------------------------------------------------------------- /apps/mainsite/static/images/emailtwitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/emailtwitter.png -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/baked_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/backpack/tests/testfiles/baked_image.png -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/unbaked_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/backpack/tests/testfiles/unbaked_image.png -------------------------------------------------------------------------------- /apps/badgrlog/__init__.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 8/27/15. 2 | 3 | from .badgrlogger import BadgrLogger 4 | from .events import * 5 | 6 | -------------------------------------------------------------------------------- /apps/mainsite/static/images/emailfacebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/emailfacebook.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/emaillinkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/emaillinkedin.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/emailpinterest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/emailpinterest.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/emailtwitter-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/emailtwitter-2x.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/icon-twitter@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/icon-twitter@2x.png -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/favicon.ico -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/favicon.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/emailfacebook-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/emailfacebook-2x.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/emaillinkedin-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/emaillinkedin-2x.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/emailpinterest-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/emailpinterest-2x.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/icon-facebook@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/icon-facebook@2x.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/icon-linkedin@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/icon-linkedin@2x.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/icon-pinterest@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/icon-pinterest@2x.png -------------------------------------------------------------------------------- /apps/issuer/testfiles/guinea_pig_testing_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/issuer/testfiles/guinea_pig_testing_badge.png -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/500-badgr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/500-badgr.png -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/add-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/add-badge.png -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/ajax-loader.gif -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/logo_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/logo_large.png -------------------------------------------------------------------------------- /apps/mainsite/static/images/image-bg-graphic-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/images/image-bg-graphic-1.png -------------------------------------------------------------------------------- /apps/health/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from .views import health 4 | 5 | urlpatterns = [ 6 | url(r'^$', health, name='server_health'), 7 | ] 8 | -------------------------------------------------------------------------------- /apps/issuer/testfiles/test_badge_png_with_no_extension: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/issuer/testfiles/test_badge_png_with_no_extension -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/500-badgr-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/500-badgr-2x.png -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/concentricsky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/concentricsky.png -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/info-addapps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/info-addapps.png -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/canvas-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/canvas-settings.png -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/info-addappform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/info-addappform.png -------------------------------------------------------------------------------- /.docker/etc/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | 3 | socket=app.sock 4 | master=true 5 | processes=4 6 | threads=2 7 | chdir=/badgr_server 8 | module=wsgi:application 9 | vacuum=true 10 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/issuer-placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/issuer-placeholder.png -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/issuer-placeholder-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/issuer-placeholder-2x.png -------------------------------------------------------------------------------- /apps/mainsite/templates/error/404.html: -------------------------------------------------------------------------------- 1 | {% extends "error/base.html" %} 2 | 3 | {% block error_content %} 4 |

The page you requested could not be found.

5 | {% endblock %} 6 | 7 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/badgr-canvas-instructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/badgr-canvas-instructions.png -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/1_0_basic_issuer_invalid_json.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Basic Issuer", 3 | "url": "http://a.com/issuer/website" 4 | "EXTRA PROPERTY, NO VALUE NO COMMA. SO INVALID!" 5 | } -------------------------------------------------------------------------------- /apps/mainsite/templates/account/email/email_confirmation_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% autoescape off %} 3 | {% blocktrans %}Confirm Badgr Email Address{% endblocktrans %} 4 | {% endautoescape %} 5 | -------------------------------------------------------------------------------- /apps/mainsite/templates/account/email/email_confirmation_signup_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% autoescape off %} 3 | {% blocktrans %}Confirm Your Badgr Account{% endblocktrans %} 4 | {% endautoescape %} 5 | -------------------------------------------------------------------------------- /apps/badgrlog/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from .views import BadgrLogContextView 4 | 5 | urlpatterns = [ 6 | url(r'^v1$', BadgrLogContextView.as_view(), name='badgr_log_context'), 7 | ] 8 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/screenshots/badgebook-setup/add-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/screenshots/badgebook-setup/add-app.png -------------------------------------------------------------------------------- /apps/badgrlog/events/__init__.py: -------------------------------------------------------------------------------- 1 | from .badgeuser import * 2 | from .backpack import * 3 | from .blacklist import * 4 | from .composition import * 5 | from .email import * 6 | from .issuer import * 7 | from .public import * 8 | -------------------------------------------------------------------------------- /apps/mainsite/templates/account/email/password_reset_confirmation_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% autoescape off %} 3 | {% blocktrans %}Your password has been successfully changed{% endblocktrans %} 4 | {% endautoescape %} 5 | -------------------------------------------------------------------------------- /apps/mainsite/templates/issuer/email/notify_account_holder_message.html: -------------------------------------------------------------------------------- 1 | {% extends "issuer/email/base_notify_award.html" %} 2 | 3 | {% load staticfiles %} 4 | 5 | {% block call_to_action_label %} 6 | Sign In 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /apps/mainsite/templates/issuer/email/notify_earner_message.html: -------------------------------------------------------------------------------- 1 | {% extends "issuer/email/base_notify_award.html" %} 2 | 3 | {% load staticfiles %} 4 | 5 | {% block call_to_action_label %} 6 | Create Account 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/kony/urls.py: -------------------------------------------------------------------------------- 1 | from allauth.socialaccount.providers.oauth.urls import default_urlpatterns 2 | 3 | from badgrsocialauth.providers.kony.provider import KonyProvider 4 | 5 | urlpatterns = default_urlpatterns(KonyProvider) -------------------------------------------------------------------------------- /apps/mainsite/signals.py: -------------------------------------------------------------------------------- 1 | from mainsite.models import AccessTokenScope 2 | 3 | 4 | def handle_token_save(sender, instance=None, **kwargs): 5 | for s in instance.scope.split(): 6 | AccessTokenScope.objects.get_or_create(token=instance, scope=s) -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/screenshots/badgebook-setup/add-app-configuration-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fedora-infra/badgr-server/develop/apps/mainsite/static/badgr-ui/images/screenshots/badgebook-setup/add-app-configuration-type.png -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/1_0_basic_badgeclass.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Basic Badge", 3 | "description": "Basic as it gets. v1.0", 4 | "image": "http://a.com/badgeclass_image", 5 | "criteria": "http://a.com/badgeclass_criteria", 6 | "issuer": "http://a.com/issuer" 7 | } -------------------------------------------------------------------------------- /apps/mainsite/templates/admin/sitewide_actions.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base_site.html" %} 2 | 3 | {% block content %} 4 |
5 | {% csrf_token %} 6 | {{ form.as_p }} 7 | 8 |
9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/1_0_basic_instance_missing_badge_prop.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid":"123abc", 3 | "recipient": {"identity": "test@example.com","hashed": false, "type": "email"}, 4 | "issuedOn": "2015-04-30", 5 | "verify": {"type": "hosted", "url": "http://a.com/instance"} 6 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - 3.7.5 5 | 6 | services: 7 | - mysql 8 | 9 | before_install: 10 | - 'travis_retry sudo apt-get update' 11 | - 'travis_retry sudo apt-get install xmlsec1' 12 | 13 | install: pip install tox-travis 14 | 15 | script: tox 16 | -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/1_0_basic_instance.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid":"123abc", 3 | "recipient": {"identity": "test@example.com","hashed": false, "type": "email"}, 4 | "badge": "http://a.com/badgeclass", 5 | "issuedOn": "2015-04-30", 6 | "verify": {"type": "hosted", "url": "http://a.com/instance"} 7 | } -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/1_0_basic_instance2.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid":"123abd", 3 | "recipient": {"identity": "test@example.com","hashed": false, "type": "email"}, 4 | "badge": "http://a.com/badgeclass", 5 | "issuedOn": "2015-04-30", 6 | "verify": {"type": "hosted", "url": "http://a.com/instance2"} 7 | } -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/1_0_basic_instance3.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid":"123abd", 3 | "recipient": {"identity": "TEST@example.com","hashed": false, "type": "email"}, 4 | "badge": "http://a.com/badgeclass", 5 | "issuedOn": "2015-04-30", 6 | "verify": {"type": "hosted", "url": "http://a.com/instance3"} 7 | } -------------------------------------------------------------------------------- /.docker/Dockerfile.nginx: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | 3 | COPY .docker/etc/nginx.conf /etc/nginx/nginx.conf 4 | COPY .docker/etc/site.conf /etc/nginx/sites-available/ 5 | 6 | RUN mkdir -p /etc/nginx/sites-enabled/\ 7 | && ln -s /etc/nginx/sites-available/site.conf /etc/nginx/sites-enabled/ 8 | 9 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/1_0_basic_instance_with_bad_date.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid":"123abd", 3 | "recipient": {"identity": "test@example.com","hashed": false, "type": "email"}, 4 | "badge": "http://a.com/badgeclass", 5 | "issuedOn": "2015-04-31", 6 | "verify": {"type": "hosted", "url": "http://a.com/instancebaddate"} 7 | } -------------------------------------------------------------------------------- /apps/badgrsocialauth/permissions.py: -------------------------------------------------------------------------------- 1 | from rest_framework import permissions 2 | 3 | 4 | class IsSocialAccountOwner(permissions.BasePermission): 5 | """ 6 | Only grant access to owner of SocialAccount. 7 | """ 8 | 9 | def has_object_permission(self, request, view, obj): 10 | return obj.user == request.user -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/markdown-mark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/badgeuser/account_forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from allauth.account import forms as allauth_forms 4 | 5 | 6 | class AddEmailForm(allauth_forms.AddEmailForm): 7 | email = forms.EmailField( 8 | label="email", required=True, 9 | widget=forms.TextInput(attrs={"type": "email", "size": "30"}) 10 | ) 11 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0004_merge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('badgeuser', '0003_auto_20160210_0313'), 11 | ('badgeuser', '0003_auto_20160309_0820'), 12 | ] 13 | 14 | operations = [ 15 | ] 16 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0010_merge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('badgeuser', '0007_auto_20170427_0724'), 11 | ('badgeuser', '0009_auto_20170427_1509'), 12 | ] 13 | 14 | operations = [ 15 | ] 16 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0006_merge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('mainsite', '0005_auto_20170427_0724'), 11 | ('mainsite', '0005_auto_20170616_1406'), 12 | ] 13 | 14 | operations = [ 15 | ] 16 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/markdown-mark-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0022_merge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0021_remove_badgeinstance_evidence_url'), 11 | ('issuer', '0021_auto_20170424_1427'), 12 | ] 13 | 14 | operations = [ 15 | ] 16 | -------------------------------------------------------------------------------- /.docker/etc/wsgi.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | OUR_DIR = os.path.abspath(os.path.dirname(__file__)) 5 | 6 | APPS_DIR = os.path.join(OUR_DIR, 'apps') 7 | 8 | sys.path.insert(0, APPS_DIR) 9 | 10 | from django.core.wsgi import get_wsgi_application 11 | 12 | os.environ["DJANGO_SETTINGS_MODULE"] = "mainsite.settings_local" 13 | 14 | application = get_wsgi_application() -------------------------------------------------------------------------------- /apps/mainsite/context_processors.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | 4 | def extra_settings(request): 5 | return { 6 | 'HELP_EMAIL': getattr(settings, 'HELP_EMAIL', 'help@badgr.io'), 7 | 'PINGDOM_MONITORING_ID': getattr(settings, 'PINGDOM_MONITORING_ID', None), 8 | 'GOOGLE_ANALYTICS_ID': getattr(settings, 'GOOGLE_ANALYTICS_ID', None), 9 | } 10 | -------------------------------------------------------------------------------- /apps/badgrlog/events/email.py: -------------------------------------------------------------------------------- 1 | from .base import BaseBadgrEvent 2 | 3 | 4 | class EmailRendered(BaseBadgrEvent): 5 | def __init__(self, email): 6 | self.email = email 7 | 8 | def to_representation(self): 9 | return { 10 | 'subject': self.email.subject, 11 | 'fromAddress': self.email.from_email, 12 | 'toAddress': self.email.to 13 | } 14 | -------------------------------------------------------------------------------- /apps/mainsite/celery.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 8/24/15. 2 | 3 | 4 | 5 | from django.conf import settings 6 | from celery import Celery 7 | import os 8 | 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mainsite.settings_local') 10 | app = Celery('mainsite') 11 | 12 | app.config_from_object('django.conf:settings') 13 | app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) 14 | 15 | -------------------------------------------------------------------------------- /apps/badgeuser/permissions.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from rest_framework.permissions import BasePermission 5 | 6 | from badgeuser.models import BadgeUser 7 | 8 | 9 | class BadgeUserIsAuthenticatedUser(BasePermission): 10 | def has_object_permission(self, request, view, obj): 11 | if isinstance(obj, BadgeUser): 12 | return request.user.pk == obj.pk 13 | return False 14 | -------------------------------------------------------------------------------- /apps/externaltools/v1_api_urls.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from django.conf.urls import url 5 | 6 | from externaltools.api import ExternalToolList, ExternalToolLaunch 7 | 8 | urlpatterns = [ 9 | url(r'^$', ExternalToolList.as_view(), name='v1_api_externaltools_list'), 10 | url(r'^launch/(?P[^/]+)/(?P[^/]+)$', ExternalToolLaunch.as_view(), name='v1_api_externaltools_launch'), 11 | ] -------------------------------------------------------------------------------- /apps/issuer/migrations/0036_merge_20171101_0815.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-11-01 15:15 3 | 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0034_badgeinstance_hashed'), 12 | ('issuer', '0035_issuer_badgrapp'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /apps/externaltools/v2_api_urls.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from django.conf.urls import url 5 | 6 | from externaltools.api import ExternalToolList, ExternalToolLaunch 7 | 8 | urlpatterns = [ 9 | url(r'^$', ExternalToolList.as_view(), name='v2_api_externaltools_list'), 10 | url(r'^launch/(?P[^/]+)/(?P[^/]+)$', ExternalToolLaunch.as_view(), name='v2_api_externaltools_launch'), 11 | ] 12 | -------------------------------------------------------------------------------- /apps/mainsite/templates/account/email/email_confirmation_signup_message.txt: -------------------------------------------------------------------------------- 1 | Please verify your email address on Badgr, 2 | {{ email.email }} 3 | 4 | Confirm your email address to activate your Badgr account. 5 | Click the link below, or copy/paste it into your browser url bar. 6 | 7 | {{ activate_url }} 8 | 9 | If you didn't make this request, you can safely ignore this email, 10 | and no action will be taken on your behalf. -------------------------------------------------------------------------------- /.docker/Dockerfile.prod.api: -------------------------------------------------------------------------------- 1 | FROM python:3.7-slim 2 | 3 | RUN mkdir /badgr_server 4 | WORKDIR /badgr_server 5 | 6 | COPY manage.py /badgr_server 7 | COPY .docker/etc/uwsgi.ini /badgr_server 8 | COPY .docker/etc/wsgi.py /badgr_server 9 | COPY apps /badgr_server/apps 10 | COPY .docker/etc/settings_local.py /badgr_server/apps/mainsite/ 11 | 12 | RUN pip install uwsgi 13 | -------------------------------------------------------------------------------- /apps/pathway/public_api_urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from rest_framework.urlpatterns import format_suffix_patterns 3 | 4 | from pathway.public_api import PathwayElementJson 5 | 6 | json_patterns = [ 7 | url(r'^pathways/(?P[^/]+)/(?P[^/]+)$', PathwayElementJson.as_view(), name='pathway_element_json'), 8 | ] 9 | 10 | urlpatterns = format_suffix_patterns(json_patterns, allowed=['json']) 11 | -------------------------------------------------------------------------------- /apps/mainsite/templates/pingdom/embed.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0006_remove_badgeinstance_email.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0005_auto_20150915_1723'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='badgeinstance', 16 | name='email', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0008_auto_20170427_1508.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | from entity.db.migrations import PopulateEntityIdsMigration 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('badgeuser', '0007_auto_20170427_0957'), 13 | ] 14 | 15 | operations = [ 16 | PopulateEntityIdsMigration('badgeuser', 'BadgeUser'), 17 | ] 18 | -------------------------------------------------------------------------------- /.docker/etc/site.conf: -------------------------------------------------------------------------------- 1 | upstream uwsgi { 2 | server unix:/badgr_server/app.sock; 3 | } 4 | 5 | server { 6 | listen 80; 7 | charset utf-8; 8 | 9 | location /media { 10 | alias /badgr_server/mediafiles; 11 | } 12 | 13 | location /static { 14 | alias /badgr_server/staticfiles; 15 | } 16 | 17 | location / { 18 | uwsgi_pass uwsgi; 19 | 20 | include /etc/nginx/uwsgi_params; 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0023_delete_badgraccesstoken.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-06-20 21:25 3 | 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('badgeuser', '0022_auto_20190405_1344'), 12 | ] 13 | 14 | operations = [ 15 | migrations.DeleteModel( 16 | name='BadgrAccessToken', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0021_remove_badgeinstance_evidence_url.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0020_auto_20170420_0811'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='badgeinstance', 16 | name='evidence_url', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.egg 3 | settings_local.py 4 | .*.sw* 5 | *~ 6 | .DS_Store 7 | AppleDouble 8 | *.sqlite* 9 | *.sass-cache 10 | 11 | staticfiles* 12 | mediafiles* 13 | emailfiles* 14 | logs/* 15 | node_modules/* 16 | bower_components/* 17 | npm-debug.log 18 | 19 | .ropeproject 20 | .idea/* 21 | *.iml 22 | 23 | test.cache/ 24 | 25 | .coverage 26 | .tox/ 27 | *.egg-info/ 28 | build/ 29 | dist/ 30 | htmlcov/ 31 | api_spec_v1.json 32 | api_spec_v2.json 33 | 34 | django.log 35 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib.admin import ModelAdmin 2 | from mainsite.admin import badgr_admin 3 | from .models import Saml2Configuration, Saml2Account 4 | 5 | class Saml2ConfigurationModelAdmin(ModelAdmin): 6 | model = Saml2Configuration 7 | 8 | class Saml2AccountModelAdmin(ModelAdmin): 9 | model = Saml2Account 10 | 11 | badgr_admin.register(Saml2Configuration, Saml2ConfigurationModelAdmin) 12 | badgr_admin.register(Saml2Account, Saml2AccountModelAdmin) -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0003_auto_20160210_0313.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('badgeuser', '0002_cachedemailaddress'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelOptions( 15 | name='badgeuser', 16 | options={'verbose_name': 'badge user', 'verbose_name_plural': 'badge users'}, 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0003_auto_20160309_0820.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('badgeuser', '0002_cachedemailaddress'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelOptions( 15 | name='badgeuser', 16 | options={'verbose_name': 'badge user', 'verbose_name_plural': 'badge users'}, 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /apps/badgrlog/badgrlogger.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 8/27/15. 2 | 3 | import logging 4 | from .events.base import BaseBadgrEvent 5 | 6 | 7 | class BadgrLogger(object): 8 | def __init__(self, name='Badgr.Events'): 9 | self.logger = logging.getLogger(name) 10 | 11 | def event(self, event): 12 | if not isinstance(event, BaseBadgrEvent): 13 | raise NotImplementedError() 14 | obj = event.compacted() 15 | self.logger.info(obj) 16 | 17 | 18 | -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/0_5_basic_instance.json: -------------------------------------------------------------------------------- 1 | { 2 | "recipient": "test@example.com", 3 | "badge": { 4 | "version": "0.5.0", 5 | "name": "Basic McBadge", 6 | "image": "http://oldstyle.com/images/1", 7 | "description": "A basic badge.", 8 | "criteria": "http://oldsyle.com/criteria/1", 9 | "issuer": { 10 | "origin": "http://oldstyle.com", 11 | "name": "Basic Issuer" 12 | } 13 | }, 14 | "issued_on": "2011-12-31" 15 | } -------------------------------------------------------------------------------- /apps/mainsite/migrations/0003_auto_20160901_1537.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('mainsite', '0002_badgrapp'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelOptions( 15 | name='emailblacklist', 16 | options={'verbose_name': 'Blacklisted email', 'verbose_name_plural': 'Blacklisted emails'}, 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0005_auto_20170427_0724.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('mainsite', '0004_auto_20170120_1724'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='emailblacklist', 16 | name='email', 17 | field=models.EmailField(unique=True, max_length=254), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0007_badgrapp_ui_connect_success_redirect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('mainsite', '0006_merge'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='badgrapp', 16 | name='ui_connect_success_redirect', 17 | field=models.URLField(null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import os 4 | 5 | # assume 'apps' is a directory with same parent directory as us 6 | APPS_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'apps')) 7 | if APPS_DIR not in sys.path: 8 | sys.path.insert(0, APPS_DIR) 9 | 10 | if __name__ == "__main__": 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mainsite.settings_local") 12 | from django.core.management import execute_from_command_line 13 | execute_from_command_line(sys.argv) 14 | -------------------------------------------------------------------------------- /apps/mainsite/templates/account/email/email_confirmation_message.txt: -------------------------------------------------------------------------------- 1 | Please confirm your email address on Badgr, 2 | {{ email.email }} 3 | 4 | A Badgr user has requested to add this email to their account or use it in a connected application. 5 | Once confirmed, you may upload badges to your Badgr account that have been issued to this address 6 | or use features within connected applications. 7 | 8 | {{ activate_url }} 9 | 10 | If you didn't make this request, you can safely ignore this email, and 11 | no action will be taken on your behalf. 12 | -------------------------------------------------------------------------------- /apps/pathway/migrations/0004_pathway_is_active.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('pathway', '0003_auto_20160415_1030'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='pathway', 16 | name='is_active', 17 | field=models.BooleanField(default=True, db_index=True), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0011_auto_20170619_2301.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | import badgeuser.managers 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('badgeuser', '0010_merge'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterModelManagers( 16 | name='badgeuser', 17 | managers=[ 18 | ('objects', badgeuser.managers.BadgeUserManager()), 19 | ], 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0034_badgeinstance_hashed.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-11-01 14:39 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0033_auto_20171002_1413'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgeinstance', 17 | name='hashed', 18 | field=models.BooleanField(default=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/management/commands/clear_cache.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.core.cache import cache 3 | from django.core.management.base import BaseCommand 4 | 5 | 6 | class Command(BaseCommand): 7 | """A simple management command which clears the site-wide cache.""" 8 | help = 'Fully clear your site-wide cache.' 9 | 10 | def handle(self, *args, **kwargs): 11 | assert settings.CACHES, 'The CACHES setting is not configured!' 12 | cache.clear() 13 | self.stdout.write('Your cache has been cleared!\n') -------------------------------------------------------------------------------- /apps/issuer/migrations/0025_badgeinstance_issued_on.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-07-26 21:09 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0024_auto_20170609_0845'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgeinstance', 17 | name='issued_on', 18 | field=models.DateTimeField(null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0018_auto_20190723_1532.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-07-23 22:32 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('mainsite', '0017_accesstokenscope'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='accesstokenscope', 17 | name='scope', 18 | field=models.CharField(max_length=255), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0021_auto_20191230_1752.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.23 on 2019-12-31 01:52 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('mainsite', '0020_auto_20191114_1056'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgrapp', 17 | name='ui_login_redirect', 18 | field=models.URLField(null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0022_badgrapp_is_default.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.23 on 2020-01-06 22:19 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('mainsite', '0021_auto_20191230_1752'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgrapp', 17 | name='is_default', 18 | field=models.BooleanField(default=False), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/templates/error/base.html: -------------------------------------------------------------------------------- 1 | {% extends "public/base.html" %} 2 | {% load staticfiles %} 3 | 4 | {% block content %} 5 | 6 |
7 | Badgr is sorry :( 8 | {% block error_content %} 9 |

We're sorry, an error has occurred.

10 | {% endblock %} 11 |

12 | 13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/v1_api_urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from badgrsocialauth.api import BadgrSocialAccountList, BadgrSocialAccountDetail, BadgrSocialAccountConnect 4 | 5 | urlpatterns = [ 6 | url(r'^socialaccounts$', BadgrSocialAccountList.as_view(), name='v1_api_user_socialaccount_list'), 7 | url(r'^socialaccounts/connect$', BadgrSocialAccountConnect.as_view(), name='v1_api_user_socialaccount_connect'), 8 | url(r'^socialaccounts/(?P[^/]+)$', BadgrSocialAccountDetail.as_view(), name='v1_api_user_socialaccount_detail') 9 | ] 10 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/v2_api_urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from badgrsocialauth.api import BadgrSocialAccountList, BadgrSocialAccountDetail, BadgrSocialAccountConnect 4 | 5 | urlpatterns = [ 6 | url(r'^socialaccounts$', BadgrSocialAccountList.as_view(), name='v2_api_user_socialaccount_list'), 7 | url(r'^socialaccounts/connect$', BadgrSocialAccountConnect.as_view(), name='v2_api_user_socialaccount_connect'), 8 | url(r'^socialaccounts/(?P[^/]+)$', BadgrSocialAccountDetail.as_view(), name='v2_api_user_socialaccount_detail') 9 | ] 10 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0016_auto_20170214_0749.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0015_auto_20170214_0738'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='issuer', 16 | name='owner', 17 | ), 18 | migrations.RemoveField( 19 | model_name='issuerstaff', 20 | name='editor', 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0009_auto_20170427_1509.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('badgeuser', '0008_auto_20170427_1508'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='badgeuser', 16 | name='entity_id', 17 | field=models.CharField(default=None, unique=True, max_length=254), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0012_badgrapp_public_pages_redirect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-31 04:01 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('mainsite', '0011_auto_20171019_0634'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgrapp', 17 | name='public_pages_redirect', 18 | field=models.URLField(null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0018_termsversion_short_description.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2018-06-12 14:09 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('badgeuser', '0017_auto_20180611_0819'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='termsversion', 17 | name='short_description', 18 | field=models.TextField(blank=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/externaltools/migrations/0004_auto_20180411_0653.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2018-04-11 13:53 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('externaltools', '0003_auto_20180411_0650'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='externaltool', 17 | name='xml_config', 18 | field=models.TextField(blank=True, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0048_auto_20190812_1229.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.21 on 2019-08-12 19:29 3 | 4 | 5 | from django.db import migrations 6 | 7 | def nullify_blanks(apps, schema_editor): 8 | Issuer = apps.get_model('issuer', 'Issuer') 9 | Issuer.objects.filter(source_url='').update(source_url=None) 10 | 11 | class Migration(migrations.Migration): 12 | 13 | dependencies = [ 14 | ('issuer', '0047_badgeinstance_user'), 15 | ] 16 | 17 | operations = [ 18 | migrations.RunPython(nullify_blanks), 19 | ] 20 | -------------------------------------------------------------------------------- /apps/backpack/migrations/0012_auto_20200106_1621.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.23 on 2020-01-07 00:21 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('backpack', '0011_auto_20181102_1438'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='backpackcollection', 17 | name='updated_at', 18 | field=models.DateTimeField(auto_now=True, db_index=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/composition/migrations/0004_auto_20150915_1057.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('composition', '0003_auto_20150914_1447'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='localissuer', 16 | name='image', 17 | field=models.ImageField(null=True, upload_to=b'uploads/issuers', blank=True), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/externaltools/migrations/0007_auto_20190319_1111.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-03-19 18:11 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('externaltools', '0006_auto_20181102_1438'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='externaltoollaunchpoint', 17 | name='launch_url', 18 | field=models.CharField(max_length=1024), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0037_auto_20171113_1015.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-11-13 18:15 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0036_merge_20171101_0815'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeinstance', 17 | name='recipient_identifier', 18 | field=models.EmailField(db_index=True, max_length=1024), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0038_badgeinstance_expires_at.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-12-04 20:36 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0037_auto_20171113_1015'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgeinstance', 17 | name='expires_at', 18 | field=models.DateTimeField(blank=True, default=None, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0044_auto_20180713_0658.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-07-13 13:58 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0043_auto_20180614_0949'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeinstance', 17 | name='recipient_identifier', 18 | field=models.EmailField(db_index=True, max_length=768), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0051_auto_20190826_1604.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-08-26 23:04 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0050_auto_20190813_1945'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeinstance', 17 | name='recipient_identifier', 18 | field=models.CharField(db_index=True, max_length=768), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/recipient/migrations/0012_auto_20181102_1438.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-11-02 21:38 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('recipient', '0011_auto_20171025_1020'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='recipientgroup', 17 | name='created_at', 18 | field=models.DateTimeField(auto_now_add=True, db_index=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/recipient/migrations/0013_auto_20200106_1621.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.23 on 2020-01-07 00:21 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('recipient', '0012_auto_20181102_1438'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='recipientgroup', 17 | name='updated_at', 18 | field=models.DateTimeField(auto_now=True, db_index=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/backpack/migrations/0011_auto_20181102_1438.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-11-02 21:38 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('backpack', '0010_auto_20180802_1026'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='backpackcollection', 17 | name='created_at', 18 | field=models.DateTimeField(auto_now_add=True, db_index=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0027_auto_20170801_1636.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-08-01 23:36 3 | 4 | 5 | import datetime 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('issuer', '0026_auto_20170726_1409'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='badgeinstance', 18 | name='issued_on', 19 | field=models.DateTimeField(default=datetime.datetime.now), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0049_auto_20190812_1232.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.21 on 2019-08-12 19:32 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0048_auto_20190812_1229'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='issuer', 17 | name='source_url', 18 | field=models.CharField(blank=True, default=None, max_length=254, null=True, unique=True), 19 | ), 20 | ] -------------------------------------------------------------------------------- /apps/mainsite/migrations/0013_badgrapp_oauth_authorization_redirect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-11-02 18:12 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('mainsite', '0012_badgrapp_public_pages_redirect'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgrapp', 17 | name='oauth_authorization_redirect', 18 | field=models.URLField(null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/badgeuser/backends.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 9/3/15. 2 | from allauth.account.auth_backends import AuthenticationBackend 3 | from django.contrib.auth.backends import ModelBackend 4 | 5 | from badgeuser.models import BadgeUser 6 | 7 | 8 | class CachedModelBackend(ModelBackend): 9 | def get_user(self, user_id): 10 | try: 11 | return BadgeUser.cached.get(pk=user_id) 12 | except BadgeUser.DoesNotExist: 13 | return None 14 | 15 | 16 | class CachedAuthenticationBackend(CachedModelBackend, AuthenticationBackend): 17 | pass 18 | 19 | -------------------------------------------------------------------------------- /apps/recipient/v2_api_urls.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from django.conf.urls import url 5 | 6 | from recipient.api import IssuerRecipientGroupList, RecipientGroupDetail 7 | 8 | urlpatterns = [ 9 | url(r'^issuers/(?P[^/]+)/recipientGroups$', IssuerRecipientGroupList.as_view(), name='v2_api_issuer_recipient_group_list'), 10 | url(r'^recipientGroups/(?P[^/]+)$', RecipientGroupDetail.as_view(), name='v2_api_recipient_group_detail'), 11 | # url(r'^recipientGroups$', AllRecipientGroupsList.as_view(), name='v2_api_all_recipient_groups_list'), 12 | ] 13 | 14 | 15 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0015_badgrapp_use_auth_code_exchange.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-10-02 13:21 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('mainsite', '0014_applicationinfo_trust_email_verification'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgrapp', 17 | name='use_auth_code_exchange', 18 | field=models.BooleanField(default=False), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /.docker/etc/nginx.conf: -------------------------------------------------------------------------------- 1 | user root; 2 | worker_processes 1; 3 | 4 | error_log /var/log/nginx/error.log warn; 5 | pid /var/run/nginx.pid; 6 | 7 | 8 | events { 9 | worker_connections 1024; 10 | } 11 | 12 | 13 | http { 14 | include /etc/nginx/mime.types; 15 | default_type application/octet-stream; 16 | 17 | sendfile on; 18 | 19 | keepalive_timeout 65; 20 | 21 | gzip on; 22 | gzip_types text/plain application/xml; 23 | gzip_proxied expired no-cache no-store private auth; 24 | gzip_vary on; 25 | 26 | include /etc/nginx/sites-available/*; 27 | } -------------------------------------------------------------------------------- /apps/issuer/migrations/0042_auto_20180220_1150.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2018-02-20 19:50 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0041_badgeinstancebakedimage'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeinstanceevidence', 17 | name='evidence_url', 18 | field=models.CharField(blank=True, default=None, max_length=2083, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0028_auto_20170802_1035.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-08-02 17:35 3 | 4 | 5 | from django.db import migrations, models 6 | import django.utils.timezone 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('issuer', '0027_auto_20170801_1636'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='badgeinstance', 18 | name='issued_on', 19 | field=models.DateTimeField(default=django.utils.timezone.now), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0029_badgeinstance_recipient_type.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-08-15 15:49 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0028_auto_20170802_1035'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgeinstance', 17 | name='recipient_type', 18 | field=models.CharField(choices=[('email', 'email')], default='email', max_length=255), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0014_issuerstaff_role.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0013_auto_20170214_0711'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='issuerstaff', 16 | name='role', 17 | field=models.CharField(default='staff', max_length=254, choices=[('owner', 'Owner'), ('editor', 'Editor'), ('staff', 'Staff')]), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0014_applicationinfo_trust_email_verification.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-09-05 14:20 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('mainsite', '0013_badgrapp_oauth_authorization_redirect'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='applicationinfo', 17 | name='trust_email_verification', 18 | field=models.BooleanField(default=False), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/testrunner.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from django.conf import settings 5 | from django.test.runner import DiscoverRunner 6 | 7 | 8 | class BadgrRunner(DiscoverRunner): 9 | def run_tests(self, test_labels, extra_tests=None, **kwargs): 10 | if not test_labels and extra_tests is None and 'badgebook' in getattr(settings, 'INSTALLED_APPS', []): 11 | badgebook_suite = self.build_suite(('badgebook',)) 12 | extra_tests = badgebook_suite._tests 13 | return super(BadgrRunner, self).run_tests(test_labels, extra_tests=extra_tests, **kwargs) 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /apps/externaltools/migrations/0005_auto_20180802_1026.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-08-02 17:26 3 | 4 | 5 | from django.db import migrations 6 | import django.db.models.manager 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('externaltools', '0004_auto_20180411_0653'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterModelManagers( 17 | name='externaltool', 18 | managers=[ 19 | ('cached', django.db.models.manager.Manager()), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /apps/pathway/migrations/0005_auto_20170217_1104.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('pathway', '0004_pathway_is_active'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='pathwayelement', 16 | name='completion_badgeclass', 17 | field=models.ForeignKey(related_name='completion_elements', blank=True, to='issuer.BadgeClass', null=True), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/backpack/migrations/0004_auto_20170711_1326.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.13 on 2017-07-11 20:26 3 | 4 | 5 | from django.db import migrations 6 | import django.db.models.manager 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('backpack', '0003_backpackcollection_assertions'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterModelManagers( 17 | name='backpackcollection', 18 | managers=[ 19 | ('cached', django.db.models.manager.Manager()), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0002_auto_20150409_1200.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RenameField( 15 | model_name='issuerstaff', 16 | old_name='badgeuser', 17 | new_name='user', 18 | ), 19 | migrations.AlterUniqueTogether( 20 | name='issuerstaff', 21 | unique_together=set([('issuer', 'user')]), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0018_auto_20170413_1054.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | import autoslug.fields 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0017_auto_20170227_1334'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeinstance', 17 | name='slug', 18 | field=autoslug.fields.AutoSlugField(populate_from='get_new_slug', unique=True, max_length=255, editable=False), 19 | preserve_default=True, 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/issuer/testfiles/test_badgeclass.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0011_auto_20171019_0634.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-19 13:34 3 | 4 | 5 | from django.db import migrations, models 6 | import mainsite.models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('mainsite', '0010_auto_20171004_1510'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='applicationinfo', 18 | name='allowed_scopes', 19 | field=models.TextField(validators=[mainsite.models.DefinedScopesValidator()]), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/recipient/migrations/0007_auto_20170509_1529.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | import entity 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('recipient', '0006_auto_20170509_1529'), 13 | ] 14 | 15 | operations = [ 16 | entity.db.migrations.PopulateEntityIdsMigration('recipient', 'RecipientProfile'), 17 | entity.db.migrations.PopulateEntityIdsMigration('recipient', 'RecipientGroup'), 18 | entity.db.migrations.PopulateEntityIdsMigration('recipient', 'RecipientGroupMembership'), 19 | ] 20 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0022_auto_20190405_1344.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-04-05 20:44 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('badgeuser', '0021_auto_20190405_0921'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='userrecipientidentifier', 17 | name='type', 18 | field=models.CharField(choices=[('url', 'URL'), ('telephone', 'Phone Number')], default='url', max_length=9), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/formatters.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 8/27/15. 2 | 3 | import logging 4 | from pythonjsonlogger import jsonlogger 5 | from django.utils import timezone 6 | import datetime 7 | 8 | 9 | class JsonFormatter(jsonlogger.JsonFormatter): 10 | default_time_format = "%Y-%m-%dT%H:%M:%S.%f%z" 11 | 12 | def converter(self, timestamp): 13 | return datetime.datetime.fromtimestamp(timestamp, tz=timezone.utc) 14 | 15 | def formatTime(self, record, datefmt=None): 16 | dt = self.converter(record.created) 17 | return dt.strftime(datefmt if datefmt else self.default_time_format) 18 | 19 | -------------------------------------------------------------------------------- /apps/mainsite/templates/account/email/password_reset_key_message.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with site_name=site.name site_domain=site.domain %}Hello from {{ site_name }}! 2 | 3 | You're receiving this email because you or someone else has requested a password for your user account at {{ site_domain }}. 4 | It can be safely ignored if you did not request this reset. If this is you and you're ready to change your password, click the link below. 5 | {% endblocktrans %} 6 | 7 | {{ password_reset_url }} 8 | 9 | {% blocktrans with site_name=site.name site_domain=site.domain %}Thank you for using {{ site_name }}!{% endblocktrans %} 10 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0002_cachedemailaddress.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('account', '0002_email_max_length'), 11 | ('badgeuser', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='CachedEmailAddress', 17 | fields=[ 18 | ], 19 | options={ 20 | 'proxy': True, 21 | }, 22 | bases=('account.emailaddress', models.Model), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /apps/issuer/testfiles/test_badgeclass_with_no_svg_extension: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/recipient/migrations/0003_recipientgroup_pathways.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('pathway', '0003_auto_20160415_1030'), 11 | ('recipient', '0002_auto_20160331_1418'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='recipientgroup', 17 | name='pathways', 18 | field=models.ManyToManyField(related_name='recipient_groups', to='pathway.Pathway'), 19 | preserve_default=True, 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/backpack/migrations/0003_backpackcollection_assertions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0023_auto_20170531_1044'), 11 | ('backpack', '0002_auto_20170531_1101'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='backpackcollection', 17 | name='assertions', 18 | field=models.ManyToManyField(to='issuer.BadgeInstance', through='backpack.BackpackCollectionBadgeInstance', blank=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0019_auto_20190710_0805.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-07-10 15:05 3 | 4 | 5 | from django.conf import settings 6 | from django.db import migrations 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | migrations.swappable_dependency(settings.OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL), 13 | ('mainsite', '0018_auto_20190723_1532'), 14 | ] 15 | 16 | operations = [ 17 | migrations.AlterUniqueTogether( 18 | name='accesstokenscope', 19 | unique_together=set([('token', 'scope')]), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/composition/migrations/0012_localbadgeinstance_badgeclass.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0017_auto_20170227_1334'), 11 | ('composition', '0011_auto_20170227_0847'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='localbadgeinstance', 17 | name='issuer_badgeclass', 18 | field=models.ForeignKey(blank=True, to='issuer.BadgeClass', null=True), 19 | preserve_default=True, 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0009_badgeinstance_acceptance.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0008_auto_20160322_1404'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='badgeinstance', 16 | name='acceptance', 17 | field=models.CharField(default=b'Accepted', max_length=254, choices=[(b'Unaccepted', b'Unaccepted'), (b'Accepted', b'Accepted'), (b'Rejected', b'Rejected')]), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/templates/account/email/password_reset_confirmation_message.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with site_name=site.name site_domain=site.domain %}Hello from {{ site_name }}! 2 | 3 | The password has been successfully reset for your account at {{ site_domain }}. 4 | You may now log in with your new password. If you did not request this password change, 5 | please use the forgot password link on the login page to reset it to your control, 6 | and contact us immediately at {{ help_email }}. 7 | {% endblocktrans %} 8 | 9 | 10 | {% blocktrans with site_name=site.name site_domain=site.domain %}Thank you for using {{ site_name }}!{% endblocktrans %} 11 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0010_auto_20170120_1724.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0009_badgeinstance_acceptance'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='badgeinstance', 16 | name='acceptance', 17 | field=models.CharField(default=b'Unaccepted', max_length=254, choices=[(b'Unaccepted', b'Unaccepted'), (b'Accepted', b'Accepted'), (b'Rejected', b'Rejected')]), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0020_auto_20170413_1139.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations 5 | 6 | from entity.db.migrations import PopulateEntityIdsMigration 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('issuer', '0019_auto_20170413_1136'), 13 | ('composition', '0010_auto_20170214_0712'), 14 | ] 15 | 16 | operations = [ 17 | PopulateEntityIdsMigration('issuer', 'Issuer'), 18 | PopulateEntityIdsMigration('issuer', 'BadgeClass'), 19 | PopulateEntityIdsMigration('issuer', 'BadgeInstance', entity_class_name='Assertion'), 20 | ] 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='EmailBlacklist', 15 | fields=[ 16 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 17 | ('email', models.EmailField(unique=True, max_length=75)), 18 | ], 19 | options={ 20 | }, 21 | bases=(models.Model,), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0033_auto_20171002_1413.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-02 21:13 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0032_badgeclasstag'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeinstance', 17 | name='recipient_type', 18 | field=models.CharField(choices=[('email', 'email'), ('openBadgeId', 'openBadgeId'), ('telephone', 'telephone'), ('url', 'url')], default='email', max_length=255), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/mainsite/settings_tests.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from cryptography.fernet import Fernet 5 | 6 | from .settings import * 7 | 8 | # disable logging for tests 9 | LOGGING = {} 10 | 11 | DATABASES = { 12 | 'default': { 13 | 'ENGINE': 'django.db.backends.mysql', 14 | 'NAME': 'badgr_server', 15 | 'OPTIONS': { 16 | "init_command": "SET default_storage_engine=InnoDB", 17 | }, 18 | } 19 | } 20 | 21 | CELERY_ALWAYS_EAGER = True 22 | SECRET_KEY = 'aninsecurekeyusedfortesting' 23 | UNSUBSCRIBE_SECRET_KEY = str(SECRET_KEY) 24 | PAGINATION_SECRET_KEY = Fernet.generate_key() 25 | AUTHCODE_SECRET_KEY = Fernet.generate_key() 26 | -------------------------------------------------------------------------------- /apps/composition/migrations/0011_auto_20170227_0847.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('composition', '0010_auto_20170214_0712'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RenameField( 15 | model_name='localbadgeinstance', 16 | old_name='badgeclass', 17 | new_name='local_badgeclass', 18 | ), 19 | migrations.RenameField( 20 | model_name='localbadgeinstance', 21 | old_name='issuer', 22 | new_name='local_issuer', 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0005_auto_20150915_1723.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | def copy_email_into_recipient_identifier(apps, schema_editor): 8 | BadgeInstance = apps.get_model('issuer', 'BadgeInstance') 9 | for badgeinstance in BadgeInstance.objects.all(): 10 | badgeinstance.recipient_identifier = badgeinstance.email 11 | badgeinstance.save() 12 | 13 | 14 | class Migration(migrations.Migration): 15 | 16 | dependencies = [ 17 | ('issuer', '0004_auto_20150915_1722'), 18 | ] 19 | 20 | operations = [ 21 | migrations.RunPython(copy_email_into_recipient_identifier) 22 | ] 23 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/migrations/0002_saml2configuration_cached_metadata.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-07-02 01:10 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('badgrsocialauth', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='saml2configuration', 17 | name='cached_metadata', 18 | field=models.TextField(blank=True, default=b'', help_text=b'If the XML is provided here we avoid making a network request to the metadata_conf_url.'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0014_badgraccesstoken.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-02 21:13 3 | 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('oauth2_provider', '0005_auto_20170514_1141'), 12 | ('badgeuser', '0013_auto_20170725_1305'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='BadgrAccessToken', 18 | fields=[ 19 | ], 20 | options={ 21 | 'proxy': True, 22 | }, 23 | bases=('oauth2_provider.accesstoken',), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0031_auto_20170918_0735.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-09-18 14:35 3 | 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('issuer', '0030_badgeclassalignment'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='badgeinstance', 18 | name='recipient_type', 19 | field=models.CharField(choices=[('email', 'email'), ('id', 'id'), ('telephone', 'telephone'), ('url', 'url')], default='email', max_length=255), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/pathway/migrations/0003_auto_20160415_1030.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('pathway', '0002_auto_20160331_1443'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelOptions( 15 | name='pathwayelementbadge', 16 | options={'ordering': ('ordering',)}, 17 | ), 18 | migrations.AddField( 19 | model_name='pathwayelementbadge', 20 | name='ordering', 21 | field=models.IntegerField(default=99), 22 | preserve_default=True, 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | ## System information & context: 3 | - Operating system you are using: 4 | - Browser & version: 5 | - URL or path of the screen where you encountered this issue or would like to see a new feature: 6 | 7 | ## Description of issue or feature request, including any error messages: 8 | 9 | 10 | 11 | 12 | 13 | --- 14 | Notes (safe to delete): 15 | 16 | - You can also [add a screenshot](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests/) or [add a file](https://github.com/blog/2061-attach-files-to-comments) 17 | - When reporting a feature request, consider writing one or more [user stories](https://www.mountaingoatsoftware.com/agile/user-stories) 18 | -------------------------------------------------------------------------------- /apps/composition/migrations/0003_auto_20150914_1447.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('composition', '0002_auto_20150914_1421'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='localbadgeinstance', 16 | name='email', 17 | ), 18 | migrations.AddField( 19 | model_name='localbadgeinstance', 20 | name='recipient_identifier', 21 | field=models.EmailField(default='', max_length=1024), 22 | preserve_default=False, 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0003_auto_20150512_0657.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0002_auto_20150409_1200'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelOptions( 15 | name='badgeclass', 16 | options={'verbose_name_plural': 'Badge classes'}, 17 | ), 18 | migrations.AlterField( 19 | model_name='badgeinstance', 20 | name='image', 21 | field=models.ImageField(upload_to=b'issued', blank=True), 22 | preserve_default=True, 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/image-failed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0023_auto_20170531_1044.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0022_merge'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='badgeinstance', 16 | name='source', 17 | field=models.CharField(default='local', max_length=254), 18 | ), 19 | migrations.AddField( 20 | model_name='badgeinstance', 21 | name='source_url', 22 | field=models.CharField(default=None, max_length=254, null=True, blank=True), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0006_auto_20161128_0938.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations, IntegrityError, transaction 5 | from allauth.account.adapter import get_adapter 6 | from allauth.account.models import EmailConfirmation 7 | 8 | from badgeuser.models import CachedEmailAddress, BadgeUser, EmailConfirmation 9 | 10 | 11 | def do_nothing(apps, schema_editor): 12 | """ 13 | Replaced with a management task. 14 | """ 15 | pass 16 | 17 | 18 | class Migration(migrations.Migration): 19 | 20 | dependencies = [ 21 | ('badgeuser', '0005_auto_20160901_1537'), 22 | ] 23 | 24 | operations = [ 25 | migrations.RunPython(do_nothing) 26 | ] 27 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0021_auto_20190405_0921.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-04-05 16:21 3 | 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('badgeuser', '0020_userrecipientidentifier'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RenameField( 16 | model_name='userrecipientidentifier', 17 | old_name='format', 18 | new_name='type', 19 | ), 20 | migrations.AlterUniqueTogether( 21 | name='userrecipientidentifier', 22 | unique_together=set([('user', 'type', 'identifier')]), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /apps/badgeuser/signals.py: -------------------------------------------------------------------------------- 1 | import badgrlog 2 | 3 | badgrlogger = badgrlog.BadgrLogger() 4 | 5 | 6 | def log_user_signed_up(sender, **kwargs): 7 | badgrlogger.event(badgrlog.UserSignedUp(**kwargs)) 8 | 9 | 10 | def log_email_confirmed(sender, **kwargs): 11 | badgrlogger.event(badgrlog.EmailConfirmed(**kwargs)) 12 | 13 | 14 | def handle_email_created(sender, instance=None, created=False, **kwargs): 15 | """ 16 | SocialLogin.save saves the user before creating EmailAddress objects. In cases 17 | where the user is not otherwise updated during the login / signup flow, this 18 | leaves user.cached_emails() empty. 19 | """ 20 | if created: 21 | instance.user.publish_method('cached_emails') 22 | -------------------------------------------------------------------------------- /apps/entity/authentication.py: -------------------------------------------------------------------------------- 1 | from rest_framework import exceptions 2 | from rest_framework.authentication import SessionAuthentication 3 | 4 | 5 | class CSRFPermissionDenied(exceptions.PermissionDenied): 6 | pass 7 | 8 | 9 | class ExplicitCSRFSessionAuthentication(SessionAuthentication): 10 | """ 11 | Wrapper class that raises an explicit CSRFPermissionDenied on CSRF failure to facilitate custom behavior in 12 | entity.views.exception_handler. 13 | """ 14 | def enforce_csrf(self, request): 15 | try: 16 | return super(ExplicitCSRFSessionAuthentication, self).enforce_csrf(request) 17 | except exceptions.PermissionDenied as e: 18 | raise CSRFPermissionDenied(e.detail) 19 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0035_issuer_badgrapp.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-31 04:01 3 | 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('mainsite', '0012_badgrapp_public_pages_redirect'), 13 | ('issuer', '0034_auto_20171025_1020'), 14 | ] 15 | 16 | operations = [ 17 | migrations.AddField( 18 | model_name='issuer', 19 | name='badgrapp', 20 | field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='mainsite.BadgrApp'), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0024_auto_20170609_0845.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0023_auto_20170531_1044'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='badgeinstance', 16 | name='original_json', 17 | field=models.TextField(default=None, null=True, blank=True), 18 | ), 19 | migrations.AddField( 20 | model_name='badgeinstanceevidence', 21 | name='original_json', 22 | field=models.TextField(default=None, null=True, blank=True), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0015_badgeuser_badgrapp.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-31 17:13 3 | 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('mainsite', '0012_badgrapp_public_pages_redirect'), 13 | ('badgeuser', '0014_badgraccesstoken'), 14 | ] 15 | 16 | operations = [ 17 | migrations.AddField( 18 | model_name='badgeuser', 19 | name='badgrapp', 20 | field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='mainsite.BadgrApp'), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /apps/pathway/renderers.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from rest_framework.renderers import BrowsableAPIRenderer 5 | 6 | 7 | class PathwayElementHTMLRenderer(BrowsableAPIRenderer): 8 | media_type = 'text/html' 9 | template = 'public/pathway_element.html' 10 | 11 | def get_context(self, data, accepted_media_type, renderer_context): 12 | context = super(PathwayElementHTMLRenderer, self).get_context( 13 | data, accepted_media_type, renderer_context) 14 | 15 | context['issuer'] = renderer_context.get('issuer') 16 | context['pathway'] = renderer_context.get('pathway') 17 | context['pathway_element'] = renderer_context.get('pathway_element') 18 | 19 | return context 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0047_badgeinstance_user.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-07-03 21:21 3 | 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ('issuer', '0046_auto_20181114_1517'), 15 | ] 16 | 17 | operations = [ 18 | migrations.AddField( 19 | model_name='badgeinstance', 20 | name='user', 21 | field=models.ForeignKey(blank=True, null=True, on_delete=models.SET_NULL, to=settings.AUTH_USER_MODEL), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /apps/pathway/api_urls.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 3/30/16. 2 | from django.conf.urls import url 3 | 4 | from pathway.api import PathwayList, PathwayDetail, PathwayElementDetail, PathwayElementList, PathwayCompletionDetail 5 | 6 | urlpatterns = [ 7 | url(r'^(?P[^/]+)$', PathwayDetail.as_view(), name='pathway_detail'), 8 | url(r'^(?P[^/]+)/elements$', PathwayElementList.as_view(), name='pathway_element_list'), 9 | url(r'^(?P[^/]+)/elements/(?P[^/]+)$', PathwayElementDetail.as_view(), name='pathway_element_detail'), 10 | url(r'^(?P[^/]+)/completion/(?P[^/]+)$', PathwayCompletionDetail.as_view(), name='pathway_completion_detail'), 11 | ] 12 | -------------------------------------------------------------------------------- /apps/mainsite/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import sys 4 | import os 5 | import semver 6 | 7 | 8 | __all__ = ['APPS_DIR', 'TOP_DIR', 'get_version'] 9 | 10 | 11 | def get_version(version=None): 12 | if version is None: 13 | from .version import VERSION 14 | version = VERSION 15 | return semver.format_version(*version) 16 | 17 | 18 | # assume we are ./apps/mainsite/__init__.py 19 | APPS_DIR = os.path.dirname(os.path.abspath(os.path.dirname(__file__))) 20 | if APPS_DIR not in sys.path: 21 | sys.path.insert(0, APPS_DIR) 22 | 23 | # Path to the whole project (one level up from apps) 24 | TOP_DIR = os.path.dirname(APPS_DIR) 25 | 26 | # import the celery app so INSTALLED_APPS gets autodiscovered 27 | from .celery import app as celery_app 28 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0043_auto_20180614_0949.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2018-06-14 16:49 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0042_auto_20180220_1150'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeinstance', 17 | name='recipient_identifier', 18 | field=models.EmailField(db_index=True, max_length=768), 19 | ), 20 | migrations.AlterIndexTogether( 21 | name='badgeinstance', 22 | index_together=set([('recipient_identifier', 'badgeclass', 'revoked')]), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /.docker/Dockerfile.dev.api: -------------------------------------------------------------------------------- 1 | FROM python:3.7-slim 2 | 3 | RUN mkdir /badgr_server 4 | WORKDIR /badgr_server 5 | 6 | COPY requirements.txt /badgr_server 7 | COPY manage.py /badgr_server 8 | COPY .docker/etc/uwsgi.ini /badgr_server 9 | COPY .docker/etc/wsgi.py /badgr_server 10 | COPY apps /badgr_server/apps 11 | COPY .docker/etc/settings_local.py /badgr_server/apps/mainsite/ 12 | 13 | RUN apt-get update && apt-get upgrade -y 14 | RUN apt-get install -y default-libmysqlclient-dev \ 15 | python3-dev \ 16 | python3-cairo \ 17 | build-essential 18 | 19 | RUN pip install -r requirements.txt 20 | RUN pip install uwsgi 21 | 22 | 23 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0005_auto_20170616_1406.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('mainsite', '0004_auto_20170120_1724'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='badgrapp', 16 | name='ui_login_redirect', 17 | field=models.URLField(null=True), 18 | preserve_default=True, 19 | ), 20 | migrations.AddField( 21 | model_name='badgrapp', 22 | name='ui_signup_success_redirect', 23 | field=models.URLField(null=True), 24 | preserve_default=True, 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /apps/externaltools/migrations/0003_auto_20180411_0650.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2018-04-11 13:50 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('externaltools', '0002_externaltooluseractivation'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='externaltool', 17 | name='is_active', 18 | field=models.BooleanField(default=True), 19 | ), 20 | migrations.AddField( 21 | model_name='externaltool', 22 | name='requires_user_activation', 23 | field=models.BooleanField(default=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0020_auto_20191114_1056.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.23 on 2019-11-14 18:56 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('mainsite', '0019_auto_20190710_0805'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgrapp', 17 | name='ui_signup_failure_redirect', 18 | field=models.URLField(null=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='badgrapp', 22 | name='ui_login_redirect', 23 | field=models.URLField(default=b'default_redirect', null=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0024_auto_20200106_1621.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.23 on 2020-01-07 00:21 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('badgeuser', '0023_delete_badgraccesstoken'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='termsagreement', 17 | name='updated_at', 18 | field=models.DateTimeField(auto_now=True, db_index=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='termsversion', 22 | name='updated_at', 23 | field=models.DateTimeField(auto_now=True, db_index=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0004_auto_20170120_1724.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('mainsite', '0003_auto_20160901_1537'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='badgrapp', 16 | name='name', 17 | field=models.CharField(default='Badgr', max_length=254), 18 | preserve_default=False, 19 | ), 20 | migrations.AddField( 21 | model_name='badgrapp', 22 | name='signup_redirect', 23 | field=models.URLField(default='https://badgr.io/signup'), 24 | preserve_default=False, 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /.docker/Dockerfile.api: -------------------------------------------------------------------------------- 1 | FROM python:3.7-slim 2 | 3 | RUN mkdir /badgr_server 4 | WORKDIR /badgr_server 5 | 6 | COPY requirements.txt /badgr_server 7 | COPY manage.py /badgr_server 8 | COPY .docker/etc/uwsgi.ini /badgr_server 9 | COPY .docker/etc/wsgi.py /badgr_server 10 | COPY apps /badgr_server/apps 11 | COPY .docker/etc/settings_local.py /badgr_server/apps/mainsite/ 12 | 13 | RUN apt-get update && apt-get upgrade -y 14 | RUN apt-get install -y default-libmysqlclient-dev \ 15 | python3-dev \ 16 | python3-cairo \ 17 | build-essential \ 18 | xmlsec1 19 | 20 | RUN pip install -r requirements.txt 21 | RUN pip install uwsgi 22 | 23 | 24 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0017_auto_20180611_0819.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2018-06-11 15:19 3 | 4 | 5 | from django.db import migrations, models 6 | import django.db.models.manager 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('badgeuser', '0016_auto_20180611_0802'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterModelManagers( 17 | name='termsversion', 18 | managers=[ 19 | ('cached', django.db.models.manager.Manager()), 20 | ], 21 | ), 22 | migrations.AddField( 23 | model_name='termsversion', 24 | name='is_active', 25 | field=models.BooleanField(default=True), 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0019_auto_20181102_1438.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-11-02 21:38 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('badgeuser', '0018_termsversion_short_description'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='termsagreement', 17 | name='created_at', 18 | field=models.DateTimeField(auto_now_add=True, db_index=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='termsversion', 22 | name='created_at', 23 | field=models.DateTimeField(auto_now_add=True, db_index=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/externaltools/migrations/0008_auto_20200106_1621.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.23 on 2020-01-07 00:21 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('externaltools', '0007_auto_20190319_1111'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='externaltool', 17 | name='updated_at', 18 | field=models.DateTimeField(auto_now=True, db_index=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='externaltooluseractivation', 22 | name='updated_at', 23 | field=models.DateTimeField(auto_now=True, db_index=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/externaltools/migrations/0006_auto_20181102_1438.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-11-02 21:38 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('externaltools', '0005_auto_20180802_1026'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='externaltool', 17 | name='created_at', 18 | field=models.DateTimeField(auto_now_add=True, db_index=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='externaltooluseractivation', 22 | name='created_at', 23 | field=models.DateTimeField(auto_now_add=True, db_index=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/kony/tests.py: -------------------------------------------------------------------------------- 1 | from allauth.tests import MockedResponse 2 | 3 | from .provider import KonyProvider 4 | from ..tests.base import BadgrSocialAuthTestCase, BadgrOAuthTestsMixin, DoesNotSendVerificationEmailMixin 5 | 6 | 7 | class KonyProviderTests(DoesNotSendVerificationEmailMixin, BadgrOAuthTestsMixin, BadgrSocialAuthTestCase): 8 | provider_id = KonyProvider.id 9 | 10 | def get_mocked_response(self): 11 | # inferred by looking at KonyProvider implementation 12 | return [ 13 | MockedResponse(200, """ 14 | { 15 | "primary_email": "raymond.penners@intenct.nl", 16 | "first_name": "Raymond", 17 | "user_guid": "ZLARGMFT1M", 18 | "last_name": "Penners" 19 | }""") 20 | ] 21 | -------------------------------------------------------------------------------- /apps/backpack/migrations/0006_backpackcollectionbadgeinstance_badgeuser.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-27 15:37 3 | 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ('backpack', '0005_auto_20171025_1020'), 15 | ] 16 | 17 | operations = [ 18 | migrations.AddField( 19 | model_name='backpackcollectionbadgeinstance', 20 | name='badgeuser', 21 | field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0008_auto_20160322_1404.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0007_auto_20151117_1555'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='badgeclass', 16 | name='issuer', 17 | field=models.ForeignKey(related_name='badgeclasses', to='issuer.Issuer'), 18 | preserve_default=True, 19 | ), 20 | migrations.AlterField( 21 | model_name='badgeinstance', 22 | name='badgeclass', 23 | field=models.ForeignKey(related_name='badgeinstances', to='issuer.BadgeClass'), 24 | preserve_default=True, 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/image-placeholder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | badge-empty 9 | Created with Sketch. 10 | 12 | 13 | -------------------------------------------------------------------------------- /apps/composition/migrations/0006_auto_20160928_0648.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('composition', '0005_auto_20151117_1555'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='localbadgeclass', 16 | name='image_preview_status', 17 | field=models.IntegerField(default=None, null=True, blank=True), 18 | preserve_default=True, 19 | ), 20 | migrations.AddField( 21 | model_name='localissuer', 22 | name='image_preview_status', 23 | field=models.IntegerField(default=None, null=True, blank=True), 24 | preserve_default=True, 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0050_auto_20190813_1945.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.21 on 2019-08-14 02:45 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0049_auto_20190812_1232'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeclass', 17 | name='source_url', 18 | field=models.CharField(blank=True, default=None, max_length=254, null=True, unique=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='badgeinstance', 22 | name='source_url', 23 | field=models.CharField(blank=True, default=None, max_length=254, null=True, unique=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/badgeuser/forms.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.forms import UserCreationForm, UserChangeForm 2 | from django import forms 3 | 4 | from .models import BadgeUser 5 | 6 | 7 | class BadgeUserCreationForm(UserCreationForm): 8 | """ 9 | A form that creates a user, with no privileges, from the given email and 10 | password. 11 | """ 12 | 13 | class Meta: 14 | model = BadgeUser 15 | fields = ("email", "first_name", "last_name") 16 | 17 | def signup(self, request, user): 18 | pass 19 | 20 | 21 | class BadgeUserChangeForm(UserChangeForm): 22 | """A form for updating users. Includes all the fields on 23 | the user, but replaces the password field with admin's 24 | password hash display field. 25 | """ 26 | 27 | class Meta: 28 | model = BadgeUser 29 | exclude = [] 30 | 31 | 32 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0013_auto_20170725_1305.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-07-25 20:05 3 | 4 | 5 | import django.contrib.auth.validators 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('badgeuser', '0012_auto_20170711_1326'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='badgeuser', 18 | name='username', 19 | field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.ASCIIUsernameValidator()], verbose_name='username'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0026_auto_20170726_1409.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-07-26 21:09 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | def created_at_to_issued_on(apps, schema_editor): 9 | BadgeInstance = apps.get_model('issuer', 'BadgeInstance') 10 | for badge in BadgeInstance.objects.all(): 11 | badge.issued_on = badge.created_at 12 | badge.save() 13 | 14 | 15 | class Migration(migrations.Migration): 16 | 17 | dependencies = [ 18 | ('issuer', '0025_badgeinstance_issued_on'), 19 | ] 20 | 21 | operations = [ 22 | migrations.RunPython(created_at_to_issued_on), 23 | migrations.AlterField( 24 | model_name='badgeinstance', 25 | name='issued_on', 26 | field=models.DateTimeField(), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /apps/backpack/share_urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from backpack.views import LegacyBadgeShareRedirectView, RedirectSharedCollectionView, LegacyCollectionShareRedirectView 4 | 5 | urlpatterns = [ 6 | # legacy redirects 7 | 8 | url(r'^share/?collection/(?P[^/]+)(/embed)?$', RedirectSharedCollectionView.as_view(), name='redirect_backpack_shared_collection'), 9 | url(r'^share/?badge/(?P[^/]+)$', LegacyBadgeShareRedirectView.as_view(), name='legacy_redirect_backpack_shared_badge'), 10 | 11 | url(r'^earner/collections/(?P[^/]+)/(?P[^/]+)$', LegacyCollectionShareRedirectView.as_view(), name='legacy_shared_collection'), 12 | url(r'^earner/collections/(?P[^/]+)/(?P[^/]+)/embed$', LegacyCollectionShareRedirectView.as_view(), name='legacy_shared_collection_embed'), 13 | ] 14 | 15 | -------------------------------------------------------------------------------- /apps/recipient/migrations/0009_auto_20170509_1937.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | from django.conf import settings 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('recipient', '0008_auto_20170509_1531'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='recipientgroup', 17 | name='updated_at', 18 | ), 19 | migrations.RemoveField( 20 | model_name='recipientgroup', 21 | name='updated_by', 22 | ), 23 | migrations.AlterField( 24 | model_name='recipientgroup', 25 | name='created_by', 26 | field=models.ForeignKey(related_name='+', blank=True, to=settings.AUTH_USER_MODEL, null=True), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0045_auto_20181104_1847.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-11-05 02:47 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0044_auto_20180713_0658'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='badgeclass', 17 | name='expires_amount', 18 | field=models.IntegerField(blank=True, default=None, null=True), 19 | ), 20 | migrations.AddField( 21 | model_name='badgeclass', 22 | name='expires_duration', 23 | field=models.CharField(blank=True, choices=[('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months'), ('years', 'Years')], default=None, max_length=254, null=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/mainsite/management/commands/testserver.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from django.contrib.staticfiles.management.commands.runserver import Command as RunserverCommand 4 | from django.core.management import call_command 5 | from django.test.runner import setup_databases 6 | 7 | from mainsite import TOP_DIR 8 | 9 | 10 | class Command(RunserverCommand): 11 | args = '' 12 | help = 'Builds a test database, and runs a test runserver' 13 | 14 | def handle(self, *args, **options): 15 | if len(args) < 1: 16 | args = ["8001"] 17 | if not options.get('settings'): 18 | os.environ['DJANGO_SETTINGS_MODULE'] = 'mainsite.settings_testserver' 19 | setup_databases(verbosity=1, interactive=False) 20 | call_command("loaddata", os.path.join(TOP_DIR, "fixtures", "testserver.json")) 21 | return super(Command, self).handle(*args, **options) 22 | -------------------------------------------------------------------------------- /apps/backpack/migrations/0007_auto_20171027_0837.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-27 15:37 3 | 4 | 5 | from django.db import migrations 6 | 7 | 8 | def populate_backpackcollectionbadgeinstance_user(apps, schema_editor): 9 | BackpackCollectionBadgeInstance = apps.get_model('backpack', 'BackpackCollectionBadgeInstance') 10 | for collect in BackpackCollectionBadgeInstance.objects.all(): 11 | collect.badgeuser_id = collect.collection.created_by_id 12 | collect.save() 13 | 14 | 15 | def noop(apps, schema_editor): 16 | pass 17 | 18 | 19 | class Migration(migrations.Migration): 20 | 21 | dependencies = [ 22 | ('backpack', '0006_backpackcollectionbadgeinstance_badgeuser'), 23 | ] 24 | 25 | operations = [ 26 | migrations.RunPython(populate_backpackcollectionbadgeinstance_user, reverse_code=noop) 27 | ] 28 | -------------------------------------------------------------------------------- /apps/pathway/migrations/0006_auto_20170413_1054.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | import autoslug.fields 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('pathway', '0005_auto_20170217_1104'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='pathway', 17 | name='slug', 18 | field=autoslug.fields.AutoSlugField(populate_from=b'populate_slug', unique=True, max_length=254, editable=False), 19 | preserve_default=True, 20 | ), 21 | migrations.AlterField( 22 | model_name='pathwayelement', 23 | name='slug', 24 | field=autoslug.fields.AutoSlugField(populate_from=b'name', unique=True, max_length=254, editable=False), 25 | preserve_default=True, 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /apps/backpack/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib.admin import ModelAdmin, TabularInline 2 | 3 | from mainsite.admin import badgr_admin 4 | from .models import (BackpackCollection, ) 5 | 6 | 7 | ### 8 | # 9 | # Collection 10 | # 11 | ### 12 | 13 | 14 | class CollectionInstanceInline(TabularInline): 15 | model = BackpackCollection.assertions.through 16 | extra = 0 17 | raw_id_fields = ('badgeinstance',) 18 | 19 | 20 | class CollectionAdmin(ModelAdmin): 21 | list_display = ('created_by', 'name', 'entity_id', ) 22 | search_fields = ('created_by__email', 'name', 'entity_id') 23 | fieldsets = ( 24 | (None, {'fields': ('created_by', 'name', 'entity_id', 'description', 'share_hash')}), 25 | ) 26 | readonly_fields = ('created_by', 'entity_id') 27 | inlines = [ 28 | CollectionInstanceInline, 29 | ] 30 | pass 31 | badgr_admin.register(BackpackCollection, CollectionAdmin) 32 | -------------------------------------------------------------------------------- /apps/backpack/migrations/0008_auto_20171204_1236.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-12-04 20:36 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('backpack', '0007_auto_20171027_0837'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='backpackbadgeshare', 17 | name='provider', 18 | field=models.CharField(choices=[(b'twitter', b'Twitter'), (b'facebook', b'Facebook'), (b'linkedin', b'LinkedIn')], max_length=254), 19 | ), 20 | migrations.AlterField( 21 | model_name='backpackcollectionshare', 22 | name='provider', 23 | field=models.CharField(choices=[(b'twitter', b'Twitter'), (b'facebook', b'Facebook'), (b'linkedin', b'LinkedIn')], max_length=254), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0012_auto_20170711_1326.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.13 on 2017-07-11 20:26 3 | 4 | 5 | import django.core.validators 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('badgeuser', '0011_auto_20170619_2301'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='badgeuser', 18 | name='username', 19 | field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=30, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], verbose_name='username'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0032_badgeclasstag.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-09-18 14:36 3 | 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('issuer', '0031_auto_20170918_0735'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='BadgeClassTag', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('name', models.CharField(db_index=True, max_length=254)), 21 | ('badgeclass', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='issuer.BadgeClass')), 22 | ], 23 | options={ 24 | 'abstract': False, 25 | }, 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /wsgi.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | # assume we(this file) have a parent that is a sibling to the CODE_DIR 5 | OUR_DIR = os.path.abspath(os.path.dirname(__file__)) 6 | 7 | # code dir is one level above us 8 | APPS_DIR = os.path.join(OUR_DIR, '..', 'code', 'apps') 9 | 10 | # the env dir is one level above us 11 | ENV_DIR = os.path.join(OUR_DIR, '..', 'env') 12 | 13 | # activate the virtualenv 14 | activate_this = os.path.join(ENV_DIR, 'bin', 'activate_this.py') 15 | exec(compile(open(activate_this, "rb").read(), activate_this, 'exec'), dict(__file__=activate_this)) 16 | 17 | # add the apps directory to the python path 18 | sys.path.insert(0, APPS_DIR) 19 | 20 | # load up django 21 | from django.core.wsgi import get_wsgi_application 22 | 23 | # tell django to find settings entry point' 24 | os.environ['DJANGO_SETTINGS_MODULE'] = 'mainsite.settings_local' 25 | 26 | # hand off to the wsgi application 27 | application = get_wsgi_application() 28 | -------------------------------------------------------------------------------- /apps/mainsite/management/commands/dist.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pkg_resources 3 | import sys 4 | 5 | from django.core.management import call_command 6 | from django.core.management.base import BaseCommand, CommandError 7 | from subprocess import call 8 | 9 | import mainsite 10 | from mainsite import TOP_DIR 11 | 12 | 13 | class Command(BaseCommand): 14 | args = '' 15 | help = 'Runs build tasks to compile javascript and css' 16 | 17 | def handle(self, *args, **options): 18 | dirname = os.path.join(TOP_DIR, 'apps', 'mainsite', 'static', 'swagger-ui') 19 | if not os.path.exists(dirname): 20 | os.makedirs(dirname) 21 | 22 | call_command('generate_swagger_spec', 23 | output=os.path.join(dirname, 'api_spec_{version}.json'), 24 | preamble=os.path.join(dirname, "API_DESCRIPTION_{version}.md"), 25 | versions=['v1', 'v2'], 26 | include_oauth2_security=True 27 | ) 28 | -------------------------------------------------------------------------------- /apps/badgeuser/middleware.py: -------------------------------------------------------------------------------- 1 | from django.core.exceptions import ImproperlyConfigured 2 | from django.core.urlresolvers import reverse 3 | from django.http import HttpResponseRedirect 4 | 5 | 6 | class InactiveUserMiddleware(object): 7 | def process_request(self, request): 8 | if not hasattr(request, 'user'): 9 | raise ImproperlyConfigured( 10 | "The Django remote user auth middleware requires the" 11 | " authentication middleware to be installed. Edit your" 12 | " MIDDLEWARE_CLASSES setting to insert" 13 | " 'django.contrib.auth.middleware.AuthenticationMiddleware'" 14 | " before the InactiveAccountMiddleware class.") 15 | if (request.user.is_authenticated() and 16 | request.user.is_active == False and 17 | request.path != reverse('account_enabled')): 18 | return HttpResponseRedirect(reverse('account_enabled')) 19 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/twitter/provider.py: -------------------------------------------------------------------------------- 1 | from urllib.parse import urlparse 2 | 3 | from allauth.account.models import EmailAddress 4 | from allauth.socialaccount import providers 5 | from allauth.socialaccount.providers.twitter.provider import TwitterProvider, TwitterAccount 6 | from django.core.exceptions import ValidationError 7 | 8 | from badgeuser.models import UserRecipientIdentifier 9 | 10 | 11 | class TwitterProviderWithIdentifier(TwitterProvider): 12 | id = 'twitter' 13 | name = 'Twitter' 14 | package = 'allauth.socialaccount.providers.twitter' 15 | account_class = TwitterAccount 16 | 17 | def extract_common_fields(self, data): 18 | common_fields = super(TwitterProviderWithIdentifier, self).extract_common_fields(data) 19 | common_fields['url'] = 'https://twitter.com/{}'.format(data.get('screen_name')) 20 | return common_fields 21 | 22 | providers.registry.register(TwitterProviderWithIdentifier) 23 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0052_auto_20200106_1621.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.23 on 2020-01-07 00:21 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0051_auto_20190826_1604'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeclass', 17 | name='updated_at', 18 | field=models.DateTimeField(auto_now=True, db_index=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='badgeinstance', 22 | name='updated_at', 23 | field=models.DateTimeField(auto_now=True, db_index=True), 24 | ), 25 | migrations.AlterField( 26 | model_name='issuer', 27 | name='updated_at', 28 | field=models.DateTimeField(auto_now=True, db_index=True), 29 | ), 30 | ] 31 | -------------------------------------------------------------------------------- /apps/recipient/migrations/0008_auto_20170509_1531.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('recipient', '0007_auto_20170509_1529'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='recipientgroup', 16 | name='entity_id', 17 | field=models.CharField(default=None, unique=True, max_length=254), 18 | ), 19 | migrations.AlterField( 20 | model_name='recipientgroupmembership', 21 | name='entity_id', 22 | field=models.CharField(default=None, unique=True, max_length=254), 23 | ), 24 | migrations.AlterField( 25 | model_name='recipientprofile', 26 | name='entity_id', 27 | field=models.CharField(default=None, unique=True, max_length=254), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0007_auto_20170427_0957.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | from entity.db.migrations import PopulateEntityIdsMigration 7 | from mainsite.utils import generate_entity_uri 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | ('badgeuser', '0006_auto_20161128_0938'), 14 | ] 15 | 16 | operations = [ 17 | migrations.AddField( 18 | model_name='badgeuser', 19 | name='entity_id', 20 | field=models.CharField(default=None, null=True, max_length=254), 21 | preserve_default=True, 22 | ), 23 | migrations.AddField( 24 | model_name='badgeuser', 25 | name='entity_version', 26 | field=models.PositiveIntegerField(default=1), 27 | preserve_default=True, 28 | ), 29 | PopulateEntityIdsMigration('badgeuser', 'BadgeUser') 30 | ] 31 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from badgeuser.models import BadgeUser 3 | 4 | class Saml2Configuration(models.Model): 5 | metadata_conf_url = models.URLField(verbose_name="Metadata Configuration URL", help_text="The URL for the XML configuration for SAML2 flows. Get this from the Identity Provider Application.") 6 | cached_metadata = models.TextField(default='', blank=True, help_text="If the XML is provided here we avoid making a network request to the metadata_conf_url.") 7 | slug = models.CharField(max_length=32, unique=True, help_text="This slug must be prefixed with saml2.") 8 | 9 | def __str__(self): 10 | return self.slug 11 | 12 | class Saml2Account(models.Model): 13 | user = models.ForeignKey(BadgeUser) 14 | config = models.ForeignKey(Saml2Configuration) 15 | uuid = models.CharField(max_length=255, unique=True) 16 | 17 | def __str__(self): 18 | return "{} on {}".format(self.uuid, self.config) -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/facebook/provider.py: -------------------------------------------------------------------------------- 1 | from allauth.account.models import EmailAddress 2 | from allauth.socialaccount import providers 3 | from allauth.socialaccount.providers.facebook.provider import FacebookProvider, FacebookAccount 4 | 5 | 6 | class VerifiedFacebookProvider(FacebookProvider): 7 | id = 'facebook' 8 | name = 'Facebook' 9 | package = 'allauth.socialaccount.providers.facebook' 10 | account_class = FacebookAccount 11 | 12 | def extract_email_addresses(self, data): 13 | """ 14 | Force verification of email addresses 15 | """ 16 | ret = [] 17 | email = data.get('email') 18 | if email and data.get('email'): 19 | ret.append(EmailAddress(email=email, 20 | verified=True, # Originally verified=False 21 | primary=True)) 22 | return ret 23 | 24 | providers.registry.register(VerifiedFacebookProvider) 25 | -------------------------------------------------------------------------------- /apps/badgeuser/v1_api_urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from badgeuser.api import BadgeUserToken, BadgeUserForgotPassword, BadgeUserEmailConfirm, BadgeUserDetail 4 | from badgeuser.api_v1 import BadgeUserEmailList, BadgeUserEmailDetail 5 | 6 | urlpatterns = [ 7 | url(r'^auth-token$', BadgeUserToken.as_view(), name='v1_api_user_auth_token'), 8 | url(r'^profile$', BadgeUserDetail.as_view(), name='v1_api_user_profile'), 9 | url(r'^forgot-password$', BadgeUserForgotPassword.as_view(), name='v1_api_auth_forgot_password'), 10 | url(r'^emails$', BadgeUserEmailList.as_view(), name='v1_api_user_emails'), 11 | url(r'^emails/(?P[^/]+)$', BadgeUserEmailDetail.as_view(), name='v1_api_user_email_detail'), 12 | url(r'^legacyconfirmemail/(?P[^/]+)$', BadgeUserEmailConfirm.as_view(), name='legacy_user_email_confirm'), 13 | url(r'^confirmemail/(?P[^/]+)$', BadgeUserEmailConfirm.as_view(), name='v1_api_user_email_confirm') 14 | ] 15 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0046_auto_20181114_1517.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-11-14 23:17 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('issuer', '0045_auto_20181104_1847'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='badgeclass', 17 | name='created_at', 18 | field=models.DateTimeField(auto_now_add=True, db_index=True), 19 | ), 20 | migrations.AlterField( 21 | model_name='badgeinstance', 22 | name='created_at', 23 | field=models.DateTimeField(auto_now_add=True, db_index=True), 24 | ), 25 | migrations.AlterField( 26 | model_name='issuer', 27 | name='created_at', 28 | field=models.DateTimeField(auto_now_add=True, db_index=True), 29 | ), 30 | ] 31 | -------------------------------------------------------------------------------- /apps/recipient/migrations/0011_auto_20171025_1020.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-25 17:20 3 | 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ('recipient', '0010_auto_20170711_1326'), 15 | ] 16 | 17 | operations = [ 18 | migrations.AddField( 19 | model_name='recipientgroup', 20 | name='updated_at', 21 | field=models.DateTimeField(auto_now=True), 22 | ), 23 | migrations.AddField( 24 | model_name='recipientgroup', 25 | name='updated_by', 26 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /apps/backpack/migrations/0010_auto_20180802_1026.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.13 on 2018-08-02 17:26 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('backpack', '0009_auto_20180119_0711'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='backpackbadgeshare', 17 | name='provider', 18 | field=models.CharField(choices=[(b'twitter', b'Twitter'), (b'facebook', b'Facebook'), (b'linkedin', b'LinkedIn'), (b'pinterest', b'Pinterest')], max_length=254), 19 | ), 20 | migrations.AlterField( 21 | model_name='backpackcollectionshare', 22 | name='provider', 23 | field=models.CharField(choices=[(b'twitter', b'Twitter'), (b'facebook', b'Facebook'), (b'linkedin', b'LinkedIn'), (b'pinterest', b'Pinterest')], max_length=254), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /apps/backpack/migrations/0005_auto_20171025_1020.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-25 17:20 3 | 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ('backpack', '0004_auto_20170711_1326'), 15 | ] 16 | 17 | operations = [ 18 | migrations.AddField( 19 | model_name='backpackcollection', 20 | name='updated_at', 21 | field=models.DateTimeField(auto_now=True), 22 | ), 23 | migrations.AddField( 24 | model_name='backpackcollection', 25 | name='updated_by', 26 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0017_accesstokenscope.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-07-10 14:35 3 | 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL), 14 | ('mainsite', '0016_auto_20181003_0903'), 15 | ] 16 | 17 | operations = [ 18 | migrations.CreateModel( 19 | name='AccessTokenScope', 20 | fields=[ 21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 22 | ('scope', models.CharField(max_length=256)), 23 | ('token', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL)), 24 | ], 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /apps/mainsite/settings_testserver.py: -------------------------------------------------------------------------------- 1 | from mainsite.settings import * 2 | 3 | DATABASES = { 4 | 'default': { 5 | 'ENGINE': 'django.db.backends.mysql', 6 | 'NAME': 'badgr', 7 | 'OPTIONS': { 8 | # "init_command": "SET storage_engine=InnoDB", # Uncomment when using MySQL to ensure consistency across servers 9 | }, 10 | } 11 | } 12 | 13 | CACHES = { 14 | 'default': { 15 | 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 16 | 'LOCATION': '127.0.0.1:11211', 17 | 'KEY_PREFIX': 'test_badgr_', 18 | 'VERSION': 1, 19 | } 20 | } 21 | 22 | 23 | # django test speedups 24 | PASSWORD_HASHERS = ( 25 | 'django.contrib.auth.hashers.MD5PasswordHasher', 26 | ) 27 | DEBUG = False 28 | logging.disable(logging.CRITICAL) 29 | 30 | # EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend" 31 | 32 | CELERY_ALWAYS_EAGER = True 33 | CELERY_EAGER_PROPAGATES_EXCEPTIONS = True 34 | BROKER_BACKEND = 'memory' 35 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0015_auto_20170214_0738.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | def noop(apps, schema): 8 | pass 9 | 10 | 11 | def update_staff_role(apps, schema): 12 | IssuerStaff = apps.get_model('issuer', 'IssuerStaff') 13 | Issuer = apps.get_model('issuer', 'Issuer') 14 | for staff in IssuerStaff.objects.all(): 15 | if staff.editor and staff.role != 'editor': 16 | staff.role = 'editor' 17 | staff.save() 18 | 19 | for issuer in Issuer.objects.all(): 20 | new_staff, created = IssuerStaff.objects.get_or_create(issuer=issuer, user=issuer.owner, defaults={ 21 | 'role': 'owner' 22 | }) 23 | new_staff.save() 24 | 25 | 26 | class Migration(migrations.Migration): 27 | 28 | dependencies = [ 29 | ('issuer', '0014_issuerstaff_role'), 30 | ] 31 | 32 | operations = [ 33 | migrations.RunPython(update_staff_role, reverse_code=noop) 34 | ] 35 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0020_auto_20170420_0811.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | from django.db.migrations import RunPython 6 | 7 | 8 | def noop(apps, schema): 9 | pass 10 | 11 | 12 | def migrate_evidence_url_to_badgeinstanceevidence(apps, schema): 13 | BadgeInstance = apps.get_model('issuer', 'BadgeInstance') 14 | BadgeInstanceEvidence = apps.get_model('issuer', 'BadgeInstanceEvidence') 15 | for assertion in BadgeInstance.objects.all(): 16 | if assertion.evidence_url: 17 | evidence, created = BadgeInstanceEvidence.objects.get_or_create( 18 | badgeinstance=assertion, 19 | evidence_url=assertion.evidence_url) 20 | 21 | 22 | class Migration(migrations.Migration): 23 | 24 | dependencies = [ 25 | ('issuer', '0019_auto_20170420_0810'), 26 | ] 27 | 28 | operations = [ 29 | RunPython(migrate_evidence_url_to_badgeinstanceevidence, reverse_code=noop) 30 | ] 31 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/badge-loading.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /apps/backpack/tests/testfiles/2_0_assertion_embedded_badgeclass.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "http://a.com/assertion-embedded1", 5 | "badge": { 6 | "type": "BadgeClass", 7 | "id": "urn:uuid:8b4efa06-41bc-4f53-a80d-e3d5e063c936", 8 | "name": "Embedded badgeclass", 9 | "description": "bespoke embedded badgeclass", 10 | "criteria": { 11 | "narrative": "do it" 12 | }, 13 | "image": "http://a.com/badgeclass_image", 14 | "issuer": { 15 | "type": "Issuer", 16 | "name": "Basic Issuer", 17 | "url": "http://a.com/issuer/website" 18 | } 19 | }, 20 | "verify": { 21 | "url": "http://a.com/assertion-embedded1", 22 | "type": "hosted" 23 | }, 24 | "issuedOn": "2017-06-29T21:50:14+00:00", 25 | "recipient": { 26 | "type": "email", 27 | "hashed": false, 28 | "identity": "test@example.com" 29 | } 30 | } -------------------------------------------------------------------------------- /apps/issuer/migrations/0039_badgeclassextension.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2018-01-08 16:57 3 | 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('issuer', '0038_badgeinstance_expires_at'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='BadgeClassExtension', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('name', models.CharField(max_length=254)), 21 | ('original_json', models.TextField(blank=True, default=None, null=True)), 22 | ('badgeclass', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='issuer.BadgeClass')), 23 | ], 24 | options={ 25 | 'abstract': False, 26 | }, 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0021_auto_20170424_1427.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0020_auto_20170413_1139'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='badgeclass', 16 | name='entity_id', 17 | field=models.CharField(default=None, unique=True, max_length=254), 18 | preserve_default=True, 19 | ), 20 | migrations.AlterField( 21 | model_name='badgeinstance', 22 | name='entity_id', 23 | field=models.CharField(default=None, unique=True, max_length=254), 24 | preserve_default=True, 25 | ), 26 | migrations.AlterField( 27 | model_name='issuer', 28 | name='entity_id', 29 | field=models.CharField(default=None, unique=True, max_length=254), 30 | preserve_default=True, 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/badge-failed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | 20 | 21 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/providers/kony/provider.py: -------------------------------------------------------------------------------- 1 | from allauth.socialaccount import providers 2 | from allauth.socialaccount.providers.base import ProviderAccount 3 | from allauth.socialaccount.providers.oauth.provider import OAuthProvider 4 | 5 | from badgeuser.models import CachedEmailAddress 6 | 7 | 8 | class KonyAccount(ProviderAccount): 9 | pass 10 | 11 | 12 | class KonyProvider(OAuthProvider): 13 | id = 'kony' 14 | name = 'Kony' 15 | package = 'badgrsocialauth.providers.kony' 16 | account_class = KonyAccount 17 | 18 | def extract_uid(self, data): 19 | return data['user_guid'] 20 | 21 | def extract_common_fields(self, data): 22 | return { 23 | 'email': data['primary_email'], 24 | 'first_name': data['first_name'], 25 | 'last_name': data['last_name'] 26 | } 27 | 28 | def extract_email_addresses(self, data): 29 | return [CachedEmailAddress(email=data['primary_email'], verified=True, primary=True)] 30 | 31 | 32 | providers.registry.register(KonyProvider) 33 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0007_auto_20151117_1555.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0006_remove_badgeinstance_email'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='badgeclass', 16 | name='image', 17 | field=models.FileField(upload_to=b'uploads/badges', blank=True), 18 | preserve_default=True, 19 | ), 20 | migrations.AlterField( 21 | model_name='badgeinstance', 22 | name='image', 23 | field=models.FileField(upload_to=b'uploads/badges', blank=True), 24 | preserve_default=True, 25 | ), 26 | migrations.AlterField( 27 | model_name='issuer', 28 | name='image', 29 | field=models.FileField(null=True, upload_to=b'uploads/issuers', blank=True), 30 | preserve_default=True, 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /apps/recipient/v1_api_urls.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 3/31/16. 2 | from django.conf.urls import url 3 | 4 | from recipient.api import IssuerRecipientGroupList, RecipientGroupDetail 5 | from recipient.api_v1 import RecipientGroupMembershipList, RecipientGroupMembershipDetail 6 | 7 | urlpatterns = [ 8 | # views shared with v2 9 | url(r'^issuers/(?P[^/]+)/recipient-groups$', IssuerRecipientGroupList.as_view(), name='v1_api_recipient_group_list'), 10 | url(r'^issuers/(?P[^/]+)/recipient-groups/(?P[^/]+)$', RecipientGroupDetail.as_view(), name='v1_api_recipient_group_detail'), 11 | 12 | # views only on v1 13 | url(r'^issuers/(?P[^/]+)/recipient-groups/(?P[^/]+)/members$', RecipientGroupMembershipList.as_view(), name='v1_api_recipient_group_membership_list'), 14 | url(r'^issuers/(?P[^/]+)/recipient-groups/(?P[^/]+)/members/(?P[^/]+)$', RecipientGroupMembershipDetail.as_view(), name='v1_api_recipient_group_membership_detail'), 15 | 16 | ] -------------------------------------------------------------------------------- /apps/entity/db/migrations.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from django.db.migrations import RunPython 5 | 6 | from mainsite.utils import generate_entity_uri 7 | 8 | 9 | class PopulateEntityIdsMigration(RunPython): 10 | def __init__(self, app_label, model_name, entity_class_name=None, **kwargs): 11 | self.app_label = app_label 12 | self.model_name = model_name 13 | self.entity_class_name = entity_class_name if entity_class_name is not None else model_name 14 | if 'reverse_code' not in kwargs: 15 | kwargs['reverse_code'] = self.noop 16 | super(PopulateEntityIdsMigration, self).__init__(self.generate_ids, **kwargs) 17 | 18 | def noop(self, apps, schema_editor): 19 | pass 20 | 21 | def generate_ids(self, apps, schema_editor): 22 | model_cls = apps.get_model(self.app_label, self.model_name) 23 | for obj in model_cls.objects.all(): 24 | if obj.entity_id is None: 25 | obj.entity_id = generate_entity_uri() 26 | obj.save(force_update=True) 27 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | api: 4 | build: 5 | context: . 6 | dockerfile: .docker/Dockerfile.api 7 | depends_on: 8 | - "db" 9 | - "memcached" 10 | command: uwsgi --ini uwsgi.ini 11 | volumes: 12 | - badgr_server_api:/badgr_server 13 | 14 | memcached: 15 | image: 'bitnami/memcached:latest' 16 | ports: 17 | - "11211:11211" 18 | expose: 19 | - "11211" 20 | 21 | db: 22 | image: mysql:5.6.39 23 | volumes: 24 | - badgr_server_db:/var/lib/mysql:rw 25 | - ./.docker/etc/init.sql:/docker-entrypoint-initdb.d/init.sql 26 | environment: 27 | - "MYSQL_PASSWORD=password" 28 | - "MYSQL_HOST=db" 29 | - "MYSQL_ROOT_PASSWORD=password" 30 | expose: 31 | - "3306" 32 | 33 | nginx: 34 | build: 35 | context: . 36 | dockerfile: .docker/Dockerfile.nginx 37 | volumes: 38 | - badgr_server_api:/badgr_server 39 | depends_on: 40 | - "api" 41 | ports: 42 | - "8080:80" 43 | 44 | volumes: 45 | badgr_server_api: 46 | badgr_server_db: -------------------------------------------------------------------------------- /apps/pathway/migrations/0007_fix_children_of_deleted.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | import autoslug.fields 6 | 7 | def noop(apps, schema_editor): 8 | pass 9 | 10 | def mark_children_of_inactive_as_inactive(apps, schema_editor): 11 | PathwayElement = apps.get_model('pathway', 'PathwayElement') 12 | Pathway = apps.get_model('pathway', 'Pathway') 13 | 14 | def fix_element(elem, parent_active): 15 | if not parent_active and elem.is_active: 16 | elem.is_active = False 17 | elem.save() 18 | 19 | for child in elem.pathwayelement_set.all(): 20 | fix_element(child, elem.is_active) 21 | 22 | for pathway in Pathway.objects.all(): 23 | root = pathway.root_element 24 | fix_element(root, root.is_active) 25 | 26 | 27 | class Migration(migrations.Migration): 28 | dependencies = [ 29 | ('pathway', '0006_auto_20170413_1054'), 30 | ] 31 | 32 | operations = [ 33 | migrations.RunPython(mark_children_of_inactive_as_inactive, reverse_code=noop) 34 | ] 35 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0041_badgeinstancebakedimage.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2018-02-02 15:13 3 | 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | import issuer.models 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | ('issuer', '0040_badgeinstanceextension_issuerextension'), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='BadgeInstanceBakedImage', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('obi_version', models.CharField(max_length=254)), 22 | ('image', models.FileField(blank=True, upload_to=issuer.models._baked_badge_instance_filename_generator)), 23 | ('badgeinstance', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='issuer.BadgeInstance')), 24 | ], 25 | options={ 26 | 'abstract': False, 27 | }, 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /apps/mainsite/middleware.py: -------------------------------------------------------------------------------- 1 | from django import http 2 | from mainsite import settings 3 | 4 | 5 | class MaintenanceMiddleware(object): 6 | """Serve a temporary redirect to a maintenance url in maintenance mode""" 7 | def process_request(self, request): 8 | if request.method == 'POST': 9 | if getattr(settings, 'MAINTENANCE_MODE', False) is True and hasattr(settings, 'MAINTENANCE_URL'): 10 | return http.HttpResponseRedirect(settings.MAINTENANCE_URL) 11 | return None 12 | 13 | 14 | class TrailingSlashMiddleware(object): 15 | def process_request(self, request): 16 | """Removes the slash from urls, or adds a slash for the admin urls""" 17 | exceptions = ['/staff', '/__debug__'] 18 | if list(filter(request.path.startswith, exceptions)): 19 | if request.path[-1] != '/': 20 | return http.HttpResponsePermanentRedirect(request.path+"/") 21 | else: 22 | if request.path != '/' and request.path[-1] == '/': 23 | return http.HttpResponsePermanentRedirect(request.path[:-1]) 24 | return None 25 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # Tox (https://tox.readthedocs.io/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = py37,flake8 8 | 9 | 10 | [testenv] 11 | deps = 12 | -rrequirements.txt 13 | coverage 14 | flake8 15 | 16 | setenv = 17 | DJANGO_SETTINGS_MODULE=mainsite.settings_tests 18 | 19 | commands = 20 | pip install -U pip 21 | pip install -r requirements.txt 22 | 23 | coverage erase 24 | 25 | coverage run --branch --omit={envdir}/*,build/*,*/migrations/*.py manage.py test --noinput 26 | 27 | ; Write coverage report to console 28 | coverage report -i 29 | 30 | ; Write html report for benefit of Jenkins coverage plugin 31 | coverage html -i --directory={toxinidir}/htmlcov/ 32 | 33 | 34 | [testenv:flake8] 35 | deps = 36 | flake8 37 | 38 | commands = 39 | - flake8 --statistics 40 | 41 | 42 | [flake8] 43 | ignore = E226,E501 44 | max-line-length = 120 45 | exclude = .git,.tox,__pycache__,build,dist 46 | -------------------------------------------------------------------------------- /apps/mainsite/management/commands/generate_token_scopes.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from django.utils import timezone 3 | 4 | from mainsite.models import AccessTokenProxy, AccessTokenScope 5 | 6 | 7 | class Command(BaseCommand): 8 | def handle(self, *args, **options): 9 | self.stdout.write('Splitting all scopes on tokens') 10 | 11 | chunk_size = 5000 12 | page = 0 13 | 14 | self.stdout.write('Deleting AccessTokenScopes') 15 | AccessTokenScope.objects.all().delete() 16 | 17 | self.stdout.write('Bulk creating AccessTokenScope') 18 | while True: 19 | tokens = AccessTokenProxy.objects.filter(expires__gt=timezone.now())[page:page+chunk_size] 20 | for t in tokens: 21 | scopes = [] 22 | for s in t.scope.split(): 23 | scopes.append(AccessTokenScope(scope=s, token=t)) 24 | 25 | AccessTokenScope.objects.bulk_create(scopes) 26 | if len(tokens) < chunk_size: break 27 | page += chunk_size 28 | 29 | self.stdout.write('All done.') 30 | -------------------------------------------------------------------------------- /apps/mainsite/static/swagger-ui/API_DESCRIPTION_v1.md: -------------------------------------------------------------------------------- 1 | ## Authentication 2 | 3 | Authenticate requests by including an Authorization header of type "Bearer". For example: 4 | 5 | ```bash 6 | curl 'https://api.badgr.io/v1/user/profile' -H "Authorization: Bearer YOURACCESSTOKEN" 7 | ``` 8 | 9 | ## Access Tokens 10 | To retrieve an access token, POST a username/password combination to /o/token. For example: 11 | 12 | ```bash 13 | curl -X POST 'https://api.badgr.io/o/token' -d "username=YOUREMAIL&password=YOURPASSWORD" 14 | ``` 15 | 16 | returns a response like: 17 | ```javascript 18 | { 19 | "access_token": "YOURACCESSTOKEN", 20 | "token_type": "Bearer", 21 | "expires_in": 86400, 22 | "refresh_token": "YOURREFRESHTOKEN", 23 | } 24 | ``` 25 | 26 | ## Token Expiration 27 | Access tokens will expire, if an expired token is used a 403 status code will be returned. 28 | 29 | The refresh token can be used to automatically renew an access token without requiring the password again. For example: 30 | 31 | ```bash 32 | curl -X POST 'https://api.badgr.io/o/token' -d "grant_type=refresh_token&refresh_token=YOURREFRESHTOKEN" 33 | ``` 34 | -------------------------------------------------------------------------------- /apps/mainsite/static/swagger-ui/API_DESCRIPTION_v2.md: -------------------------------------------------------------------------------- 1 | ## Authentication 2 | 3 | Authenticate requests by including an Authorization header of type "Bearer". For example: 4 | 5 | ```bash 6 | curl 'https://api.badgr.io/v2/users/self' -H "Authorization: Bearer YOURACCESSTOKEN" 7 | ``` 8 | 9 | ## Access Tokens 10 | To retrieve an access token, POST a username/password combination to /o/token. For example: 11 | 12 | ```bash 13 | curl -X POST 'https://api.badgr.io/o/token' -d "username=YOUREMAIL&password=YOURPASSWORD" 14 | ``` 15 | 16 | returns a response like: 17 | ```javascript 18 | { 19 | "access_token": "YOURACCESSTOKEN", 20 | "token_type": "Bearer", 21 | "expires_in": 86400, 22 | "refresh_token": "YOURREFRESHTOKEN", 23 | } 24 | ``` 25 | 26 | ## Token Expiration 27 | Access tokens will expire, if an expired token is used a 403 status code will be returned. 28 | 29 | The refresh token can be used to automatically renew an access token without requiring the password again. For example: 30 | 31 | ```bash 32 | curl -X POST 'https://api.badgr.io/o/token' -d "grant_type=refresh_token&refresh_token=YOURREFRESHTOKEN" 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /apps/recipient/migrations/0002_auto_20160331_1418.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | import autoslug.fields 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('recipient', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='recipientgroup', 17 | name='slug', 18 | field=autoslug.fields.AutoSlugField(default=None, unique=True, max_length=254, editable=False), 19 | preserve_default=False, 20 | ), 21 | migrations.AddField( 22 | model_name='recipientgroupmembership', 23 | name='slug', 24 | field=autoslug.fields.AutoSlugField(default=None, unique=True, max_length=254, editable=False), 25 | preserve_default=False, 26 | ), 27 | migrations.AddField( 28 | model_name='recipientprofile', 29 | name='slug', 30 | field=autoslug.fields.AutoSlugField(default=None, unique=True, max_length=254, editable=False), 31 | preserve_default=False, 32 | ), 33 | ] 34 | -------------------------------------------------------------------------------- /apps/composition/migrations/0015_auto_20170420_0649.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('composition', '0014_auto_20170413_1054'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='localbadgeclass', 16 | name='created_by', 17 | ), 18 | migrations.RemoveField( 19 | model_name='localbadgeclass', 20 | name='issuer', 21 | ), 22 | migrations.RemoveField( 23 | model_name='localissuer', 24 | name='created_by', 25 | ), 26 | migrations.RemoveField( 27 | model_name='localbadgeinstance', 28 | name='local_badgeclass', 29 | ), 30 | migrations.DeleteModel( 31 | name='LocalBadgeClass', 32 | ), 33 | migrations.RemoveField( 34 | model_name='localbadgeinstance', 35 | name='local_issuer', 36 | ), 37 | migrations.DeleteModel( 38 | name='LocalIssuer', 39 | ), 40 | ] 41 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0010_auto_20171004_1510.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-04 22:10 3 | 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('mainsite', '0009_applicationinfo'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='applicationinfo', 17 | name='allowed_scopes', 18 | field=models.TextField(blank=True), 19 | ), 20 | migrations.AddField( 21 | model_name='applicationinfo', 22 | name='website_url', 23 | field=models.URLField(blank=True, default=None, null=True), 24 | ), 25 | migrations.AlterField( 26 | model_name='applicationinfo', 27 | name='icon', 28 | field=models.FileField(blank=True, null=True, upload_to=b''), 29 | ), 30 | migrations.AlterField( 31 | model_name='applicationinfo', 32 | name='name', 33 | field=models.CharField(blank=True, default=None, max_length=254, null=True), 34 | ), 35 | ] 36 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0019_auto_20170420_0810.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0018_auto_20170413_1054'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='BadgeInstanceEvidence', 16 | fields=[ 17 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 18 | ('evidence_url', models.CharField(max_length=2083)), 19 | ('narrative', models.TextField(default=None, null=True, blank=True)), 20 | ('badgeinstance', models.ForeignKey(to='issuer.BadgeInstance')), 21 | ], 22 | options={ 23 | 'abstract': False, 24 | }, 25 | bases=(models.Model,), 26 | ), 27 | migrations.AddField( 28 | model_name='badgeinstance', 29 | name='narrative', 30 | field=models.TextField(default=None, null=True, blank=True), 31 | preserve_default=True, 32 | ), 33 | ] 34 | -------------------------------------------------------------------------------- /apps/badgrlog/events/base.py: -------------------------------------------------------------------------------- 1 | # Created by wiggins@concentricsky.com on 8/27/15. 2 | import datetime 3 | import pytz 4 | import uuid 5 | 6 | import django.utils.timezone as timezone 7 | 8 | 9 | class BaseBadgrEvent(object): 10 | def serializeWithUTCWithZ(self, date): 11 | if timezone.is_aware(date): 12 | tz_datetime = date.astimezone(pytz.utc) 13 | else: 14 | tz_datetime = timezone.make_aware(date, pytz.utc) 15 | tz_datetime = tz_datetime.isoformat() 16 | if tz_datetime.endswith('+00:00'): 17 | tz_datetime = tz_datetime[:-6] + 'Z' 18 | return tz_datetime 19 | 20 | def get_type(self): 21 | return self.__class__.__name__ 22 | 23 | def to_representation(self): 24 | raise NotImplementedError("subclasses must provide a to_representation method") 25 | 26 | def compacted(self): 27 | data = self.to_representation() 28 | data.update({ 29 | 'type': 'Action', 30 | 'actionType': self.get_type(), 31 | 'timestamp': self.serializeWithUTCWithZ(datetime.datetime.now()), 32 | 'event_id': str(uuid.uuid4()) 33 | }) 34 | return data 35 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0008_auto_20170711_1326.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.13 on 2017-07-11 20:26 3 | 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | ('mainsite', '0007_badgrapp_ui_connect_success_redirect'), 14 | ] 15 | 16 | operations = [ 17 | migrations.AlterField( 18 | model_name='badgrapp', 19 | name='created_by', 20 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), 21 | ), 22 | migrations.AlterField( 23 | model_name='badgrapp', 24 | name='is_active', 25 | field=models.BooleanField(default=True), 26 | ), 27 | migrations.AlterField( 28 | model_name='badgrapp', 29 | name='updated_by', 30 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /apps/mainsite/templates/admin/base_site.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/base.html" %} 2 | {% load staticfiles %} 3 | 4 | {% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} 5 | 6 | {% block extrastyle %} 7 | {{ block.super }} 8 | 35 | {% endblock %} 36 | 37 | {% block branding %} 38 |
39 | 40 | 41 | 42 |
43 | {% endblock %} 44 | 45 | {% block nav-global %}{% endblock %} 46 | 47 | {% block userlinks %} 48 | Sitewide Actions / 49 | {{ block.super }} 50 | {% endblock %} -------------------------------------------------------------------------------- /apps/recipient/migrations/0005_auto_20170413_1054.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | import autoslug.fields 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('recipient', '0004_auto_20160511_1024'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='recipientgroup', 17 | name='slug', 18 | field=autoslug.fields.AutoSlugField(populate_from=b'name', unique=True, max_length=254, editable=False), 19 | preserve_default=True, 20 | ), 21 | migrations.AlterField( 22 | model_name='recipientgroupmembership', 23 | name='slug', 24 | field=autoslug.fields.AutoSlugField(populate_from=b'populate_slug', unique=True, max_length=254, editable=False), 25 | preserve_default=True, 26 | ), 27 | migrations.AlterField( 28 | model_name='recipientprofile', 29 | name='slug', 30 | field=autoslug.fields.AutoSlugField(populate_from=b'recipient_identifier', unique=True, max_length=254, editable=False), 31 | preserve_default=True, 32 | ), 33 | ] 34 | -------------------------------------------------------------------------------- /apps/pathway/migrations/0002_auto_20160331_1443.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | import autoslug.fields 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('pathway', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterModelOptions( 16 | name='pathwayelement', 17 | options={'ordering': ('ordering',)}, 18 | ), 19 | migrations.AddField( 20 | model_name='pathway', 21 | name='slug', 22 | field=autoslug.fields.AutoSlugField(default=None, unique=True, max_length=254, editable=False), 23 | preserve_default=False, 24 | ), 25 | migrations.AddField( 26 | model_name='pathwayelement', 27 | name='ordering', 28 | field=models.IntegerField(default=99), 29 | preserve_default=True, 30 | ), 31 | migrations.AddField( 32 | model_name='pathwayelement', 33 | name='slug', 34 | field=autoslug.fields.AutoSlugField(default=None, unique=True, max_length=254, editable=False), 35 | preserve_default=False, 36 | ), 37 | ] 38 | -------------------------------------------------------------------------------- /apps/badgrsocialauth/serializers_v1.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from mainsite.serializers import DateTimeWithUtcZAtEndField 4 | 5 | 6 | class BadgrSocialAccountSerializerV1(serializers.Serializer): 7 | id = serializers.CharField() 8 | provider = serializers.CharField() 9 | dateAdded = DateTimeWithUtcZAtEndField(source='date_joined') 10 | uid = serializers.CharField() 11 | 12 | def to_representation(self, instance): 13 | representation = super(BadgrSocialAccountSerializerV1, self).to_representation(instance) 14 | provider = instance.get_provider() 15 | common_fields = provider.extract_common_fields(instance.extra_data) 16 | email = common_fields.get('email', None) 17 | url = common_fields.get('url', None) 18 | if not email and 'userPrincipalName' in instance.extra_data: 19 | email = instance.extra_data['userPrincipalName'] 20 | 21 | representation.update({ 22 | 'firstName': common_fields.get('first_name', common_fields.get('name', None)), 23 | 'lastName': common_fields.get('last_name', None), 24 | 'primaryEmail': email, 25 | 'url': url, 26 | }) 27 | 28 | return representation 29 | -------------------------------------------------------------------------------- /apps/mainsite/migrations/0009_applicationinfo.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10.7 on 2017-10-04 20:47 3 | 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.OAUTH2_PROVIDER_APPLICATION_MODEL), 14 | ('mainsite', '0008_auto_20170711_1326'), 15 | ('oauth2_provider', '0005_auto_20170514_1141'), 16 | ] 17 | 18 | operations = [ 19 | migrations.CreateModel( 20 | name='ApplicationInfo', 21 | fields=[ 22 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 23 | ('icon', models.ImageField(blank=True, null=True, upload_to=b'')), 24 | ('name', models.CharField(blank=True, max_length=254, null=True)), 25 | ('application', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.OAUTH2_PROVIDER_APPLICATION_MODEL)), 26 | ], 27 | options={ 28 | 'abstract': False, 29 | }, 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /apps/badgeuser/migrations/0020_userrecipientidentifier.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.20 on 2019-04-05 15:58 3 | 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | ('badgeuser', '0019_auto_20181102_1438'), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='UserRecipientIdentifier', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('format', models.CharField(choices=[('url', 'URL')], default='url', max_length=3)), 22 | ('identifier', models.CharField(max_length=255)), 23 | ('verified', models.BooleanField(default=False)), 24 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 25 | ], 26 | ), 27 | migrations.AlterUniqueTogether( 28 | name='userrecipientidentifier', 29 | unique_together=set([('user', 'format', 'identifier')]), 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /apps/composition/migrations/0005_auto_20151117_1555.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('composition', '0004_auto_20150915_1057'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelOptions( 15 | name='localbadgeclass', 16 | options={'verbose_name': 'local badge class', 'verbose_name_plural': 'local badge classes'}, 17 | ), 18 | migrations.AlterField( 19 | model_name='localbadgeclass', 20 | name='image', 21 | field=models.FileField(upload_to=b'uploads/badges', blank=True), 22 | preserve_default=True, 23 | ), 24 | migrations.AlterField( 25 | model_name='localbadgeinstance', 26 | name='image', 27 | field=models.FileField(upload_to=b'uploads/badges', blank=True), 28 | preserve_default=True, 29 | ), 30 | migrations.AlterField( 31 | model_name='localissuer', 32 | name='image', 33 | field=models.FileField(null=True, upload_to=b'uploads/issuers', blank=True), 34 | preserve_default=True, 35 | ), 36 | ] 37 | -------------------------------------------------------------------------------- /apps/mainsite/pagination.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | from rest_framework.pagination import CursorPagination 3 | 4 | 5 | class BadgrCursorPagination(CursorPagination): 6 | ordering = '-created_at' 7 | page_size_query_param = 'num' 8 | offset_cutoff = 15000 9 | 10 | def __init__(self, ordering=None, page_size=None): 11 | if ordering is not None: 12 | self.ordering = ordering 13 | if page_size is not None: 14 | self.page_size = page_size 15 | super(BadgrCursorPagination, self).__init__() 16 | 17 | def get_link_header(self): 18 | links = [] 19 | if self.has_next: 20 | links.append('<{}>; rel="next"'.format(self.get_next_link())) 21 | if self.has_previous: 22 | links.append('<{}>; rel="prev"'.format(self.get_previous_link())) 23 | if len(links): 24 | return ', '.join(links) 25 | 26 | def get_page_info(self): 27 | return OrderedDict([ 28 | ('hasNext', self.has_next), 29 | ('nextResults', self.get_next_link() if self.has_next else None), 30 | ('hasPrevious', self.has_previous), 31 | ('previousResults', self.get_previous_link() if self.has_previous else None), 32 | ]) 33 | -------------------------------------------------------------------------------- /apps/badgrlog/events/backpack.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from .base import BaseBadgrEvent 4 | 5 | 6 | class BadgeSharedEvent(BaseBadgrEvent): 7 | def __init__(self, assertion, platform, shared_date, source): 8 | if not isinstance(shared_date, datetime.datetime): 9 | raise ValueError('shared_date parameter must be a datetime object') 10 | 11 | self.issuer_ob_id = assertion.issuer_jsonld_id 12 | self.badgeclass_ob_id = assertion.badgeclass_jsonld_id 13 | self.assertion_ob_id = assertion.jsonld_id 14 | self.recipient_identifier = assertion.recipient_identifier 15 | self.recipient_type = assertion.recipient_type 16 | self.platform = platform 17 | self.shared_date = shared_date 18 | self.source = source 19 | 20 | def to_representation(self): 21 | return { 22 | 'issuer_ob_id': self.issuer_ob_id, 23 | 'badgeclass_ob_id': self.badgeclass_ob_id, 24 | 'assertion_ob_id': self.assertion_ob_id, 25 | 'recipient': {'value': self.recipient_identifier, 'type': self.recipient_type}, 26 | 'platform': self.platform, 27 | 'shared_date': self.serializeWithUTCWithZ(self.shared_date), 28 | 'source': self.source 29 | } 30 | -------------------------------------------------------------------------------- /apps/issuer/migrations/0013_auto_20170214_0711.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('issuer', '0012_auto_20170213_1531'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='badgeclass', 16 | name='source', 17 | field=models.CharField(default='local', max_length=254), 18 | preserve_default=True, 19 | ), 20 | migrations.AddField( 21 | model_name='badgeclass', 22 | name='source_url', 23 | field=models.CharField(default=None, max_length=254, null=True, blank=True), 24 | preserve_default=True, 25 | ), 26 | migrations.AddField( 27 | model_name='issuer', 28 | name='source', 29 | field=models.CharField(default='local', max_length=254), 30 | preserve_default=True, 31 | ), 32 | migrations.AddField( 33 | model_name='issuer', 34 | name='source_url', 35 | field=models.CharField(default=None, max_length=254, null=True, blank=True), 36 | preserve_default=True, 37 | ), 38 | ] 39 | -------------------------------------------------------------------------------- /apps/backpack/management/commands/emit_old_share_events.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from django.core.management.base import BaseCommand 4 | 5 | import badgrlog 6 | 7 | from backpack.models import BackpackBadgeShare 8 | 9 | 10 | logger = badgrlog.BadgrLogger() 11 | 12 | 13 | class Command(BaseCommand): 14 | def handle(self, *args, **options): 15 | self.stdout.write("Start emit old share events to badgr events log at %s" % datetime.datetime.now()) 16 | 17 | chunk_size = 5000 18 | start_index = 0 19 | processing_index = 1 20 | 21 | while True: 22 | start = start_index 23 | end = start_index+chunk_size 24 | 25 | shares = BackpackBadgeShare.objects.order_by('id')[start:end] 26 | for share in shares: 27 | self.stdout.write("Processing shares %s" % processing_index) 28 | event = badgrlog.BadgeSharedEvent(share.badgeinstance, share.provider, share.created_at, share.source) 29 | logger.event(event) 30 | processing_index = processing_index + 1 31 | if len(shares) < chunk_size: break 32 | start_index += chunk_size 33 | 34 | self.stdout.write("End emit old share events to badgr events log at %s" % datetime.datetime.now()) 35 | -------------------------------------------------------------------------------- /apps/composition/migrations/0002_auto_20150914_1421.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('composition', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelOptions( 15 | name='localbadgeinstancecollection', 16 | options={'verbose_name': 'BadgeInstance in a Collection', 'verbose_name_plural': 'BadgeInstances in Collections'}, 17 | ), 18 | migrations.AddField( 19 | model_name='localbadgeclass', 20 | name='identifier', 21 | field=models.CharField(default=b'get_full_url', max_length=1024), 22 | preserve_default=True, 23 | ), 24 | migrations.AddField( 25 | model_name='localbadgeinstance', 26 | name='identifier', 27 | field=models.CharField(default=b'get_full_url', max_length=1024), 28 | preserve_default=True, 29 | ), 30 | migrations.AddField( 31 | model_name='localissuer', 32 | name='identifier', 33 | field=models.CharField(default=b'get_full_url', max_length=1024), 34 | preserve_default=True, 35 | ), 36 | ] 37 | -------------------------------------------------------------------------------- /apps/composition/migrations/0013_auto_20170227_0847.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from django.db import models, migrations 5 | 6 | 7 | def noop(apps, schema_editor): 8 | pass 9 | 10 | 11 | def migrate_localbadgeinstance_to_use_issuer(apps, schema_editor): 12 | LocalBadgeInstance = apps.get_model('composition', 'LocalBadgeInstance') 13 | BadgeClass = apps.get_model('issuer', 'BadgeClass') 14 | for local_badge_instance in LocalBadgeInstance.objects.all(): 15 | try: 16 | source_url = getattr(local_badge_instance.local_badgeclass, 'identifier', None) 17 | 18 | badgeclass = BadgeClass.objects.get(source='legacy_local_badgeclass', 19 | source_url=source_url) 20 | local_badge_instance.issuer_badgeclass = badgeclass 21 | local_badge_instance.save() 22 | except BadgeClass.DoesNotExist: 23 | pass 24 | 25 | pass 26 | 27 | 28 | class Migration(migrations.Migration): 29 | 30 | dependencies = [ 31 | ('composition', '0012_localbadgeinstance_badgeclass'), 32 | ('issuer', '0017_auto_20170227_1334'), 33 | ] 34 | 35 | operations = [ 36 | migrations.RunPython(migrate_localbadgeinstance_to_use_issuer, reverse_code=noop), 37 | ] 38 | -------------------------------------------------------------------------------- /apps/mainsite/templates/public/bot_openbadge.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ title }} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {% if oembed_link_url %} 20 | {% if 'LinkedInBot' not in user_agent %} 21 | 22 | {% endif %} 23 | {% endif %} 24 | 25 | 26 | 27 | 28 |

{{ title }}

29 |
{{ description }}
30 | {{ public_url }} 31 | 32 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /apps/backpack/v2_api_urls.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from django.conf.urls import url 5 | 6 | from backpack.api import BackpackAssertionList, BackpackAssertionDetail, BackpackCollectionList, \ 7 | BackpackCollectionDetail, BackpackAssertionDetailImage, BackpackImportBadge, ShareBackpackCollection, \ 8 | ShareBackpackAssertion 9 | 10 | urlpatterns = [ 11 | url(r'^import$', BackpackImportBadge.as_view(), name='v2_api_backpack_import_badge'), 12 | 13 | url(r'^assertions$', BackpackAssertionList.as_view(), name='v2_api_backpack_assertion_list'), 14 | url(r'^assertions/(?P[^/]+)$', BackpackAssertionDetail.as_view(), name='v2_api_backpack_assertion_detail'), 15 | url(r'^assertions/(?P[^/]+)/image$', BackpackAssertionDetailImage.as_view(), name='v2_api_backpack_assertion_detail_image'), 16 | 17 | url(r'^collections$', BackpackCollectionList.as_view(), name='v2_api_backpack_collection_list'), 18 | url(r'^collections/(?P[^/]+)$', BackpackCollectionDetail.as_view(), name='v2_api_backpack_collection_detail'), 19 | 20 | url(r'^share/assertion/(?P[^/]+)$', ShareBackpackAssertion.as_view(), name='v2_api_share_assertion'), 21 | url(r'^share/collection/(?P[^/]+)$', ShareBackpackCollection.as_view(), name='v2_api_share_collection'), 22 | ] -------------------------------------------------------------------------------- /apps/mainsite/templates/rest_framework/api.html: -------------------------------------------------------------------------------- 1 | {% extends "rest_framework/base.html" %} 2 | 3 | {% load staticfiles %} 4 | {% load rest_framework %} 5 | 6 | {% block title %}Badgr REST API{% endblock %} 7 | 8 | {% block meta %} 9 | 10 | 11 | 12 | 15 | {% endblock %} 16 | 17 | {% block navbar %} 18 |
19 | 20 | 21 | 22 | Badgr logo 23 | 24 | 25 | {% block userlinks %} 26 | {% if user.is_authenticated %} 27 | {% optional_logout request user %} 28 | {% else %} 29 | {% optional_login request %} 30 | {% endif %} 31 | {% endblock %} 32 |
33 | {% endblock %} 34 | -------------------------------------------------------------------------------- /apps/badgeuser/v2_api_urls.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from django.conf.urls import url 5 | 6 | from badgeuser.api import (BadgeUserAccountConfirm, BadgeUserToken, BadgeUserForgotPassword, BadgeUserEmailConfirm, 7 | BadgeUserDetail, AccessTokenList, AccessTokenDetail, LatestTermsVersionDetail,) 8 | 9 | urlpatterns = [ 10 | 11 | url(r'^auth/token$', BadgeUserToken.as_view(), name='v2_api_auth_token'), 12 | url(r'^auth/forgot-password$', BadgeUserForgotPassword.as_view(), name='v2_api_auth_forgot_password'), 13 | url(r'^auth/confirm-email/(?P[^/]+)$', BadgeUserEmailConfirm.as_view(), name='v2_api_auth_confirm_email'), 14 | url(r'^auth/confirm-account/(?P[^/]+)$', BadgeUserAccountConfirm.as_view(), name='v2_api_account_confirm'), 15 | 16 | url(r'^auth/tokens$', AccessTokenList.as_view(), name='v2_api_access_token_list'), 17 | url(r'^auth/tokens/(?P[^/]+)$', AccessTokenDetail.as_view(), name='v2_api_access_token_detail'), 18 | 19 | url(r'^users/(?Pself)$', BadgeUserDetail.as_view(), name='v2_api_user_self'), 20 | url(r'^users/(?P[^/]+)$', BadgeUserDetail.as_view(), name='v2_api_user_detail'), 21 | 22 | url(r'^termsVersions/latest$', LatestTermsVersionDetail.as_view(), name='v2_latest_terms_version_detail'), 23 | ] -------------------------------------------------------------------------------- /apps/externaltools/admin.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from django.contrib.admin import ModelAdmin, TabularInline 5 | 6 | from externaltools.models import ExternalTool, ExternalToolLaunchpoint 7 | from mainsite.admin import badgr_admin 8 | 9 | 10 | class LaunchpointInline(TabularInline): 11 | model = ExternalToolLaunchpoint 12 | extra = 0 13 | fields = ('launchpoint', 'label', 'launch_url', 'icon_url') 14 | 15 | 16 | class ExternalToolAdmin(ModelAdmin): 17 | readonly_fields = ('created_at', 'created_by', 'updated_at', 'updated_by', 'entity_id') 18 | list_display = ('name', 'entity_id', 'config_url', 'created_at') 19 | list_filter = ('created_at',) 20 | search_fields = ('name', 'config_url', 'xml_config', 'client_id') 21 | fieldsets = ( 22 | ('Metadata', { 23 | 'fields': ('created_by', 'created_at', 'updated_by', 'updated_at', 'entity_id'), 24 | 'classes': ("collapse",) 25 | }), 26 | (None, { 27 | 'fields': ('is_active', 'requires_user_activation', 'name', 'config_url', 'client_id', 'client_secret') 28 | }), 29 | ('Config', { 30 | 'fields': ('xml_config',) 31 | }) 32 | ) 33 | inlines = [ 34 | LaunchpointInline 35 | ] 36 | 37 | 38 | badgr_admin.register(ExternalTool, ExternalToolAdmin) 39 | -------------------------------------------------------------------------------- /apps/badgeuser/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | from allauth.account.signals import user_signed_up, email_confirmed 4 | from django.db.models.signals import post_save 5 | 6 | from .signals import log_user_signed_up, log_email_confirmed, handle_email_created 7 | 8 | 9 | class BadgeUserConfig(AppConfig): 10 | name = 'badgeuser' 11 | 12 | def ready(self): 13 | user_signed_up.connect(log_user_signed_up, 14 | dispatch_uid="user_signed_up") 15 | email_confirmed.connect(log_email_confirmed, 16 | dispatch_uid="email_confirmed") 17 | 18 | from allauth.account.models import EmailAddress 19 | post_save.connect(handle_email_created, 20 | sender=EmailAddress, 21 | dispatch_uid="email_created") 22 | 23 | from mainsite.signals import handle_token_save 24 | from mainsite.models import AccessTokenProxy 25 | from oauth2_provider.models import AccessToken 26 | post_save.connect(handle_token_save, 27 | sender=AccessToken, 28 | dispatch_uid="token_saved") 29 | post_save.connect(handle_token_save, 30 | sender=AccessTokenProxy, 31 | dispatch_uid="token_proxy_saved") 32 | -------------------------------------------------------------------------------- /apps/issuer/management/commands/verify_get_json.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | from collections import OrderedDict 5 | 6 | from django.core.management import BaseCommand 7 | 8 | from issuer.models import Issuer, BadgeClass, BadgeInstance 9 | 10 | 11 | def sorted_dict(d): 12 | return OrderedDict((k,d[k]) for k in sorted(d.keys())) 13 | 14 | 15 | class Command(BaseCommand): 16 | 17 | def handle(self, *args, **options): 18 | self.verbosity = int(options.get('verbosity', 1)) 19 | self.check_jsons(Issuer) 20 | self.check_jsons(BadgeClass) 21 | self.check_jsons(BadgeInstance) 22 | 23 | def check_jsons(self, model_cls): 24 | mismatch = 0 25 | correct = 0 26 | for obj in model_cls.objects.all(): 27 | new_json = obj.get_json() 28 | orig_json = obj.old_json 29 | if cmp(new_json, orig_json) != 0: 30 | if self.verbosity > 1: 31 | self.stdout.write(" Jsons don't match! pk={}\n old: {}\n new: {}\n\n".format(obj.pk, sorted_dict(orig_json), sorted_dict(new_json))) 32 | mismatch += 1 33 | else: 34 | correct += 1 35 | 36 | if self.verbosity > 0: 37 | self.stdout.write("Found {} {}s. {} correct. {} mismatch".format(mismatch+correct, model_cls.__name__, correct, mismatch)) 38 | 39 | 40 | -------------------------------------------------------------------------------- /apps/mainsite/templates/issuer/email/notify_account_holder_message.txt: -------------------------------------------------------------------------------- 1 | ************************************ 2 | Congratulations, you earned a badge! 3 | ************************************ 4 | 5 | --------- 6 | {{ badge_name }} 7 | --------- 8 | 9 | {{ badge_description }} 10 | 11 | --------- 12 | Issuer 13 | --------- 14 | 15 | {{ issuer_name }} 16 | {{ issuer_url }} 17 | 18 | ---------- 19 | Your badge is ready 20 | ---------- 21 | 22 | This badge has been automatically added to your {{ site_name }} ( {{ site_url }} ) account. Wherever you 23 | share or display your badge, portable information about your achievement will 24 | be locked inside. If you have questions about this badge, please contact the issuer at {{ issuer_email }}. 25 | 26 | ---------- 27 | Download 28 | ---------- 29 | 30 | You may also save this badge image for your records or to upload to any Open 31 | Badges-compatible service: 32 | {{ download_url }} 33 | 34 | ----------- 35 | Open Badges: Portable Digital Credentials 36 | ----------- 37 | 38 | Open digital badges let you take your credentials from the many places you learn, 39 | and combine them to tell a cohesive story about your learning. 40 | 41 | Learn more at http://openbadges.org 42 | 43 | 44 | Unsubscribe: If you wish not to be notified of any future badge awards from 45 | this service, click the link below: 46 | {{ unsubscribe_url }} 47 | -------------------------------------------------------------------------------- /apps/mainsite/tests/test_api_throttle.py: -------------------------------------------------------------------------------- 1 | from django.test import override_settings 2 | 3 | from mainsite.tests.base import BadgrTestCase 4 | from mainsite.utils import clamped_backoff_in_seconds, iterate_backoff_count 5 | 6 | SETTINGS_OVERRIDE = { 7 | 'TOKEN_BACKOFF_MAXIMUM_SECONDS': 3600, 8 | 'TOKEN_BACKOFF_PERIOD_SECONDS': 2 9 | } 10 | 11 | 12 | class BackoffTests(BadgrTestCase): 13 | @override_settings(**SETTINGS_OVERRIDE) 14 | def test_clamped_backoff(self): 15 | for m, n in [ 16 | (0, 1), 17 | (1, 2), 18 | (2, 4), 19 | (3, 8), 20 | (4, 16), 21 | (5, 32), 22 | (6, 64), 23 | (7, 128), 24 | (8, 256), 25 | (9, 512), 26 | (10, 1024), 27 | (11, 2048), 28 | (12, 3600), 29 | (13, 3600), 30 | (400, 3600), 31 | ]: 32 | backoff = clamped_backoff_in_seconds(m) 33 | self.assertEqual(backoff, n, "For count {}, backoff should = {} seconds, not {}".format(m, n, backoff)) 34 | 35 | @override_settings(**SETTINGS_OVERRIDE) 36 | def test_iterate_backoff_count(self): 37 | backoff = { 38 | 'count': 1 39 | } 40 | 41 | new_backoff = iterate_backoff_count(backoff) 42 | self.assertEqual(new_backoff['count'], 2) 43 | -------------------------------------------------------------------------------- /apps/mainsite/static/badgr-ui/images/placeholderavatar-failed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | placeholderavatar-issuer 11 | Created with Sketch. 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | --------------------------------------------------------------------------------