def test_award_detail(self): """Can view award detail""" user = self._get_user() user2 = self._get_user(username="******") b1, created = Badge.objects.get_or_create(creator=user, title="Code Badge #1", description="Some description") award = b1.award_to(user2) url = reverse("badger.views.award_detail", args=(b1.slug, award.pk)) r = self.client.get(url, follow=True) doc = pq(r.content) eq_("award_detail", doc.find("body").attr("id")) eq_(1, doc.find('.award .awarded_to .username:contains("%s")' % user2.username).length) eq_(1, doc.find('.badge-title:contains("%s")' % b1.title).length) # Now, take a look at the JSON format url = reverse("badger.award_detail_json", args=(b1.slug, award.pk)) r = self.client.get(url, follow=True) data = json.loads(r.content) hash_salt = hashlib.md5("%s-%s" % (award.badge.pk, award.pk)).hexdigest() recipient_text = "%s%s" % (award.user.email, hash_salt) recipient_hash = "sha256$%s" % hashlib.sha256(recipient_text).hexdigest() eq_(recipient_hash, data["recipient"]) eq_("http://testserver%s" % award.get_absolute_url(), data["evidence"]) eq_(award.badge.title, data["badge"]["name"]) eq_(award.badge.description, data["badge"]["description"]) eq_("http://testserver%s" % award.badge.get_absolute_url(), data["badge"]["criteria"])
def test_deferred_award_immediate_claim(self): """Ensure that a deferred award can be immediately claimed rather than viewing detail""" deferred_email = "*****@*****.**" user1 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, title="Badge to defer") da = DeferredAward(badge=b1, creator=user1) da.save() url = da.get_claim_url() # Just viewing the claim URL shouldn't require login. r = self.client.get(url, follow=False) eq_(200, r.status_code) # But, attempting to claim the award should require login r = self.client.post(reverse("badger.views.claim_deferred_award"), dict(code=da.claim_code), follow=False) eq_(302, r.status_code) ok_("login" in r["Location"]) # So, try logging in and fetch the immediate-claim URL user2 = self._get_user(username="******", email=deferred_email) self.client.login(username="******", password="******") r = self.client.post(reverse("badger.views.claim_deferred_award"), dict(code=da.claim_code), follow=False) eq_(302, r.status_code) ok_("awards" in r["Location"]) ok_(b1.is_awarded_to(user2))
def test_deferred_award_claim_on_login(self): """Ensure that a deferred award gets claimed on login.""" deferred_email = "*****@*****.**" user1 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, title="Badge to defer") url = reverse('badger.views.award_badge', args=(b1.slug, )) self.client.login(username="******", password="******") r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) form = doc('form#award_badge') eq_(1, form.length) eq_(1, form.find('*[name=emails]').length) eq_(1, form.find('input.submit,button.submit').length) r = self.client.post(url, dict(emails=deferred_email, ), follow=False) ok_('award' not in r['Location']) user2 = self._get_user(username="******", email=deferred_email) self.client.login(username="******", password="******") r = self.client.get(reverse('badger.views.detail', args=(b1.slug, )), follow=True) ok_(b1.is_awarded_to(user2))
def test_deferred_award_immediate_claim(self): """Ensure that a deferred award can be immediately claimed rather than viewing detail""" deferred_email = "*****@*****.**" user1 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, title="Badge to defer") da = DeferredAward(badge=b1, creator=user1) da.save() url = da.get_claim_url() # Just viewing the claim URL shouldn't require login. r = self.client.get(url, follow=False) eq_(200, r.status_code) # But, attempting to claim the award should require login r = self.client.post(reverse('badger.views.claim_deferred_award'), dict(code=da.claim_code, ), follow=False) eq_(302, r.status_code) ok_('login' in r['Location']) # So, try logging in and fetch the immediate-claim URL user2 = self._get_user(username="******", email=deferred_email) self.client.login(username="******", password="******") r = self.client.post(reverse('badger.views.claim_deferred_award'), dict(code=da.claim_code, ), follow=False) eq_(302, r.status_code) ok_('awards' in r['Location']) ok_(b1.is_awarded_to(user2))
def test_badge_detail(self): """Can view badge detail""" user = self._get_user() badge = Badge(creator=user, title="Test II", description="Another test") badge.save() r = self.client.get(reverse('badger.views.detail', args=(badge.slug, )), follow=True) doc = pq(r.content) eq_('badge_detail', doc.find('body').attr('id')) eq_(1, doc.find('.badge-title:contains("%s")' % badge.title).length) eq_(badge.description, doc.find('.badge .description').text()) # Now, take a look at the JSON format url = reverse('badger.detail_json', args=(badge.slug, )) r = self.client.get(url, follow=True) data = json.loads(r.content) eq_(badge.title, data['name']) eq_(badge.description, data['description']) eq_('http://testserver%s' % badge.get_absolute_url(), data['criteria'])
def test_deferred_award_claim_on_login(self): """Ensure that a deferred award gets claimed on login.""" deferred_email = "*****@*****.**" user1 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, title="Badge to defer") url = reverse("badger.views.award_badge", args=(b1.slug,)) self.client.login(username="******", password="******") r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) form = doc("form#award_badge") eq_(1, form.length) eq_(1, form.find("*[name=emails]").length) eq_(1, form.find("input.submit,button.submit").length) r = self.client.post(url, dict(emails=deferred_email), follow=False) ok_("award" not in r["Location"]) user2 = self._get_user(username="******", email=deferred_email) self.client.login(username="******", password="******") r = self.client.get(reverse("badger.views.detail", args=(b1.slug,)), follow=True) ok_(b1.is_awarded_to(user2))
def build_related_link(self, model_name, name_single, name_plural, qs): link = '%s?%s' % (reverse('admin:badger_%s_changelist' % model_name, args=[]), 'badge__exact=%s' % (self.id)) new_link = '%s?%s' % (reverse('admin:badger_%s_add' % model_name, args=[]), 'badge=%s' % (self.id)) count = qs.count() what = (count == 1) and name_single or name_plural return ('<a href="%s">%s %s</a> (<a href="%s">new</a>)' % (link, count, what, new_link))
def _redirect_to_claimed_awards(awards, awards_ct): # Has this claim code already been used for awards? # If so, then a GET redirects to an award detail or list if awards_ct == 1: award = awards[0] url = reverse('badger.views.award_detail', args=(award.badge.slug, award.id,)) return HttpResponseRedirect(url) elif awards_ct > 1: award = awards[0] url = reverse('badger.views.awards_list', args=(award.badge.slug,)) return HttpResponseRedirect(url)
def build_related_link(self, model_name, name_single, name_plural, qs): link = '%s?%s' % ( reverse('admin:badger_%s_changelist' % model_name, args=[]), 'badge__exact=%s' % (self.id) ) new_link = '%s?%s' % ( reverse('admin:badger_%s_add' % model_name, args=[]), 'badge=%s' % (self.id) ) count = qs.count() what = (count == 1) and name_single or name_plural return ('<a href="%s">%s %s</a> (<a href="%s">new</a>)' % (link, count, what, new_link))
def test_create(self): """Can create badge with form""" # Login should be required r = self.client.get(reverse('badger.views.create')) eq_(302, r.status_code) ok_('/accounts/login' in r['Location']) # Should be fine after login settings.BADGER_ALLOW_ADD_BY_ANYONE = True self.client.login(username="******", password="******") r = self.client.get(reverse('badger.views.create')) eq_(200, r.status_code) # Make a chick check for expected form elements doc = pq(r.content) form = doc('form#create_badge') eq_(1, form.length) eq_(1, form.find('input[name=title]').length) eq_(1, form.find('textarea[name=description]').length) # For styling purposes, we'll allow either an input or button element eq_(1, form.find('input.submit,button.submit').length) r = self.client.post(reverse('badger.views.create'), dict(), follow=True) doc = pq(r.content) eq_(1, doc.find('form .error > input[name=title]').length) badge_title = "Test badge #1" badge_desc = "This is a test badge" r = self.client.post(reverse('badger.views.create'), dict( title=badge_title, description=badge_desc, ), follow=True) doc = pq(r.content) eq_('badge_detail', doc.find('body').attr('id')) ok_(badge_title in doc.find('.badge-title').text()) eq_(badge_desc, doc.find('.badge .description').text()) slug = doc.find('.badge').attr('data-slug') badge = Badge.objects.get(slug=slug) eq_(badge_title, badge.title) eq_(badge_desc, badge.description)
def _redirect_to_claimed_awards(awards, awards_ct): # Has this claim code already been used for awards? # If so, then a GET redirects to an award detail or list if awards_ct == 1: award = awards[0] url = reverse('badger.views.award_detail', args=( award.badge.slug, award.id, )) return HttpResponseRedirect(url) elif awards_ct > 1: award = awards[0] url = reverse('badger.views.awards_list', args=(award.badge.slug, )) return HttpResponseRedirect(url)
def test_delete(self): """Can delete badge""" user = self._get_user() badge = Badge(creator=user, title="Test III", description="Another test") badge.save() slug = badge.slug badge.award_to(user) self.client.login(username="******", password="******") r = self.client.get(reverse("badger.views.detail", args=(badge.slug,)), follow=True) doc = pq(r.content) eq_("badge_detail", doc.find("body").attr("id")) delete_url = doc.find("a.delete_badge").attr("href") ok_(delete_url is not None) r = self.client.get(delete_url) doc = pq(r.content) eq_("badge_delete", doc.find("body").attr("id")) eq_("1", doc.find(".awards_count").text()) r = self.client.post(delete_url, {}, follow=True) doc = pq(r.content) try: badge = Badge.objects.get(slug=slug) ok_(False) except Badge.DoesNotExist: ok_(True)
def test_edit(self): """Can edit badge detail""" user = self._get_user() badge = Badge(creator=user, title="Test II", description="Another test") badge.save() self.client.login(username="******", password="******") r = self.client.get(reverse("badger.views.detail", args=(badge.slug,)), follow=True) doc = pq(r.content) eq_("badge_detail", doc.find("body").attr("id")) edit_url = doc.find("a.edit_badge").attr("href") ok_(edit_url is not None) r = self.client.get(edit_url) doc = pq(r.content) eq_("badge_edit", doc.find("body").attr("id")) badge_title = "Edited title" badge_desc = "Edited description" r = self.client.post(edit_url, dict(title=badge_title, description=badge_desc), follow=True) doc = pq(r.content) eq_("badge_detail", doc.find("body").attr("id")) ok_(badge_title in doc.find(".badge-title").text()) eq_(badge_desc, doc.find(".badge .description").text()) slug = doc.find(".badge").attr("data-slug") badge = Badge.objects.get(slug=slug) eq_(badge_title, badge.title) eq_(badge_desc, badge.description)
def test_grant_deferred_award(self): """Deferred award for a badge can be granted to an email address.""" deferred_email = "*****@*****.**" user1 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, title="Badge to defer") da = DeferredAward(badge=b1, creator=user1, email="*****@*****.**") da.save() url = da.get_claim_url() self.client.login(username="******", password="******") r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) form = doc("form#grant_award") eq_(1, form.length) eq_(1, form.find("*[name=email]").length) eq_(1, form.find("input.submit,button.submit").length) r = self.client.post(url, dict(is_grant=1, email=deferred_email), follow=False) user2 = self._get_user(username="******", email=deferred_email) self.client.login(username="******", password="******") r = self.client.get(reverse("badger.views.detail", args=(b1.slug,)), follow=True) ok_(b1.is_awarded_to(user2))
def test_baked_award_image(self): """Award gets image baked with OBI assertion""" # Get the source for a sample badge image img_data = open(BADGE_IMG_FN, 'r').read() # Make a badge with a creator user_creator = self._get_user(username="******") badge = self._get_badge(title="Badge with Creator", creator=user_creator) badge.image.save('', ContentFile(img_data), True) # Get some users who can award any badge user_1 = self._get_user(username="******", is_superuser=True) user_2 = self._get_user(username="******", is_superuser=True) # Get some users who can receive badges user_awardee_1 = self._get_user(username="******") user_awardee_2 = self._get_user(username="******") # Try awarding the badge once with baking enabled and once without for enabled in (True, False): with patch_settings(BADGER_BAKE_AWARD_IMAGES=enabled): award_1 = badge.award_to(awardee=user_awardee_1) if not enabled: ok_(not award_1.image) else: ok_(award_1.image) img = Image.open(award_1.image.file) hosted_assertion_url = img.info['openbadges'] expected_url = '%s%s' % ( BASE_URL, reverse('badger.award_detail_json', args=(award_1.badge.slug, award_1.id))) eq_(expected_url, hosted_assertion_url) award_1.delete()
def staff_tools(request): """HACK: This page offers miscellaneous tools useful to event staff. Will go away in the future, addressed by: https://github.com/mozilla/django-badger/issues/35 """ if not (request.user.is_staff or request.user.is_superuser): return HttpResponseForbidden() if request.method != "POST": grant_form = DeferredAwardMultipleGrantForm() else: if request.REQUEST.get('is_grant', False) is not False: grant_form = DeferredAwardMultipleGrantForm(request.POST, request.FILES) if grant_form.is_valid(): email = grant_form.cleaned_data['email'] codes = grant_form.cleaned_data['claim_codes'] for claim_code in codes: da = DeferredAward.objects.get(claim_code=claim_code) da.grant_to(email, request.user) messages.info(request, _(u'Badge "{badgetitle}" granted to {email}').format( badgetitle=da.badge, email=email)) url = reverse('badger.views.staff_tools') return HttpResponseRedirect(url) return render_to_response('%s/staff_tools.html' % bsettings.TEMPLATE_BASE, dict( grant_form=grant_form ), context_instance=RequestContext(request))
def test_grant_deferred_award(self): """Deferred award for a badge can be granted to an email address.""" deferred_email = "*****@*****.**" user1 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, title="Badge to defer") da = DeferredAward(badge=b1, creator=user1, email='*****@*****.**') da.save() url = da.get_claim_url() self.client.login(username="******", password="******") r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) form = doc('form#grant_award') eq_(1, form.length) eq_(1, form.find('*[name=email]').length) eq_(1, form.find('input.submit,button.submit').length) r = self.client.post(url, dict( is_grant=1, email=deferred_email, ), follow=False) user2 = self._get_user(username="******", email=deferred_email) self.client.login(username="******", password="******") r = self.client.get(reverse('badger.views.detail', args=(b1.slug, )), follow=True) ok_(b1.is_awarded_to(user2))
def test_delete(self): """Can delete badge""" user = self._get_user() badge = Badge(creator=user, title="Test III", description="Another test") badge.save() slug = badge.slug badge.award_to(user) self.client.login(username="******", password="******") r = self.client.get(reverse('badger.views.detail', args=(badge.slug, )), follow=True) doc = pq(r.content) eq_('badge_detail', doc.find('body').attr('id')) delete_url = doc.find('a.delete_badge').attr('href') ok_(delete_url is not None) r = self.client.get(delete_url) doc = pq(r.content) eq_('badge_delete', doc.find('body').attr('id')) eq_("1", doc.find('.awards_count').text()) r = self.client.post(delete_url, {}, follow=True) doc = pq(r.content) try: badge = Badge.objects.get(slug=slug) ok_(False) except Badge.DoesNotExist: ok_(True)
def setUp(self): self.client = Client() self.testuser = self._get_user() self.badge = Badge(creator=self.testuser, title="Test II", description="Another test", unique=True) self.badge.save() self.awards_url = reverse('badger.views.awards_list', args=(self.badge.slug, )) key = Key() key.user = self.testuser self.password = key.generate_secret() self.username = key.key key.save() self.key = key auth_ct = '%s:%s' % (self.username, self.password) self.basic_auth = 'Basic %s' % b64encode(auth_ct) self.headers = {'HTTP_AUTHORIZATION': self.basic_auth} Award.objects.all().delete()
def test_claim_code_shows_awards_after_claim(self): """Claim code URL should lead to award detail or list after claim""" user1 = self._get_user(username="******", email="*****@*****.**") user2 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, unique=False, title="Badge for claim viewing") da = DeferredAward(badge=b1, creator=user1) da.save() url = da.get_claim_url() # Before claim, code URL leads to claim page. r = self.client.get(url, follow=False) eq_(200, r.status_code) doc = pq(r.content) form = doc('form#claim_award') # After claim, code URL leads to a single award detail page. award = da.claim(user2) r = self.client.get(url, follow=False) eq_(302, r.status_code) award_url = reverse('badger.views.award_detail', args=(award.badge.slug, award.pk)) ok_(award_url in r['Location'])
def staff_tools(request): """HACK: This page offers miscellaneous tools useful to event staff. Will go away in the future, addressed by: https://github.com/mozilla/django-badger/issues/35 """ if not (request.user.is_staff or request.user.is_superuser): return HttpResponseForbidden() if request.method != "POST": grant_form = DeferredAwardMultipleGrantForm() else: if request.REQUEST.get('is_grant', False) is not False: grant_form = DeferredAwardMultipleGrantForm( request.POST, request.FILES) if grant_form.is_valid(): email = grant_form.cleaned_data['email'] codes = grant_form.cleaned_data['claim_codes'] for claim_code in codes: da = DeferredAward.objects.get(claim_code=claim_code) da.grant_to(email, request.user) messages.info( request, _(u'Badge "{badgetitle}" granted to {email}').format( badgetitle=da.badge, email=email)) url = reverse('badger.views.staff_tools') return HttpResponseRedirect(url) return render_to_response('%s/staff_tools.html' % bsettings.TEMPLATE_BASE, dict(grant_form=grant_form), context_instance=RequestContext(request))
def nomination_detail(request, slug, id, format="html"): """Show details on a nomination, provide for approval and acceptance""" badge = get_object_or_404(Badge, slug=slug) nomination = get_object_or_404(Nomination, badge=badge, pk=id) if not nomination.allows_detail_by(request.user): return HttpResponseForbidden() if request.method == "POST": action = request.POST.get('action', '') if action == 'approve_by': nomination.approve_by(request.user) elif action == 'accept': nomination.accept(request.user) elif action == 'reject_by': nomination.reject_by(request.user) return HttpResponseRedirect( reverse('badger.views.nomination_detail', args=(slug, id))) return render_to_response('%s/nomination_detail.html' % bsettings.TEMPLATE_BASE, dict( badge=badge, nomination=nomination, ), context_instance=RequestContext(request))
def test_delete_award(self): """Can delete award""" user = self._get_user() badge = Badge(creator=user, title="Test III", description="Another test") badge.save() award = badge.award_to(user) self.client.login(username="******", password="******") r = self.client.get(reverse('badger.views.award_detail', args=(badge.slug, award.id)), follow=True) doc = pq(r.content) eq_('award_detail', doc.find('body').attr('id')) delete_url = doc.find('a.delete_award').attr('href') ok_(delete_url is not None) r = self.client.post(delete_url, {}, follow=True) try: award = Award.objects.get(pk=award.pk) ok_(False) except Award.DoesNotExist: ok_(True)
def award_badge(request, slug): """Issue an award for a badge""" badge = get_object_or_404(Badge, slug=slug) if not badge.allows_award_to(request.user): return HttpResponseForbidden('Award forbidden') if request.method != "POST": form = BadgeAwardForm() else: form = BadgeAwardForm(request.POST, request.FILES) if form.is_valid(): emails = form.cleaned_data['emails'] description = form.cleaned_data['description'] for email in emails: result = badge.award_to(email=email, awarder=request.user, description=description) if result: if not hasattr(result, 'claim_code'): messages.info(request, _(u'Award issued to {email}').format( email=email)) else: messages.info(request, _( u'Invitation to claim award sent to {email}').format(email=email)) return HttpResponseRedirect(reverse('badger.views.detail', args=(badge.slug,))) return render_to_response('%s/badge_award.html' % bsettings.TEMPLATE_BASE, dict( form=form, badge=badge, ), context_instance=RequestContext(request))
def test_award_detail(self): """Can view award detail""" user = self._get_user() user2 = self._get_user(username='******') b1, created = Badge.objects.get_or_create( creator=user, title="Code Badge #1", description="Some description") award = b1.award_to(user2) url = reverse('badger.views.award_detail', args=( b1.slug, award.pk, )) r = self.client.get(url, follow=True) doc = pq(r.content) eq_('award_detail', doc.find('body').attr('id')) eq_( 1, doc.find('.award .awarded_to .username:contains("%s")' % user2.username).length) eq_(1, doc.find('.badge-title:contains("%s")' % b1.title).length) # Now, take a look at the JSON format url = reverse('badger.award_detail_json', args=( b1.slug, award.pk, )) r = self.client.get(url, follow=True) data = json.loads(r.content) hash_salt = (hashlib.md5('%s-%s' % (award.badge.pk, award.pk)).hexdigest()) recipient_text = '%s%s' % (award.user.email, hash_salt) recipient_hash = ('sha256$%s' % hashlib.sha256(recipient_text).hexdigest()) eq_(recipient_hash, data['recipient']) eq_('http://testserver%s' % award.get_absolute_url(), data['evidence']) eq_(award.badge.title, data['badge']['name']) eq_(award.badge.description, data['badge']['description']) eq_('http://testserver%s' % award.badge.get_absolute_url(), data['badge']['criteria'])
def test_create(self): """Can create badge with form""" # Login should be required r = self.client.get(reverse("badger.views.create")) eq_(302, r.status_code) ok_("/accounts/login" in r["Location"]) # Should be fine after login settings.BADGER_ALLOW_ADD_BY_ANYONE = True self.client.login(username="******", password="******") r = self.client.get(reverse("badger.views.create")) eq_(200, r.status_code) # Make a chick check for expected form elements doc = pq(r.content) form = doc("form#create_badge") eq_(1, form.length) eq_(1, form.find("input[name=title]").length) eq_(1, form.find("textarea[name=description]").length) # For styling purposes, we'll allow either an input or button element eq_(1, form.find("input.submit,button.submit").length) r = self.client.post(reverse("badger.views.create"), dict(), follow=True) doc = pq(r.content) eq_(1, doc.find("form .error > input[name=title]").length) badge_title = "Test badge #1" badge_desc = "This is a test badge" r = self.client.post( reverse("badger.views.create"), dict(title=badge_title, description=badge_desc), follow=True ) doc = pq(r.content) eq_("badge_detail", doc.find("body").attr("id")) ok_(badge_title in doc.find(".badge-title").text()) eq_(badge_desc, doc.find(".badge .description").text()) slug = doc.find(".badge").attr("data-slug") badge = Badge.objects.get(slug=slug) eq_(badge_title, badge.title) eq_(badge_desc, badge.description)
def bake_obi_image(self, request=None): """Bake the OBI JSON badge award assertion into a copy of the original badge's image, if one exists.""" if request: base_url = request.build_absolute_uri('/') else: base_url = 'http://%s' % (Site.objects.get_current().domain, ) if self.badge.image: # Make a duplicate of the badge image self.badge.image.open() img_copy_fh = StringIO(self.badge.image.file.read()) else: # Make a copy of the default badge image img_copy_fh = StringIO(open(DEFAULT_BADGE_IMAGE, 'rb').read()) try: # Try processing the image copy, bail if the image is bad. img = Image.open(img_copy_fh) except IOError: return False # Here's where the baking gets done. JSON representation of the OBI # assertion gets written into the "openbadges" metadata field # see: http://blog.client9.com/2007/08/python-pil-and-png-metadata-take-2.html # see: https://github.com/mozilla/openbadges/blob/development/lib/baker.js # see: https://github.com/mozilla/openbadges/blob/development/controllers/baker.js try: from PIL import PngImagePlugin except ImportError: import PngImagePlugin meta = PngImagePlugin.PngInfo() # TODO: Will need this, if we stop doing hosted assertions # assertion = self.as_obi_assertion(request) # meta.add_text('openbadges', json.dumps(assertion)) hosted_assertion_url = '%s%s' % (base_url, reverse( 'badger.award_detail_json', args=(self.badge.slug, self.id))) meta.add_text('openbadges', hosted_assertion_url) # And, finally save out the baked image. new_img = StringIO() img.save(new_img, "PNG", pnginfo=meta) img_data = new_img.getvalue() name_before = self.image.name self.image.save('', ContentFile(img_data), False) if (self.image.storage.exists(name_before)): self.image.storage.delete(name_before) # Update the image field with the new image name # NOTE: Can't do a full save(), because this gets called in save() Award.objects.filter(pk=self.pk).update(image=self.image) return True
def _do_claim(request, deferred_award): """Perform claim of a deferred award""" if not deferred_award.allows_claim_by(request.user): return HttpResponseForbidden('Claim denied') award = deferred_award.claim(request.user) if award: url = reverse('badger.views.award_detail', args=(award.badge.slug, award.id,)) return HttpResponseRedirect(url)
def bake_obi_image(self, request=None): """Bake the OBI JSON badge award assertion into a copy of the original badge's image, if one exists.""" if request: base_url = request.build_absolute_uri('/') else: base_url = 'http://%s' % (Site.objects.get_current().domain,) if self.badge.image: # Make a duplicate of the badge image self.badge.image.open() img_copy_fh = StringIO(self.badge.image.file.read()) else: # Make a copy of the default badge image img_copy_fh = StringIO(open(DEFAULT_BADGE_IMAGE, 'rb').read()) try: # Try processing the image copy, bail if the image is bad. img = Image.open(img_copy_fh) except IOError: return False # Here's where the baking gets done. JSON representation of the OBI # assertion gets written into the "openbadges" metadata field # see: http://blog.client9.com/2007/08/python-pil-and-png-metadata-take-2.html # see: https://github.com/mozilla/openbadges/blob/development/lib/baker.js # see: https://github.com/mozilla/openbadges/blob/development/controllers/baker.js try: from PIL import PngImagePlugin except ImportError: import PngImagePlugin meta = PngImagePlugin.PngInfo() # TODO: Will need this, if we stop doing hosted assertions # assertion = self.as_obi_assertion(request) # meta.add_text('openbadges', json.dumps(assertion)) hosted_assertion_url = '%s%s' % ( base_url, reverse('badger.award_detail_json', args=(self.badge.slug, self.id))) meta.add_text('openbadges', hosted_assertion_url) # And, finally save out the baked image. new_img = StringIO() img.save(new_img, "PNG", pnginfo=meta) img_data = new_img.getvalue() name_before = self.image.name self.image.save('', ContentFile(img_data), False) if (self.image.storage.exists(name_before)): self.image.storage.delete(name_before) # Update the image field with the new image name # NOTE: Can't do a full save(), because this gets called in save() Award.objects.filter(pk=self.pk).update(image=self.image) return True
def claim_deferred_award(request, claim_code=None): """Deferred award detail view""" if not claim_code: claim_code = request.REQUEST.get('code', '').strip() # Look for any awards that match this claim code. awards = Award.objects.filter(claim_code=claim_code) awards_ct = awards.count() # Try fetching a DeferredAward matching the claim code. If none found, then # make one last effort to redirect a POST to awards. Otherwise, 404 try: deferred_award = DeferredAward.objects.get(claim_code=claim_code) # If this is a GET and there are awards matching the claim code, # redirect to the awards. if (request.method == "GET" and awards_ct > 0 and not deferred_award.reusable): return _redirect_to_claimed_awards(awards, awards_ct) except DeferredAward.DoesNotExist: if awards_ct > 0: return _redirect_to_claimed_awards(awards, awards_ct) else: raise Http404('No such claim code, %s' % claim_code) if not deferred_award.allows_detail_by(request.user): return HttpResponseForbidden('Claim detail denied') if request.method != "POST": grant_form = DeferredAwardGrantForm() else: grant_form = DeferredAwardGrantForm(request.POST, request.FILES) if not request.POST.get('is_grant', False) is not False: return _do_claim(request, deferred_award) else: if not deferred_award.allows_grant_by(request.user): return HttpResponseForbidden('Grant denied') if grant_form.is_valid(): email = request.POST.get('email', None) deferred_award.grant_to(email=email, granter=request.user) messages.info( request, _(u'Award claim granted to {email}').format(email=email)) url = reverse('badger.views.detail', args=(deferred_award.badge.slug, )) return HttpResponseRedirect(url) return render_to_response('%s/claim_deferred_award.html' % bsettings.TEMPLATE_BASE, dict(badge=deferred_award.badge, deferred_award=deferred_award, grant_form=grant_form), context_instance=RequestContext(request))
def _do_claim(request, deferred_award): """Perform claim of a deferred award""" if not deferred_award.allows_claim_by(request.user): return HttpResponseForbidden('Claim denied') award = deferred_award.claim(request.user) if award: url = reverse('badger.views.award_detail', args=( award.badge.slug, award.id, )) return HttpResponseRedirect(url)
def test_badge_detail(self): """Can view badge detail""" user = self._get_user() badge = Badge(creator=user, title="Test II", description="Another test") badge.save() r = self.client.get(reverse("badger.views.detail", args=(badge.slug,)), follow=True) doc = pq(r.content) eq_("badge_detail", doc.find("body").attr("id")) eq_(1, doc.find('.badge-title:contains("%s")' % badge.title).length) eq_(badge.description, doc.find(".badge .description").text()) # Now, take a look at the JSON format url = reverse("badger.detail_json", args=(badge.slug,)) r = self.client.get(url, follow=True) data = json.loads(r.content) eq_(badge.title, data["name"]) eq_(badge.description, data["description"]) eq_("http://testserver%s" % badge.get_absolute_url(), data["criteria"])
def detail(request, slug, format="html"): """Badge detail view""" badge = get_object_or_404(Badge, slug=slug) if not badge.allows_detail_by(request.user): return HttpResponseForbidden('Detail forbidden') awards = (Award.objects.filter( badge=badge).order_by('-created'))[:bsettings.MAX_RECENT] # FIXME: This is awkward. It used to collect sections as responses to a # signal sent out to badger_multiplayer and hypothetical future expansions # to badger sections = dict() sections['award'] = dict(form=BadgeAwardForm()) if badge.allows_nominate_for(request.user): sections['nominate'] = dict(form=BadgeSubmitNominationForm()) if request.method == "POST": if request.POST.get('is_generate', None): if not badge.allows_manage_deferred_awards_by(request.user): return HttpResponseForbidden('Claim generate denied') amount = int(request.POST.get('amount', 10)) reusable = (amount == 1) cg = badge.generate_deferred_awards(user=request.user, amount=amount, reusable=reusable) if request.POST.get('is_delete', None): if not badge.allows_manage_deferred_awards_by(request.user): return HttpResponseForbidden('Claim delete denied') group = request.POST.get('claim_group') badge.delete_claim_group(request.user, group) url = reverse('badger.views.detail', kwargs=dict(slug=slug)) return HttpResponseRedirect(url) claim_groups = badge.claim_groups if format == 'json': data = badge.as_obi_serialization(request) resp = HttpResponse(json.dumps(data)) resp['Content-Type'] = 'application/json' return resp else: return render_to_response('%s/badge_detail.html' % bsettings.TEMPLATE_BASE, dict(badge=badge, award_list=awards, sections=sections, claim_groups=claim_groups), context_instance=RequestContext(request))
def claim_deferred_award(request, claim_code=None): """Deferred award detail view""" if not claim_code: claim_code = request.REQUEST.get('code', '').strip() # Look for any awards that match this claim code. awards = Award.objects.filter(claim_code=claim_code) awards_ct = awards.count() # Try fetching a DeferredAward matching the claim code. If none found, then # make one last effort to redirect a POST to awards. Otherwise, 404 try: deferred_award = DeferredAward.objects.get(claim_code=claim_code) # If this is a GET and there are awards matching the claim code, # redirect to the awards. if (request.method == "GET" and awards_ct > 0 and not deferred_award.reusable): return _redirect_to_claimed_awards(awards, awards_ct) except DeferredAward.DoesNotExist: if awards_ct > 0: return _redirect_to_claimed_awards(awards, awards_ct) else: raise Http404('No such claim code, %s' % claim_code) if not deferred_award.allows_detail_by(request.user): return HttpResponseForbidden('Claim detail denied') if request.method != "POST": grant_form = DeferredAwardGrantForm() else: grant_form = DeferredAwardGrantForm(request.POST, request.FILES) if not request.POST.get('is_grant', False) is not False: return _do_claim(request, deferred_award) else: if not deferred_award.allows_grant_by(request.user): return HttpResponseForbidden('Grant denied') if grant_form.is_valid(): email = request.POST.get('email', None) deferred_award.grant_to(email=email, granter=request.user) messages.info(request, _(u'Award claim granted to {email}').format( email=email)) url = reverse('badger.views.detail', args=(deferred_award.badge.slug,)) return HttpResponseRedirect(url) return render_to_response('%s/claim_deferred_award.html' % bsettings.TEMPLATE_BASE, dict( badge=deferred_award.badge, deferred_award=deferred_award, grant_form=grant_form ), context_instance=RequestContext(request))
def detail(request, slug, format="html"): """Badge detail view""" badge = get_object_or_404(Badge, slug=slug) if not badge.allows_detail_by(request.user): return HttpResponseForbidden('Detail forbidden') awards = (Award.objects.filter(badge=badge) .order_by('-created'))[:bsettings.MAX_RECENT] # FIXME: This is awkward. It used to collect sections as responses to a # signal sent out to badger_multiplayer and hypothetical future expansions # to badger sections = dict() sections['award'] = dict(form=BadgeAwardForm()) if badge.allows_nominate_for(request.user): sections['nominate'] = dict(form=BadgeSubmitNominationForm()) if request.method == "POST": if request.POST.get('is_generate', None): if not badge.allows_manage_deferred_awards_by(request.user): return HttpResponseForbidden('Claim generate denied') amount = int(request.POST.get('amount', 10)) reusable = (amount == 1) cg = badge.generate_deferred_awards(user=request.user, amount=amount, reusable=reusable) if request.POST.get('is_delete', None): if not badge.allows_manage_deferred_awards_by(request.user): return HttpResponseForbidden('Claim delete denied') group = request.POST.get('claim_group') badge.delete_claim_group(request.user, group) url = reverse('badger.views.detail', kwargs=dict(slug=slug)) return HttpResponseRedirect(url) claim_groups = badge.claim_groups if format == 'json': data = badge.as_obi_serialization(request) resp = HttpResponse(json.dumps(data)) resp['Content-Type'] = 'application/json' return resp else: return render_to_response('%s/badge_detail.html' % bsettings.TEMPLATE_BASE, dict( badge=badge, award_list=awards, sections=sections, claim_groups=claim_groups ), context_instance=RequestContext(request))
def nominate_for(request, slug): """Submit nomination for a badge""" badge = get_object_or_404(Badge, slug=slug) if not badge.allows_nominate_for(request.user): return HttpResponseForbidden() if request.method != "POST": form = BadgeSubmitNominationForm() else: form = BadgeSubmitNominationForm(request.POST, request.FILES) if form.is_valid(): emails = form.cleaned_data['emails'] for email in emails: users = User.objects.filter(email=email) if not users: # TODO: Need a deferred nomination mechanism for # non-registered users. pass else: nominee = users[0] try: award = badge.nominate_for(nominee, request.user) messages.info( request, _(u'Nomination submitted for {email}').format( email=email)) except BadgeAlreadyAwardedException: messages.info( request, _(u'Badge already awarded to {email}').format( email=email)) except Exception: messages.info( request, _(u'Nomination failed for {email}').format( email=email)) return HttpResponseRedirect( reverse('badger.views.detail', args=(badge.slug, ))) return render_to_response('%s/badge_nominate_for.html' % bsettings.TEMPLATE_BASE, dict( form=form, badge=badge, ), context_instance=RequestContext(request))
def award_delete(request, slug, id): """Delete an award""" badge = get_object_or_404(Badge, slug=slug) award = get_object_or_404(Award, badge=badge, pk=id) if not award.allows_delete_by(request.user): return HttpResponseForbidden('Award delete forbidden') if request.method == "POST": messages.info(request, _(u'Award for badge "{badgetitle}" deleted.').format( badgetitle=badge.title)) award.delete() url = reverse('badger.views.detail', kwargs=dict(slug=slug)) return HttpResponseRedirect(url) return render_to_response('%s/award_delete.html' % bsettings.TEMPLATE_BASE, dict( badge=badge, award=award ), context_instance=RequestContext(request))
def delete(request, slug): """Delete a badge""" badge = get_object_or_404(Badge, slug=slug) if not badge.allows_delete_by(request.user): return HttpResponseForbidden() awards_count = badge.award_set.count() if request.method == "POST": messages.info(request, _(u'Badge "{badgetitle}" deleted.').format( badgetitle=badge.title)) badge.delete() return HttpResponseRedirect(reverse('badger.views.badges_list')) return render_to_response('%s/badge_delete.html' % bsettings.TEMPLATE_BASE, dict( badge=badge, awards_count=awards_count, ), context_instance=RequestContext(request))
def test_issue_award(self): """Badge creator can issue award to another user""" SAMPLE_DESCRIPTION = u'This is a sample description' user1 = self._get_user(username="******", email="*****@*****.**") user2 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, title="Badge to awarded") url = reverse('badger.views.award_badge', args=(b1.slug, )) # Non-creator should be denied attempt to award badge self.client.login(username="******", password="******") r = self.client.get(url, follow=True) eq_(403, r.status_code) # But, the creator should be allowed self.client.login(username="******", password="******") r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) form = doc('form#award_badge') eq_(1, form.length) eq_(1, form.find('*[name=emails]').length) eq_(1, form.find('*[name=description]').length) eq_(1, form.find('input.submit,button.submit').length) r = self.client.post(url, dict(emails=user2.email, description=SAMPLE_DESCRIPTION), follow=False) ok_('award' in r['Location']) ok_(b1.is_awarded_to(user2)) award = Award.objects.filter(user=user2, badge=b1)[0] eq_(SAMPLE_DESCRIPTION, award.description) r = self.client.get(award.get_absolute_url(), follow=True) eq_(200, r.status_code) doc = pq(r.content) eq_(SAMPLE_DESCRIPTION, doc.find('.award .description').text())
def test_edit_preserves_creator(self): """Edit preserves the original creator of the badge (bugfix)""" orig_user = self._get_user(username="******") badge = Badge(creator=orig_user, title="Test 3", description="Another test") badge.save() edit_user = self._get_user(username="******") edit_user.is_superuser = True edit_user.save() self.client.login(username="******", password="******") edit_url = reverse("badger.views.edit", args=(badge.slug,)) r = self.client.post(edit_url, dict(title="New Title"), follow=True) doc = pq(r.content) # The badge's creator should not have changed to the editing user. badge_after = Badge.objects.get(pk=badge.pk) ok_(badge_after.creator.pk != edit_user.pk)
def test_disallowed_badge_award(self): """User should not be able to POST an award to a badge for which the user hasn't got permission to do so""" user = self._get_user(username="******", email="*****@*****.**") badge = Badge(creator=user, title="Hey you badge", description="Another test", unique=True) badge.save() awards_url = reverse('badger.views.awards_list', args=(self.badge.slug,)) data = dict(emails=['*****@*****.**',]) resp = self.client.post(awards_url, json.dumps(data), content_type='application/json', HTTP_AUTHORIZATION=self.basic_auth) ok_(403, resp.status_code)
def test_awards_list(self): """Can view awards by badge""" user = self._get_user() b1 = Badge.objects.create(creator=user, title="Code Badge #1") u1 = self._get_user(username="******") u2 = self._get_user(username="******") u3 = self._get_user(username="******") for u in (u1, u2, u3): b1.award_to(u) url = reverse("badger.views.awards_list", args=(b1.slug,)) r = self.client.get(url, follow=True) doc = pq(r.content) eq_(3, doc.find(".award").length) for u in (u1, u2, u3): eq_(1, doc.find('.award .user:contains("%s")' % u.username).length)
def test_awards_by_badge(self): """Can view awards by badge""" user = self._get_user() b1 = Badge.objects.create(creator=user, title="Code Badge #1") u1 = self._get_user(username='******') u2 = self._get_user(username='******') u3 = self._get_user(username='******') for u in (u1, u2, u3): b1.award_to(u) url = reverse('badger.views.awards_by_badge', args=(b1.slug, )) r = self.client.get(url, follow=True) doc = pq(r.content) eq_(3, doc.find('.award').length) for u in (u1, u2, u3): eq_(1, doc.find('.award .user:contains("%s")' % u.username).length)
def test_edit(self): """Can edit badge detail""" user = self._get_user() badge = Badge(creator=user, title="Test II", description="Another test") badge.save() self.client.login(username="******", password="******") r = self.client.get(reverse('badger.views.detail', args=(badge.slug, )), follow=True) doc = pq(r.content) eq_('badge_detail', doc.find('body').attr('id')) edit_url = doc.find('a.edit_badge').attr('href') ok_(edit_url is not None) r = self.client.get(edit_url) doc = pq(r.content) eq_('badge_edit', doc.find('body').attr('id')) badge_title = "Edited title" badge_desc = "Edited description" r = self.client.post(edit_url, dict( title=badge_title, description=badge_desc, ), follow=True) doc = pq(r.content) eq_('badge_detail', doc.find('body').attr('id')) ok_(badge_title in doc.find('.badge-title').text()) eq_(badge_desc, doc.find('.badge .description').text()) slug = doc.find('.badge').attr('data-slug') badge = Badge.objects.get(slug=slug) eq_(badge_title, badge.title) eq_(badge_desc, badge.description)
def award_delete(request, slug, id): """Delete an award""" badge = get_object_or_404(Badge, slug=slug) award = get_object_or_404(Award, badge=badge, pk=id) if not award.allows_delete_by(request.user): return HttpResponseForbidden('Award delete forbidden') if request.method == "POST": messages.info( request, _(u'Award for badge "{badgetitle}" deleted.').format( badgetitle=badge.title)) award.delete() url = reverse('badger.views.detail', kwargs=dict(slug=slug)) return HttpResponseRedirect(url) return render_to_response('%s/award_delete.html' % bsettings.TEMPLATE_BASE, dict(badge=badge, award=award), context_instance=RequestContext(request))
def test_issue_award(self): """Badge creator can issue award to another user""" SAMPLE_DESCRIPTION = u"This is a sample description" user1 = self._get_user(username="******", email="*****@*****.**") user2 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, title="Badge to awarded") url = reverse("badger.views.award_badge", args=(b1.slug,)) # Non-creator should be denied attempt to award badge self.client.login(username="******", password="******") r = self.client.get(url, follow=True) eq_(403, r.status_code) # But, the creator should be allowed self.client.login(username="******", password="******") r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) form = doc("form#award_badge") eq_(1, form.length) eq_(1, form.find("*[name=emails]").length) eq_(1, form.find("*[name=description]").length) eq_(1, form.find("input.submit,button.submit").length) r = self.client.post(url, dict(emails=user2.email, description=SAMPLE_DESCRIPTION), follow=False) ok_("award" in r["Location"]) ok_(b1.is_awarded_to(user2)) award = Award.objects.filter(user=user2, badge=b1)[0] eq_(SAMPLE_DESCRIPTION, award.description) r = self.client.get(award.get_absolute_url(), follow=True) eq_(200, r.status_code) doc = pq(r.content) eq_(SAMPLE_DESCRIPTION, doc.find(".award .description").text())
def edit(request, slug): """Edit an existing badge""" badge = get_object_or_404(Badge, slug=slug) if not badge.allows_edit_by(request.user): return HttpResponseForbidden() if request.method != "POST": form = BadgeEditForm(instance=badge) else: form = BadgeEditForm(request.POST, request.FILES, instance=badge) if form.is_valid(): new_sub = form.save(commit=False) new_sub.save() form.save_m2m() return HttpResponseRedirect(reverse( 'badger.views.detail', args=(new_sub.slug,))) return render_to_response('%s/badge_edit.html' % bsettings.TEMPLATE_BASE, dict( badge=badge, form=form, ), context_instance=RequestContext(request))
def test_edit_preserves_creator(self): """Edit preserves the original creator of the badge (bugfix)""" orig_user = self._get_user(username='******') badge = Badge(creator=orig_user, title="Test 3", description="Another test") badge.save() edit_user = self._get_user(username='******') edit_user.is_superuser = True edit_user.save() self.client.login(username="******", password="******") edit_url = reverse('badger.views.edit', args=(badge.slug, )) r = self.client.post(edit_url, dict(title='New Title', ), follow=True) doc = pq(r.content) # The badge's creator should not have changed to the editing user. badge_after = Badge.objects.get(pk=badge.pk) ok_(badge_after.creator.pk != edit_user.pk)
def delete(request, slug): """Delete a badge""" badge = get_object_or_404(Badge, slug=slug) if not badge.allows_delete_by(request.user): return HttpResponseForbidden() awards_count = badge.award_set.count() if request.method == "POST": messages.info( request, _(u'Badge "{badgetitle}" deleted.').format(badgetitle=badge.title)) badge.delete() return HttpResponseRedirect(reverse('badger.views.badges_list')) return render_to_response('%s/badge_delete.html' % bsettings.TEMPLATE_BASE, dict( badge=badge, awards_count=awards_count, ), context_instance=RequestContext(request))
def create(request): """Create a new badge""" if not Badge.objects.allows_add_by(request.user): return HttpResponseForbidden() if request.method != "POST": form = BadgeNewForm() form.initial['tags'] = request.GET.get('tags', '') else: form = BadgeNewForm(request.POST, request.FILES) if form.is_valid(): new_sub = form.save(commit=False) new_sub.creator = request.user new_sub.save() form.save_m2m() return HttpResponseRedirect(reverse( 'badger.views.detail', args=(new_sub.slug,))) return render_to_response('%s/badge_create.html' % bsettings.TEMPLATE_BASE, dict( form=form, ), context_instance=RequestContext(request))
def test_awards_by_user(self): """Can view awards by user""" user = self._get_user() user2 = self._get_user(username="******") b1, created = Badge.objects.get_or_create(creator=user, title="Code Badge #1") b2, created = Badge.objects.get_or_create(creator=user, title="Code Badge #2") b3, created = Badge.objects.get_or_create(creator=user, title="Code Badge #3") b1.award_to(user2) award_badge(b2.slug, user2) Award.objects.create(badge=b3, user=user2) url = reverse("badger.views.awards_by_user", args=(user2.username,)) r = self.client.get(url, follow=True) doc = pq(r.content) eq_("badge_awards_by_user", doc.find("body").attr("id")) eq_(3, doc.find(".badge").length) for b in (b1, b2, b3): eq_(1, doc.find('.badge .title:contains("%s")' % b.title).length)
def create(request): """Create a new badge""" if not Badge.objects.allows_add_by(request.user): return HttpResponseForbidden() if request.method != "POST": form = BadgeNewForm() form.initial['tags'] = request.GET.get('tags', '') else: form = BadgeNewForm(request.POST, request.FILES) if form.is_valid(): new_sub = form.save(commit=False) new_sub.creator = request.user new_sub.save() form.save_m2m() return HttpResponseRedirect( reverse('badger.views.detail', args=(new_sub.slug, ))) return render_to_response('%s/badge_create.html' % bsettings.TEMPLATE_BASE, dict(form=form, ), context_instance=RequestContext(request))
def test_issue_multiple_awards(self): """Multiple emails can be submitted at once to issue awards""" # Build creator user and badge creator = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=creator, title="Badge to defer") # Build future awardees user1 = self._get_user(username="******", email="*****@*****.**") user2 = self._get_user(username="******", email="*****@*****.**") user3 = self._get_user(username="******", email="*****@*****.**") user4_email = '*****@*****.**' # Login as the badge creator, prepare to award... self.client.login(username="******", password="******") url = reverse('badger.views.award_badge', args=(b1.slug, )) r = self.client.get(url, follow=True) eq_(200, r.status_code) # Make sure the expected parts appear in the form. doc = pq(r.content) form = doc('form#award_badge') eq_(1, form.length) eq_(1, form.find('*[name=emails]').length) eq_(1, form.find('input.submit,button.submit').length) # Post a list of emails with a variety of separators. r = self.client.post( url, dict(emails=( "%s,%s\n%s %s" % (user1.email, user2.email, user3.email, user4_email)), ), follow=False) # Ensure that the known users received awards and the unknown user got # a deferred award. ok_(b1.is_awarded_to(user1)) ok_(b1.is_awarded_to(user2)) ok_(b1.is_awarded_to(user3)) eq_(1, DeferredAward.objects.filter(email=user4_email).count())
def nomination_detail(request, slug, id, format="html"): """Show details on a nomination, provide for approval and acceptance""" badge = get_object_or_404(Badge, slug=slug) nomination = get_object_or_404(Nomination, badge=badge, pk=id) if not nomination.allows_detail_by(request.user): return HttpResponseForbidden() if request.method == "POST": action = request.POST.get('action', '') if action == 'approve_by': nomination.approve_by(request.user) elif action == 'accept': nomination.accept(request.user) elif action == 'reject_by': nomination.reject_by(request.user) return HttpResponseRedirect(reverse( 'badger.views.nomination_detail', args=(slug, id))) return render_to_response('%s/nomination_detail.html' % bsettings.TEMPLATE_BASE, dict(badge=badge, nomination=nomination,), context_instance=RequestContext(request))
def test_claim_code_shows_awards_after_claim(self): """Claim code URL should lead to award detail or list after claim""" user1 = self._get_user(username="******", email="*****@*****.**") user2 = self._get_user(username="******", email="*****@*****.**") b1 = Badge.objects.create(creator=user1, unique=False, title="Badge for claim viewing") da = DeferredAward(badge=b1, creator=user1) da.save() url = da.get_claim_url() # Before claim, code URL leads to claim page. r = self.client.get(url, follow=False) eq_(200, r.status_code) doc = pq(r.content) form = doc("form#claim_award") # After claim, code URL leads to a single award detail page. award = da.claim(user2) r = self.client.get(url, follow=False) eq_(302, r.status_code) award_url = reverse("badger.views.award_detail", args=(award.badge.slug, award.pk)) ok_(award_url in r["Location"])
def test_disallowed_badge_award(self): """User should not be able to POST an award to a badge for which the user hasn't got permission to do so""" user = self._get_user(username="******", email="*****@*****.**") badge = Badge(creator=user, title="Hey you badge", description="Another test", unique=True) badge.save() awards_url = reverse('badger.views.awards_list', args=(self.badge.slug, )) data = dict(emails=[ '*****@*****.**', ]) resp = self.client.post(awards_url, json.dumps(data), content_type='application/json', HTTP_AUTHORIZATION=self.basic_auth) ok_(403, resp.status_code)
def edit(request, slug): """Edit an existing badge""" badge = get_object_or_404(Badge, slug=slug) if not badge.allows_edit_by(request.user): return HttpResponseForbidden() if request.method != "POST": form = BadgeEditForm(instance=badge) else: form = BadgeEditForm(request.POST, request.FILES, instance=badge) if form.is_valid(): new_sub = form.save(commit=False) new_sub.save() form.save_m2m() return HttpResponseRedirect( reverse('badger.views.detail', args=(new_sub.slug, ))) return render_to_response('%s/badge_edit.html' % bsettings.TEMPLATE_BASE, dict( badge=badge, form=form, ), context_instance=RequestContext(request))
def nominate_for(request, slug): """Submit nomination for a badge""" badge = get_object_or_404(Badge, slug=slug) if not badge.allows_nominate_for(request.user): return HttpResponseForbidden() if request.method != "POST": form = BadgeSubmitNominationForm() else: form = BadgeSubmitNominationForm(request.POST, request.FILES) if form.is_valid(): emails = form.cleaned_data['emails'] for email in emails: users = User.objects.filter(email=email) if not users: # TODO: Need a deferred nomination mechanism for # non-registered users. pass else: nominee = users[0] try: award = badge.nominate_for(nominee, request.user) messages.info(request, _(u'Nomination submitted for {email}').format(email=email)) except BadgeAlreadyAwardedException: messages.info(request, _(u'Badge already awarded to {email}').format(email=email)) except Exception: messages.info(request, _(u'Nomination failed for {email}').format(email=email)) return HttpResponseRedirect(reverse('badger.views.detail', args=(badge.slug,))) return render_to_response('%s/badge_nominate_for.html' % bsettings.TEMPLATE_BASE, dict(form=form, badge=badge,), context_instance=RequestContext(request))
def setUp(self): self.client = Client() self.testuser = self._get_user() self.badge = Badge(creator=self.testuser, title="Test II", description="Another test", unique=True) self.badge.save() self.awards_url = reverse('badger.views.awards_list', args=(self.badge.slug,)) key = Key() key.user = self.testuser self.password = key.generate_secret() self.username = key.key key.save() self.key = key auth_ct = '%s:%s' % (self.username, self.password) self.basic_auth = 'Basic %s' % b64encode(auth_ct) self.headers = {'HTTP_AUTHORIZATION': self.basic_auth} Award.objects.all().delete()