diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 755c39238..13b1782de 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -34,6 +34,8 @@ Motions:
follow recommendation, manage submitters and supporters, change motion
category, motion block and origin and manage motion polls [#3913].
- Added new permission to create amendments [#4128].
+ - Allowed submitters to set state of new motions in complex and customized
+ workflow [#4236].
- Added multi select action to manage submitters, tags, states and
recommendations [#4037, #4132].
- Added timestampes for motions [#4134].
diff --git a/client/src/app/site/motions/components/motion-detail/motion-detail.component.html b/client/src/app/site/motions/components/motion-detail/motion-detail.component.html
index 1cf555806..7331a681a 100644
--- a/client/src/app/site/motions/components/motion-detail/motion-detail.component.html
+++ b/client/src/app/site/motions/components/motion-detail/motion-detail.component.html
@@ -222,12 +222,14 @@
-
-
+
+ 0">
+
+
-
+
{{ stateLabel }}
@@ -238,7 +240,7 @@
-
+
{{ stateLabel }}
diff --git a/client/src/app/site/motions/services/local-permissions.service.ts b/client/src/app/site/motions/services/local-permissions.service.ts
index 078c10381..e6d1cbacb 100644
--- a/client/src/app/site/motions/services/local-permissions.service.ts
+++ b/client/src/app/site/motions/services/local-permissions.service.ts
@@ -108,6 +108,20 @@ export class LocalPermissionsService {
motion.state.allow_submitter_edit &&
motion.submitters.some(submitter => submitter.id === this.operator.user.id)
);
+ case 'change_state':
+ // check also for empty ViewMotion object (e.g. if motion.id is null)
+ // important for creating new motion as normal user
+ if (!motion || !motion.id) {
+ return false;
+ }
+ return (
+ this.operator.hasPerms('motions.can_manage') ||
+ this.operator.hasPerms('motions.can_manage_metadata') ||
+ (motion.state &&
+ motion.state.allow_submitter_edit &&
+ motion.submitters &&
+ motion.submitters.some(submitter => submitter.id === this.operator.user.id))
+ );
case 'change_metadata':
return (
this.operator.hasPerms('motions.can_manage') ||
diff --git a/openslides/motions/views.py b/openslides/motions/views.py
index 554bee02b..18c1a7b12 100644
--- a/openslides/motions/views.py
+++ b/openslides/motions/views.py
@@ -75,11 +75,10 @@ class MotionViewSet(ModelViewSet):
result = has_perm(self.request.user, "motions.can_see")
# For partial_update, update and destroy requests the rest of the check is
# done in the update method. See below.
- elif self.action == "create":
+ elif self.action in ("create", "set_state"):
result = has_perm(self.request.user, "motions.can_see")
- # For create the rest of the check is done in the create method. See below.
+ # For create the rest of the check is done in the respective method. See below.
elif self.action in (
- "set_state",
"manage_multiple_state",
"set_recommendation",
"manage_multiple_recommendation",
@@ -561,6 +560,10 @@ class MotionViewSet(ModelViewSet):
# Set or reset state.
if state is not None:
# Check data and set state.
+ if not has_perm(request.user, "motions.can_manage_metadata") and not (
+ motion.is_submitter(request.user) and motion.state.allow_submitter_edit
+ ):
+ self.permission_denied(request)
try:
state_id = int(state)
except ValueError:
@@ -574,6 +577,8 @@ class MotionViewSet(ModelViewSet):
motion.set_state(state_id)
else:
# Reset state.
+ if not has_perm(self.request.user, "motions.can_manage_metadata"):
+ self.permission_denied(request)
motion.reset_state()
# Save motion.