class ObjectReadOnlyBase(Object, Events, ObjectWorkflow): """ *Non-container object with read only access* This one does not support subobjects. """ implements(INonContainer, IObject, IReadonly)
class ObjectBase(Object, ObjectEdit, Events, ObjectWorkflow): """ *Default non-container object with write access* This one does not support subobjects. """ implements(INonContainer, IObject)
class column(PageElementContainerBase): implements(IColumn) @property def page(self): return self.parent def IsLocal(self, page): return self.meta.pool_unitref == page.id def GetName(self): return self.meta["title"] def IsContainer(self): return True def IsPage(self): return False def GetPage(self): return self.parent def GetPages(self): return [] def GetElementContainer(self): return self def GetContainer(self): return self.parent def GetColumn(self, name): if name == self.meta["title"]: return self return self.GetPage().GetColumn(name)
class PersistentConf(object): """ configuration persistence base class --------------------------------------- """ implements(IPersistent) def __init__(self, app, configuration): self.app = app self.conf = configuration def Load(self): """ Load configuration values from backend and map to configuration. """ raise TypeError, "subclass" def Save(self, values): """ Store configuration values in backend. """ raise TypeError, "subclass" def Changed(self): """ Validate configuration and backend timestamp and check if values have changed. """ return False def _GetUid(self): return self.conf.uid()
class root(PageRootBase): implements(IWebsiteRoot) extension = u"html" def Init(self): self.queryRestraints = {"pool_state": 1}, {}
class RootReadOnlyBase(Root, Container, Search, Events, ContainerFactory, RootWorkflow): """ *Root with readonly access and cache* Root class without add and delete support for subobjects. Objects are cached in memory. """ implements(IRoot, IContainer, IReadonly)
class ObjectContainerReadOnlyBase(Object, ObjectWorkflow, Container, Events, ContainerFactory): """ *Container object with read only access and cache* This one supports subobjects and caches them in memory. """ implements(IObject, IContainer, IReadonly)
class RootBase(Root, Container, Search, ContainerEdit, ContainerSecurity, Events, ContainerFactory, RootWorkflow): """ *Root Edit* Default root class with add and delete support for subobjects. """ implements(IContainer, IRoot)
class FolderBase(ContainerCopy, PageElement, ObjectContainerBase): """ *Resource container* - stored in database - handles files and resource objects - supports paste of elements """ implements(IFolder)
class ObjectContainerBase(Object, ObjectEdit, ObjectWorkflow, Container, ContainerEdit, ContainerSecurity, Events, ContainerFactory): """ *Default container object with write access* This one supports subobjects. """ implements(IContainer, IObject)
class UserDB(ApplicationBase): """ """ implements(IUserDatabase) def Groupfinder(self, userid, request=None, context=None): """ returns the list of groups assigned to the user """ if request: try: user = request.environ["authenticated_user"] except KeyError: user = self.root().GetUser(userid) request.environ["authenticated_user"] = user def remove_user(request): if "authenticated_user" in request.environ: del request.environ["authenticated_user"] request.add_finished_callback(remove_user) else: user = self.root().GetUser(userid) if user is None: return None # users groups or empty list groups = user.groups or () # lookup context for local roles if context is None and hasattr(request, "context"): context = request.context if context and ILocalGroups.providedBy(context): local = context.GetLocalGroups(userid, user=user) if not groups: return local return tuple(list(groups) + list(local)) return groups def RememberLogin(self, request, user): """ add login info to cookies or session. """ if not hasattr(request.response, "headerlist"): request.response.headerlist = [] headers = remember(request, user) request.response.headerlist += list(headers) def ForgetLogin(self, request, url=None): """ removes login info from cookies and session """ if not hasattr(request.response, "headerlist"): setattr(request.response, "headerlist", []) headers = forget(request) request.response.headerlist += list(headers)
class ApplicationBase(Application, AppFactory, Configuration, Registration, Events): """ *Nive cms application* The application manages module registration, module configuration, root dispatching and basic application events. """ implements(IApplication)
class PageElementBase(ObjCopy, PageElement, ObjectBase): """ *Page element* - stored in database - does not store subobjects - stored in element containers - cut, copy and paste support Interfaces: ``INonContainer, IObject, IPageElement`` """ implements(IPageElement)
class PageElementContainerBase(Sort, ContainerCopy, PageElementContainer, ObjectContainerBase): """ *Element container* - stored in database - handles page elements - supports paste of elements and pages - contained pages and elements are sortable Interfaces: ``IContainer, IObject, IPageElement, IPageElementContainer`` """ implements(IPageElement, IPageElementContainer)
class SessionUser(object): """ The session user is created on login by the _real_ database user and cached on app level. In subsequent requests the session user is loaded from cache and attached to the request. All functions are readonly. The Session User is not connected to the database or application. Lifecycle: Login adds the user to the cache. Logout removes the user from the cache. Updates of user values also removes the user from cache. Default data values: name, email, surname, lastname, groups """ implements(ISessionUser) def __init__(self, ident, id, data, meta=None): self.id = id self.identity = ident self.data = data self.meta = meta self.lastlogin = data.get(u"lastlogin") self.currentlogin = time.time() def __str__(self): return str(self.identity) @property def groups(self): return self.data.groups def GetGroups(self, context=None): """ Returns the users gloabal groups as tuple. Local assignments are not supported, `context` is currently unused. """ return self.data.groups def InGroups(self, groups): """ check if user has one of these groups """ if isinstance(groups, basestring): return groups in self.data.groups for g in groups: if g in self.data.groups: return True return False def ReadableName(self): if self.data.surname or self.data.lastname: return u" ".join([self.data.surname, self.data.lastname]) return self.data.name
class PageElementFileBase(ObjCopy, PageElement, ObjectBase): """ *Page element with file download support* - stored in database - does not store subobjects - stored in element containers - cut, copy and paste support - contained files can be downloaded Interfaces: ``INonContainer, IObject, IPageElement, IFile`` """ implements(IPageElement, IFile)
class PageRootBase(ContainerCopy, Sort, AlternateRootPath, PageColumns, PageContainer, PageElementContainer, RootBase): """ *Root with content element support* - handles sub pages - handles page columns - rendered as website page - is an element container - supports paste of elements and pages - contained pages and elements are sortable Interfaces: ``IPageContainer, IPageElementContainer, IContainer, IRoot`` """ implements(IPageContainer, IPageElementContainer)
class cmsroot(PageRootBase): #implements(IWebsiteRoot, ICMSRoot) implements(ICMSRoot) extension = u"html" def Init(self): self.__acl__ = ( (Allow, 'group:editor', 'view'), (Allow, 'group:author', 'view'), (Allow, 'group:reviewer', 'view'), (Allow, 'group:reader', 'view'), (Allow, 'group:admin', 'view'), (Deny, Everyone, 'view'), )
class PageBase(ContainerCopy, Sort, AlternatePath, PageColumns, PageContainer, PageElementContainer, ObjectContainerBase): """ *Page with content element support* - stored in database - rendered as website page - handles sub pages - handles page columns - is an element container - supports paste of elements and pages - contained pages and elements are sortable Interfaces: ``IPage, IPageContainer, IPageElementContainer, IContainer, IObject`` """ implements(IPage, IPageContainer, IPageElementContainer)
class AdminUser(object): """ Admin User object with groups and login possibility. """ implements(IAdminUser) def __init__(self, values, ident): self.id = 0 self.data = Conf(**values) self.meta = Conf() self.identity = ident or str(self.id) if values.get("groups"): groups = tuple(values.get("groups")) else: groups = (u"group:admin", ) self.groups = self.data.groups = groups def __str__(self): return str(self.identity) def Authenticate(self, password): return password == unicode(self.data["password"]) def Login(self): """ """ def Logout(self): """ """ def GetGroups(self, context=None): """ """ return self.groups def InGroups(self, groups): """ check if user has one of these groups """ if isinstance(groups, basestring): return groups in self.groups for g in groups: if g in self.groups: return True return False def ReadableName(self): return self.data.name
class user(ObjectBase): """ User object with groups and login possibility. """ implements(IUser) @property def identity(self): return self.data.get(self.parent.identityField,str(self.id)) def __str__(self): return str(self.identity) def Init(self): self.groups = tuple(self.data.get("groups",())) self.ListenEvent("commit", "OnCommit") def Authenticate(self, password): return Sha(password) == self.data["password"] def Login(self): """ events: login(lastlogin) """ lastlogin = self.data.get("lastlogin") date = datetime.now() self.data.set("lastlogin", date) self.Commit(self) self.Signal("login", lastlogin=lastlogin) def Logout(self): """ events: logout() """ self.Signal("logout") self.Commit(self) def OnCommit(self): self.HashPassword() t = self.ReadableName() if t != self.meta["title"]: self.meta["title"] = t def HashPassword(self): if not self.data.HasTempKey("password"): return pw = Sha(self.data.password) self.data["password"] = pw def ReadableName(self): if self.data.surname or self.data.lastname: return u" ".join([self.data.surname, self.data.lastname]) return self.data.name def SecureUpdate(self, data, user): """ Update existing user data. name, groups, pool_state cannot be changed """ if data.has_key("name"): del data["name"] if data.has_key("groups"): del data["groups"] if data.has_key("pool_state"): del data["pool_state"] if not self.Update(data, user): return False, [_(u"Update failed.")] self.Commit(user) return True, [] def UpdateGroups(self, groups): """ update groups of user """ self.groups = tuple(groups) self.data["groups"] = groups return True def AddGroup(self, group, user): """ add user to this group event: securityCahnged() """ if group in self.groups: return True g = list(self.groups) g.append(group) self.groups = tuple(g) self.data["groups"] = g self.Commit(user) return True def GetGroups(self, context=None): """ Returns the users gloabal groups as tuple. Local assignments are not supported, `context` is currently unused. """ return self.groups def InGroups(self, groups): """ check if user has one of these groups """ if isinstance(groups, basestring): return groups in self.groups for g in groups: if g in self.groups: return True return False
class Portal(Events, object): """ """ implements(IPortal) __name__ = u"" __parent__ = None def __init__(self, configuration=None): """ Events: - init(configuration) """ self.components = [] self.groups = [ Conf(id=u"authenticated", name=_(u"Authenticated"), visible=True) ] self.__acl__ = [(Allow, "group:admin", ALL_PERMISSIONS)] self.configuration = configuration or PortalConf() self.Signal("init", configuration=self.configuration) def __del__(self): self.Close() def __getitem__(self, name): """ Called by traversal machinery event: getitem(obj) called with the traversed object """ try: obj = getattr(self, name) self.Signal("getitem", obj=obj) return obj except AttributeError: raise KeyError, name def Register(self, comp, name=None): """ Register an application or component. This is usually done in the pyramid app file. The registered component is automatically loaded and set up to work with url traversal. *comp* can be one of the following cases - AppConf object - AppConf string as python dotted name - python object. Requires *name* parameter or *comp.id* attribute *name* is used as the url path name to lookup the component. """ log = logging.getLogger("portal") iface, conf = ResolveConfiguration(comp) if not conf: if not name or isinstance(comp, basestring): raise ConfigurationError, "Portal registration failure. No name given (%s)" % ( str(comp)) elif isinstance(comp, basestring): c = ResolveName(conf.context) comp = c(conf) elif iface and iface.providedBy(comp): c = ResolveName(conf.context) comp = c(conf) try: if not name: name = conf.id except: pass if not name: raise ConfigurationError, "Portal registration failure. No name given (%s)" % ( str(comp)) log.debug("Portal.Register: %s %s", name, repr(conf)) self.__dict__[name] = comp comp.__parent__ = self comp.__name__ = name self.components.append(name) #self.RegisterGroups(comp) def Startup(self, pyramidConfig, debug=False): """ *Startup* is called once by the *main* function of the pyramid wsgi app on server startup. All configuration, registration and setup is handled during the startup call. Calls *Startup()* for each registered component. *pyramidConfig* is the pyramid registration configuration object for views and other system components. nive ViewConf_ and ViewModuelConf_ are automatically with pyramid. *debug* signals whether running in debug mode or not. """ log = logging.getLogger("portal") log.debug("Portal.Startup with debug=%s", str(debug)) if pyramidConfig: self.SetupPortalViews(pyramidConfig) #pyramidConfig.add_subscriber(self.StartConnection, iface=NewRequest) for c in self.components: component = getattr(self, c) if hasattr(component, "Startup"): component.Startup(pyramidConfig, debug=debug) def GetApps(self, interface=None): """ Returns registered components and apps as list. """ if isinstance(interface, basestring): interface = ResolveName(interface) apps = [] for name in self.components: a = getattr(self, name) if interface: if not interface.providedBy(a): continue apps.append(a) return apps def StartConnection(self, event): """ Called by pyramid for each new connection with event as parameter. The current request stored as *event.request*. Stores the authenticated user *event.request.environ["REMOTE_USER"]*. Event: - start(event) """ uid = authenticated_userid(event.request) event.request.environ["REMOTE_USER"] = uid event.request.environ["START_TIME"] = time.time() self.Signal("start", event=event) #event.request.add_finished_callback(self.FinishConnection) def FinishConnection(self, request): """ Called by pyramid on termination for each connection with request as parameter. Event: - finish(request) """ self.Signal("finish", request) def GetGroups(self, sort=u"id", visibleOnly=False): """ returns all groups registered by components as list """ if visibleOnly: #opt g = [] for a in self.groups: if not a.get("hidden"): g.append(a) else: g = self.groups if not sort: return g l = copy.deepcopy(g) return SortConfigurationList(l, sort) @property def portal(self): return self def RegisterGroups(self, component): """ Collects groups from the component """ try: gr = component.configuration.groups for g in gr: add = 1 for g2 in self.groups: if g["id"] == g2["id"]: add = 0 break if add: self.groups.append(g) except: pass def SetupPortalViews(self, config): # redirects config.add_view(error_view, context=HTTPError) config.add_view(forbidden_view, context=Forbidden) config.add_view(portal_view, name="", context="nive.portal.Portal") config.add_view(robots_view, name="robots.txt", context="nive.portal.Portal") config.add_view(sitemap_view, name="sitemap.xml", context="nive.portal.Portal") config.add_view(logout_view, name="logout", context="nive.portal.Portal") config.add_view(login_view, name="login", context="nive.portal.Portal") config.add_view(account_view, name="account", context="nive.portal.Portal") #config.add_view(favicon_view, name=u"favicon.txt", context=u"nive.portal.Portal", view=PortalViews) # translations config.add_translation_dirs('nive:locale/') config.commit() def Close(self): for name in self.components: a = getattr(self, name) a.Close() setattr(self, name, None) # bw 0.9.4 def GetComponents(self): return self.GetApps()
class ContainerCache: """ Object caching support Caches loaded objects including data as attributes. Subsequent lookups won't access the database to load the object. Options :: useCache = enable or disable caching cacheTypes = a list of pool_types to be cached. not matching types are not cached expires = objs are reloaded or purged after this many seconds. 0 = never expires The cache is currently not *edit* aware and only recommended for readonly pages. """ implements(ICache) useCache = True cacheTypes = None expires = 0 def Cache(self, obj, id): """ """ if not self.useCache: return True try: t = obj.GetTypeID() if self.cacheTypes and not t in self.cacheTypes: return False except: if self.cacheTypes: return False try: lock = thread.allocate_lock() lock.acquire(1) setattr(self, self._Cachename(id), (obj, time())) if lock.locked(): lock.release() except: if lock and lock.locked(): lock.release() return False return True def GetFromCache(self, id=0): """ returns the cached object """ if not self.useCache: return None n = self._Cachename(id) try: lock = thread.allocate_lock() lock.acquire(1) if hasattr(self, n): o = getattr(self, n) if lock.locked(): lock.release() return o[0] except: if lock and lock.locked(): lock.release() return None def GetAllFromCache(self): """ returns all cached objects """ objs = [] try: lock = thread.allocate_lock() lock.acquire(1) for v in self.__dict__.keys(): if v[:5] == "__c__": objs.append(getattr(self, v)[0]) if lock.locked(): lock.release() except: if lock and lock.locked(): lock.release() return objs def RemoveCache(self, id): """ """ if not self.useCache: return True try: lock = thread.allocate_lock() lock.acquire(1) try: delattr(self, self._Cachename(id)) except: pass if lock.locked(): lock.release() except: if lock and lock.locked(): lock.release() return True def _Cachename(self, id): return "__c__" + str(id)
class Tool(object): """ """ implements(ITool) def __init__(self, configuration, app): self.configuration = configuration self.app_ = app self.stream = False self.__name__ = "" self.__parent__ = None self.__acl__ = [] self.id = "" self.mimetype = "text/html" self._LoadConfiguration() def _LoadConfiguration(self): """ loads self.configuration """ if not self.configuration: raise ConfigurationError, "Tool configuration is None. Please load the tool by referencing the tool configuration." c = self.configuration for k in c.keys(): # special values if k == "id" and c.id: self.__name__ = c.id self.id = c.id if k == "acl" and c.acl: self.__acl__ = c.acl continue # map value setattr(self, k, c[k]) @property def app(self): """ returns the cms application object """ return self.app_ # Subclass functions -------------------------------------------- def _Run(self, **values): result = True return result # Execution -------------------------------------------------------------------------------------------- def __call__(self, **kw): return self.Run(**kw) def Run(self, **kw): """ Execute the tool. If stream is disabled (self.stream = None) and no stream is passed, the function returns the result data as string/binary. Otherwise the stream is returned as second parameter. returns bool, stream """ if not self.stream: self.stream = StringIO() # call function values = self.ExtractValues(**kw) values["original"] = kw result = self._Run(**values) return result, self.stream def ExtractValues(self, **kw): """ Extract values for configured parameters 1) tool.Run(values): call specific values 2) tool.configuration.values: configured values on application level 3) tool.data: default prarameter values returns dictionary """ values = {} cv = self.configuration.values for p in self.configuration.data: if p.id in kw: values[p.id] = kw[p.id] elif p.id in cv: values[p.id] = cv[p.id] else: values[p.id] = p.default return values def AppliesTo(self, poolType): """ Return if this tool applies to the given nive object type. returns bool """ if not self.configuration.apply: return False return poolType in self.configuration.apply def GetAllParameters(self): """ Return the configured parameter definitions for the function returns list """ return self.configuration.data def GetParameter(self, id): """ Get single parameter definition for function returns configuration or None """ for fld in self.configuration.data: if fld.id == id: return fld return None
class _GlobalObject(object): """ used for global tool lookup """ implements(_IGlobal)
class Sort: """ Container sort functionality Objects can explicitly be sorted and moved up or down in sequence. Sort values are stored in meta.pool_sort. """ implements(ISort) def GetSort(self): """ default sort field for subobjects """ return u"pool_sort" def GetSortElements(self, selection=None): """ returns the contents as sorted list """ if selection == "pages": return self.GetPages(public=0) if selection == "elements": return self.GetPageElements() return self.GetObjs() def GetMaxSort(self): """ returns the maximum sort number """ parameter = {u"pool_unitref": self.GetID()} operators = {u"pool_unitref": u"="} fields = [u"-max(pool_sort)"] root = self.dataroot parameter, operators = root.ObjQueryRestraints(self, parameter, operators) r = root.Select(parameter=parameter, fields=fields, operators=operators, sort=u"", max=1) if len(r): s = r[0][0] if s == None: s = 0 return s return 0 def UpdateSort(self, objs, user): """ update pool_sort values according to list """ if not objs: return False, _(u"List is empty") if isinstance(objs, basestring): objs = ConvertToNumberList(objs) ids = [] for oi in objs: # check if listed objects are objects or ids if not IObject.providedBy(oi): ids.append(int(oi)) objs2 = [] if ids: # load remaining objects by id objs2 = self.GetObjsBatch(ids) pos = 10 processed = [] for obj in objs: if not IObject.providedBy(obj): for o in objs2: if o.id == int(obj): obj = o break if not IObject.providedBy(obj): continue if obj.id in processed: continue processed.append(obj.id) obj.meta.set("pool_sort", pos) obj.CommitInternal(user) pos += 10 return True, _(u"OK") def InsertAtPosition(self, id, position, user, selection=None): """ position = 'first', 'last' or number """ if position == u"last": return self.MoveEnd(id, user=user) elif position == u"first": return self.MoveStart(id, user=user) return self.InsertAfter(id, position, user, selection=selection) def InsertBefore(self, id, position, user, selection=None): """ insert id before position element id """ position = int(position) order = [] objs = self.GetSortElements(selection) oid = id if not IObject.providedBy(id) else id.id # if id already included in container, remove it delpos = -1 # make sure id is added even if position does not exist added = False for current in objs: if position == current.id: order.append(id) order.append(current) if current.id == oid: delpos = len(order) - 1 if delpos > -1: del order[delpos] if not added: order.insert(0, id) ok, msgs = self.UpdateSort(order, user=user) return ok, msgs def InsertAfter(self, id, position, user, selection=None): """ insert id after position element id """ position = int(position) order = [] objs = self.GetSortElements(selection) oid = id if not IObject.providedBy(id) else id.id # if id already included in container, remove it delpos = -1 # make sure id is added even if position does not exist added = False for current in objs: order.append(current) if current.id == oid: delpos = len(order) - 1 if position == current.id: order.append(id) if delpos > -1: del order[delpos] if not added: order.append(id) ok, msgs = self.UpdateSort(order, user=user) return ok, msgs def MoveUp(self, id, user, selection=None): """ move one position up in container """ objs = self.GetSortElements(selection) order = [] oid = id if not IObject.providedBy(id) else id.id pos = 0 for obj in objs: if obj.id == oid: if len(order) == 0: return True, [] order.insert(len(order) - 1, obj) else: order.append(obj) ok, msgs = self.UpdateSort(order, user=user) return ok, msgs def MoveDown(self, id, user, selection=None): """ move one position down in container """ objs = self.GetSortElements(selection) order = [] oid = id if not IObject.providedBy(id) else id.id insertID = None for obj in objs: if obj.id == oid: insertID = obj else: order.append(obj) if insertID: order.append(insertID) insertID = None if insertID: order.append(insertID) ok, msgs = self.UpdateSort(order, user=user) return ok, msgs def MoveStart(self, id, user, selection=None): """ move to top in container """ objs = self.GetSortElements(selection) oid = id if not IObject.providedBy(id) else id.id order = [id] for obj in objs: if oid == obj.id: order[1:].insert(0, obj) else: order.append(obj) ok, msgs = self.UpdateSort(order, user=user) return ok, msgs def MoveEnd(self, id, user, selection=None): """ move to bottom in container """ objs = self.GetSortElements(selection) oid = id if not IObject.providedBy(id) else id.id lastObj = None order = [] for obj in objs: if oid == obj.id: lastObj = obj else: order.append(obj) if lastObj: order.append(lastObj) else: order.append(id) ok, msgs = self.UpdateSort(order, user=user) return ok, msgs
class LocalGroups(object): """ """ _owner = u"group:owner" implements(ILocalGroups) def Init(self): self._localRoles = {} self.ListenEvent("create", "AddOwner") self._secid = self.id or self.idhash def GetLocalGroups(self, username, user=None): """ Group assignments use the user name. returns a list of all local user groups, including parent settings """ if self.id <= 0: return self._LocalGroups(username) g = [] o = self while o: g += o._LocalGroups(username) o = o.GetParent() return g def AllLocalGroups(self): """ returns a list of all local user group settings as list including [username, group, id]. This function does not include parent level settings. """ return self.db.GetGroups(self._secid) def AddOwner(self, user, **kw): """ Add the current user as group:owner to local roles """ if not user or not str(user): return self.AddLocalGroup(str(user), self._owner) def AddLocalGroup(self, username, group): """ Add a local group assignment for username. """ groups = self._LocalGroups(username) if group in groups: return if username==None: return self._AddLocalGroupsCache(username, group) self.db.AddGroup(self._secid, userid=username, group=group) def RemoveLocalGroups(self, username, group=None): """ Remove a local group assignment. If group is None all local groups will be removed. """ self._DelLocalGroupsCache(username, group) self.db.RemoveGroups(self._secid, userid=username, group=group) def _LocalGroups(self, username): if username in self._localRoles: return list(self._localRoles[username]) g = [r[1] for r in self.db.GetGroups(self._secid, userid=username)] self._localRoles[username] = tuple(g) return g def _AddLocalGroupsCache(self, username, group): if username in self._localRoles: if group in self._localRoles[username]: return l = list(self._localRoles[username]) l.append(group) self._localRoles[username] = tuple(l) return self._localRoles[username] = (group,) def _DelLocalGroupsCache(self, username, group=None): if not username in self._localRoles: return if username in self._localRoles and not group: del self._localRoles[username] return if not group in self._localRoles[username]: return l = list(self._localRoles[username]) l.remove(group) self._localRoles[username] = tuple(l)
class WebsitePublisher(AlternateAppPath, ApplicationBase): """ the main cms application class """ implements(IWebsite)
class CMSLocalGroups(object): """ """ _owner = u"group:owner" _secid = None implements(ILocalGroups) def Init(self): self._localRoles = {} self.ListenEvent("create", "AddOwner") self.ListenEvent("delete", "RemoveGroups") self._secid = self._secid or self.id or self.idhash # set view permission based on pool_groups. if pool_groups is empty everyone is allowed. permission = "view" groups = self.meta.get("pool_groups") if groups: acl = [(Allow, "group:editor", permission), (Allow, "group:author", permission), (Allow, "group:admin", permission)] for g in groups: if g in (u"authenticated", u"sys:authenticated"): acl.append((Allow, Authenticated, permission)) else: acl.append((Allow, g, permission)) acl.append((Deny, Everyone, permission)) self.__acl__ = tuple(acl) @property def securityID(self): return self._secid def GetLocalGroups(self, username, user=None): """ Group assignments use the user name. returns a list of all local user groups, including parent settings """ if self.id <= 0: return self._LocalGroups(username) g = [] o = self while o: g += o._LocalGroups(username) o = o.parent return g def AllLocalGroups(self): """ returns a list of all local user group settings as list including [username, group, id]. This function does not include parent level settings. """ return self.db.GetGroups(self.securityID) def AddOwner(self, user, **kw): """ Add the current user as group:owner to local roles """ if not user or not str(user): return self.AddLocalGroup(str(user), self._owner) def AddLocalGroup(self, username, group): """ Add a local group assignment for username. """ groups = self._LocalGroups(username) if group in groups: return if username == None: return self._AddLocalGroupsCache(username, group) self.db.AddGroup(self.securityID, userid=username, group=group) def RemoveLocalGroups(self, username, group=None): """ Remove a local group assignment. If group is None all local groups will be removed. """ self._DelLocalGroupsCache(username, group) self.db.RemoveGroups(self.securityID, userid=username, group=group) def RemoveGroups(self, **kw): """ Remove all group assignments before deleting the object. """ self.db.RemoveGroups(self.securityID) self._localRoles = {} def _LocalGroups(self, username): if username in self._localRoles: return list(self._localRoles[username]) g = [r[1] for r in self.db.GetGroups(self.securityID, userid=username)] self._localRoles[username] = tuple(g) return g def _AddLocalGroupsCache(self, username, group): if username in self._localRoles: if group in self._localRoles[username]: return l = list(self._localRoles[username]) l.append(group) self._localRoles[username] = tuple(l) return self._localRoles[username] = (group, ) def _DelLocalGroupsCache(self, username, group=None): if not username in self._localRoles: return if username in self._localRoles and not group: del self._localRoles[username] return if not group in self._localRoles[username]: return l = list(self._localRoles[username]) l.remove(group) self._localRoles[username] = tuple(l)
class WebsitePublisher(ApplicationBase): """ the main cms application class """ implements(IWebsite)