33 Finding_Template , Test_Type , Development_Environment , Report_Type , \
44 JIRA_Issue , Tool_Product_Settings , Tool_Configuration , Tool_Type , \
55 Product_Type , JIRA_Conf , Endpoint , BurpRawRequestResponse , JIRA_PKey , \
6- Notes , Dojo_User
6+ Notes , Dojo_User , Regulation
77from dojo .forms import ImportScanForm , SEVERITY_CHOICES
88from dojo .tools .factory import import_parser_factory
99from django .core .validators import URLValidator , validate_ipv46_address
10-
1110from rest_framework import serializers
1211from django .core .exceptions import ValidationError
1312from django .utils import timezone
1413import datetime
14+ import six
15+ from django .utils .translation import ugettext_lazy as _
16+ import json
17+
18+
19+ class TagList (list ):
20+ def __init__ (self , * args , ** kwargs ):
21+ pretty_print = kwargs .pop ("pretty_print" , True )
22+ list .__init__ (self , * args , ** kwargs )
23+ self .pretty_print = pretty_print
24+
25+ def __add__ (self , rhs ):
26+ return TagList (list .__add__ (self , rhs ))
27+
28+ def __getitem__ (self , item ):
29+ result = list .__getitem__ (self , item )
30+ try :
31+ return TagList (result )
32+ except TypeError :
33+ return result
34+
35+ def __str__ (self ):
36+ if self .pretty_print :
37+ return json .dumps (
38+ self , sort_keys = True , indent = 4 , separators = (',' , ': ' ))
39+ else :
40+ return json .dumps (self )
41+
42+
43+ class TagListSerializerField (serializers .ListField ):
44+ child = serializers .CharField ()
45+ default_error_messages = {
46+ 'not_a_list' : _ (
47+ 'Expected a list of items but got type "{input_type}".' ),
48+ 'invalid_json' : _ ('Invalid json list. A tag list submitted in string'
49+ ' form must be valid json.' ),
50+ 'not_a_str' : _ ('All list items must be of string type.' )
51+ }
52+ order_by = None
53+
54+ def __init__ (self , ** kwargs ):
55+ pretty_print = kwargs .pop ("pretty_print" , True )
56+
57+ style = kwargs .pop ("style" , {})
58+ kwargs ["style" ] = {'base_template' : 'textarea.html' }
59+ kwargs ["style" ].update (style )
60+
61+ super (TagListSerializerField , self ).__init__ (** kwargs )
62+
63+ self .pretty_print = pretty_print
64+
65+ def to_internal_value (self , value ):
66+ if isinstance (value , six .string_types ):
67+ if not value :
68+ value = "[]"
69+ try :
70+ value = json .loads (value )
71+ except ValueError :
72+ self .fail ('invalid_json' )
73+
74+ if not isinstance (value , list ):
75+ self .fail ('not_a_list' , input_type = type (value ).__name__ )
76+
77+ for s in value :
78+ if not isinstance (s , six .string_types ):
79+ self .fail ('not_a_str' )
80+
81+ self .child .run_validation (s )
82+
83+ return value
84+
85+ def to_representation (self , value ):
86+ if not isinstance (value , TagList ):
87+ if not isinstance (value , list ):
88+ if self .order_by :
89+ tags = value .all ().order_by (* self .order_by )
90+ else :
91+ tags = value .all ()
92+ value = [tag .name for tag in tags ]
93+ value = TagList (value , pretty_print = self .pretty_print )
94+
95+ return value
96+
97+
98+ class TaggitSerializer (serializers .Serializer ):
99+ def create (self , validated_data ):
100+ to_be_tagged , validated_data = self ._pop_tags (validated_data )
101+
102+ tag_object = super (TaggitSerializer , self ).create (validated_data )
103+
104+ return self ._save_tags (tag_object , to_be_tagged )
105+
106+ def update (self , instance , validated_data ):
107+ to_be_tagged , validated_data = self ._pop_tags (validated_data )
108+
109+ tag_object = super (TaggitSerializer , self ).update (
110+ instance , validated_data )
111+
112+ return self ._save_tags (tag_object , to_be_tagged )
113+
114+ def _save_tags (self , tag_object , tags ):
115+ for key in tags .keys ():
116+ tag_values = tags .get (key )
117+ tag_object .tags = ", " .join (tag_values )
118+
119+ return tag_object
120+
121+ def _pop_tags (self , validated_data ):
122+ to_be_tagged = {}
123+
124+ for key in self .fields .keys ():
125+ field = self .fields [key ]
126+ if isinstance (field , TagListSerializerField ):
127+ if key in validated_data :
128+ to_be_tagged [key ] = validated_data .pop (key )
129+
130+ return (to_be_tagged , validated_data )
15131
16132
17133class UserSerializer (serializers .HyperlinkedModelSerializer ):
@@ -20,27 +136,30 @@ class Meta:
20136 fields = ('url' , 'username' , 'first_name' , 'last_name' , 'last_login' )
21137
22138
23- class ProductSerializer (serializers .HyperlinkedModelSerializer ):
139+ class ProductSerializer (TaggitSerializer , serializers .HyperlinkedModelSerializer ):
24140 findings_count = serializers .SerializerMethodField ()
25141 product_manager = serializers .HyperlinkedRelatedField (
26142 queryset = User .objects .all (),
27143 view_name = 'user-detail' ,
28- format = 'html' )
144+ format = 'html' , required = False )
29145 technical_contact = serializers .HyperlinkedRelatedField (
30146 queryset = User .objects .all (),
31147 view_name = 'user-detail' ,
32- format = 'html' )
148+ format = 'html' , required = False )
33149 team_manager = serializers .HyperlinkedRelatedField (
34150 queryset = User .objects .all (),
35151 view_name = 'user-detail' ,
36- format = 'html' )
152+ format = 'html' , required = False )
37153 authorized_users = serializers .HyperlinkedRelatedField (
38154 many = True ,
39155 queryset = User .objects .exclude (is_staff = True ).exclude (is_active = False ),
40156 view_name = 'user-detail' ,
41- format = 'html' )
157+ format = 'html' , required = False )
42158 prod_type = serializers .PrimaryKeyRelatedField (
43159 queryset = Product_Type .objects .all ())
160+ regulations = serializers .PrimaryKeyRelatedField (
161+ queryset = Regulation .objects .all (), many = True , required = False )
162+ tags = TagListSerializerField (required = False )
44163
45164 class Meta :
46165 model = Product
@@ -51,11 +170,12 @@ def get_findings_count(self, obj):
51170 return obj .findings_count
52171
53172
54- class EngagementSerializer (serializers .HyperlinkedModelSerializer ):
173+ class EngagementSerializer (TaggitSerializer , serializers .HyperlinkedModelSerializer ):
55174 eng_type = serializers .PrimaryKeyRelatedField (
56- queryset = Engagement_Type .objects .all ())
175+ queryset = Engagement_Type .objects .all (), required = False )
57176 report_type = serializers .PrimaryKeyRelatedField (
58- queryset = Report_Type .objects .all ())
177+ queryset = Report_Type .objects .all (), required = False )
178+ tags = TagListSerializerField (required = False )
59179
60180 class Meta :
61181 model = Engagement
@@ -95,7 +215,8 @@ class Meta:
95215 fields = '__all__'
96216
97217
98- class EndpointSerializer (serializers .HyperlinkedModelSerializer ):
218+ class EndpointSerializer (TaggitSerializer , serializers .HyperlinkedModelSerializer ):
219+ tags = TagListSerializerField (required = False )
99220
100221 class Meta :
101222 model = Endpoint
@@ -204,7 +325,7 @@ class Meta:
204325 fields = '__all__'
205326
206327
207- class TestSerializer (serializers .HyperlinkedModelSerializer ):
328+ class TestSerializer (TaggitSerializer , serializers .HyperlinkedModelSerializer ):
208329 engagement = serializers .HyperlinkedRelatedField (
209330 read_only = True ,
210331 view_name = 'engagement-detail' ,
@@ -213,13 +334,17 @@ class TestSerializer(serializers.HyperlinkedModelSerializer):
213334 queryset = Test_Type .objects .all ())
214335 environment = serializers .PrimaryKeyRelatedField (
215336 queryset = Development_Environment .objects .all ())
337+ notes = serializers .PrimaryKeyRelatedField (
338+ queryset = Notes .objects .all (),
339+ many = True )
340+ tags = TagListSerializerField (required = False )
216341
217342 class Meta :
218343 model = Test
219344 fields = '__all__'
220345
221346
222- class TestCreateSerializer (serializers .HyperlinkedModelSerializer ):
347+ class TestCreateSerializer (TaggitSerializer , serializers .HyperlinkedModelSerializer ):
223348 test_type = serializers .PrimaryKeyRelatedField (
224349 queryset = Test_Type .objects .all ())
225350 environment = serializers .PrimaryKeyRelatedField (
@@ -233,6 +358,7 @@ class TestCreateSerializer(serializers.HyperlinkedModelSerializer):
233358 notes = serializers .PrimaryKeyRelatedField (
234359 queryset = Notes .objects .all (),
235360 many = True )
361+ tags = TagListSerializerField (required = False )
236362
237363 class Meta :
238364 model = Test
@@ -245,7 +371,7 @@ class Meta:
245371 fields = '__all__'
246372
247373
248- class FindingSerializer (serializers .HyperlinkedModelSerializer ):
374+ class FindingSerializer (TaggitSerializer , serializers .HyperlinkedModelSerializer ):
249375 review_requested_by = serializers .HyperlinkedRelatedField (
250376 queryset = Dojo_User .objects .all (),
251377 view_name = 'user-detail' ,
@@ -274,6 +400,7 @@ class FindingSerializer(serializers.HyperlinkedModelSerializer):
274400 source = 'url' ,
275401 read_only = True )
276402 url = serializers .HyperlinkedIdentityField (view_name = 'finding-detail' )
403+ tags = TagListSerializerField (required = False )
277404
278405 class Meta :
279406 model = Finding
@@ -299,7 +426,7 @@ def validate(self, data):
299426 return data
300427
301428
302- class FindingCreateSerializer (serializers .HyperlinkedModelSerializer ):
429+ class FindingCreateSerializer (TaggitSerializer , serializers .HyperlinkedModelSerializer ):
303430 review_requested_by = serializers .HyperlinkedRelatedField (
304431 queryset = Dojo_User .objects .all (),
305432 view_name = 'user-detail' ,
@@ -330,6 +457,7 @@ class FindingCreateSerializer(serializers.HyperlinkedModelSerializer):
330457 queryset = Test_Type .objects .all (),
331458 many = True )
332459 url = serializers .CharField ()
460+ tags = TagListSerializerField (required = False )
333461
334462 class Meta :
335463 model = Finding
@@ -418,7 +546,7 @@ class Meta:
418546 fields = '__all__'
419547
420548
421- class ImportScanSerializer (serializers .Serializer ):
549+ class ImportScanSerializer (TaggitSerializer , serializers .Serializer ):
422550 scan_date = serializers .DateField ()
423551 minimum_severity = serializers .ChoiceField (
424552 choices = SEVERITY_CHOICES ,
@@ -427,14 +555,14 @@ class ImportScanSerializer(serializers.Serializer):
427555 verified = serializers .BooleanField (default = True )
428556 scan_type = serializers .ChoiceField (
429557 choices = ImportScanForm .SCAN_TYPE_CHOICES )
430- tags = serializers .CharField ()
431558 file = serializers .FileField ()
432559 engagement = serializers .HyperlinkedRelatedField (
433560 view_name = 'engagement-detail' ,
434561 queryset = Engagement .objects .all ())
435562 lead = serializers .HyperlinkedRelatedField (
436563 view_name = 'user-detail' ,
437564 queryset = User .objects .all ())
565+ tags = TagListSerializerField (required = False )
438566
439567 def save (self ):
440568 data = self .validated_data
@@ -456,8 +584,6 @@ def save(self):
456584 pass
457585
458586 test .save ()
459- test .tags = data ['tags' ]
460-
461587 try :
462588 parser = import_parser_factory (data ['file' ],
463589 test ,
@@ -516,8 +642,8 @@ def save(self):
516642
517643 item .endpoints .add (ep )
518644
519- if item .unsaved_tags is not None :
520- item .tags = item .unsaved_tags
645+ # if item.unsaved_tags is not None:
646+ # item.tags = item.unsaved_tags
521647 except SyntaxError :
522648 raise Exception ('Parser SyntaxError' )
523649
@@ -530,7 +656,7 @@ def validate_scan_data(self, value):
530656 return value
531657
532658
533- class ReImportScanSerializer (serializers .Serializer ):
659+ class ReImportScanSerializer (TaggitSerializer , serializers .Serializer ):
534660 scan_date = serializers .DateField ()
535661 minimum_severity = serializers .ChoiceField (
536662 choices = SEVERITY_CHOICES ,
@@ -539,7 +665,7 @@ class ReImportScanSerializer(serializers.Serializer):
539665 verified = serializers .BooleanField (default = True )
540666 scan_type = serializers .ChoiceField (
541667 choices = ImportScanForm .SCAN_TYPE_CHOICES )
542- tags = serializers . CharField ( )
668+ tags = TagListSerializerField ( required = False )
543669 file = serializers .FileField ()
544670 test = serializers .HyperlinkedRelatedField (
545671 view_name = 'test-detail' ,
@@ -650,8 +776,8 @@ def save(self):
650776 product = test .engagement .product )
651777 finding .endpoints .add (ep )
652778
653- if item .unsaved_tags :
654- finding .tags = item .unsaved_tags
779+ # if item.unsaved_tags:
780+ # finding.tags = item.unsaved_tags
655781
656782 to_mitigate = set (original_items ) - set (new_items )
657783 for finding in to_mitigate :
0 commit comments