This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/shared/common/GroupsCommon.py

409 lines
15 KiB
Python

# -*- coding: iso-8859-15 -*-
# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
# Romain Chantereau <rchantereau@entrouvert.com>
# Nicolas Clapiès <nclapies@easter-eggs.org>
# Pierre-Antoine Dejace <padejace@entrouvert.be>
# Thierry Dulieu <tdulieu@easter-eggs.com>
# Florent Monnier <monnier@codelutin.com>
# Cédric Musso <cmusso@easter-eggs.org>
# Frédéric Péters <fpeters@entrouvert.be>
# Benjamin Poussin <poussin@codelutin.com>
# Emmanuel Raviart <eraviart@entrouvert.com>
# Sébastien Régnier <regnier@codelutin.com>
# Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
# Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
# Régnier, Emmanuel Saracco, Théridion & Vecam
#
# This program 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.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
__doc__ = """Glasnost Groups Common Models"""
__version__ = '$Revision$'[11:-2]
import context
import faults
import ObjectsCommon as objects
import system
import tools_new as commonTools
class AdminGroups(objects.AdminCommon):
serverRole = 'groups'
class GroupAbstract(objects.ObjectCommon):
# FIME: Replace by kind ServerRoles.
acceptedRoles = None
acceptedRoles_kindName = 'AcceptedRoles'
name = None
name_kind_balloonHelp = N_('Enter the name of this group.')
name_kind_isRequired = 1
name_kindName = 'String'
serverRole = 'groups'
writersSet = None
writersSet_kindName = 'WritersSet'
def canCache(self):
return 1
def contains(self, objectId, indirect = 1, resultWhenUnknown = 0):
"""Indicates whether the group contains an element."""
result = self.contains1(objectId, indirect, {})
if result is None:
result = resultWhenUnknown
return result
def contains1(self, objectId, indirect, results):
if results.has_key(self.id):
return results[self.id]
results[self.id] = None
result = self.contains2(objectId, indirect, results)
results[self.id] = result
return result
def contains2(self, objectId, indirect, results):
raise NotImplementedError
def getContainedIds(self, serverRoles = None, resultWhenUnknown = 0):
"""Return the ids of the objects contained in the group."""
small, large = self.getContainedIds1(serverRoles, {})
if resultWhenUnknown:
result = large
else:
result = small
if result == 'uncountable':
raise faults.UncountableGroup(self)
return result
def getContainedIds1(self, serverRoles, results):
if results.has_key(self.id):
return results[self.id]
results[self.id] = None
smallAndLarge = self.getContainedIds2(serverRoles, results)
results[self.id] = smallAndLarge
return smallAndLarge
def getContainedIds2(self, serverRoles, results):
raise NotImplementedError
def getGroup(self, groupId):
raise NotImplementedError
def getGroupContainedIds(self, groupId, serverRoles, results):
if groupId == system.generalPublicId:
if results.has_key(groupId):
return results[groupId]
if not serverRoles or 'people' in serverRoles:
smallAndLarge = 'uncountable', 'uncountable'
else:
smallAndLarge = [], []
results[groupId] = smallAndLarge
return smallAndLarge
else:
return self.getGroup(groupId).getContainedIds1(
serverRoles, results)
def getLabel(self):
label = self.name
if label is None:
return ''
return label
def getOrderedLayoutSlotNames(self, parentSlot = None):
slotNames = objects.ObjectCommon.getOrderedLayoutSlotNames(
self, parentSlot = parentSlot)
slotNames += ['name', 'className', 'acceptedRoles', 'writersSet']
return slotNames
def groupContains(self, groupId, objectId, indirect, results):
if groupId == system.generalPublicId:
if results.has_key(groupId):
return results[groupId]
result = not objectId \
or commonTools.extractRole(objectId) == 'people'
results[groupId] = result
return result
else:
return self.getGroup(groupId).contains1(
objectId, indirect, results)
class GroupCountableAbstract(GroupAbstract):
membersSet = None
membersSet_kind_itemKind_valueName = 'Id'
membersSet_kindName = 'Sequence'
def getOrderedLayoutSlotNames(self, parentSlot = None):
import glasnost.proxy.GroupsProxy as proxyGroups
import glasnost.web.GroupsWeb as webGroups
slotNames = GroupAbstract.getOrderedLayoutSlotNames(
self, parentSlot = parentSlot)
i = slotNames.index('writersSet')
slotNames = slotNames[:]
slotNames[i:i] = ['membersSet', 'itemIds']
return slotNames
class GroupAll(GroupAbstract):
def contains2(self, objectId, indirect, results):
if not objectId:
return 1
if self.acceptedRoles is None:
return 1
role = commonTools.extractRole(objectId)
return role in self.acceptedRoles
def getContainedIds2(self, serverRoles, results):
if not serverRoles or self.acceptedRoles is None:
return 'uncountable', 'uncountable'
for acceptedRole in self.acceptedRoles:
if acceptedRole in serverRoles:
return 'uncountable', 'uncountable'
return [], []
class GroupDelta(GroupCountableAbstract):
membersSet_kind_balloonHelp = N_('Select the items to subtract.')
def contains2(self, objectId, indirect, results):
if self.membersSet is None or len(self.membersSet) == 0:
return 0
elementId = self.membersSet[0]
if elementId != objectId and not isGroupId(elementId):
return 0
nonElementIds = []
for nonElementId in self.membersSet[1:]:
if nonElementId == objectId:
return 0
elif not isGroupId(nonElementId):
pass
else:
nonElementIds.append(nonElementId)
if not indirect:
return elementId == objectId
if self.groupContains(elementId, objectId, indirect, results) == 0:
return 0
result = 1
for nonElementId in nonElementIds:
nonElementResult = self.groupContains(
nonElementId, objectId, indirect, results)
if nonElementResult is None:
result = None
elif nonElementResult:
return 0
return result
def getContainedIds2(self, serverRoles, results):
if self.membersSet is None or len(self.membersSet) == 0:
return [], []
elementId = self.membersSet[0]
if isGroupId(elementId):
result = self.getGroupContainedIds(elementId, serverRoles, results)
if result is None:
raise faults.IllegalRecursiveGroup(elementId)
if not result[1]:
return [], []
else:
if serverRoles:
elementServerRole = commonTools.extractRole(elementId)
if not elementServerRole in serverRoles:
return [], []
result = [[elementId], [elementId]]
for memberId in self.membersSet[1:]:
if isGroupId(memberId):
memberResult = self.getGroupContainedIds(
memberId, serverRoles, results)
if memberResult is None:
raise faults.IllegalRecursiveGroup(memberId)
memberResult.reverse()
for i in [0, 1]:
if memberResult[i] == 'uncountable':
result[i] = []
elif result[i] == 'uncountable':
pass
else:
for nonElementId in memberResult[i]:
if nonElementId in result[i]:
result[i].remove(nonElementId)
else:
if serverRoles:
memberServerRole = commonTools.extractRole(memberId)
if not memberServerRole in serverRoles:
continue
for i in [0, 1]:
if result[i] == 'uncountable':
pass
elif memberId in result[i]:
result[i].remove(memberId)
if not result[1]:
return [], []
return result
class GroupIntersection(GroupCountableAbstract):
membersSet_kind_balloonHelp = N_('Select the items to intersect.')
def contains2(self, objectId, indirect, results):
if self.membersSet is None or len(self.membersSet) == 0:
return 0
result = 1
memberIds = []
for memberId in self.membersSet:
if memberId == objectId:
pass
elif not isGroupId(memberId):
return 0
else:
memberIds.append(memberId)
if not indirect:
return not memberIds
for memberId in memberIds:
memberResult = self.groupContains(
memberId, objectId, indirect, results)
if memberResult is None:
result = None
elif not memberResult:
return 0
return result
def getContainedIds2(self, serverRoles, results):
if self.membersSet is None or len(self.membersSet) == 0:
return [], []
result = ['uncountable', 'uncountable']
for memberId in self.membersSet:
if isGroupId(memberId):
memberResult = self.getGroupContainedIds(
memberId, serverRoles, results)
if memberResult is None:
raise faults.IllegalRecursiveGroup(memberId)
for i in [0, 1]:
if memberResult[i] == 'uncountable':
continue
elif not memberResult[i]:
result[i] = []
else:
if result[i] == 'uncountable':
result[i] = memberResult[i][:]
else:
for elementId in result[i][:]:
if not elementId in memberResult[i]:
result[i].remove(elementId)
else:
if serverRoles:
memberServerRole = commonTools.extractRole(memberId)
if not memberServerRole in serverRoles:
return [], []
for i in [0, 1]:
if result[i] == 'uncountable' or memberId in result[i]:
result[i] = [memberId]
else:
result[i] = []
if not result[1]:
return [], []
return result
class GroupUnion(GroupCountableAbstract):
membersSet_kind_balloonHelp = N_('Select the items of this group.')
def contains2(self, objectId, indirect, results):
if self.membersSet is None or len(self.membersSet) == 0:
return 0
result = 0
memberIds = []
for memberId in self.membersSet:
if memberId == objectId:
return 1
elif isGroupId(memberId):
memberIds.append(memberId)
if not indirect:
return 0
for memberId in memberIds:
memberResult = self.groupContains(
memberId, objectId, indirect, results)
if memberResult is None:
result = None
elif memberResult:
return 1
return result
def getContainedIds2(self, serverRoles, results):
if self.membersSet is None or len(self.membersSet) == 0:
return [], []
result = [[], []]
for memberId in self.membersSet:
if isGroupId(memberId):
memberResult = self.getGroupContainedIds(
memberId, serverRoles, results)
if memberResult is None:
raise faults.IllegalRecursiveGroup(memberId)
for i in [0, 1]:
if memberResult[i] == 'uncountable':
result[i] = 'uncountable'
elif result[i] == 'uncountable':
pass
else:
for elementId in memberResult[i]:
if not elementId in result[i]:
result[i].append(elementId)
else:
if serverRoles:
memberServerRole = commonTools.extractRole(memberId)
if not memberServerRole in serverRoles:
continue
for i in [0, 1]:
if result[i] == 'uncountable':
pass
elif not memberId in result[i]:
result[i].append(memberId)
if result[0] == 'uncountable':
return 'uncountable', 'uncountable'
return result
class GroupsCommonMixin(objects.ObjectsCommonMixin):
adminClassName = 'AdminGroups'
newObjectNameCapitalized = N_('New Group')
objectClassName = 'GroupUnion'
objectName = N_('group')
objectNameCapitalized = N_('Group')
objectsName = N_('groups')
objectsNameCapitalized = N_('Groups')
serverRole = 'groups'
def isGroupId(id):
return GroupsCommonMixin.serverRole == commonTools.extractRole(id)