409 lines
15 KiB
Python
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)
|
|
|