mirror of https://github.com/CIRCL/AIL-framework
chg: [core] add users organisation + tracker acl by organisation
parent
ee443ff313
commit
69471e0d37
|
@ -186,10 +186,13 @@ class Tracker:
|
|||
def is_level_user(self):
|
||||
return self.get_level() == 0
|
||||
|
||||
def is_level_org(self):
|
||||
return self.get_level() == 2
|
||||
|
||||
def is_level_global(self):
|
||||
return self.get_level() == 1
|
||||
|
||||
def _set_level(self, level, tracker_type=None, user=None):
|
||||
def _set_level(self, level, tracker_type=None, org=None, user=None):
|
||||
if not tracker_type:
|
||||
tracker_type = self.get_type()
|
||||
if level == 0: # user only
|
||||
|
@ -200,6 +203,9 @@ class Tracker:
|
|||
elif level == 1: # global
|
||||
r_tracker.sadd('global:tracker', self.uuid)
|
||||
r_tracker.sadd(f'global:tracker:{tracker_type}', self.uuid)
|
||||
elif level == 2: # org only
|
||||
r_tracker.sadd(f'org:tracker:{org}', self.uuid)
|
||||
r_tracker.sadd(f'org:tracker:{org}:{tracker_type}', self.uuid)
|
||||
self._set_field('level', level)
|
||||
|
||||
def get_filters(self):
|
||||
|
@ -252,6 +258,9 @@ class Tracker:
|
|||
def _del_mails(self):
|
||||
r_tracker.delete(f'tracker:mail:{self.uuid}')
|
||||
|
||||
def get_org(self):
|
||||
return self._get_field('org')
|
||||
|
||||
def get_user(self):
|
||||
return self._get_field('user_id')
|
||||
|
||||
|
@ -285,6 +294,8 @@ class Tracker:
|
|||
'date': self.get_date(),
|
||||
'first_seen': self.get_first_seen(),
|
||||
'last_seen': self.get_last_seen()}
|
||||
if 'org' in options:
|
||||
meta['org'] = self.get_org()
|
||||
if 'user' in options:
|
||||
meta['user'] = self.get_user()
|
||||
if 'level' in options:
|
||||
|
@ -391,7 +402,7 @@ class Tracker:
|
|||
|
||||
# TODO escape custom tags
|
||||
# TODO escape mails ????
|
||||
def create(self, tracker_type, to_track, user_id, level, description=None, filters={}, tags=[], mails=[], webhook=None):
|
||||
def create(self, tracker_type, to_track, org, user_id, level, description=None, filters={}, tags=[], mails=[], webhook=None):
|
||||
if self.exists():
|
||||
raise Exception('Error: Tracker already exists')
|
||||
|
||||
|
@ -413,6 +424,7 @@ class Tracker:
|
|||
self._set_field('tracked', to_track)
|
||||
self._set_field('type', tracker_type)
|
||||
self._set_field('date', datetime.date.today().strftime("%Y%m%d"))
|
||||
self._set_field('org', org)
|
||||
self._set_field('user_id', user_id)
|
||||
if description:
|
||||
self._set_field('description', escape(description))
|
||||
|
@ -426,8 +438,10 @@ class Tracker:
|
|||
r_tracker.sadd('trackers:all', self.uuid)
|
||||
r_tracker.sadd(f'trackers:all:{tracker_type}', self.uuid)
|
||||
|
||||
|
||||
|
||||
# TRACKER LEVEL
|
||||
self._set_level(level, tracker_type=tracker_type, user=user_id)
|
||||
self._set_level(level, tracker_type=tracker_type, org=org, user=user_id)
|
||||
|
||||
# create tracker tags list
|
||||
if tags:
|
||||
|
@ -454,7 +468,7 @@ class Tracker:
|
|||
trigger_trackers_refresh(tracker_type)
|
||||
return self.uuid
|
||||
|
||||
def edit(self, tracker_type, to_track, level, description=None, filters={}, tags=[], mails=[], webhook=None):
|
||||
def edit(self, tracker_type, to_track, level, org, description=None, filters={}, tags=[], mails=[], webhook=None): # TODO ADMIN: EDIT ORG UUID
|
||||
|
||||
# edit tracker
|
||||
old_type = self.get_type()
|
||||
|
@ -481,9 +495,14 @@ class Tracker:
|
|||
# LEVEL
|
||||
if old_level == 0:
|
||||
r_tracker.srem(f'user:tracker:{user_id}:{old_type}', self.uuid)
|
||||
r_tracker.srem(f'user:tracker:{user_id}', self.uuid)
|
||||
elif old_level == 1:
|
||||
r_tracker.srem(f'global:tracker:{old_type}', self.uuid)
|
||||
self._set_level(level, tracker_type=tracker_type, user=user_id)
|
||||
r_tracker.srem(f'global:tracker', self.uuid)
|
||||
elif old_level == 2:
|
||||
r_tracker.srem(f'org:tracker:{self.get_org()}:{old_type}', self.uuid)
|
||||
r_tracker.srem(f'org:tracker:{self.get_org()}', self.uuid)
|
||||
self._set_level(level, tracker_type=tracker_type, org=org, user=user_id)
|
||||
# Delete OLD YARA Rule File
|
||||
if old_type == 'yara':
|
||||
if not is_default_yara_rule(old_to_track):
|
||||
|
@ -506,11 +525,16 @@ class Tracker:
|
|||
|
||||
# Same Type
|
||||
elif level != old_level:
|
||||
if level == 0:
|
||||
r_tracker.srem('global:tracker', self.uuid)
|
||||
elif level == 1:
|
||||
if old_level == 0:
|
||||
r_tracker.srem(f'user:tracker:{user_id}', self.uuid)
|
||||
self._set_level(level, tracker_type=tracker_type, user=user_id)
|
||||
r_tracker.srem(f'user:tracker:{user_id}:{tracker_type}', self.uuid)
|
||||
elif old_level == 1:
|
||||
r_tracker.srem('global:tracker', self.uuid)
|
||||
r_tracker.srem(f'global:tracker:{tracker_type}', self.uuid)
|
||||
elif old_level == 2:
|
||||
r_tracker.srem(f'org:tracker:{self.get_org()}', self.uuid)
|
||||
r_tracker.srem(f'org:tracker:{self.get_org()}:{tracker_type}', self.uuid)
|
||||
self._set_level(level, tracker_type=tracker_type, org=org, user=user_id)
|
||||
|
||||
# To Track Edited
|
||||
if to_track != old_to_track:
|
||||
|
@ -589,21 +613,25 @@ class Tracker:
|
|||
elif level == 1: # global
|
||||
r_tracker.srem('global:tracker', self.uuid)
|
||||
r_tracker.srem(f'global:tracker:{tracker_type}', self.uuid)
|
||||
elif level == 2: # TODO ORG check delete permission
|
||||
org = self.get_org()
|
||||
r_tracker.srem(f'org:tracker:{org}', self.uuid)
|
||||
r_tracker.srem(f'org:tracker:{org}:{tracker_type}', self.uuid)
|
||||
|
||||
# meta
|
||||
r_tracker.delete(f'tracker:{self.uuid}')
|
||||
trigger_trackers_refresh(tracker_type)
|
||||
|
||||
|
||||
def create_tracker(tracker_type, to_track, user_id, level, description=None, filters={}, tags=[], mails=[], webhook=None, tracker_uuid=None):
|
||||
def create_tracker(tracker_type, to_track, org, user_id, level, description=None, filters={}, tags=[], mails=[], webhook=None, tracker_uuid=None):
|
||||
if not tracker_uuid:
|
||||
tracker_uuid = str(uuid.uuid4())
|
||||
tracker = Tracker(tracker_uuid)
|
||||
return tracker.create(tracker_type, to_track, user_id, level, description=description, filters=filters, tags=tags,
|
||||
return tracker.create(tracker_type, to_track, org, user_id, level, description=description, filters=filters, tags=tags,
|
||||
mails=mails, webhook=webhook)
|
||||
|
||||
def _re_create_tracker(tracker_type, tracker_uuid, to_track, user_id, level, description=None, filters={}, tags=[], mails=[], webhook=None, first_seen=None, last_seen=None):
|
||||
create_tracker(tracker_type, to_track, user_id, level, description=description, filters=filters,
|
||||
def _re_create_tracker(tracker_type, tracker_uuid, to_track, org, user_id, level, description=None, filters={}, tags=[], mails=[], webhook=None, first_seen=None, last_seen=None):
|
||||
create_tracker(tracker_type, to_track, org, user_id, level, description=description, filters=filters,
|
||||
tags=tags, mails=mails, webhook=webhook, tracker_uuid=tracker_uuid)
|
||||
|
||||
def get_trackers_types():
|
||||
|
@ -649,6 +677,12 @@ def get_user_trackers(user_id, tracker_type=None):
|
|||
else:
|
||||
return r_tracker.smembers(f'user:tracker:{user_id}')
|
||||
|
||||
def get_org_trackers(org, tracker_type=None):
|
||||
if tracker_type:
|
||||
return r_tracker.smembers(f'org:tracker:{org}:{tracker_type}')
|
||||
else:
|
||||
return r_tracker.smembers(f'org:tracker:{org}')
|
||||
|
||||
def get_nb_global_trackers(tracker_type=None):
|
||||
if tracker_type:
|
||||
return r_tracker.scard(f'global:tracker:{tracker_type}')
|
||||
|
@ -661,6 +695,13 @@ def get_nb_user_trackers(user_id, tracker_type=None):
|
|||
else:
|
||||
return r_tracker.scard(f'user:tracker:{user_id}')
|
||||
|
||||
def get_nb_org_trackers(org, tracker_type=None):
|
||||
if tracker_type:
|
||||
return r_tracker.scard(f'org:tracker:{org}:{tracker_type}')
|
||||
else:
|
||||
return r_tracker.scard(f'org:tracker:{org}')
|
||||
|
||||
|
||||
def get_user_trackers_meta(user_id, tracker_type=None):
|
||||
metas = []
|
||||
for tracker_uuid in get_user_trackers(user_id, tracker_type=tracker_type):
|
||||
|
@ -675,6 +716,13 @@ def get_global_trackers_meta(tracker_type=None):
|
|||
metas.append(tracker.get_meta(options={'description', 'mails', 'sparkline', 'tags'}))
|
||||
return metas
|
||||
|
||||
def get_org_trackers_meta(user_org, tracker_type=None):
|
||||
metas = []
|
||||
for tracker_uuid in get_org_trackers(user_org, tracker_type=tracker_type):
|
||||
tracker = Tracker(tracker_uuid)
|
||||
metas.append(tracker.get_meta(options={'description', 'mails', 'sparkline', 'tags'}))
|
||||
return metas
|
||||
|
||||
def get_users_trackers_meta():
|
||||
trackers = []
|
||||
for tracker_uuid in get_trackers():
|
||||
|
@ -683,6 +731,14 @@ def get_users_trackers_meta():
|
|||
trackers.append(tracker.get_meta(options={'mails', 'sparkline', 'tags'}))
|
||||
return trackers
|
||||
|
||||
def get_orgs_trackers_meta():
|
||||
trackers = []
|
||||
for tracker_uuid in get_trackers():
|
||||
tracker = Tracker(tracker_uuid)
|
||||
if tracker.is_level_org():
|
||||
trackers.append(tracker.get_meta(options={'mails', 'sparkline', 'tags'}))
|
||||
return trackers
|
||||
|
||||
def get_trackers_graph_by_day(l_trackers, num_day=31, date_from=None, date_to=None):
|
||||
if date_from and date_to:
|
||||
date_range = Date.substract_date(date_from, date_to)
|
||||
|
@ -725,13 +781,14 @@ def get_user_dashboard(user_id): # TODO SORT + REMOVE OLDER ROWS (trim)
|
|||
|
||||
return trackers
|
||||
|
||||
def get_trackers_stats(user_id):
|
||||
def get_trackers_stats(user_org, user_id):
|
||||
stats = {'all': 0}
|
||||
for tracker_type in get_trackers_types():
|
||||
nb_global = get_nb_global_trackers(tracker_type=tracker_type)
|
||||
nb_user = get_nb_user_trackers(user_id, tracker_type=tracker_type)
|
||||
stats[tracker_type] = nb_global + nb_user
|
||||
stats['all'] += nb_global + nb_user
|
||||
nb_org = get_nb_org_trackers(user_org, tracker_type=tracker_type)
|
||||
stats[tracker_type] = nb_global + nb_user + nb_org
|
||||
stats['all'] += nb_global + nb_user + nb_org
|
||||
return stats
|
||||
|
||||
|
||||
|
@ -789,7 +846,7 @@ def api_check_tracker_uuid(tracker_uuid):
|
|||
return {"status": "error", "reason": "Unknown uuid"}, 404
|
||||
return None
|
||||
|
||||
def api_check_tracker_acl(tracker_uuid, user_id):
|
||||
def api_check_tracker_acl(tracker_uuid, user_org, user_id):
|
||||
res = api_check_tracker_uuid(tracker_uuid)
|
||||
if res:
|
||||
return res
|
||||
|
@ -797,31 +854,45 @@ def api_check_tracker_acl(tracker_uuid, user_id):
|
|||
if tracker.is_level_user():
|
||||
if tracker.get_user() != user_id or not AILUser(user_id).is_in_role('admin'):
|
||||
return {"status": "error", "reason": "Access Denied"}, 403
|
||||
elif tracker.is_level_org():
|
||||
if tracker.get_org() != user_org or not AILUser(user_id).is_in_role('admin'):
|
||||
return {"status": "error", "reason": "Access Denied"}, 403
|
||||
return None
|
||||
|
||||
def api_is_allowed_to_edit_tracker(tracker_uuid, user_id):
|
||||
if not is_valid_uuid_v4(tracker_uuid):
|
||||
return {"status": "error", "reason": "Invalid uuid"}, 400
|
||||
tracker_creator = r_tracker.hget('tracker:{}'.format(tracker_uuid), 'user_id')
|
||||
if not tracker_creator:
|
||||
return {"status": "error", "reason": "Unknown uuid"}, 404
|
||||
user = AILUser(user_id)
|
||||
if not user.is_in_role('admin') and user_id != tracker_creator:
|
||||
def api_is_allowed_to_edit_tracker(tracker_uuid, user_org, user_id):
|
||||
res = api_check_tracker_uuid(tracker_uuid)
|
||||
if res:
|
||||
return res
|
||||
tracker = Tracker(tracker_uuid)
|
||||
if tracker.is_level_user():
|
||||
if tracker.get_user() != user_id or not AILUser(user_id).is_in_role('admin'):
|
||||
return {"status": "error", "reason": "Access Denied"}, 403
|
||||
return {"uuid": tracker_uuid}, 200
|
||||
|
||||
|
||||
def api_is_allowed_to_access_tracker(tracker_uuid, user_id):
|
||||
if not is_valid_uuid_v4(tracker_uuid):
|
||||
return {"status": "error", "reason": "Invalid uuid"}, 400
|
||||
tracker_creator = r_tracker.hget('tracker:{}'.format(tracker_uuid), 'user_id')
|
||||
if not tracker_creator:
|
||||
return {"status": "error", "reason": "Unknown uuid"}, 404
|
||||
user = AILUser(user_id)
|
||||
if not is_tracker_global_level(tracker_uuid):
|
||||
if not user.is_in_role('admin') and user_id != tracker_creator:
|
||||
elif tracker.is_level_org():
|
||||
if tracker.get_org() != user_org or not AILUser(user_id).is_in_role('admin'):
|
||||
return {"status": "error", "reason": "Access Denied"}, 403
|
||||
else: # global
|
||||
if tracker.get_user() != user_id or not AILUser(user_id).is_in_role('admin'):
|
||||
return {"status": "error", "reason": "Access Denied"}, 403
|
||||
return None
|
||||
|
||||
def api_is_allowed_to_edit_tracker_level(tracker_uuid, user_org, user_id, new_level):
|
||||
tracker = Tracker(tracker_uuid)
|
||||
level = tracker.get_level()
|
||||
if level == new_level:
|
||||
return None
|
||||
# Global Edit
|
||||
if level == 1:
|
||||
if new_level == 0:
|
||||
if tracker.get_user() != user_id or not AILUser(user_id).is_in_role('admin'):
|
||||
return {"status": "error", "reason": "Access Denied"}, 403
|
||||
elif new_level == 2:
|
||||
if tracker.get_org() != user_org or not AILUser(user_id).is_in_role('admin'):
|
||||
return {"status": "error", "reason": "Access Denied"}, 403
|
||||
# Community Edit
|
||||
elif level == 2:
|
||||
if new_level == 0:
|
||||
if tracker.get_user() != user_id or not AILUser(user_id).is_in_role('admin'):
|
||||
return {"status": "error", "reason": "Access Denied"}, 403
|
||||
return {"uuid": tracker_uuid}, 200
|
||||
|
||||
##-- ACL --##
|
||||
|
||||
|
@ -922,7 +993,7 @@ def api_validate_tracker_to_add(to_track, tracker_type, nb_words=1):
|
|||
return {"status": "error", "reason": "Incorrect type"}, 400
|
||||
return {"status": "success", "tracked": to_track, "type": tracker_type}, 200
|
||||
|
||||
def api_add_tracker(dict_input, user_id):
|
||||
def api_add_tracker(dict_input, org, user_id):
|
||||
to_track = dict_input.get('tracked', None)
|
||||
if not to_track:
|
||||
return {"status": "error", "reason": "Tracker not provided"}, 400
|
||||
|
@ -982,17 +1053,17 @@ def api_add_tracker(dict_input, user_id):
|
|||
level = int(level)
|
||||
except TypeError:
|
||||
level = 1
|
||||
if level not in range(0, 1):
|
||||
if level not in range(0, 3):
|
||||
level = 1
|
||||
|
||||
tracker_uuid = create_tracker(tracker_type, to_track, user_id, level, description=description, filters=filters,
|
||||
tracker_uuid = create_tracker(tracker_type, to_track, org, user_id, level, description=description, filters=filters,
|
||||
tags=tags, mails=mails, webhook=webhook)
|
||||
|
||||
return {'tracked': to_track, 'type': tracker_type, 'uuid': tracker_uuid}, 200
|
||||
|
||||
def api_edit_tracker(dict_input, user_id):
|
||||
def api_edit_tracker(dict_input, user_org, user_id):
|
||||
tracker_uuid = dict_input.get('uuid')
|
||||
res = api_check_tracker_acl(tracker_uuid, user_id)
|
||||
res = api_check_tracker_acl(tracker_uuid, user_org, user_id)
|
||||
if res:
|
||||
return res
|
||||
|
||||
|
@ -1004,6 +1075,18 @@ def api_edit_tracker(dict_input, user_id):
|
|||
tracker_type = dict_input.get('type', None)
|
||||
if not tracker_type:
|
||||
return {"status": "error", "reason": "Tracker type not provided"}, 400
|
||||
|
||||
level = dict_input.get('level', 1)
|
||||
try:
|
||||
level = int(level)
|
||||
except TypeError:
|
||||
level = 1
|
||||
if level not in range(0, 3):
|
||||
level = 1
|
||||
res = api_is_allowed_to_edit_tracker_level(tracker_uuid, user_org, user_id, level)
|
||||
if res:
|
||||
return res
|
||||
|
||||
nb_words = dict_input.get('nb_words', 1)
|
||||
description = dict_input.get('description', '')
|
||||
description = escape(description)
|
||||
|
@ -1053,31 +1136,23 @@ def api_edit_tracker(dict_input, user_id):
|
|||
if subtype not in obj_subtypes:
|
||||
return {"status": "error", "reason": "Invalid Tracker Object subtype"}, 400
|
||||
|
||||
level = dict_input.get('level', 1)
|
||||
try:
|
||||
level = int(level)
|
||||
except TypeError:
|
||||
level = 1
|
||||
if level not in range(0, 1):
|
||||
level = 1
|
||||
|
||||
tracker.edit(tracker_type, to_track, level, description=description, filters=filters,
|
||||
tracker.edit(tracker_type, to_track, level, user_org, description=description, filters=filters,
|
||||
tags=tags, mails=mails, webhook=webhook)
|
||||
return {'tracked': to_track, 'type': tracker_type, 'uuid': tracker_uuid}, 200
|
||||
|
||||
|
||||
def api_delete_tracker(data, user_id):
|
||||
def api_delete_tracker(data, user_org, user_id):
|
||||
tracker_uuid = data.get('uuid')
|
||||
res = api_check_tracker_acl(tracker_uuid, user_id)
|
||||
res = api_check_tracker_acl(tracker_uuid, user_org, user_id)
|
||||
if res:
|
||||
return res
|
||||
|
||||
tracker = Tracker(tracker_uuid)
|
||||
return tracker.delete(), 200
|
||||
|
||||
def api_tracker_add_object(data, user_id):
|
||||
def api_tracker_add_object(data, user_org, user_id):
|
||||
tracker_uuid = data.get('uuid')
|
||||
res = api_check_tracker_acl(tracker_uuid, user_id)
|
||||
res = api_check_tracker_acl(tracker_uuid, user_org, user_id)
|
||||
if res:
|
||||
return res
|
||||
tracker = Tracker(tracker_uuid)
|
||||
|
@ -1092,9 +1167,9 @@ def api_tracker_add_object(data, user_id):
|
|||
return {"status": "error", "reason": "Invalid Object"}, 400
|
||||
return tracker.add(obj_type, subtype, obj_id, date=date), 200
|
||||
|
||||
def api_tracker_remove_object(data, user_id):
|
||||
def api_tracker_remove_object(data, user_org, user_id):
|
||||
tracker_uuid = data.get('uuid')
|
||||
res = api_check_tracker_acl(tracker_uuid, user_id)
|
||||
res = api_check_tracker_acl(tracker_uuid, user_org, user_id)
|
||||
if res:
|
||||
return res
|
||||
|
||||
|
@ -1216,7 +1291,6 @@ def get_tracked_yara_rules():
|
|||
else:
|
||||
rules[tracked] = rule
|
||||
to_track[obj_type] = yara.compile(filepaths=rules)
|
||||
print(to_track)
|
||||
return to_track
|
||||
|
||||
def reload_yara_rules():
|
||||
|
|
|
@ -20,8 +20,10 @@ sys.path.append(os.environ['AIL_BIN'])
|
|||
# Import Project packages
|
||||
##################################
|
||||
from lib import ail_logger
|
||||
from lib.ail_core import is_valid_uuid_v4
|
||||
from lib.ConfigLoader import ConfigLoader
|
||||
|
||||
|
||||
# LOGS
|
||||
|
||||
access_logger = ail_logger.get_access_config()
|
||||
|
@ -40,6 +42,145 @@ config_loader = None
|
|||
regex_password = r'^(?=(.*\d){2})(?=.*[a-z])(?=.*[A-Z]).{10,100}$'
|
||||
regex_password = re.compile(regex_password)
|
||||
|
||||
#### ORGANISATIONS ####
|
||||
|
||||
# TODO EDIT
|
||||
# TODO DELETE CHECK
|
||||
|
||||
# TODO ORG View
|
||||
|
||||
# TODO TAGS
|
||||
# TODO TAGS USERS ????
|
||||
|
||||
# TODO Check if ORG name is UNIQUE
|
||||
|
||||
def get_orgs():
|
||||
return r_serv_db.smembers(f'ail:orgs')
|
||||
|
||||
def is_user_in_org(org_uuid, user_id):
|
||||
return r_serv_db.sadd(f'ail:org:{org_uuid}:users', user_id)
|
||||
|
||||
class Organisation:
|
||||
|
||||
def __init__(self, org_uuid):
|
||||
self.uuid = org_uuid
|
||||
|
||||
def exists(self):
|
||||
return r_serv_db.exists(f'ail:org:{self.uuid}')
|
||||
|
||||
def _get_field(self, field):
|
||||
return r_serv_db.hget(f'ail:org:{self.uuid}', field)
|
||||
|
||||
def _set_fields(self, field, value):
|
||||
return r_serv_db.hset(f'ail:org:{self.uuid}', field, value)
|
||||
|
||||
def get_uuid(self):
|
||||
return self.uuid
|
||||
|
||||
def get_date_created(self):
|
||||
date = self._get_field('date_created')
|
||||
|
||||
def get_date_modified(self):
|
||||
date = self._get_field('date_modified')
|
||||
|
||||
def get_description(self):
|
||||
return self._get_field('description')
|
||||
|
||||
def get_name(self):
|
||||
return self._get_field('name')
|
||||
|
||||
def get_nationality(self):
|
||||
return self._get_field('nationality')
|
||||
|
||||
def get_creator(self):
|
||||
return self._get_field('creator')
|
||||
|
||||
def get_org_type(self):
|
||||
return self._get_field('type')
|
||||
|
||||
def get_sector(self):
|
||||
return self._get_field('sector')
|
||||
|
||||
def get_tags(self): # TODO
|
||||
pass
|
||||
|
||||
def get_logo(self):
|
||||
pass
|
||||
|
||||
def get_users(self):
|
||||
return r_serv_db.smembers(f'ail:org:{self.uuid}:users')
|
||||
|
||||
def get_nb_users(self):
|
||||
return r_serv_db.scard(f'ail:org:{self.uuid}:users')
|
||||
|
||||
def get_meta(self, options=set()):
|
||||
meta = {'uuid': self.uuid}
|
||||
if 'name' in options:
|
||||
meta['name'] = self._get_field('name')
|
||||
if 'description' in options:
|
||||
meta['description'] = self._get_field('description')
|
||||
if 'creator' in options:
|
||||
meta['creator'] = self._get_field('creator')
|
||||
if 'date_created' in options:
|
||||
meta['date_created'] = self._get_field('date_created')
|
||||
return meta
|
||||
|
||||
def add_user(self, user_id):
|
||||
if exists_user(user_id) and not get_user_org(user_id):
|
||||
r_serv_db.sadd(f'ail:org:{self.uuid}:users', user_id)
|
||||
r_serv_db.hset(f'ail:user:metadata:{user_id}', 'org', self.uuid)
|
||||
|
||||
def remove_user(self, user_id):
|
||||
r_serv_db.srem(f'ail:org:{self.uuid}:users', user_id)
|
||||
r_serv_db.hdel(f'ail:user:metadata:{user_id}', 'org')
|
||||
|
||||
def remove_users(self):
|
||||
for user_id in self.get_users():
|
||||
self.remove_user(user_id)
|
||||
|
||||
def create(self, creator, name, description=None, nationality=None, sector=None, org_type=None, logo=None):
|
||||
r_serv_db.sadd(f'ail:orgs', self.uuid)
|
||||
|
||||
self._set_fields('creator', creator)
|
||||
self._set_fields('name', name)
|
||||
self._set_fields('description', description)
|
||||
if nationality:
|
||||
self._set_fields('nationality', nationality)
|
||||
if sector:
|
||||
self._set_fields('sector', sector)
|
||||
if org_type:
|
||||
self._set_fields('type', org_type)
|
||||
#if logo:
|
||||
|
||||
current = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
|
||||
self._set_fields('date_created', current)
|
||||
self._set_fields('date_modified', current)
|
||||
|
||||
def edit(self):
|
||||
pass
|
||||
|
||||
def delete(self): # TODO CHANGE ACL ASSOCIATED WITH ORGS -> Tracker, Investigation, objects, ...
|
||||
self.remove_users()
|
||||
r_serv_db.delete(f'ail:org:{self.uuid}')
|
||||
r_serv_db.srem(f'ail:orgs', self.uuid)
|
||||
|
||||
|
||||
|
||||
def exists_org(org_uuid):
|
||||
return r_serv_db.exists(f'ail:org:{org_uuid}')
|
||||
|
||||
def create_org(name, description, uuid=None, nationality=None, sector=None, org_type=None, logo=None): # contacts ?????
|
||||
if uuid is None:
|
||||
uuid = str(uuid4()) # TODO check if is uuidv4
|
||||
else:
|
||||
if exists_org(uuid):
|
||||
raise Exception('Organisation already exists') # TODO CUSTOM ERROR
|
||||
|
||||
org = Organisation(uuid)
|
||||
org.create( name, description, nationality=nationality, sector=sector, org_type=org_type, logo=logo)
|
||||
|
||||
## --ORGANISATIONS-- ##
|
||||
|
||||
#### SESSIONS ####
|
||||
|
||||
def get_sessions():
|
||||
|
@ -266,6 +407,9 @@ def get_user_role(user_id):
|
|||
def exists_user(user_id):
|
||||
return r_serv_db.exists(f'ail:user:metadata:{user_id}')
|
||||
|
||||
def get_user_org(user_id):
|
||||
return r_serv_db.hget(f'ail:user:metadata:{user_id}', 'org')
|
||||
|
||||
def get_user_creator(user_id):
|
||||
return r_serv_db.hget(f'ail:user:metadata:{user_id}', 'creator')
|
||||
|
||||
|
@ -409,6 +553,9 @@ class AILUser(UserMixin):
|
|||
def update_last_login(self):
|
||||
r_serv_db.hset(f'ail:user:metadata:{self.user_id}', 'last_login', datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'))
|
||||
|
||||
def get_org(self):
|
||||
return get_user_org(self.user_id)
|
||||
|
||||
def get_meta(self, options=set()):
|
||||
meta = {'id': self.user_id}
|
||||
if 'creator' in options:
|
||||
|
@ -435,6 +582,8 @@ class AILUser(UserMixin):
|
|||
meta['is_disabled'] = self.is_disabled()
|
||||
if 'is_logged' in options:
|
||||
meta['is_logged'] = is_user_logged(self.user_id)
|
||||
if 'org' in options:
|
||||
meta['org'] = self.get_org()
|
||||
return meta
|
||||
|
||||
## SESSION ##
|
||||
|
@ -549,6 +698,33 @@ class AILUser(UserMixin):
|
|||
|
||||
#### API ####
|
||||
|
||||
def api_get_orgs_meta():
|
||||
meta = {'orgs': []}
|
||||
options = {'date_created', 'description', 'name'}
|
||||
for org_uuid in get_orgs():
|
||||
org = Organisation(org_uuid)
|
||||
meta['orgs'].append(org.get_meta(options=options))
|
||||
return meta
|
||||
|
||||
def api_create_org(creator, org_uuid, name, ip_address, description=None):
|
||||
if not is_valid_uuid_v4(org_uuid):
|
||||
return {'status': 'error', 'reason': 'Invalid UUID'}, 400
|
||||
if exists_org(org_uuid):
|
||||
return {'status': 'error', 'reason': 'Org already exists'}, 400
|
||||
|
||||
org = Organisation(org_uuid)
|
||||
org.create(creator, name, description=description)
|
||||
access_logger.info(f'Created org {org_uuid}', extra={'user_id': creator, 'ip_address': ip_address})
|
||||
return org.get_uuid(), 200
|
||||
|
||||
def api_delete_org(org_uuid, admin_id, ip_address): # TODO check if nothing is linked to this org
|
||||
if not exists_org(org_uuid):
|
||||
return {'status': 'error', 'reason': 'Org not found'}, 404
|
||||
access_logger.warning(f'Deleted org {org_uuid}', extra={'user_id': admin_id, 'ip_address': ip_address})
|
||||
org = Organisation(org_uuid)
|
||||
org.delete()
|
||||
return org_uuid, 200
|
||||
|
||||
def api_get_users_meta():
|
||||
meta = {'users': []}
|
||||
options = {'api_key', 'creator', 'created_at', 'is_logged', 'last_edit', 'last_login', 'last_seen', 'last_seen_api', 'role', '2fa', 'otp_setup'}
|
||||
|
|
|
@ -220,7 +220,7 @@ def trackers_migration():
|
|||
print('TRACKERS MIGRATION...')
|
||||
for tracker_uuid in old_Tracker.get_all_tracker_uuid():
|
||||
meta = get_tracker_metadata(tracker_uuid)
|
||||
Tracker._re_create_tracker(meta['type'], meta['uuid'], meta['tracked'], meta['user_id'], meta['level'],
|
||||
Tracker._re_create_tracker(meta['type'], meta['uuid'], meta['tracked'], 'TEST_ORG', meta['user_id'], meta['level'],
|
||||
tags=meta['tags'], mails=meta['mails'], description=meta['description'],
|
||||
webhook=meta['webhook'], sources=meta['sources'],
|
||||
first_seen=meta['first_seen'], last_seen=meta['last_seen'])
|
||||
|
|
|
@ -9,7 +9,7 @@ import os
|
|||
import sys
|
||||
import json
|
||||
|
||||
from flask import render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort
|
||||
from flask import render_template, jsonify, request, Blueprint, redirect, url_for, Response
|
||||
from flask_login import login_required, current_user
|
||||
|
||||
sys.path.append('modules')
|
||||
|
@ -67,7 +67,7 @@ def get_default_yara_rule_content():
|
|||
def trackers_dashboard():
|
||||
user_id = current_user.get_user_id()
|
||||
trackers = Tracker.get_trackers_dashboard()
|
||||
stats = Tracker.get_trackers_stats(user_id)
|
||||
stats = Tracker.get_trackers_stats(current_user.get_org(), user_id)
|
||||
return render_template("trackers_dashboard.html", trackers=trackers, stats=stats, bootstrap_label=bootstrap_label)
|
||||
|
||||
@hunters.route("/trackers/all")
|
||||
|
@ -75,9 +75,10 @@ def trackers_dashboard():
|
|||
@login_read_only
|
||||
def tracked_menu():
|
||||
user_id = current_user.get_user_id()
|
||||
org_trackers = Tracker.get_org_trackers_meta(current_user.get_org())
|
||||
user_trackers = Tracker.get_user_trackers_meta(user_id)
|
||||
global_trackers = Tracker.get_global_trackers_meta()
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label)
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, org_trackers=org_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label)
|
||||
|
||||
@hunters.route("/trackers/word")
|
||||
@login_required
|
||||
|
@ -85,9 +86,10 @@ def tracked_menu():
|
|||
def tracked_menu_word():
|
||||
tracker_type = 'word'
|
||||
user_id = current_user.get_user_id()
|
||||
org_trackers = Tracker.get_org_trackers_meta(current_user.get_org(), tracker_type='word')
|
||||
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type='word')
|
||||
global_trackers = Tracker.get_global_trackers_meta(tracker_type='word')
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, org_trackers=org_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
|
||||
|
||||
@hunters.route("/trackers/set")
|
||||
@login_required
|
||||
|
@ -95,9 +97,10 @@ def tracked_menu_word():
|
|||
def tracked_menu_set():
|
||||
tracker_type = 'set'
|
||||
user_id = current_user.get_user_id()
|
||||
org_trackers = Tracker.get_org_trackers_meta(current_user.get_org(), tracker_type=tracker_type)
|
||||
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type=tracker_type)
|
||||
global_trackers = Tracker.get_global_trackers_meta(tracker_type=tracker_type)
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, org_trackers=org_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
|
||||
|
||||
@hunters.route("/trackers/regex")
|
||||
@login_required
|
||||
|
@ -105,9 +108,10 @@ def tracked_menu_set():
|
|||
def tracked_menu_regex():
|
||||
tracker_type = 'regex'
|
||||
user_id = current_user.get_user_id()
|
||||
org_trackers = Tracker.get_org_trackers_meta(current_user.get_org(), tracker_type=tracker_type)
|
||||
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type=tracker_type)
|
||||
global_trackers = Tracker.get_global_trackers_meta(tracker_type=tracker_type)
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, org_trackers=org_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
|
||||
|
||||
@hunters.route("/trackers/yara")
|
||||
@login_required
|
||||
|
@ -115,9 +119,10 @@ def tracked_menu_regex():
|
|||
def tracked_menu_yara():
|
||||
tracker_type = 'yara'
|
||||
user_id = current_user.get_user_id()
|
||||
org_trackers = Tracker.get_org_trackers_meta(current_user.get_org(), tracker_type=tracker_type)
|
||||
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type=tracker_type)
|
||||
global_trackers = Tracker.get_global_trackers_meta(tracker_type=tracker_type)
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, org_trackers=org_trackers, global_trackers=global_trackers, bootstrap_label=bootstrap_label, tracker_type=tracker_type)
|
||||
|
||||
@hunters.route("/trackers/typosquatting")
|
||||
@login_required
|
||||
|
@ -125,17 +130,19 @@ def tracked_menu_yara():
|
|||
def tracked_menu_typosquatting():
|
||||
tracker_type = 'typosquatting'
|
||||
user_id = current_user.get_user_id()
|
||||
org_trackers = Tracker.get_org_trackers_meta(current_user.get_org(), tracker_type=tracker_type)
|
||||
user_trackers = Tracker.get_user_trackers_meta(user_id, tracker_type=tracker_type)
|
||||
global_trackers = Tracker.get_global_trackers_meta(tracker_type=tracker_type)
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=global_trackers,
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, org_trackers=org_trackers, global_trackers=global_trackers,
|
||||
bootstrap_label=bootstrap_label, tracker_type=tracker_type)
|
||||
|
||||
@hunters.route("/trackers/admin")
|
||||
@login_required
|
||||
@login_admin
|
||||
def tracked_menu_admin():
|
||||
org_trackers = Tracker.get_orgs_trackers_meta()
|
||||
user_trackers = Tracker.get_users_trackers_meta()
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, global_trackers=[],
|
||||
return render_template("trackersManagement.html", user_trackers=user_trackers, org_trackers=org_trackers, global_trackers=[],
|
||||
bootstrap_label=bootstrap_label)
|
||||
|
||||
|
||||
|
@ -145,8 +152,8 @@ def tracked_menu_admin():
|
|||
def show_tracker():
|
||||
user_id = current_user.get_user_id()
|
||||
tracker_uuid = request.args.get('uuid', None)
|
||||
res = Tracker.api_is_allowed_to_access_tracker(tracker_uuid, user_id)
|
||||
if res[1] != 200: # invalid access
|
||||
res = Tracker.api_check_tracker_acl(tracker_uuid, current_user.get_org(), user_id)
|
||||
if res: # invalid access
|
||||
return Response(json.dumps(res[0], indent=2, sort_keys=True), mimetype='application/json'), res[1]
|
||||
|
||||
date_from = request.args.get('date_from')
|
||||
|
@ -241,10 +248,7 @@ def parse_add_edit_request(request_form):
|
|||
to_track = yara_default_rule
|
||||
tracker_type = 'yara_default'
|
||||
|
||||
if level == 'on':
|
||||
level = 1
|
||||
else:
|
||||
level = 0
|
||||
level = int(level)
|
||||
if mails:
|
||||
mails = mails.split()
|
||||
else:
|
||||
|
@ -293,7 +297,8 @@ def add_tracked_menu():
|
|||
if request.method == 'POST':
|
||||
input_dict = parse_add_edit_request(request.form)
|
||||
user_id = current_user.get_user_id()
|
||||
res = Tracker.api_add_tracker(input_dict, user_id)
|
||||
org = current_user.get_org()
|
||||
res = Tracker.api_add_tracker(input_dict, org, user_id)
|
||||
if res[1] == 200:
|
||||
return redirect(url_for('hunters.trackers_dashboard'))
|
||||
else:
|
||||
|
@ -309,19 +314,19 @@ def add_tracked_menu():
|
|||
@login_required
|
||||
@login_analyst
|
||||
def tracker_edit():
|
||||
user_id = current_user.get_user_id()
|
||||
user_org = current_user.get_org()
|
||||
if request.method == 'POST':
|
||||
input_dict = parse_add_edit_request(request.form)
|
||||
user_id = current_user.get_user_id()
|
||||
res = Tracker.api_edit_tracker(input_dict, user_id)
|
||||
res = Tracker.api_edit_tracker(input_dict, user_org, user_id)
|
||||
if res[1] == 200:
|
||||
return redirect(url_for('hunters.show_tracker', uuid=res[0].get('uuid')))
|
||||
else:
|
||||
return create_json_response(res[0], res[1])
|
||||
else:
|
||||
user_id = current_user.get_user_id()
|
||||
tracker_uuid = request.args.get('uuid', None)
|
||||
res = Tracker.api_is_allowed_to_edit_tracker(tracker_uuid, user_id)
|
||||
if res[1] != 200: # invalid access
|
||||
res = Tracker.api_is_allowed_to_edit_tracker(tracker_uuid, user_org, user_id)
|
||||
if res: # invalid access
|
||||
return Response(json.dumps(res[0], indent=2, sort_keys=True), mimetype='application/json'), res[1]
|
||||
|
||||
tracker = Tracker.Tracker(tracker_uuid)
|
||||
|
@ -352,7 +357,7 @@ def tracker_edit():
|
|||
def tracker_delete():
|
||||
user_id = current_user.get_user_id()
|
||||
tracker_uuid = request.args.get('uuid')
|
||||
res = Tracker.api_delete_tracker({'uuid': tracker_uuid}, user_id)
|
||||
res = Tracker.api_delete_tracker({'uuid': tracker_uuid}, current_user.get_org(), user_id)
|
||||
if res[1] != 200:
|
||||
return create_json_response(res[0], res[1])
|
||||
else:
|
||||
|
@ -365,7 +370,7 @@ def tracker_delete():
|
|||
def get_json_tracker_graph():
|
||||
user_id = current_user.get_user_id()
|
||||
tracker_uuid = request.args.get('uuid')
|
||||
res = Tracker.api_check_tracker_acl(tracker_uuid, user_id)
|
||||
res = Tracker.api_check_tracker_acl(tracker_uuid, current_user.get_org(), user_id)
|
||||
if res:
|
||||
return create_json_response(res[0], res[1])
|
||||
|
||||
|
@ -394,7 +399,7 @@ def tracker_object_add():
|
|||
date = obj.get_date()
|
||||
else:
|
||||
date = request.args.get('date') # TODO check daterange
|
||||
res = Tracker.api_tracker_add_object({'uuid': tracker_uuid, 'gid': object_global_id, 'date': date}, user_id)
|
||||
res = Tracker.api_tracker_add_object({'uuid': tracker_uuid, 'gid': object_global_id, 'date': date}, current_user.get_org(), user_id)
|
||||
if res[1] != 200:
|
||||
return create_json_response(res[0], res[1])
|
||||
else:
|
||||
|
@ -410,7 +415,7 @@ def tracker_object_remove():
|
|||
user_id = current_user.get_user_id()
|
||||
tracker_uuid = request.args.get('uuid')
|
||||
object_global_id = request.args.get('gid')
|
||||
res = Tracker.api_tracker_remove_object({'uuid': tracker_uuid, 'gid': object_global_id}, user_id)
|
||||
res = Tracker.api_tracker_remove_object({'uuid': tracker_uuid, 'gid': object_global_id}, current_user.get_org(), user_id)
|
||||
if res[1] != 200:
|
||||
return create_json_response(res[0], res[1])
|
||||
else:
|
||||
|
@ -426,8 +431,8 @@ def tracker_object_remove():
|
|||
def tracker_objects():
|
||||
user_id = current_user.get_user_id()
|
||||
tracker_uuid = request.args.get('uuid', None)
|
||||
res = Tracker.api_is_allowed_to_edit_tracker(tracker_uuid, user_id)
|
||||
if res[1] != 200: # invalid access
|
||||
res = Tracker.api_is_allowed_to_edit_tracker(tracker_uuid, current_user.get_org(), user_id)
|
||||
if res: # invalid access
|
||||
return Response(json.dumps(res[0], indent=2, sort_keys=True), mimetype='application/json'), res[1]
|
||||
|
||||
tracker = Tracker.Tracker(tracker_uuid)
|
||||
|
|
|
@ -303,6 +303,56 @@ def users_list():
|
|||
|
||||
#############################################
|
||||
|
||||
@settings_b.route("/settings/organisations", methods=['GET'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def organisations_list():
|
||||
meta = ail_users.api_get_orgs_meta()
|
||||
return render_template("orgs_list.html", meta=meta, acl_admin=True)
|
||||
|
||||
@settings_b.route("/settings/create_organisation", methods=['GET'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def create_organisation():
|
||||
meta = {}
|
||||
return render_template("create_org.html", meta=meta, error_mail=False, acl_admin=True)
|
||||
|
||||
@settings_b.route("/settings/create_org_post", methods=['POST'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def create_org_post():
|
||||
# Admin ID
|
||||
admin_id = current_user.get_user_id()
|
||||
|
||||
org_uuid = request.form.get('uuid')
|
||||
name = request.form.get('name')
|
||||
description = request.form.get('description')
|
||||
|
||||
r = ail_users.api_create_org(admin_id, org_uuid, name, request.remote_addr, description=description)
|
||||
if r[1] != 200:
|
||||
return create_json_response(r[0], r[1])
|
||||
else:
|
||||
return redirect(url_for('settings_b.organisations_list'))
|
||||
|
||||
|
||||
# TODO check if uuid4
|
||||
# TODO check name format + length
|
||||
|
||||
@settings_b.route("/settings/delete_org", methods=['GET'])
|
||||
@login_required
|
||||
@login_admin
|
||||
def delete_org():
|
||||
admin_id = current_user.get_user_id()
|
||||
org_uuid = request.args.get('uuid')
|
||||
r = ail_users.api_delete_org(org_uuid, admin_id, request.remote_addr)
|
||||
if r[1] != 200:
|
||||
return create_json_response(r[0], r[1])
|
||||
else:
|
||||
return redirect(url_for('settings_b.organisations_list'))
|
||||
|
||||
|
||||
#############################################
|
||||
|
||||
@settings_b.route("/settings/passivedns", methods=['GET'])
|
||||
@login_required
|
||||
@login_read_only
|
||||
|
|
|
@ -211,12 +211,20 @@
|
|||
|
||||
</div>
|
||||
<div class="col-12 col-xl-3">
|
||||
<div class="custom-control custom-switch mt-1">
|
||||
<input class="custom-control-input" type="checkbox" name="level" id="id_level" {%if dict_tracker%}{%if dict_tracker['level']==1%}checked{%endif%}{%else%}checked{%endif%}>
|
||||
<label class="custom-control-label" for="id_level">
|
||||
<i class="fas fa-users"></i> Show tracker to all Users
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="mt-3" for="level_selector">View Level</label>
|
||||
<select class="custom-select" id="level_selector" name="level">
|
||||
{% if dict_tracker %}
|
||||
<option value="1" {% if dict_tracker['level'] == 1 %}selected{% endif %}><i class="fas fa-users"></i> Global</option>
|
||||
<option value="2" {% if dict_tracker['level'] == 2 %}selected{% endif %}><i class="fas fa-landmark"></i> My Organisation</option>
|
||||
<option value="0" {% if dict_tracker['level'] == 0 %}selected{% endif %}><i class="fas fa-user"></i> My User</option>
|
||||
{% else %}
|
||||
<option value="1" selected><i class="fas fa-users"></i> Global</option>
|
||||
<option value="2"><i class="fas fa-landmark"></i> My Organisation</option>
|
||||
<option value="0"><i class="fas fa-user"></i> My User</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -119,9 +119,11 @@
|
|||
<td class="text-right"><b>Level</b></td>
|
||||
<td>
|
||||
{% if meta['level'] == 0 %}
|
||||
Private
|
||||
{% else %}
|
||||
My User
|
||||
{% elif meta['level'] == 1 %}
|
||||
Global
|
||||
{% elif meta['level'] == 2 %}
|
||||
My Organisation
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -115,6 +115,78 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if org_trackers %}
|
||||
|
||||
<div class="card my-3">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title">Organisation {{ tracker_type }} Trackers</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table id="table_org_trackers" class="table table-striped table-bordered">
|
||||
<thead class="bg-dark text-white">
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Tracker</th>
|
||||
<th>First seen</th>
|
||||
<th>Last seen</th>
|
||||
<th>Emails</th>
|
||||
<th>sparkline</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody style="font-size: 15px;">
|
||||
{% for dict_uuid in org_trackers %}
|
||||
<tr>
|
||||
<td>{{ dict_uuid['type'] }}</td>
|
||||
<td>
|
||||
<span>
|
||||
<a target="_blank" href="{{ url_for('hunters.show_tracker') }}?uuid={{ dict_uuid['uuid'] }}">
|
||||
{% if dict_uuid['tracked'] %}
|
||||
{% if dict_uuid['tracked']|length > 256 %}
|
||||
{{ dict_uuid['tracked'][0:256] }}...
|
||||
{% else %}
|
||||
{{ dict_uuid['tracked'] }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</a>
|
||||
</span>
|
||||
{% if dict_uuid['description'] %}
|
||||
<div><i>{{ dict_uuid['description'] }}</i></div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% for tag in dict_uuid['tags'] %}
|
||||
<a href="{{ url_for('tags_ui.get_obj_by_tags') }}?object_type=item<ags={{ tag }}">
|
||||
<span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }} pull-left">{{ tag }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% if dict_uuid['first_seen'] %}
|
||||
{{ dict_uuid['first_seen'][0:4] }}/{{ dict_uuid['first_seen'][4:6] }}/{{ dict_uuid['first_seen'][6:8] }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if dict_uuid['last_seen'] %}
|
||||
{{ dict_uuid['last_seen'][0:4] }}/{{ dict_uuid['last_seen'][4:6] }}/{{ dict_uuid['last_seen'][6:8] }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% for mail in dict_uuid['mails'] %}
|
||||
{{ mail }}<br>
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td id="sparklines_{{ dict_uuid['uuid'] }}" style="text-align:center;"></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<div class="card my-3">
|
||||
|
@ -203,6 +275,9 @@
|
|||
{% for dict_uuid in user_trackers %}
|
||||
sparkline("sparklines_{{ dict_uuid['uuid'] }}", {{ dict_uuid['sparkline'] }}, {height: 40});
|
||||
{% endfor %}
|
||||
{% for dict_uuid in org_trackers %}
|
||||
sparkline("sparklines_{{ dict_uuid['uuid'] }}", {{ dict_uuid['sparkline'] }}, {height: 40});
|
||||
{% endfor %}
|
||||
{% for dict_uuid in global_trackers %}
|
||||
sparkline("sparklines_{{ dict_uuid['uuid'] }}", {{ dict_uuid['sparkline'] }}, {height: 40});
|
||||
{% endfor %}
|
||||
|
@ -212,6 +287,11 @@
|
|||
"iDisplayLength": 10,
|
||||
"order": [[0, "desc"]]
|
||||
});
|
||||
$('#table_org_trackers').DataTable({
|
||||
"aLengthMenu": [[5, 10, 15, -1], [5, 10, 15, "All"]],
|
||||
"iDisplayLength": 10,
|
||||
"order": [[0, "desc"]]
|
||||
});
|
||||
$('#table_global_trackers').DataTable({
|
||||
"aLengthMenu": [[5, 10, 15, -1], [5, 10, 15, "All"]],
|
||||
"iDisplayLength": 10,
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Create Org - AIL</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/dataTables.bootstrap.min.css') }}" rel="stylesheet">
|
||||
|
||||
<!-- JS -->
|
||||
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/popper.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/dataTables.bootstrap.min.js')}}"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% include 'nav_bar.html' %}
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
{% include 'settings/menu_sidebar.html' %}
|
||||
<div class="col-12 col-lg-10" id="core_content">
|
||||
|
||||
<form class="form-signin" action="{{ url_for('settings_b.create_org_post')}}" autocomplete="off" method="post">
|
||||
|
||||
<h1 class="h3 mt-1 mb-3 text-center text-secondary">{% if meta['uuid'] %}Edit{% else %}Create{% endif %} Org</h1>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="inputUUID">UUID:</label>
|
||||
<input class="form-control" type="text" id="inputUUID" name="uuid" placeholder="UUID" autocomplete="off" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="inputName">Name:</label>
|
||||
<input class="form-control" type="text" id="inputName" name="name" placeholder="Name" autocomplete="off" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="inputDescription">Description:</label>
|
||||
<input class="form-control" type="text" id="inputDescription" name="description" placeholder="Description - (optional)" autocomplete="off">
|
||||
</div>
|
||||
|
||||
<button class="btn btn-lg btn-primary btn-block mt-3" type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$("#nav_create_org").addClass("active");
|
||||
$("#nav_orgs_management").removeClass("text-muted");
|
||||
|
||||
} );
|
||||
|
||||
function toggle_sidebar(){
|
||||
if($('#nav_menu').is(':visible')){
|
||||
$('#nav_menu').hide();
|
||||
$('#side_menu').removeClass('border-right')
|
||||
$('#side_menu').removeClass('col-lg-2')
|
||||
$('#core_content').removeClass('col-lg-10')
|
||||
}else{
|
||||
$('#nav_menu').show();
|
||||
$('#side_menu').addClass('border-right')
|
||||
$('#side_menu').addClass('col-lg-2')
|
||||
$('#core_content').addClass('col-lg-10')
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
|
@ -101,6 +101,23 @@
|
|||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h5 class="d-flex text-muted w-100 py-2" id="nav_orgs_management">
|
||||
<span>Organisations</span>
|
||||
</h5>
|
||||
<ul class="nav flex-md-column flex-row navbar-nav justify-content-between w-100">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{url_for('settings_b.organisations_list')}}" id="nav_orgs_list">
|
||||
<i class="fas fa-landmark"></i>
|
||||
<span>Organisations List</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{url_for('settings_b.create_organisation')}}" id="nav_create_org">
|
||||
<i class="fas fa-plus"></i>
|
||||
<span>Create Organisation</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="d-flex text-muted w-100" id="nav_doc">
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Organisations - AIL</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/dataTables.bootstrap.min.css') }}" rel="stylesheet">
|
||||
|
||||
<!-- JS -->
|
||||
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/popper.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/dataTables.bootstrap.min.js')}}"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% include 'nav_bar.html' %}
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
{% include 'settings/menu_sidebar.html' %}
|
||||
<div class="col-12 col-lg-10" id="core_content">
|
||||
|
||||
<h3>AIL Organisations:</h3>
|
||||
<table id="tableorgs" class="table table-hover table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>uuid</th>
|
||||
<th>Description</th>
|
||||
<th>Created at</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody_last_crawled">
|
||||
{% for org in meta['orgs'] %}
|
||||
<tr>
|
||||
<td>{{org['name']}}</td>
|
||||
<td>{{org['uuid']}}</td>
|
||||
<td>{{org['description']}}</td>
|
||||
<td>
|
||||
{% if org['date_created'] %}
|
||||
{{org['date_created']}}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-start">
|
||||
{# <a class="btn btn-outline-primary ml-3 px-1 py-0" href="{{ url_for('settings_b.edit_user', org_uuid=org['uuid']) }}">#}
|
||||
{# <i class="fas fa-pencil-alt"></i>#}
|
||||
{# </a>#}
|
||||
<a class="btn btn-outline-danger ml-3 px-1 py-0" href="{{ url_for('settings_b.delete_org', uuid=org['uuid']) }}">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$("#nav_orgs_list").addClass("active");
|
||||
$("#nav_orgs_management").removeClass("text-muted");
|
||||
$('#tableorgs').DataTable({
|
||||
"aLengthMenu": [[5, 10, 15, -1], [5, 10, 15, "All"]],
|
||||
"iDisplayLength": 10,
|
||||
"order": [[ 0, "asc" ]]
|
||||
});
|
||||
});
|
||||
|
||||
function toggle_sidebar(){
|
||||
if($('#nav_menu').is(':visible')){
|
||||
$('#nav_menu').hide();
|
||||
$('#side_menu').removeClass('border-right')
|
||||
$('#side_menu').removeClass('col-lg-2')
|
||||
$('#core_content').removeClass('col-lg-10')
|
||||
}else{
|
||||
$('#nav_menu').show();
|
||||
$('#side_menu').addClass('border-right')
|
||||
$('#side_menu').addClass('col-lg-2')
|
||||
$('#core_content').addClass('col-lg-10')
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue