22# -*-coding:UTF-8 -*
33import json
44import os
5- import logging
65import logging .config
76import re
87import sys
@@ -1827,6 +1826,12 @@ def get_meta(self, options=set()):
18271826 meta ['nb_match' ] = self .get_nb_match ()
18281827 if 'nb_objs' in options :
18291828 meta ['nb_objs' ] = self .get_nb_objs ()
1829+ if 'objs_stats' in options :
1830+ if 'nb_objs' in meta :
1831+ total = meta ['nb_objs' ]
1832+ else :
1833+ total = None
1834+ meta ['objs_stats' ] = self .get_objs_stats (total = total )
18301835 if 'org' in options :
18311836 meta ['org' ] = self .get_org ()
18321837 if 'org_name' in options :
@@ -1912,6 +1917,12 @@ def get_nb_objs(self):
19121917 objs [obj_type ] = nb
19131918 return objs
19141919
1920+ def get_nb_total_objs (self ):
1921+ nb = 0
1922+ for obj_type in get_objects_retro_hunted ():
1923+ nb += self .get_nb_objs_by_type (obj_type )
1924+ return nb
1925+
19151926 def get_objs (self ):
19161927 objs = []
19171928 for obj_type in get_objects_retro_hunted ():
@@ -1920,20 +1931,102 @@ def get_objs(self):
19201931 objs .append ((obj_type , subtype , obj_id ))
19211932 return objs
19221933
1934+ def is_retro_hunted_obj (self , obj_gid ):
1935+ return r_tracker .sismember (f'obj:retro_hunts:{ obj_gid } ' , self .uuid )
1936+
19231937 def add (self , obj_type , subtype , obj_id ):
19241938 # match by object type:
19251939 r_tracker .sadd (f'retro_hunt:objs:{ self .uuid } :{ obj_type } ' , f'{ subtype } :{ obj_id } ' )
19261940 # MAP object -> retro hunt
19271941 r_tracker .sadd (f'obj:retro_hunts:{ obj_type } :{ subtype } :{ obj_id } ' , self .uuid )
19281942 self ._incr_nb_match ()
19291943
1930- def remove (self , obj_type , subtype , obj_id ):
1944+ def remove (self , obj_gid ):
1945+ obj_type , subtype , obj_id = obj_gid .split (':' , 2 )
19311946 # match by object type:
19321947 r_tracker .srem (f'retro_hunt:objs:{ self .uuid } :{ obj_type } ' , f'{ subtype } :{ obj_id } ' )
19331948 # MAP object -> retro hunt
1934- r_tracker .srem (f'obj:retro_hunts:{ obj_type } :{ subtype } :{ obj_id } ' , self .uuid )
1949+ r_tracker .srem (f'obj:retro_hunts:{ obj_gid } ' , self .uuid )
1950+ # obj status
1951+ self .delete_obj_status (obj_gid )
19351952 self ._decr_nb_match ()
19361953
1954+ def get_nb_objs_read (self ):
1955+ return r_tracker .scard (f'retro_hunt:objs:read:{ self .uuid } ' )
1956+
1957+ def get_objs_done (self ):
1958+ return r_tracker .smembers (f'retro_hunt:objs:done:{ self .uuid } ' )
1959+
1960+ def get_nb_objs_done (self ):
1961+ return r_tracker .scard (f'retro_hunt:objs:done:{ self .uuid } ' )
1962+
1963+ def get_objs_rejected (self ):
1964+ return r_tracker .smembers (f'retro_hunt:objs:fp:{ self .uuid } ' )
1965+
1966+ def get_nb_objs_rejected (self ):
1967+ return r_tracker .scard (f'retro_hunt:objs:fp:{ self .uuid } ' )
1968+
1969+ def get_objs_stats (self , total = None ):
1970+ done = self .get_nb_objs_done ()
1971+ fp = self .get_nb_objs_rejected ()
1972+ read = self .get_nb_objs_read ()
1973+ if total :
1974+ nb = 0
1975+ for nb_obj in total :
1976+ nb += total [nb_obj ]
1977+ else :
1978+ nb = self .get_nb_total_objs ()
1979+ unread = nb - done - fp - read
1980+ return {'done' : done , 'fp' : fp , 'read' : read , 'unread' : unread }
1981+
1982+ def is_obj_read (self , obj_gid ):
1983+ return r_tracker .sismember (f'retro_hunt:objs:read:{ self .uuid } ' , obj_gid )
1984+
1985+ def is_obj_done (self , obj_gid ):
1986+ return r_tracker .sismember (f'retro_hunt:objs:done:{ self .uuid } ' , obj_gid )
1987+
1988+ def is_obj_rejected (self , obj_gid ):
1989+ return r_tracker .sismember (f'retro_hunt:objs:fp:{ self .uuid } ' , obj_gid )
1990+
1991+ def get_obj_status (self , obj_gid ):
1992+ if self .is_obj_read (obj_gid ):
1993+ return 'read'
1994+ elif self .is_obj_done (obj_gid ):
1995+ return 'done'
1996+ elif self .is_obj_rejected (obj_gid ):
1997+ return 'rejected'
1998+ else :
1999+ return 'unread'
2000+
2001+ def obj_read (self , obj_gid ):
2002+ self .obj_undone (obj_gid )
2003+ self .obj_unreject (obj_gid )
2004+ r_tracker .sadd (f'retro_hunt:objs:read:{ self .uuid } ' , obj_gid )
2005+
2006+ def obj_unread (self , obj_gid ):
2007+ r_tracker .srem (f'retro_hunt:objs:read:{ self .uuid } ' , obj_gid )
2008+
2009+ def obj_done (self , obj_gid ):
2010+ self .obj_unread (obj_gid )
2011+ self .obj_unreject (obj_gid )
2012+ r_tracker .sadd (f'retro_hunt:objs:done:{ self .uuid } ' , obj_gid )
2013+
2014+ def obj_undone (self , obj_gid ):
2015+ r_tracker .srem (f'retro_hunt:objs:done:{ self .uuid } ' , obj_gid )
2016+
2017+ def obj_reject (self , obj_gid ):
2018+ self .obj_unread (obj_gid )
2019+ self .obj_undone (obj_gid )
2020+ r_tracker .sadd (f'retro_hunt:objs:fp:{ self .uuid } ' , obj_gid )
2021+
2022+ def obj_unreject (self , obj_gid ):
2023+ r_tracker .srem (f'retro_hunt:objs:fp:{ self .uuid } ' , obj_gid )
2024+
2025+ def delete_obj_status (self , obj_gid ):
2026+ self .obj_unread (obj_gid )
2027+ self .obj_undone (obj_gid )
2028+ self .obj_unreject (obj_gid )
2029+
19372030 def create (self , org_uuid , user_id , level , name , rule , description = None , filters = [], mails = [], tags = [], timeout = 30 , state = 'pending' ):
19382031 if self .exists ():
19392032 raise Exception ('Error: Retro Hunt Task already exists' )
@@ -1976,6 +2069,10 @@ def delete_objs(self):
19762069 r_tracker .srem (f'retro_hunt:objs:{ self .uuid } :{ obj_type } ' , f'{ subtype } :{ obj_id } ' )
19772070 # MAP object -> retro hunt
19782071 r_tracker .srem (f'obj:retro_hunts:{ obj_type } :{ subtype } :{ obj_id } ' , self .uuid )
2072+ # objs status
2073+ r_tracker .delete (f'retro_hunts:objs:read:{ self .uuid } ' )
2074+ r_tracker .delete (f'retro_hunts:objs:done:{ self .uuid } ' )
2075+ r_tracker .delete (f'retro_hunts:objs:fp:{ self .uuid } ' )
19792076
19802077 def delete (self ):
19812078 if self .is_running () and self .get_state () not in ['completed' , 'paused' ]:
@@ -2092,13 +2189,13 @@ def get_retro_hunt_metas(trackers_uuid):
20922189def is_obj_retro_hunted (obj_type , subtype , obj_id ):
20932190 return r_tracker .exists (f'obj:retro_hunts:{ obj_type } :{ subtype } :{ obj_id } ' )
20942191
2095- def get_obj_retro_hunts (obj_type , subtype , obj_id ):
2096- return r_tracker .smembers (f'obj:retro_hunts:{ obj_type } : { subtype } : { obj_id } ' )
2192+ def get_obj_retro_hunts (obj_gid ):
2193+ return r_tracker .smembers (f'obj:retro_hunts:{ obj_gid } ' )
20972194
2098- def delete_obj_retro_hunts (obj_type , subtype , obj_id ):
2099- for retro_uuid in get_obj_retro_hunts (obj_type , subtype , obj_id ):
2195+ def delete_obj_retro_hunts (obj_gid ):
2196+ for retro_uuid in get_obj_retro_hunts (obj_gid ):
21002197 retro_hunt = RetroHunt (retro_uuid )
2101- retro_hunt .remove (obj_type , subtype , obj_id )
2198+ retro_hunt .remove (obj_gid )
21022199
21032200#### ACL ####
21042201
@@ -2153,7 +2250,7 @@ def api_validate_rule_to_add(rule, rule_type):
21532250 if rule_type == 'yara_custom' :
21542251 valid_yara_rule , error = is_valid_yara_rule (rule )
21552252 if not valid_yara_rule :
2156- return {"status" : "error" , "reason" : f"Invalid Yara Rule: { e } " }, 400
2253+ return {"status" : "error" , "reason" : f"Invalid Yara Rule: { error } " }, 400
21572254 elif rule_type == 'yara_default' :
21582255 if not is_valid_default_yara_rule (rule ):
21592256 return {"status" : "error" , "reason" : "The Yara Rule doesn't exist" }, 400
@@ -2256,6 +2353,61 @@ def api_delete_retro_hunt_task(user_org, user_id, user_role, task_uuid):
22562353 else :
22572354 return retro_hunt .delete (), 200
22582355
2356+ def api_retro_hunt_object_status_done (data , user_org , user_id , user_role ):
2357+ retro_uuid = data .get ('uuid' )
2358+ res = api_check_retro_hunt_acl (retro_uuid , user_org , user_id , user_role , 'edit' )
2359+ if res :
2360+ return res
2361+ retro_hunt = RetroHunt (retro_uuid )
2362+ object_gid = data .get ('gid' )
2363+ if not retro_hunt .is_retro_hunted_obj (object_gid ):
2364+ return {"status" : "error" , "reason" : "Not Retro Hunted Object" }, 404
2365+ return retro_hunt .obj_done (object_gid ), 200
2366+
2367+ def api_retro_hunt_object_status_reject (data , user_org , user_id , user_role ):
2368+ retro_uuid = data .get ('uuid' )
2369+ res = api_check_retro_hunt_acl (retro_uuid , user_org , user_id , user_role , 'edit' )
2370+ if res :
2371+ return res
2372+ retro_hunt = RetroHunt (retro_uuid )
2373+ object_gid = data .get ('gid' )
2374+ if not retro_hunt .is_retro_hunted_obj (object_gid ):
2375+ return {"status" : "error" , "reason" : "Not Retro Hunted Object" }, 404
2376+ return retro_hunt .obj_reject (object_gid ), 200
2377+
2378+ def api_retro_hunt_object_status_unread (data , user_org , user_id , user_role ):
2379+ retro_uuid = data .get ('uuid' )
2380+ res = api_check_retro_hunt_acl (retro_uuid , user_org , user_id , user_role , 'edit' )
2381+ if res :
2382+ return res
2383+ retro_hunt = RetroHunt (retro_uuid )
2384+ object_gid = data .get ('gid' )
2385+ if not retro_hunt .is_retro_hunted_obj (object_gid ):
2386+ return {"status" : "error" , "reason" : "Not Retro Hunted Object" }, 404
2387+ return retro_hunt .delete_obj_status (object_gid ), 200
2388+
2389+ def api_retro_hunt_object_status_read (data , user_org , user_id , user_role ):
2390+ retro_uuid = data .get ('uuid' )
2391+ res = api_check_retro_hunt_acl (retro_uuid , user_org , user_id , user_role , 'edit' )
2392+ if res :
2393+ return res
2394+ retro_hunt = RetroHunt (retro_uuid )
2395+ object_gid = data .get ('gid' )
2396+ if not retro_hunt .is_retro_hunted_obj (object_gid ):
2397+ return {"status" : "error" , "reason" : "Not Retro Hunted Object" }, 404
2398+ return retro_hunt .obj_read (object_gid ), 200
2399+
2400+ def api_retro_hunt_remove_object (data , user_org , user_id , user_role ):
2401+ retro_uuid = data .get ('uuid' )
2402+ res = api_check_retro_hunt_acl (retro_uuid , user_org , user_id , user_role , 'edit' )
2403+ if res :
2404+ return res
2405+ retro_hunt = RetroHunt (retro_uuid )
2406+ object_gid = data .get ('gid' )
2407+ if not retro_hunt .is_retro_hunted_obj (object_gid ):
2408+ return {"status" : "error" , "reason" : "Not Retro Hunted Object" }, 404
2409+ return retro_hunt .remove (object_gid ), 200
2410+
22592411################################################################################
22602412################################################################################
22612413################################################################################
0 commit comments