Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Pootle-2.0.0/local_apps/pootle_app/models/permissions.py
diff options
context:
space:
mode:
Diffstat (limited to 'Pootle-2.0.0/local_apps/pootle_app/models/permissions.py')
-rw-r--r--Pootle-2.0.0/local_apps/pootle_app/models/permissions.py167
1 files changed, 167 insertions, 0 deletions
diff --git a/Pootle-2.0.0/local_apps/pootle_app/models/permissions.py b/Pootle-2.0.0/local_apps/pootle_app/models/permissions.py
new file mode 100644
index 0000000..bcb3c9c
--- /dev/null
+++ b/Pootle-2.0.0/local_apps/pootle_app/models/permissions.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2008 Zuza Software Foundation
+#
+# This file is part of translate.
+#
+# translate is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# translate is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with translate; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from django.db import models
+from django.contrib.auth.models import Permission
+from django.contrib.contenttypes.models import ContentType
+from django.db.models.signals import pre_delete, post_save
+
+from pootle_app.lib.util import RelatedManager
+from pootle_app.models.directory import Directory
+
+def get_pootle_permission(codename):
+ # The content type of our permission
+ content_type = ContentType.objects.get(name='pootle', app_label='pootle_app')
+ # Get the pootle view permission
+ return Permission.objects.get(content_type=content_type, codename=codename)
+
+def get_pootle_permissions(codenames=None):
+ """gets the available rights and their localized names"""
+ # l10n: Verb
+ content_type = ContentType.objects.get(name='pootle', app_label='pootle_app')
+ if codenames is not None:
+ permissions = Permission.objects.filter(content_type=content_type, codename__in=codenames)
+ else:
+ permissions = Permission.objects.filter(content_type=content_type)
+ return dict((permission.codename, permission) for permission in permissions)
+
+def get_permission_set_by_username(username, directory):
+ try:
+ return PermissionSet.objects.get(profile__user__username=username, directory=directory)
+ except PermissionSet.DoesNotExist:
+ pass
+ try:
+ return PermissionSet.objects.get(profile__user__username='default', directory=directory)
+ except PermissionSet.DoesNotExist:
+ return None
+
+def get_matching_permission_set(profile, directory):
+ if profile.user.is_authenticated():
+ try:
+ return PermissionSet.objects.get(profile=profile, directory=directory)
+ except PermissionSet.DoesNotExist:
+ return get_permission_set_by_username('default', directory)
+ else:
+ return get_permission_set_by_username('nobody', directory)
+
+def get_matching_permissions_recurse(profile, directory):
+ """Build a (permission codename -> permission) dictionary which
+ reflects the permissions that the PootleProfile 'profile' has in
+ the directory 'directory'. This is done by taking the permissions
+ associated with 'profile' in all parent directories into account.
+
+ Recurse from 'directory' all the way up to the root directory.
+ Once we hit the root, find a PermissionSet which matches the
+ supplied PootleProfile 'profile' and Directory 'directory'. Add
+ the positive permissions from this PermissionSet to the dictionary
+ which we are building and use the negative permissions associated
+ with the root directory to remove permissions from the permissions
+ dictionary.
+
+ Once this has been done for the root directory, we recurse one
+ level up and do the same to the child directory and so on until we
+ reach the directory from which we started this process. By that
+ point we'll have a permissions dictionary reflecting the
+ permissions that 'profile' has in 'directory'."""
+ if directory.parent is not None:
+ permissions = get_matching_permissions(profile, directory.parent)
+ else:
+ permissions = {}
+
+ permission_set = get_matching_permission_set(profile, directory)
+ if permission_set is not None:
+ permissions.update((permission.codename, permission)
+ for permission in permission_set.positive_permissions.all())
+ for permission in permission_set.negative_permissions.all():
+ if permission.codename in permissions:
+ del permissions[permission.codename]
+ return permissions
+
+def get_matching_permissions(profile, directory):
+ try:
+ cached_permission_set = PermissionSetCache.objects.get(profile=profile, directory=directory)
+ return dict((permission.codename, permission) for permission in cached_permission_set.permissions.all())
+ except PermissionSetCache.DoesNotExist:
+ permissions = get_matching_permissions_recurse(profile, directory)
+ # Ensure that administrative superusers always get admin rights
+ if profile.user.is_superuser and 'administrate' not in permissions:
+ permissions['administrate'] = get_pootle_permission('administrate')
+ cached_permission_set = PermissionSetCache(profile=profile, directory=directory)
+ cached_permission_set.save()
+ cached_permission_set.permissions = permissions.values()
+ cached_permission_set.save()
+ return permissions
+
+
+def check_profile_permission(profile, permission_codename, directory):
+ """it checks if current user has the permission the perform C{permission_codename}"""
+ if profile.user.is_superuser:
+ return True
+ permissions = get_matching_permissions(profile, directory)
+ return permission_codename in permissions
+
+def check_permission(permission_codename, request):
+ """it checks if current user has the permission the perform C{permission_codename}"""
+ if request.user.is_superuser:
+ return True
+ return permission_codename in request.permissions
+
+class PermissionSet(models.Model):
+ objects = RelatedManager()
+ class Meta:
+ unique_together = ('profile', 'directory')
+ app_label = "pootle_app"
+
+ profile = models.ForeignKey('pootle_app.PootleProfile', db_index=True)
+ directory = models.ForeignKey(Directory, db_index=True, related_name='permission_sets')
+ positive_permissions = models.ManyToManyField(Permission, db_index=True, related_name='permission_sets_positive')
+ negative_permissions = models.ManyToManyField(Permission, db_index=True, related_name='permission_sets_negative')
+
+class PermissionSetCache(models.Model):
+ objects = RelatedManager()
+ class Meta:
+ unique_together = ('profile', 'directory')
+ app_label = "pootle_app"
+
+
+ profile = models.ForeignKey('pootle_app.PootleProfile', db_index=True)
+ directory = models.ForeignKey(Directory, db_index=True, related_name='permission_set_caches')
+ permissions = models.ManyToManyField(Permission, related_name='cached_permissions', db_index=True)
+
+
+def nuke_permission_set_caches(profile, directory):
+ """Delete all PermissionSetCache objects matching the current
+ profile and whose directories are subdirectories of directory."""
+ for permission_set_cache in PermissionSetCache.objects.filter(profile=profile, directory__pootle_path__startswith=directory.pootle_path):
+ permission_set_cache.delete()
+
+def void_cached_permissions(sender, instance, **kwargs):
+ if instance.profile.user.username == 'default':
+ profile_to_permission_set = dict((permission_set.profile, permission_set) for permission_set
+ in PermissionSet.objects.filter(directory=instance.directory))
+ for permission_set_cache in PermissionSetCache.objects.filter(directory=instance.directory):
+ if permission_set_cache.profile not in profile_to_permission_set:
+ nuke_permission_set_caches(permission_set_cache.profile, instance.directory)
+ else:
+ nuke_permission_set_caches(instance.profile, instance.directory)
+
+post_save.connect(void_cached_permissions, sender=PermissionSet)
+pre_delete.connect(void_cached_permissions, sender=PermissionSet)