99# Django Imports
1010from django .contrib import messages
1111from django .contrib .auth .decorators import login_required
12- from django .core .exceptions import FieldDoesNotExist
1312from django .http import HttpResponse , HttpResponseRedirect , JsonResponse
1413from django .shortcuts import get_object_or_404 , redirect , render
1514from django .urls import reverse
3635# Using __name__ resolves to ghostwriter.oplog.views
3736logger = logging .getLogger (__name__ )
3837
39-
4038def escape_message (message ):
4139 """
4240 Escape single quotes, double quotes, newlines and other characters
@@ -109,30 +107,6 @@ def post(self, *args, **kwargs):
109107
110108 return JsonResponse (data )
111109
112-
113- def parse_fields (data : dict , entry_field_specs : dict ) -> tuple :
114- """
115- Parse a dictionary of fields and return a list of fields and extra fields.
116-
117- **Parameters**
118-
119- ``data`` (dict)
120- Dictionary of fields
121- ``entry_field_specs`` (dict)
122- Dictionary of field specifications
123- """
124- fields = [field ["name" ] for field in data ]
125- extra_fields = []
126- # Remove any extra fields from the list of fields
127- for field_spec in entry_field_specs :
128- if field_spec ["internal_name" ] in fields :
129- fields .pop (fields .index (field_spec ["internal_name" ]))
130- extra_fields .append (field_spec ["internal_name" ])
131- if extra_fields :
132- fields .append ("extra_fields" )
133- return fields , extra_fields
134-
135-
136110class OplogSanitize (RoleBasedAccessControlMixin , SingleObjectMixin , View ):
137111 """
138112 Sanitize all :model:`oplog.OplogEntry` objects associated with an individual :model:`oplog.Oplog`.
@@ -144,6 +118,20 @@ class OplogSanitize(RoleBasedAccessControlMixin, SingleObjectMixin, View):
144118
145119 model = Oplog
146120
121+ clearable_fields = {
122+ "identifier" ,
123+ "start_date" ,
124+ "end_date" ,
125+ "source_ip" ,
126+ "dest_ip" ,
127+ "tool" ,
128+ "user_context" ,
129+ "description" ,
130+ "output" ,
131+ "comments" ,
132+ "operator_name" ,
133+ }
134+
147135 def test_func (self ):
148136 return verify_user_is_privileged (self .request .user )
149137
@@ -155,17 +143,32 @@ def post(self, *args, **kwargs):
155143 obj = self .get_object ()
156144 data = self .request .POST .get ("fields" , None )
157145 try :
158- json_data = json .loads (data )
146+ fields_json = json .loads (data )
159147 except (json .JSONDecodeError , TypeError ):
160- json_data = None
161-
162- if json_data and len (json_data ) > 0 :
148+ fields_json = []
149+
150+ entry_field_specs = {spec .internal_name : spec for spec in ExtraFieldSpec .for_model (OplogEntry )}
151+ fields = [
152+ field ["name" ]
153+ for field in fields_json
154+ if field ["name" ] == "command"
155+ or field ["name" ] == "tags"
156+ or field ["name" ] in self .clearable_fields
157+ or field ["name" ] in entry_field_specs
158+ ]
159+
160+ bulk_update_fields = [
161+ field ["name" ]
162+ for field in fields_json
163+ if field ["name" ] == "command"
164+ or field ["name" ] == "tags"
165+ or field ["name" ] in self .clearable_fields
166+ ]
167+ if any (field ["name" ] in entry_field_specs for field in fields_json ):
168+ bulk_update_fields .append ("extra_fields" )
169+
170+ if fields :
163171 entries = obj .entries .all ()
164- entry_field_specs = ExtraFieldsSpecSerializer (
165- ExtraFieldSpec .objects .filter (target_model = OplogEntry ._meta .label ), many = True
166- ).data
167- fields , _ = parse_fields (json_data , entry_field_specs )
168-
169172 logger .info (
170173 "Sanitizing log entries for %s %s by request of %s" , obj .__class__ .__name__ , obj .id , self .request .user
171174 )
@@ -176,29 +179,22 @@ def post(self, *args, **kwargs):
176179 try :
177180 for entry in entries :
178181 extra_fields_data = entry .extra_fields
179- for field in json_data :
180- for field_spec in entry_field_specs :
181- if field_spec [ "internal_name" ] == field [ "name" ] :
182- extra_fields_data [ field [ "name" ]] = None
183- else :
184- if field [ "name" ] == "command" :
185- if entry . command :
186- setattr (entry , field [ "name" ], entry . command . split ( " " )[ 0 ] )
187- else :
188- setattr ( entry , field [ "name" ], None )
182+ for field in fields :
183+ if field == "command" :
184+ if entry . command :
185+ setattr ( entry , field , entry . command . split ( " " )[ 0 ])
186+ elif field == "tags" :
187+ entry . tags . clear ()
188+ elif field in self . clearable_fields :
189+ setattr (entry , field , "" )
190+ elif field in entry_field_specs :
191+ extra_fields_data [ field ] = entry_field_specs [ field ]. empty_value ( )
189192 entry .extra_fields = extra_fields_data
190- try :
191- OplogEntry .objects .bulk_update (entries , fields )
192- except FieldDoesNotExist as exception :
193- logger .error ("One of the fields submitted for sanitization does not exist: %s" , exception )
194- data = {
195- "result" : "failed" ,
196- "message" : "One of the fields submitted for sanitization does not exist." ,
197- }
193+ OplogEntry .objects .bulk_update (entries , bulk_update_fields , batch_size = 100 )
198194 except Exception as exception : # pragma: no cover
199195 template = "An exception of type {0} occurred. Arguments:\n {1!r}"
200196 log_message = template .format (type (exception ).__name__ , exception .args )
201- logger .error (log_message )
197+ logger .exception (log_message )
202198 data = {
203199 "result" : "failed" ,
204200 "message" : "An error occurred while sanitizing log entries." ,
0 commit comments