Skip to content

Commit d4705e1

Browse files
NarayanBavisettisriramveeraghanta
authored andcommitted
[WEB-4544] chore: added field validations in serializer (#7460)
* chore: added field validations in serializer * chore: added enum for roles
1 parent 69d5cd1 commit d4705e1

File tree

3 files changed

+148
-30
lines changed

3 files changed

+148
-30
lines changed

apps/api/plane/api/serializers/issue.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
ProjectMember,
2121
State,
2222
User,
23+
EstimatePoint,
2324
)
2425
from plane.utils.content_validator import (
2526
validate_html_content,
@@ -126,13 +127,27 @@ def validate(self, data):
126127
if (
127128
data.get("parent")
128129
and not Issue.objects.filter(
129-
workspace_id=self.context.get("workspace_id"), pk=data.get("parent").id
130+
workspace_id=self.context.get("workspace_id"),
131+
project_id=self.context.get("project_id"),
132+
pk=data.get("parent").id,
130133
).exists()
131134
):
132135
raise serializers.ValidationError(
133136
"Parent is not valid issue_id please pass a valid issue_id"
134137
)
135138

139+
if (
140+
data.get("estimate_point")
141+
and not EstimatePoint.objects.filter(
142+
workspace_id=self.context.get("workspace_id"),
143+
project_id=self.context.get("project_id"),
144+
pk=data.get("estimate_point").id,
145+
).exists()
146+
):
147+
raise serializers.ValidationError(
148+
"Estimate point is not valid please pass a valid estimate_point_id"
149+
)
150+
136151
return data
137152

138153
def create(self, validated_data):

apps/api/plane/app/serializers/draft.py

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
DraftIssueLabel,
1717
DraftIssueCycle,
1818
DraftIssueModule,
19+
ProjectMember,
20+
EstimatePoint,
1921
)
2022
from plane.utils.content_validator import (
2123
validate_html_content,
2224
validate_json_content,
2325
validate_binary_data,
2426
)
27+
from plane.app.permissions import ROLE
2528

2629

2730
class DraftIssueCreateSerializer(BaseSerializer):
@@ -62,31 +65,84 @@ def to_representation(self, instance):
6265
data["label_ids"] = label_ids if label_ids else []
6366
return data
6467

65-
def validate(self, data):
68+
def validate(self, attrs):
6669
if (
67-
data.get("start_date", None) is not None
68-
and data.get("target_date", None) is not None
69-
and data.get("start_date", None) > data.get("target_date", None)
70+
attrs.get("start_date", None) is not None
71+
and attrs.get("target_date", None) is not None
72+
and attrs.get("start_date", None) > attrs.get("target_date", None)
7073
):
7174
raise serializers.ValidationError("Start date cannot exceed target date")
7275

7376
# Validate description content for security
74-
if "description" in data and data["description"]:
75-
is_valid, error_msg = validate_json_content(data["description"])
77+
if "description" in attrs and attrs["description"]:
78+
is_valid, error_msg = validate_json_content(attrs["description"])
7679
if not is_valid:
7780
raise serializers.ValidationError({"description": error_msg})
7881

79-
if "description_html" in data and data["description_html"]:
80-
is_valid, error_msg = validate_html_content(data["description_html"])
82+
if "description_html" in attrs and attrs["description_html"]:
83+
is_valid, error_msg = validate_html_content(attrs["description_html"])
8184
if not is_valid:
8285
raise serializers.ValidationError({"description_html": error_msg})
8386

84-
if "description_binary" in data and data["description_binary"]:
85-
is_valid, error_msg = validate_binary_data(data["description_binary"])
87+
if "description_binary" in attrs and attrs["description_binary"]:
88+
is_valid, error_msg = validate_binary_data(attrs["description_binary"])
8689
if not is_valid:
8790
raise serializers.ValidationError({"description_binary": error_msg})
8891

