class GameSession(Document): oracle_chat = ReferenceField(Chat) # type: Chat rogue_chat = ReferenceField(Chat) # type: Chat passphrase = ListField(StringField(), required=True) # type: List[str] # game turn = StringField(choices=['oracle', 'rogue'], default='rogue') # type: str rogue_room = IntField(default=0) # type: int spells = EmbeddedDocumentListField(Spell, default=generate_spells) # oracle stuff map_researched = BooleanField(default=False) # type: bool target_cast = StringField(null=True, default=None) cast_text = StringField(null=True, default=None) oracle_informed = BooleanField(default=False) # thief stuff is_disorientated = BooleanField(default=False) # type: bool informed = BooleanField(default=False) rogue_status = StringField(default=None, null=True) dungeon = EmbeddedDocumentField(Dungeon, default=generate_dungeon) # type: Dungeon @classmethod def find_user_session(cls, chat: Chat) -> Optional['GameSession']: try: return cls.objects.get(Q(oracle_chat=chat) | Q(rogue_chat=chat)) except DoesNotExist: return None @classmethod def find_by_pass(cls, words: List[str]) -> Optional['GameSession']: try: return cls.objects.get( passphrase=[text_utils.normalize(w) for w in words]) except DoesNotExist: return None @property def ready(self): return self.oracle_chat is not None and self.rogue_chat is not None def init_session(self): self.passphrase = [ text_utils.generate_word_for_pass() for i in range(4) ] # self.spells = generate_spells() def join(self, chat: Chat): if self.oracle_chat is None: self.oracle_chat = chat elif self.rogue_chat is None: self.rogue_chat = chat else: raise ValueError() def next_turn(self): if self.turn == 'oracle': self.turn = 'rogue' else: self.turn = 'oracle'
class RawData(CritsBaseAttributes, CritsSourceDocument, Document): """ Raw Data class. """ meta = { "collection": settings.COL_RAW_DATA, "crits_type": 'RawData', "latest_schema_version": 2, "schema_doc": {}, "jtable_opts": { 'details_url': 'crits.raw_data.views.raw_data_details', 'details_url_key': 'id', 'default_sort': "modified DESC", 'searchurl': 'crits.raw_data.views.raw_data_listing', 'fields': [ "title", "data_type", "version", "modified", "source", "campaign", "id", "status" ], 'jtopts_fields': [ "details", "title", "data_type", "version", "modified", "source", "campaign", "status", "favorite", "id" ], 'hidden_fields': [], 'linked_fields': ["source", "campaign"], 'details_link': 'details', 'no_sort': ['details'] } } data_type = StringField() data = StringField() highlights = ListField(EmbeddedDocumentField(EmbeddedHighlight)) inlines = ListField(EmbeddedDocumentField(EmbeddedInline)) link_id = UUIDField(binary=True, required=True, default=uuid.uuid4) md5 = StringField() title = StringField() tool = EmbeddedDocumentField(EmbeddedTool) version = IntField() def migrate(self): """ Migrate to the latest schema version. """ migrate_raw_data(self) def add_file_data(self, file_data): """ Add filedata to RawData. :param file_data: The raw data to add. :type file_data: str """ self._generate_file_metadata(file_data) self.data = file_data def add_file_obj(self, file_obj): """ Add filedata to RawData. :param file_data: The raw data to add. :type file_data: file handle """ data = file_obj.read() self._generate_file_metadata(data) self.data = data def _generate_file_metadata(self, data): """ Generate metadata from the raw data. Uses the data to generate an MD5. :param data: The data to generate metadata from. """ from hashlib import md5 if not self.md5: self.md5 = md5(data).hexdigest() def add_tool(self, name=None, version=None, details=None): """ Add a tool to RawData. :param name: The name of the tool used to generate/acquire the raw data. :type name: str :param version: The version number of the tool. :type version: str :param details: Details about the tool. :type details: str """ if name: et = EmbeddedTool(name=name, version=version, details=details) self.tool = et def add_inline_comment(self, comment, line_num, analyst): """ Add an inline comment for RawData. :param comment: The comment to add. :type comment: str :param line_num: The line number this comment is associated with. :type line_Num: int :param analyst: The user making the comment. :type analyst: str """ if comment: ei = EmbeddedInline(line=line_num, comment=comment, analyst=analyst) c = 1 for i in self.inlines: if i.line == int(line_num) and i.counter >= c: c = i.counter + 1 ei.counter = c self.inlines.append(ei) def add_highlight(self, line_num, line_data, analyst): """ Highlight a specific line of the RawData. :param line_num: The line number being highlighted. :type line_num: str :param line_data: The data on that line. :type line_data: str :param analyst: The user highlighting the line. :type analyst: str """ eh = EmbeddedHighlight(line=line_num, line_data=line_data, analyst=analyst) # determine line date try: pd = parse(line_data, fuzzy=True) if pd: eh.line_date = pd except: eh.line_date = datetime.datetime.now() self.highlights.append(eh) def remove_highlight(self, line_num, analyst): """ Remove highlight from a specific line of the RawData. :param line_num: The line number being unhighlighted. :type line_num: str :param analyst: The user unhighlighting the line. :type analyst: str """ highlights = [] for h in self.highlights: if h.line == int(line_num) and h.analyst == analyst: continue else: highlights.append(h) self.highlights = highlights
class DataDoc(Document): name = StringField() embed = EmbeddedDocumentField(EmbedData) meta = {"allow_inheritance": True}
class AnalysisResult(CritsDocument, CritsSchemaDocument, CritsDocumentFormatter, Document): """ Analysis Result from running an analytic service. """ meta = { "crits_type": "AnalysisResult", "collection": settings.COL_ANALYSIS_RESULTS, "latest_schema_version": 1, "schema_doc": { 'analyst': 'Analyst who ran the service.', 'analysis_id': 'Unique ID for this service execution.', 'analysis_type': 'Type of analysis this is.', 'config': 'Configuration options used for this execution.', 'distributed': 'Distributed for this execution.', 'finish_date': 'Date execution finished.', 'log': 'Log entries for this execution.', 'object_type': 'Type of TLO this is for.', 'object_id': 'ObjectId of the TLO.', 'results': 'Analysis results.', 'service_name': 'Name of the service.', 'source': 'Source of the service.', 'start_date': 'Date execution started.', 'status': 'Status of the execution.', 'template': 'Custom template to render results.', 'version': 'Version of the service used.', }, "jtable_opts": { 'details_url': 'crits.services.views.analysis_result', 'details_url_key': 'id', 'default_sort': "start_date DESC", 'searchurl': 'crits.services.views.analysis_results_listing', 'fields': [ "object_type", "service_name", "version", "start_date", "finish_date", "results", "object_id", "id" ], 'jtopts_fields': [ "details", "object_type", "service_name", "version", "start_date", "finish_date", "results", "id" ], 'hidden_fields': ["object_id", "id"], 'linked_fields': ["object_type", "service_name"], 'details_link': 'details', 'no_sort': ['details'] } } #TODO: these should be datetime objects, not strings analyst = StringField() analysis_id = UUIDField(binary=False) analysis_type = StringField(db_field="type") config = EmbeddedDocumentField(AnalysisConfig) distributed = BooleanField() finish_date = StringField() log = ListField(EmbeddedDocumentField(EmbeddedAnalysisResultLog)) object_type = StringField(required=True) object_id = StringField(required=True) results = ListField(DynamicField(DictField)) service_name = StringField() source = StringField() start_date = StringField() status = StringField() template = StringField() version = StringField()
class A(DynamicDocument): ddd = StringField() aa = EmbeddedDocumentField(BA)
class Person(Document): wallet = EmbeddedDocumentField(Wallet) wallet_map = MapField(EmbeddedDocumentField(Wallet))
class MyFailingdoc2(Document): emb = EmbeddedDocumentField("MyDoc")
class Bed(EmbeddedDocument): uuid = UUIDField(required=True, default=lambda: str( uuid.uuid4()), binary=False) plant = StringField() sensors = ListField(EmbeddedDocumentField('Sensor'))
class Greenhouse(Document): location = StringField() user = StringField(required=True) beds = ListField(EmbeddedDocumentField('Bed'))
class Journal(Document): _id = StringField(max_length=32, primary_key=True, required=True) jid = StringField(max_length=32, required=True, unique=True, ) collection = ReferenceField(Collection, reverse_delete_rule=CASCADE) timeline = EmbeddedDocumentListField(Timeline) subject_categories = ListField(field=StringField()) study_areas = ListField(field=StringField()) social_networks = EmbeddedDocumentListField(SocialNetwork) title = StringField() title_iso = StringField() next_title = StringField() short_title = StringField() title_slug = StringField() created = DateTimeField() updated = DateTimeField() acronym = StringField() scielo_issn = StringField() print_issn = StringField() eletronic_issn = StringField() subject_descriptors = ListField(field=StringField()) copyrighter = StringField() online_submission_url = StringField() logo_url = StringField() previous_journal_ref = StringField() other_titles = EmbeddedDocumentListField(OtherTitle) publisher_name = StringField() publisher_country = StringField() publisher_state = StringField() publisher_city = StringField() publisher_address = StringField() publisher_telephone = StringField() current_status = StringField() editor_email = EmailField() enable_contact = BooleanField(default=False) mission = EmbeddedDocumentListField(Mission) index_at = ListField(field=StringField()) sponsors = ListField(field=StringField()) issue_count = IntField() last_issue = EmbeddedDocumentField(LastIssue) is_public = BooleanField(required=True, default=True) unpublish_reason = StringField() url_segment = StringField() metrics = EmbeddedDocumentField(JounalMetrics) scimago_id = StringField() meta = { 'collection': 'journal', 'indexes': [ 'jid', 'title', 'title_slug', 'acronym', 'is_public', 'url_segment', 'issue_count', 'current_status', 'scimago_id', ] } @property def legend_last_issue(self): leg_dict = { 'title': self.title, 'pubdate': str(self.last_issue.year), 'short_title': self.short_title, 'volume': self.last_issue.volume, 'number': self.last_issue.number, 'suppl': self.last_issue.suppl_text } return short_format(**leg_dict) @property def url_last_issue(self): leg_dict = {'acron': self.acronym, 'year_pub': self.last_issue.year, 'volume': self.last_issue.volume, 'number': self.last_issue.number, 'suppl_number': self.last_issue.suppl_text} return URLegendarium(**leg_dict).url_issue @property def legend(self): return self.title_iso @classmethod def pre_save(cls, sender, document, **kwargs): document.title_slug = slugify(document.title) leg_dict = {'acron': document.acronym} document.url_segment = URLegendarium(**leg_dict).get_journal_seg() def __unicode__(self): return self.legend or 'Journal: %s' % self._id def get_mission_by_lang(self, lang): """ Retorna a missão por idioma do param lang, caso não exista damos preferência para o Inglês. Caso não exista o Inglês devemos retornar a missão em qualquer idioma. Caso não exista nenhuma missão cadastrada retornamos None. "mission" : [ { "language" : "en", "description" : "To publish original articles..." }, { "language" : "pt", "description" : "Publicar artigos originais..." }, { "language" : "es", "description" : "Publicar artículos originales..." } ] """ dict_mission = {m['language']: m['description'] for m in self.mission} try: return dict_mission[lang] except KeyError: try: return dict_mission['en'] except KeyError: if len(dict_mission) > 0: return next(dict_mission.values()) @property def url(self): leg_dict = { 'acron': self.journal.acronym, 'year_pub': self.year } return URLegendarium(**leg_dict).url_journal @property def url_next_journal(self): url_next_journal = "" if self.next_title: next_journal = self.__class__.objects( title_slug=slugify(self.next_title) ).first() if next_journal: url_next_journal = URLegendarium(**{'acron': next_journal.acronym}).get_journal_seg() return url_next_journal @property def url_previous_journal(self): url_previous_journal = "" if self.previous_journal_ref: previous_journal = self.__class__.objects( title_slug=slugify(self.previous_journal_ref) ).first() if previous_journal: url_previous_journal = URLegendarium(**{'acron': previous_journal.acronym}).get_journal_seg() return url_previous_journal
class Article(Document): _id = StringField(max_length=32, primary_key=True, required=True) aid = StringField(max_length=32, required=True, unique=True) issue = ReferenceField(Issue, reverse_delete_rule=CASCADE) journal = ReferenceField(Journal, reverse_delete_rule=CASCADE) title = StringField() translated_titles = EmbeddedDocumentListField(TranslatedTitle) section = StringField() sections = EmbeddedDocumentListField(TranslatedSection) authors = ListField(field=StringField()) abstract = StringField() abstracts = EmbeddedDocumentListField(Abstract) is_aop = BooleanField() order = IntField() doi = StringField() pid = StringField() aop_pid = StringField() languages = ListField(field=StringField()) abstract_languages = ListField(field=StringField()) original_language = StringField() publication_date = StringField() type = StringField() keywords = EmbeddedDocumentListField(ArticleKeyword) domain_key = StringField() xml = StringField() htmls = ListField(field=DictField()) pdfs = ListField(field=DictField()) created = DateTimeField() updated = DateTimeField() is_public = BooleanField(required=True, default=True) unpublish_reason = StringField() elocation = StringField() fpage = StringField() fpage_sequence = StringField() lpage = StringField() url_segment = StringField() aop_url_segs = EmbeddedDocumentField(AOPUrlSegments) meta = { 'collection': 'article', 'indexes': [ 'pid', 'aop_pid', 'aid', 'journal', 'issue', 'type', 'title', 'order', 'doi', 'is_public', 'fpage', 'fpage_sequence', 'lpage', 'url_segment', 'elocation', ] } def __unicode__(self): if self.issue and self.journal: return '%s - %s' % (self.legend, self.title) else: return 'Article: %s' % self._id def get_title_by_lang(self, lang): """ Retorna o título do artigo por idioma, caso não encontre o idioma retorna o título original, caso não tenha título original retorna ``None``. O parâmetro ``lang`` é o acrônimo do idioma, ex.: en, es, pt. """ for title in self.translated_titles: if title.language == lang: return title.name return self.title def get_section_by_lang(self, lang): """ Retorna a seção por idioma, caso não encontre retorna o atributo: ``article.section``, caso o artigo não tenha o atributo ``section``, retorna ``None``. """ for section in self.sections: if section.language == lang: return section.name return self.section def get_abstract_by_lang(self, lang): """ Retorna a resumo por idioma do param lang. Caso não exista nenhum resumo cadastrado retornamos None. "abstract" : [ { "language" : "en", "text" : "Original articles..." }, { "language" : "pt", "text" : "Artigos originais..." }, { "language" : "es", "text" : "Artículos originales..." } ] """ dict_abstract = {m['language']: m['text'] for m in self.abstracts} try: return dict_abstract[lang] except KeyError: return None @classmethod def pre_save(cls, sender, document, **kwargs): leg_dict = { 'acron': document.journal.acronym, 'year_pub': document.issue.year, 'volume': document.issue.volume, 'number': document.issue.number, 'suppl_number': document.issue.suppl_text, 'fpage': document.fpage, 'fpage_sequence': document.fpage_sequence, 'lpage': document.lpage, 'article_id': document.elocation, 'doi': document.doi, 'order': str(document.order) } document.url_segment = URLegendarium(**leg_dict).get_article_seg() @property def legend(self): leg_dict = { 'title': self.journal.title, 'short_title': self.journal.short_title, 'pubdate': str(self.issue.year), 'volume': self.issue.volume, 'number': self.issue.number, 'suppl': self.issue.suppl_text } return short_format(**leg_dict) @property def url(self): return self.url_segment
class Product(Document): name = StringField(max_length=200) brand = StringField(max_length=100) items = ListField(EmbeddedDocumentField(Item))
class RawData(CritsBaseAttributes, CritsSourceDocument, Document): """ Raw Data class. """ meta = { "collection": settings.COL_RAW_DATA, "crits_type": 'RawData', "latest_schema_version": 2, "schema_doc": {}, "jtable_opts": { 'details_url': 'crits.raw_data.views.raw_data_details', 'details_url_key': 'id', 'default_sort': "modified DESC", 'searchurl': 'crits.raw_data.views.raw_data_listing', 'fields': [ "title", "data_type", "version", "modified", "source", "campaign", "id", "status" ], 'jtopts_fields': [ "details", "title", "data_type", "version", "modified", "source", "campaign", "status", "favorite", "id" ], 'hidden_fields': [], 'linked_fields': ["source", "campaign"], 'details_link': 'details', 'no_sort': ['details'] } } data_type = StringField() description = StringField() data = StringField() highlights = ListField(EmbeddedDocumentField(EmbeddedHighlight)) inlines = ListField(EmbeddedDocumentField(EmbeddedInline)) link_id = UUIDField(binary=True, required=True, default=uuid.uuid4) md5 = StringField() title = StringField() tool = EmbeddedDocumentField(EmbeddedTool) version = IntField() def migrate(self): """ Migrate to the latest schema version. """ migrate_raw_data(self) def add_file_data(self, file_data): """ Add filedata to RawData. :param file_data: The raw data to add. :type file_data: str """ self._generate_file_metadata(file_data) self.data = file_data def add_file_obj(self, file_obj): """ Add filedata to RawData. :param file_data: The raw data to add. :type file_data: file handle """ data = file_obj.read() self._generate_file_metadata(data) self.data = data def _generate_file_metadata(self, data): """ Generate metadata from the raw data. Uses the data to generate an MD5. :param data: The data to generate metadata from. """ from hashlib import md5 if not self.md5: self.md5 = md5(data).hexdigest() def add_tool(self, name=None, version=None, details=None): """ Add a tool to RawData. :param name: The name of the tool used to generate/acquire the raw data. :type name: str :param version: The version number of the tool. :type version: str :param details: Details about the tool. :type details: str """ if name: et = EmbeddedTool(name=name, version=version, details=details) self.tool = et def add_inline_comment(self, comment, line_num, analyst): """ Add an inline comment for RawData. :param comment: The comment to add. :type comment: str :param line_num: The line number this comment is associated with. :type line_Num: int :param analyst: The user making the comment. :type analyst: str """ if comment: ei = EmbeddedInline(line=line_num, comment=comment, analyst=analyst) c = 1 for i in self.inlines: if i.line == int(line_num) and i.counter >= c: c = i.counter + 1 ei.counter = c self.inlines.append(ei) def add_highlight(self, line_num, line_data, analyst): """ Highlight a specific line of the RawData. :param line_num: The line number being highlighted. :type line_num: str :param line_data: The data on that line. :type line_data: str :param analyst: The user highlighting the line. :type analyst: str """ eh = EmbeddedHighlight(line=line_num, line_data=line_data, analyst=analyst) # determine line date try: pd = parse(line_data, fuzzy=True) if pd: eh.line_date = pd except: eh.line_date = datetime.datetime.now() self.highlights.append(eh) def remove_highlight(self, line_num, analyst): """ Remove highlight from a specific line of the RawData. :param line_num: The line number being unhighlighted. :type line_num: str :param analyst: The user unhighlighting the line. :type analyst: str """ highlights = [] for h in self.highlights: if h.line == int(line_num) and h.analyst == analyst: continue else: highlights.append(h) self.highlights = highlights def to_cybox_observable(self): """ Convert a RawData to a CybOX Observables. Returns a tuple of (CybOX object, releasability list). To get the cybox object as xml or json, call to_xml() or to_json(), respectively, on the resulting CybOX object. """ obj = Artifact(self.data, Artifact.TYPE_FILE) obj.packaging.append(Base64Encoding()) obs = Observable(obj) obs.description = self.description return ([obs], self.releasability) @classmethod def from_cybox(cls, cybox_obs): """ Convert a Cybox DefinedObject to a MongoEngine RawData object. :param cybox_obs: The cybox object to create the RawData from. :type cybox_obs: :class:`cybox.core.Observable`` :returns: :class:`crits.raw_data.raw_data.RawData` """ cybox_object = cybox_obs.object_.properties rawdata = cls() rawdata.add_file_data(cybox_object.data) db_obj = RawData.objects(md5=rawdata.md5).first() if db_obj: return db_obj return rawdata
class Post(Document): title = StringField(max_length=120, required=True) author = ReferenceField(User, reverse_delete_rule=2) tags = ListField(StringField(max_length=30)) comments = ListField(EmbeddedDocumentField(Comment))
class Record(Document): posts = ListField(EmbeddedDocumentField(Post))
class Regions(EmbeddedDocument): detecting_region = EmbeddedDocumentField(Polygon) tracking_region = EmbeddedDocumentField(Polygon)
def test___init___throw_error_if_document_type_is_not_EmbeddedDocument( self): with pytest.raises(ValidationError): EmbeddedDocumentField(dict)
class Task(AttributedDocument): _field_collation_overrides = { "execution.parameters.": AttributedDocument._numeric_locale, "last_metrics.": AttributedDocument._numeric_locale, "hyperparams.": AttributedDocument._numeric_locale, } meta = { "db_alias": Database.backend, "strict": strict, "indexes": [ "created", "started", "completed", "active_duration", "parent", "project", "models.input.model", ("company", "name"), ("company", "user"), ("company", "status", "type"), ("company", "system_tags", "last_update"), ("company", "type", "system_tags", "status"), ("company", "project", "type", "system_tags", "status"), ("status", "last_update"), # for maintenance tasks { "fields": ["company", "project"], "collation": AttributedDocument._numeric_locale, }, { "name": "%s.task.main_text_index" % Database.backend, "fields": [ "$name", "$id", "$comment", "$models.input.model", "$models.output.model", "$script.repository", "$script.entry_point", ], "default_language": "english", "weights": { "name": 10, "id": 10, "comment": 10, "models.output.model": 2, "models.input.model": 2, "script.repository": 1, "script.entry_point": 1, }, }, ], } get_all_query_options = GetMixin.QueryParameterOptions( list_fields=( "id", "user", "tags", "system_tags", "type", "status", "project", "parent", "hyperparams.*", ), range_fields=("started", "active_duration", "last_metrics.*", "last_iteration"), datetime_fields=("status_changed", "last_update"), pattern_fields=("name", "comment"), ) id = StringField(primary_key=True) name = StrippedStringField(required=True, user_set_allowed=True, sparse=False, min_length=3) type = StringField(required=True, choices=get_options(TaskType)) status = StringField(default=TaskStatus.created, choices=get_options(TaskStatus)) status_reason = StringField() status_message = StringField(user_set_allowed=True) status_changed = DateTimeField() comment = StringField(user_set_allowed=True) created = DateTimeField(required=True, user_set_allowed=True) started = DateTimeField() completed = DateTimeField() published = DateTimeField() active_duration = IntField(default=None) parent = StringField(reference_field="Task") project = StringField(reference_field=Project, user_set_allowed=True) output: Output = EmbeddedDocumentField(Output, default=Output) execution: Execution = EmbeddedDocumentField(Execution, default=Execution) tags = SafeSortedListField(StringField(required=True), user_set_allowed=True) system_tags = SafeSortedListField(StringField(required=True), user_set_allowed=True) script: Script = EmbeddedDocumentField(Script, default=Script) last_worker = StringField() last_worker_report = DateTimeField() last_update = DateTimeField() last_change = DateTimeField() last_iteration = IntField(default=DEFAULT_LAST_ITERATION) last_metrics = SafeMapField( field=SafeMapField(EmbeddedDocumentField(MetricEvent))) metric_stats = SafeMapField(field=EmbeddedDocumentField(MetricEventStats)) company_origin = StringField(exclude_by_default=True) duration = IntField() # task duration in seconds hyperparams = SafeMapField( field=SafeMapField(EmbeddedDocumentField(ParamsItem))) configuration = SafeMapField( field=EmbeddedDocumentField(ConfigurationItem)) runtime = SafeDictField(default=dict) models: Models = EmbeddedDocumentField(Models, default=Models) container = SafeMapField(field=NullableStringField()) enqueue_status = StringField(choices=get_options(TaskStatus), exclude_by_default=True) def get_index_company(self) -> str: """ Returns the company ID used for locating indices containing task data. In case the task has a valid company, this is the company ID. Otherwise, if the task has a company_origin, this is a task that has been made public and the origin company should be used. Otherwise, an empty company is used. """ return self.company or self.company_origin or ""
class MyFailingDoc(Document): emb = EmbeddedDocumentField(MyDoc)
class Subscriber(Document): MAX_DATE = datetime(2100, 1, 1) ID_FIELD = "id" EMAIL_FIELD = "login" PASSWORD_FIELD = "password" class Status(IntEnum): NOT_ACTIVE = 0 ACTIVE = 1 TRIAL_FINISHED = 2 BANNED = 3 @classmethod def choices(cls): return [(choice, choice.name) for choice in cls] @classmethod def coerce(cls, item): return cls(int(item)) if not isinstance(item, cls) else item def __str__(self): return str(self.value) SUBSCRIBER_HASH_LENGTH = 32 meta = {'allow_inheritance': True, 'collection': 'subscribers', 'auto_create_index': False} email = StringField(max_length=64, required=True) password = StringField(min_length=SUBSCRIBER_HASH_LENGTH, max_length=SUBSCRIBER_HASH_LENGTH, required=True) created_date = DateTimeField(default=datetime.now) exp_date = DateTimeField(default=MAX_DATE) status = IntField(default=Status.NOT_ACTIVE) country = StringField(min_length=2, max_length=3, required=True) language = StringField(default=constants.DEFAULT_LOCALE, required=True) servers = ListField(ReferenceField(ServiceSettings, reverse_delete_rule=PULL), default=[]) devices = ListField(EmbeddedDocumentField(Device), default=[]) streams = ListField(ReferenceField(IStream, reverse_delete_rule=PULL), default=[]) own_streams = ListField(ReferenceField(IStream, reverse_delete_rule=PULL), default=[]) def add_server(self, server): self.servers.append(server) self.save() def add_device(self, device: Device): self.devices.append(device) self.save() def remove_device(self, sid: str): for device in self.devices: if str(device.id) == sid: self.devices.remove(device) break self.save() def find_device(self, sid: str): for device in self.devices: if str(device.id) == sid: return device return None def generate_playlist(self, did: str, lb_server_host_and_port: str) -> str: result = '#EXTM3U\n' sid = str(self.id) for stream in self.streams: result += stream.generate_device_playlist(sid, self.password, did, lb_server_host_and_port, False) for own in self.own_streams: result += own.generate_playlist(False) return result def add_official_stream(self, stream: IStream): self.streams.append(stream) self.save() def add_own_stream(self, stream: IStream): self.own_streams.append(stream) self.save() def remove_own_stream(self, sid: str): for stream in self.own_streams: if str(stream.id) == sid: self.own_streams.remove(stream) stream.delete() break self.save() def find_own_stream(self, sid: str): for stream in self.own_streams: if str(stream.id) == sid: return stream return None def remove_all_own_streams(self): for stream in self.own_streams: self.own_streams.remove(stream) stream.delete() self.own_streams = [] self.save() def get_not_active_devices(self): devices = [] for dev in self.devices: if dev.status == Device.Status.NOT_ACTIVE: devices.append(dev.to_dict()) return devices def delete(self, *args, **kwargs): for stream in self.own_streams: stream.delete() return super(Subscriber, self).delete(*args, **kwargs) @staticmethod def make_md5_hash_from_password(password: str) -> str: m = md5() m.update(password.encode()) return m.hexdigest() @staticmethod def generate_password_hash(password: str) -> str: return Subscriber.make_md5_hash_from_password(password) @staticmethod def check_password_hash(hash: str, password: str) -> bool: return hash == Subscriber.generate_password_hash(password)
class Person(Document): settings = EmbeddedDocumentField(AdminSettings) name = StringField()
class CompanyDefaults(EmbeddedDocument): cluster = StringField() stats_option = EmbeddedDocumentField(ReportStatsOption, default=ReportStatsOption)
class ServiceSettings(Document): DEFAULT_SERVICE_NAME = 'Service' MIN_SERVICE_NAME_LENGTH = 3 MAX_SERVICE_NAME_LENGTH = 30 DEFAULT_FEEDBACK_DIR_PATH = constants.DEFAULT_SERVICE_ROOT_DIR_PATH + '/feedback' DEFAULT_TIMESHIFTS_DIR_PATH = constants.DEFAULT_SERVICE_ROOT_DIR_PATH + '/timeshifts' DEFAULT_HLS_DIR_PATH = constants.DEFAULT_SERVICE_ROOT_DIR_PATH + '/hls' DEFAULT_PLAYLISTS_DIR_PATH = constants.DEFAULT_SERVICE_ROOT_DIR_PATH + '/playlists' DEFAULT_DVB_DIR_PATH = constants.DEFAULT_SERVICE_ROOT_DIR_PATH + '/dvb' DEFAULT_CAPTURE_DIR_PATH = constants.DEFAULT_SERVICE_ROOT_DIR_PATH + '/capture_card' DEFAULT_VODS_IN_DIR_PATH = constants.DEFAULT_SERVICE_ROOT_DIR_PATH + '/vods_in' DEFAULT_VODS_DIR_PATH = constants.DEFAULT_SERVICE_ROOT_DIR_PATH + '/vods' DEFAULT_CODS_DIR_PATH = constants.DEFAULT_SERVICE_ROOT_DIR_PATH + '/cods' DEFAULT_SERVICE_HOST = 'localhost' DEFAULT_SERVICE_PORT = 6317 DEFAULT_SERVICE_HTTP_HOST = 'localhost' DEFAULT_SERVICE_HTTP_PORT = 8000 DEFAULT_SERVICE_VODS_HOST = 'localhost' DEFAULT_SERVICE_VODS_PORT = 7000 DEFAULT_SERVICE_CODS_HOST = 'localhost' DEFAULT_SERVICE_CODS_PORT = 6001 meta = {'collection': 'services', 'auto_create_index': False} streams = ListField(ReferenceField(IStream, reverse_delete_rule=PULL), default=[]) providers = ListField(EmbeddedDocumentField(ProviderPair), default=[]) subscribers = ListField(ReferenceField('Subscriber'), default=[]) name = StringField(unique=True, default=DEFAULT_SERVICE_NAME, max_length=MAX_SERVICE_NAME_LENGTH, min_length=MIN_SERVICE_NAME_LENGTH) host = EmbeddedDocumentField(HostAndPort, default=HostAndPort( host=DEFAULT_SERVICE_HOST, port=DEFAULT_SERVICE_PORT)) http_host = EmbeddedDocumentField(HostAndPort, default=HostAndPort( host=DEFAULT_SERVICE_HTTP_HOST, port=DEFAULT_SERVICE_HTTP_PORT)) vods_host = EmbeddedDocumentField(HostAndPort, default=HostAndPort( host=DEFAULT_SERVICE_VODS_HOST, port=DEFAULT_SERVICE_VODS_PORT)) cods_host = EmbeddedDocumentField(HostAndPort, default=HostAndPort( host=DEFAULT_SERVICE_CODS_HOST, port=DEFAULT_SERVICE_CODS_PORT)) feedback_directory = StringField(default=DEFAULT_FEEDBACK_DIR_PATH) timeshifts_directory = StringField(default=DEFAULT_TIMESHIFTS_DIR_PATH) hls_directory = StringField(default=DEFAULT_HLS_DIR_PATH) playlists_directory = StringField(default=DEFAULT_PLAYLISTS_DIR_PATH) dvb_directory = StringField(default=DEFAULT_DVB_DIR_PATH) capture_card_directory = StringField(default=DEFAULT_CAPTURE_DIR_PATH) vods_in_directory = StringField(default=DEFAULT_VODS_IN_DIR_PATH) vods_directory = StringField(default=DEFAULT_VODS_DIR_PATH) cods_directory = StringField(default=DEFAULT_CODS_DIR_PATH) def get_host(self) -> str: return str(self.host) def get_http_host(self) -> str: return 'http://{0}'.format(str(self.http_host)) def get_vods_host(self) -> str: return 'http://{0}'.format(str(self.vods_host)) def get_cods_host(self) -> str: return 'http://{0}'.format(str(self.cods_host)) def generate_http_link(self, url: str) -> str: return url.replace(self.hls_directory, self.get_http_host()) def generate_vods_link(self, url: str) -> str: return url.replace(self.vods_directory, self.get_vods_host()) def generate_cods_link(self, url: str) -> str: return url.replace(self.cods_directory, self.get_cods_host()) def generate_playlist(self) -> str: result = '#EXTM3U\n' for stream in self.streams: result += stream.generate_playlist(False) return result def add_provider(self, user: ProviderPair): self.providers.append(user) self.save() def remove_provider(self, provider): for user in self.providers: if user.user == provider: self.providers.remove(user) break self.save() def add_subscriber(self, subscriber): self.subscribers.append(subscriber) self.save() def remove_subscriber(self, subscriber): self.subscribers.remove(subscriber) self.save() def find_stream_settings_by_id(self, sid): for stream in self.streams: if stream.id == sid: return stream return None def delete(self, *args, **kwargs): for stream in self.streams: stream.delete() return super(ServiceSettings, self).delete(*args, **kwargs)
class Indicator(CritsBaseAttributes, CritsSourceDocument, Document): """ Indicator class. """ meta = { "collection": settings.COL_INDICATORS, "crits_type": 'Indicator', "latest_schema_version": 3, "schema_doc": { 'type': 'The type of this indicator.', 'threat_type': 'The threat type of this indicator.', 'attack_type': 'The attack type of this indicator.', 'value': 'The value of this indicator', 'created': 'The ISODate when this indicator was entered', 'modified': 'The ISODate when this indicator was last modified', 'actions': 'List [] of actions taken for this indicator', 'activity': 'List [] of activity containing this indicator', 'campaign': 'List [] of campaigns using this indicator', 'confidence': { 'rating': 'Low/Medium/High confidence', 'analyst': 'Analyst who provided this confidence level' }, 'impact': { 'rating': 'Low/Medium/High impact', 'analyst': 'Analyst who provided this impact level' }, 'source': ('List [] of source information about who provided this' ' indicator') }, "jtable_opts": { 'details_url': 'crits.indicators.views.indicator', 'details_url_key': 'id', 'default_sort': "created DESC", 'searchurl': 'crits.indicators.views.indicators_listing', 'fields': ["value", "ind_type", "threat_type", "attack_type", "created", "modified", "source", "campaign", "status", "id"], 'jtopts_fields': ["details", "splunk", "value", "type", "threat_type", "attack_type", "created", "modified", "source", "campaign", "status", "favorite", "id"], 'hidden_fields': ["threat_type", "attack_type"], 'linked_fields': ["value", "source", "campaign", "type", "status"], 'details_link': 'details', 'no_sort': ['details', 'splunk'], } } actions = ListField(EmbeddedDocumentField(EmbeddedAction)) activity = ListField(EmbeddedDocumentField(EmbeddedActivity)) confidence = EmbeddedDocumentField(EmbeddedConfidence, default=EmbeddedConfidence()) impact = EmbeddedDocumentField(EmbeddedImpact, default=EmbeddedImpact()) ind_type = StringField(db_field="type") threat_type = StringField(default=IndicatorThreatTypes.UNKNOWN) attack_type = StringField(default=IndicatorAttackTypes.UNKNOWN) value = StringField() def migrate(self): """ Migrate to the latest schema version. """ migrate_indicator(self) def to_csv(self, fields=[], headers=False): """ Generate a CSV row for this Indicator. :param fields: The fields to include. :type fields: list :param headers: To write column headers into the CSV. :type headers: boolean :returns: str """ # Fix some of the embedded fields # confidence if 'confidence' in self._data: self.confidence = self.confidence.rating # impact if 'impact' in self._data: self.impact = self.impact.rating return super(self.__class__, self).to_csv(fields=fields,headers=headers) def set_confidence(self, analyst, rating): """ Set Indicator confidence. :param analyst: The user setting the confidence. :type analyst: str :param rating: The level of confidence. :type rating: str ("unknown", "benign", "low", "medium", "high") """ ec = EmbeddedConfidence() ec.analyst = analyst ec.rating = rating self.confidence = ec def set_impact(self, analyst, rating): """ Set Indicator impact. :param analyst: The user setting the impact. :type analyst: str :param rating: The level of impact. :type rating: str ("unknown", "benign", "low", "medium", "high") """ ei = EmbeddedImpact() ei.analyst = analyst ei.rating = rating self.impact = ei def add_action(self, type_, active, analyst, begin_date, end_date, performed_date, reason, date=None): """ Add an action to an Indicator. :param type_: The type of action. :type type_: str :param active: Whether this action is active or not. :param active: str ("on", "off") :param analyst: The user adding this action. :type analyst: str :param begin_date: The date this action begins. :type begin_date: datetime.datetime :param end_date: The date this action ends. :type end_date: datetime.datetime :param performed_date: The date this action was performed. :type performed_date: datetime.datetime :param reason: The reason for this action. :type reason: str :param date: The date this action was added to CRITs. :type date: datetime.datetime """ ea = EmbeddedAction() ea.action_type = type_ ea.active = active ea.analyst = analyst ea.begin_date = begin_date ea.end_date = end_date ea.performed_date = performed_date ea.reason = reason if date: ea.date = date self.actions.append(ea) def edit_action(self, type_, active, analyst, begin_date, end_date, performed_date, reason, date=None): """ Edit an action for an Indicator. :param type_: The type of action. :type type_: str :param active: Whether this action is active or not. :param active: str ("on", "off") :param analyst: The user editing this action. :type analyst: str :param begin_date: The date this action begins. :type begin_date: datetime.datetime :param end_date: The date this action ends. :type end_date: datetime.datetime :param performed_date: The date this action was performed. :type performed_date: datetime.datetime :param reason: The reason for this action. :type reason: str :param date: The date this action was added to CRITs. :type date: datetime.datetime """ if not date: return for t in self.actions: if t.date == date: self.actions.remove(t) ea = EmbeddedAction() ea.action_type = type_ ea.active = active ea.analyst = analyst ea.begin_date = begin_date ea.end_date = end_date ea.performed_date = performed_date ea.reason = reason ea.date = date self.actions.append(ea) break def delete_action(self, date=None): """ Delete an action. :param date: The date of the action to delete. :type date: datetime.datetime """ if not date: return for t in self.actions: if t.date == date: self.actions.remove(t) break def add_activity(self, analyst, start_date, end_date, description, date=None): """ Add activity to an indicator. :param analyst: The user adding this activity. :type analyst: str :param start_date: The date this activity started. :type start_date: datetime.datetime :param end_date: The date this activity ended. :type end_date: datetime.datetime :param description: Description of the activity. :type description: str :param date: The date this activity was entered into CRITs. :type date: datetime.datetime """ ea = EmbeddedActivity() ea.analyst = analyst ea.start_date = start_date ea.end_date = end_date ea.description = description if date: ea.date = date self.activity.append(ea) def edit_activity(self, analyst, start_date, end_date, description, date=None): """ Edit activity for an indicator. :param analyst: The user editing this activity. :type analyst: str :param start_date: The date this activity started. :type start_date: datetime.datetime :param end_date: The date this activity ended. :type end_date: datetime.datetime :param description: Description of the activity. :type description: str :param date: The date this activity was entered into CRITs. :type date: datetime.datetime """ if not date: return for t in self.activity: if t.date == date: self.activity.remove(t) ea = EmbeddedActivity() ea.analyst = analyst ea.start_date = start_date ea.end_date = end_date ea.date = date ea.description = description self.activity.append(ea) break def delete_activity(self, date=None): """ Delete activity from this indicator. :param date: The date of the activity entry to delete. :type date: datetime.datetime """ if not date: return for t in self.activity: if t.date == date: self.activity.remove(t) break
class Indicator(CritsBaseAttributes, CritsSourceDocument, Document): """ Indicator class. """ meta = { "collection": settings.COL_INDICATORS, "crits_type": 'Indicator', "latest_schema_version": 2, "schema_doc": { 'value': 'The value of this indicator', 'type': 'The type of this indicator based on CybOX Object Types', 'created': 'The ISODate when this indicator was entered', 'modified': 'The ISODate when this indicator was last modified', 'actions': 'List [] of actions taken for this indicator', 'activity': 'List [] of activity containing this indicator', 'campaign': 'List [] of campaigns using this indicator', 'confidence': { 'rating': 'Low/Medium/High confidence', 'analyst': 'Analyst who provided this confidence level' }, 'impact': { 'rating': 'Low/Medium/High impact', 'analyst': 'Analyst who provided this impact level' }, 'source': ('List [] of source information about who provided this' ' indicator') }, "jtable_opts": { 'details_url': 'crits.indicators.views.indicator', 'details_url_key': 'id', 'default_sort': "created DESC", 'searchurl': 'crits.indicators.views.indicators_listing', 'fields': [ "value", "ind_type", "created", "modified", "source", "campaign", "status", "id" ], 'jtopts_fields': [ "details", "value", "type", "created", "modified", "source", "campaign", "status", "favorite", "id" ], 'hidden_fields': [], 'linked_fields': [ "value", "source", "campaign", "type", "status" ], 'details_link': 'details', 'no_sort': ['details'] } } actions = ListField(EmbeddedDocumentField(EmbeddedAction)) activity = ListField(EmbeddedDocumentField(EmbeddedActivity)) confidence = EmbeddedDocumentField(EmbeddedConfidence, default=EmbeddedConfidence()) impact = EmbeddedDocumentField(EmbeddedImpact, default=EmbeddedImpact()) ind_type = StringField(db_field="type") value = StringField() def migrate(self): """ Migrate to the latest schema version. """ migrate_indicator(self) def to_csv(self, fields=[],headers=False): """ Generate a CSV row for this Indicator. :param fields: The fields to include. :type fields: list :param headers: To write column headers into the CSV. :type headers: boolean :returns: str """ # Fix some of the embedded fields # confidence if 'confidence' in self._data: self.confidence = self.confidence.rating # impact if 'impact' in self._data: self.impact = self.impact.rating return super(self.__class__, self).to_csv(fields=fields,headers=headers) def to_stix_indicator(self): """ Creates a STIX Indicator object from a CybOX object. Returns the STIX Indicator and the original CRITs object's releasability list. """ from stix.indicator import Indicator as S_Ind from stix.common.identity import Identity ind = S_Ind() obs, releas = self.to_cybox() for ob in obs: ind.add_observable(ob) #TODO: determine if a source wants its name shared. This will # probably have to happen on a per-source basis rather than a per- # object basis. identity = Identity(name=settings.COMPANY_NAME) ind.set_producer_identity(identity) return (ind, releas) def to_cybox(self): """ Convert an indicator to a CybOX Observable. Returns a tuple of (CybOX object, releasability list). To get the cybox object as xml or json, call to_xml() or to_json(), respectively, on the resulting CybOX object. """ observables = [] parts = self.ind_type.split(' - ') if len(parts) == 2: (type_, name) = parts else: type_ = parts[0] name = None obj = make_cybox_object(type_, name, self.value) observables.append(Observable(obj)) return (observables, self.releasability) @classmethod def from_cybox(cls, cybox_object): """ Convert a Cybox DefinedObject to a MongoEngine Indicator object. :param cybox_object: The cybox object to create the indicator from. :type cybox_object: :class:`cybox.core.Observable`` :returns: :class:`crits.indicators.indicator.Indicator` """ obj = make_crits_object(cybox_object) if obj.name and obj.name != obj.object_type: ind_type = "%s - %s" % (obj.object_type, obj.name) else: ind_type = obj.object_type db_indicator = Indicator.objects(Q(ind_type=ind_type) & Q(value=obj.value)).first() if db_indicator: indicator = db_indicator else: indicator = cls() indicator.value = obj.value indicator.created = obj.date indicator.modified = obj.date return indicator def has_cybox_repr(self): """ Determine if this indicator is of a type that can successfully be converted to a CybOX object. :return The CybOX representation if possible, else False. """ try: rep = self.to_cybox() return rep except: return False def set_confidence(self, analyst, rating): """ Set Indicator confidence. :param analyst: The user setting the confidence. :type analyst: str :param rating: The level of confidence. :type rating: str ("unknown", "benign", "low", "medium", "high") """ ec = EmbeddedConfidence() ec.analyst = analyst ec.rating = rating self.confidence = ec def set_impact(self, analyst, rating): """ Set Indicator impact. :param analyst: The user setting the impact. :type analyst: str :param rating: The level of impact. :type rating: str ("unknown", "benign", "low", "medium", "high") """ ei = EmbeddedImpact() ei.analyst = analyst ei.rating = rating self.impact = ei def add_action(self, type_, active, analyst, begin_date, end_date, performed_date, reason, date=None): """ Add an action to an Indicator. :param type_: The type of action. :type type_: str :param active: Whether this action is active or not. :param active: str ("on", "off") :param analyst: The user adding this action. :type analyst: str :param begin_date: The date this action begins. :type begin_date: datetime.datetime :param end_date: The date this action ends. :type end_date: datetime.datetime :param performed_date: The date this action was performed. :type performed_date: datetime.datetime :param reason: The reason for this action. :type reason: str :param date: The date this action was added to CRITs. :type date: datetime.datetime """ ea = EmbeddedAction() ea.action_type = type_ ea.active = active ea.analyst = analyst ea.begin_date = begin_date ea.end_date = end_date ea.performed_date = performed_date ea.reason = reason if date: ea.date = date self.actions.append(ea) def edit_action(self, type_, active, analyst, begin_date, end_date, performed_date, reason, date=None): """ Edit an action for an Indicator. :param type_: The type of action. :type type_: str :param active: Whether this action is active or not. :param active: str ("on", "off") :param analyst: The user editing this action. :type analyst: str :param begin_date: The date this action begins. :type begin_date: datetime.datetime :param end_date: The date this action ends. :type end_date: datetime.datetime :param performed_date: The date this action was performed. :type performed_date: datetime.datetime :param reason: The reason for this action. :type reason: str :param date: The date this action was added to CRITs. :type date: datetime.datetime """ if not date: return found = False c = 0 for t in self.actions: if t.date == date: found = True del self.actions[c] c += 1 if found: ea = EmbeddedAction() ea.action_type = type_ ea.active = active ea.analyst = analyst ea.begin_date = begin_date ea.end_date = end_date ea.performed_date = performed_date ea.reason = reason ea.date = date self.actions.append(ea) def delete_action(self, date=None): """ Delete an action. :param date: The date of the action to delete. :type date: datetime.datetime """ if not date: return c = 0 for t in self.actions: if t.date == date: del self.actions[c] c += 1 def add_activity(self, analyst, start_date, end_date, description, date=None): """ Add activity to an indicator. :param analyst: The user adding this activity. :type analyst: str :param start_date: The date this activity started. :type start_date: datetime.datetime :param end_date: The date this activity ended. :type end_date: datetime.datetime :param description: Description of the activity. :type description: str :param date: The date this activity was entered into CRITs. :type date: datetime.datetime """ ea = EmbeddedActivity() ea.analyst = analyst ea.start_date = start_date ea.end_date = end_date ea.description = description if date: ea.date = date self.activity.append(ea) def edit_activity(self, analyst, start_date, end_date, description, date=None): """ Edit activity for an indicator. :param analyst: The user editing this activity. :type analyst: str :param start_date: The date this activity started. :type start_date: datetime.datetime :param end_date: The date this activity ended. :type end_date: datetime.datetime :param description: Description of the activity. :type description: str :param date: The date this activity was entered into CRITs. :type date: datetime.datetime """ if not date: return found = False c = 0 for t in self.activity: if t.date == date: found = True del self.activity[c] c += 1 if found: ea = EmbeddedActivity() ea.analyst = analyst ea.start_date = start_date ea.end_date = end_date ea.date = date ea.description = description self.activity.append(ea) def delete_activity(self, date=None): """ Delete activity from this indicator. :param date: The date of the activity entry to delete. :type date: datetime.datetime """ if not date: return c = 0 for t in self.activity: if t.date == date: del self.activity[c] c += 1
class Medias(Document): content = BinaryField() label = StringField() event = EmbeddedDocumentField('Events', required=True) album = EmbeddedDocumentField('Album')
class User(Document): """ Represents a user in Semaphore """ username = EmailField(required=True, unique=True) organizations = ListField(ReferenceField(Organization)) password = ReferenceField(AuthenticationToken) active = BooleanField(required=True, default=True) name = EmbeddedDocumentField(NameToken, required=True) permissions = Permissions(required=True) settings = Settings(required=True) meta = { 'indexes': ['username'], 'allow_inheritance': True, } def __repr__(self): return u'<User: %s (id: %s)>' % (self.username, self.id) @property def active_organizations(self): """ Returns a filtered list of active organizations for a user """ return filter(lambda o: o.active == True, self.organizations) @classmethod def login_user(cls, username, ipaddr, password): """ Finds a user and logs them in with the given password. Returns True if the user was found and logged in, False otherwise. """ user = User.get_user(username) if user is not None and user.handle_login(ipaddr, password): return user return None @classmethod def get_all_users(cls, org_id): return cls.objects(__raw__={"organizations.$id": ObjectId(org_id), "active": True}) @classmethod def get_user(cls, username): """ Returns a user (without authentication) """ return cls.objects(__raw__={'username': username, 'active': True}).first() @classmethod def get_user_id(cls, user_id): """ Returns a user (without authentication) """ return cls.objects(__raw__={'_id': ObjectId(user_id) , 'active': True}).first() def handle_login(self, ipaddr, password): """ Tries to login in the user. If the login is successful, then it returns True. Otherwise, it returns false. Logs the attempt in the database """ status = self.password.check(password, ignore_expired=False) LoginHistory.create_history(self, ipaddr, status) return status
class Person(Document): settings = EmbeddedDocumentField(BaseSettings)
class Post(EmbeddedDocument): title = StringField(max_length=60) created = DateTimeField(default=datetime.now, required=True) creator = EmbeddedDocumentField(UserDT) body = StringField(max_length=10000)
class ApparatusAndSystems(EmbeddedDocument): skin = EmbeddedDocumentField(Skin, required=False, db_field="piel") ophthalmic_system = EmbeddedDocumentField(OphthalmicSystem, required=False, db_field="sistema_oftalmologico") ent_system = EmbeddedDocumentField( EntSystem, required=False, db_field="sistema_otorrinolaringologico") mouth_throat = EmbeddedDocumentField(MouthThroat, required=False, db_field="boca_garganta") digestive_system = EmbeddedDocumentField(DigestiveSystem, required=False, db_field="sistema_digestivo") respiratory_apparatus = EmbeddedDocumentField( RespiratoryApparatus, required=False, db_field="aparato_respiratorio") cardiovascular_apparatus = EmbeddedDocumentField( CardiovascularApparatus, required=False, db_field="aparato_cardiovascular") genitourinary_system = EmbeddedDocumentField( GenitourinarySystem, required=False, db_field="sistema_genitourinario") musculoskeletal_system = EmbeddedDocumentField( MusculoskeletalSystem, required=False, db_field="sistema_musculo_esqueletico") hematological_system = EmbeddedDocumentField( HematologicalSystem, required=False, db_field="sistema_hematologico") nervous_system = EmbeddedDocumentField(NervousSystem, required=False, db_field="sistema_nervioso") psychic_system = EmbeddedDocumentField(PsychicSystem, required=False, db_field="sistema_psiquico") physical_observations = StringField( required=False, db_field="observaciones_exploracion_fisica") follow_up = EmbeddedDocumentField(FollowUp, required=False, db_field="seguimiento")