diff --git a/patchwork/admin.py b/patchwork/admin.py index d3bdae1bb..49e981c8d 100644 --- a/patchwork/admin.py +++ b/patchwork/admin.py @@ -8,6 +8,8 @@ from django.contrib.auth.models import User from django.db.models import Prefetch +from guardian.admin import GuardedModelAdmin + from patchwork.models import Bundle from patchwork.models import Check from patchwork.models import Cover @@ -45,7 +47,7 @@ class DelegationRuleInline(admin.TabularInline): @admin.register(Project) -class ProjectAdmin(admin.ModelAdmin): +class ProjectAdmin(GuardedModelAdmin): list_display = ('name', 'linkname', 'listid', 'listemail') inlines = [ DelegationRuleInline, diff --git a/patchwork/api/check.py b/patchwork/api/check.py index 74bbc19e0..e793aef9e 100644 --- a/patchwork/api/check.py +++ b/patchwork/api/check.py @@ -108,9 +108,27 @@ class CheckListCreate(CheckMixin, ListCreateAPIView): lookup_url_kwarg = 'patch_id' ordering = 'id' + def is_editable(self, user, patch): + if not user.is_authenticated: + return False + + # Only users with add_check permission can do it. + # Notice that this is a global permission: it allows + # adding checks to any project inside Patchwork. + if user.has_perm('patchwork.add_check'): + patch._edited_by = user + return True + + if user.has_perm('patchwork.add_check', patch.project): + patch._edited_by = user + return True + + # Being maintainer doesn't grant rights to create checks. + return False + def create(self, request, patch_id, *args, **kwargs): p = get_object_or_404(Patch, id=patch_id) - if not p.is_editable(request.user): + if not self.is_editable(request.user, p): raise PermissionDenied() request.patch = p return super(CheckListCreate, self).create(request, *args, **kwargs) diff --git a/patchwork/models.py b/patchwork/models.py index d5cb31de9..700476ce6 100644 --- a/patchwork/models.py +++ b/patchwork/models.py @@ -52,6 +52,7 @@ def __str__(self): return self.email class Meta: + default_permissions = () verbose_name_plural = 'People' @@ -120,8 +121,13 @@ def __str__(self): return self.name class Meta: + default_permissions = () unique_together = (('listid', 'subject_match'),) ordering = ['linkname'] + permissions = [ + # Per-project permission to add checks + ("add_check", "Can add checks"), + ] class DelegationRule(models.Model): @@ -145,6 +151,7 @@ def __str__(self): return self.path class Meta: + default_permissions = () ordering = ['-priority', 'path'] unique_together = ('path', 'project') @@ -253,6 +260,7 @@ def __str__(self): return self.name class Meta: + default_permissions = () ordering = ['ordering'] @@ -285,6 +293,7 @@ def __str__(self): return self.name class Meta: + default_permissions = () ordering = ['abbrev'] @@ -294,6 +303,7 @@ class PatchTag(models.Model): count = models.IntegerField(default=1) class Meta: + default_permissions = () unique_together = [('patch', 'tag')] @@ -415,6 +425,7 @@ def save(self, *args, **kwargs): super(EmailMixin, self).save(*args, **kwargs) class Meta: + default_permissions = () abstract = True @@ -457,6 +468,7 @@ def __str__(self): return self.name class Meta: + default_permissions = () abstract = True @@ -480,6 +492,7 @@ def get_mbox_url(self): ) class Meta: + default_permissions = () ordering = ['date'] unique_together = [('msgid', 'project')] indexes = [ @@ -717,6 +730,7 @@ def __str__(self): return self.name class Meta: + default_permissions = () verbose_name_plural = 'Patches' ordering = ['date'] base_manager_name = 'objects' @@ -780,6 +794,7 @@ def is_editable(self, user): return False class Meta: + default_permissions = () ordering = ['date'] unique_together = [('msgid', 'cover')] indexes = [ @@ -825,6 +840,7 @@ def is_editable(self, user): return self.patch.is_editable(user) class Meta: + default_permissions = () ordering = ['date'] unique_together = [('msgid', 'patch')] indexes = [ @@ -985,6 +1001,7 @@ def __str__(self): return self.name if self.name else 'Untitled series #%d' % self.id class Meta: + default_permissions = () verbose_name_plural = 'Series' @@ -1010,6 +1027,7 @@ def __str__(self): return self.msgid class Meta: + default_permissions = () unique_together = [('project', 'msgid')] @@ -1072,6 +1090,7 @@ def get_mbox_url(self): ) class Meta: + default_permissions = () unique_together = [('owner', 'name')] @@ -1081,6 +1100,7 @@ class BundlePatch(models.Model): order = models.IntegerField() class Meta: + default_permissions = () unique_together = [('bundle', 'patch')] ordering = ['order'] @@ -1150,6 +1170,9 @@ def __repr__(self): def __str__(self): return '%s (%s)' % (self.context, self.get_state_display()) + class Meta: + default_permissions = ('add',) + class Event(models.Model): """An event raised against a patch. @@ -1332,6 +1355,7 @@ def __repr__(self): return "