1616 DraftIssueLabel ,
1717 DraftIssueCycle ,
1818 DraftIssueModule ,
19+ ProjectMember ,
20+ EstimatePoint ,
1921)
2022from 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
2730class 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 )
0 commit comments