89-
return data
92+
# Validate assignees are from project
93+
if attrs.get("assignee_ids", []):
94+
attrs["assignee_ids"] = ProjectMember.objects.filter(
95+
project_id=self.context["project_id"],
96+
role__gte=ROLE.MEMBER.value,
97+
is_active=True,
98+
member_id__in=attrs["assignee_ids"],
99+
).values_list("member_id", flat=True)
100+
101+
# Validate labels are from project
102+
if attrs.get("label_ids"):
103+
label_ids = [label.id for label in attrs["label_ids"]]
104+
attrs["label_ids"] = list(
105+
Label.objects.filter(
106+
project_id=self.context.get("project_id"), id__in=label_ids
107+
).values_list("id", flat=True)
108+
)
109+
110+
# # Check state is from the project only else raise validation error
111+
if (
112+
attrs.get("state")
113+
and not State.objects.filter(
114+
project_id=self.context.get("project_id"),
115+
pk=attrs.get("state").id,
116+
).exists()
117+
):
118+
raise serializers.ValidationError(
119+
"State is not valid please pass a valid state_id"
120+
)
121+
122+
# # Check parent issue is from workspace as it can be cross workspace
123+
if (
124+
attrs.get("parent")
125+
and not Issue.objects.filter(
126+
project_id=self.context.get("project_id"),
127+
pk=attrs.get("parent").id,
128+
).exists()
129+
):
130+
raise serializers.ValidationError(
131+
"Parent is not valid issue_id please pass a valid issue_id"
132+
)
133+
134+
if (
135+
attrs.get("estimate_point")
136+
and not EstimatePoint.objects.filter(
137+
project_id=self.context.get("project_id"),
138+
pk=attrs.get("estimate_point").id,
139+
).exists()
140+
):
141+
raise serializers.ValidationError(
142+
"Estimate point is not valid please pass a valid estimate_point_id"
143+
)
144+
145+
return attrs
90146

91147
def create(self, validated_data):
92148
assignees = validated_data.pop("assignee_ids", None)
@@ -111,14 +167,14 @@ def create(self, validated_data):
111167
DraftIssueAssignee.objects.bulk_create(
112168
[
113169
DraftIssueAssignee(
114-
assignee=user,
170+
assignee_id=assignee_id,
115171
draft_issue=issue,
116172
workspace_id=workspace_id,
117173
project_id=project_id,
118174
created_by_id=created_by_id,
119175
updated_by_id=updated_by_id,
120176
)
121-
for user in assignees
177+
for assignee_id in assignees
122178
],
123179
batch_size=10,
124180
)
@@ -127,14 +183,14 @@ def create(self, validated_data):
127183
DraftIssueLabel.objects.bulk_create(
128184
[
129185
DraftIssueLabel(
130-
label=label,
186+
label_id=label_id,
131187
draft_issue=issue,
132188
project_id=project_id,
133189
workspace_id=workspace_id,
134190
created_by_id=created_by_id,
135191
updated_by_id=updated_by_id,
136192
)
137-
for label in labels
193+
for label_id in labels
138194
],
139195
batch_size=10,
140196
)
@@ -185,14 +241,14 @@ def update(self, instance, validated_data):
185241
DraftIssueAssignee.objects.bulk_create(
186242
[
187243
DraftIssueAssignee(
188-
assignee=user,
244+
assignee_id=assignee_id,
189245
draft_issue=instance,
190246
workspace_id=workspace_id,
191247
project_id=project_id,
192248
created_by_id=created_by_id,
193249
updated_by_id=updated_by_id,
194250
)
195-
for user in assignees
251+
for assignee_id in assignees
196252
],
197253
batch_size=10,
198254
)

