class DomainInfo(Document): Target = ReferenceField('Target', reverse_delete_rule=CASCADE) SubDomains = ListField() IsValid = BooleanField(default=True)
class TgMessage(TelegramDocument): meta = {'collection': 'telegram_message'} file_types = [ 'audio', 'sticker', 'video', 'animation', 'photo', 'document', 'voice', 'video_note', ] _file_id = None class Meta: original = Message message_id = LongField() chat = ReferenceField(TgChat) from_user = ReferenceField(TgUser) original_object = DictField() reactions = DictField() is_current_message = BooleanField(default=False) def __new__(cls, *args, **kwargs): first_arg = next(iter(args), None) if first_arg is not None and isinstance(first_arg, Message): chat = TgChat.objects(id=first_arg.chat.id).first() obj = cls.objects(message_id=first_arg.message_id, chat=chat).first() if obj: obj.self_from_object(first_arg) return obj return super().__new__(cls) def __repr__(self): return f'{super().__repr__()} - {self.message_id}:{self.chat.id}' @property def file_ids(self) -> Generator[int, None, None]: if self._file_id is not None: yield from self._file_id return self._file_id = [] message = self.original_object if not message: return for file_type in self.file_types: file = message.get(file_type, None) if isinstance(file, list): for file_dict in file: self._file_id.append(file_dict['file_id']) elif isinstance(file, dict) and 'file_id' in file: self._file_id.append(file['file_id']) yield from self._file_id def is_any_type_of(self, *types: str) -> str or None: if isinstance(types, str): types = [types] for type in types: if self.original_object.get(type): return type def _get_file_for_image_search(self, bot: Bot) -> File or None: if (not bot and not self._bot) or self.is_any_type_of( 'photo', 'sticker') is None: return self._bot = bot or self._bot file_id = next(iter(self.file_ids), None) if not file_id: return return self._bot.get_file(file_id=file_id) def find_similar(self, chat_id: int = None, bot: Bot = None) -> list: file = self._get_file_for_image_search(bot) if not file: return [] try: filter = None if chat_id: filter = {'term': {'metadata.chat_id': chat_id}} return image_match_ses.search_image(file.file_path, pre_filter=filter) except (ConnectionError, NewConnectionError, NotFoundError): return [] def get_self_image_match(self, bot: Bot = None) -> dict or None: results = self.find_similar(bot) for result in results: if result['dist'] == 0.0: return result def add_to_image_match(self, chat_id: int = None, bot: Bot = None): metadata = None if chat_id: metadata = {'chat_id': chat_id} file = self._get_file_for_image_search(bot) if not file: return try: image_match_ses.add_image(file.file_path, metadata=metadata) except (ConnectionError, NewConnectionError, NotFoundError): return
class UserEmail(EmbeddedDocument): email = StringField() primary_email = BooleanField() verified = BooleanField()
class Case(Document): """Represents a case (family) of individuals (samples).""" # This is a string with the id for the family: case_id = StringField(primary_key=True, required=True) # This is the string that will be shown in scout: display_name = StringField(required=True) # This is the owner of the case. E.g. 'cust003' owner = StringField(required=True) # These are the names of all the collaborators that are allowed to view the # case, including the owner collaborators = ListField(StringField()) assignee = ReferenceField('User') individuals = ListField(EmbeddedDocumentField(Individual)) created_at = DateTimeField(default=datetime.now) updated_at = DateTimeField(default=datetime.now) suspects = ListField(ReferenceField('Variant')) causative = ReferenceField('Variant') # The synopsis is a text blob synopsis = StringField(default='') status = StringField(default='inactive', choices=STATUS) is_research = BooleanField(default=False) # default_gene_lists specifies which gene lists that should be shown when # the case is opened default_gene_lists = ListField(StringField()) clinical_gene_lists = ListField(EmbeddedDocumentField(GeneList)) research_gene_lists = ListField(EmbeddedDocumentField(GeneList)) dynamic_gene_list = ListField(DictField()) genome_build = StringField() genome_version = FloatField() analysis_date = StringField() gender_check = StringField(choices=['unconfirmed', 'confirm', 'deviation'], default='unconfirmed') phenotype_terms = ListField(EmbeddedDocumentField(PhenotypeTerm)) # madeline info is a full xml file madeline_info = StringField() vcf_file = StringField() # The coverage report will be read as a binary blob coverage_report = BinaryField() @property def is_solved(self): """Check if the case is marked as solved.""" return self.status == 'solved' @property def hpo_gene_ids(self): """Parse out all HGNC symbols form the dynamic Phenomizer query.""" return [ term['gene_id'] for term in self.dynamic_gene_list if term['gene_id'] ] @property def bam_files(self): """Aggregate all BAM files across all individuals.""" return [ individual.bam_file for individual in self.individuals if individual.bam_file ] @property def all_gene_lists(self): """Yield all gene lists (both clinical and research).""" return itertools.chain(self.clinical_gene_lists, self.research_gene_lists) def __repr__(self): return "Case(case_id={0}, display_name={1}, owner={2})".format( self.case_id, self.display_name, self.owner)
class School(Document): code = IntField(required=True, primary_key=True) name = StringField(required=True) street = StringField(required=True) suburb = StringField(required=True) postcode = IntField(required=True) phone = StringField(required=True) email = EmailField(required=True) website = URLField(required=True) logo = URLField(required=False) fax = StringField(required=True) enrolments = IntField(required=True) level = StringField(required=True) opportunity_classes = BooleanField(requred=True) specialty_type = StringField(required=True) subtype = StringField(required=True) selective = StringField(required=True) gender = StringField(required=True) location = PointField(required=True) preschool = BooleanField(required=True) late_opening = BooleanField(required=True) intensive_english_centre = BooleanField(required=True) healthy_canteen = BooleanField(required=True) indigenous_pct = FloatField(required=True) lbote_pct = FloatField(required=True) icsea = IntField(required=True) support_classes = ListField(required=False) attendance_rate = FloatField(required=False) selective_entry_score = IntField(required=False) opportunity_classes_entry_score = IntField(required=False) train_station_id = StringField(required=False) train_station = StringField(required=False) train_distance = IntField(required=False) train_duration = IntField(required=False) meta = {'collection': 'schools'} def __init__(self, code, name, street, suburb, postcode, phone, email, website, fax, enrolments, level, opportunity_classes, specialty_type, subtype, selective, gender, location, preschool, late_opening, intensive_english_centre, healthy_canteen, indigenous_pct, lbote_pct, icsea, *args, **kwargs): super().__init__(*args, **kwargs) self.code = code self.name = name self.street = street self.suburb = suburb self.postcode = postcode self.phone = phone self.email = email self.website = website self.fax = fax self.enrolments = enrolments self.level = level self.opportunity_classes = opportunity_classes self.specialty_type = specialty_type self.subtype = subtype self.selective = selective self.gender = gender self.location = location self.preschool = preschool self.late_opening = late_opening self.intensive_english_centre = intensive_english_centre self.healthy_canteen = healthy_canteen self.indigenous_pct = indigenous_pct self.lbote_pct = lbote_pct self.icsea = icsea
class FileContentUnit(ContentUnit): """ A content unit representing content that is of type *file*. :ivar downloaded: Indicates whether all of the files associated with the unit have been downloaded. :type downloaded: bool """ downloaded = BooleanField(default=True) meta = { 'abstract': True, 'indexes': [ 'downloaded' ] } @classmethod def pre_save_signal(cls, sender, document, **kwargs): """ The signal that is triggered before a unit is saved. Ensures the _storage_path is populated. :param sender: sender class :type sender: object :param document: Document that sent the signal :type document: FileContentUnit """ super(FileContentUnit, cls).pre_save_signal(sender, document, **kwargs) if not document._storage_path: document.set_storage_path() def set_storage_path(self, filename=None): """ Set the storage path. This is a total hack to support existing single-file units with a _storage_path that includes the file name. :param filename: An optional filename to appended to the path. :rtype filename: str """ path = FileStorage.get_path(self) if filename: if not os.path.isabs(filename): path = os.path.join(path, filename) else: raise ValueError(_('must be relative path')) self._storage_path = path def import_content(self, path, location=None): """ Import a content file into platform storage. The (optional) *location* may be used to specify a path within the unit storage where the content is to be stored. For example: import_content('/tmp/file') will store 'file' at: _storage_path import_content('/tmp/file', 'a/b/c) will store 'file' at: _storage_path/a/b/c :param path: The absolute path to the file to be imported. :type path: str :param location: The (optional) location within the unit storage path where the content is to be stored. :type location: str :raises ImportError: if the unit has not been saved. :raises PulpCodedException: PLP0037 if *path* is not an existing file. """ if not self._last_updated: raise ImportError("Content unit must be saved before associated content" " files can be imported.") if not os.path.isfile(path): raise exceptions.PulpCodedException(error_code=error_codes.PLP0037, path=path) with FileStorage() as storage: storage.put(self, path, location) def save_and_import_content(self, path, location=None): """ Saves this unit to the database, then calls safe_import_content. :param path: The absolute path to the file to be imported :type path: str :param location: The (optional) location within the unit storage path where the content is to be stored. :type location: str """ self.save() self.safe_import_content(path, location) def safe_import_content(self, path, location=None): """ If import_content raises exception, cleanup and raise the exception :param path: The absolute path to the file to be imported :type path: str :param location: The (optional) location within the unit storage path where the content is to be stored. :type location: str """ try: self.import_content(path, location) except: self.clean_orphans() raise def clean_orphans(self): """ Exposes the ability to clean up this unit as an orphan. """ orphan_manger = factory.content_orphan_manager() orphan_manger.delete_orphan_content_units_by_type(self._content_type_id, self.id)
class Session(Document): parent_id = StringField() name = StringField(required=True) guild = StringField(required=True) description = StringField() channel_id = StringField() character = ReferenceField(Character) characters = ListField(StringField()) archived = BooleanField(default=False) history_id = StringField() started_on = DateTimeField() ended_on = DateTimeField() created_by = StringField() created = DateTimeField(required=True) updated_by = StringField() updated = DateTimeField(required=True) @classmethod def post_save(cls, sender, document, **kwargs): if document.history_id: user = User().get_by_id(document.updated_by) user.history_id = document.history_id user.updated_by = document.updated_by user.updated = document.updated user.save() print({'history_id': document.history_id}) else: changes = document._delta()[0] action = 'updated' if 'created' in kwargs: action = 'created' if kwargs['created'] else action if action == 'updated' and 'archived' in changes: action = 'archived' if changes['archived'] else 'restored' Log().create_new(str(document.id), document.name, document.updated_by, document.guild, 'Session', changes, action) user = User().get_by_id(document.updated_by) if user.history_id: user.history_id = None user.updated_by = document.updated_by user.updated = document.updated user.save() print(changes) @staticmethod def query(): return Session.objects @staticmethod def filter(**params): return Session.objects.filter(**params) def create_new(self, user, guild, channel_id, name, archived): self.name = name self.guild = guild self.channel_id = channel_id self.created_by = str(user.id) self.created = T.now() self.updated_by = str(user.id) self.updated = T.now() self.save() return self def find(self, guild, channel_id, name, archived=False): filter = Session.objects(guild=guild, channel_id=channel_id, name__icontains=name, archived=archived) session = filter.first() return session def get_or_create(self, user, guild, channel, name, archived=False): session = self.find(guild, str(channel.id), name, archived) if session is None: session = self.create_new(user, guild, str(channel.id), name, archived) session.character = Character().get_or_create( user, name, guild, session, 'Session', archived) session.save() return session def get_by_id(self, id): session = Session.objects(id=id).first() return session @classmethod def get_by_channel(cls, channel, archived=False, page_num=1, page_size=5): if page_num: offset = (page_num - 1) * page_size items = cls.filter( channel_id=str(channel.id), archived=archived).skip(offset).limit(page_size).all() else: items = cls.filter(channel_id=str(channel.id), archived=archived).order_by('name', 'created').all() return items @classmethod def get_by_page(cls, params, page_num=1, page_size=5): if page_num: offset = (page_num - 1) * page_size logs = cls.filter(**params).order_by( 'name', 'created').skip(offset).limit(page_size).all() else: logs = cls.filter(**params).order_by('name', 'created').all() return logs @classmethod def get_by_parent(cls, **params): items = cls.filter(**params).all() return [items] if items else [] def archive(self, user): self.reverse_archive(self.user) self.archived = True self.updated_by = str(user.id) self.updated = T.now() self.save() def reverse_archive(self, user): for s in Session().get_by_parent(parent_id=str(self.id)): s.reverse_archive(self.user) s.archived = True s.updated_by = str(user.id) s.updated = T.now() s.save() def restore(self, user): self.reverse_restore(self.user) self.archived = False self.updated_by = str(user.id) self.updated = T.now() self.save() def reverse_restore(self, user): for s in Session().get_by_parent(parent_id=str(self.id)): s.reverse_restore(self.user) s.archived = False s.updated_by = str(user.id) s.updated = T.now() s.save() def get_string_characters(self, user=None): characters = '\n '.join( f'***{c.name}***' + (' _(Active Character)_' if str(c.id) == user.active_character else '') for c in Character.filter( id__in=[ObjectId(id) for id in self.characters]) if c) return f'\n\n _Characters:_\n {characters}' def get_string(self, channel=None, user=None): if user and not user.time_zone: raise Exception( 'No time zone defined```css\n.d user timezone New_York```') name = f'***{self.name}***' active = '' if channel: active = ' _(Active Session)_ ' if str( self.id) == channel.active_session else '' start = '' if self.started_on: start = f'\n_Started On:_ ***{T.to(self.started_on, user)}***' if self.started_on else '' end = '' if self.ended_on: end = f'\n_Ended On:_ ***{T.to(self.ended_on, user)}***' if self.ended_on else '' description = f' - "{self.description}"' if self.description else '' characters = f'{self.get_string_characters(user)}' if self.characters else '' if self.character: name = f'***{self.character.name}***' if self.character.name else name description = f' - "{self.character.description}"' if self.character.description else description return f' {name}{active}{start}{end}{description}{characters}' def get_short_string(self, channel=None): name = f'***{self.name}***' active = '' if channel: active = ' _(Active Session)_ ' if str( self.id) == channel.active_session else '' return f' {name}{active}'
class DPVP(Request): full_name = 'Devolución proporcional del valor pagado por concepto de derechos de matrícula' percentage = FloatField(required=True, display='Porcentaje devuelto', default=0.0) cancel = BooleanField(required=True, display='¿Cancelación fue aprobada?', default=True) council_number = StringField(required=True, max_length=2, default='00', display='# Acta de cancelación') council_year = StringField(required=True, min_length=4, max_length=4, display='Año del Acta', default='0000') regulation_list = ['032|2010|CSU', '1416|2013|RE'] str_cm = [ 'devolución proporcional del {:0.2f} % del valor pagado por concepto de ' + 'derechos de matricula del periodo {}, teniendo en cuenta la fecha de ' + 'presentación de la solicitud y que {}le fue aprobada la cancelación ' + 'de periodo en Acta {} de {} de Consejo de Facultad.' ] str_pcm = [] def cm(self, docx): paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.str_council_header + ' ') self.cm_answer(paragraph) def cm_answer(self, paragraph): paragraph.add_run( # pylint: disable=no-member self.get_approval_status_display().upper() + ' ').font.bold = True self.add_text(paragraph) def pcm(self, docx): add_analysis_paragraph(docx, self.extra_analysis) paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.str_answer + ' ').font.bold = True paragraph.add_run(self.str_comittee_header + ' ') self.pcm_answer(paragraph) def pcm_answer(self, paragraph): paragraph.add_run( # pylint: disable=no-member self.get_advisor_response_display().upper() + ' ').font.bold = True self.add_text(paragraph) def add_text(self, paragraph): modifier = '' if self.cancel else 'no ' paragraph.add_run(self.str_cm[0].format(self.percentage, self.academic_period, modifier, self.council_number, self.council_year)) def resource_analysis(self, docx): last_paragraph = docx.paragraphs[-1] self.pcm_answer(last_paragraph) def resource_pre_answer(self, docx): last_paragraph = docx.paragraphs[-1] self.pcm_answer(last_paragraph) def resource_answer(self, docx): last_paragraph = docx.paragraphs[-1] self.cm_answer(last_paragraph)
class FileContentUnit(ContentUnit): """ A content unit representing content that is of type *file*. :ivar downloaded: Indicates whether all of the files associated with the unit have been downloaded. :type downloaded: bool """ downloaded = BooleanField(default=True) meta = {'abstract': True, 'indexes': ['downloaded']} @classmethod def pre_save_signal(cls, sender, document, **kwargs): """ The signal that is triggered before a unit is saved. Ensures the _storage_path is populated. :param sender: sender class :type sender: object :param document: Document that sent the signal :type document: FileContentUnit """ super(FileContentUnit, cls).pre_save_signal(sender, document, **kwargs) if not document._storage_path: document.set_storage_path() def set_storage_path(self, filename=None): """ Set the storage path. This is a total hack to support existing single-file units with a _storage_path that includes the file name. :param filename: An optional filename to appended to the path. :rtype filename: str """ path = FileStorage.get_path(self) if filename: if not os.path.isabs(filename): path = os.path.join(path, filename) else: raise ValueError(_('must be relative path')) self._storage_path = path def list_files(self): """ List absolute paths to files associated with this unit. This *must* be overridden by multi-file unit subclasses. :return: A list of absolute file paths. :rtype: list """ if self._storage_path and not os.path.isdir(self._storage_path): return [self._storage_path] else: return [] def import_content(self, path, location=None): """ Import a content file into platform storage. The (optional) *location* may be used to specify a path within the unit storage where the content is to be stored. For example: import_content('/tmp/file') will store 'file' at: _storage_path import_content('/tmp/file', 'a/b/c) will store 'file' at: _storage_path/a/b/c :param path: The absolute path to the file to be imported. :type path: str :param location: The (optional) location within the unit storage path where the content is to be stored. :type location: str :raises PulpCodedException: PLP0036 if the unit has not been saved. :raises PulpCodedException: PLP0037 if *path* is not an existing file. """ if not self._last_updated: raise exceptions.PulpCodedException(error_code=error_codes.PLP0036) if not os.path.isfile(path): raise exceptions.PulpCodedException(error_code=error_codes.PLP0037, path=path) with FileStorage() as storage: storage.put(self, path, location)
class Comment(Document): _id = ObjectIdField() user = StringField(required=True) comment = StringField(required=True) is_thread = BooleanField(default=False), previous_comment = ObjectIdField()
class EREP(Request): full_name = 'Expedición de recibo' ah_active = BooleanField(required=True, display='¿Tiene activa la historia académica?', default=False) payment_date = DateField(display='Fecha límite de pago') regulation_list = ['051|2003|CSU'] # List of regulations str_cm = [ 'presentar con concepto positivo al Comité de Matrículas de la Sede Bogotá, ' + 'la expedición de un único recibo correspondiente a los derechos académicos y ' + 'administrativos para el periodo académico {}', ' y se le concede como fecha de ' + 'pago el {} ({}), teniendo en cuenta el estado de pago por parte de {}.' ] list_analysis = ['El estudiante {}tiene la historia académica activa.'] def cm(self, docx): paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) self.cm_answer(paragraph) def cm_answer(self, paragraph): paragraph.add_run(self.str_council_header + ' ') paragraph.add_run( # pylint: disable=no-member self.get_approval_status_display().upper() + ' ').font.bold = True paragraph.add_run(self.str_cm[0].format(self.academic_period)) if self.is_affirmative_response_approval_status(): self.cm_af(paragraph) else: self.cm_ng(paragraph) def pcm(self, docx): self.pcm_analysis(docx) self.pcm_answer(docx) def pcm_answer(self, docx): paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.str_answer + ': ').font.bold = True paragraph.add_run(self.str_comittee_header + ' ') paragraph.add_run( # pylint: disable=no-member self.get_advisor_response_display().upper()).font.bold = True paragraph.add_run(' ' + self.str_cm[0].format(self.academic_period)) if self.is_affirmative_response_advisor_response(): self.pcm_answers_af(paragraph) else: self.pcm_answers_ng(paragraph) def cm_af(self, paragraph): paragraph.add_run(self.str_cm[1].format( self.payment_date, string_to_date(str(self.payment_date)), self.student_name)) def cm_ng(self, paragraph): paragraph.add_run(self.council_decision + '.') def pcm_analysis(self, docx): active = '' if self.ah_active else 'no ' final_analysis = [] final_analysis += [self.list_analysis[0].format(active)] for extra_a in self.extra_analysis: final_analysis += [extra_a] add_analysis_paragraph(docx, final_analysis) def pcm_answers_af(self, paragraph): paragraph.add_run(self.str_cm[1].format( self.payment_date, string_to_date(str(self.payment_date)), self.student_name)) def pcm_answers_ng(self, paragraph): paragraph.add_run(self.council_decision + '.')
class User(UserMixin, db.Document): """ 用户模型 继承于数据库模型和 flask-login 的用户模型 """ uid = SequenceField() name = StringField(max_length=64, unique=True, required=True) email = StringField(max_length=64, unique=True, required=True) password_hash = StringField(max_length=128) confirmed = BooleanField(default=False) since = DateTimeField(default=datetime.utcnow()) gender = BooleanField(default=True) interests = ListField(StringField(max_length=64)) @property def password(self): """ pasword 属性只有 setter 没有 getter :return: Error """ raise AttributeError('password is not readable') @password.setter def password(self, password): """ 设置 password 散列值 :param password: password :return: None """ self.password_hash = generate_password_hash(password) def verify_password(self, password): """ 验证密码 :param password: 输入的密码 :return: bool """ return check_password_hash(self.password_hash, password) def generate_confirmation_token(self, expiration=3600): """ 生成确认令牌 默认过期时间为1小时 :param expiration: 过期时间 :return: token """ s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'confirm': str(self.id)}) def confirm(self, token): """ 令牌确认,更改 confirmed 字段 :param token: token :return: bool """ s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('confirm') != str(self.id): return False self.confirmed = True self.save() return True def __repr__(self): return '<User %r>' % self.name
class WebInfo(Document): # for whatweb cms Target = ReferenceField('Target', reverse_delete_rule=CASCADE) Data = DictField() IsValid = BooleanField(default=True)
class HostInfo(Document): # for nmap Target = ReferenceField('Target', reverse_delete_rule=CASCADE) Ip = StringField() Data = DictField() IsValid = BooleanField(default=True)
class User(Document, UserMixin): email = StringField(max_length=255) password = StringField(max_length=255) active = BooleanField(default=True) confirmed_at = DateTimeField() roles = ListField(ReferenceField(Role), default=[])
class CRITsConfig(CritsDocument, Document): """ CRITs Configuration Class. """ from django.conf import settings meta = { "collection": settings.COL_CONFIG, "crits_type": 'Config', "latest_schema_version": 1, "schema_doc": { }, } allowed_hosts = ListField(StringField(), default=['*']) classification = StringField(default='unclassified') company_name = StringField(default='My Company') create_unknown_user = BooleanField(default=False) crits_message = StringField(default='') crits_email = StringField(default='') crits_email_subject_tag = StringField(default='') crits_email_end_tag = BooleanField(default=True) # This is actually the internal DB version, but is named crits_version # for historical reasons. crits_version = StringField(required=True, default=settings.CRITS_VERSION) debug = BooleanField(default=True) depth_max = IntField(default=10) email_host = StringField(default='') email_port = StringField(default='') enable_api = BooleanField(default=False) enable_toasts = BooleanField(default=False) git_repo_url = StringField(default='https://github.com/crits/crits') http_proxy = StringField(default='') instance_name = StringField(default='My Instance') instance_url = StringField(default='') invalid_login_attempts = IntField(default=3) language_code = StringField(default='en-us') ldap_auth = BooleanField(default=False) ldap_tls = BooleanField(default=False) ldap_server = StringField(default='') ldap_usercn = StringField(default='') ldap_userdn = StringField(default='') ldap_update_on_login = BooleanField(default=False) log_directory = StringField(default=os.path.join(settings.SITE_ROOT, '..', 'logs')) log_level = StringField(default='INFO') password_complexity_desc = StringField(default='8 characters, at least 1 capital, 1 lowercase and 1 number/special') password_complexity_regex = StringField(default='(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$') query_caching = BooleanField(default=False) rel_max = IntField(default=50) remote_user = BooleanField(default=False) rt_url = StringField(default='') secure_cookie = BooleanField(default=True) service_dirs = ListField(StringField()) service_model = StringField(default='process') service_pool_size = IntField(default=12) session_timeout = IntField(default=12) splunk_search_url = StringField(default='') temp_dir = StringField(default='/tmp') timezone = StringField(default='America/New_York') total_max = IntField(default=250) totp_web = StringField(default='Disabled') totp_cli = StringField(default='Disabled') zip7_path = StringField(default='/usr/bin/7z') zip7_password = StringField(default='infected') def migrate(self): """ Migrate the Configuration Schema to the latest version. """ pass
class User(YetiDocument): available_settings = dict() username = StringField(required=True, unique=True) password = StringField() enabled = BooleanField(required=True, default=True) permissions = DictField(verbose_name="Permissions") settings = DictField(verbose_name="Settings") api_key = StringField(required=True, unique=True) session_token = StringField() SEARCH_ALIASES = {} @property def is_authenticated(self): return self.enabled @property def is_admin(self): return self.permissions.get('admin', False) @property def is_active(self): return self.enabled @property def is_anonymous(self): return False def get_id(self): return unicode(self.session_token) def has_settings(self, settings): for setting in settings: if setting not in self.settings: return False return True def has_permission(self, object_name, permission): return self.permissions.get(object_name, {}).get(permission) def has_role(self, role): return self.permissions.get(role, False) def __unicode__(self): return u"<User: {}>".format(self.username) @classmethod def get_form(klass): return model_form(User) @classmethod def register_setting(klass, id, name, description): klass.available_settings[id] = { 'name': name, 'description': description } @classmethod def get_available_settings(klass): # We have to load all OneShotAnalytics in order to make sure # available_settings are up to date from core.analytics import OneShotAnalytics list(OneShotAnalytics.objects) return klass.available_settings @staticmethod def generate_api_key(): return os.urandom(40).encode('hex') def info(self): i = {k: v for k, v in self._data.items() if k in ["username", "enabled", "permissions", "api_key"]} i['url'] = url_for("api.UserAdmin:post", id=str(self.id), _external=True) i['human_url'] = url_for("frontend.UsersView:profile", id=str(self.id), _external=True) return i
class APGD(Request): class Coadvisor(EmbeddedDocument): name_co_advisor = StringField(display='Nombre del codirector', required=True, default='') inst_co_advisor = StringField( display='Departamento de adscripción del codirector', default=Request.DP_CIVIL_AGRICOLA, required=True, choices=Request.DP_CHOICES) co_advisor_ext = StringField(display='Institución externa', default='') full_name = 'Aprobación de propuesta de proyecto de tesis de maestria y ' +\ 'designación de director y co-director' GO_TRABAJO_FINAL_MAESTRIA = 'TFM' GO_TESIS_MAESTRIA = 'TSM' GO_TESIS_DOCTORADO = 'TSD' GO_CHOICES = ((GO_TRABAJO_FINAL_MAESTRIA, 'Trabajo Final de Maestría'), (GO_TESIS_MAESTRIA, 'Tesis de Maestría'), (GO_TESIS_DOCTORADO, 'Tesis de Doctorado')) IG_OWNERSHIP = 'OS' IG_NOT_OWNERSHIP = 'NO' IG_UNDEFINED = 'UN' IG_CHOICES = ( (IG_OWNERSHIP, 'Sí pertenece'), (IG_NOT_OWNERSHIP, 'No pertenece'), (IG_UNDEFINED, 'No dice o no se sabe'), ) CP_APROBADA = 'AP' CP_NO_APROBADO = 'NA' CP_CHOICES = ( (CP_APROBADA, 'aprobado'), (CP_NO_APROBADO, 'no aprobado'), ) grade_option = StringField( required=True, # display='Tipo de tesis/trabajo final', choices=GO_CHOICES, default=GO_TESIS_MAESTRIA) enrolled_proyect = BooleanField( required=True, default=False, display='¿Tiene inscrita la asignatura proyecto de tesis?') have_signature = BooleanField( required=True, default=False, display='¿Tiene la firma del (los) director(es)?') enrroled_periods = IntField(min_value=1, default=1, display='Número de matrícula actual', required=True) cd_delivered = BooleanField(required=True, default=False, display='¿Entregó CD?') general_objetive = StringField(required=True, display='Objetivo general', default='') specific_objetives = ListField(StringField(), display='Objetivos específicos') title = StringField(required=True, display='Título de la tesis', default='') ownership_ig = StringField( required=True, choices=IG_CHOICES, default=IG_UNDEFINED, display='¿El proyecto hace parte de un grupo de investigación?') advisor = StringField(display='Director de tesis', default='', required=True) advisor_inst = StringField( display='Departamento de adscripción del director', required=True, choices=Request.DP_CHOICES, default=Request.DP_EMPTY) advisor_ext = StringField(display='Institución externa', default='') co_advisor_list = EmbeddedDocumentListField(Coadvisor, display='Codirector(es)') grade_proyect = StringField(required=True, display='Calificación del proyecto', choices=CP_CHOICES, default=CP_APROBADA) regulation_list = ['040|2017|CFA', '056|2012|CSU'] # List of regulations str_cm = [ 'Calificación {} ({}) a {} de {}, cuyo título es:', 'Designar director', 'Designar codirector', 'al profesor', 'del', 'de la institución', 'de', 'cuyo título es', 'Debido a que' ] list_analysis = [ 'Perfil de {}.', 'El estudiante {}tiene inscrita la asignatura {}.', 'Estudiante de matrícula número {}.', 'ntregó CD.', 'iene la firma del (los) director(es) de tesis/trabajo final:', 'El proyecto de tesis debe inscribirse y entregarse, antes de alcanzar el 50' + '% de la duración establecida para el programa (Parágrafo Artículo 14 del ' + '{})', 'Título:', 'Objetivo general:', 'Objetivos específicos:' ] def cm(self, docx): paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.str_council_header + ' ') self.cm_answer(paragraph) self.cm_grade(docx) if self.is_affirmative_response_approval_status(): self.cm_design(docx) else: paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(' ' + self.str_cm[8] + ' ' + self.council_decision + '.') def cm_answer(self, paragraph): # pylint: disable=no-member paragraph.add_run(self.get_approval_status_display().upper() + ':').font.bold = True def pcm(self, docx): self.pcm_analysis(docx) paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.str_answer + ': ').font.bold = True paragraph.add_run(self.str_comittee_header + ' ') self.pcm_answer(paragraph) self.cm_grade(docx) if self.is_affirmative_response_advisor_response(): self.cm_design(docx) else: paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(' ' + self.str_cm[8] + ' ' + self.council_decision + '.') def pcm_answer(self, paragraph): # pylint: disable=no-member paragraph.add_run(self.get_advisor_response_display().upper() + ':').font.bold = True def pcm_analysis(self, docx): # pylint: disable=no-member if self.grade_option in [ self.GO_TESIS_MAESTRIA, self.GO_TESIS_DOCTORADO ]: profile = 'investigación' else: profile = 'profundización' type_subject = 'Proyecto' if self.grade_option in [ self.GO_TESIS_MAESTRIA, self.GO_TESIS_DOCTORADO ] else 'Propuesta' final_analysis = [] final_analysis += [self.list_analysis[0].format(profile)] ets = '' if self.enrolled_proyect else 'no ' final_analysis += [ self.list_analysis[1].format( ets, type_subject + ' ' + self.get_grade_option_display()) ] final_analysis += [self.list_analysis[2].format(self.enrroled_periods)] cdd = 'E' if self.cd_delivered else 'No e' final_analysis += [cdd + self.list_analysis[3]] hss = 'T' if self.have_signature else 'No t' final_analysis += [ hss + self.list_analysis[4] + ' ' + self.advisor + '.' ] final_analysis += [ self.list_analysis[5].format( Request.regulations['056|2012|CSU'][0]) + '.' ] add_analysis_paragraph(docx, final_analysis) paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.style = 'List Bullet' paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.list_analysis[6] + ' ').font.bold = True paragraph.add_run(self.title + '.').font.italic = True paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.style = 'List Bullet' paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.list_analysis[7] + ' ').font.bold = True paragraph.add_run(self.general_objetive + '.') paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.style = 'List Bullet' paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.list_analysis[8]).font.bold = True for spec_ob in self.specific_objetives: paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.style = 'List Bullet 2' paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(spec_ob + '.') for ex_an in self.extra_analysis: paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.style = 'List Bullet' paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(ex_an + '.') def cm_grade(self, docx): # pylint: disable=no-member paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.style = 'List Bullet' paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.str_cm[0].format( self.grade_proyect, self.get_grade_proyect_display(), self.get_grade_option_display(), self.get_academic_program_display())) paragraph.add_run(' "{}".'.format(self.title)).font.italic = True def cm_design(self, docx): # pylint: disable=no-member paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.style = 'List Bullet' paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.str_cm[1] + ' ') paragraph.add_run(self.str_cm[6] + ' ' + self.get_grade_option_display() + ' ' + self.str_cm[7]) paragraph.add_run(' "{}" '.format(self.title)).font.italic = True paragraph.add_run(self.str_cm[3] + ' ') paragraph.add_run(self.advisor) if self.advisor_inst == Request.DP_EXTERNO_FACULTAD: paragraph.add_run(' ' + self.str_cm[5] + ' ' + self.advisor_ext + '.') else: paragraph.add_run(' ' + self.str_cm[4] + ' ' + self.get_advisor_inst_display() + '.') if self.co_advisor_list != []: for co_advc in self.co_advisor_list: paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.style = 'List Bullet' paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.str_cm[2] + ' ') paragraph.add_run(self.str_cm[6] + ' ' + self.get_grade_option_display() + ' ' + self.str_cm[7]) paragraph.add_run(' "{}" '.format( self.title)).font.italic = True paragraph.add_run(self.str_cm[3] + ' ') paragraph.add_run(co_advc.name_co_advisor) if co_advc.inst_co_advisor == Request.DP_EXTERNO_FACULTAD: paragraph.add_run(' ' + self.str_cm[5] + ' ' + co_advc.co_advisor_ext + '.') else: paragraph.add_run(' ' + self.str_cm[4] + ' ' + co_advc.get_inst_co_advisor_display() + '.') def resource_analysis(self, docx): last_paragraph = docx.paragraphs[-1] self.pcm_answer(last_paragraph) def resource_pre_answer(self, docx): last_paragraph = docx.paragraphs[-1] self.pcm_answer(last_paragraph) def resource_answer(self, docx): last_paragraph = docx.paragraphs[-1] self.cm_answer(last_paragraph)
class Transaction(DynamicDocument): created_at = DateTimeField(default=datetime.datetime.now) tag = StringField() channel = StringField(choices=ChannelNameChoices.choices) decision = ReferenceField(DecisionSignal) pair = StringField(choices=pairs_without_slash, required=True) take_profits = ListField(EmbeddedDocumentField('TakeProfit')) stop_loss = EmbeddedDocumentField('StopLoss') initial_pair_price = DecimalField(precision=6) initial_pair_price_retries = IntField() amount_invested = IntField() result = DecimalField(precision=6) result_ratio = FloatField() date_open = DateTimeField() date_closed = DateTimeField() status = StringField(choices=TransactionStatusChoices.choices) closed_by = StringField(choices=TransactionClosedByChoices.choices) duration = FloatField(default=None) is_ratio_suspicious = BooleanField(default=None) strategy_label = StringField() @property def profit_result(self): result = 0 return result @property def history(self): return def assign_take_profits_from_strategy(self, assigned_amount, strategy, tp_closed_dates): take_profits_length = len(self.decision.take_profits) distribution = strategy.get(take_profits_length) if distribution is None: logger.error("add some extra distribution") take_profits = [] if len(self.decision.take_profits) != len(tp_closed_dates): raise Exception("Incompatiblity") for tp, closed_date in zip(self.decision.take_profits, tp_closed_dates.values()): if closed_date == PositionCloseDetector.NOT_FOUND: closed_date = None try: distribution_percentage = distribution[tp['order_number']] except KeyError: if len(self.decision.take_profits) == 1: distribution_percentage = 1 tp['order_number'] = 1 else: distribution_percentage = 0 if distribution_percentage != 0: if list(distribution.values()).count(1) == 1: tp['is_last'] = True take_profit = TakeProfit( **tp, closed_date=closed_date, amount_invested=assigned_amount*distribution_percentage ) take_profits.append(take_profit) try: if take_profits[-1]['is_last'] == False: logger.error('incorrect situation') take_profits[-1]['is_last'] = True except Exception: logger.error('Jaki exception ląduje?') return take_profits def get_event_id_cancel(self): return "{transaction_id}_cancel".format(transaction_id=self.id) def get_stop_loss_result(self): """ There can be situation that stop loss has been triggered after 1 from 3 realised take_profits so in this case we realise StopLoss with 66% of invested money If 2 of 3 take profits are realised then we return 1/3*stop_loss.amount_invested """ not_realised_take_profits = [tp for tp in self.take_profits if tp.is_closed is False] result = sum([tp.amount_invested for tp in not_realised_take_profits]) return result def get_last_occured_event(self): take_profits_dates = { tp['order_number']: tp['closed_date'] for tp in self.take_profits if tp['closed_date'] is not None } if self.stop_loss['closed_date'] != None: stop_loss_date = {'sl': self.stop_loss['closed_date']} else: stop_loss_date = {} zbior = { **take_profits_dates, **stop_loss_date } zbior_sorted = sorted(zbior.items(), key=lambda d: d[1], reverse=True) last_event = zbior_sorted[0] if last_event[0] == 'sl': return 'sl' elif isinstance(last_event[0], int): return 'tp' else: logger.error(f'LastEvent value error: {last_event[0]}') def on_last_take_profit_or_stop_loss_reached(self, closed_by, date_closed=None, duration=None): self.status = TransactionStatusChoices.CLOSED self.date_closed = date_closed self.closed_by = closed_by self.result = self.get_result() self.result_ratio = self.result/self.amount_invested self.duration = duration if self.is_result_suspicious(): self.is_ratio_suspicious = True self.result = self.amount_invested else: self.is_ratio_suspicious = False self.save() def on_initial_price_not_found(self): self.status = TransactionStatusChoices.INITIAL_PRICE_NOT_FOUND self.save() def get_closed_take_profits_result(self): result = 0 for tp in self.take_profits: if tp.is_closed: if tp.result is not None: result += tp.result else: # is closed without result ? some error.... result += tp.amount_invested return result def get_result(self): if self.closed_by == TransactionClosedByChoices.TAKE_PROFIT: try: return self.get_closed_take_profits_result() except TypeError: take_profit_result = 0 pass elif self.closed_by == TransactionClosedByChoices.STOP_LOSS: closed_take_profits_result = self.get_closed_take_profits_result() return closed_take_profits_result+(self.amount_invested-closed_take_profits_result)*self.stop_loss.ratio else: return self.amount_invested def is_result_suspicious(self): return self.result_ratio < 0.9 or self.result_ratio > 1.1 or \ (self.closed_by == 'take_profit' and self.result < self.amount_invested) or \ (self.closed_by =='stop_loss' and self.result > self.amount_invested) def cancel_all(self): for take_profit in self.decision.take_profits: take_profit.cancel() def cancel_particular(self, take_profit): take_profit.cancel() pass def add_hold_days(self, days): self.duration += days def change_stop_loss(self): pass def change_take_profit(self, take_profit): pass def add_take_profit(self, take_profit): pass
class Message(Document): msg = StringField() sender = ObjectIdField() reciever = ObjectIdField() isRead = BooleanField(default=False) createdAt = DateTimeField(default=datetime.now())
class User(Document, UserMixin): public_id = StringField(default=str(uuid.uuid4())) name = StringField() username = StringField(required=True, unique=True) password_hash = StringField() roles = ListField(default=[]) active = BooleanField(default=True) def __init__(self, *args, **kwargs): if "password" in kwargs and kwargs.get("password") is not None: kwargs["password_hash"] = generate_password_hash( kwargs.pop("password"), method='sha256') # if "roles" in kwargs: # roles = kwargs.pop("roles") # o_roles = [] # if isinstance(roles, str): # roles = roles.split(",") # for role in roles: # if isinstance(role, str): # o_role = Role.objects(name=role).first() # if o_role: # o_roles.append(o_role) # elif isinstance(role, Role): # o_roles.append(role) # kwargs["roles"] = o_roles if kwargs.pop("admin", False): # o_admin = Role.objects(name__iexact="admin").first() # kwargs["roles"] = kwargs.get("roles",[]).append(o_admin) kwargs["roles"] = kwargs.get("roles", []) + ["admin"] super().__init__(*args, **kwargs) def to_barn_dict(self): return dict(name=self.name, username=self.username, public_id=self.public_id, type="user", active=self.active, roles=self.roles) def reset_password(self, password): self.password_hash = generate_password_hash(password, method='sha256') def __repr__(self): return '<User %r>' % (self.name) def get_id(self): return self.public_id def has_role(self, role): return role in self.roles def get_roles(self): return [RoleNeed(**{'value': role}) for role in self.roles] def isadmin(self): if self.roles is not None and "admin" in self.roles: return True return False def missing_roles(self, roles): missing_roles = [] if self.isadmin(): return [] for role in roles: if not self.has_role(role): missing_roles.append(role) return missing_roles def __hash__(self): return hash((self.name, self.username, self.public_id, self.password_hash, self.active, frozenset(self.roles)))
class SignatureAccess(EmbeddedDocument, CritsDocumentFormatter, CommonAccess): """ ACL for Signatures. """ upload_new_version = BooleanField(default=False) data_type_read = BooleanField(default=False) data_type_edit = BooleanField(default=False) data_type_min_version_read = BooleanField(default=False) data_type_min_version_edit = BooleanField(default=False) data_type_max_version_read = BooleanField(default=False) data_type_max_version_edit = BooleanField(default=False) data_read = BooleanField(default=False) data_edit = BooleanField(default=False) dependencies_read = BooleanField(default=False) dependencies_edit = BooleanField(default=False)
class Link(Document): """Collection representing a shortened url""" long_url_index_spec = [('long_url', 'hashed')] meta = { 'auto_create_index': settings.MONGO_AUTO_CREATE_INDEXES, # We can't used a "hashed" index on hash because it needs to be unique 'indexes': [('hash', ), long_url_index_spec] } hash = StringField(required=True, unique=True) long_url = StringField(required=True) act_as_proxy = BooleanField() clicks = IntField(default=0) @classmethod def find_for_prefix(cls, prefix): """Retrieves all Link objects where the hash starts with a specific prefix If you do not give a prefix (or prefix='') this is not going to be indexed, so make sure you filter on another field that is actually indexed. """ if prefix: return cls.objects(hash__startswith=('%s/' % prefix.lower())) else: return cls.objects(hash__not__contains='/') @classmethod def find_for_prefix_and_long_url(cls, prefix, long_url): """Retrieves Link objects for a specific long_url that also match a specific prefix""" # For some reason, we need to hint explictly at the index to use return cls.find_for_prefix(prefix).filter(long_url=long_url).hint( cls.long_url_index_spec) @classmethod def shorten(cls, long_url, short_path=None, prefix=None): """Public API to create a short link""" ForbiddenKeyword.raise_if_banned(short_path) ForbiddenKeyword.raise_if_banned(prefix) if prefix is None: prefix = '' if short_path is None or not len(short_path): link = cls.find_for_prefix_and_long_url(prefix, long_url).first() if link is None: link = cls.create_with_random_short_path(long_url, prefix) else: link, created = cls.__get_or_create(prefix, short_path, long_url) if not created and link.long_url != long_url: raise ShortPathConflict(link) link.save() return link @classmethod def create_with_random_short_path(cls, long_url, prefix): """Generate an unused, valid random short path for prefix""" nb_tries = 0 while True: # Generate a seed from the long url and the current date (with milliseconds) seed = "%s%s%s" % (long_url, datetime.utcnow(), nb_tries) hashed = int(sha1(seed).hexdigest(), 16) mod = 1 while hashed > mod: mod *= 10 nb_tries += 1 short_path = int_to_alnum.encode(hashed % mod) if not cls.is_valid_random_short_path(short_path): continue link, created = cls.__get_or_create(prefix, short_path, long_url) if created: # Short path didn't exist, store number of tries and we're done statsd.histogram('workforus.nb_tries_to_generate', nb_tries, tags=['prefix:' + prefix]) return link RE_VALID_RANDOM_SHORT_PATHS = re.compile(r'^([a-z]{0,2}\d)+[a-z]{0,2}$') @classmethod def is_valid_random_short_path(cls, short_path): """Checks if the random short path is valid (does not contain words)""" # We don't check for ForbiddenKeywords because the constraints make that redundant return cls.RE_VALID_RANDOM_SHORT_PATHS.match(short_path) is not None @classmethod def __get_or_create(cls, prefix, short_path, long_url): """Retrieves or Creates a Link object by (prefix, short_path)""" # pylint: disable=W0511 # FIXME: Deprecated in MongoEngine 0.8 - https://work4labs.atlassian.net/browse/OPS-1529 return cls.objects.get_or_create( hash=Link.hash_for_prefix_and_short_path(prefix, short_path), defaults={'long_url': long_url}) @classmethod def hash_for_prefix_and_short_path(cls, prefix, short_path): """Returns the hash for a combination of prefix and short_path""" return ('%s%s' % ('%s/' % prefix if prefix != '' else '', short_path)).lower() @classmethod def find_by_hash(cls, path): """Searches for a Link object by hash""" return cls.objects(hash=path.lower()).first() @property def prefix(self): """If present, return the prefix""" if '/' not in self.hash: return '' return self.hash.split('/')[0] def click(self): """Register a click on this link""" self.__class__.objects(hash=self.hash).update_one(inc__clicks=1) def build_relative_path(self): """Builds the relative path for the current url (since we only store the hash, we get a lowercase version)""" return '/%s' % self.hash def build_absolute_uri(self, request): """Builds the absolute url for the target link (including full server url)""" return request.build_absolute_uri(self.build_relative_path()) def __str__(self): return "%s -> %s\n" % (self.hash, self.long_url)
class User(Document): meta = {"collection": "Users", 'allow_inheritance': True} first_name = StringField(required=True) last_name = StringField(required=True) username = StringField(required=True) moderator = BooleanField(required=True, default=False) locale = 'en_GB' points = IntField(required=True, default=0) cursors = DictField() has_read_welcome_msg = BooleanField(required=True, default=False) has_paid = BooleanField(required=True, default=False) payment_details = EmbeddedDocumentField(UserPaymentDetails) price = StringField(required=True, default="4.99") def record_payment(self, transaction_id, receipt_id): ''' Records the payment ''' self.has_paid = True pd = UserPaymentDetails() pd.transaction_id = transaction_id pd.receipt_id = receipt_id self.payment_details = pd self.save() def toggle_moderator(self): self.moderator = not self.moderator self.save() def update_section_cursor(self, section_id, section_length, current_cursor): self.cursors.setdefault(section_id, 0) #Only increment cursor if this is an unseen nugget and we havent' finished studying the section if current_cursor >= self.cursors[ section_id] and current_cursor + 1 < section_length: self.cursors[section_id] += 1 self.save() def get_section_cursor(self, section_id): #Get either the first nugget of the section or where the user left it off. return self.cursors.has_key( section_id) and self.cursors[section_id] or 0 def update_points(self, score): self.points += score * 10 self.save() def get_user_stats(self): ''' calculates user stats and returns a dict. ''' try: stats = {} test_history = Test.objects(user=str(self.id)) if len(test_history) != 0: no_of_correct_answers = 0 for test in test_history: no_of_correct_answers += test.score stats['correct_answers'] = no_of_correct_answers #count total questions total_questions_answered = 0 for test in test_history: if isinstance(test, MockTest): total_questions_answered += 50 elif isinstance(test, PractiseTest): total_questions_answered += 20 stats['accuracy'] = 0 if total_questions_answered != 0: stats['accuracy'] = 100 * no_of_correct_answers / float( total_questions_answered) stats['total_questions_answered'] = total_questions_answered else: stats['correct_answers'] = 0 stats['accuracy'] = 0 stats['total_questions_answered'] = 0 stats[ 'points'] = self.points #The user may receive points without completing a test. We're good people return stats except Exception, e: print e
class SessionConfigs(Document): sesssionExpirationTime = LongField(required=True, default=60) carryOverSlots = BooleanField(required=True, default=True) bot = StringField(required=True) user = StringField(required=True) timestamp = DateTimeField(default=datetime.utcnow)
class Roles(EmbeddedDocument): """ Roles Permission """ admin: BooleanField = BooleanField(default=False)
class Book(Document): name = StringField() pages = IntField() tags = ListField(StringField()) is_published = BooleanField() author_email = EmailField()
class Domain(CritsBaseAttributes, CritsSourceDocument, Document): """ Domain Class. """ meta = { "collection": settings.COL_DOMAINS, "crits_type": 'Domain', "latest_schema_version": 2, "schema_doc": { 'analyst': 'Analyst who added/modified this domain', 'domain': 'The domain name of this domain', 'type': 'Record type of this domain', 'watchlistEnabled': 'Boolean - whether this is a domain to watch', 'whois': 'List [] of dictionaries of whois data on given dates', }, "jtable_opts": { 'details_url': 'crits.domains.views.domain_detail', 'details_url_key': 'domain', 'default_sort': "domain ASC", 'searchurl': 'crits.domains.views.domains_listing', 'fields': [ "domain", "modified", "source", "campaign", "status", "id"], 'jtopts_fields': [ "details", "domain", "modified", "source", "campaign", "status", "favorite", "id"], 'hidden_fields': [], 'linked_fields': ["source", "campaign"], 'details_link': 'details', 'no_sort': ['details'] } } domain = StringField(required=True) record_type = StringField(default="A", db_field="type") watchlistEnabled = BooleanField(default=False) whois = ListField(EmbeddedDocumentField(EmbeddedWhoIs)) analyst = StringField() def migrate(self): """ Migrate to the latest schema version. """ migrate_domain(self) def _custom_save(self, force_insert=False, validate=True, clean=False, write_concern=None, cascade=None, cascade_kwargs=None, _refs=None, username=None, **kwargs): """ Custom save. Overrides default core custom save function. """ #TODO: parse for potential root domain and add it as well? # - would require adding relationships between the two as well return super(self.__class__, self)._custom_save(force_insert, validate, clean, write_concern, cascade, cascade_kwargs, _refs, username) def add_whois(self, data, analyst, date=None, editable=True): """ Add whois information to the domain. :param data: The contents of the whois. :type data: str :param analyst: The user adding the whois. :type analyst: str :param date: The date for this whois entry. :type date: datetime.datetime :param editable: If this entry can be modified. :type editable: boolean :returns: :class:`crits.core.domains.domain.WhoisEntry` """ if not date: date = datetime.datetime.now() whois_entry = WhoisEntry(data).to_dict() e = EmbeddedWhoIs() e.date = date e.analyst = analyst e.editable = editable e.text = data e.data = whois_entry self.whois.append(e) return whois_entry def edit_whois(self, data, date=None): """ Edit whois information for the domain. :param data: The contents of the whois. :type data: str :param date: The date for this whois entry. :type date: datetime.datetime """ if not date: return for w in self.whois: if w.date == date: whois_entry = WhoisEntry(data).to_dict() w.data = whois_entry w.text = data def delete_whois(self, date): """ Remove whois information from the domain. :param date: The date for this whois entry. :type date: datetime.datetime """ if not date: return for w in self.whois: if w.date == date: self.whois.remove(w) break def whois_diff(self, from_date, to_date): """ Generate a diff between two whois entries. :param from_date: The date for the first whois entry. :type date: datetime.datetime :param to_date: The date for the second whois entry. :type date: datetime.datetime :returns: str, None """ from_whois = None to_whois = None for w in self.whois: if w.date == from_date: from_whois = str(WhoisEntry.from_dict(w.data)).splitlines(True) if w.date == to_date: to_whois = str(WhoisEntry.from_dict(w.data)).splitlines(True) if not from_whois or not to_whois: return None return unified_diff(from_whois, to_whois, fromfile=from_date, tofile=to_date) def to_cybox_observable(self): """ Convert a Domain 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 = DomainName() obj.value = self.domain obj.type_ = self.record_type return ([Observable(obj)], self.releasability) @classmethod def from_cybox(cls, cybox_obs): """ Convert a Cybox DefinedObject to a MongoEngine Domain object. :param cybox_obs: The cybox observable to create the Domain from. :type cybox_obs: :class:`cybox.core.Observable`` :returns: :class:`crits.domains.domain.Domain` """ cybox_object = cybox_obs.object_.properties db_obj = Domain.objects(domain=str(cybox_object.value)).first() if db_obj: return db_obj else: domain = cls() domain.domain = str(cybox_object.value) domain.record_type = str(cybox_object.type_) return domain
class User(DynamicDocument): email = StringField(max_length=255, api_public=True) password = StringField(max_length=255) first_name = StringField( api_public=True) last_name = StringField( api_public=True) phone_number = StringField(max_length=255, api_public=True) role = StringField(default='owner', api_public=True) date_account_claimed = DateTimeField(api_public=True) date_last_invite_sent = DateTimeField(api_public=True) accepted_tos_date = DateTimeField() accepted_tos_ip = StringField() websocket_session_id = StringField() trading_account_username = StringField() trading_account_token = StringField() confirmed_emails = ListField(StringField(), default=[], api_public=True) authy_id = StringField() enable_sound_alerts = BooleanField(default=False) enable_voice_alerts = BooleanField(default=False) def check_alerts(self): alerts = Alert.objects(user=self, is_open=True) for alert in alerts: alert.check() def check_trading_data(self): t = TradingService(token=self.trading_account_token) status = t.check() return status def clear_trading_account(self): self.trading_account_token = None self.trading_account_username = None self.save() def clear_positions(self): for position in Position.objects(is_open=True, user=self): position.remove() def stop_trading_data(self, token=None): token = token or self.trading_account_token t = TradingService(token=token) status = t.stop() self.clear_trading_account() self.clear_positions() return status def start_trading_data(self, username, password, trading_mode): self.stop_trading_data() websocket_endpoint = WEBSOCKET_ENDPOINT webhook_url = API_ENDPOINT + '/webhooks/trading_service' t = TradingService( username, password, trading_mode, websocket_endpoint=websocket_endpoint, startup_done_webhook=webhook_url, ) token, status = t.start() self.logger.info('STARTING') self.logger.info(token) self.logger.info(status) self.trading_account_token = token self.trading_account_username = username self.save() return status def send_confirm_email(self): link = self.confirm_email_link() subject = "Please confirm your email" message_data = { 'link': link, 'subject': subject, } self.send_message('confirm_email', message_data=message_data) def has_role(self, role_name): return role_name == self.role @staticmethod def hash_password(plaintext): plaintext = plaintext.encode('utf-8') hashed = bcrypt.hashpw(plaintext, bcrypt.gensalt()).decode('utf-8') return hashed @staticmethod def is_email_available(email, user): if user: existing_user = User.objects(email=email, id__ne=user.id).first() else: existing_user = User.objects(email=email).first() if not existing_user: return True return False @staticmethod def is_email_valid(email): return validate_email(email) @staticmethod def is_email_usable(email, user=None): email = email.lower().strip() if not User.is_email_available(email, user): return False, 'Email is in use' if not User.is_email_valid(email): return False, 'Email is invalid' return True, None def is_correct_password(self, plaintext): plaintext = plaintext.encode('utf-8') hashed_password = self.password.encode('utf-8') return bcrypt.checkpw(plaintext, hashed_password) def set_password(self, password): self.password = User.hash_password(password) self.save() def set_email(self, email): email = email.lower().strip() self.email = email self.save() def set_phone_number(self, phone_number): self.phone_number = phone_number self.save() self.create_authy() def password_changed(self): """tell user their password has changed""" message_data = {'subject': 'Your password has changed'} self.send_message(message_template='password_changed', message_data=message_data) def password_reset_link(self, invite=False): """generate password reset link""" token = self.generate_token() link = self.dashboard_url() + CHANGE_PASSWORD_ROUTE + '?token=' + token if invite: link += '&invite=true' return link def confirm_email_link(self): """generate confirm email link and return""" token = self.generate_token() link = self.dashboard_url() + '/confirm_email?token=' + token return link def send_invite(self, medium='email', message_template='invite_team', **data): """send invite link and send to user""" link = self.password_reset_link(invite=True) subject = "You've been invited to {}".format(BRAND_NAME) message_data = { 'link': link, 'subject': subject, } message_data.update(data) self.send_message(message_template=message_template, message_data=message_data, medium=medium) self.date_last_invite_sent = datetime.datetime.now() self.save() def claim_account(self): if not self.date_account_claimed: self.date_account_claimed = datetime.datetime.now() self.save() def dashboard_url(self): """get the dashboard url if this user""" url = DASHBOARD_ENDPOINT return url def send_password_reset(self): """generate password token and send to user""" link = self.password_reset_link() message_data = {'link': link, 'subject': 'Reset Your Password'} self.send_message(message_template='reset_your_password', message_data=message_data) def generate_token(self): """generate token used for password resets""" ts = URLSafeTimedSerializer(FLASK_SECRET_KEY) token = ts.dumps(self.email, salt=PASSWORD_RECOVER_KEY) return token @staticmethod def get_user_from_reset_token(token): """Returns user if token is right and token not expired""" ts = URLSafeTimedSerializer(FLASK_SECRET_KEY) email = ts.loads(token, salt=PASSWORD_RECOVER_KEY, max_age=86400) if email: user = User.objects(email=email).first() return user def full_name(self): return "{} {}".format(self.first_name.encode('utf-8').decode('utf-8'), self.last_name.encode('utf-8').decode('utf-8')) def request_two_factor_token(self): if not self.authy_id: raise Exception('No Authy id for this user') sms = authy_api.users.request_sms(self.authy_id, {'force': True}) def validate_two_factor_token(self, token): try: verification = authy_api.tokens.verify( self.authy_id, token ) if not verification.ok(): self.logger.error('Invalid Token') return False except AuthyFormatException as e: self.logger.error(str(e)) return False return True def create_authy(self): authy_user = authy_api.users.create( self.email, self.phone_number, 1, ) self.authy_id = str(authy_user.id) self.save() @staticmethod def create(email, password, **kwargs): first_name = kwargs.get('first_name', '').strip() last_name = kwargs.get('last_name', '').strip() middle_name = kwargs.get('middle_name', '').strip() trading_account_username = kwargs.get('trading_account_username') requires_two_factor = kwargs.get('requires_two_factor', False) email = email.lower().strip() dob = kwargs.get('dob') phone_number = kwargs.get('phone_number') dob = Dob(**dob) if dob else dob password = User.hash_password(password) user = User.objects(email=email).first() if not user: user = User( email=email, password=password, first_name=first_name, middle_name=middle_name, last_name=last_name, dob=dob, phone_number=phone_number, trading_account_username=trading_account_username, requires_two_factor=requires_two_factor, ) user.save() if user.requires_two_factor: user.create_authy() return user else: raise Exception('User exists already') def send_message( self, message_template, message_data={}, medium='email', attachments=None, alert=None, ): sender_data = { 'first_name': self.first_name, 'last_name': self.last_name } if medium == 'sms': recipients = [self.phone_number] else: recipients = [self.email] m = Message( message_template=message_template, user=self, sender_data=sender_data, message_data=message_data, recipients=recipients, medium=medium, attachments=attachments, alert=alert, ) m.send()
class Task(Document): Target = ReferenceField('Target', reverse_delete_rule=CASCADE) Start = DateTimeField() End = DateTimeField() IsValid = BooleanField(default=True)