filer.models.foldermodels: 180 total statements, 0.0% covered

Generated: Wed 2013-03-13 10:33 CET

Source file: /media/Envs/Envs/filer-gallery/lib/python2.7/site-packages/filer/models/foldermodels.py

Stats: 0 executed, 146 missed, 34 excluded, 119 ignored

  1. #-*- coding: utf-8 -*-
  2. from django.contrib.auth import models as auth_models
  3. from django.core import urlresolvers
  4. from django.core.exceptions import ValidationError
  5. from django.db import models
  6. from django.db.models import Q
  7. from django.utils.translation import ugettext_lazy as _
  8. from filer.models import mixins
  9. from filer import settings as filer_settings
  10. import mptt
  11. class FolderManager(models.Manager):
  12. def with_bad_metadata(self):
  13. return self.get_query_set().filter(has_all_mandatory_data=False)
  14. class FolderPermissionManager(models.Manager):
  15. """
  16. Theses methods are called by introspection from "has_generic_permisison" on
  17. the folder model.
  18. """
  19. def get_read_id_list(self, user):
  20. """
  21. Give a list of a Folders where the user has read rights or the string
  22. "All" if the user has all rights.
  23. """
  24. return self.__get_id_list(user, "can_read")
  25. def get_edit_id_list(self, user):
  26. return self.__get_id_list(user, "can_edit")
  27. def get_add_children_id_list(self, user):
  28. return self.__get_id_list(user, "can_add_children")
  29. def __get_id_list(self, user, attr):
  30. if user.is_superuser or not filer_settings.FILER_ENABLE_PERMISSIONS:
  31. return 'All'
  32. allow_list = set()
  33. deny_list = set()
  34. group_ids = user.groups.all().values_list('id', flat=True)
  35. q = Q(user=user) | Q(group__in=group_ids) | Q(everybody=True)
  36. perms = self.filter(q).order_by('folder__tree_id', 'folder__level',
  37. 'folder__lft')
  38. for perm in perms:
  39. p = getattr(perm, attr)
  40. if p is None:
  41. # Not allow nor deny, we continue with the next permission
  42. continue
  43. if not perm.folder:
  44. assert perm.type == FolderPermission.ALL
  45. if p == FolderPermission.ALLOW:
  46. allow_list.update(Folder.objects.all().values_list('id', flat=True))
  47. else:
  48. deny_list.update(Folder.objects.all().values_list('id', flat=True))
  49. continue
  50. folder_id = perm.folder.id
  51. if p == FolderPermission.ALLOW:
  52. allow_list.add(folder_id)
  53. else:
  54. deny_list.add(folder_id)
  55. if perm.type == FolderPermission.CHILDREN:
  56. if p == FolderPermission.ALLOW:
  57. allow_list.update(perm.folder.get_descendants().values_list('id', flat=True))
  58. else:
  59. deny_list.update(perm.folder.get_descendants().values_list('id', flat=True))
  60. # Deny has precedence over allow
  61. return allow_list - deny_list
  62. class Folder(models.Model, mixins.IconsMixin):
  63. """
  64. Represents a Folder that things (files) can be put into. Folders are *NOT*
  65. mirrored in the Filesystem and can have any unicode chars as their name.
  66. Other models may attach to a folder with a ForeignKey. If the related name
  67. ends with "_files" they will automatically be listed in the
  68. folder.files list along with all the other models that link to the folder
  69. in this way. Make sure the linked models obey the AbstractFile interface
  70. (Duck Type).
  71. """
  72. file_type = 'Folder'
  73. is_root = False
  74. can_have_subfolders = True
  75. _icon = 'plainfolder'
  76. parent = models.ForeignKey('self', verbose_name=('parent'), null=True, blank=True,
  77. related_name='children')
  78. name = models.CharField(_('name'), max_length=255)
  79. owner = models.ForeignKey(auth_models.User, verbose_name=('owner'),
  80. related_name='filer_owned_folders',
  81. null=True, blank=True)
  82. uploaded_at = models.DateTimeField(_('uploaded at'), auto_now_add=True)
  83. created_at = models.DateTimeField(_('created at'), auto_now_add=True)
  84. modified_at = models.DateTimeField(_('modified at'),auto_now=True)
  85. objects = FolderManager()
  86. @property
  87. def file_count(self):
  88. if not hasattr(self, '_file_count_cache'):
  89. self._file_count_cache = self.files.count()
  90. return self._file_count_cache
  91. @property
  92. def children_count(self):
  93. if not hasattr(self, '_children_count_cache'):
  94. self._children_count_cache = self.children.count()
  95. return self._children_count_cache
  96. @property
  97. def item_count(self):
  98. return self.file_count + self.children_count
  99. @property
  100. def files(self):
  101. return self.all_files.all()
  102. @property
  103. def logical_path(self):
  104. """
  105. Gets logical path of the folder in the tree structure.
  106. Used to generate breadcrumbs
  107. """
  108. folder_path = []
  109. if self.parent:
  110. folder_path.extend(self.parent.get_ancestors())
  111. folder_path.append(self.parent)
  112. return folder_path
  113. @property
  114. def pretty_logical_path(self):
  115. return u"/%s" % u"/".join([f.name for f in self.logical_path+[self]])
  116. def has_edit_permission(self, request):
  117. return self.has_generic_permission(request, 'edit')
  118. def has_read_permission(self, request):
  119. return self.has_generic_permission(request, 'read')
  120. def has_add_children_permission(self, request):
  121. return self.has_generic_permission(request, 'add_children')
  122. def has_generic_permission(self, request, permission_type):
  123. """
  124. Return true if the current user has permission on this
  125. folder. Return the string 'ALL' if the user has all rights.
  126. """
  127. user = request.user
  128. if not user.is_authenticated():
  129. return False
  130. elif user.is_superuser:
  131. return True
  132. elif user == self.owner:
  133. return True
  134. else:
  135. if not hasattr(self, "permission_cache") or\
  136. permission_type not in self.permission_cache or \
  137. request.user.pk != self.permission_cache['user'].pk:
  138. if not hasattr(self, "permission_cache") or request.user.pk != self.permission_cache['user'].pk:
  139. self.permission_cache = {
  140. 'user': request.user,
  141. }
  142. # This calls methods on the manager i.e. get_read_id_list()
  143. func = getattr(FolderPermission.objects,
  144. "get_%s_id_list" % permission_type)
  145. permission = func(user)
  146. if permission == "All":
  147. self.permission_cache[permission_type] = True
  148. self.permission_cache['read'] = True
  149. self.permission_cache['edit'] = True
  150. self.permission_cache['add_children'] = True
  151. else:
  152. self.permission_cache[permission_type] = self.id in permission
  153. return self.permission_cache[permission_type]
  154. def get_admin_url_path(self):
  155. return urlresolvers.reverse('admin:filer_folder_change',
  156. args=(self.id,))
  157. def get_admin_directory_listing_url_path(self):
  158. return urlresolvers.reverse('admin:filer-directory_listing',
  159. args=(self.id,))
  160. def __unicode__(self):
  161. return u"%s" % (self.name,)
  162. def contains_folder(self, folder_name):
  163. try:
  164. self.children.get(name=folder_name)
  165. return True
  166. except Folder.DoesNotExist:
  167. return False
  168. class Meta:
  169. unique_together = (('parent', 'name'),)
  170. ordering = ('name',)
  171. permissions = (("can_use_directory_listing",
  172. "Can use directory listing"),)
  173. app_label = 'filer'
  174. verbose_name = _("Folder")
  175. verbose_name_plural = _("Folders")
  176. # MPTT registration
  177. try:
  178. mptt.register(Folder)
  179. except mptt.AlreadyRegistered:
  180. pass
  181. class FolderPermission(models.Model):
  182. ALL = 0
  183. THIS = 1
  184. CHILDREN = 2
  185. ALLOW = 1
  186. DENY = 0
  187. TYPES = (
  188. (ALL, _('all items')),
  189. (THIS, _('this item only')),
  190. (CHILDREN, _('this item and all children')),
  191. )
  192. PERMISIONS = (
  193. (ALLOW, _('allow')),
  194. (DENY, _('deny')),
  195. )
  196. folder = models.ForeignKey(Folder, verbose_name=('folder'), null=True, blank=True)
  197. type = models.SmallIntegerField(_('type'), choices=TYPES, default=ALL)
  198. user = models.ForeignKey(auth_models.User,
  199. related_name="filer_folder_permissions",
  200. verbose_name=_("user"), blank=True, null=True)
  201. group = models.ForeignKey(auth_models.Group,
  202. related_name="filer_folder_permissions",
  203. verbose_name=_("group"), blank=True, null=True)
  204. everybody = models.BooleanField(_("everybody"), default=False)
  205. can_edit = models.SmallIntegerField(_("can edit"), choices=PERMISIONS, blank=True, null=True, default=None)
  206. can_read = models.SmallIntegerField(_("can read"), choices=PERMISIONS, blank=True, null=True, default=None)
  207. can_add_children = models.SmallIntegerField(_("can add children"), choices=PERMISIONS, blank=True, null=True, default=None)
  208. objects = FolderPermissionManager()
  209. def __unicode__(self):
  210. if self.folder:
  211. name = u'%s' % self.folder
  212. else:
  213. name = u'All Folders'
  214. ug = []
  215. if self.everybody:
  216. ug.append('Everybody')
  217. else:
  218. if self.group:
  219. ug.append(u"Group: %s" % self.group)
  220. if self.user:
  221. ug.append(u"User: %s" % self.user)
  222. usergroup = " ".join(ug)
  223. perms = []
  224. for s in ['can_edit', 'can_read', 'can_add_children']:
  225. perm = getattr(self, s)
  226. if perm == self.ALLOW:
  227. perms.append(s)
  228. elif perm == self.DENY:
  229. perms.append('!%s' % s)
  230. perms = ', '.join(perms)
  231. return u"Folder: '%s'->%s [%s] [%s]" % (
  232. name, unicode(self.TYPES[self.type][1]),
  233. perms, usergroup)
  234. def clean(self):
  235. if self.type == self.ALL and self.folder:
  236. raise ValidationError('Folder cannot be selected with type "all items".')
  237. if self.type != self.ALL and not self.folder:
  238. raise ValidationError('Folder has to be selected when type is not "all items".')
  239. if self.everybody and (self.user or self.group):
  240. raise ValidationError('User or group cannot be selected together with "everybody".')
  241. if not self.user and not self.group and not self.everybody:
  242. raise ValidationError('At least one of user, group, or "everybody" has to be selected.')
  243. class Meta:
  244. verbose_name = _('folder permission')
  245. verbose_name_plural = _('folder permissions')
  246. app_label = 'filer'