apps/api/plane/app/serializers/issue.py

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
IssueVersion,
3838
IssueDescriptionVersion,
3939
ProjectMember,
40+
EstimatePoint,
4041
)
4142
from plane.utils.content_validator import (
4243
validate_html_content,
@@ -124,14 +125,6 @@ def validate(self, attrs):
124125
):
125126
raise serializers.ValidationError("Start date cannot exceed target date")
126127

127-
if attrs.get("assignee_ids", []):
128-
attrs["assignee_ids"] = ProjectMember.objects.filter(
129-
project_id=self.context["project_id"],
130-
role__gte=15,
131-
is_active=True,
132-
member_id__in=attrs["assignee_ids"],
133-
).values_list("member_id", flat=True)
134-
135128
# Validate description content for security
136129
if "description" in attrs and attrs["description"]:
137130
is_valid, error_msg = validate_json_content(attrs["description"])
@@ -148,6 +141,60 @@ def validate(self, attrs):
148141
if not is_valid:
149142
raise serializers.ValidationError({"description_binary": error_msg})
150143

144+
# Validate assignees are from project
145+
if attrs.get("assignee_ids", []):
146+
attrs["assignee_ids"] = ProjectMember.objects.filter(
147+
project_id=self.context["project_id"],
148+
role__gte=15,
149+
is_active=True,
150+
member_id__in=attrs["assignee_ids"],
151+
).values_list("member_id", flat=True)
152+
153+
# Validate labels are from project
154+
if attrs.get("label_ids"):
155+
label_ids = [label.id for label in attrs["label_ids"]]
156+
attrs["label_ids"] = list(
157+
Label.objects.filter(
158+
project_id=self.context.get("project_id"),
159+
id__in=label_ids,
160+
).values_list("id", flat=True)
161+
)
162+
163+
# Check state is from the project only else raise validation error
164+
if (
165+
attrs.get("state")
166+
and not State.objects.filter(
167+
project_id=self.context.get("project_id"),
168+
pk=attrs.get("state").id,
169+
).exists()
170+
):
171+
raise serializers.ValidationError(
172+
"State is not valid please pass a valid state_id"
173+
)
174+
175+
# Check parent issue is from workspace as it can be cross workspace
176+
if (
177+
attrs.get("parent")
178+
and not Issue.objects.filter(
179+
project_id=self.context.get("project_id"),
180+
pk=attrs.get("parent").id,
181+
).exists()
182+
):
183+
raise serializers.ValidationError(
184+
"Parent is not valid issue_id please pass a valid issue_id"
185+
)
186+
187+
if (
188+
attrs.get("estimate_point")
189+
and not EstimatePoint.objects.filter(
190+
project_id=self.context.get("project_id"),
191+
pk=attrs.get("estimate_point").id,
192+
).exists()
193+
):
194+
raise serializers.ValidationError(
195+
"Estimate point is not valid please pass a valid estimate_point_id"
196+
)
197+
151198
return attrs
152199

153200
def create(self, validated_data):
@@ -211,14 +258,14 @@ def create(self, validated_data):
211258
IssueLabel.objects.bulk_create(
212259
[
213260
IssueLabel(
214-
label=label,
261+
label_id=label_id,
215262
issue=issue,
216263
project_id=project_id,
217264
workspace_id=workspace_id,
218265
created_by_id=created_by_id,
219266
updated_by_id=updated_by_id,
220267
)
221-
for label in labels
268+
for label_id in labels
222269
],
223270
batch_size=10,
224271
)
@@ -264,14 +311,14 @@ def update(self, instance, validated_data):
264311
IssueLabel.objects.bulk_create(
265312
[
266313
IssueLabel(
267-
label=label,
314+
label_id=label_id,
268315
issue=instance,
269316
project_id=project_id,
270317
workspace_id=workspace_id,
271318
created_by_id=created_by_id,
272319
updated_by_id=updated_by_id,
273320
)
274-
for label in labels
321+
for label_id in labels
275322
],
276323
batch_size=10,
277324
ignore_conflicts=True,

0 commit comments

Comments
 (0)