Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Lukas Niegsch
erp5
Commits
3c925863
Commit
3c925863
authored
May 07, 2015
by
wenjie.zheng
Committed by
Sebastien Robin
Jul 16, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean The Codes.
parent
61299a46
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
388 additions
and
474 deletions
+388
-474
product/ERP5/ERP5Site.py
product/ERP5/ERP5Site.py
+1
-15
product/ERP5/InteractionWorkflow.py
product/ERP5/InteractionWorkflow.py
+7
-8
product/ERP5/Tool/ERP5WorkflowTool.py
product/ERP5/Tool/ERP5WorkflowTool.py
+40
-44
product/ERP5Type/Base.py
product/ERP5Type/Base.py
+57
-80
product/ERP5Type/ERP5Type.py
product/ERP5Type/ERP5Type.py
+16
-7
product/ERP5Type/Utils.py
product/ERP5Type/Utils.py
+10
-17
product/ERP5Type/dynamic/lazy_class.py
product/ERP5Type/dynamic/lazy_class.py
+0
-1
product/ERP5Type/id_as_reference.py
product/ERP5Type/id_as_reference.py
+5
-3
product/ERP5Type/patches/DCWorkflow.py
product/ERP5Type/patches/DCWorkflow.py
+133
-29
product/ERP5Type/patches/WorkflowTool.py
product/ERP5Type/patches/WorkflowTool.py
+17
-133
product/ERP5Workflow/Document/Interaction.py
product/ERP5Workflow/Document/Interaction.py
+12
-11
product/ERP5Workflow/Document/InteractionWorkflow.py
product/ERP5Workflow/Document/InteractionWorkflow.py
+17
-20
product/ERP5Workflow/Document/PermissionRoles.py
product/ERP5Workflow/Document/PermissionRoles.py
+5
-11
product/ERP5Workflow/Document/State.py
product/ERP5Workflow/Document/State.py
+3
-9
product/ERP5Workflow/Document/Transition.py
product/ERP5Workflow/Document/Transition.py
+14
-14
product/ERP5Workflow/Document/Variable.py
product/ERP5Workflow/Document/Variable.py
+5
-7
product/ERP5Workflow/Document/Workflow.py
product/ERP5Workflow/Document/Workflow.py
+31
-46
product/ERP5Workflow/Document/WorkflowScript.py
product/ERP5Workflow/Document/WorkflowScript.py
+5
-4
product/ERP5Workflow/Document/Worklist.py
product/ERP5Workflow/Document/Worklist.py
+10
-15
No files found.
product/ERP5/ERP5Site.py
View file @
3c925863
...
...
@@ -1631,7 +1631,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
tool_id
=
tool
.
id
if
tool_id
not
in
(
'portal_property_sheets'
,
'portal_components'
):
if
tool_id
in
(
'portal_categories'
,
):
tool
=
tool
.
activate
()
### return self
tool
=
tool
.
activate
()
tool
.
migrateToPortalTypeClass
(
tool_id
not
in
(
'portal_activities'
,
'portal_simulation'
,
'portal_templates'
,
'portal_trash'
))
...
...
@@ -1654,20 +1654,6 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
self
.
manage_delObjects
([
'portal_workflow'
])
self
.
manage_renameObject
(
new_tool
.
id
,
'portal_workflow'
)
security
.
declareProtected
(
Permissions
.
ManagePortal
,
'migrateWorkflowModuleToPortalWorkflow'
)
def
migrateWorkflowModuleToPortalWorkflow
(
self
):
""" manually called function to migrate dcworkflow to erp5workflow.
only for the specific case of workflow migration.
"""
tool
=
self
.
workflow_module
object_id_list
=
tool
.
objectIds
()
new_tool
=
self
.
portal_workflow
object_clipboard
=
tool
.
manage_copyObjects
(
object_id_list
)
new_tool
=
self
.
portal_workflow
new_tool
.
manage_pasteObjects
(
object_clipboard
)
Globals
.
InitializeClass
(
ERP5Site
)
def
getBootstrapDirectory
():
...
...
product/ERP5/InteractionWorkflow.py
View file @
3c925863
...
...
@@ -17,21 +17,20 @@
#
##############################################################################
import
transaction
from
Products.ERP5Type
import
Globals
import
App
from
types
import
StringTypes
import
transaction
from
AccessControl
import
getSecurityManager
,
ClassSecurityInfo
from
AccessControl.SecurityManagement
import
setSecurityManager
from
Acquisition
import
aq_base
from
Products.CMFActivity.ActiveObject
import
ActiveObject
from
Products.CMFCore.utils
import
getToolByName
from
Products.ERP5Type
import
Permissions
,
Globals
from
Products.ERP5Type.Workflow
import
addWorkflowFactory
from
Products.DCWorkflow.DCWorkflow
import
DCWorkflowDefinition
from
Products.DCWorkflow.Transitions
import
TRIGGER_WORKFLOW_METHOD
from
Products.DCWorkflow.Expression
import
StateChangeInfo
,
createExprContext
from
Products.ERP5Type.Workflow
import
addWorkflowFactory
from
Products.CMFActivity.ActiveObject
import
ActiveObject
from
Products.ERP5Type
import
Permissions
from
Products.DCWorkflow.Transitions
import
TRIGGER_WORKFLOW_METHOD
from
types
import
StringTypes
from
zLOG
import
LOG
,
WARNING
_MARKER
=
[]
...
...
product/ERP5/Tool/ERP5WorkflowTool.py
View file @
3c925863
...
...
@@ -26,8 +26,7 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from
webdav.client
import
Resource
from
App.config
import
getConfiguration
import
os
import
shutil
import
sys
...
...
@@ -38,49 +37,46 @@ import cPickle
import
urllib2
import
re
from
Acquisition
import
Implicit
,
Explicit
from
AccessControl
import
ClassSecurityInfo
from
AccessControl
import
ClassSecurityInfo
,
Unauthorized
from
AccessControl.SecurityInfo
import
ModuleSecurityInfo
from
Acquisition
import
aq_base
,
Implicit
,
Explicit
from
App.config
import
getConfiguration
from
base64
import
b64encode
,
b64decode
,
decodestring
from
cStringIO
import
StringIO
from
DateTime
import
DateTime
from
itertools
import
izip
from
MethodObject
import
Method
from
MySQLdb
import
ProgrammingError
,
OperationalError
from
Persistence
import
Persistent
from
Products.CMFActivity.ActiveResult
import
ActiveResult
from
Products.ERP5Type.Globals
import
InitializeClass
,
DTMLFile
,
PersistentMapping
from
Products.ERP5Type.DiffUtils
import
DiffFile
from
Products.ERP5Type.Tool.BaseTool
import
BaseTool
from
Products.ERP5Type.Base
import
Base
from
Products.ERP5Type.Cache
import
transactional_cached
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.CMFCore.utils
import
Message
as
_
from
Products.CMFCore.utils
import
getToolByName
,
_getAuthenticatedUser
from
Products.CMFCore.WorkflowTool
import
WorkflowTool
as
OriginalWorkflowTool
from
Products.CMFCore.WorkflowCore
import
ObjectMoved
,
ObjectDeleted
,
\
WorkflowException
from
Products.DCWorkflow.DCWorkflow
import
DCWorkflowDefinition
from
Products.DCWorkflow.Transitions
import
TRIGGER_WORKFLOW_METHOD
from
Products.ERP5
import
_dtmldir
from
Products.ERP5.Document.BusinessTemplate
import
BusinessTemplateMissingDependency
from
Products.ERP5.genbt5list
import
generateInformation
from
Products.CMFCore.WorkflowTool
import
WorkflowTool
as
OriginalWorkflowTool
from
Acquisition
import
aq_base
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.Base
import
Base
from
Products.ERP5Type.Cache
import
transactional_cached
,
CachingMethod
from
Products.ERP5Type.Core.Folder
import
Folder
from
Products.ERP5Type.DiffUtils
import
DiffFile
from
Products.ERP5Type.Globals
import
InitializeClass
,
DTMLFile
,
PersistentMapping
from
Products.ERP5Type.Message
import
translateString
from
Products.ERP5Type.Tool.BaseTool
import
BaseTool
from
Products.ZSQLCatalog.SQLCatalog
import
SimpleQuery
,
AutoQuery
,
ComplexQuery
,
NegatedQuery
from
sets
import
ImmutableSet
from
tempfile
import
mkstemp
,
mkdtemp
from
Products.ERP5
import
_dtmldir
from
cStringIO
import
StringIO
from
types
import
StringTypes
from
urllib
import
pathname2url
,
urlopen
,
splittype
,
urlretrieve
from
xml.dom.minidom
import
parse
from
xml.parsers.expat
import
ExpatError
from
base64
import
b64encode
,
b64decode
from
Products.ERP5Type.Message
import
translateString
from
webdav.client
import
Resource
from
zLOG
import
LOG
,
INFO
,
WARNING
from
base64
import
decodestring
from
zLOG
import
LOG
,
WARNING
from
types
import
StringTypes
from
AccessControl
import
Unauthorized
from
Products.CMFCore.WorkflowCore
import
ObjectMoved
,
ObjectDeleted
from
Products.CMFCore.WorkflowCore
import
WorkflowException
from
Products.DCWorkflow.DCWorkflow
import
DCWorkflowDefinition
from
Products.DCWorkflow.Transitions
import
TRIGGER_WORKFLOW_METHOD
from
Products.CMFCore.utils
import
Message
as
_
from
Products.CMFCore.utils
import
getToolByName
from
Products.ZSQLCatalog.SQLCatalog
import
SimpleQuery
,
AutoQuery
,
ComplexQuery
,
NegatedQuery
from
Products.CMFCore.utils
import
_getAuthenticatedUser
from
Products.ERP5Type.Cache
import
CachingMethod
from
sets
import
ImmutableSet
from
Persistence
import
Persistent
from
itertools
import
izip
from
MySQLdb
import
ProgrammingError
,
OperationalError
from
DateTime
import
DateTime
from
MethodObject
import
Method
from
Products.ERP5Type.Core.Folder
import
Folder
"""
Most of the codes in this file are copy-pasted from patches/WorkflowTool.py.
"""
...
...
@@ -248,7 +244,7 @@ class ERP5WorkflowTool(BaseTool, OriginalWorkflowTool):
return
workflow_list
def
dc_workflow_asERP5Object
(
self
,
container
,
dc_workflow
,
temp
):
#
##
create a temporary ERP5 Workflow
# create a temporary ERP5 Workflow
workflow_type_id
=
dc_workflow
.
__class__
.
__name__
if
workflow_type_id
==
'DCWorkflowDefinition'
:
LOG
(
"2.a Workflow '%s' is a DCWorkflow'"
%
dc_workflow
.
id
,
WARNING
,
' in ERP5WorkflowTool.py'
)
...
...
@@ -265,7 +261,7 @@ class ERP5WorkflowTool(BaseTool, OriginalWorkflowTool):
workflow
.
edit
(
title
=
dc_workflow
.
title
)
workflow
.
edit
(
description
=
dc_workflow
.
description
)
#
##
create transitions
# create transitions
if
workflow_type_id
==
'DCWorkflowDefinition'
:
for
tid
in
dc_workflow
.
transitions
:
tdef
=
dc_workflow
.
transitions
.
get
(
tid
)
...
...
@@ -282,7 +278,7 @@ class ERP5WorkflowTool(BaseTool, OriginalWorkflowTool):
transition
.
setBeforeScriptId
(
tdef
.
script_name
)
transition
.
setDestination
(
tdef
.
new_state_id
)
transition
.
guard
=
tdef
.
guard
#
##
create states (portal_type = State)
# create states (portal_type = State)
for
sid
in
dc_workflow
.
states
:
sdef
=
dc_workflow
.
states
.
get
(
sid
)
LOG
(
"2.2 Convert state '%s' of workflow '%s'"
%
(
sdef
.
id
,
workflow
.
getTitle
()),
WARNING
,
' in ERP5WorkflowTool.py'
)
...
...
@@ -291,7 +287,7 @@ class ERP5WorkflowTool(BaseTool, OriginalWorkflowTool):
state
.
setReference
(
sdef
.
id
)
state
.
setStatePermissionRoles
(
sdef
.
permission_roles
)
state
.
setDestinationList
(
sdef
.
transitions
)
#
##
create worklists (portal_type = Worklist)
# create worklists (portal_type = Worklist)
for
qid
in
dc_workflow
.
worklists
:
qdef
=
dc_workflow
.
worklists
.
get
(
qid
)
LOG
(
"2.3 Convert worklist '%s' of workflow '%s'"
%
(
qdef
.
id
,
workflow
.
getTitle
()),
WARNING
,
' in ERP5WorkflowTool.py'
)
...
...
@@ -325,12 +321,12 @@ class ERP5WorkflowTool(BaseTool, OriginalWorkflowTool):
interaction
.
setPortalTypeFilter
(
tdef
.
portal_type_filter
)
interaction
.
setPortalTypeGroupFilter
(
tdef
.
portal_type_group_filter
)
interaction
.
setTemporaryDocumentDisallowed
(
tdef
.
temporary_document_disallowed
)
#interaction.setTransition
_form_id ### this is not defined in DC interaction
#interaction.setTransition
FormId() # this is not defined in DC interaction?
interaction
.
setTriggerMethodId
(
tdef
.
method_id
)
interaction
.
setTriggerOncePerTransaction
(
tdef
.
once_per_transaction
)
interaction
.
setTriggerType
(
tdef
.
trigger_type
)
#
##
create scripts (portal_type = Workflow Script)
# create scripts (portal_type = Workflow Script)
for
script_id
in
dc_workflow
.
scripts
:
script
=
dc_workflow
.
scripts
.
get
(
script_id
)
workflow_script
=
workflow
.
newContent
(
portal_type
=
'Workflow Script'
,
temp_object
=
temp
)
...
...
@@ -338,10 +334,10 @@ class ERP5WorkflowTool(BaseTool, OriginalWorkflowTool):
workflow_script
.
edit
(
title
=
script
.
title
)
workflow_script
.
setId
(
script
.
id
)
workflow_script
.
setParameterSignature
(
script
.
_params
)
#workflow_script.setCallableType(script.callable_type)#
## not defined in DC script
#workflow_script.setCallableType(script.callable_type)#
not defined in DC script?
workflow_script
.
setBody
(
script
.
_body
)
workflow_script
.
setProxyRole
(
script
.
_proxy_roles
)
#
##
create variables (portal_type = Variable)
# create variables (portal_type = Variable)
for
vid
in
dc_workflow
.
variables
:
vdef
=
dc_workflow
.
variables
.
get
(
vid
)
variable
=
workflow
.
newContent
(
portal_type
=
'Variable'
,
temp_object
=
temp
)
...
...
product/ERP5Type/Base.py
View file @
3c925863
This diff is collapsed.
Click to expand it.
product/ERP5Type/ERP5Type.py
View file @
3c925863
...
...
@@ -20,17 +20,24 @@
# FOR A PARTICULAR PURPOSE
#
##############################################################################
import
Products
import
zope.interface
from
Products.ERP5Type.Globals
import
InitializeClass
from
AccessControl
import
ClassSecurityInfo
,
getSecurityManager
from
Acquisition
import
aq_base
,
aq_inner
,
aq_parent
import
Products
from
Products.CMFCore.TypesTool
import
FactoryTypeInformation
from
Products.CMFCore.exceptions
import
zExceptions_Unauthorized
,
\
AccessControl_Unauthorized
from
Products.CMFCore.Expression
import
Expression
from
Products.CMFCore.
exceptions
import
AccessControl_Unauthorized
from
Products.CMFCore.
TypesTool
import
FactoryTypeInformation
from
Products.CMFCore.utils
import
getToolByName
from
Products.ERP5Type
import
interfaces
,
Constraint
,
Permissions
,
PropertySheet
from
Products.ERP5Type.Base
import
getClassPropertyList
from
Products.ERP5Type.Cache
import
CachingMethod
from
Products.ERP5Type.dynamic.accessor_holder
import
getPropertySheetValueList
,
\
getAccessorHolderList
from
Products.ERP5Type.Globals
import
InitializeClass
from
Products.ERP5Type.TransactionalVariable
import
getTransactionalVariable
from
Products.ERP5Type.UnrestrictedMethod
import
UnrestrictedMethod
from
Products.ERP5Type.Utils
import
deprecated
,
createExpressionContext
from
Products.ERP5Type.XMLObject
import
XMLObject
...
...
@@ -45,9 +52,11 @@ from TranslationProviderBase import TranslationProviderBase
from
Products.ERP5Type.Accessor.Translation
import
TRANSLATION_DOMAIN_CONTENT_TRANSLATION
from
sys
import
exc_info
from
zLOG
import
LOG
,
ERROR
from
Products.CMFCore.exceptions
import
zExceptions_Unauthorized
from
TranslationProviderBase
import
TranslationProviderBase
from
types
import
NoneType
from
zLOG
import
LOG
,
ERROR
ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT
=
'ERP5Type_asSecurityGroupId'
def
getCurrentUserIdOrAnonymousToken
():
"""Return connected user_id or simple token for
...
...
@@ -133,7 +142,7 @@ class LocalRoleAssignorMixIn(object):
## Make sure that the object is reindexed if modified
# XXX: Document modification detection assumes local roles are always
# part of ob and not separate persistent objects.
if
reindex
:
#
and ob._p_changed:
if
reindex
and
ob
.
_p_changed
:
ob
.
reindexObjectSecurity
(
activate_kw
=
dict
(
activate_kw
))
security
.
declarePrivate
(
'getFilteredRoleListFor'
)
...
...
product/ERP5Type/Utils.py
View file @
3c925863
...
...
@@ -28,33 +28,26 @@
##############################################################################
# Required modules - some modules are imported later to prevent circular deadlocks
import
inspect
import
os
import
persistent
import
re
import
string
import
sys
import
time
import
warnings
import
sys
import
inspect
import
persistent
from
hashlib
import
md5
as
md5_new
,
sha1
as
sha_new
from
Products.ERP5Type.Globals
import
package_home
from
Products.ERP5Type.Globals
import
DevelopmentMode
from
Acquisition
import
aq_base
from
Acquisition
import
aq_inner
from
Acquisition
import
aq_parent
from
Acquisition
import
aq_self
from
AccessControl
import
ModuleSecurityInfo
from
AccessControl
import
ModuleSecurityInfo
,
getSecurityManager
from
AccessControl.SecurityInfo
import
allow_class
from
AccessControl
import
getSecurityManager
from
AccessControl.SecurityManagement
import
newSecurityManager
from
Acquisition
import
aq_base
,
aq_inner
,
aq_parent
,
aq_self
from
hashlib
import
md5
as
md5_new
,
sha1
as
sha_new
from
Products.CMFCore
import
utils
from
Products.CMFCore.Expression
import
Expression
from
Products.CMFCore.DirectoryView
import
registerDirectory
from
Products.CMFCore.Expression
import
Expression
from
Products.CMFCore.utils
import
getToolByName
from
Products.
PageTemplates.Expressions
import
getEngin
e
from
Products.PageTemplates.Expressions
import
SecureModuleImporter
from
Products.
ERP5Type.Globals
import
package_home
,
DevelopmentMod
e
from
Products.PageTemplates.Expressions
import
getEngine
,
SecureModuleImporter
from
Products.ZCatalog.Lazy
import
LazyMap
try
:
...
...
product/ERP5Type/dynamic/lazy_class.py
View file @
3c925863
...
...
@@ -278,7 +278,6 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder):
category_tool
)
portal_workflow
=
getattr
(
site
,
'portal_workflow'
,
None
)
if
portal_workflow
is
None
:
if
not
getattr
(
site
,
'_v_bootstrapping'
,
False
):
LOG
(
"ERP5Type.Dynamic"
,
WARNING
,
...
...
product/ERP5Type/id_as_reference.py
View file @
3c925863
# -*- coding: utf-8 -*-
##############################################################################
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
# Julien Muchembled <jm@nexedi.com>
# Julien Muchembled <jm@nexedi.com>
# 2015 wenjie Zheng <wenjie.zheng@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
...
...
@@ -27,11 +28,12 @@
##############################################################################
import
transaction
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Acquisition
import
aq_base
from
Products.CMFActivity.Errors
import
ActivityPendingError
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
zLOG
import
LOG
,
WARNING
from
Acquisition
import
aq_base
def
IdAsReferenceMixin
(
extra_string
,
string_type
=
"suffix"
):
...
...
product/ERP5Type/patches/DCWorkflow.py
View file @
3c925863
...
...
@@ -2,7 +2,7 @@
##############################################################################
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
# Copyright (c) 2002,2005 Nexedi SARL and Contributors. All Rights Reserved.
# Copyright (c) 2002,2005
,2015
Nexedi SARL and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
...
...
@@ -13,31 +13,31 @@
#
##############################################################################
# Optimized rendering of global actions (cache)
from
Products.ERP5Type.Globals
import
DTMLFile
from
Products.ERP5Type
import
_dtmldir
from
Products.DCWorkflow.DCWorkflow
import
DCWorkflowDefinition
,
StateChangeInfo
,
createExprContext
from
Products.DCWorkflow.DCWorkflow
import
ObjectDeleted
,
ObjectMoved
,
aq_parent
,
aq_inner
from
Products.DCWorkflow
import
DCWorkflow
from
Products.DCWorkflow.Transitions
import
TRIGGER_WORKFLOW_METHOD
,
TransitionDefinition
from
Products.DCWorkflow.Transitions
import
TRIGGER_USER_ACTION
from
AccessControl
import
getSecurityManager
,
ModuleSecurityInfo
,
Unauthorized
from
Products.CMFCore.utils
import
getToolByName
from
Products.CMFCore.WorkflowCore
import
WorkflowException
from
Products.CMFCore.utils
import
_getAuthenticatedUser
from
DocumentTemplate.DT_Util
import
TemplateDict
from
DateTime
import
DateTime
from
Products.ERP5Type.Cache
import
CachingMethod
from
Products.ERP5Type.Utils
import
convertToMixedCase
import
sys
from
Acquisition
import
aq_base
from
AccessControl
import
getSecurityManager
,
ModuleSecurityInfo
,
Unauthorized
from
copy
import
deepcopy
# Patch WorkflowUIMixin to add description on workflows
from
Products.DCWorkflow.WorkflowUIMixin
import
WorkflowUIMixin
as
WorkflowUIMixin_class
from
DateTime
import
DateTime
from
DocumentTemplate.DT_Util
import
TemplateDict
from
Products.CMFCore.utils
import
getToolByName
,
_getAuthenticatedUser
from
Products.CMFCore.WorkflowCore
import
WorkflowException
from
Products.DCWorkflow
import
DCWorkflow
from
Products.DCWorkflow.DCWorkflow
import
DCWorkflowDefinition
,
\
StateChangeInfo
,
createExprContext
,
\
ObjectDeleted
,
ObjectMoved
,
aq_parent
,
aq_inner
from
Products.DCWorkflow.Guard
import
Guard
,
_checkPermission
from
Products.DCWorkflow.States
import
StateDefinition
from
Products.DCWorkflow.Transitions
import
TRIGGER_WORKFLOW_METHOD
,
\
TransitionDefinition
,
TRIGGER_USER_ACTION
from
Products.DCWorkflow.Variables
import
VariableDefinition
from
Products.DCWorkflow.Worklists
import
WorklistDefinition
from
Products.DCWorkflow.WorkflowUIMixin
import
WorkflowUIMixin
as
WorkflowUIMixin_class
from
Products.ERP5Type
import
_dtmldir
# Optimized rendering of global actions (cache)
from
Products.ERP5Type.Cache
import
CachingMethod
from
Products.ERP5Type.Globals
import
DTMLFile
# Patch WorkflowUIMixin to add description on workflows
from
Products.ERP5Type.Utils
import
convertToMixedCase
from
zLOG
import
LOG
,
WARNING
ACTIVITY_GROUPING_COUNT
=
100
...
...
@@ -62,7 +62,6 @@ def WorkflowUIMixin_setProperties( self, title
WorkflowUIMixin_class
.
setProperties
=
WorkflowUIMixin_setProperties
WorkflowUIMixin_class
.
manage_properties
=
DTMLFile
(
'workflow_properties'
,
_dtmldir
)
def
Guard_checkWithoutRoles
(
self
,
sm
,
wf_def
,
ob
,
**
kw
):
"""Checks conditions in this guard.
This function is the same as Guard.check, but roles are not taken
...
...
@@ -109,7 +108,6 @@ def Guard_checkWithoutRoles(self, sm, wf_def, ob, **kw):
return
0
return
1
def
DCWorkflowDefinition_listGlobalActions
(
self
,
info
):
'''
Allows this workflow to
...
...
@@ -208,7 +206,6 @@ def DCWorkflowDefinition_listGlobalActions(self, info):
user
=
str
(
_getAuthenticatedUser
(
self
))
return
_listGlobalActions
(
user
=
user
,
id
=
self
.
id
,
portal_path
=
self
.
_getPortalRoot
().
getPhysicalPath
())
DCWorkflowDefinition
.
listGlobalActions
=
DCWorkflowDefinition_listGlobalActions
# Patches over original listObjectActions:
...
...
@@ -351,7 +348,6 @@ DCWorkflow.ValidationFailed = ValidationFailed
ModuleSecurityInfo
(
'Products.DCWorkflow.DCWorkflow'
).
declarePublic
(
'ValidationFailed'
)
# Patch excecuteTransition from DCWorkflowDefinition, to put ValidationFailed
# error messages in workflow history.
def
DCWorkflowDefinition_executeTransition
(
self
,
ob
,
tdef
=
None
,
kwargs
=
None
):
...
...
@@ -581,7 +577,6 @@ def DCWorkflowDefinition_wrapWorkflowMethod(self, ob, method_id, func, args, kw)
DCWorkflowDefinition
.
wrapWorkflowMethod
=
DCWorkflowDefinition_wrapWorkflowMethod
# Patch updateRoleMappingsFor so that if 2 workflows define security, then we
# should do an AND operation between each permission
def
updateRoleMappingsFor
(
self
,
ob
):
...
...
@@ -721,10 +716,120 @@ def DCWorkflowDefinition_getFutureStateSet(self, state, ignore=(),
DCWorkflowDefinition
.
getFutureStateSet
=
DCWorkflowDefinition_getFutureStateSet
def
DCWorkflowDefinition_getStateVariable
(
self
):
### return state variable name, for ERP5 compatibility
return
self
.
state_var
DCWorkflowDefinition
.
getStateVariable
=
DCWorkflowDefinition_getStateVariable
def
DCWorkflowDefinition_notifyWorkflowMethod
(
self
,
ob
,
transition_list
,
args
=
None
,
kw
=
None
):
'''
Allows the system to request a workflow action. This method
must perform its own security checks.
'''
if
type
(
transition_list
)
in
StringTypes
:
method_id
=
transition_list
elif
len
(
transition_list
)
==
1
:
method_id
=
transition_list
[
0
]
else
:
raise
ValueError
(
'WorkflowMethod should be attached to exactly 1 transition per DCWorkflow instance.'
)
sdef
=
self
.
_getWorkflowStateOf
(
ob
)
if
sdef
is
None
:
raise
WorkflowException
,
'Object is in an undefined state'
if
method_id
not
in
sdef
.
transitions
:
raise
Unauthorized
(
method_id
)
tdef
=
self
.
transitions
.
get
(
method_id
,
None
)
if
tdef
is
None
or
tdef
.
trigger_type
!=
TRIGGER_WORKFLOW_METHOD
:
raise
WorkflowException
,
(
'Transition %s is not triggered by a workflow method'
%
method_id
)
if
not
self
.
_checkTransitionGuard
(
tdef
,
ob
):
raise
Unauthorized
(
method_id
)
self
.
_changeStateOf
(
ob
,
tdef
,
kw
)
if
getattr
(
ob
,
'reindexObject'
,
None
)
is
not
None
:
if
kw
is
not
None
:
activate_kw
=
kw
.
get
(
'activate_kw'
,
{})
else
:
activate_kw
=
{}
ob
.
reindexObject
(
activate_kw
=
activate_kw
)
def
DCWorkflowDefinition_notifyBefore
(
self
,
ob
,
transition_list
,
args
=
None
,
kw
=
None
):
'''
Notifies this workflow of an action before it happens,
allowing veto by exception. Unless an exception is thrown, either
a notifySuccess() or notifyException() can be expected later on.
The action usually corresponds to a method name.
'''
pass
def
DCWorkflowDefinition_notifySuccess
(
self
,
ob
,
transition_list
,
result
,
args
=
None
,
kw
=
None
):
'''
Notifies this workflow that an action has taken place.
'''
pass
def
method_getReference
(
self
):
return
self
.
id
def
DCWorkflowDefinition_getVariableValueList
(
self
):
if
self
.
variables
is
not
None
:
return
self
.
variables
return
{}
def
DCWorkflowDefinition_getVariableIdList
(
self
):
if
self
.
variables
is
not
None
:
return
self
.
variables
.
objectIds
()
return
[]
def
DCWorkflowDefinition_getStateValueList
(
self
):
if
self
.
states
is
not
None
:
return
self
.
states
return
{}
def
DCWorkflowDefinition_getStateIdList
(
self
):
if
self
.
states
is
not
None
:
return
self
.
states
.
objectIds
()
return
[]
def
DCWorkflowDefinition_getTransitionValueList
(
self
):
if
self
.
transitions
is
not
None
:
return
self
.
transitions
else
:
return
{}
def
DCWorkflowDefinition_getTransitionIdList
(
self
):
if
self
.
transitions
is
not
None
:
return
self
.
transitions
.
objectIds
()
return
[]
def
DCWorkflowDefinition_getWorklistValueList
(
self
):
if
self
.
worklists
is
not
None
:
return
self
.
worklists
return
{}
def
DCWorkflowDefinition_getWorklistIdList
(
self
):
if
self
.
worklists
is
not
None
:
return
self
.
worklists
.
objectIds
()
return
[]
def
StateDefinition_getDestinationIdList
(
self
):
return
self
.
transitions
DCWorkflowDefinition
.
getReference
=
method_getReference
TransitionDefinition
.
getReference
=
method_getReference
StateDefinition
.
getReference
=
method_getReference
StateDefinition
.
getDestinationIdList
=
StateDefinition_getDestinationIdList
VariableDefinition
.
getReference
=
method_getReference
WorklistDefinition
.
getReference
=
method_getReference
DCWorkflowDefinition
.
notifyWorkflowMethod
=
DCWorkflowDefinition_notifyWorkflowMethod
DCWorkflowDefinition
.
notifyBefore
=
DCWorkflowDefinition_notifyBefore
DCWorkflowDefinition
.
notifySuccess
=
DCWorkflowDefinition_notifySuccess
DCWorkflowDefinition
.
getVariableValueList
=
DCWorkflowDefinition_getVariableValueList
DCWorkflowDefinition
.
getStateValueList
=
DCWorkflowDefinition_getStateValueList
DCWorkflowDefinition
.
getTransitionValueList
=
DCWorkflowDefinition_getTransitionValueList
DCWorkflowDefinition
.
getWorklistValueList
=
DCWorkflowDefinition_getWorklistValueList
DCWorkflowDefinition
.
getVariableIdList
=
DCWorkflowDefinition_getVariableIdList
DCWorkflowDefinition
.
getStateIdList
=
DCWorkflowDefinition_getStateIdList
DCWorkflowDefinition
.
getTransitionIdList
=
DCWorkflowDefinition_getTransitionIdList
DCWorkflowDefinition
.
getWorklistIdList
=
DCWorkflowDefinition_getWorklistIdList
# This patch allows to use workflowmethod as an after_script
# However, the right way of doing would be to have a combined state of TRIGGER_USER_ACTION and TRIGGER_WORKFLOW_METHOD
# as well as workflow inheritance. This way, different user actions and dialogs can be specified easliy
...
...
@@ -742,4 +847,3 @@ def getAvailableScriptIds(self):
self
.
getWorkflow
().
transitions
[
k
].
trigger_type
==
TRIGGER_WORKFLOW_METHOD
]
TransitionDefinition
.
getAvailableScriptIds
=
getAvailableScriptIds
product/ERP5Type/patches/WorkflowTool.py
View file @
3c925863
...
...
@@ -14,151 +14,35 @@
##############################################################################
import
sys
from
zLOG
import
LOG
,
WARNING
from
types
import
StringTypes
# Make sure Interaction Workflows are called even if method not wrapped
from
AccessControl
import
Unauthorized
from
Acquisition
import
aq_base
from
DateTime
import
DateTime
from
itertools
import
izip
from
MySQLdb
import
ProgrammingError
,
OperationalError
from
Products.ERP5Type.Cache
import
CachingMethod
from
Persistence
import
Persistent
from
Products.ERP5Type.Globals
import
PersistentMapping
from
Products.CMFCore.utils
import
getToolByName
,
_getAuthenticatedUser
from
Products.CMFCore.utils
import
Message
as
_
from
Products.CMFCore.WorkflowCore
import
ObjectMoved
,
ObjectDeleted
,
\
WorkflowException
from
Products.CMFCore.WorkflowTool
import
WorkflowTool
from
Products.CMFCore.WorkflowCore
import
ObjectMoved
,
ObjectDeleted
from
Products.CMFCore.WorkflowCore
import
WorkflowException
from
Products.DCWorkflow.Transitions
import
TRIGGER_WORKFLOW_METHOD
from
Products.DCWorkflow.DCWorkflow
import
DCWorkflowDefinition
from
Products.DCWorkflow.Transitions
import
T
ransitionDefinition
from
Products.DCWorkflow.States
import
State
Definition
from
Products.DCWorkflow.Transitions
import
T
RIGGER_WORKFLOW_METHOD
,
\
Transition
Definition
from
Products.DCWorkflow.Variables
import
VariableDefinition
from
Products.DCWorkflow.Worklists
import
WorklistDefinition
from
Products.CMFCore.utils
import
Message
as
_
from
Products.CMFCore.utils
import
getToolByName
from
Products.ZSQLCatalog.SQLCatalog
import
SimpleQuery
,
AutoQuery
,
ComplexQuery
,
NegatedQuery
from
Products.CMFCore.utils
import
_getAuthenticatedUser
from
Products.ERP5Type.Cache
import
CachingMethod
from
Products.ZSQLCatalog.SQLCatalog
import
SimpleQuery
,
AutoQuery
,
\
ComplexQuery
,
NegatedQuery
from
sets
import
ImmutableSet
from
Acquisition
import
aq_base
from
Persistence
import
Persistent
from
Products.ERP5Type.Globals
import
PersistentMapping
from
itertools
import
izip
from
MySQLdb
import
ProgrammingError
,
OperationalError
from
DateTime
import
DateTime
from
types
import
StringTypes
from
zLOG
import
LOG
,
WARNING
_marker
=
[]
# Create a new marker object.
def
DCWorkflowDefinition_notifyWorkflowMethod
(
self
,
ob
,
transition_list
,
args
=
None
,
kw
=
None
):
'''
Allows the system to request a workflow action. This method
must perform its own security checks.
'''
if
type
(
transition_list
)
in
StringTypes
:
method_id
=
transition_list
elif
len
(
transition_list
)
==
1
:
method_id
=
transition_list
[
0
]
else
:
raise
ValueError
(
'WorkflowMethod should be attached to exactly 1 transition per DCWorkflow instance.'
)
sdef
=
self
.
_getWorkflowStateOf
(
ob
)
if
sdef
is
None
:
raise
WorkflowException
,
'Object is in an undefined state'
if
method_id
not
in
sdef
.
transitions
:
raise
Unauthorized
(
method_id
)
tdef
=
self
.
transitions
.
get
(
method_id
,
None
)
if
tdef
is
None
or
tdef
.
trigger_type
!=
TRIGGER_WORKFLOW_METHOD
:
raise
WorkflowException
,
(
'Transition %s is not triggered by a workflow method'
%
method_id
)
if
not
self
.
_checkTransitionGuard
(
tdef
,
ob
):
raise
Unauthorized
(
method_id
)
self
.
_changeStateOf
(
ob
,
tdef
,
kw
)
if
getattr
(
ob
,
'reindexObject'
,
None
)
is
not
None
:
if
kw
is
not
None
:
activate_kw
=
kw
.
get
(
'activate_kw'
,
{})
else
:
activate_kw
=
{}
ob
.
reindexObject
(
activate_kw
=
activate_kw
)
def
DCWorkflowDefinition_notifyBefore
(
self
,
ob
,
transition_list
,
args
=
None
,
kw
=
None
):
'''
Notifies this workflow of an action before it happens,
allowing veto by exception. Unless an exception is thrown, either
a notifySuccess() or notifyException() can be expected later on.
The action usually corresponds to a method name.
'''
pass
def
DCWorkflowDefinition_notifySuccess
(
self
,
ob
,
transition_list
,
result
,
args
=
None
,
kw
=
None
):
'''
Notifies this workflow that an action has taken place.
'''
pass
DCWorkflowDefinition
.
notifyWorkflowMethod
=
DCWorkflowDefinition_notifyWorkflowMethod
DCWorkflowDefinition
.
notifyBefore
=
DCWorkflowDefinition_notifyBefore
DCWorkflowDefinition
.
notifySuccess
=
DCWorkflowDefinition_notifySuccess
def
method_getReference
(
self
):
return
self
.
id
def
DCWorkflowDefinition_getVariableValueList
(
self
):
if
self
.
variables
is
not
None
:
return
self
.
variables
return
{}
def
DCWorkflowDefinition_getVariableIdList
(
self
):
if
self
.
variables
is
not
None
:
return
self
.
variables
.
objectIds
()
return
[]
def
DCWorkflowDefinition_getStateValueList
(
self
):
if
self
.
states
is
not
None
:
return
self
.
states
return
{}
def
DCWorkflowDefinition_getStateIdList
(
self
):
if
self
.
states
is
not
None
:
return
self
.
states
.
objectIds
()
return
[]
def
DCWorkflowDefinition_getTransitionValueList
(
self
):
if
self
.
transitions
is
not
None
:
return
self
.
transitions
else
:
return
{}
def
DCWorkflowDefinition_getTransitionIdList
(
self
):
if
self
.
transitions
is
not
None
:
return
self
.
transitions
.
objectIds
()
return
[]
def
DCWorkflowDefinition_getWorklistValueList
(
self
):
if
self
.
worklists
is
not
None
:
return
self
.
worklists
return
{}
def
DCWorkflowDefinition_getWorklistIdList
(
self
):
if
self
.
worklists
is
not
None
:
return
self
.
worklists
.
objectIds
()
return
[]
def
StateDefinition_getDestinationIdList
(
self
):
return
self
.
transitions
DCWorkflowDefinition
.
getReference
=
method_getReference
TransitionDefinition
.
getReference
=
method_getReference
StateDefinition
.
getReference
=
method_getReference
StateDefinition
.
getDestinationIdList
=
StateDefinition_getDestinationIdList
VariableDefinition
.
getReference
=
method_getReference
WorklistDefinition
.
getReference
=
method_getReference
DCWorkflowDefinition
.
getVariableValueList
=
DCWorkflowDefinition_getVariableValueList
DCWorkflowDefinition
.
getStateValueList
=
DCWorkflowDefinition_getStateValueList
DCWorkflowDefinition
.
getTransitionValueList
=
DCWorkflowDefinition_getTransitionValueList
DCWorkflowDefinition
.
getWorklistValueList
=
DCWorkflowDefinition_getWorklistValueList
DCWorkflowDefinition
.
getVariableIdList
=
DCWorkflowDefinition_getVariableIdList
DCWorkflowDefinition
.
getStateIdList
=
DCWorkflowDefinition_getStateIdList
DCWorkflowDefinition
.
getTransitionIdList
=
DCWorkflowDefinition_getTransitionIdList
DCWorkflowDefinition
.
getWorklistIdList
=
DCWorkflowDefinition_getWorklistIdList
WORKLIST_METADATA_KEY
=
'metadata'
SECURITY_PARAMETER_ID
=
'local_roles'
COUNT_COLUMN_TITLE
=
'count'
...
...
product/ERP5Workflow/Document/Interaction.py
View file @
3c925863
##############################################################################
#
# Copyright (c) 20
06
Nexedi SARL and Contributors. All Rights Reserved.
#
2015
Wenjie Zheng <wenjie.zheng@tiolive.com>
# Copyright (c) 20
15
Nexedi SARL and Contributors. All Rights Reserved.
#
Wenjie Zheng <wenjie.zheng@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
...
...
@@ -25,20 +25,21 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import
transaction
from
AccessControl
import
getSecurityManager
,
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5Type.Globals
import
PersistentMapping
from
Acquisition
import
aq_inner
,
aq_parent
from
Products.ERP5Type
import
Globals
from
Products.ERP5Type.Permissions
import
ManagePortal
from
Products.DCWorkflow.Guard
import
Guard
from
Products.DCWorkflow.Expression
import
Expression
from
Products.ERP5Workflow.Document.Transition
import
TRIGGER_WORKFLOW_METHOD
,
TRIGGER_USER_ACTION
from
zLOG
import
LOG
,
INFO
,
ERROR
,
WARNING
from
Products.DCWorkflow.Expression
import
StateChangeInfo
from
Products.DCWorkflow.Expression
import
Expression
,
StateChangeInfo
from
Products.ERP5Type
import
Globals
,
Permissions
,
PropertySheet
from
Products.ERP5Type.Globals
import
PersistentMapping
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
from
Products.ERP5Type.Permissions
import
ManagePortal
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5Workflow.Document.Transition
import
TRIGGER_WORKFLOW_METHOD
,
\
TRIGGER_USER_ACTION
from
zLOG
import
LOG
,
INFO
,
ERROR
,
WARNING
class
Interaction
(
IdAsReferenceMixin
(
'interaction_'
,
"prefix"
),
XMLObject
):
...
...
product/ERP5Workflow/Document/InteractionWorkflow.py
View file @
3c925863
##############################################################################
#
# Copyright (c) 20
06
Nexedi SARL and Contributors. All Rights Reserved.
#
2015
Wenjie Zheng <wenjie.zheng@tiolive.com>
# Copyright (c) 20
15
Nexedi SARL and Contributors. All Rights Reserved.
#
Wenjie Zheng <wenjie.zheng@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
...
...
@@ -26,26 +26,26 @@
#
##############################################################################
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5Workflow.Document.Workflow
import
Workflow
import
transaction
from
Products.ERP5Type
import
Globals
import
App
from
types
import
StringTypes
import
transaction
from
AccessControl
import
getSecurityManager
,
ClassSecurityInfo
from
AccessControl.SecurityManagement
import
setSecurityManager
from
Acquisition
import
aq_base
from
Products.CMFActivity.ActiveObject
import
ActiveObject
from
Products.CMFCore.utils
import
getToolByName
from
Products.DCWorkflow.DCWorkflow
import
DCWorkflowDefinition
from
Products.ERP5Workflow.Document.Transition
import
TRIGGER_WORKFLOW_METHOD
from
Products.DCWorkflow.Expression
import
StateChangeInfo
from
Products.ERP5Type.Workflow
import
addWorkflowFactory
from
Products.CMFActivity.ActiveObject
import
ActiveObject
from
Products.ERP5Type.patches.Expression
import
Expression_createExprContext
from
Products.ERP5Type
import
Permissions
,
PropertySheet
,
Globals
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
from
Products.ERP5Type.Globals
import
PersistentMapping
from
Products.ERP5Type.patches.Expression
import
Expression_createExprContext
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5Type.Workflow
import
addWorkflowFactory
from
Products.ERP5Workflow.Document.Transition
import
TRIGGER_WORKFLOW_METHOD
from
Products.ERP5Workflow.Document.Workflow
import
Workflow
from
types
import
StringTypes
from
zLOG
import
LOG
,
ERROR
,
WARNING
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
_MARKER
=
[]
...
...
@@ -60,7 +60,6 @@ class InteractionWorkflow(IdAsReferenceMixin("interactionworkflow_", "prefix"),
isPortalContent
=
1
isRADContent
=
1
default_reference
=
''
### zwj: for security issue
managed_permission_list
=
()
managed_role
=
()
...
...
@@ -93,7 +92,7 @@ class InteractionWorkflow(IdAsReferenceMixin("interactionworkflow_", "prefix"),
wf_tool
=
getToolByName
(
self
,
'portal_workflow'
)
types_tool
=
getToolByName
(
self
,
'portal_types'
)
for
ptype
in
types_tool
.
objectValues
():
if
self
.
getId
()
in
ptype
.
getTypeERP5WorkflowList
():
### getRef
if
self
.
getId
()
in
ptype
.
getTypeERP5WorkflowList
():
chained_ptype_list
.
append
(
ptype
.
getId
())
return
chained_ptype_list
...
...
@@ -113,7 +112,7 @@ class InteractionWorkflow(IdAsReferenceMixin("interactionworkflow_", "prefix"),
'''
Returns a true value if the given info name is supported.
'''
vdef
=
self
.
_getOb
(
name
,
None
)
### getObjectByRef
vdef
=
self
.
_getOb
(
name
,
None
)
if
vdef
is
not
None
:
if
vdef
.
getTypeInfo
().
getId
()
==
'Variable'
:
return
1
...
...
@@ -151,7 +150,6 @@ class InteractionWorkflow(IdAsReferenceMixin("interactionworkflow_", "prefix"),
is supported in the current state.
'''
tdef
=
self
.
_getOb
(
'interaction_'
+
tid
)
LOG
(
' Trigger %s passing guard'
%
(
tdef
.
getId
()),
WARNING
,
'in InteractionWorkflow.py'
)
### getRef
if
tdef
is
not
None
and
self
.
_checkTransitionGuard
(
tdef
,
ob
):
return
1
return
0
...
...
@@ -223,7 +221,7 @@ class InteractionWorkflow(IdAsReferenceMixin("interactionworkflow_", "prefix"),
"""
Generate a key used in the workflow history.
"""
history_key
=
self
.
unrestrictedTraverse
(
self
.
getRelativeUrl
()).
getId
()
### getRef
history_key
=
self
.
unrestrictedTraverse
(
self
.
getRelativeUrl
()).
getId
()
return
history_key
security
.
declarePrivate
(
'getWorklistVariableMatchDict'
)
...
...
@@ -297,8 +295,7 @@ class InteractionWorkflow(IdAsReferenceMixin("interactionworkflow_", "prefix"),
kw
[
'workflow_method_args'
]
=
args
for
t_id
in
transition_list
:
LOG
(
" t_id is '%s'"
%
t_id
,
WARNING
,
" in InteractionWorkflow.py 279."
)
tdef
=
self
.
_getOb
(
t_id
)
# t_id is id or reference?
tdef
=
self
.
_getOb
(
t_id
)
assert
tdef
.
trigger_type
==
TRIGGER_WORKFLOW_METHOD
former_status
=
self
.
_getOb
(
status_dict
[
self
.
getStateVariable
()],
None
)
econtext
=
None
...
...
product/ERP5Workflow/Document/PermissionRoles.py
View file @
3c925863
##############################################################################
#
# Copyright (c) 20
06
Nexedi SARL and Contributors. All Rights Reserved.
# Copyright (c) 20
15
Nexedi SARL and Contributors. All Rights Reserved.
# Wenjie ZHENG <wenjie.zheng@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
...
...
@@ -26,17 +26,13 @@
#
##############################################################################
from
Acquisition
import
aq_inner
from
Acquisition
import
aq_parent
from
AccessControl
import
ClassSecurityInfo
from
Acquisition
import
aq_inner
,
aq_parent
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.XMLObject
import
XMLObject
from
zLOG
import
LOG
,
ERROR
,
DEBUG
,
WARNING
class
PermissionRoles
(
XMLObject
):
"""
Permission role matrix cell unit,
Used to assign a role to a permission.
...
...
@@ -46,7 +42,7 @@ class PermissionRoles(XMLObject):
portal_type
=
'PermissionRoles'
add_permission
=
Permissions
.
AddPortalContent
is_selected
=
0
#
##
for checkerbox (True 1 /False 0)
is_selected
=
0
# for checkerbox (True 1 /False 0)
isPortalContent
=
1
isRADContent
=
1
...
...
@@ -69,15 +65,13 @@ class PermissionRoles(XMLObject):
if
self
.
is_selected
==
1
:
permission_id
=
int
(
self
.
id
.
split
(
'_'
)[
1
])
role_id
=
int
(
self
.
id
.
split
(
'_'
)[
2
])
### zwj: make sure here gets the right coordinates
#LOG('zwj: Assign %s to %s' %(role_id, permission_id), WARNING, "in PermissionRole.")
# zwj: make sure here gets the right coordinates
workflow
=
self
.
getParent
().
getParent
()
permission_list
=
sorted
(
workflow
.
getManagedPermissionList
())
role_list
=
workflow
.
getRoleList
()
permission
=
permission_list
[
permission_id
]
role
=
role_list
[
role_id
]
### zwj: check the name of the role and permission is the one we want
#LOG('zwj: Assign %s to %s' %(role, permission), WARNING, "in PermissionRole.")
# zwj: check the name of the role and permission is the one we want
if
role
==
'None'
:
role
=
[
'Manager'
]
return
permission
,
role
product/ERP5Workflow/Document/State.py
View file @
3c925863
...
...
@@ -2,7 +2,7 @@
#
# Copyright (c) 2006 Nexedi SARL and Contributors. All Rights Reserved.
# Romain Courteaud <romain@nexedi.com>
#
Wenjie ZHENG <wenjie.zheng@tiolive.com>
#
2015
Wenjie ZHENG <wenjie.zheng@tiolive.com>
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
...
...
@@ -27,14 +27,13 @@
##############################################################################
from
AccessControl
import
ClassSecurityInfo
from
Acquisition
import
aq_inner
,
aq_parent
from
Persistence
import
PersistentMapping
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
from
Products.ERP5Type.XMLMatrix
import
XMLMatrix
from
Products.ERP5Type.XMLObject
import
XMLObject
from
zLOG
import
LOG
,
ERROR
,
DEBUG
,
WARNING
from
Acquisition
import
aq_inner
from
Acquisition
import
aq_parent
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
class
StateError
(
Exception
):
"""
...
...
@@ -51,7 +50,6 @@ class State(IdAsReferenceMixin("state_", "prefix"), XMLObject, XMLMatrix):
add_permission
=
Permissions
.
AddPortalContent
isPortalContent
=
1
isRADContent
=
1
###zwj: security features
erp5_permission_roles
=
{}
# { permission: [role] or (role,) }
default_reference
=
''
# Declarative security
...
...
@@ -81,7 +79,6 @@ class State(IdAsReferenceMixin("state_", "prefix"), XMLObject, XMLMatrix):
raise
StateError
else
:
transition
.
execute
(
document
,
form_kw
=
form_kw
)
### zwj: update Role mapping, also in Workflow, initialiseDocument()
self
.
getParent
().
updateRoleMappingsFor
(
document
)
def
undoTransition
(
self
,
document
):
...
...
@@ -121,9 +118,6 @@ class State(IdAsReferenceMixin("state_", "prefix"), XMLObject, XMLMatrix):
status_dict
=
self
.
getParentValue
().
getCurrentStatusDict
(
document
)
return
status_dict
[
variable_name
]
##### zwj: following parts related to the security features ####################
### zwj: Martix method
# Multiple inheritance definition
updateRelatedContent
=
XMLMatrix
.
updateRelatedContent
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
...
...
product/ERP5Workflow/Document/Transition.py
View file @
3c925863
...
...
@@ -26,25 +26,26 @@
#
##############################################################################
import
sys
from
AccessControl
import
ClassSecurityInfo
from
Acquisition
import
aq_base
from
copy
import
deepcopy
from
Products.CMFCore.Expression
import
Expression
from
Products.CMFCore.utils
import
getToolByName
from
Products.DCWorkflow.DCWorkflow
import
ObjectDeleted
,
ObjectMoved
from
Products.DCWorkflow.Expression
import
StateChangeInfo
from
Products.DCWorkflow.Guard
import
Guard
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5Type.Accessor.Base
import
_evaluateTales
from
Products.ERP5Type.Globals
import
PersistentMapping
from
Products.DCWorkflow.Expression
import
StateChangeInfo
from
zLOG
import
LOG
,
ERROR
,
DEBUG
,
WARNING
from
Products.ERP5Type.Utils
import
convertToUpperCase
,
convertToMixedCase
from
Products.DCWorkflow.DCWorkflow
import
ObjectDeleted
,
ObjectMoved
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
from
Products.ERP5Type.patches.DCWorkflow
import
ValidationFailed
from
copy
import
deepcopy
import
sys
from
Products.CMFCore.utils
import
getToolByName
from
Products.ERP5Type.patches.WorkflowTool
import
WorkflowHistoryList
from
Products.ERP5Type.patches.Expression
import
Expression_createExprContext
from
Products.DCWorkflow.Guard
import
Guard
from
Products.CMFCore.Expression
import
Expression
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
from
Products.ERP5Type.patches.WorkflowTool
import
WorkflowHistoryList
from
Products.ERP5Type.Utils
import
convertToUpperCase
,
convertToMixedCase
from
Products.ERP5Type.XMLObject
import
XMLObject
from
zLOG
import
LOG
,
ERROR
,
DEBUG
,
WARNING
TRIGGER_AUTOMATIC
=
0
TRIGGER_USER_ACTION
=
1
...
...
@@ -91,8 +92,7 @@ class Transition(IdAsReferenceMixin("transition_", "prefix"), XMLObject):
def
getGuard
(
self
):
if
self
.
guard
is
None
:
self
.
generateGuard
()
return
self
.
guard
### only generate gurad when self is a User Action
#return Guard().__of__(self) # Create a temporary guard.
return
self
.
guard
def
getVarExprText
(
self
,
id
):
if
not
self
.
var_exprs
:
...
...
product/ERP5Workflow/Document/Variable.py
View file @
3c925863
...
...
@@ -2,7 +2,7 @@
#
# Copyright (c) 2006 Nexedi SARL and Contributors. All Rights Reserved.
# Romain Courteaud <romain@nexedi.com>
#
#
2015 Wenjie Zheng <wenjie.zheng@tiolive.com>
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
...
...
@@ -27,11 +27,11 @@
##############################################################################
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.DCWorkflow.Guard
import
Guard
from
Products.CMFCore.Expression
import
Expression
from
Products.DCWorkflow.Guard
import
Guard
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
from
Products.ERP5Type.XMLObject
import
XMLObject
class
Variable
(
IdAsReferenceMixin
(
"variable_"
,
"prefix"
),
XMLObject
):
"""
...
...
@@ -100,14 +100,12 @@ class Variable(IdAsReferenceMixin("variable_", "prefix"), XMLObject):
res
=
self
.
info_guard
.
getSummary
()
return
res
#
##
zwj: originated from DC workflow; seems useless here?
# zwj: originated from DC workflow; seems useless here?
def
setProperties
(
self
,
description
,
default_value
=
''
,
default_expr
=
''
,
for_catalog
=
0
,
for_status
=
0
,
update_always
=
0
,
props
=
None
,
REQUEST
=
None
):
'''
'''
self
.
description
=
str
(
description
)
self
.
default_value
=
str
(
default_value
)
if
default_expr
:
...
...
product/ERP5Workflow/Document/Workflow.py
View file @
3c925863
...
...
@@ -25,46 +25,40 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import
os
import
sys
from
types
import
StringTypes
from
AccessControl
import
ClassSecurityInfo
from
AccessControl.SecurityManagement
import
getSecurityManager
from
AccessControl.unauthorized
import
Unauthorized
from
Products.DCWorkflow.utils
import
modifyRolesForPermission
from
Products.DCWorkflow.DCWorkflow
import
DCWorkflowDefinition
as
DCWorkflow
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5Type.Globals
import
PersistentMapping
from
Products.ERP5Type.Accessor
import
WorkflowState
from
Products.ERP5Type
import
Permissions
from
tempfile
import
mktemp
import
os
from
Products.CMFCore.WorkflowCore
import
WorkflowException
from
Products.ERP5Workflow.Document.Transition
import
TRIGGER_AUTOMATIC
from
Products.ERP5Workflow.Document.Transition
import
TRIGGER_USER_ACTION
from
Products.ERP5Workflow.Document.Transition
import
TRIGGER_WORKFLOW_METHOD
from
Products.DCWorkflowGraph.config
import
DOT_EXE
from
Products.DCWorkflowGraph.DCWorkflowGraph
import
bin_search
,
getGraph
from
Products.DCWorkflow.States
import
StateDefinition
as
DCWorkflowState
from
Products.CMFCore.WorkflowCore
import
ObjectDeleted
from
Products.CMFCore.WorkflowCore
import
ObjectMoved
from
Products.DCWorkflow.utils
import
Message
as
_
from
DocumentTemplate.DT_Util
import
TemplateDict
from
Products.ERP5Type.Utils
import
UpperCase
,
convertToMixedCase
from
AccessControl.SecurityManagement
import
getSecurityManager
from
Acquisition
import
aq_base
,
aq_inner
,
aq_parent
from
DateTime
import
DateTime
from
zLOG
import
LOG
,
ERROR
,
DEBUG
,
WARNING
from
DocumentTemplate.DT_Util
import
TemplateDict
from
Products.CMFCore.Expression
import
Expression
from
Products.ERP5Type.Cache
import
CachingMethod
from
Products.ERP5Type.patches.Expression
import
Expression_createExprContext
from
Products.ERP5Type.patches.DCWorkflow
import
Guard_checkWithoutRoles
from
Products.DCWorkflow.Expression
import
StateChangeInfo
from
Products.ERP5Type.patches.WorkflowTool
import
SECURITY_PARAMETER_ID
,
WORKLIST_METADATA_KEY
from
Products.CMFCore.utils
import
getToolByName
from
Products.CMFCore.WorkflowCore
import
WorkflowException
,
ObjectDeleted
,
\
ObjectMoved
from
Products.DCWorkflow.Expression
import
StateChangeInfo
from
Products.DCWorkflowGraph.config
import
DOT_EXE
from
Products.DCWorkflowGraph.DCWorkflowGraph
import
bin_search
,
getGraph
from
Products.DCWorkflow.utils
import
Message
as
_
from
Products.DCWorkflow.utils
import
modifyRolesForPermission
from
Products.DCWorkflow.DCWorkflow
import
DCWorkflowDefinition
as
DCWorkflow
from
Products.ERP5.Tool
import
ERP5WorkflowTool
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.Globals
import
PersistentMapping
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
from
Products.ERP5Type.patches.Expression
import
Expression_createExprContext
from
Products.ERP5Type.patches.WorkflowTool
import
SECURITY_PARAMETER_ID
,
\
WORKLIST_METADATA_KEY
from
Products.ERP5Type.Utils
import
UpperCase
,
convertToMixedCase
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5Workflow.Document.Transition
import
TRIGGER_AUTOMATIC
,
\
TRIGGER_USER_ACTION
,
TRIGGER_WORKFLOW_METHOD
from
tempfile
import
mktemp
from
types
import
StringTypes
from
zLOG
import
LOG
,
ERROR
,
DEBUG
,
WARNING
class
Workflow
(
IdAsReferenceMixin
(
"workflow_"
,
"prefix"
),
XMLObject
):
"""
...
...
@@ -78,7 +72,6 @@ class Workflow(IdAsReferenceMixin("workflow_", "prefix"), XMLObject):
isPortalContent
=
1
isRADContent
=
1
default_reference
=
''
### zwj: for security issue
managed_permission_list
=
()
managed_role
=
()
erp5_permission_roles
=
{}
# { permission: [role] or (role,) }
...
...
@@ -151,7 +144,7 @@ class Workflow(IdAsReferenceMixin("workflow_", "prefix"), XMLObject):
document
.
workflow_history
[
workflow_key
]
+=
(
status_dict
,)
# XXX this _p_changed marks the document modified, but the
# only the PersistentMapping is modified
#document._p_changed = 1
#
document._p_changed = 1
# XXX this _p_changed is apparently not necessary
#document.workflow_history._p_changed = 1
...
...
@@ -256,22 +249,22 @@ class Workflow(IdAsReferenceMixin("workflow_", "prefix"), XMLObject):
managed_permission
=
self
.
getManagedPermissionList
()
if
sdef
is
None
:
return
0
#
##
zwj: get all matrix cell objects
# zwj: get all matrix cell objects
permission_role_matrix_cells
=
sdef
.
objectValues
(
portal_type
=
"PermissionRoles"
)
#
##
zwj: build a permission roles dict
# zwj: build a permission roles dict
for
perm_role
in
permission_role_matrix_cells
:
permission
,
role
=
perm_role
.
getPermissionRole
()
#
##
zwj: double check the right role and permission are obtained
# zwj: double check the right role and permission are obtained
if
permission
!=
'None'
:
if
self
.
erp5_permission_roles
.
has_key
(
permission
):
self
.
erp5_permission_roles
[
permission
]
+=
(
role
,)
else
:
self
.
erp5_permission_roles
.
update
({
permission
:
(
role
,)})
#
##
zwj: update role list to permission
# zwj: update role list to permission
for
permission_roles
in
self
.
erp5_permission_roles
.
keys
():
if
modifyRolesForPermission
(
document
,
permission_roles
,
self
.
erp5_permission_roles
[
permission_roles
]):
changed
=
1
#
## zwj: clean Permission Role list for
next role mapping
#
zwj: clean Permission Role list for the
next role mapping
del
self
.
erp5_permission_roles
[
permission_roles
]
return
changed
...
...
@@ -368,8 +361,6 @@ class Workflow(IdAsReferenceMixin("workflow_", "prefix"), XMLObject):
if
not
self
.
objectValues
(
portal_type
=
'Worklist'
):
return
None
LOG
(
"380 '%s' Worklists found!"
%
len
(
self
.
objectValues
(
portal_type
=
'Worklist'
)),
WARNING
,
"in Workflow.py"
)
### zwj: for DC workflow
portal
=
self
.
getPortalObject
()
def
getPortalTypeListForWorkflow
(
workflow_id
):
workflow_tool
=
portal
.
portal_workflow
...
...
@@ -377,7 +368,6 @@ class Workflow(IdAsReferenceMixin("workflow_", "prefix"), XMLObject):
append
=
result
.
append
for
workflow_id
in
info
.
object
.
getTypeInfo
().
getTypeERP5WorkflowList
():
append
(
info
.
object
.
getTypeInfo
().
getId
())
#LOG ('Supported portal types are: %s'%result, WARNING, ' in Workflow.py')
return
result
portal_type_list
=
getPortalTypeListForWorkflow
(
self
.
id
)
...
...
@@ -405,7 +395,6 @@ class Workflow(IdAsReferenceMixin("workflow_", "prefix"), XMLObject):
variable_match
[
key
]
=
evaluated_value
if
'portal_type'
in
variable_match
and
len
(
variable_match
[
'portal_type'
]):
#raise NotImplementedError (variable_match['portal_type'])
portal_type_intersection
=
set
(
variable_match
[
'portal_type'
]).
intersection
(
portal_type_list
)
# in case the current workflow is not associated with portal_types
# defined on the worklist, don't display the worklist for this
...
...
@@ -484,9 +473,8 @@ class Workflow(IdAsReferenceMixin("workflow_", "prefix"), XMLObject):
def
_getWorkflowStateOf
(
self
,
ob
,
id_only
=
0
):
tool
=
getToolByName
(
self
,
'portal_workflow'
)
id_no_suffix
=
'_'
.
join
(
self
.
id
.
split
(
'_'
)[
1
:]
)
id_no_suffix
=
self
.
getReference
(
)
status
=
tool
.
getStatusOf
(
id_no_suffix
,
ob
)
LOG
(
"502 tool is '%s' type, status is '%s'"
%
(
tool
.
getPortalType
(),
status
),
WARNING
,
" in Workflow.py"
)
if
status
is
None
:
state
=
self
.
getSourceValue
()
else
:
...
...
@@ -550,7 +538,6 @@ class Workflow(IdAsReferenceMixin("workflow_", "prefix"), XMLObject):
def
notifyWorkflowMethod
(
self
,
ob
,
transition_list
,
args
=
None
,
kw
=
None
):
""" Execute workflow methods.
"""
LOG
(
"transition_list is '%s'"
%
transition_list
,
WARNING
,
" in Workflow.py 528."
)
if
type
(
transition_list
)
in
StringTypes
:
method_id
=
transition_list
elif
len
(
transition_list
)
==
1
:
...
...
@@ -618,8 +605,6 @@ class Workflow(IdAsReferenceMixin("workflow_", "prefix"), XMLObject):
new_state
=
new_sdef
.
getReference
()
former_status
=
current_state_value
.
getReference
()
LOG
(
" Object '%s' will change from state '%s' to '%s'"
%
(
document
.
getId
(),
old_state
,
new_state
),
WARNING
,
" in Workflow.py 593"
)
# Execute the "before" script.
before_script_success
=
1
if
tdef
is
not
None
and
tdef
.
getBeforeScriptId
():
...
...
product/ERP5Workflow/Document/WorkflowScript.py
View file @
3c925863
...
...
@@ -25,14 +25,15 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from
AccessControl.class_init
import
InitializeClass
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
AccessControl.class_init
import
InitializeClass
from
App.special_dtml
import
HTMLFile
from
Products.ERP5Type.XMLObject
import
XMLObject
from
Products.ERP5.Document.Ticket
import
Ticket
from
Products.ERP5.Document.PythonScript
import
PythonScript
from
Products.ERP5.Document.Ticket
import
Ticket
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.ConsistencyMessage
import
ConsistencyMessage
from
Products.ERP5Type.XMLObject
import
XMLObject
from
zLOG
import
LOG
,
ERROR
,
DEBUG
,
WARNING
class
WorkflowScript
(
PythonScript
):
...
...
product/ERP5Workflow/Document/Worklist.py
View file @
3c925863
...
...
@@ -26,21 +26,22 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import
re
from
zLOG
import
LOG
,
WARNING
from
AccessControl
import
ClassSecurityInfo
from
Acquisition
import
aq_inner
from
Acquisition
import
aq_parent
from
Acquisition
import
aq_inner
,
aq_parent
from
Persistence
import
PersistentMapping
from
Products.CMFCore.utils
import
getToolByName
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5Type.
XMLObject
import
XMLObject
from
Products.ERP5Type.
id_as_reference
import
IdAsReferenceMixin
from
Products.ERP5Type.patches.Expression
import
Expression_createExprContext
from
Products.
DCWorkflow.Expression
import
Expression
from
Products.DCWorkflow.Expression
import
StateChangeInfo
from
Products.
ERP5Type.XMLObject
import
XMLObject
from
Products.DCWorkflow.Expression
import
Expression
,
StateChangeInfo
from
Products.DCWorkflow.Guard
import
Guard
from
Products.DCWorkflow.permissions
import
ManagePortal
from
Persistence
import
PersistentMapping
from
Products.CMFCore.utils
import
getToolByName
from
Products.ERP5Type.id_as_reference
import
IdAsReferenceMixin
from
zLOG
import
LOG
,
WARNING
tales_re
=
re
.
compile
(
r'(\
w+:)?(.*)
')
...
...
@@ -54,14 +55,11 @@ class Worklist(IdAsReferenceMixin("worklist_", "prefix"), XMLObject):
add_permission = Permissions.AddPortalContent
isPortalContent = 1
isRADContent = 1
description = ''
var_matches = None # Compared with catalog when set.
### zwj: following 3 variables take place var_matches for this moment
matched_portal_type = ''
matched_validation_state = None
matched_simulation_state = None
actbox_name = ''
actbox_url = ''
actbox_icon = ''
...
...
@@ -110,7 +108,6 @@ class Worklist(IdAsReferenceMixin("worklist_", "prefix"), XMLObject):
if self.guard.expr != self.getExpression():
self.guard.expr = self.getExpression()
def getAvailableCatalogVars(self):
res = []
res.append(self.getParentValue().getStateVariable())
...
...
@@ -145,10 +142,8 @@ class Worklist(IdAsReferenceMixin("worklist_", "prefix"), XMLObject):
v = [ var.strip() for var in self.getMatchedPortalTypeList() ]
matches = tuple(v)
elif id == '
validation_state
':
LOG('
3.2
Matched
validation
state
=
%
s
'%self.getMatchedValidationStateList(), WARNING, '
in
Worklist
.
py
')
matches = tuple([self.getMatchedValidationStateList()])
elif id == '
simulation_stae
':
LOG('
3.3
Matched
simulation
state
=
%
s
'%self.getMatchedSimulationStateList(), WARNING, '
in
Worklist
.
py
')
matches = tuple([self.getMatchedSimulationStateList()])
else:
raise NotImplementedError ("Cataloged variable matching error in Worklist.py")
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment