def test_group_management(self): x = UserProfile.objects.get(pk=10482) assert not action_allowed_user(x, 'Admin', '%') do_adduser('10482', '1') assert action_allowed_user(x, 'Admin', '%') do_removeuser('10482', '1') assert not action_allowed_user(x, 'Admin', '%')
def test_group_management(self): #TODO. I don't know how to override caching in tests --clouserw raise SkipTest('Fails due to caching of groups.all()') x = UserProfile.objects.get(pk=10482) assert not action_allowed_user(x, 'Admin', '%') do_adduser('10482', '1') assert action_allowed_user(x, 'Admin', '%') do_removeuser('10482', '1') assert not action_allowed_user(x, 'Admin', '%')
def save_from_email_reply(reply_text): from mkt.comm.utils import create_comm_note log.debug("Saving from email reply") parser = CommEmailParser(reply_text) if hasattr(parser, 'decode_error'): return False uuid = parser.get_uuid() if not uuid: return False try: tok = CommunicationThreadToken.objects.get(uuid=uuid) except CommunicationThreadToken.DoesNotExist: log.error('An email was skipped with non-existing uuid %s.' % uuid) return False thread = tok.thread if user_has_perm_thread(thread, tok.user) and tok.is_valid(): # Deduce an appropriate note type. note_type = comm.NO_ACTION # grep: comm-content-type. if (thread.obj.__class__ == Webapp and tok.user.addonuser_set.filter(addon=thread.obj).exists()): note_type = comm.DEVELOPER_COMMENT elif (thread.obj.__class__ == Extension and tok.user.extension_set.filter(id=thread.obj.id).exists()): note_type = comm.DEVELOPER_COMMENT elif (acl.action_allowed_user(tok.user, 'Apps', 'Review') or acl.action_allowed_user(tok.user, 'ContentTools', 'AddonReview')): note_type = comm.REVIEWER_PUBLIC_COMMENT t, note = create_comm_note(tok.thread.obj, tok.thread.version, tok.user, parser.get_body(), note_type=note_type) log.info('A new note has been created (from %s using tokenid %s).' % (tok.user.id, uuid)) return note elif tok.is_valid(): log.error('%s did not have perms to reply to comm email thread %s.' % (tok.user.email, tok.thread.id)) else: log.error('%s tried to use an invalid comm token for thread %s.' % (tok.user.email, tok.thread.id)) return False
def save_from_email_reply(reply_text): from mkt.comm.utils import create_comm_note log.debug("Saving from email reply") parser = CommEmailParser(reply_text) if hasattr(parser, 'decode_error'): return False uuid = parser.get_uuid() if not uuid: return False try: tok = CommunicationThreadToken.objects.get(uuid=uuid) except CommunicationThreadToken.DoesNotExist: log.error('An email was skipped with non-existing uuid %s.' % uuid) return False thread = tok.thread if user_has_perm_thread(thread, tok.user) and tok.is_valid(): # Deduce an appropriate note type. note_type = comm.NO_ACTION # grep: comm-content-type. if (thread.obj.__class__ == Webapp and tok.user.addonuser_set.filter(addon=thread.obj).exists()): note_type = comm.DEVELOPER_COMMENT elif (thread.obj.__class__ == Extension and tok.user.extension_set.filter(id=thread.obj.id).exists()): note_type = comm.DEVELOPER_COMMENT elif (acl.action_allowed_user(tok.user, 'Apps', 'Review') or acl.action_allowed_user(tok.user, 'ContentTools', 'AddonReview')): note_type = comm.REVIEWER_COMMENT t, note = create_comm_note(tok.thread.obj, tok.thread.version, tok.user, parser.get_body(), note_type=note_type) log.info('A new note has been created (from %s using tokenid %s).' % (tok.user.id, uuid)) return note elif tok.is_valid(): log.error('%s did not have perms to reply to comm email thread %s.' % (tok.user.email, tok.thread.id)) else: log.error('%s tried to use an invalid comm token for thread %s.' % (tok.user.email, tok.thread.id)) return False
def save_from_email_reply(reply_text): parser = CommEmailParser(reply_text) if hasattr(parser, "decode_error"): return False uuid = parser.get_uuid() if not uuid: return False try: tok = CommunicationThreadToken.objects.get(uuid=uuid) except CommunicationThreadToken.DoesNotExist: log.error("An email was skipped with non-existing uuid %s." % uuid) return False if user_has_perm_thread(tok.thread, tok.user) and tok.is_valid(): # Deduce an appropriate note type. note_type = comm.NO_ACTION if tok.user.addonuser_set.filter(addon=tok.thread.addon).exists(): note_type = comm.DEVELOPER_COMMENT elif acl.action_allowed_user(tok.user, "Apps", "Review"): note_type = comm.REVIEWER_COMMENT t, note = create_comm_note( tok.thread.addon, tok.thread.version, tok.user, parser.get_body(), note_type=note_type ) log.info("A new note has been created (from %s using tokenid %s)." % (tok.user.id, uuid)) return note elif tok.is_valid(): log.error("%s did not have perms to reply to comm email thread %s." % (tok.user.email, tok.thread.id)) else: log.error("%s tried to use an invalid comm token for thread %s." % (tok.user.email, tok.thread.id)) return False
def check_acls(user, obj, acl_type): """Check ACLs.""" if acl_type == "moz_contact": try: return user.email in obj.addon.get_mozilla_contacts() except AttributeError: return user.email in obj.thread.addon.get_mozilla_contacts() if acl_type == "admin": return acl.action_allowed_user(user, "Admin", "%") elif acl_type == "reviewer": return acl.action_allowed_user(user, "Apps", "Review") elif acl_type == "senior_reviewer": return acl.action_allowed_user(user, "Apps", "ReviewEscalated") else: raise Exception("Invalid ACL lookup.") return False
def check_acls(user, obj, acl_type): """Check ACLs.""" if acl_type == 'moz_contact': try: return user.email in obj.addon.get_mozilla_contacts() except AttributeError: return user.email in obj.thread.addon.get_mozilla_contacts() if acl_type == 'admin': return acl.action_allowed_user(user, 'Admin', '%') elif acl_type == 'reviewer': return acl.action_allowed_user(user, 'Apps', 'Review') elif acl_type == 'senior_reviewer': return acl.action_allowed_user(user, 'Apps', 'ReviewEscalated') else: raise Exception('Invalid ACL lookup.') return False
def issue(request, addon): user = request.user review = acl.action_allowed_user(user, 'Apps', 'Review') if user else None developer = addon.has_author(user) if not (review or developer): raise PermissionDenied install, flavour = ((apps.INSTALL_TYPE_REVIEWER, 'reviewer') if review else (apps.INSTALL_TYPE_DEVELOPER, 'developer')) installed, c = Installed.objects.safer_get_or_create(addon=addon, user=request.user, install_type=install) error = '' receipt_cef.log(request, addon, 'sign', 'Receipt signing for %s' % flavour) receipt = None try: receipt = create_receipt(addon, user, get_uuid(addon, user), flavour=flavour) except SigningError: error = _('There was a problem installing the app.') return {'addon': addon.pk, 'receipt': receipt, 'error': error}
def get_mail_context(note, user_id): """ Get context data for comm emails, specifically for review action emails. """ obj = note.thread.obj # grep: comm-content-type. if obj.name and obj.__class__ == Webapp: # We need to display the name in some language that is relevant to the # recipient(s) instead of using the reviewer's. addon.default_locale # should work. lang = to_language(obj.default_locale) with translation.override(lang): obj = Webapp.with_deleted.get(id=obj.id) elif not obj.name: # For deleted objects. obj.name = obj.app_slug if hasattr(obj, 'app_slug') else obj.slug if user_id: UserProfile.objects.get(id=user_id) # grep: comm-content-type. manage_url = '' obj_type = '' thread_url = '' if obj.__class__ == Webapp: manage_url = absolutify(obj.get_dev_url('versions')) obj_type = 'app' thread_url = absolutify( reverse('commonplace.commbadge.show_thread', args=[note.thread.id])) elif obj.__class__ == Extension: manage_url = absolutify( reverse('commonplace.content.addon_manage', args=[obj.slug])) # Not "Firefox OS add-on" for a/an consistency with "app". obj_type = 'add-on' if user_id: user = UserProfile.objects.get(id=user_id) if acl.action_allowed_user(user, 'ContentTools', 'AddonReview'): thread_url = absolutify( reverse('commonplace.content.addon_review', args=[obj.slug])) else: thread_url = manage_url return { 'mkt': mkt, 'comm': comm, 'is_app': obj.__class__ == Webapp, 'is_extension': obj.__class__ == Extension, 'manage_url': manage_url, 'note': note, 'obj': obj, 'obj_type': obj_type, 'settings': settings, 'thread_url': thread_url }
def get_mail_context(note, user_id): """ Get context data for comm emails, specifically for review action emails. """ obj = note.thread.obj # grep: comm-content-type. if obj.name and obj.__class__ == Webapp: # We need to display the name in some language that is relevant to the # recipient(s) instead of using the reviewer's. addon.default_locale # should work. lang = to_language(obj.default_locale) with translation.override(lang): obj = Webapp.with_deleted.get(id=obj.id) elif not obj.name: # For deleted objects. obj.name = obj.app_slug if hasattr(obj, 'app_slug') else obj.slug if user_id: UserProfile.objects.get(id=user_id) # grep: comm-content-type. manage_url = '' obj_type = '' thread_url = '' if obj.__class__ == Webapp: manage_url = absolutify(obj.get_dev_url('versions')) obj_type = 'app' thread_url = absolutify(reverse('commonplace.commbadge.show_thread', args=[note.thread.id])) elif obj.__class__ == Extension: manage_url = absolutify(reverse('commonplace.content.addon_manage', args=[obj.slug])) # Not "Firefox OS add-on" for a/an consistency with "app". obj_type = 'add-on' if user_id: user = UserProfile.objects.get(id=user_id) if acl.action_allowed_user(user, 'ContentTools', 'AddonReview'): thread_url = absolutify( reverse('commonplace.content.addon_review', args=[obj.slug])) else: thread_url = manage_url return { 'mkt': mkt, 'comm': comm, 'is_app': obj.__class__ == Webapp, 'is_extension': obj.__class__ == Extension, 'manage_url': manage_url, 'note': note, 'obj': obj, 'obj_type': obj_type, 'settings': settings, 'thread_url': thread_url }
def issue(request, addon): user = request.user review = acl.action_allowed_user(user, "Apps", "Review") if user else None developer = addon.has_author(user) if not (review or developer): raise PermissionDenied install, flavour = ( (apps.INSTALL_TYPE_REVIEWER, "reviewer") if review else (apps.INSTALL_TYPE_DEVELOPER, "developer") ) installed, c = Installed.objects.safer_get_or_create(addon=addon, user=request.user, install_type=install) error = "" receipt_cef.log(request, addon, "sign", "Receipt signing for %s" % flavour) receipt = None try: receipt = create_receipt(addon, user, get_uuid(addon, user), flavour=flavour) except SigningError: error = _("There was a problem installing the app.") return {"addon": addon.pk, "receipt": receipt, "error": error}
def verify(request, uuid): # Because this will be called at any point in the future, # use guid in the URL. addon = get_object_or_404(Addon, guid=uuid) receipt = request.read() verify = Verify(receipt, request.META) output = verify.check_without_purchase() # Only reviewers or the developers can use this which is different # from the standard receipt verification. The user is contained in the # receipt. if verify.user_id: try: user = UserProfile.objects.get(pk=verify.user_id) except UserProfile.DoesNotExist: user = None if user and (acl.action_allowed_user(user, "Apps", "Review") or addon.has_author(user)): amo.log(amo.LOG.RECEIPT_CHECKED, addon, user=user) return response(output) return response(verify.invalid())
def issue(request, addon): user = request.amo_user review = acl.action_allowed_user(user, 'Apps', 'Review') if user else None developer = addon.has_author(user) if not (review or developer): raise PermissionDenied install, flavour = ((apps.INSTALL_TYPE_REVIEWER, 'reviewer') if review else (apps.INSTALL_TYPE_DEVELOPER, 'developer')) installed, c = Installed.objects.safer_get_or_create(addon=addon, user=request.amo_user, install_type=install) error = '' receipt_cef.log(request, addon, 'sign', 'Receipt signing for %s' % flavour) receipt = None try: receipt = create_receipt(addon, user, get_uuid(addon, user), flavour=flavour) except SigningError: error = _('There was a problem installing the app.') return {'addon': addon.pk, 'receipt': receipt, 'error': error}
def verify(request, uuid): # Because this will be called at any point in the future, # use guid in the URL. addon = get_object_or_404(Webapp, guid=uuid) receipt = request.read() verify = Verify(receipt, request.META) output = verify.check_without_purchase() # Only reviewers or the developers can use this which is different # from the standard receipt verification. The user is contained in the # receipt. if verify.user_id: try: user = UserProfile.objects.get(pk=verify.user_id) except UserProfile.DoesNotExist: user = None if user and (acl.action_allowed_user(user, 'Apps', 'Review') or addon.has_author(user)): amo.log(amo.LOG.RECEIPT_CHECKED, addon, user=user) return response(output) return response(verify.invalid())
def create_receipt_data(webapp, user, uuid, flavour=None, contrib=None): """ Creates receipt data for use in payments. :params app: the app record. :params user: the UserProfile record. :params uuid: a uuid placed in the user field for this purchase. :params flavour: None, developer, inapp, or reviewer - the flavour of receipt. :param: contrib: the Contribution object for the purchase. """ # Unflavo(u)red receipts are for plain ol' vanilla app purchases. assert flavour in (None, 'developer', 'inapp', 'reviewer'), ( 'Invalid flavour: %s' % flavour) time_ = calendar.timegm(time.gmtime()) typ = 'purchase-receipt' storedata = {'id': int(webapp.pk)} # Generate different receipts for reviewers or developers. expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS verify = static_url('WEBAPPS_RECEIPT_URL') if flavour == 'inapp': if not contrib: raise ValueError( 'a contribution object is required for in-app receipts') if not contrib.inapp_product: raise ValueError( 'contribution {c} does not link to an in-app product' .format(c=contrib)) storedata['contrib'] = int(contrib.pk) storedata['inapp_id'] = contrib.inapp_product.guid elif flavour in ('developer', 'reviewer'): if not (acl.action_allowed_user(user, 'Apps', 'Review') or webapp.has_author(user)): raise ValueError('User %s is not a reviewer or developer' % user.pk) # Developer and reviewer receipts should expire after 24 hours. expiry = time_ + (60 * 60 * 24) typ = flavour + '-receipt' verify = absolutify(reverse('receipt.verify', args=[webapp.guid])) product = {'storedata': urlencode(storedata), # Packaged and hosted apps should have an origin. If there # isn't one, fallback to the SITE_URL. 'url': webapp.origin or settings.SITE_URL} reissue = absolutify(reverse('receipt.reissue')) receipt = dict(exp=expiry, iat=time_, iss=settings.SITE_URL, nbf=time_, product=product, # TODO: This is temporary until detail pages get added. # TODO: bug 1020997, bug 1020999 detail=absolutify(reissue), # Currently this is a 404. reissue=absolutify(reissue), typ=typ, user={'type': 'directed-identifier', 'value': uuid}, verify=verify) return receipt
def create_receipt_data(webapp, user, uuid, flavour=None, contrib=None): """ Creates receipt data for use in payments. :params app: the app record. :params user: the UserProfile record. :params uuid: a uuid placed in the user field for this purchase. :params flavour: None, developer, inapp, or reviewer - the flavour of receipt. :param: contrib: the Contribution object for the purchase. """ # Unflavo(u)red receipts are for plain ol' vanilla app purchases. assert flavour in (None, 'developer', 'inapp', 'reviewer'), ('Invalid flavour: %s' % flavour) time_ = calendar.timegm(time.gmtime()) typ = 'purchase-receipt' storedata = {'id': int(webapp.pk)} # Generate different receipts for reviewers or developers. expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS verify = static_url('WEBAPPS_RECEIPT_URL') if flavour == 'inapp': if not contrib: raise ValueError( 'a contribution object is required for in-app receipts') if not contrib.inapp_product: raise ValueError( 'contribution {c} does not link to an in-app product'.format( c=contrib)) storedata['contrib'] = int(contrib.pk) storedata['inapp_id'] = contrib.inapp_product.guid elif flavour in ('developer', 'reviewer'): if not (acl.action_allowed_user(user, 'Apps', 'Review') or webapp.has_author(user)): raise ValueError('User %s is not a reviewer or developer' % user.pk) # Developer and reviewer receipts should expire after 24 hours. expiry = time_ + (60 * 60 * 24) typ = flavour + '-receipt' verify = absolutify(reverse('receipt.verify', args=[webapp.guid])) product = { 'storedata': urlencode(storedata), # Packaged and hosted apps should have an origin. If there # isn't one, fallback to the SITE_URL. 'url': webapp.origin or settings.SITE_URL } reissue = absolutify(reverse('receipt.reissue')) receipt = dict( exp=expiry, iat=time_, iss=settings.SITE_URL, nbf=time_, product=product, # TODO: This is temporary until detail pages get added. # TODO: bug 1020997, bug 1020999 detail=absolutify(reissue), # Currently this is a 404. reissue=absolutify(reissue), typ=typ, user={ 'type': 'directed-identifier', 'value': uuid }, verify=verify) return receipt
def is_staff(self): from mkt.access import acl return acl.action_allowed_user(self, 'Admin', '%')