[gen] Users have now a workflow allowing them to deactivated. An inactive user can't log in anymore. This is useful if the User is tied to other objects and cannot be removed without braking the data model, but does not correspond anymore to an active user that is allowed to log in.

This commit is contained in:
Gaetan Delannay 2014-09-11 16:41:08 +02:00
parent 4fc74b36e7
commit 400158a0a1
5 changed files with 32 additions and 20 deletions

View file

@ -546,23 +546,28 @@ class WritePermission(Permission): pass
# Standard workflows -----------------------------------------------------------
class WorkflowAnonymous:
'''One-state workflow allowing anyone to consult and Manager to edit.'''
mgr = 'Manager'
ma = 'Manager'
o = 'Owner'
active = State({r:(mgr, 'Anonymous', 'Authenticated'), w:(mgr,o),d:(mgr,o)},
initial=True)
everyone = (ma, 'Anonymous', 'Authenticated')
active = State({r:everyone, w:(ma, o), d:(ma, o)}, initial=True)
class WorkflowAuthenticated:
'''One-state workflow allowing authenticated users to consult and Manager
to edit.'''
mgr = 'Manager'
ma = 'Manager'
o = 'Owner'
active = State({r:(mgr, 'Authenticated'), w:(mgr,o), d:(mgr,o)},
initial=True)
authenticated = (ma, 'Authenticated')
active = State({r:authenticated, w:(ma, o), d:(ma, o)}, initial=True)
class WorkflowOwner:
'''One-state workflow allowing only manager and owner to consult and
edit.'''
mgr = 'Manager'
ma = 'Manager'
o = 'Owner'
active = State({r:(mgr, o), w:(mgr, o), d:mgr}, initial=True)
# States
active = State({r:(ma, o), w:(ma, o), d:ma}, initial=True)
inactive = State({r:(ma, o), w:ma, d:ma})
# Transitions
deactivate = Transition( (active, inactive), condition=ma)
reactivate = Transition( (inactive, active), condition=ma)
# ------------------------------------------------------------------------------

View file

@ -1072,7 +1072,7 @@ class ToolMixin(BaseMixin):
if not user: return
# Authentify the user if required.
if authentify:
if not user.checkPassword(password):
if (user.state == 'inactive') or (not user.checkPassword(password)):
# Disable the authentication cookie.
req.RESPONSE.expireCookie('_appy_', path='/')
return

View file

@ -9,7 +9,7 @@ from appy.px import Px
from appy.fields.workflow import UiTransition
import appy.gen as gen
from appy.gen.utils import *
from appy.gen.layout import Table, defaultPageLayouts
from appy.gen.layout import Table
from appy.gen.descriptors import WorkflowDescriptor, ClassDescriptor
from appy.shared import utils as sutils
from appy.shared.data import rtlLanguages
@ -1596,8 +1596,9 @@ class BaseMixin:
# Fallback to 'en'.
translation = getattr(tool, 'en').appy()
res = getattr(translation, label, '')
# If still no result, put the label instead of a translated message
if not res: res = label
# If still no result, put a nice name derived from the label instead of
# a translated message.
if not res: res = produceNiceMessage(label.rsplit('_', 1)[-1])
else:
# Perform replacements, according to p_format.
res = self.formatText(res, format)
@ -1609,14 +1610,9 @@ class BaseMixin:
def getPageLayout(self, layoutType):
'''Returns the layout corresponding to p_layoutType for p_self.'''
appyClass = self.wrapperClass.__bases__[-1]
if hasattr(appyClass, 'layouts'):
layout = appyClass.layouts[layoutType]
if isinstance(layout, basestring):
layout = Table(layout)
else:
layout = defaultPageLayouts[layoutType]
return layout
res = self.wrapperClass.getPageLayouts()[layoutType]
if isinstance(res, basestring): res = Table(res)
return res
def download(self, name=None):
'''Downloads the content of the file that is in the File field whose

View file

@ -1,5 +1,6 @@
# ------------------------------------------------------------------------------
from appy.gen import WorkflowOwner
from appy.gen.layout import summaryPageLayouts
from appy.gen.wrappers import AbstractWrapper
from appy.gen import utils as gutils
@ -7,6 +8,7 @@ from appy.gen import utils as gutils
class UserWrapper(AbstractWrapper):
workflow = WorkflowOwner
specialUsers = ('system', 'anon', 'admin')
layouts = summaryPageLayouts
def showLogin(self):
'''When must we show the login field?'''

View file

@ -6,6 +6,7 @@ import os, os.path, mimetypes
import appy.pod
from appy.gen import Field, Search, Ref, String, WorkflowAnonymous
from appy.gen.indexer import defaultIndexes
from appy.gen.layout import defaultPageLayouts
from appy.gen.utils import createObject
from appy.px import Px
from appy.shared.utils import getOsTempFolder, executeCommand, \
@ -681,6 +682,14 @@ class AbstractWrapper(object):
if not res: res = WorkflowAnonymous
return res
@classmethod
def getPageLayouts(klass):
'''Returns the page layouts for p_klass.'''
res = klass._getParentAttr('layouts')
# Return the default page layout if no layout was found.
if not res: res = defaultPageLayouts
return res
@classmethod
def getIndexes(klass, includeDefaults=True):
'''Returns a dict whose keys are the names of the indexes that are