def user_has_perm_note(note, profile, request=None): """ Check if the user has read/write permissions on the given note. Developers of the add-on used in the note, users in the CC list, and users who post to the thread are allowed to access the object. Moreover, other object permissions are also checked against the ACLs of the user. """ if note.author and note.author.id == profile.id: # Let the person access their own note. return True if request and note.note_type == comm.REVIEWER_COMMENT: # Internal reviewer comment only for reviewers. return acl.check_reviewer(request) if (request and note.note_type == comm.DEVELOPER_COMMENT and acl.check_reviewer(request)): # Reviewers can see developer comments. return True # User is a developer of the add-on and has the permission to read. user_is_author = profile.addons.filter(pk=note.thread._addon_id) if (user_is_author.exists() and note.read_permission_developer or note.note_type == comm.REVIEWER_PUBLIC_COMMENT): return True return check_acls_comm_obj(note, profile)
def setup_viewer(request, file_obj): data = {'file': file_obj, 'version': file_obj.version, 'webapp': file_obj.version.webapp, 'status': False, 'selected': {}, 'validate_url': ''} if (acl.check_reviewer(request) or acl.check_webapp_ownership(request, file_obj.version.webapp, viewer=True, ignore_disabled=True)): data['validate_url'] = reverse( 'mkt.developers.apps.json_file_validation', args=[file_obj.version.webapp.app_slug, file_obj.id]) if acl.check_reviewer(request): data['file_link'] = {'text': _('Back to review'), 'url': reverse('reviewers.apps.review', args=[data['webapp'].app_slug])} else: data['file_link'] = { 'text': _('Back to app'), 'url': reverse('detail', args=[data['webapp'].pk]) } return data
def setup_viewer(request, file_obj): data = { 'file': file_obj, 'version': file_obj.version, 'addon': file_obj.version.addon, 'status': False, 'selected': {}, 'validate_url': '' } if (acl.check_reviewer(request) or acl.check_addon_ownership( request, file_obj.version.addon, viewer=True, ignore_disabled=True)): data['validate_url'] = reverse( 'mkt.developers.apps.json_file_validation', args=[file_obj.version.addon.app_slug, file_obj.id]) if acl.check_reviewer(request): data['file_link'] = { 'text': _('Back to review'), 'url': reverse('reviewers.apps.review', args=[data['addon'].app_slug]) } else: data['file_link'] = { 'text': _('Back to app'), 'url': reverse('detail', args=[data['addon'].pk]) } return data
def create(self, request, *args, **kwargs): if not waffle.switch_is_active('comm-dashboard'): return Response(status=status.HTTP_403_FORBIDDEN) thread = get_object_or_404(CommunicationThread, id=kwargs['thread_id']) # Validate note. form = forms.CreateCommNoteForm(request.DATA) if not form.is_valid(): return Response(form.errors, status=status.HTTP_400_BAD_REQUEST) note_type = form.cleaned_data['note_type'] if (note_type == comm.DEVELOPER_COMMENT and not request.user.addonuser_set.filter( addon=thread.addon).exists()): # Developer comment only for developers. return Response('Only developers can make developer comments', status=status.HTTP_403_FORBIDDEN) elif (note_type == comm.REVIEWER_COMMENT and not acl.check_reviewer(request)): # Reviewer comment only for reviewers. return Response('Only reviewers can make reviewer comments', status=status.HTTP_403_FORBIDDEN) # Create notes. thread, note = create_comm_note( thread.addon, thread.version, self.request.user, form.cleaned_data['body'], note_type=note_type) return Response( NoteSerializer(note, context={'request': request}).data, status=status.HTTP_201_CREATED)
def create(self, request, *args, **kwargs): if not waffle.switch_is_active('comm-dashboard'): return Response(status=status.HTTP_403_FORBIDDEN) thread = get_object_or_404(CommunicationThread, id=kwargs['thread_id']) # Validate note. form = forms.CreateCommNoteForm(request.DATA) if not form.is_valid(): return Response(form.errors, status=status.HTTP_400_BAD_REQUEST) note_type = form.cleaned_data['note_type'] if (note_type == comm.DEVELOPER_COMMENT and not request.user.addonuser_set.filter( addon=thread.addon).exists()): # Developer comment only for developers. return Response('Only developers can make developer comments', status=status.HTTP_403_FORBIDDEN) elif (note_type == comm.REVIEWER_COMMENT and not acl.check_reviewer(request)): # Reviewer comment only for reviewers. return Response('Only reviewers can make reviewer comments', status=status.HTTP_403_FORBIDDEN) # Create notes. thread, note = create_comm_note(thread.addon, thread.version, self.request.user, form.cleaned_data['body'], note_type=note_type) return Response(NoteSerializer(note, context={ 'request': request }).data, status=status.HTTP_201_CREATED)
def global_settings(request): """Store global Marketplace-wide info. used in the header.""" account_links = [] tools_links = [] footer_links = [] context = {} tools_title = _('Tools') context['user'] = request.user if request.user.is_authenticated(): context['is_reviewer'] = acl.check_reviewer(request) account_links = [ # TODO: Coming soon with payments. # {'text': _('Account History'), # 'href': reverse('account.purchases')}, {'text': _('Account Settings'), 'href': '/settings'}, {'text': _('Change Password'), 'href': 'https://login.persona.org/signin'}, {'text': _('Sign out'), 'href': reverse('users.logout')}, ] if '/developers/' not in request.path: tools_links.append({'text': _('Developer Hub'), 'href': reverse('ecosystem.landing')}) if request.user.is_developer: tools_links.append({'text': _('My Submissions'), 'href': reverse('mkt.developers.apps')}) if '/reviewers/' not in request.path and context['is_reviewer']: footer_links.append({ 'text': _('Reviewer Tools'), 'href': reverse('reviewers.apps.queue_pending'), }) if acl.action_allowed(request, 'AccountLookup', '%'): footer_links.append({'text': _('Lookup Tool'), 'href': reverse('lookup.home')}) if acl.action_allowed(request, 'Admin', '%'): footer_links.append({'text': _('Admin Tools'), 'href': reverse('zadmin.home')}) tools_links += footer_links logged = True else: logged = False DESKTOP = (getattr(request, 'TABLET', None) or not getattr(request, 'MOBILE', None)) context.update(account_links=account_links, settings=settings, mkt=mkt, tools_links=tools_links, tools_title=tools_title, footer_links=footer_links, ADMIN_MESSAGE=get_config('site_notice'), collect_timings_percent=get_collect_timings(), is_admin=acl.action_allowed(request, 'Apps', 'Edit'), DESKTOP=DESKTOP, logged=logged) return context
def _record(request, addon): logged = request.user.is_authenticated() premium = addon.is_premium() # Require login for premium. if not logged and premium: return http.HttpResponseRedirect(reverse('users.login')) ctx = {'addon': addon.pk} # Don't generate receipts if we're allowing logged-out install. if logged: is_dev = request.check_ownership(addon, require_owner=False, ignore_disabled=True, admin=False) is_reviewer = acl.check_reviewer(request) if (not addon.is_public() and not (is_reviewer or is_dev)): raise http.Http404 if (premium and not addon.has_purchased(request.user) and not is_reviewer and not is_dev): raise PermissionDenied # If you are reviewer, you get a user receipt. Use the reviewer tools # to get a reviewer receipt. App developers still get their special # receipt. install = (apps.INSTALL_TYPE_DEVELOPER if is_dev else apps.INSTALL_TYPE_USER) # Log the install. installed, c = Installed.objects.get_or_create(addon=addon, user=request.user, install_type=install) # Get a suitable uuid for this receipt. uuid = get_uuid(addon, request.user) error = '' receipt_cef.log(request, addon, 'sign', 'Receipt requested') try: receipt = create_receipt(addon, request.user, uuid) except SigningError: error = _('There was a problem installing the app.') ctx.update(receipt=receipt, error=error) else: if not addon.is_public(): raise http.Http404 amo.log(amo.LOG.INSTALL_ADDON, addon) record_action( 'install', request, { 'app-domain': addon.domain_from_url(addon.origin, allow_none=True), 'app-id': addon.pk, 'anonymous': request.user.is_anonymous(), }) return ctx
def _record(request, addon): logged = request.user.is_authenticated() premium = addon.is_premium() # Require login for premium. if not logged and premium: return http.HttpResponseRedirect(reverse('users.login')) ctx = {'addon': addon.pk} # Don't generate receipts if we're allowing logged-out install. if logged: is_dev = request.check_ownership(addon, require_owner=False, ignore_disabled=True, admin=False) is_reviewer = acl.check_reviewer(request) if (not addon.is_webapp() or not addon.is_public() and not (is_reviewer or is_dev)): raise http.Http404 if (premium and not addon.has_purchased(request.amo_user) and not is_reviewer and not is_dev): raise PermissionDenied # If you are reviewer, you get a user receipt. Use the reviewer tools # to get a reviewer receipt. App developers still get their special # receipt. install = (apps.INSTALL_TYPE_DEVELOPER if is_dev else apps.INSTALL_TYPE_USER) # Log the install. installed, c = Installed.objects.get_or_create(addon=addon, user=request.amo_user, install_type=install) # Get a suitable uuid for this receipt. uuid = get_uuid(addon, request.amo_user) error = '' receipt_cef.log(request, addon, 'sign', 'Receipt requested') try: receipt = create_receipt(addon, request.amo_user, uuid) except SigningError: error = _('There was a problem installing the app.') ctx.update(receipt=receipt, error=error) else: if not addon.is_public() or not addon.is_webapp(): raise http.Http404 amo.log(amo.LOG.INSTALL_ADDON, addon) record_action('install', request, { 'app-domain': addon.domain_from_url(addon.origin, allow_none=True), 'app-id': addon.pk, 'anonymous': request.user.is_anonymous(), }) return ctx
def _has_create_perms(self, request, thread, profile, note_type): # Permissions check on the note type. if note_type == comm.DEVELOPER_COMMENT: # Developer comment only for developers. return thread.check_obj_author(profile) elif note_type == comm.REVIEWER_COMMENT: # Reviewer comment only for reviewers. return acl.check_reviewer(request) else: return True
def wrapper(request, *args, **kw): reviewer_perm = acl.check_reviewer(request) moderator_perm = (moderator and acl.action_allowed( request, 'Apps', 'ModerateReview')) view_only = (request.method == 'GET' and acl.action_allowed( request, 'ReviewerTools', 'View')) if (reviewer_perm or moderator_perm or view_only): return f(request, *args, **kw) else: raise PermissionDenied
def wrapper(request, *args, **kw): reviewer_perm = acl.check_reviewer(request) moderator_perm = (moderator and acl.action_allowed(request, 'Apps', 'ModerateReview')) view_only = (request.method == 'GET' and acl.action_allowed(request, 'ReviewerTools', 'View')) if (reviewer_perm or moderator_perm or view_only): return f(request, *args, **kw) else: raise PermissionDenied
def app_header(context, app, page_type=''): t = env.get_template('lookup/helpers/app_header.html') is_author = acl.check_ownership(context['request'], app) is_operator = any(g.name == 'Operators' for g in context['request'].groups) is_admin = acl.action_allowed(context['request'], 'Users', 'Edit') is_staff = acl.action_allowed(context['request'], 'Apps', 'Configure') is_reviewer = acl.check_reviewer(context['request']) return jinja2.Markup(t.render({'app': app, 'page_type': page_type, 'is_admin': is_admin, 'is_staff': is_staff, 'is_reviewer': is_reviewer, 'is_author': is_author, 'is_operator': is_operator}))
def allowed(request, file): allowed = acl.check_reviewer(request) if not allowed: try: addon = file.version.addon except ObjectDoesNotExist: raise http.Http404 if addon.status in amo.REVIEWED_STATUSES: allowed = True else: allowed = acl.check_addon_ownership(request, addon, viewer=True, dev=True) if not allowed: raise PermissionDenied return True
def user_can_delete_review(request, review): """Return whether or not the request.user can delete reviews. People who can delete reviews: * The original review author. * Reviewers, but only if they aren't listed as an author of the add-on. * Users in a group with "Users:Edit" privileges. * Users in a group with "Apps:ModerateReview" privileges. """ is_editor = acl.check_reviewer(request) is_author = review.addon.has_author(request.user) return (review.user_id == request.user.id or not is_author and (is_editor or acl.action_allowed(request, 'Users', 'Edit') or acl.action_allowed(request, 'Apps', 'ModerateReview')))
def home(request): durations = (('new', _('New Apps (Under 5 days)')), ('med', _('Passable (5 to 10 days)')), ('old', _('Overdue (Over 10 days)'))) progress, percentage = _progress() data = context( request, reviews_total=ActivityLog.objects.total_reviews(webapp=True)[:5], reviews_monthly=ActivityLog.objects.monthly_reviews(webapp=True)[:5], progress=progress, percentage=percentage, durations=durations, full_reviewer=acl.check_reviewer(request)) return render(request, 'reviewers/home.html', data)
def allowed(request, file): allowed = acl.check_reviewer(request) if not allowed: try: webapp = file.version.webapp except ObjectDoesNotExist: raise http.Http404 if webapp.status in mkt.REVIEWED_STATUSES: allowed = True else: allowed = acl.check_webapp_ownership(request, webapp, viewer=True, dev=True) if not allowed: raise PermissionDenied return True
def wrapper(request, webapp, *args, **kw): from mkt.submit.views import _resume def fun(): return f(request, webapp_id=webapp.id, webapp=webapp, *args, **kw) if allow_editors and acl.check_reviewer(request): return fun() if staff and (acl.action_allowed(request, 'Apps', 'Configure') or acl.action_allowed(request, 'Apps', 'ViewConfiguration')): return fun() if support: # Let developers and support people do their thangs. if (acl.check_webapp_ownership(request, webapp, support=True) or acl.check_webapp_ownership(request, webapp, dev=True)): return fun() else: # Require an owner or dev for POST requests. if request.method == 'POST': if acl.check_webapp_ownership(request, webapp, dev=not owner_for_post): return fun() # Ignore disabled so they can view their add-on. elif acl.check_webapp_ownership(request, webapp, viewer=True, ignore_disabled=True): if not skip_submit_check: try: # If it didn't go through the app submission # checklist. Don't die. This will be useful for # creating apps with an API later. step = webapp.appsubmissionchecklist.get_next() except ObjectDoesNotExist: step = None # Redirect to the submit flow if they're not done. if not getattr(f, 'submitting', False) and step: return _resume(webapp, step) return fun() raise PermissionDenied
def home(request): durations = (('new', _('New Apps (Under 5 days)')), ('med', _('Passable (5 to 10 days)')), ('old', _('Overdue (Over 10 days)'))) progress, percentage = _progress() data = context( request, reviews_total=ActivityLog.objects.total_reviews(webapp=True)[:5], reviews_monthly=ActivityLog.objects.monthly_reviews(webapp=True)[:5], progress=progress, percentage=percentage, durations=durations, full_reviewer=acl.check_reviewer(request) ) return render(request, 'reviewers/home.html', data)
def wrapper(request, addon, *args, **kw): from mkt.submit.views import _resume fun = lambda: f( request, addon_id=addon.id, addon=addon, *args, **kw) if allow_editors and acl.check_reviewer(request): return fun() if staff and (acl.action_allowed(request, 'Apps', 'Configure') or acl.action_allowed(request, 'Apps', 'ViewConfiguration')): return fun() if support: # Let developers and support people do their thangs. if (acl.check_addon_ownership(request, addon, support=True) or acl.check_addon_ownership(request, addon, dev=True)): return fun() else: # Require an owner or dev for POST requests. if request.method == 'POST': if acl.check_addon_ownership(request, addon, dev=not owner_for_post): return fun() # Ignore disabled so they can view their add-on. elif acl.check_addon_ownership(request, addon, viewer=True, ignore_disabled=True): if not skip_submit_check: try: # If it didn't go through the app submission # checklist. Don't die. This will be useful for # creating apps with an API later. step = addon.appsubmissionchecklist.get_next() except ObjectDoesNotExist: step = None # Redirect to the submit flow if they're not done. if not getattr(f, 'submitting', False) and step: return _resume(addon, step) return fun() raise PermissionDenied
def user_can_delete_review(request, review): """Return whether or not the request.user can delete reviews. People who can delete reviews: * The original review author. * Editors, but only if they aren't listed as an author of the add-on. * Users in a group with "Users:Edit" privileges. * Users in a group with "Addons:Edit" privileges. TODO: Make this more granular when we have multiple reviewer types, e.g. persona reviewers shouldn't be able to delete add-on reviews. """ is_editor = acl.check_reviewer(request) is_author = review.addon.has_author(request.user) return (review.user_id == request.user.id or not is_author and (is_editor or acl.action_allowed(request, 'Users', 'Edit') or acl.action_allowed(request, 'Apps', 'Edit')))
def user_can_delete_review(request, review): """Return whether or not the request.user can delete reviews. People who can delete reviews: * The original review author. * Reviewers, but only if they aren't listed as an author of the add-on. * Users in a group with "Users:Edit" privileges. * Users in a group with "Apps:ModerateReview" privileges. """ is_editor = acl.check_reviewer(request) is_author = review.addon.has_author(request.user) return ( review.user_id == request.user.id or not is_author and ( is_editor or acl.action_allowed(request, 'Users', 'Edit') or acl.action_allowed(request, 'Apps', 'ModerateReview')))
def user_can_delete_review(request, review): """Return whether or not the request.user can delete reviews. People who can delete reviews: * The original review author. * Editors, but only if they aren't listed as an author of the add-on. * Users in a group with "Users:Edit" privileges. * Users in a group with "Addons:Edit" privileges. TODO: Make this more granular when we have multiple reviewer types, e.g. persona reviewers shouldn't be able to delete add-on reviews. """ is_editor = acl.check_reviewer(request) is_author = review.addon.has_author(request.user) return ( review.user_id == request.user.id or not is_author and ( is_editor or acl.action_allowed(request, 'Users', 'Edit') or acl.action_allowed(request, 'Apps', 'Edit')))
def wrapper(request, *args, **kw): if (acl.check_reviewer(request, region=kw.get('region')) or _view_on_get(request)): return f(request, *args, **kw) else: raise PermissionDenied
def global_settings(request): """Store global Marketplace-wide info. used in the header.""" account_links = [] tools_links = [] footer_links = [] context = {} tools_title = _('Tools') context['user'] = request.user if request.user.is_authenticated(): context['is_reviewer'] = acl.check_reviewer(request) account_links = [ # TODO: Coming soon with payments. # {'text': _('Account History'), # 'href': reverse('account.purchases')}, { 'text': _('Account Settings'), 'href': '/settings' }, { 'text': _('Change Password'), 'href': 'https://login.persona.org/signin' }, { 'text': _('Sign out'), 'href': reverse('users.logout') }, ] if '/developers/' not in request.path: tools_links.append({ 'text': _('Developer Hub'), 'href': reverse('ecosystem.landing') }) if request.user.is_developer: tools_links.append({ 'text': _('My Submissions'), 'href': reverse('mkt.developers.apps') }) if '/reviewers/' not in request.path and context['is_reviewer']: footer_links.append({ 'text': _('Reviewer Tools'), 'href': reverse('reviewers.apps.queue_pending'), }) if acl.action_allowed(request, 'AccountLookup', '%'): footer_links.append({ 'text': _('Lookup Tool'), 'href': reverse('lookup.home') }) if acl.action_allowed(request, 'Admin', '%'): footer_links.append({ 'text': _('Admin Tools'), 'href': reverse('zadmin.home') }) tools_links += footer_links logged = True else: logged = False DESKTOP = (getattr(request, 'TABLET', None) or not getattr(request, 'MOBILE', None)) context.update(account_links=account_links, settings=settings, amo=amo, mkt=mkt, tools_links=tools_links, tools_title=tools_title, footer_links=footer_links, ADMIN_MESSAGE=get_config('site_notice'), collect_timings_percent=get_collect_timings(), is_admin=acl.action_allowed(request, 'Apps', 'Edit'), DESKTOP=DESKTOP, logged=logged) return context