2022-03-07 14:12:01 +00:00
|
|
|
# -*-coding:UTF-8 -*
|
|
|
|
"""
|
|
|
|
Base Class for AIL Objects
|
|
|
|
"""
|
|
|
|
|
|
|
|
##################################
|
|
|
|
# Import External packages
|
|
|
|
##################################
|
|
|
|
import os
|
2023-06-09 09:19:22 +00:00
|
|
|
import logging.config
|
2022-03-07 14:12:01 +00:00
|
|
|
import sys
|
|
|
|
from abc import ABC, abstractmethod
|
2022-11-28 14:01:40 +00:00
|
|
|
from pymisp import MISPObject
|
2022-03-07 14:12:01 +00:00
|
|
|
|
2022-11-28 14:01:40 +00:00
|
|
|
# from flask import url_for
|
2022-03-07 14:12:01 +00:00
|
|
|
|
|
|
|
sys.path.append(os.environ['AIL_BIN'])
|
|
|
|
##################################
|
|
|
|
# Import Project packages
|
|
|
|
##################################
|
2023-06-09 09:19:22 +00:00
|
|
|
from lib import ail_logger
|
2022-09-01 12:04:00 +00:00
|
|
|
from lib import Tag
|
2023-08-18 09:05:21 +00:00
|
|
|
from lib.ConfigLoader import ConfigLoader
|
2022-07-13 13:10:27 +00:00
|
|
|
from lib import Duplicate
|
2024-01-02 16:15:45 +00:00
|
|
|
from lib.correlations_engine import get_nb_correlations, get_correlations, add_obj_correlation, delete_obj_correlation, delete_obj_correlations, exists_obj_correlation, is_obj_correlated, get_nb_correlation_by_correl_type, get_obj_inter_correlation
|
2022-07-08 07:47:47 +00:00
|
|
|
from lib.Investigations import is_object_investigated, get_obj_investigations, delete_obj_investigations
|
2024-06-06 09:26:46 +00:00
|
|
|
from lib.relationships_engine import get_obj_nb_relationships, get_obj_relationships, add_obj_relationship
|
2024-04-10 14:43:54 +00:00
|
|
|
from lib.Language import get_obj_languages, add_obj_language, remove_obj_language, detect_obj_language, get_obj_language_stats, get_obj_translation, set_obj_translation, delete_obj_translation, get_obj_main_language
|
2023-05-04 14:35:56 +00:00
|
|
|
from lib.Tracker import is_obj_tracked, get_obj_trackers, delete_obj_trackers
|
2022-03-07 14:12:01 +00:00
|
|
|
|
2023-06-09 09:19:22 +00:00
|
|
|
logging.config.dictConfig(ail_logger.get_config(name='ail'))
|
2022-03-07 14:12:01 +00:00
|
|
|
|
2023-08-18 09:05:21 +00:00
|
|
|
config_loader = ConfigLoader()
|
|
|
|
# r_cache = config_loader.get_redis_conn("Redis_Cache")
|
|
|
|
r_object = config_loader.get_db_conn("Kvrocks_Objects")
|
|
|
|
config_loader = None
|
|
|
|
|
2022-03-07 14:12:01 +00:00
|
|
|
class AbstractObject(ABC):
|
|
|
|
"""
|
|
|
|
Abstract Object
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, obj_type, id, subtype=None):
|
|
|
|
""" Abstract for all the AIL object
|
|
|
|
|
|
|
|
:param obj_type: object type (item, ...)
|
|
|
|
:param id: Object ID
|
|
|
|
"""
|
|
|
|
self.id = id
|
|
|
|
self.type = obj_type
|
|
|
|
self.subtype = subtype
|
|
|
|
|
2023-06-09 09:19:22 +00:00
|
|
|
self.logger = logging.getLogger(f'{self.__class__.__name__}')
|
|
|
|
|
2022-03-07 14:12:01 +00:00
|
|
|
def get_id(self):
|
|
|
|
return self.id
|
|
|
|
|
|
|
|
def get_type(self):
|
|
|
|
return self.type
|
|
|
|
|
|
|
|
def get_subtype(self, r_str=False):
|
|
|
|
if not self.subtype:
|
|
|
|
if r_str:
|
|
|
|
return ''
|
|
|
|
return self.subtype
|
|
|
|
|
2022-11-28 14:01:40 +00:00
|
|
|
def get_global_id(self):
|
|
|
|
return f'{self.get_type()}:{self.get_subtype(r_str=True)}:{self.get_id()}'
|
|
|
|
|
2024-03-22 10:37:35 +00:00
|
|
|
def get_last_full_date(self):
|
|
|
|
return None
|
|
|
|
|
2023-08-28 14:29:38 +00:00
|
|
|
def get_default_meta(self, tags=False, link=False):
|
2022-03-07 14:12:01 +00:00
|
|
|
dict_meta = {'id': self.get_id(),
|
|
|
|
'type': self.get_type(),
|
2023-06-26 14:28:31 +00:00
|
|
|
'subtype': self.get_subtype(r_str=True)}
|
2022-03-07 14:12:01 +00:00
|
|
|
if tags:
|
2024-02-13 15:13:18 +00:00
|
|
|
dict_meta['tags'] = self.get_tags(r_list=True)
|
2023-08-28 14:29:38 +00:00
|
|
|
if link:
|
|
|
|
dict_meta['link'] = self.get_link()
|
2022-03-07 14:12:01 +00:00
|
|
|
return dict_meta
|
|
|
|
|
2023-08-18 09:05:21 +00:00
|
|
|
def _get_field(self, field):
|
|
|
|
if self.subtype is None:
|
|
|
|
return r_object.hget(f'meta:{self.type}:{self.id}', field)
|
|
|
|
else:
|
|
|
|
return r_object.hget(f'meta:{self.type}:{self.get_subtype(r_str=True)}:{self.id}', field)
|
|
|
|
|
|
|
|
def _set_field(self, field, value):
|
|
|
|
if self.subtype is None:
|
|
|
|
return r_object.hset(f'meta:{self.type}:{self.id}', field, value)
|
|
|
|
else:
|
|
|
|
return r_object.hset(f'meta:{self.type}:{self.get_subtype(r_str=True)}:{self.id}', field, value)
|
|
|
|
|
2022-03-07 14:12:01 +00:00
|
|
|
## Tags ##
|
2022-09-20 14:11:48 +00:00
|
|
|
def get_tags(self, r_list=False):
|
2022-09-01 12:04:00 +00:00
|
|
|
tags = Tag.get_object_tags(self.type, self.id, self.get_subtype(r_str=True))
|
2022-09-20 14:11:48 +00:00
|
|
|
if r_list:
|
|
|
|
tags = list(tags)
|
2022-03-07 14:12:01 +00:00
|
|
|
return tags
|
|
|
|
|
2022-09-01 12:04:00 +00:00
|
|
|
def add_tag(self, tag):
|
|
|
|
Tag.add_object_tag(tag, self.type, self.id, subtype=self.get_subtype(r_str=True))
|
2022-03-07 14:12:01 +00:00
|
|
|
|
2022-11-28 14:01:40 +00:00
|
|
|
def is_tags_safe(self, tags=None):
|
|
|
|
if not tags:
|
|
|
|
tags = self.get_tags()
|
|
|
|
return Tag.is_tags_safe(tags)
|
|
|
|
|
2023-06-09 09:19:22 +00:00
|
|
|
## -Tags- ##
|
2022-03-07 14:12:01 +00:00
|
|
|
|
2023-05-04 14:35:56 +00:00
|
|
|
@abstractmethod
|
|
|
|
def get_content(self):
|
|
|
|
"""
|
|
|
|
Get Object Content
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
2022-11-29 15:01:01 +00:00
|
|
|
## Duplicates ##
|
|
|
|
def get_duplicates(self):
|
|
|
|
return Duplicate.get_obj_duplicates(self.type, self.get_subtype(r_str=True), self.id)
|
|
|
|
|
|
|
|
def add_duplicate(self, algo, similarity, id_2):
|
|
|
|
return Duplicate.add_obj_duplicate(algo, similarity, self.type, self.get_subtype(r_str=True), self.id, id_2)
|
2023-06-09 09:19:22 +00:00
|
|
|
## -Duplicates- ##
|
2022-11-29 15:01:01 +00:00
|
|
|
|
2022-03-07 14:12:01 +00:00
|
|
|
## Investigations ##
|
|
|
|
|
|
|
|
def is_investigated(self):
|
|
|
|
if not self.subtype:
|
|
|
|
is_investigated = is_object_investigated(self.id, self.type)
|
|
|
|
else:
|
|
|
|
is_investigated = is_object_investigated(self.id, self.type, self.subtype)
|
|
|
|
return is_investigated
|
|
|
|
|
|
|
|
def get_investigations(self):
|
|
|
|
if not self.subtype:
|
|
|
|
investigations = get_obj_investigations(self.id, self.type)
|
|
|
|
else:
|
|
|
|
investigations = get_obj_investigations(self.id, self.type, self.subtype)
|
|
|
|
return investigations
|
2022-07-08 07:47:47 +00:00
|
|
|
|
|
|
|
def delete_investigations(self):
|
|
|
|
if not self.subtype:
|
2022-11-28 14:01:40 +00:00
|
|
|
unregistered = delete_obj_investigations(self.id, self.type)
|
2022-07-08 07:47:47 +00:00
|
|
|
else:
|
2022-11-28 14:01:40 +00:00
|
|
|
unregistered = delete_obj_investigations(self.id, self.type, self.subtype)
|
|
|
|
return unregistered
|
2022-07-08 07:47:47 +00:00
|
|
|
|
2023-06-09 09:19:22 +00:00
|
|
|
## -Investigations- ##
|
2022-03-07 14:12:01 +00:00
|
|
|
|
2022-03-11 08:29:48 +00:00
|
|
|
## Trackers ##
|
|
|
|
|
|
|
|
def is_tracked(self):
|
|
|
|
return is_obj_tracked(self.type, self.subtype, self.id)
|
|
|
|
|
|
|
|
def get_trackers(self):
|
2023-05-04 14:35:56 +00:00
|
|
|
return get_obj_trackers(self.type, self.subtype, self.id)
|
2022-03-11 08:29:48 +00:00
|
|
|
|
2022-07-08 07:47:47 +00:00
|
|
|
def delete_trackers(self):
|
|
|
|
return delete_obj_trackers(self.type, self.subtype, self.id)
|
|
|
|
|
2023-06-09 09:19:22 +00:00
|
|
|
## -Trackers- ##
|
2022-03-11 08:29:48 +00:00
|
|
|
|
2022-03-07 14:12:01 +00:00
|
|
|
def _delete(self):
|
|
|
|
# DELETE TAGS
|
2023-05-04 14:35:56 +00:00
|
|
|
Tag.delete_object_tags(self.type, self.get_subtype(r_str=True), self.id)
|
2022-07-08 07:47:47 +00:00
|
|
|
# remove from tracker
|
|
|
|
self.delete_trackers()
|
2023-05-04 14:35:56 +00:00
|
|
|
# remove from retro hunt currently item only TODO
|
2022-07-08 07:47:47 +00:00
|
|
|
# remove from investigations
|
|
|
|
self.delete_investigations()
|
2023-05-04 14:35:56 +00:00
|
|
|
# Delete Correlations
|
|
|
|
delete_obj_correlations(self.type, self.get_subtype(r_str=True), self.id)
|
2022-03-07 14:12:01 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def delete(self):
|
|
|
|
"""
|
|
|
|
Delete Object: used for the Data Retention
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
2022-09-20 14:11:48 +00:00
|
|
|
@abstractmethod
|
|
|
|
def exists(self):
|
|
|
|
"""
|
|
|
|
Exists Object
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
2022-09-01 12:04:00 +00:00
|
|
|
@abstractmethod
|
2022-10-25 14:25:19 +00:00
|
|
|
def get_meta(self, options=set()):
|
2022-09-01 12:04:00 +00:00
|
|
|
"""
|
|
|
|
get Object metadata
|
|
|
|
"""
|
|
|
|
pass
|
2022-03-07 14:12:01 +00:00
|
|
|
|
2022-07-08 07:47:47 +00:00
|
|
|
@abstractmethod
|
|
|
|
def get_link(self, flask_context=False):
|
|
|
|
pass
|
|
|
|
|
2022-03-07 14:12:01 +00:00
|
|
|
@abstractmethod
|
|
|
|
def get_svg_icon(self):
|
|
|
|
"""
|
|
|
|
Get object svg icon
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
2022-07-08 07:47:47 +00:00
|
|
|
def get_misp_object(self):
|
2022-03-07 14:12:01 +00:00
|
|
|
pass
|
|
|
|
|
2022-11-28 14:01:40 +00:00
|
|
|
@staticmethod
|
|
|
|
def get_misp_object_tags(misp_obj):
|
|
|
|
"""
|
|
|
|
:type misp_obj: MISPObject
|
|
|
|
"""
|
|
|
|
if misp_obj.attributes:
|
|
|
|
misp_tags = misp_obj.attributes[0].tags
|
|
|
|
tags = []
|
|
|
|
for tag in misp_tags:
|
|
|
|
tags.append(tag.name)
|
|
|
|
return tags
|
|
|
|
else:
|
|
|
|
return []
|
|
|
|
|
2023-08-18 09:05:21 +00:00
|
|
|
## Correlation ##
|
|
|
|
|
2024-04-24 12:43:11 +00:00
|
|
|
def get_obj_correlations(self, obj_type, obj_subtype, obj_id, filter_types=[]):
|
2022-10-25 14:25:19 +00:00
|
|
|
"""
|
|
|
|
Get object correlation
|
|
|
|
"""
|
2024-04-24 12:43:11 +00:00
|
|
|
return get_correlations(obj_type, obj_subtype, obj_id, filter_types=filter_types)
|
2022-10-25 14:25:19 +00:00
|
|
|
|
|
|
|
def get_correlation(self, obj_type):
|
|
|
|
"""
|
|
|
|
Get object correlation
|
|
|
|
"""
|
2024-10-01 13:12:15 +00:00
|
|
|
return get_correlations(self.type, self.subtype, self.id, filter_types=[obj_type], sanityze=False)
|
2022-10-25 14:25:19 +00:00
|
|
|
|
2024-04-10 14:43:54 +00:00
|
|
|
def get_first_correlation(self, obj_type):
|
|
|
|
correlation = self.get_correlation(obj_type)
|
|
|
|
if correlation.get(obj_type):
|
|
|
|
return f'{obj_type}:{correlation[obj_type].pop()}'
|
|
|
|
|
2023-04-21 08:26:14 +00:00
|
|
|
def get_correlations(self, filter_types=[], unpack=False):
|
2022-08-19 14:53:31 +00:00
|
|
|
"""
|
|
|
|
Get object correlations
|
|
|
|
"""
|
2023-04-21 08:26:14 +00:00
|
|
|
return get_correlations(self.type, self.subtype, self.id, filter_types=filter_types, unpack=unpack)
|
2022-08-19 14:53:31 +00:00
|
|
|
|
2023-01-09 15:03:06 +00:00
|
|
|
def get_nb_correlation(self, correl_type):
|
|
|
|
return get_nb_correlation_by_correl_type(self.type, self.get_subtype(r_str=True), self.id, correl_type)
|
|
|
|
|
2022-11-22 09:47:15 +00:00
|
|
|
def get_nb_correlations(self, filter_types=[]):
|
|
|
|
return get_nb_correlations(self.type, self.subtype, self.id, filter_types=filter_types)
|
|
|
|
|
2022-08-19 14:53:31 +00:00
|
|
|
def add_correlation(self, type2, subtype2, id2):
|
|
|
|
"""
|
|
|
|
Add object correlation
|
|
|
|
"""
|
|
|
|
add_obj_correlation(self.type, self.subtype, self.id, type2, subtype2, id2)
|
|
|
|
|
|
|
|
def exists_correlation(self, type2):
|
|
|
|
"""
|
|
|
|
Check if an object is correlated
|
|
|
|
"""
|
|
|
|
return exists_obj_correlation(self.type, self.subtype, self.id, type2)
|
|
|
|
|
|
|
|
def is_correlated(self, type2, subtype2, id2):
|
|
|
|
"""
|
|
|
|
Check if an object is correlated by another object
|
|
|
|
"""
|
|
|
|
return is_obj_correlated(self.type, self.subtype, self.id, type2, subtype2, id2)
|
|
|
|
|
2023-01-16 15:27:49 +00:00
|
|
|
def are_correlated(self, object2):
|
|
|
|
"""
|
|
|
|
Check if an object is correlated with another Object
|
|
|
|
:type object2 AbstractObject
|
|
|
|
"""
|
|
|
|
return is_obj_correlated(self.type, self.subtype, self.id,
|
|
|
|
object2.get_type(), object2.get_subtype(r_str=True), object2.get_id())
|
|
|
|
|
2024-01-02 16:15:45 +00:00
|
|
|
def get_correlation_iter(self, obj_type2, subtype2, obj_id2, correl_type):
|
|
|
|
return get_obj_inter_correlation(self.type, self.get_subtype(r_str=True), self.id, obj_type2, subtype2, obj_id2, correl_type)
|
|
|
|
|
|
|
|
def get_correlation_iter_obj(self, object2, correl_type):
|
|
|
|
return self.get_correlation_iter(object2.get_type(), object2.get_subtype(r_str=True), object2.get_id(), correl_type)
|
|
|
|
|
2022-08-19 14:53:31 +00:00
|
|
|
def delete_correlation(self, type2, subtype2, id2):
|
|
|
|
"""
|
|
|
|
Get object correlations
|
|
|
|
"""
|
|
|
|
delete_obj_correlation(self.type, self.subtype, self.id, type2, subtype2, id2)
|
2023-08-18 09:05:21 +00:00
|
|
|
|
|
|
|
## -Correlation- ##
|
|
|
|
|
2024-01-26 14:42:46 +00:00
|
|
|
## Relationship ##
|
|
|
|
|
|
|
|
def get_nb_relationships(self, filter=[]):
|
|
|
|
return get_obj_nb_relationships(self.get_global_id())
|
|
|
|
|
2024-06-06 09:26:46 +00:00
|
|
|
def get_obj_relationships(self, relationships=set(), filter_types=set()):
|
|
|
|
return get_obj_relationships(self.get_global_id(), relationships=relationships, filter_types=filter_types)
|
|
|
|
|
2024-08-12 10:14:26 +00:00
|
|
|
def get_first_relationship(self, relationship, filter_type):
|
|
|
|
rel = get_obj_relationships(self.get_global_id(), relationships={relationship}, filter_types={filter_type})
|
|
|
|
if rel:
|
|
|
|
return rel.pop()
|
|
|
|
|
2024-01-26 14:42:46 +00:00
|
|
|
def add_relationship(self, obj2_global_id, relationship, source=True):
|
|
|
|
# is source
|
|
|
|
if source:
|
|
|
|
print(self.get_global_id(), obj2_global_id, relationship)
|
|
|
|
add_obj_relationship(self.get_global_id(), obj2_global_id, relationship)
|
|
|
|
# is target
|
|
|
|
else:
|
|
|
|
add_obj_relationship(obj2_global_id, self.get_global_id(), relationship)
|
|
|
|
|
|
|
|
## -Relationship- ##
|
|
|
|
|
2024-03-25 13:13:16 +00:00
|
|
|
def get_objs_container(self):
|
|
|
|
return set()
|
|
|
|
|
2024-02-14 15:43:29 +00:00
|
|
|
## Language ##
|
|
|
|
|
|
|
|
def get_languages(self):
|
|
|
|
return get_obj_languages(self.type, self.get_subtype(r_str=True), self.id)
|
|
|
|
|
|
|
|
def add_language(self, language):
|
2024-03-25 13:13:16 +00:00
|
|
|
return add_obj_language(language, self.type, self.get_subtype(r_str=True), self.id, objs_containers=self.get_objs_container())
|
2024-02-14 15:43:29 +00:00
|
|
|
|
|
|
|
def remove_language(self, language):
|
2024-03-25 13:13:16 +00:00
|
|
|
return remove_obj_language(language, self.type, self.get_subtype(r_str=True), self.id, objs_containers=self.get_objs_container())
|
2024-02-14 15:43:29 +00:00
|
|
|
|
2024-03-08 14:26:06 +00:00
|
|
|
def edit_language(self, old_language, new_language):
|
2024-03-25 13:13:16 +00:00
|
|
|
if old_language:
|
|
|
|
self.remove_language(old_language)
|
2024-03-08 14:26:06 +00:00
|
|
|
self.add_language(new_language)
|
|
|
|
|
|
|
|
def detect_language(self, field=''):
|
2024-03-25 13:13:16 +00:00
|
|
|
return detect_obj_language(self.type, self.get_subtype(r_str=True), self.id, self.get_content(), objs_containers=self.get_objs_container())
|
|
|
|
|
|
|
|
def get_obj_language_stats(self):
|
|
|
|
return get_obj_language_stats(self.type, self.get_subtype(r_str=True), self.id)
|
2024-02-14 15:43:29 +00:00
|
|
|
|
2024-04-10 14:43:54 +00:00
|
|
|
def get_main_language(self):
|
|
|
|
return get_obj_main_language(self.type, self.get_subtype(r_str=True), self.id)
|
|
|
|
|
2024-02-14 15:43:29 +00:00
|
|
|
def get_translation(self, language, field=''):
|
2024-03-25 13:13:16 +00:00
|
|
|
return get_obj_translation(self.get_global_id(), language, field=field, objs_containers=self.get_objs_container())
|
2024-02-14 15:43:29 +00:00
|
|
|
|
|
|
|
def set_translation(self, language, translation, field=''):
|
|
|
|
return set_obj_translation(self.get_global_id(), language, translation, field=field)
|
2024-01-29 13:36:53 +00:00
|
|
|
|
2024-03-08 14:26:06 +00:00
|
|
|
def delete_translation(self, language, field=''):
|
|
|
|
return delete_obj_translation(self.get_global_id(), language, field=field)
|
2024-01-29 13:36:53 +00:00
|
|
|
|
|
|
|
def translate(self, content=None, field='', source=None, target='en'):
|
|
|
|
global_id = self.get_global_id()
|
|
|
|
if not content:
|
|
|
|
content = self.get_content()
|
2024-03-25 13:13:16 +00:00
|
|
|
translation = get_obj_translation(global_id, target, source=source, content=content, field=field, objs_containers=self.get_objs_container())
|
2024-02-14 15:43:29 +00:00
|
|
|
return translation
|
2024-01-29 13:36:53 +00:00
|
|
|
|
2024-02-14 15:43:29 +00:00
|
|
|
## -Language- ##
|
2024-01-29 13:36:53 +00:00
|
|
|
|
2023-08-18 09:05:21 +00:00
|
|
|
## Parent ##
|
|
|
|
|
|
|
|
def is_parent(self):
|
|
|
|
return r_object.exists(f'child:{self.type}:{self.get_subtype(r_str=True)}:{self.id}')
|
|
|
|
|
|
|
|
def is_children(self):
|
|
|
|
return r_object.hexists(f'meta:{self.type}:{self.get_subtype(r_str=True)}:{self.id}', 'parent')
|
|
|
|
|
|
|
|
def get_parent(self):
|
|
|
|
return r_object.hget(f'meta:{self.type}:{self.get_subtype(r_str=True)}:{self.id}', 'parent')
|
|
|
|
|
2023-11-02 15:28:33 +00:00
|
|
|
def get_childrens(self):
|
2023-08-18 09:05:21 +00:00
|
|
|
return r_object.smembers(f'child:{self.type}:{self.get_subtype(r_str=True)}:{self.id}')
|
|
|
|
|
2023-11-02 15:28:33 +00:00
|
|
|
def set_parent(self, obj_type=None, obj_subtype=None, obj_id=None, obj_global_id=None): # TODO # REMOVE ITEM DUP
|
2023-08-18 09:05:21 +00:00
|
|
|
if not obj_global_id:
|
|
|
|
if obj_subtype is None:
|
|
|
|
obj_subtype = ''
|
|
|
|
obj_global_id = f'{obj_type}:{obj_subtype}:{obj_id}'
|
|
|
|
r_object.hset(f'meta:{self.type}:{self.get_subtype(r_str=True)}:{self.id}', 'parent', obj_global_id)
|
2023-11-06 13:08:23 +00:00
|
|
|
r_object.sadd(f'child:{obj_global_id}', self.get_global_id())
|
2023-08-18 09:05:21 +00:00
|
|
|
|
2023-11-02 15:28:33 +00:00
|
|
|
def add_children(self, obj_type=None, obj_subtype=None, obj_id=None, obj_global_id=None): # TODO # REMOVE ITEM DUP
|
2023-08-18 09:05:21 +00:00
|
|
|
if not obj_global_id:
|
|
|
|
if obj_subtype is None:
|
|
|
|
obj_subtype = ''
|
|
|
|
obj_global_id = f'{obj_type}:{obj_subtype}:{obj_id}'
|
|
|
|
r_object.sadd(f'child:{self.type}:{self.get_subtype(r_str=True)}:{self.id}', obj_global_id)
|
2023-11-06 13:08:23 +00:00
|
|
|
r_object.hset(f'meta:{obj_global_id}', 'parent', self.get_global_id())
|
2023-08-18 09:05:21 +00:00
|
|
|
|
2023-11-02 15:28:33 +00:00
|
|
|
## others objects ##
|
2023-08-18 09:05:21 +00:00
|
|
|
def add_obj_children(self, parent_global_id, son_global_id):
|
|
|
|
r_object.sadd(f'child:{parent_global_id}', son_global_id)
|
|
|
|
r_object.hset(f'meta:{son_global_id}', 'parent', parent_global_id)
|
|
|
|
|
|
|
|
## Parent ##
|