class APAS(Request): full_name = 'Aprobación de pasantía' 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')) date_start = DateField(required=True, display='Fecha de inicio de la pasantía', default=datetime.date.today) date_finish = DateField(required=True, display='Fecha de finalización de la pasantía', default=datetime.date.today) place = StringField(required=True, display='Lugar: Ciudad, País', default='') format_present = BooleanField( required=True, default=False, display='¿Presenta el formato de solicitud de movilidad saliente?') institut = StringField( required=True, display='Institución donde se va a desarrollar la pasantía', default='') grade_option = StringField(required=True, display='Tipo de tesis/trabajo final', choices=GO_CHOICES, default=GO_TESIS_MAESTRIA) internship_period = StringField( required=True, display='Periodo en el que se va a desarrollar la pasantía', choices=Request.PERIOD_CHOICES, default=Request.PERIOD_DEFAULT) enrolled_thesis = BooleanField( required=True, default=False, display='¿Tiene inscrita la asignatura tesis/trabajo final?') regulation_list = [] # List of regulations str_cm = [ 'realizar pasantía en la institución {} en {}, como parte del desarrollo de su {}', ', desde el {} hasta el {}. El estudiante deberá estar debidamente matriculado' + ' en el periodo {}.', 'debido a que' ] list_analysis = [ 'Perfil de {}', 'El estudiante {}tiene inscrita la asignatura {}.', 'Estancia de investigación del {} al {}.', 'Lugar: {}.', 'El estudiante {}presenta el formato de solicitud de movilidad saliente.' ] 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 + ' ') # pylint: disable=no-member paragraph.add_run(self.get_approval_status_display().upper() + ' ').font.bold = True paragraph.add_run(self.str_cm[0].format( self.institut, self.place, self.get_grade_option_display())) 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 + ' ') # pylint: disable=no-member paragraph.add_run(self.get_advisor_response_display().upper() + ' ').font.bold = True paragraph.add_run(self.str_cm[0].format( self.institut, self.place, self.get_grade_option_display())) if self.is_affirmative_response_approval_status(): self.cm_af(paragraph) else: self.cm_ng(paragraph) def cm_af(self, paragraph): paragraph.add_run(self.str_cm[1].format( string_to_date(str(self.date_start)), string_to_date(str(self.date_finish)), self.internship_period, )) def cm_ng(self, paragraph): paragraph.add_run(' ' + self.str_cm[2] + ' ' + self.council_decision + '.') def pcm_analysis(self, docx): if self.grade_option in [ self.GO_TESIS_MAESTRIA, self.GO_TESIS_DOCTORADO ]: profile = 'investigación' else: profile = 'profundización' final_analysis = [] final_analysis += [self.list_analysis[0].format(profile)] ets = '' if self.enrolled_thesis else 'no ' # pylint: disable=no-member final_analysis += [ self.list_analysis[1].format(ets, self.get_grade_option_display()) ] final_analysis += [ self.list_analysis[2].format(string_to_date(str(self.date_start)), string_to_date(str(self.date_finish))) ] final_analysis += [self.list_analysis[3].format(self.place)] pss = '' if self.format_present else 'no ' final_analysis += [self.list_analysis[4].format(pss)] for extra_a in self.extra_analysis: final_analysis += [extra_a] add_analysis_paragraph(docx, final_analysis)
class StoryLine(EmbeddedDocument): id = StringField(max_length=512, unique=True) in_branch = ListField(BooleanField(), default=4*[False])
class EvilHuman(Human): evil = BooleanField(default=True) meta = {"abstract": True}
class NetworkModel(Document): track_length = IntField(required=True) track_time = FloatField(required=True) history = DictField(required=False) model_filename = StringField(required=False) model_file = FileField(required=False) hiperparams_opt = BooleanField(default=False) keras_model = None # Net params define optimal setup. Analysis params is for optimization params_training = DictField(required=False) analysis_params = {} meta = {'allow_inheritance': True} def __init__(self, *args, **values): super().__init__(*args, **values) if self.id is None: self.save() self.model_filename = ''.join(['Models/', str(self.id)]) def train_network(self): pass def evaluate_track_input(self, track): pass def validate_test_data_accuracy(self, n_axes, normalized=True): pass def validate_test_data_mse(self, n_axes): pass def build_model(self): pass def convert_history_to_db_format(self, history_training): for k, v in history_training.history.items(): for i in range(len(history_training.history[k])): history_training.history[k][i] = float(history_training.history[k][i]) self.history = history_training.history def load_model_from_file(self, only_local_files=False): load_success = False try: self.keras_model = load_model(self.model_filename, compile=True) load_success = True except (ValueError, OSError) as e: if not only_local_files: try: print("Local model not available, loading from db") self.keras_model = self.build_model() weights = pickle.loads(self.model_file.read()) if weights is not None and self.keras_model is not None: self.keras_model.set_weights(weights) load_success = True else: raise TypeError except TypeError: print("Weights not available in DB") return load_success def save_model_file_to_db(self): self.model_file.put(pickle.dumps(self.keras_model.get_weights())) def update_model_file_to_db(self): self.model_file.replace(pickle.dumps(self.keras_model.get_weights())) def plot_loss_model(self, train=True, val=True): plt.xlabel('Epoch') plt.ylabel('Loss') if train: plt.plot(np.arange(1, len(self.history['loss']) + 1, 1), self.history['loss'], label="Train loss") if val: plt.plot(np.arange(1, len(self.history['val_loss']) + 1, 1), self.history['val_loss'], label="Val loss") plt.legend() plt.show() def plot_mse_model(self, train=True, val=True): plt.xlabel('Epoch') plt.ylabel('MSE') if train: plt.plot(np.arange(1, len(self.history['mse']) + 1, 1), self.history['mse'], label="Train mse") if val: plt.plot(np.arange(1, len(self.history['val_mse']) + 1, 1), self.history['val_mse'], label="Val mse") # plt.legend() plt.show() def plot_accuracy_model(self, train=True, val=True, categorical=False): plt.xlabel('Epoch') plt.ylabel('Loss') plt.title('Model Accuracy') if categorical: if train: plt.plot(np.arange(1, len(self.history['categorical_accuracy']) + 1, 1), self.history['categorical_accuracy'], label="Train categorical accuracy") if val: plt.plot(np.arange(1, len(self.history['val_categorical_accuracy']) + 1, 1), self.history['val_categorical_accuracy'], label="Val categorical accuracy") else: if train: plt.plot(np.arange(1, len(self.history['acc']) + 1, 1), self.history['acc'], label="Train accuracy") if val: plt.plot(np.arange(1, len(self.history['val_acc']) + 1, 1), self.history['val_acc'], label="Val accuracy") plt.legend() plt.show() def is_valid_network_track_time(self, track_time): if (self.track_time * 0.85) <= track_time <= (self.track_time * 1.15): return True else: return False
class Job(db.Document): created_at = DateTimeField(required=True) last_modified_at = DateTimeField(required=True, default=datetime.datetime.utcnow) task_id = StringField(required=True) job_id = StringField(required=True) executions = ListField(ReferenceField("JobExecution")) task = ReferenceField("Task", required=True, reverse_delete_rule=mongoengine.CASCADE) image = StringField(required=False) command = StringField(required=False) request_ip = StringField(required=False) metadata = DictField(required=False) scheduled = BooleanField(required=True, default=False) meta = { "ordering": ["-last_modified_at"], "indexes": ["last_modified_at", "job_id", { "fields": ["task_id", "job_id"] }], } def save(self, *args, **kwargs): if self.executions is None: self.executions = [] if not self.created_at: self.created_at = datetime.datetime.utcnow() self.last_modified_at = datetime.datetime.utcnow() return super(Job, self).save(*args, **kwargs) def create_execution(self, image, command): from fastlane.models.job_execution import JobExecution ex_id = str(uuid4()) ex = JobExecution( execution_id=ex_id, image=image, command=command, created_at=datetime.datetime.utcnow(), task=self.task, job=self, ) ex.save() self.executions.append(ex) self.save() return ex def get_metadata(self, blacklist_fn): if "envs" in self.metadata: envs = self.metadata["envs"] self.metadata["envs"] = words_redacted(envs, blacklist_fn) return self.metadata def to_dict( self, include_log=False, include_error=False, include_executions=True, blacklist_fn=None, ): if blacklist_fn is None: meta = self.metadata else: meta = self.get_metadata(blacklist_fn) res = { "createdAt": self.created_at.isoformat(), "image": self.image, "command": self.command, "lastModifiedAt": self.last_modified_at.isoformat(), "taskId": self.task.task_id, "scheduled": self.scheduled, "executionCount": len(self.executions), "requestIPAddress": self.request_ip, "metadata": meta, } if include_executions: executions = [ ex.to_dict(include_log, include_error) for ex in list( reversed( sorted(self.executions, key=lambda ex: ex.created_at))) [:20] ] res["executions"] = executions return res @classmethod def get_by_id(cls, task_id, job_id): from fastlane.models.task import Task if task_id is None or task_id == "" or job_id is None or job_id == "": raise RuntimeError( "Task ID and Job ID are required and can't be None or empty.") task = Task.objects(task_id=task_id).first() job = cls.objects(task=task, job_id=job_id).first() return job def get_execution_by_id(self, execution_id): for job_execution in self.executions: if job_execution.execution_id == execution_id: return job_execution return None def get_last_execution(self): if not self.executions: return None return self.executions[-1] @classmethod def get_unfinished_executions(cls, app): from fastlane.models.job_execution import JobExecution query = { "$or": [ { "status": JobExecution.Status.pulling }, { "status": JobExecution.Status.running }, ] } executions = JobExecution.objects(__raw__=query) execs = [] for execution in executions: enqueued_id = execution.job.metadata.get("enqueued_id") if enqueued_id is not None and ( app.jobs_queue.is_scheduled(enqueued_id) or app.jobs_queue.is_enqueued(enqueued_id)): continue execs.append((execution.job, execution)) return execs @classmethod def get_unscheduled_jobs(cls, app): query = { "$or": [ { "metadata.startIn": { "$exists": True } }, { "metadata.startAt": { "$exists": True } }, { "metadata.cron": { "$exists": True } }, ] } jobs = Job.objects(__raw__=query) unscheduled = [] for job in jobs: if "enqueued_id" not in job.metadata: unscheduled.append(job) continue enqueued_id = job.metadata["enqueued_id"] if not app.jobs_queue.is_scheduled( enqueued_id) and not app.jobs_queue.is_enqueued( enqueued_id): unscheduled.append(job) return list(unscheduled) def enqueue(self, app, execution_id, image=None, command=None): if image is None: image = self.image if command is None: command = self.command if image is None or command is None: raise RuntimeError("Can't enqueue job with no image or command.") logger = app.logger.bind( operation="enqueue_job", job_id=self.job_id, task_id=self.task.task_id, execution_id=execution_id, image=image, command=command, ) args = [ self.task.task_id, str(self.job_id), str(execution_id), image, command ] logger.info("Job enqueued.") return app.jobs_queue.enqueue(Categories.Job, *args) def schedule_job(self, app, details): logger = app.logger.bind(operation="schedule_job") if self.image is None or self.command is None: logger.warn("No image or command found in job.") return None start_at = details.get("startAt", None) start_in = details.get("startIn", None) cron = details.get("cron", None) args = [ str(self.task.task_id), str(self.job_id), None, self.image, self.command, ] queue_job_id = None if start_at is not None: logger.debug("Enqueuing job execution in the future...", start_at=start_at) enqueued_id = app.jobs_queue.enqueue_at(int(start_at), Categories.Job, *args) # future_date = datetime.utcfromtimestamp(int(start_at)) # result = scheduler.enqueue_at(future_date, run_job, *args) self.metadata["enqueued_id"] = enqueued_id queue_job_id = enqueued_id self.save() logger.info("Job execution enqueued successfully.", start_at=start_at) elif start_in is not None: # future_date = datetime.now(tz=timezone.utc) + start_in logger.debug("Enqueuing job execution in the future...", start_in=start_in) enqueued_id = app.jobs_queue.enqueue_in(start_in, Categories.Job, *args) # result = scheduler.enqueue_at(future_date, run_job, *args) self.metadata["enqueued_id"] = enqueued_id queue_job_id = enqueued_id self.save() logger.info("Job execution enqueued successfully.", start_in=start_in) elif cron is not None: logger.debug("Enqueuing job execution using cron...", cron=cron) enqueued_id = app.jobs_queue.enqueue_cron(cron, Categories.Job, *args) self.metadata["enqueued_id"] = enqueued_id queue_job_id = enqueued_id self.metadata["cron"] = cron self.scheduled = True self.save() logger.info("Job execution enqueued successfully.", cron=cron) return queue_job_id
class Playlist(Document): title = StringField(unique=True, required=True) isPrivate = BooleanField() songs = ListField(ReferenceField(Song), reverse_delete_rule=NULLIFY)
class User(Document): # The following fields describe the attributes of a user email = EmailField(required=True, unique=True) password = StringField(default=None, max_length=64, null=False, min_length=6) first_name = StringField(required=True, max_length=255) last_name = StringField(required=True, max_length=255) profile = EmbeddedDocumentField(document_type=UserProfile, default=None) admin_profile = EmbeddedDocumentField(document_type=AdminProfile, default=None) # The following fields describe the simulation properties saved to a users # Document for later retrieval # Note: It is necessary to use `sim_api.schemas.ConfigurationSchema`, # `sim_api.schemas.AlloySchema` and # `sim_api.schemas.SimulationResultsSchema` to validate these before # dumping to the database if we want to ensure validity. last_configuration = DictField(default=None) last_alloy_store = DictField(default=None) last_simulation_results = DictField(default=None) last_simulation_invalid_fields = DictField(default=None) # Store the number of simulations the user has run simulations_count = LongField(default=0) # Store alloys for the user saved_alloys = EmbeddedDocumentListField(document_type=Alloy) # Some rather useful metadata information that's not core to the # definition of a user active = BooleanField(default=True) is_admin = BooleanField(default=False, db_field='admin') disable_admin = BooleanField(default=False) verified = BooleanField(default=False) # Make sure when converting these that it follows ISO8601 format as # defined in settings.DATETIME_FMT created = DateTimeField( default=datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'), null=False) last_updated = DateTimeField(default=None, null=False) last_login = DateTimeField() ratings = EmbeddedDocumentListField(document_type=Rating) login_data = EmbeddedDocumentListField(document_type=LoginData) # Define the collection and indexing for this document meta = { 'collection': 'users', 'indexes': [ # This create text indexes for advanced text search { 'fields': ['$first_name', '$last_name', '$email'], # For a text index, the weight of an indexed field denotes # the significance of the field relative to the other indexed # fields in terms of the text search score. # 2 times (i.e. 10:1) the impact as a term match in the # last_name and email fields # 10:9 impact as a term match in the last_name:first_name 'weights': { 'last_name': 4, 'first_name': 2, 'email': 5 } } ] } def set_password(self, raw_password: str) -> None: """ Helper utility method to save an encrypted password using the Bcrypt Flask extension. """ self.password = bcrypt.generate_password_hash( password=raw_password, rounds=current_app.config.get('BCRYPT_LOG_ROUNDS')).decode() def to_dict(self) -> dict: """Simple Document.User helper method to get a Python dict back.""" last_login = None last_updated = None if self.last_login is not None: last_login = self.last_login.isoformat() if self.last_updated is not None: last_updated = self.last_updated.isoformat() # We set a default profile that we always send to the client profile = { 'aim': None, 'highest_education': None, 'sci_tech_exp': None, 'phase_transform_exp': None } if self.profile is not None: profile = self.profile.to_dict() user = { 'email': self.email, 'first_name': self.first_name, 'last_name': self.last_name, 'active': self.active, 'admin': self.is_admin, 'verified': self.verified, 'last_updated': str(last_updated), 'created': str(self.created.isoformat()), 'last_login': str(last_login), 'profile': profile } if self.admin_profile is not None: user['admin_profile'] = self.admin_profile.to_dict() return user def to_json(self, *args, **kwargs): """ Override the default method to customise the way a JSON format is transformed. """ return json.dumps(self.to_dict(), cls=JSONEncoder) # MongoEngine allows you to create custom cleaning rules for your documents # when calling save(). By providing a custom clean() method you can do # any pre validation / data cleaning. This might be useful if you want to # ensure a default value based on other document values. def clean(self): """ Ensures a multitude of business logic is checked before we save the User to the database. These include the following: - Password must be set by calling `new_user.set_password(raw_pw)` - Every time a User object is saved the `User.last_updated` datetime is set to the current `utcnow()` datetime. - Update the `User.is_admin` boolean based on other criteria. - By default, if there is not `User.ratings` or `User.login_data` we make a Python list as the default. """ if self.password is None: raise PasswordValidationError() if self.last_updated is None: self.last_updated = self.created else: self.last_updated = datetime.utcnow() self.is_admin = (not self.disable_admin and self.admin_profile is not None) if not self.ratings: self.ratings = [] if not self.login_data: self.login_data = [] # noinspection PyMethodParameters @queryset_manager def as_dict(cls, queryset) -> list: """Adding an additional QuerySet context method to return a list of `sim_api.models.Users` Documents instead of a QuerySet. Usage: users_list = User.as_dict() Args: queryset: the queryset that must is accepted as part of the Mongo BSON parameter. Returns: A list with every Users Document object converted to dict. """ return [obj.to_dict() for obj in queryset] def __str__(self): return self.to_json()
class Coupon(Post): code = StringField(unique=True) discountType = StringField(choices=['percent', 'dollar']) discount = FloatField() storeWide = BooleanField(default=False) applicableProducts = ListField(ReferenceField('Product')) uses = IntField(default=0) maxUses = IntField(default=-1) @classmethod def schema(cls): return super().schema() + [{ 'name': 'code', 'niceName': 'Code', 'controlType': 'input' }, { 'name': 'discountType', 'niceName': 'Discount Type', 'controlType': 'select', 'options': [{ 'key': 'Percent', 'value': 'percent' }, { 'key': 'Dollar', 'value': 'dollar' }] }, { 'name': 'discount', 'niceName': 'Discount', 'controlType': 'input', 'type': 'number' }, { 'name': 'storeWide', 'niceName': 'Store wide', 'controlType': 'checkbox' }, { 'name': 'applicableProducts', 'niceName': 'Applicable Products', 'controlType': 'post-select', 'type': 'models.Product', 'multiple': True }, { 'name': 'maxUses', 'niceName': 'Max Uses', 'controlType': 'input', 'type': 'number' }] def serialize(self): return { **super().serialize(), 'code': self.code, 'discountType': self.discountType, 'discount': self.discount, 'storeWide': self.storeWide, 'applicableProducts': list(map(lambda p: str(p.id), self.applicableProducts)), 'uses': self.uses, 'maxUses': self.maxUses }
class HardwareStream(IStream): log_level = IntField(default=StreamLogLevel.LOG_LEVEL_INFO, required=True) input = EmbeddedDocumentField(InputUrls, default=InputUrls()) have_video = BooleanField(default=constants.DEFAULT_HAVE_VIDEO, required=True) have_audio = BooleanField(default=constants.DEFAULT_HAVE_AUDIO, required=True) audio_select = IntField(default=constants.INVALID_AUDIO_SELECT, required=True) loop = BooleanField(default=constants.DEFAULT_LOOP, required=True) avformat = BooleanField(default=constants.DEFAULT_AVFORMAT, required=True) restart_attempts = IntField(default=constants.DEFAULT_RESTART_ATTEMPTS, required=True) auto_exit_time = IntField(default=constants.DEFAULT_AUTO_EXIT_TIME, required=True) # runtime _status = StreamStatus.NEW _cpu = 0.0 _timestamp = 0 _idle_time = 0 _rss = 0 _loop_start_time = 0 _restarts = 0 _start_time = 0 _input_streams = str() _output_streams = str() def __init__(self, *args, **kwargs): super(HardwareStream, self).__init__(*args, **kwargs) def get_type(self): raise NotImplementedError('subclasses must override get_type()!') def reset(self): self._status = StreamStatus.NEW self._cpu = 0.0 self._timestamp = 0 self._idle_time = 0 self._rss = 0 self._loop_start_time = 0 self._restarts = 0 self._start_time = 0 self._input_streams = str() self._output_streams = str() def update_runtime_fields(self, params: dict): assert self.get_id() == params[StreamFields.ID] assert self.get_type() == params[StreamFields.TYPE] self._status = StreamStatus(params[StreamFields.STATUS]) self._cpu = params[StreamFields.CPU] self._timestamp = params[StreamFields.TIMESTAMP] self._idle_time = params[StreamFields.IDLE_TIME] self._rss = params[StreamFields.RSS] self._loop_start_time = params[StreamFields.LOOP_START_TIME] self._restarts = params[StreamFields.RESTARTS] self._start_time = params[StreamFields.START_TIME] self._input_streams = params[StreamFields.INPUT_STREAMS] self._output_streams = params[StreamFields.OUTPUT_STREAMS] def to_dict(self) -> dict: front = super(HardwareStream, self).to_dict() front[StreamFields.STATUS] = self._status front[StreamFields.CPU] = self._cpu front[StreamFields.TIMESTAMP] = self._timestamp front[StreamFields.IDLE_TIME] = self._idle_time front[StreamFields.RSS] = self._rss front[StreamFields.LOOP_START_TIME] = self._loop_start_time front[StreamFields.RESTARTS] = self._restarts front[StreamFields.START_TIME] = self._start_time front[StreamFields.INPUT_STREAMS] = self._input_streams front[StreamFields.OUTPUT_STREAMS] = self._output_streams # runtime work_time = self._timestamp - self._start_time quality = 100 - (100 * self._idle_time / work_time) if work_time else 100 front[StreamFields.QUALITY] = quality return front def config(self) -> dict: conf = super(HardwareStream, self).config() conf[ConfigFields.FEEDBACK_DIR_FIELD] = self.generate_feedback_dir() conf[ConfigFields.LOG_LEVEL_FIELD] = self.get_log_level() conf[ConfigFields.AUTO_EXIT_TIME_FIELD] = self.get_auto_exit_time() conf[ConfigFields.LOOP_FIELD] = self.get_loop() conf[ConfigFields.AVFORMAT_FIELD] = self.get_avformat() conf[ConfigFields.HAVE_VIDEO_FIELD] = self.get_have_video() # required conf[ConfigFields.HAVE_AUDIO_FIELD] = self.get_have_audio() # required conf[ConfigFields.RESTART_ATTEMPTS_FIELD] = self.get_restart_attempts() conf[ConfigFields.INPUT_FIELD] = self.input.to_mongo( ) # required empty in timeshift_player audio_select = self.get_audio_select() if audio_select != constants.INVALID_AUDIO_SELECT: conf[ConfigFields.AUDIO_SELECT_FIELD] = audio_select return conf def generate_feedback_dir(self): return '{0}/{1}/{2}'.format(self._settings.feedback_directory, self.get_type(), self.get_id()) def generate_http_link(self, playlist_name=constants.DEFAULT_HLS_PLAYLIST ) -> OutputUrl: oid = OutputUrl.generate_id() http_root = self._generate_http_root_dir(oid) link = '{0}/{1}'.format(http_root, playlist_name) return OutputUrl(oid, self._settings.generate_http_link(link), http_root) def generate_vod_link(self, playlist_name=constants.DEFAULT_HLS_PLAYLIST ) -> OutputUrl: oid = OutputUrl.generate_id() vods_root = self._generate_vods_root_dir(oid) link = '{0}/{1}'.format(vods_root, playlist_name) return OutputUrl(oid, self._settings.generate_vods_link(link), vods_root) def generate_cod_link(self, playlist_name=constants.DEFAULT_HLS_PLAYLIST ) -> OutputUrl: oid = OutputUrl.generate_id() cods_root = self._generate_cods_root_dir(oid) link = '{0}/{1}'.format(cods_root, playlist_name) return OutputUrl(oid, self._settings.generate_cods_link(link), cods_root) def get_log_level(self): return self.log_level def get_audio_select(self): return self.audio_select def get_have_video(self): return self.have_video def get_have_audio(self): return self.have_audio def get_loop(self): return self.loop def get_avformat(self): return self.avformat def get_restart_attempts(self): return self.restart_attempts def get_auto_exit_time(self): return self.auto_exit_time def generate_input_playlist(self, header=True) -> str: result = '#EXTM3U\n' if header else '' stream_type = self.get_type() if stream_type == constants.StreamType.RELAY or \ stream_type == constants.StreamType.ENCODE or \ stream_type == constants.StreamType.TIMESHIFT_PLAYER or \ stream_type == constants.StreamType.VOD_ENCODE or \ stream_type == constants.StreamType.VOD_RELAY: for out in self.input.urls: result += '#EXTINF:-1 tvg-id="{0}" tvg-name="{1}" tvg-logo="{2}" group-title="{3}",{4}\n{5}\n'.format( self.tvg_id, self.tvg_name, self.tvg_logo, self.group, self.name, out.uri) return result @classmethod def make_stream(cls, settings): stream = cls() stream._settings = settings stream.input = InputUrls(urls=[InputUrl(id=InputUrl.generate_id())]) stream.output = OutputUrls( urls=[OutputUrl(id=OutputUrl.generate_id())]) return stream # private def _generate_http_root_dir(self, oid: int): return '{0}/{1}/{2}/{3}'.format(self._settings.hls_directory, self.get_type(), self.get_id(), oid) def _generate_vods_root_dir(self, oid: int): return '{0}/{1}/{2}/{3}'.format(self._settings.vods_directory, self.get_type(), self.get_id(), oid) def _generate_cods_root_dir(self, oid: int): return '{0}/{1}/{2}/{3}'.format(self._settings.cods_directory, self.get_type(), self.get_id(), oid) def _fixup_http_output_urls(self): for idx, val in enumerate(self.output.urls): url = val.uri if url == constants.DEFAULT_TEST_URL: return parsed_uri = urlparse(url) if parsed_uri.scheme == 'http': filename = os.path.basename(parsed_uri.path) self.output.urls[idx] = self.generate_http_link(filename) def _fixup_vod_output_urls(self): for idx, val in enumerate(self.output.urls): url = val.uri if url == constants.DEFAULT_TEST_URL: return parsed_uri = urlparse(url) if parsed_uri.scheme == 'http': filename = os.path.basename(parsed_uri.path) self.output.urls[idx] = self.generate_vod_link(filename) def _fixup_cod_output_urls(self): for idx, val in enumerate(self.output.urls): url = val.uri if url == constants.DEFAULT_TEST_URL: return parsed_uri = urlparse(url) if parsed_uri.scheme == 'http': filename = os.path.basename(parsed_uri.path) self.output.urls[idx] = self.generate_cod_link(filename)
class Media(Document): owner = LazyReferenceField('User', required=True) folder = StringField(required=True) filename = StringField(unique_with=('folder', 'private')) file = FileField() dir = BooleanField() container = BooleanField(default=False) metadata = DictField() processing = BooleanField(default=False) percentDone = FloatField() private = BooleanField(default=False) associatedMedia = ListField( LazyReferenceField('Media', reverse_delete_rule=PULL)) if MongoSettings.DEFAULT_CONNECT_URI != MongoSettings.MEDIA_CONNECT_URI: meta = {'db_alias': 'media-db'} @classmethod def post_save(cls, sender, document: Media, **kwargs): message = None if not (document.private or document.processing): message = { 'type': 'update', 'payload': { 'folder': document.folder, 'created': kwargs['created'] } } elif document.processing: message = { 'type': 'processing update', 'payload': { 'id': str(document.id), 'percentDone': document.percentDone } } if message: # Workaround to allow sending in normal and async methods as mediaBrowserManger.broadcast is async try: loop = asyncio.get_running_loop() except RuntimeError: loop = None if loop and loop.is_running(): loop.create_task(mediaBrowserManager.broadcast(message)) else: asyncio.run(mediaBrowserManager.broadcast(message)) def serialize(self, associatedMedia: Optional[bool] = False): out = { 'id': str(self.id), 'owner': str(self.owner.id), 'folder': self.folder, 'filename': self.filename } if self.dir and not associatedMedia: out['dir'] = self.dir if self.container: out['container'] = self.container size = 0 for subMedia in self.associatedMedia: subMedia = subMedia.fetch() if subMedia.file: size += subMedia.file.length out['size'] = size if self.file: out['mimetype'] = self.file.content_type out['size'] = self.file.length if self.metadata: out['metadata'] = self.metadata if self.associatedMedia and not associatedMedia: out['associatedMedia'] = list( map(lambda m: m.fetch().serialize(True), self.associatedMedia)) if self.processing: out['processing'] = self.processing out['percentDone'] = self.percentDone if self.private: out['private'] = self.private return out
class Product(Post): sku = StringField() img = ListField(ReferenceField('Media', reverse_delete_rule=PULL)) price = DecimalField(precision=2) digital = BooleanField(default=False) taxable = BooleanField(default=True) hasStock = BooleanField(default=False) stock = IntField() totalReviews = IntField(default=0) avgReviewScore = FloatField(default=0) def addReview(self, score): self.avgReviewScore = ((self.avgReviewScore * self.totalReviews) + int(score)) / (self.totalReviews + 1) self.totalReviews = self.totalReviews + 1 @classmethod def schema(cls): return super().schema() + [{ 'name': 'sku', 'niceName': 'SKU', 'controlType': 'input' }, { 'name': 'img', 'niceName': 'Images', 'controlType': 'media-browser', 'multiple': True }, { 'name': 'price', 'niceName': 'Price', 'controlType': 'input', 'type': 'number' }, { 'name': 'digital', 'niceName': 'Digital', 'controlType': 'checkbox' }, { 'name': 'taxable', 'niceName': 'Taxable', 'controlType': 'checkbox' }, { 'name': 'hasStock', 'niceName': 'Has Stock', 'controlType': 'checkbox' }, { 'name': 'stock', 'niceName': 'Stock', 'controlType': 'input', 'type': 'number', 'validators': { 'required': True } }] def serialize(self): return { **super().serialize(), 'sku': self.sku, 'img': list(map(lambda m: str(m.id), self.img)), 'price': float(self.price) if self.price else None, "digital": self.digital, "taxable": self.taxable, 'hasStock': self.hasStock, 'stock': self.stock, 'totalReviews': self.totalReviews, 'avgReviewScore': round(self.avgReviewScore, 1) # Round to 1 decimal place }
class OutputPlateDefinitionModel(EmbeddedDocument): plate_id = StringField(min_length=1, max_length=512, required=True) meta_data_id = StringField(min_length=1, max_length=512, required=True) description = StringField(min_length=1, max_length=512, required=True) use_provided_values = BooleanField(required=True)
class OUser(User): repos = ListField(ReferenceField(Repo)) private = BooleanField( default=False) #The permission access level to OnToology
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: # noqa 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) def get_symlink_name(self): """ Provides the name that should be used when creating a symlink. :return: file name as it appears in a published repository :rtype: str """ raise NotImplemented()
class EncodeStream(Stream): def __init__(self, *args, **kwargs): super(EncodeStream, self).__init__(*args, **kwargs) deinterlace = BooleanField(default=constants.DEFAULT_DEINTERLACE, required=True) frame_rate = IntField(default=constants.INVALID_FRAME_RATE, required=True) volume = FloatField(default=constants.DEFAULT_VOLUME, required=True) video_codec = StringField(default=constants.DEFAULT_VIDEO_CODEC, required=True) audio_codec = StringField(default=constants.DEFAULT_AUDIO_CODEC, required=True) audio_channels_count = IntField(default=constants.INVALID_AUDIO_CHANNELS_COUNT, required=True) size = EmbeddedDocumentField(Size, default=Size()) video_bit_rate = IntField(default=constants.INVALID_VIDEO_BIT_RATE, required=True) audio_bit_rate = IntField(default=constants.INVALID_AUDIO_BIT_RATE, required=True) logo = EmbeddedDocumentField(Logo, default=Logo()) aspect_ratio = EmbeddedDocumentField(Rational, default=Rational()) def get_type(self): return constants.StreamType.ENCODE def config(self) -> dict: conf = super(EncodeStream, self).config() conf[DEINTERLACE_FIELD] = self.get_deinterlace() frame_rate = self.get_frame_rate() if frame_rate != constants.INVALID_FRAME_RATE: conf[FRAME_RATE_FIELD] = frame_rate conf[VOLUME_FIELD] = self.get_volume() conf[VIDEO_CODEC_FIELD] = self.get_video_codec() conf[AUDIO_CODEC_FIELD] = self.get_audio_codec() audio_channels = self.get_audio_channels_count() if audio_channels != constants.INVALID_AUDIO_CHANNELS_COUNT: conf[AUDIO_CHANNELS_COUNT_FIELD] = audio_channels if self.size.is_valid(): conf[SIZE_FIELD] = str(self.size) vid_rate = self.get_video_bit_rate() if vid_rate != constants.INVALID_VIDEO_BIT_RATE: conf[VIDEO_BIT_RATE_FIELD] = vid_rate audio_rate = self.get_audio_bit_rate() if audio_rate != constants.INVALID_AUDIO_BIT_RATE: conf[AUDIO_BIT_RATE_FIELD] = self.get_audio_bit_rate() if self.logo.is_valid(): conf[LOGO_FIELD] = self.logo.to_dict() if self.aspect_ratio.is_valid(): conf[ASPCET_RATIO_FIELD] = str(self.aspect_ratio) return conf def get_deinterlace(self): return self.deinterlace def get_frame_rate(self): return self.frame_rate def get_volume(self): return self.volume def get_video_codec(self): return self.video_codec def get_audio_codec(self): return self.audio_codec def get_audio_channels_count(self): return self.audio_channels_count def get_video_bit_rate(self): return self.video_bit_rate def get_audio_bit_rate(self): return self.audio_bit_rate
class EncodeStream(HardwareStream): def __init__(self, *args, **kwargs): super(EncodeStream, self).__init__(*args, **kwargs) relay_video = BooleanField(default=constants.DEFAULT_RELAY_VIDEO, required=True) relay_audio = BooleanField(default=constants.DEFAULT_RELAY_AUDIO, required=True) deinterlace = BooleanField(default=constants.DEFAULT_DEINTERLACE, required=True) frame_rate = IntField(default=constants.INVALID_FRAME_RATE, required=True) volume = FloatField(default=constants.DEFAULT_VOLUME, required=True) video_codec = StringField(default=constants.DEFAULT_VIDEO_CODEC, required=True) audio_codec = StringField(default=constants.DEFAULT_AUDIO_CODEC, required=True) audio_channels_count = IntField( default=constants.INVALID_AUDIO_CHANNELS_COUNT, required=True) size = EmbeddedDocumentField(Size, default=Size()) video_bit_rate = IntField(default=constants.INVALID_VIDEO_BIT_RATE, required=True) audio_bit_rate = IntField(default=constants.INVALID_AUDIO_BIT_RATE, required=True) logo = EmbeddedDocumentField(Logo, default=Logo()) aspect_ratio = EmbeddedDocumentField(Rational, default=Rational()) def get_type(self): return constants.StreamType.ENCODE def get_relay_video(self): return self.relay_video def get_relay_audio(self): return self.relay_audio def config(self) -> dict: conf = super(EncodeStream, self).config() conf[ConfigFields.RELAY_VIDEO_FIELD] = self.get_relay_video() conf[ConfigFields.RELAY_AUDIO_FIELD] = self.get_relay_audio() conf[ConfigFields.DEINTERLACE_FIELD] = self.get_deinterlace() frame_rate = self.get_frame_rate() if frame_rate != constants.INVALID_FRAME_RATE: conf[ConfigFields.FRAME_RATE_FIELD] = frame_rate conf[ConfigFields.VOLUME_FIELD] = self.get_volume() conf[ConfigFields.VIDEO_CODEC_FIELD] = self.get_video_codec() conf[ConfigFields.AUDIO_CODEC_FIELD] = self.get_audio_codec() audio_channels = self.get_audio_channels_count() if audio_channels != constants.INVALID_AUDIO_CHANNELS_COUNT: conf[ConfigFields.AUDIO_CHANNELS_COUNT_FIELD] = audio_channels if self.size.is_valid(): conf[ConfigFields.SIZE_FIELD] = str(self.size) vid_rate = self.get_video_bit_rate() if vid_rate != constants.INVALID_VIDEO_BIT_RATE: conf[ConfigFields.VIDEO_BIT_RATE_FIELD] = vid_rate audio_rate = self.get_audio_bit_rate() if audio_rate != constants.INVALID_AUDIO_BIT_RATE: conf[ConfigFields.AUDIO_BIT_RATE_FIELD] = self.get_audio_bit_rate() if self.logo.is_valid(): conf[ConfigFields.LOGO_FIELD] = self.logo.to_dict() if self.aspect_ratio.is_valid(): conf[ConfigFields.ASPCET_RATIO_FIELD] = str(self.aspect_ratio) return conf def get_deinterlace(self): return self.deinterlace def get_frame_rate(self): return self.frame_rate def get_volume(self): return self.volume def get_video_codec(self): return self.video_codec def get_audio_codec(self): return self.audio_codec def get_audio_channels_count(self): return self.audio_channels_count def get_video_bit_rate(self): return self.video_bit_rate def get_audio_bit_rate(self): return self.audio_bit_rate def fixup_output_urls(self): return self._fixup_http_output_urls() @classmethod def make_stream(cls, settings): stream = cls() stream._settings = settings stream.input = InputUrls(urls=[InputUrl(id=InputUrl.generate_id())]) stream.output = OutputUrls( urls=[OutputUrl(id=OutputUrl.generate_id())]) return stream
class Stream(EmbeddedDocument): meta = {'allow_inheritance': True, 'auto_create_index': True} def __init__(self, *args, **kwargs): super(Stream, self).__init__(*args, **kwargs) id = ObjectIdField(required=True, default=ObjectId, unique=True, primary_key=True) name = StringField(default=DEFAULT_STREAM_NAME, max_length=MAX_STREAM_NAME_LENGTH, min_length=MIN_STREAM_NAME_LENGTH, required=True) created_date = DateTimeField(default=datetime.now) # for inner use log_level = IntField(default=constants.StreamLogLevel.LOG_LEVEL_INFO, required=True) input = EmbeddedDocumentField(Urls, default=Urls()) output = EmbeddedDocumentField(Urls, default=Urls()) have_video = BooleanField(default=constants.DEFAULT_HAVE_VIDEO, required=True) have_audio = BooleanField(default=constants.DEFAULT_HAVE_AUDIO, required=True) audio_select = IntField(default=constants.INVALID_AUDIO_SELECT, required=True) loop = BooleanField(default=constants.DEFAULT_LOOP, required=True) restart_attempts = IntField(default=constants.DEFAULT_RESTART_ATTEMPTS, required=True) auto_exit_time = IntField(default=constants.DEFAULT_AUTO_EXIT_TIME, required=True) # runtime _status = constants.StreamStatus.NEW _cpu = 0.0 _timestamp = 0 _rss = 0 _loop_start_time = 0 _restarts = 0 _start_time = 0 _input_streams = str() _output_streams = str() _feedback_dir = str() def set_feedback_dir(self, feedback_dir): self._feedback_dir = feedback_dir def reset(self): self._status = constants.StreamStatus.NEW self._cpu = 0.0 self._timestamp = 0 self._rss = 0 self._loop_start_time = 0 self._restarts = 0 self._start_time = 0 self._input_streams = str() self._output_streams = str() def update_runtime_fields(self, params: dict): assert self.get_id() == params[StreamFields.ID] assert self.get_type() == params[StreamFields.TYPE] self._status = constants.StreamStatus(params[StreamFields.STATUS]) self._cpu = params[StreamFields.CPU] self._timestamp = params[StreamFields.TIMESTAMP] self._rss = params[StreamFields.RSS] self._loop_start_time = params[StreamFields.LOOP_START_TIME] self._restarts = params[StreamFields.RESTARTS] self._start_time = params[StreamFields.START_TIME] self._input_streams = params[StreamFields.INPUT_STREAMS] self._output_streams = params[StreamFields.OUTPUT_STREAMS] def to_front(self) -> dict: return {StreamFields.NAME: self.name, StreamFields.ID: self.get_id(), StreamFields.TYPE: self.get_type(), StreamFields.STATUS: self._status, StreamFields.CPU: self._cpu, StreamFields.TIMESTAMP: self._timestamp, StreamFields.RSS: self._rss, StreamFields.LOOP_START_TIME: self._loop_start_time, StreamFields.RESTARTS: self._restarts, StreamFields.START_TIME: self._start_time, StreamFields.INPUT_STREAMS: self._input_streams, StreamFields.OUTPUT_STREAMS: self._output_streams} def config(self) -> dict: conf = { ID_FIELD: self.get_id(), # required TYPE_FIELD: self.get_type(), # required FEEDBACK_DIR_FIELD: self.generate_feedback_dir(), # required LOG_LEVEL_FIELD: self.get_log_level(), AUTO_EXIT_TIME_FIELD: self.get_auto_exit_time(), LOOP_FIELD: self.get_loop(), HAVE_VIDEO_FIELD: self.get_have_video(), # required HAVE_AUDIO_FIELD: self.get_have_audio(), # required RESTART_ATTEMPTS_FIELD: self.get_restart_attempts(), INPUT_FIELD: self.input.to_mongo(), # required empty in timeshift_player OUTPUT_FIELD: self.output.to_mongo() # required empty in timeshift_record } audio_select = self.get_audio_select() if audio_select != constants.INVALID_AUDIO_SELECT: conf[AUDIO_SELECT_FIELD] = audio_select return conf def generate_feedback_dir(self): return '{0}/{1}/{2}'.format(self._feedback_dir, self.get_type(), self.get_id()) def get_log_level(self): return self.log_level def get_audio_select(self): return self.audio_select def get_have_video(self): return self.have_video def get_have_audio(self): return self.have_audio def get_id(self): return str(self.id) def get_type(self): raise NotImplementedError('subclasses must override get_type()!') def get_loop(self): return self.loop def get_restart_attempts(self): return self.restart_attempts def get_auto_exit_time(self): return self.auto_exit_time
class Paper(Document, OParlDocument): type = 'https://schema.oparl.org/1.0/Paper' body = ReferenceField('Body', dbref=False, deref_location=False) name = StringField(fulltext=True) reference = StringField(fulltext=True) date = DateTimeField(datetime_format='date') paperType = StringField() relatedPaper = ListField(ReferenceField('Paper', dbref=False, deref_location=False), default=[]) superordinatedPaper = ListField(ReferenceField('Paper', dbref=False, deref_location=False), default=[]) subordinatedPaper = ListField(ReferenceField('Paper', dbref=False, deref_location=False), default=[]) mainFile = ReferenceField('File', dbref=False, deref_location=True) auxiliaryFile = ListField(ReferenceField('File', dbref=False, deref_location=True), default=[]) location = ListField(ReferenceField('Location', dbref=False, deref_location=False), default=[]) originatorPerson = ListField(ReferenceField('Person', dbref=False, deref_location=True), default=[]) underDirectionOf = ListField(ReferenceField('Organization', dbref=False, deref_location=True), default=[]) originatorOrganization = ListField(ReferenceField('Organization', dbref=False, deref_location=True), default=[]) consultation = ListField(ReferenceField('Consultation', dbref=False, deref_location=True), default=[]) license = StringField() keyword = ListField(StringField(fulltext=True), default=[]) created = DateTimeField(datetime_format='datetime', required=True) modified = DateTimeField(datetime_format='datetime', required=True) web = StringField() deleted = BooleanField() # Politik bei Uns Felder originalId = StringField(vendor_attribute=True) legacy = BooleanField(vendor_attribute=True) mirrorId = StringField(vendor_attribute=True) georeferenceStatus = StringField(vendor_attribute=True) georeferenceGenerated = DateTimeField(datetime_format='datetime', vendor_attribute=True) keywordUsergenerated = ListField(ReferenceField('KeywordUsergenerated'), vendor_attribute=True) locationOrigin = ListField(ReferenceField('LocationOrigin'), vendor_attribute=True) # Felder zur Verarbeitung _object_db_name = 'paper' _attribute = 'paper' def __init__(self, *args, **kwargs): super(Document, self).__init__(*args, **kwargs) def __repr__(self): return '<Paper %r>' % self.name
class Configuration(EmbeddedDocument): is_valid = BooleanField(default=False, required=True, null=False) method = StringField(null=False, required=True, choices=('Li98', 'Kirkaldy83')) grain_size = FloatField(null=False, required=True, validation=not_negative) nucleation_start = FloatField(null=False, required=True, validation=within_percentage_bounds) nucleation_finish = FloatField(null=False, required=True, validation=within_percentage_bounds) auto_calculate_ms = BooleanField(default=True, null=False, required=True) auto_calculate_bs = BooleanField(default=True, null=False, required=True) auto_calculate_ae = BooleanField(default=True, null=False, required=True) ms_temp = FloatField(default=0.0, null=False, required=True, validation=not_negative) ms_rate_param = FloatField(default=0.0, null=False, required=True, validation=not_negative) bs_temp = FloatField(default=0.0, null=False, required=True, validation=not_negative) ae1_temp = FloatField(default=0.0, null=False, required=True, validation=not_negative) ae3_temp = FloatField(default=0.0, null=False, required=True, validation=not_negative) start_temp = FloatField(default=900, null=False, required=True, validation=not_negative) cct_cooling_rate = FloatField(default=10, null=False, required=True, validation=not_negative) def to_dict(self) -> dict: """ Simple EmbeddedDocument.Configuration helper method to get a Python dict """ return { 'is_valid': self.is_valid, 'method': self.method, 'grain_size': self.grain_size, 'nucleation_start': self.nucleation_start, 'nucleation_finish': self.nucleation_finish, 'auto_calculate_ms': self.auto_calculate_ms, 'auto_calculate_bs': self.auto_calculate_bs, 'auto_calculate_ae': self.auto_calculate_ae, 'ms_temp': self.ms_temp, 'ms_rate_param': self.ms_rate_param, 'bs_temp': self.bs_temp, 'ae1_temp': self.ae1_temp, 'ae3_temp': self.ae3_temp, 'start_temp': self.start_temp, 'cct_cooling_rate': self.cct_cooling_rate } # noinspection PyMethodParameters @queryset_manager def as_dict(cls, queryset) -> list: """Adding an additional QuerySet context method to return a list of `sim_api.models.Configuration` Documents instead of a QuerySet. Usage: config_list = Configuration.as_dict() Args: queryset: the queryset that must is accepted as part of the Mongo BSON parameter. Returns: A list with every Configuration Document object converted to dict. """ return [obj.to_dict() for obj in queryset] def __str__(self): return self.to_json()
class Preferences(EmbeddedDocument): display_weeshes = BooleanField(default=True) display_events = BooleanField(default=True) search_distance = IntField(default=50) selected_network = StringField(default='PUBLIC') background_picture = ImageField()
class REINPRE(Request): RL_ANSWER_RENOV_MATRICULA = 'RM' RL_ANSWER_PAPA = 'PA' RL_ANSWER_CUPO_CREDITOS = 'CC' RL_ANSWER_SANCION = 'SA' RL_ANSWER_OTRO = 'OT' RL_ANSWER_CHOICES = (( RL_ANSWER_RENOV_MATRICULA, 'No cumplir con los requisitos exigidos para la' + ' renovación de la matrícula, en los plazos señalados por la Universidad.' ), ( RL_ANSWER_PAPA, 'Presentar un Promedio Aritmético Ponderado Acumulado menor que tres punto cero (3.0).' ), ( RL_ANSWER_CUPO_CREDITOS, 'No disponer de un cupo de créditos suficiente para inscribir las asignaturas' + ' del plan de estudios pendientes de aprobación.' ), (RL_ANSWER_SANCION, 'Recibir sanción disciplinaria de expulsión o suspensión impuesta de acuerdo' + ' con las normas vigentes.'), (RL_ANSWER_OTRO, 'Otro.')) full_name = 'Reingreso Pregrado' regulation_list = ['008|2008|CSU', '239|2009|VAC', '012|2014|VAC'] reing_period = StringField(required=True, display='Periodo de reingreso', choices=Request.PERIOD_CHOICES, default=Request.PERIOD_DEFAULT) loss_period = StringField( required=True, display='Periodo de perdida de calidad de estudiante', choices=Request.PERIOD_CHOICES, default=Request.PERIOD_DEFAULT) first_reing = BooleanField(required=True, display='Primer reingreso', default=True) admission_period = StringField(required=True, display='Periodo de admisión', choices=Request.PERIOD_CHOICES, default=Request.PERIOD_DEFAULT) periods_since = IntField( required=True, display='periodos desde pérdida de calidad de estudiante', default=0) papa = FloatField(required=True, display='PAPA', default=0.0) reason_of_loss = StringField(choices=RL_ANSWER_CHOICES, default=RL_ANSWER_OTRO, display='Razón pérdida calidad de estudiante') credits_minus_remaining = IntField( required=True, display='Cupo de créditos menos créditos pendientes', default=0) credits_remaining = IntField(required=True, display='Créditos restantes', default=0) credits_english = IntField(required=True, display='Créditos inglés', default=0) credits_add = IntField( required=True, display='Créditos requeridos para inscribir asignaturas', default=0) min_grade_12c = StringField( required=True, display='Promedio semestral mínimo requerido para mantener la ' + 'calidad de estudiante con 12 créditos inscritos: ', default='') min_grade_15c = StringField( required=True, display='Promedio semestral mínimo requerido para mantener la ' + 'calidad de estudiante con 15 créditos inscritos: ', default='') min_grade_18c = StringField( required=True, display='Promedio semestral mínimo requerido para mantener la ' + 'calidad de estudiante con 18 créditos inscritos: ', default='') min_grade_21c = StringField( required=True, display='Promedio semestral mínimo requerido para mantener la ' + 'calidad de estudiante con 21 créditos inscritos: ', default='') # Exiged credits exi_fund_m = IntField( required=True, display='Créditos de fundamentación obligatorios exigidos', default=0) exi_fund_o = IntField( required=True, display='Créditos de fundamentación optativos exigidos', default=0) exi_disc_m = IntField( required=True, display='Créditos disciplinares obligatorios exigidos', default=0) exi_disc_o = IntField(required=True, display='Créditos disciplinares optativos exigidos', default=0) exi_free = IntField(required=True, display='Créditos de libre elección exigidos', default=0) # Approved credits app_fund_m = IntField( required=True, display='Créditos de fundamentación obligatorios aprobados', default=0) app_fund_o = IntField( required=True, display='Créditos de fundamentación optativos aprobados', default=0) app_disc_m = IntField( required=True, display='Créditos disciplinares obligatorios aprobados', default=0) app_disc_o = IntField(required=True, display='Créditos disciplinares optativos aprobados', default=0) app_free = IntField(required=True, display='Créditos de libre elección aprobados', default=0) # Remaining credits rem_fund_m = IntField( required=True, display='Créditos de fundamentación obligatorios restantes', default=0) rem_fund_o = IntField( required=True, display='Créditos de fundamentación optativos restantes', default=0) rem_disc_m = IntField( required=True, display='Créditos disciplinares obligatorios restantes', default=0) rem_disc_o = IntField(required=True, display='Créditos disciplinares optativos restantes', default=0) rem_free = IntField(required=True, display='Créditos de libre elección restantes', default=0) comitee_act = StringField(required=True, display='Número de acta de comité', default='00') comitee_date = DateField(required=True, display='Fecha de reunión del comité', default=datetime.date.today) # Pre-cm variables request_in_date = BooleanField(display='Solicitud a tiempo', default=True) credits_granted = IntField(display='Créditos otorgados', default=0) str_pcm_pre = [ # Used in pcm and cm: 'reingreso por única vez a partir del periodo académico ', 'Si el estudiante no renueva su matrícula en el semestre de reingreso, el acto' + ' académico expedido por el Consejo de Facultad queda sin efecto.', '1. Datos Generales:', '2. Información Académica:', '3. Resumen general de créditos del plan de estudios:', '*Sin incluir los créditos correspondientes al cumplimiento del requisito de' + ' suficiencia en idioma.', # Used only in pcm: 'El estudiante ', ' tiene pendiente por aprobar ', ' créditos del plan de estudios de ', ' y ', ' créditos del requisito de nivelación', ' - inglés, con un cupo disponible para inscripción de ', ' créditos.', 'El parágrafo del artículo 11 del ', 'Superior Universitario establece: ', '"Los créditos adicionales que como resultado del ' + 'proceso de clasificación en la admisión deba aprobar ' + 'un estudiante de pregrado, se sumarán por única vez al "' + 'cupo adicional de créditos para inscripción"', ', por lo tanto solo es viable otorgar ', ' crédito(s) para la inscripción de asignaturas pendientes del plan de estudios de ', # Extra credits (optional): 'y otorga ', ' crédito(s) adicional(es) para culminar su plan de estudios. ' ] str_analysis = [ '{}a tenido otro reingreso después de 2009-01 (Artículo 46, {}). ' + 'Universitas y SIA: Revisado.', 'Si perdió calidad antes de 2009-01: Equivalencias incluyendo las asignaturas ' + 'perdidas. Comité Asesor asigna créditos a las que no tengan equivalencias ' + '(Artículo 3, {}). Universitas y SIA: Pérdida de calidad de estudiante al ' + 'finalizar {} por {}', '{}iene PAPA superior o igual a 2.7 (literal 3b – Artículo 3, {}; Artículo 46, ' + '{}). SIA: PAPA de {}.', '{}ispone de un cupo suficiente de créditos: Cupo adicional de 10 créditos a lo sumo ' + '(parágrafo 1 Artículo 46, {}). SIA: {} creditos. En caso de otorgarle un cupo adicional ' + 'de créditos, éste no podrá ser mayor que el requerido para inscribir las asignaturas ' + 'pendientes del plan de estudios. (Artículo 6, {}).', 'La solicitud {}se hace en fechas de calendario de sede.' ] str_pcm_pre_acadinfo = [ 'Periodo para el cual fue admitido en este plan de estudios', '¿Se trata de un primer reingreso?', 'Si la respuesta es NO, el Comité Asesor no debe recomendar al Consejo ' + 'de Facultad el reingreso', 'Es caso de ser primer reingreso en ¿qué periodo académico perdió la ' + 'calidad de estudiante?', 'Al momento de presentar la solicitud ¿cuántos periodos académicos (incluido' + ' el periodo académico en que presentó la solicitud) han transcurridos a partir' + ' del periodo académico en que registró su última matrícula?', 'En caso que la respuesta sea mayor de 6 periodos académicos no se debe ' + 'recomendar el reingreso', 'P.A.P.A.', 'Causa de la pérdida de la calidad de estudiante', 'Estudio de créditos', 'Cupo de créditos menos créditos pendientes', 'Créditos pendientes por ser aprobados del plan de estudios', 'Créditos pendientes por ser aprobados de nivelación – Inglés', '¿Cuántos créditos adicionales requiere para inscribir asignaturas?', # Optional: Grade needed with N credits to keep student condition. 'Al finalizar el semestre de reingreso para mantener la calidad de estudiante,' + ' deberá obtener un promedio semestral mínimo de:', 'Si inscribe 12 Créditos', 'Si inscribe 15 Créditos', 'Si inscribe 18 Créditos', 'Si inscribe 21 Créditos' ] str_out_date = [ 'reingreso por única vez a partir del periodo académico {}, porque el estudiante ' + 'presentó la solicitud fuera de las fechas establecidas en el Calendario Académico ' + 'de la Sede Bogotá.' ] def rein_general_data_table(self, docx): # pylint: disable=no-member general_data = [ ['Estudiante', self.student_name], ['DNI', self.student_dni], ['Plan de estudios', self.get_academic_program_display()], ['Código del plan de estudios', self.academic_program], ['Fecha de la solicitud', string_to_date(str(self.date))] ] case = 'REINGRESO' paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) bullet = paragraph.add_run(self.str_pcm_pre[2]) bullet.font.bold = True bullet.font.size = Pt(8) table_general_data(general_data, case, docx) def rein_academic_info(self, docx): paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) bullet = paragraph.add_run(self.str_pcm_pre[3]) bullet.font.bold = True bullet.font.size = Pt(8) table = docx.add_table(rows=13, cols=3) table.style = 'Table Grid' table.style.font.size = Pt(8) table.alignment = WD_ALIGN_PARAGRAPH.CENTER for cell in table.columns[0].cells: cell.width = 400000 for cell in table.columns[1].cells: cell.width = 3200000 for cell in table.columns[2].cells: cell.width = 1600000 table.columns[0].width = 400000 table.columns[1].width = 3200000 table.columns[2].width = 1600000 table.cell(0, 0).merge(table.cell(0, 1)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[0]) table.cell(0, 2).paragraphs[0].add_run(self.admission_period) table.cell(0, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(1, 0).merge(table.cell(1, 1)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[1]) if self.first_reing: table.cell(1, 2).paragraphs[0].add_run('Sí') else: table.cell(1, 2).paragraphs[0].add_run('No') table.cell(1, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(2, 0).merge(table.cell(2, 2)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[2]) table.cell(3, 0).merge(table.cell(3, 1)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[3]) table.cell(3, 2).paragraphs[0].add_run(self.loss_period) table.cell(3, 2).vertical_alignment = WD_ALIGN_VERTICAL.CENTER table.cell(3, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(4, 0).merge(table.cell(4, 1)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[4]) table.cell(4, 2).paragraphs[0].add_run(str(self.periods_since)) table.cell(4, 2).vertical_alignment = WD_ALIGN_VERTICAL.CENTER table.cell(4, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(5, 0).merge(table.cell(5, 2)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[5]) table.cell(6, 0).merge(table.cell(6, 1)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[6]) table.cell(6, 2).paragraphs[0].add_run(str(self.papa)) table.cell(6, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(7, 0).merge(table.cell(7, 1)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[7]) table.cell(7, 0).merge(table.cell( 7, 1)).vertical_alignment = WD_ALIGN_VERTICAL.CENTER table.cell(7, 2).paragraphs[0].add_run( # pylint: disable=no-member self.get_reason_of_loss_display()) table.cell(7, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(8, 0).merge(table.cell(8, 2)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[8]).font.bold = True table.cell(9, 0).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(9, 0).paragraphs[0].add_run('1').font.bold = True table.cell(10, 0).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(10, 0).paragraphs[0].add_run('2').font.bold = True table.cell(11, 0).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(11, 0).paragraphs[0].add_run('3').font.bold = True table.cell(12, 0).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(12, 0).paragraphs[0].add_run('4').font.bold = True table.cell(9, 1).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[9]) table.cell(10, 1).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[10]) table.cell(11, 1).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[11]) table.cell(12, 1).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[12]) table.cell(9, 2).paragraphs[0].add_run(str(self.credits_minus_remaining)) table.cell(9, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(10, 2).paragraphs[0].add_run(str(self.credits_remaining)) table.cell(10, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(11, 2).paragraphs[0].add_run(str(self.credits_english)) table.cell(11, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.cell(12, 2).paragraphs[0].add_run(str(self.credits_add)) table.cell(12, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER # Optional: Grade needed with N credits to keep student condition. if self.reason_of_loss == self.RL_ANSWER_CUPO_CREDITOS: table = docx.add_table(rows=5, cols=2) for col in table.columns: for cell in col.cells: cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER table.style = 'Table Grid' table.style.font.size = Pt(8) table.alignment = WD_ALIGN_PARAGRAPH.CENTER for cell in table.columns[0].cells: cell.width = 3100000 for cell in table.columns[1].cells: cell.width = 2100000 table.columns[0].width = 3100000 table.columns[1].width = 2100000 table.cell(0, 0).merge(table.cell( 0, 1)).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT table.cell(0, 0).merge(table.cell(0, 1)).paragraphs[0].add_run( self.str_pcm_pre_acadinfo[13]) table.cell(1, 0).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[14]) table.cell(2, 0).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[15]) table.cell(3, 0).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[16]) table.cell(4, 0).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[17]) table.cell(1, 1).paragraphs[0].add_run(str(self.min_grade_12c)) table.cell(2, 1).paragraphs[0].add_run(str(self.min_grade_15c)) table.cell(3, 1).paragraphs[0].add_run(str(self.min_grade_18c)) table.cell(4, 1).paragraphs[0].add_run(str(self.min_grade_21c)) def rein_credits_summary(self, docx): paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) bullet = paragraph.add_run(self.str_pcm_pre[4]) bullet.font.bold = True bullet.font.size = Pt(8) credits_data = [[ self.exi_fund_m, self.exi_fund_o, self.exi_disc_m, self.exi_disc_o, self.exi_free ], [ self.app_fund_m, self.app_fund_o, self.app_disc_m, self.app_disc_o, self.app_free ], [ self.rem_fund_m, self.rem_fund_o, self.rem_disc_m, self.rem_disc_o, self.rem_free ]] case = 'REINGRESO' table_credits_summary(docx, credits_data, case) paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) bullet = paragraph.add_run(self.str_pcm_pre[5]) bullet.font.size = Pt(8) def rein_recommends(self, docx): details = [] details.append( # pylint: disable=no-member self.get_academic_program_display()) # Migrate to case_utils? year = str(self.comitee_date)[0:4] month = str(self.comitee_date)[5:7] day = str(self.comitee_date)[8:10] details.append(day + '-' + month + '-' + year) details.append(self.comitee_act) details.append(str(self.comitee_date)[0:4]) if self.advisor_response == self.ARCR_APROBAR: details.append(True) else: details.append(False) table_recommend(docx, details) def extra_credits(self, paragraph): paragraph.add_run(self.str_pcm_pre[18] + str(self.credits_granted) + self.str_pcm_pre[19]) def get_analysis(self): analysis = [] modifier = 'No h' if self.first_reing else 'H' analysis.append(self.str_analysis[0].format( modifier, self.regulations['008|2008|CSU'][0])) analysis.append(self.str_analysis[1].format( self.regulations['239|2009|VAC'][0], # pylint: disable=no-member self.loss_period, self.get_reason_of_loss_display())) modifier = 'T' if self.papa >= 2.7 else 'No t' analysis.append(self.str_analysis[2].format( modifier, self.regulations['239|2009|VAC'][0], self.regulations['008|2008|CSU'][0], self.papa)) modifier = 'D' if self.credits_remaining > 0 else 'No d' analysis.append(self.str_analysis[3].format( modifier, self.regulations['008|2008|CSU'][0], self.credits_remaining, self.regulations['012|2014|VAC'][0])) modifier = '' if self.request_in_date else 'no ' analysis.append(self.str_analysis[4].format(modifier)) return analysis + self.extra_analysis def pcm(self, docx): add_analysis_paragraph(docx, self.get_analysis()) paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) self.pcm_answer(paragraph) #if self.request_in_date: To ommit tables when the request isn't in time self.cm_pcm_paragraph(docx) self.rein_general_data_table(docx) self.rein_academic_info(docx) self.rein_credits_summary(docx) self.rein_recommends(docx) def cm(self, docx): paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) #if self.request_in_date: To ommit tables when the request isn't in time self.cm_answer(paragraph) self.rein_general_data_table(docx) self.rein_academic_info(docx) self.rein_credits_summary(docx) self.rein_recommends(docx) def pcm_answer(self, paragraph): paragraph.add_run(self.str_answer + ':\n').font.bold = True paragraph.add_run(self.str_comittee_header + ' ') paragraph.add_run( # pylint: disable=no-member self.get_approval_status_display().upper() + ' ').font.bold = True if not self.request_in_date: self.out_of_date_answer(paragraph) else: aff = self.is_affirmative_response_advisor_response() self.standard_answer(paragraph, aff) def cm_pcm_paragraph(self, docx): if not self.request_in_date: return # Skip when it's out of date para = docx.add_paragraph() para.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY para.paragraph_format.space_after = Pt(0) para.add_run(self.str_pcm_pre[6] + self.student_name + self.str_pcm_pre[7] + str(self.credits_remaining)) para.add_run(self.str_pcm_pre[8] + # pylint: disable=no-member self.get_academic_program_display()) para.add_run(self.str_pcm_pre[9] + str(self.credits_english) + self.str_pcm_pre[10]) para.add_run(self.str_pcm_pre[11]) para.add_run(str(self.credits_remaining + self.credits_minus_remaining)) para.add_run(self.str_pcm_pre[12]) para = docx.add_paragraph() para.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY para.paragraph_format.space_after = Pt(0) para.add_run(self.str_pcm_pre[13] + self.regulations['008|2008|CSU'][0]) para.add_run(self.str_pcm_pre[14]) para.add_run(self.str_pcm_pre[15]).font.italic = True para.add_run(self.str_pcm_pre[16] + str(self.credits_granted)) para.add_run(self.str_pcm_pre[17]) para.add_run( # pylint: disable=no-member self.get_academic_program_display() + '.') 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 aff = self.is_affirmative_response_approval_status() self.standard_answer(paragraph, aff) def standard_answer(self, paragraph, affirmative): paragraph.add_run(self.str_pcm_pre[0]) paragraph.add_run(self.academic_period + ' ') if self.credits_granted > 0: # Y otorga n créditos adicionales: self.extra_credits(paragraph) if affirmative: paragraph.add_run(self.str_pcm_pre[1]) else: paragraph.add_run(self.council_decision + '.') paragraph.add_run('({}).'.format(self.regulations['012|2014|VAC'][0] + "; Artículo 46, " + self.regulations['008|2008|CSU'][0])) def out_of_date_answer(self, paragraph): paragraph.add_run(self.str_out_date[0].format(self.reing_period))
class TEPR(Request): full_name = 'Tránsito entre programas' origin_program = StringField(min_length=4, max_length=4, choices=Request.PLAN_CHOICES, required=True, display='Programa Académico origen', default=Request.PI_ELECTRICA) academic_period_transit = StringField(max_length=10, required=True, display='Periodo de tránsito', choices=Request.PERIOD_CHOICES, default=Request.PERIOD_DEFAULT) available_places = BooleanField(display='Hay cupos en el plan de estudios', default=False) languaje = BooleanField( display='Cumple requisito de idioma en el plan destino', default=True) on_time = BooleanField(display='Cumple fechas establecidas', default=True) regulation_list = ['035|2014|VAC', '002|2011|CFA', '241|2009|VAC'] # List of regulations str_cm = [ 'tránsito del programa {} ({}) al programa {} ({}), a partir del periodo académico {}', 'debido a que {}.' ] str_pcm = [ 'En el programa hay {}cupos para tránsito.', 'Viene del programa {} ({}).', 'El estudiante {}cumple con la suficiencia de idioma exigida.', 'La solicitud {}se hace luego de completar el plan de estudios y antes del grado (a menos' + ' que no se haya abierto convocatorio durante el periodo)(Parágrafo 2, {}).' ] def cm(self, docx): paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY 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 paragraph.add_run(self.str_cm[0].format( # pylint: disable=no-member self.get_origin_program_display(), self.origin_program, self.get_academic_program_display(), self.academic_program, self.academic_period_transit) + ', ') paragraph.add_run(self.str_cm[1].format(self.council_decision)) 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 + ': ').bold = True paragraph = docx.add_paragraph() paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.add_run(self.str_comittee_header + ' ') self.pcm_answer(paragraph) def pcm_analysis(self, docx): analysis_list = [] analysis_list += [ self.str_pcm[0].format('' if self.available_places else 'no ') ] analysis_list += [ self.str_pcm[1].format( # pylint: disable=no-member self.get_origin_program_display(), self.origin_program, ) ] analysis_list += [ self.str_pcm[2].format('' if self.languaje else 'no ') ] analysis_list += [ self.str_pcm[3].format( '' if self.on_time else 'no ', Request.regulations[self.regulation_list[2]][0]) ] analysis_list += self.extra_analysis add_analysis_paragraph(docx, analysis_list) def pcm_answer(self, paragraph): paragraph.add_run( # pylint: disable=no-member self.get_approval_status_display().upper() + ' ').font.bold = True paragraph.add_run(self.str_cm[0].format( # pylint: disable=no-member self.get_origin_program_display(), self.origin_program, self.get_academic_program_display(), self.academic_program, self.academic_period_transit) + ', ') paragraph.add_run(self.str_cm[1].format(self.council_decision)) 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 Request(DynamicDocument): meta = {'allow_inheritance': True} full_name = 'Petición sin tipo' decision_makers = ( 'Consejo de Facultad', 'Comité Asesor', 'Director de Tesis', 'Comité de Matricula', 'Consejo de Sede', 'Consejo Superior Universitario', ) decision_maker = decision_makers[0] # Request is in cm, pcm (or not) in_cm = True in_pcm = True # AS Approval Status AS_APLAZA = 'AL' AS_APRUEBA = 'AP' AS_EN_TRAMITE = 'ET' AS_EN_ESPERA = 'EE' AS_NO_APRUEBA = 'NA' AS_SE_INHIBE = 'SI' AS_CONSEJO_RECOMIENDA = 'FR' AS_CONSEJO_NO_RECOMIENDA = 'FN' AS_ANULADA = 'AN' AS_RENUNCIA = 'RN' AS_CHOICES = ( (AS_APLAZA, 'Aplaza'), (AS_APRUEBA, 'Aprueba'), (AS_EN_TRAMITE, 'En trámite'), (AS_EN_ESPERA, 'En espera'), (AS_NO_APRUEBA, 'No Aprueba'), (AS_SE_INHIBE, 'Se Inhibe'), (AS_CONSEJO_RECOMIENDA, 'Consejo Recomienda'), (AS_CONSEJO_NO_RECOMIENDA, 'Consejo No Recomienda'), (AS_ANULADA, 'Anular'), (AS_RENUNCIA, 'Desistir'), ) # ARCR Advisor Response - Committee Recommends ARCR_APROBAR = 'CAP' ARCR_NO_APROBAR = 'CNA' ARCR_RECOMENDAR = 'CRR' ARCR_NO_RECOMENDAR = 'CRN' ARCR_EN_ESPERA = 'CEE' ARCR_CHOICES = ( (ARCR_APROBAR, 'Aprobar'), (ARCR_NO_APROBAR, 'No Aprobar'), (ARCR_RECOMENDAR, 'Recomendar'), (ARCR_NO_RECOMENDAR, 'No recomendar'), (ARCR_EN_ESPERA, 'En espera'), ) DNI_TYPE_CEDULA_DE_CIUDADANIA = 'CC' DNI_TYPE_PASAPORTE = 'PS' DNI_TYPE_TARJETA_DE_IDENTIDAD = 'TI' DNI_TYPE_CEDULA_DE_EXTRANJERIA = 'CE' DNI_TYPE_OTRO = 'OT' DNI_TYPE_CHOICES = ( (DNI_TYPE_OTRO, 'Otro'), (DNI_TYPE_PASAPORTE, 'Pasaporte'), (DNI_TYPE_CEDULA_DE_EXTRANJERIA, 'Cédula de extranjería'), (DNI_TYPE_CEDULA_DE_CIUDADANIA, 'Cédula de Ciudadanía colombiana'), (DNI_TYPE_TARJETA_DE_IDENTIDAD, 'Tarjeta de Identidad colombiana'), ) # P Plan # I Ingenieria # E Especializacion # M Maestria # D Doctorado # BAP Bogota Asignaturas de Posgrado PI_CIVIL = '2542' PI_QUIMICA = '2549' PI_MECANICA = '2547' PI_AGRICOLA = '2541' PI_ELECTRICA = '2544' PI_INDUSTRIAL = '2546' PI_MECATRONICA = '2548' PI_ELECTRONICA = '2545' PM_BIOINFORMATICA = '2882' PE_GEOTECNIA = '2217' PE_TRANSPORTE = '2285' PE_ESTRUCTURAS = '2886' PMI_INDUSTRIAL = '2708' PMI_GEOTECNIA = '2700' PMI_TRANSPORTE = '2706' PMI_ESTRUCTURAS = '2699' PI_DE_SISTEMAS_Y_COMPUTACION = '2879' PE_RECURSOS_HIDRAULICOS = '2278' PE_GOBIERNO_ELECTRONICO = '2896' PEI_ELECTRICA = '2113' PE_CALIDAD_DE_LA_ENERGIA = '2064' PDI_CIVIL = '2887' PMI_TELECOMUNICACIONES = '2707' PE_AUTOMATIZACION_INDUSTRIAL = '2687' PMI_QUIMICA = '2704' PDI_QUIMICA = '2686' PMI_MECANICA = '2709' PMI_MATERIALES_Y_PROCESOS = '2710' PMI_AGRICOLA = '2701' PMI_RECURSOS_HIDRAULICOS = '2705' PMI_AMBIENTAL = '2562' PDI_ELECTRICA = '2685' PMI_ELECTRICA = '2703' PDI_SISTEMAS_Y_COMPUTACION = '2684' PE_ILUMINACION_PUBLICA_Y_PRIVADA = '2691' PMI_ELECTRONICA = '2865' PMI_AUTOMATIZACION_INDUSTRIAL = '2698' PDI_INDUSTRIA_Y_ORGANIZACIONES = '2838' PE_TRANSITO_DISEÑO_Y_SEGURIDAD_VIAL = '2696' PDI_CIENCIA_Y_TECNOLOGIA_DE_MATERIALES = '2682' PDI_MECANICA_Y_MECATRONICA = '2839' PMI_DE_SISTEMAS_Y_COMPUTACION = '2702' PDI_ESTUDIOS_AMBIENTALES = '2979' PMI_ELECTRICA_CONVENIO_SEDE_MANIZALES = '2794' PMI_DE_SISTEMAS_Y_COMPUTACION_CONV_UPC = '2856' PMI_DE_SISTEMAS_Y_COMPUTACION_CONV_UNILLANOS = '2928' BAP_ARTES = 'BAPA' BAP_CIENCIAS = 'BAPC' BAP_DERECHO = 'BAPD' BAP_ECONOMIA = 'BAPE' BAP_AGRONOMIA = 'BAPG' BAP_HUMANAS = 'BAPH' BAP_INGENIERIA = 'BAPI' BAP_MEDICINA = 'BAPM' BAP_ENFERMERIA = 'BAPN' BAP_ODONTOLOGIA = 'BAPO' PLAN_CHOICES = ( (PI_CIVIL, 'Ingeniería Civil'), (PI_QUIMICA, 'Ingeniería Química'), (PI_MECANICA, 'Ingeniería Mecánica'), (PI_AGRICOLA, 'Ingeniería Agrícola'), (PI_ELECTRICA, 'Ingeniería Eléctrica'), (PI_INDUSTRIAL, 'Ingeniería Industrial'), (PI_MECATRONICA, 'Ingeniería Mecatrónica'), (PI_ELECTRONICA, 'Ingeniería Electrónica'), (PM_BIOINFORMATICA, 'Maestría en Bioinformática'), (PE_GEOTECNIA, 'Especialización en Geotecnia'), (PE_TRANSPORTE, 'Especialización en Transporte'), (PE_ESTRUCTURAS, 'Especialización en Estructuras'), (PMI_INDUSTRIAL, 'Maestría en Ingeniería Industrial'), (PMI_GEOTECNIA, 'Maestría en Ingeniería - Geotecnia'), (PMI_TRANSPORTE, 'Maestría en Ingeniería - Transporte'), (PMI_ESTRUCTURAS, 'Maestría en Ingeniería - Estructuras'), (PI_DE_SISTEMAS_Y_COMPUTACION, 'Ingeniería de Sistemas y Computación'), (PE_RECURSOS_HIDRAULICOS, 'Especialización en Recursos Hidráulicos'), (PE_GOBIERNO_ELECTRONICO, 'Especialización en Gobierno Electrónico'), (PEI_ELECTRICA, 'Especialización en Ingeniería Eléctrica'), (PE_CALIDAD_DE_LA_ENERGIA, 'Especialización en Calidad de la Energía'), (PDI_CIVIL, 'Doctorado en Ingeniería - Ingeniería Civil'), (PMI_TELECOMUNICACIONES, 'Maestría en Ingeniería - Telecomunicaciones'), (PE_AUTOMATIZACION_INDUSTRIAL, 'Especialización en Automatización Industrial'), (PMI_QUIMICA, 'Maestría en Ingeniería - Ingeniería Química'), (PDI_QUIMICA, 'Doctorado en Ingeniería - Ingeniería Química'), (PMI_MECANICA, 'Maestría en Ingeniería - Ingeniería Mecánica'), (PMI_MATERIALES_Y_PROCESOS, 'Maestría en Ingeniería - Materiales y Procesos'), (PMI_AGRICOLA, 'Maestría en Ingeniería - Ingeniería Agrícola'), (PMI_RECURSOS_HIDRAULICOS, 'Maestría en Ingeniería - Recursos Hidráulicos'), (PMI_AMBIENTAL, 'Maestría en Ingeniería - Ingeniería Ambiental'), (PDI_ELECTRICA, 'Doctorado en Ingeniería - Ingeniería Eléctrica'), (PMI_ELECTRICA, 'Maestría en Ingeniería - Ingeniería Eléctrica'), (PDI_SISTEMAS_Y_COMPUTACION, 'Doctorado en Ingeniería - Sistemas y Computación'), (PE_ILUMINACION_PUBLICA_Y_PRIVADA, 'Especialización en Iluminación Pública y Privada'), (PMI_ELECTRONICA, 'Maestría en Ingeniería - Ingeniería Electrónica'), (PMI_AUTOMATIZACION_INDUSTRIAL, 'Maestría en Ingeniería - Automatización Industrial'), (PDI_INDUSTRIA_Y_ORGANIZACIONES, 'Doctorado en Ingeniería - Industria y Organizaciones'), (PE_TRANSITO_DISEÑO_Y_SEGURIDAD_VIAL, 'Especialización en Transito, Diseño y Seguridad Vial'), (PDI_CIENCIA_Y_TECNOLOGIA_DE_MATERIALES, 'Doctorado en Ingeniería - Ciencia y Tecnología de Materiales'), (PDI_MECANICA_Y_MECATRONICA, 'Doctorado en Ingeniería - Ingeniería Mecánica y Mecatrónica'), (PMI_DE_SISTEMAS_Y_COMPUTACION, 'Maestría en Ingeniería - Ingeniería de Sistemas y Computación'), (PMI_ELECTRICA_CONVENIO_SEDE_MANIZALES, 'Maestría en Ingeniería - Ingeniería Eléctrica Convenio Sede Manizales' ), (PMI_DE_SISTEMAS_Y_COMPUTACION_CONV_UPC, 'Maestría en Ingeniería - Ingeniería de Sistemas y Computación - Conv UPC' ), (PMI_DE_SISTEMAS_Y_COMPUTACION_CONV_UNILLANOS, 'Maestría en Ingeniería - Ingeniería de Sistemas y Computación - Conv Unillanos' ), (PDI_ESTUDIOS_AMBIENTALES, 'Doctorado en Estudios Ambientales'), (BAP_ARTES, 'Modalidad de Asignaturas de Posgrado Facultad de Artes'), (BAP_CIENCIAS, 'Modalidad de Asignaturas de Posgrado Facultad de Ciencias'), (BAP_DERECHO, 'Modalidad de Asignaturas de Posgrado Facultad de Derecho'), (BAP_ECONOMIA, 'Modalidad de Asignaturas de Posgrado Facultad de Economía'), (BAP_AGRONOMIA, 'Modalidad de Asignaturas de Posgrado Facultad de Agronomía'), (BAP_HUMANAS, 'Modalidad de Asignaturas de Posgrado Facultad de Humanas'), (BAP_INGENIERIA, 'Modalidad de Asignaturas de Posgrado Facultad de Ingeniería'), (BAP_MEDICINA, 'Modalidad de Asignaturas de Posgrado Facultad de Medicina'), (BAP_ENFERMERIA, 'Modalidad de Asignaturas de Posgrado Facultad de Enfermería'), (BAP_ODONTOLOGIA, 'Modalidad de Asignaturas de Posgrado Facultad de Odontología'), ) # DP Departamento DP_CIVIL_AGRICOLA = 'DCA' DP_ELECTRICA_ELECTRONICA = 'DEE' DP_MECANICA_MECATRONICA = 'DMM' DP_SISTEMAS_INDUSTRIAL = 'DSI' DP_QUIMICA_AMBIENTAL = 'DQA' DP_EXTERNO_FACULTAD = 'EFA' DP_EMPTY = '' DP_CHOICES = ( (DP_CIVIL_AGRICOLA, 'Departamento de Ingeniería Civil y Agrícola'), (DP_ELECTRICA_ELECTRONICA, 'Departamento de Ingeniería Eléctrica y Electrónica'), (DP_MECANICA_MECATRONICA, 'Departamento de Ingeniería Mecánica y Mecatrónica'), (DP_SISTEMAS_INDUSTRIAL, 'Departamento de Ingeniería de Sistemas e Industrial'), (DP_QUIMICA_AMBIENTAL, 'Departamento de Ingeniería Química y Ambiental'), (DP_EXTERNO_FACULTAD, 'Externo a la Facultad de Ingeniería'), (DP_EMPTY, ''), ) PROFILE_INVE = 'I' PROFILE_PROF = 'P' PROFILE_CHOICES = ((PROFILE_INVE, 'Investigación'), (PROFILE_PROF, 'Profundización')) GRADE_OPTION_TRABAJO_FINAL_MAESTRIA = 'TFM' GRADE_OPTION_TESIS_MAESTRIA = 'TSM' GRADE_OPTION_TESIS_DOCTORADO = 'TSD' GRADE_OPTION_CHOICES = ((GRADE_OPTION_TRABAJO_FINAL_MAESTRIA, 'Trabajo Final de Maestría'), (GRADE_OPTION_TESIS_MAESTRIA, 'Tesis de Maestría')) PERIOD_CHOICES = get_period_choices() PERIOD_DEFAULT = PERIOD_CHOICES[1][0] if datetime.date.today( ).month <= 6 else PERIOD_CHOICES[0][0] _cls = StringField(required=True) _cls_display = StringField(default=full_name) date_stamp = DateTimeField(default=datetime.datetime.now) user = StringField(max_length=255, required=True) consecutive_minute = IntField( min_value=0, default=0, display='Número del Acta de Consejo de Facultad') consecutive_minute_ac = IntField(min_value=0, default=0, display='Número del Acta de Comité Asesor' ) # ac stands for advisory committe year = IntField(min_value=2000, max_value=2100, display='Año del Acta', default=datetime.date.today().year) to_legal = BooleanField( default=False, display='Sugerir remitir caso a Comisión Delegataria') date = DateTimeField(default=datetime.date.today, display='Fecha de radicación') academic_program = StringField(min_length=4, max_length=4, choices=PLAN_CHOICES, display='Programa Académico', default=PI_AGRICOLA) student_dni_type = StringField(min_length=2, choices=DNI_TYPE_CHOICES, default=DNI_TYPE_CEDULA_DE_CIUDADANIA, display='Tipo de Documento') student_dni = StringField(max_length=22, display='Documento', default='') student_name = StringField(max_length=512, display='Nombre del Estudiante', default='') academic_period = StringField(max_length=10, display='Periodo Académico Actual', choices=PERIOD_CHOICES, default=PERIOD_DEFAULT) approval_status = StringField(min_length=2, max_length=2, choices=AS_CHOICES, default=AS_EN_ESPERA, display='Estado de Aprobación') archive_note = StringField(max_length=200, default=None) advisor_response = StringField(min_length=3, max_length=3, choices=ARCR_CHOICES, default=ARCR_EN_ESPERA, display='Respuesta del Comité') council_decision = StringField( max_length=255, default='Justifica debidamente la solicitud.', display='Justificación del Consejo') student_justification = StringField(default='', display='Justificación del Estudiante') supports = StringField(default='', display='Soportes') extra_analysis = ListField(StringField(), display='Análisis Extra') received_date = DateTimeField( ) # Date when advisor recieves a case from secretary notes = StringField() regulations = { '008|2008|CSU': ('Acuerdo 008 de 2008 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=34983'), '026|2012|CSU': ('Acuerdo 026 de 2012 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=47025'), '032|2010|CSU': ('Acuerdo 032 de 2010 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=39424'), '040|2017|CSU': ('Acuerdo 40 de 2012 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=89183'), '051|2003|CSU': ('Resolución 051 de 2003 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=35163'), '056|2012|CSU': ('Acuerdo 056 de 2012 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=48208'), '102|2013|CSU': ('Acuerdo 102 de 2013 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=56987'), '230|2016|CSU': ('Acuerdo 230 de 2016 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=87737'), '014|2008|CAC': ('Acuerdo 014 de 2008 del Consejo Académico', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=34127'), '016|2011|CAC': ('Acuerdo 016 de 2011 del Consejo Academico', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=44965'), '070|2009|CAC': ('Acuerdo 070 de 2009 de Consejo Académico', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=35443'), '089|2014|CAC': ('Acuerdo 089 de 2014 del Consejo Académico', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=66330'), '002|2012|CFA': ('Acuerdo 002 de 2012 de Consejo de Facultad', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=50509'), '002|2011|CFA': ('Acuerdo 002 de 2011 de Consejo de Facultad', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=42724'), '040|2017|CFA': ('Acuerdo 40 de 2017 del Consejo de Facultad', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=89183'), '001|2016|VAC': ('Circular 01 de 2016 de la Vicerectoría Académica', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=86414#0'), '012|2014|VAC': ('Resolución 012 de 2014 de Vicerrectoría Académica', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=62849'), '035|2014|VAC': ('Resolución 035 de 2018 de La Vicerrectoría Académica', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=69990'), '239|2009|VAC': ('Resolución 239 de 2009 de Vicerrectoría Académica', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=34644'), '241|2009|VAC': ('Resolución 241 de 2009 de la Vicerrectoría Académica', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=34651'), '001|2019|VSB': ('Circular 001 de 2019 de Vicerrectoría de Sede Bogotá', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=92579'), '1416|2013|RE': ('Resolución 1416 de 2013 de Rectoría', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=60849'), '070|2012|CSU': ('Acuerdo 70 de 2018 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=50105'), '155|2014|CSU': ('Acuerdo 155 de 2014 del Consejo Superior Universitario', 'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=69337'), } assertionerror = {'CHOICES': '{} is not in choices list.'} str_analysis = 'Análisis' str_answer = 'Concepto' str_council_header = 'El Consejo de Facultad' str_comittee_header = 'El Comité Asesor recomienda al Consejo de Facultad' def is_affirmative_response_approval_status(self): return self.approval_status in (self.AS_APRUEBA, self.AS_CONSEJO_RECOMIENDA) def is_waiting_response_advisor_response(self): return self.advisor_response in (self.ARCR_EN_ESPERA) def is_affirmative_response_advisor_response(self): return self.advisor_response in (self.ARCR_RECOMENDAR, self.ARCR_APROBAR) def is_pre(self): return self.academic_program in (self.PI_AGRICOLA, self.PI_CIVIL, self.PI_DE_SISTEMAS_Y_COMPUTACION, self.PI_INDUSTRIAL, self.PI_ELECTRICA, self.PI_MECANICA, self.PI_MECATRONICA, self.PI_ELECTRONICA, self.PI_QUIMICA) def safe_save(self): try: self.save() except ValidationError as e: raise ValueError(e.message) @staticmethod def get_cases_by_query(query): # pylint: disable=no-member ## Get all cases that follows the query cases = Request.objects(**query) ## Ignore "deleted" cases cases = cases.filter( approval_status__nin=[Request.AS_ANULADA, Request.AS_RENUNCIA]) return cases.order_by('-date_stamp') @staticmethod def get_case_by_id(caseid): try: # pylint: disable=no-member return Request.objects.get(id=caseid) except ValidationError as e: raise ValueError(e.message) except DoesNotExist as e: raise KeyError('ID {} does not exist') @staticmethod def get_programs(): return {'programs': sorted([plan[1] for plan in Request.PLAN_CHOICES])} @staticmethod def get_cases(): cases = [{ 'code': type_case.__name__, 'name': type_case.full_name } for type_case in Request.get_subclasses()] cases.sort(key=lambda case: case['name']) return {'cases': cases} @classmethod def translate(cls, data): to_del = [] data_json = json.loads(data) for key in data_json: if data_json[key] is None or data_json[key] == 'None': to_del.append(key) continue try: # pylint: disable=no-member choices = cls._fields[key].choices if choices: for item in choices: if item[1] == data_json[key]: data_json[key] = item[0] break elif isinstance(cls._fields[key], EmbeddedDocumentListField): _cls = cls._fields[key].field.document_type_obj for field in _cls._fields: choices = _cls._fields[field].choices if choices: _dict = dict((y, x) for x, y in choices) for element in data_json[key]: if element[field] in _dict: element[field] = _dict[element[field]] elif isinstance(cls._fields[key], ListField): choices = cls._fields[key].field.choices if choices: _dict = dict((y, x) for x, y in choices) for i, element in enumerate(data_json[key]): if element in _dict: data_json[key][i] = _dict[element] except KeyError: pass for key in to_del: del data_json[key] return json.dumps(data_json) @classmethod def get_entire_name(cls): parents = cls.mro() index = parents.index(Request) name = 'Request.' for _cls in reversed(parents[:index]): name += _cls.__name__ + '.' return name[:-1] @classmethod def get_subclasses(cls): subs = [] for subclass in cls.__subclasses__(): subs.append(subclass) subs += subclass.get_subclasses() return subs
class IndicatorAccess(EmbeddedDocument, CritsDocumentFormatter, CommonAccess): """ ACL for Indicators. """ type_edit = BooleanField(default=False) threat_type_edit = BooleanField(default=False) attack_type_edit = BooleanField(default=False) confidence_edit = BooleanField(default=False) impact_edit = BooleanField(default=False) actions_read = BooleanField(default=False) actions_add = BooleanField(default=False) actions_edit = BooleanField(default=False) actions_delete = BooleanField(default=False) activity_read = BooleanField(default=False) activity_add = BooleanField(default=False) activity_edit = BooleanField(default=False) activity_delete = BooleanField(default=False)
class User(Document): username = StringField() password = StringField() email_verified = BooleanField(default=False)
class CPTE(Request): full_name = 'Cambio de proyecto de tesis de maestría' 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')) title = StringField(required=True, display='Nuevo título de la tesis', default='') grade_option = StringField( required=True, # display='Tipo de tesis/trabajo final', choices=GO_CHOICES, default=GO_TESIS_MAESTRIA) new_advisor = StringField(required=True, display='Nuevo director de tesis', default='') old_advisor = StringField(display='Antiguo director de tesis', default='') new_co_advisor = StringField(display='Nuevo codirector de tesis', default='') old_co_advisor = StringField(display='Antiguo codirector de tesis', default='') inst_new_advisor = StringField( choices=Request.DP_CHOICES, display='Departamento de adscripción del nuevo director', default=Request.DP_EMPTY) inst_new_co_advisor = StringField( choices=Request.DP_CHOICES, display='Departamento de adscripción del nuevo codirector', default=Request.DP_EMPTY) inst_old_co_advisor = StringField( choices=Request.DP_CHOICES, display='Departamento de adscripción del antiguo codirector', default=Request.DP_EMPTY) inst_old_advisor = StringField( choices=Request.DP_CHOICES, display='Departamento de adscripción del antiguo director', default=Request.DP_EMPTY) enrolled_thesis = BooleanField( required=True, default=False, display='¿Tiene inscrita la asignatura tesis/trabajo final?') have_signature = BooleanField( required=True, default=False, display='¿Tiene la firma del (los) director(es)?') regulation_list = ['002|2011|CFA', '056|2012|CSU'] # List of regulations str_cm = [ 'cambiar el título de {} del programa {} a: ', '"{}"', 'ratificar director', 'designar nuevo director', 'al profesor', 'en reemplazo del profesor', 'Designar nuevo codirector', 'ratificar director', ' del ', 'debido a que', 'Ratificar nuevo codirector' ] list_analysis = [ 'Perfil de {}.', 'El estudiante {}tiene inscrita la asignatura {}.', 'iene la firma de los directores de tesis/trabajo final: {}' ] 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 # pylint: disable=no-member paragraph.add_run(self.str_cm[0].format( self.get_grade_option_display(), self.get_academic_program_display())) paragraph.add_run(self.str_cm[1].format(self.title)).font.italic = True if self.is_affirmative_response_approval_status(): self.cm_af(paragraph) else: self.cm_ng(paragraph) 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) def pcm_answer(self, paragraph): paragraph.add_run( # pylint: disable=no-member self.get_advisor_response_display().upper()).font.bold = True # pylint: disable=no-member paragraph.add_run( ' ' + self.str_cm[0].format(self.get_grade_option_display(), self.get_academic_program_display())) paragraph.add_run(self.str_cm[1].format(self.title)).font.italic = True if self.is_affirmative_response_approval_status(): self.cm_af(paragraph) else: self.cm_ng(paragraph) def cm_af(self, paragraph): if self.old_advisor == self.new_advisor or self.old_advisor == '': paragraph.add_run(', ' + self.str_cm[2] + ' ' + self.str_cm[4] + ' ') paragraph.add_run(self.new_advisor) if self.inst_new_advisor != self.DP_EXTERNO_FACULTAD and \ self.inst_new_advisor != '': # pylint: disable=no-member paragraph.add_run(self.str_cm[8] + self.get_inst_new_advisor_display()) else: paragraph.add_run(', ' + self.str_cm[3] + ' ' + self.str_cm[4] + ' ') paragraph.add_run(self.new_advisor) if self.inst_new_advisor != self.DP_EXTERNO_FACULTAD and \ self.inst_new_advisor != '': # pylint: disable=no-member paragraph.add_run(self.str_cm[8] + self.get_inst_new_advisor_display()) paragraph.add_run(' ' + self.str_cm[5] + ' ' + self.old_advisor) # pylint: disable=no-member paragraph.add_run(self.str_cm[8] + self.get_inst_old_advisor_display()) paragraph.add_run('.') if self.new_co_advisor != '': if self.old_co_advisor == self.new_co_advisor or\ self.old_co_advisor == '': paragraph.add_run(' ' + self.str_cm[10] + ' ' + self.str_cm[4] + ' ') paragraph.add_run(self.new_co_advisor) if self.inst_new_co_advisor != self.DP_EXTERNO_FACULTAD and \ self.inst_new_co_advisor != '': # pylint: disable=no-member paragraph.add_run(self.str_cm[8] + self.get_inst_new_co_advisor_display()) else: paragraph.add_run(' ' + self.str_cm[6] + ' ' + self.str_cm[4] + ' ') paragraph.add_run(self.new_co_advisor) if self.inst_new_co_advisor != self.DP_EXTERNO_FACULTAD and \ self.inst_new_co_advisor != '': # pylint: disable=no-member paragraph.add_run(self.str_cm[8] + self.get_inst_new_co_advisor_display()) paragraph.add_run(' ' + self.str_cm[5] + ' ') paragraph.add_run(self.old_co_advisor) if self.inst_old_co_advisor != self.DP_EXTERNO_FACULTAD and \ self.inst_old_co_advisor != '': # pylint: disable=no-member paragraph.add_run(self.str_cm[8] + self.get_inst_old_co_advisor_display()) paragraph.add_run('.') def cm_ng(self, paragraph): paragraph.add_run(' ' + self.str_cm[9] + ' ' + self.council_decision + '.') def pcm_analysis(self, docx): if self.grade_option in [ self.GO_TESIS_MAESTRIA, self.GO_TESIS_DOCTORADO ]: profile = 'investigación' else: profile = 'profundización' final_analysis = [] final_analysis += [self.list_analysis[0].format(profile)] ets = '' if self.enrolled_thesis else 'no ' # pylint: disable=no-member final_analysis += [ self.list_analysis[1].format(ets, self.get_grade_option_display()) ] hss = 'T' if self.have_signature else 'No t' final_analysis += [ hss + self.list_analysis[2].format(self.new_advisor) ] for extra_a in self.extra_analysis: final_analysis += [extra_a] add_analysis_paragraph(docx, final_analysis) 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 MOTP(Request): full_name = 'Cambio de objetivos de tesis o trabajo final' decision_maker = Request.decision_makers[1] in_cm = False 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') ) title = StringField( required=True, display='Título de la tesis/trabajo final', default=''), grade_option = StringField( required=True, display='Tipo de tesis/trabajo final', choices=GO_CHOICES, default=GO_TESIS_MAESTRIA) general_objetive = StringField( required=True, display='Objetivo general', default='') specific_objetives = ListField(StringField(), display='Objetivos específicos') enrolled_thesis = BooleanField( required=True, default=False, display='¿Tiene inscrita la asignatura tesis/trabajo final?') regulation_list = ['040|2017|CFA', '056|2012|CSU'] # List of regulations str_cm = ['cambiar los objetivos de ', '"{}"', 'a:', 'debido a que'] list_analysis = ['Título:', 'Objetivo general:', 'Objetivos específicos:', 'Perfil de {}.', 'El estudiante {}tiene inscrita la asignatura {}.'] 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) self.cm_ob(docx) def cm_answer(self, paragraph): paragraph.add_run(self.str_council_header + ' ') # pylint: disable=no-member paragraph.add_run( self.get_approval_status_display().upper() + ' ').font.bold = True paragraph.add_run( self.str_cm[0] + self.get_grade_option_display() + ' ') paragraph.add_run(self.str_cm[1].format(self.title)).font.italic = True 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) self.cm_ob(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 # pylint: disable=no-member paragraph.add_run(' ' + self.str_cm[0].format( self.get_grade_option_display(), self.get_academic_program_display())) paragraph.add_run(self.str_cm[1].format(self.title)).font.italic = True if self.is_affirmative_response_approval_status(): self.cm_af(paragraph) else: self.cm_ng(paragraph) def cm_af(self, paragraph): paragraph.add_run(' ' + self.str_cm[2]) def cm_ng(self, paragraph): paragraph.add_run( ' ' + self.str_cm[3] + ' ' + self.council_decision + '.') def cm_ob(self, docx): if not self.is_affirmative_response_approval_status(): return paragraph = docx.add_paragraph() paragraph.style = 'List Bullet' paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.list_analysis[1]).font.bold = True paragraph = docx.add_paragraph() paragraph.style = 'List Bullet 2' paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.general_objetive + '.') paragraph = docx.add_paragraph() paragraph.style = 'List Bullet' paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.list_analysis[2]).font.bold = True for spec in self.specific_objetives: paragraph = docx.add_paragraph() paragraph.style = 'List Bullet 2' paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(spec + '.') def pcm_analysis(self, docx): if self.grade_option in [self.GO_TESIS_MAESTRIA, self.GO_TESIS_DOCTORADO]: profile = 'investigación' else: profile = 'profundización' final_analysis = [] final_analysis += [self.list_analysis[3].format(profile)] ets = '' if self.enrolled_thesis else 'no ' # pylint: disable=no-member final_analysis += [self.list_analysis[4].format( ets, self.get_grade_option_display())] for extra_a in self.extra_analysis: final_analysis += [extra_a] add_analysis_paragraph(docx, final_analysis) paragraph = docx.add_paragraph() paragraph.style = 'List Bullet' paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY paragraph.paragraph_format.space_after = Pt(0) paragraph.add_run(self.list_analysis[0] + ' ').font.bold = True paragraph.add_run(self.title + '.').font.italic = True
class EMCA(Request): full_name = 'Exención de matrícula por consideración atípica' percentage = FloatField( min_value=0.0, max_value=100.0, required=True, display='Porcentaje de exención del valor de la matrícula', default=0.0) academic_period_exe = StringField(max_length=10, display='Periodo de exención', choices=Request.PERIOD_CHOICES, default=Request.PERIOD_DEFAULT) ha_active = BooleanField(default=True, display='¿Tiene la historia académica activa?') regulation_list = ['070|2009|CAC'] # List of regulations str_cm = [ ' otorgrar exención del pago de {}% del valor de la matrícula para el periodo ' + 'académico {}, ', ' ({}).' ] str_analysis = ['iene la historia académica activa.'] list_analysis = [] 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): # pylint: disable=no-member paragraph.add_run(self.str_council_header + ' ') paragraph.add_run(self.get_approval_status_display().upper() + ' ').font.bold = True paragraph.add_run(self.str_cm[0].format(self.percentage, self.academic_period_exe)) paragraph.add_run(self.council_decision) paragraph.add_run(self.str_cm[1].format( Request.regulations['070|2009|CAC'][0])) def pcm(self, docx): self.pcm_analysis(docx) self.pcm_answer(docx) def pcm_answer(self, docx): # pylint: disable=no-member 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( self.get_advisor_response_display().upper()).font.bold = True paragraph.add_run(self.str_cm[0].format(self.percentage, self.academic_period_exe)) paragraph.add_run(self.council_decision) paragraph.add_run(self.str_cm[1].format( Request.regulations['070|2009|CAC'][0])) def pcm_analysis(self, docx): final_analysis = [] aux = 'T' if self.ha_active else 'No t' final_analysis += [aux + self.str_analysis[0]] for extra_a in self.extra_analysis: final_analysis += [extra_a] add_analysis_paragraph(docx, final_analysis)
class CRITsUser(CritsDocument, CritsSchemaDocument, Document): """ CRITs User object """ meta = { "collection": settings.COL_USERS, 'indexes': [ { 'fields': ['username'], 'unique': True, 'sparse': True, }, ], "crits_type": 'User', "latest_schema_version": 3, "schema_doc": { 'username': '******', 'organization': 'The name of the organization this user is from', 'role': 'The role this user has been granted from a CRITs Admin', 'sources': ('List [] of source names this user has been granted' ' access to view data from'), 'subscriptions': { 'Campaign': [{ 'date': 'ISODate subscribed', 'id': 'ObjectId of the object subscribed to' }], 'Domain': [{ 'date': 'ISODate subscribed', 'id': 'ObjectId of the object subscribed to' }], 'Email': [{ 'date': 'ISODate subscribed', 'id': 'ObjectId of the object subscribed to' }], 'Target': [{ 'date': 'ISODate subscribed', 'id': 'ObjectId of the object subscribed to' }], 'Event': [{ 'date': 'ISODate subscribed', 'id': 'ObjectId of the object subscribed to' }], 'IP': [{ 'date': 'ISODate subscribed', 'id': 'ObjectId of the object subscribed to' }], 'Indicator': [{ 'date': 'ISODate subscribed', 'id': 'ObjectId of the object subscribed to' }], 'PCAP': [{ 'date': 'ISODate subscribed', 'id': 'ObjectId of the object subscribed to' }], 'Sample': [{ 'date': 'ISODate subscribed', 'id': 'ObjectId of the object subscribed to' }], 'Source': [{ 'date': 'ISODate subscribed', 'name': 'Name of the source subscribed to' }], }, 'favorites': { 'Actor': [], 'Backdoor': [], 'Campaign': [], 'Domain': [], 'Email': [], 'Target': [], 'Event': [], 'Exploit': [], 'IP': [], 'Indicator': [], 'PCAP': [], 'Sample': [], } }, } username = StringField( max_length=30, required=True, verbose_name='username', help_text= "Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters" ) first_name = StringField(max_length=30, verbose_name='first name') last_name = StringField(max_length=30, verbose_name='last name') email = EmailField(verbose_name='e-mail address') password = StringField( max_length=128, verbose_name='password', help_text= "Use '[algo]$[iterations]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>." ) secret = StringField(verbose_name='TOTP Secret') is_staff = BooleanField( default=False, verbose_name='staff status', help_text="Designates whether the user can log into this admin site.") is_active = BooleanField( default=True, verbose_name='active', help_text= "Designates whether this user should be treated as active. Unselect this instead of deleting accounts." ) is_superuser = BooleanField( default=False, verbose_name='superuser status', help_text= "Designates that this user has all permissions without explicitly assigning them." ) last_login = DateTimeField(default=datetime_now, verbose_name='last login') date_joined = DateTimeField(default=datetime_now, verbose_name='date joined') invalid_login_attempts = IntField(default=0) login_attempts = ListField(EmbeddedDocumentField(EmbeddedLoginAttempt)) organization = StringField(default=settings.COMPANY_NAME) password_reset = EmbeddedDocumentField(EmbeddedPasswordReset, default=EmbeddedPasswordReset()) role = StringField(default="Analyst") sources = ListField(StringField()) subscriptions = EmbeddedDocumentField(EmbeddedSubscriptions, default=EmbeddedSubscriptions()) favorites = EmbeddedDocumentField(EmbeddedFavorites, default=EmbeddedFavorites()) prefs = EmbeddedDocumentField(PreferencesField, default=PreferencesField()) totp = BooleanField(default=False) secret = StringField(default="") api_keys = ListField(EmbeddedDocumentField(EmbeddedAPIKey)) USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] defaultDashboard = ObjectIdField(required=False, default=None) def migrate(self): """ Migrate to latest schema version. """ migrate_user(self) def __setattr__(self, name, value): """ Overrides our core __setattr__ because we have to allow for extra authentication attributes that would normally get moved to unsupported_attrs. """ if (not self._dynamic and hasattr(self, 'unsupported_attrs') and not name in self._fields and not name.startswith('_') and not name.startswith('$') and not '.' in name and name not in ('backend')): if not self.unsupported_attrs: self.unsupported_attrs = UnsupportedAttrs() self.unsupported_attrs.__setattr__(name, value) else: super(CritsDocument, self).__setattr__(name, value) @property def pk(self): """ Return the ObjectId as the primary key. """ return self.id def __str__(self): """ This is so request.user returns the username like Django expects, not the whole object. """ if self.username: return self.username # the rest of this taken from the MongoEngine User class. def __unicode__(self): """ This is so request.user returns the username like Django expects, not the whole object. """ return self.username def get_full_name(self): """ Returns the users first and last names, separated by a space. """ full_name = u'%s %s' % (self.first_name or '', self.last_name or '') return full_name.strip() def is_anonymous(self): """ We do not allow anonymous users. """ return False def is_authenticated(self): """ If we know about the user from the request, it means they've authenticated. """ return True def mark_active(self, analyst=None): """ Mark the user as active. """ self.is_active = True self.save(username=analyst) return self def mark_inactive(self, analyst=None): """ Deactivate the user. """ self.is_active = False self.save(username=analyst) return self def is_password_complex(self, password): """ Based on the CRITsConfig, is the password provided complex enough to be used? :param password: The password to check for complexity. :type password: str :returns: True, False """ crits_config = CRITsConfig.objects().first() if crits_config: pw_regex = crits_config.password_complexity_regex else: pw_regex = settings.PASSWORD_COMPLEXITY_REGEX complex_regex = re.compile(pw_regex) if complex_regex.match(password): return True return False def set_password(self, raw_password, analyst=None): """ Sets the user's password - always use this rather than directly assigning to :attr:`~mongoengine.django.auth.User.password` as the password is hashed before storage. :param raw_password: The password to hash and store. :type raw_password: str :returns: self, False """ if self.is_password_complex(raw_password): self.password = make_password(raw_password) self.save(username=analyst) return self else: return False def set_reset_code(self, analyst): """ Sets a reset code on the account for password reset validation. :returns: str """ e = EmbeddedPasswordReset() char_set = string.ascii_uppercase + string.digits e.reset_code = ''.join(random.sample(char_set * 6, 6)) e.date = datetime.datetime.now() self.password_reset = e self.save(username=analyst) return e.reset_code def reset_password(self, rcode, new_p, new_p_c, analyst): """ Reset the user's password. Validate the reset code, ensure the two passwords are identical, and then set. :param rcode: Reset Code to validate. :type rcode: str :param new_p: New password. :type new_p: str :param new_p_c: New password confirmation. :type new_p_c: str :param analyst: The user. :type analyst: str :returns: dict with keys "success" (boolean) and "message" (str). """ if self.validate_reset_code(rcode, analyst)['success']: if new_p == new_p_c: self.password_reset.reset_code = "" if self.set_password(new_p): return {'success': True, 'message': 'Password reset.'} else: crits_config = CRITsConfig.objects().first() if crits_config: pw_desc = crits_config.password_complexity_desc else: pw_desc = settings.PASSWORD_COMPLEXITY_DESC message = 'Password not complex enough: %s' % pw_desc return {'success': False, 'message': message} else: return {'success': False, 'message': 'Passwords do not match.'} else: self.password_reset.reset_code = "" self.save(username=analyst) return {'success': False, 'message': 'Reset Code Expired.'} def validate_reset_code(self, reset_code, analyst): """ Validate the reset code. Also ensure that the reset code hasn't expired already since it is a limited-time use reset. :param reset_code: The reset code. :type reset_code: str :param analyst: The user. :type analyst: str :returns: dict with keys "success" (boolean) and "message" (str). """ my_reset = self.password_reset.reset_code if len(reset_code) == 6 and len( my_reset) == 6 and my_reset == reset_code: date = datetime.datetime.now() diff = date - self.password_reset.date window = divmod(diff.days * 86400 + diff.seconds, 60) if window[0] < 5: self.password_reset.attempts = 0 self.save(username=analyst) return {'success': True, 'message': 'Reset Code Validated.'} else: self.password_reset.attempts += 1 self.password_reset.reset_code = "" self.save(username=analyst) return {'success': False, 'message': 'Reset Code Expired.'} self.password_reset.attempts += 1 if self.password_reset.attempts > 2: self.password_reset.date = self.password_reset.date + datetime.timedelta( minutes=-5) self.save(username=analyst) return {'success': False, 'message': 'Reset Code Expired.'} self.save(username=analyst) return {'success': False, 'message': 'Reset Code Invalid.'} def check_password(self, raw_password): """ Checks the user's password against a provided password - always use this rather than directly comparing to :attr:`~mongoengine.django.auth.User.password` as the password is hashed before storage. """ return check_password(raw_password, self.password) def create_api_key(self, name, analyst, default=False): """ Generate an API key for the user. It will require a name as we allow for unlimited API keys and users need a way to reference them. :param name: The name for the API key. :type name: str :param analyst: The user. :type analyst: str :param default: Use as default API key. :type default: boolean :returns: dict with keys "success" (boolean) and "message" (str). """ if not name: return {'success': False, 'message': 'Need a name'} new_uuid = uuid.uuid4() key = hmac.new(new_uuid.bytes, digestmod=sha1).hexdigest() ea = EmbeddedAPIKey(name=name, api_key=key, default=default) if len(self.api_keys) < 1: ea.default = True self.api_keys.append(ea) self.save(username=analyst) return { 'success': True, 'message': { 'name': name, 'key': key, 'date': str(ea.date) } } def default_api_key(self, name, analyst): """ Make an API key the default key for a user. The default key is used for situations where the user is not or cannot be asked which API key to use. :param name: The name of the API key. :type name: str :param analyst: The user. :type analyst: str :returns: dict with keys "success" (boolean) and "message" (str). """ c = 0 for key in self.api_keys: if key.name == name: self.api_keys[c].default = True else: self.api_keys[c].default = False c += 1 self.save(username=analyst) return {'success': True} def revoke_api_key(self, name, analyst): """ Revoke an API key so it can no longer be used. :param name: The name of the API key. :type name: str :param analyst: The user. :type analyst: str :returns: dict with keys "success" (boolean) and "message" (str). """ keys = self.api_keys keyslen = len(keys) self.api_keys = [k for k in keys if k.name != name] if keyslen > len(self.api_keys): self.save(username=analyst) return {'success': True} else: return {'success': False, 'message': 'Key not found.'} def get_api_key(self, name): """ Get the API key. :param name: The name of the API key. :type name: str :returns: str, None """ for key in self.api_keys: if key.name == name: return key.api_key return None def validate_api_key(self, key): """ Validate that the API key exists for this user. :param key: The API key. :type key: str :returns: True, False """ for keys in self.api_keys: if keys.api_key == key: return True return False @classmethod def create_user(cls, username, password, email=None, analyst=None): """ Create (and save) a new user with the given username, password and email address. """ now = datetime_now() # Normalize the address by lowercasing the domain part of the email # address. if email is not None: try: email_name, domain_part = email.strip().split('@', 1) except ValueError: pass else: email = '@'.join([email_name, domain_part.lower()]) user = cls(username=username, email=email, date_joined=now) user.create_api_key("default", analyst, default=True) if password and user.set_password(password): user.save(username=analyst) return user elif CRITsConfig.remote_user: user.save(username="******") return user else: return None def get_group_permissions(self, obj=None): """ Returns a list of permission strings that this user has through his/her groups. This method queries all available auth backends. If an object is passed in, only permissions matching this object are returned. """ permissions = set() for backend in auth.get_backends(): if hasattr(backend, "get_group_permissions"): permissions.update(backend.get_group_permissions(self, obj)) return permissions def get_all_permissions(self, obj=None): return _user_get_all_permissions(self, obj) def has_perm(self, perm, obj=None): """ Returns True if the user has the specified permission. This method queries all available auth backends, but returns immediately if any backend returns True. Thus, a user who has permission from a single auth backend is assumed to have permission in general. If an object is provided, permissions for this specific object are checked. """ # Active superusers have all permissions. if self.is_active and self.is_superuser: return True # Otherwise we need to check the backends. return _user_has_perm(self, perm, obj) def has_module_perms(self, app_label): """ Returns True if the user has any permissions in the given app label. Uses pretty much the same logic as has_perm, above. """ # Active superusers have all permissions. if self.is_active and self.is_superuser: return True return _user_has_module_perms(self, app_label) def email_user(self, subject, message, from_email=None): """ Sends an e-mail to this User. """ from django.core.mail import send_mail if not from_email: crits_config = CRITsConfig.objects().first() if crits_config: from_email = crits_config.crits_email send_mail(subject, message, from_email, [self.email]) def get_username(self): return self.username ''' def get_profile(self): """ Returns site-specific profile for this user. Raises SiteProfileNotAvailable if this site does not allow profiles. """ if not hasattr(self, '_profile_cache'): from django.conf import settings if not getattr(settings, 'AUTH_PROFILE_MODULE', False): raise SiteProfileNotAvailable('You need to set AUTH_PROFILE_MO' 'DULE in your project settings') try: app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.') except ValueError: raise SiteProfileNotAvailable('app_label and model_name should' ' be separated by a dot in the AUTH_PROFILE_MODULE set' 'ting') try: model = models.get_model(app_label, model_name) if model is None: raise SiteProfileNotAvailable('Unable to load the profile ' 'model, check AUTH_PROFILE_MODULE in your project sett' 'ings') self._profile_cache = model._default_manager.using(self._state.db).get(user__id__exact=self.id) self._profile_cache.user = self except (ImportError, ImproperlyConfigured): raise SiteProfileNotAvailable return self._profile_cache ''' def get_preference(self, section, setting, default=None): """ Get a user preference setting out of the deep dynamic dictionary 'section' is the preferences 'section' e.g. 'ui' 'setting' is the dot separated preference setting e.g. 'foo.bar.enabled' :param section: A specific section of preferences you want. :type section: str :param setting: The setting you want to get. :type setting: str :returns: None, str, dict """ if not section in self.prefs: return default # Split the preference option into subtrees on '.' otree = setting.split(".") param = otree.pop() opt = self.prefs[section] if len(otree): for subsect in otree: if subsect in opt: opt = opt[subsect] else: return default if not param in opt: return default return opt[param] def update_from_ldap(self, analyst, config=None, passw=''): """ Set First Name, Last Name, and Email from LDAP if we can get the data. """ info = self.info_from_ldap(config, passw) if info['result'] == "OK": self.first_name = info['first_name'] self.last_name = info['last_name'] self.email = info['email'] self.save(username=analyst) def info_from_ldap(self, config=None, password=''): """ Get information about this user from LDAP. """ import ldap, ldapurl resp = {"result": "ERROR"} if not config: config = CRITsConfig.objects().first() # Make sure we have the rquired settings, else return failure if not config.ldap_server or not config.ldap_userdn: return resp ldap_server = config.ldap_server.split(':') scheme = "ldap" if config.ldap_tls: scheme = "ldaps" url = ldapurl.LDAPUrl('%s://%s' % (scheme, ldap_server[0])) if len(ldap_server) == 2: l = ldap.initialize('%s:%s' % (url.unparse(), ldap_server[1])) else: l = ldap.initialize(url.unparse()) l.protocol_version = 3 l.set_option(ldap.OPT_REFERRALS, 0) l.set_option(ldap.OPT_TIMEOUT, 10) # setup auth for custom cn's cn = "cn=" if config.ldap_usercn: cn = config.ldap_usercn # setup auth for custom cn's if len(config.ldap_usercn) > 0: un = "%s%s,%s" % (config.ldap_usercn, self.username, config.ldap_userdn) elif "@" in config.ldap_userdn: un = "%s%s" % (self.username, config.ldap_userdn) else: un = self.username try: # Try auth bind first l.simple_bind_s(un, password) logger.info("Bound to LDAP for: %s" % self.username) except Exception, e: logger.error("Error binding to LDAP for: %s" % self.username) logger.error("ERR: %s" % e) try: uatr = None uatr = l.search_s(config.ldap_userdn, ldap.SCOPE_SUBTREE, "(%s%s)" % (cn, self.username))[0][1] resp['first_name'] = uatr['givenName'][0] resp['last_name'] = uatr['sn'][0] resp['email'] = uatr['mail'][0] resp['result'] = "OK" logger.info("Retrieved LDAP info for: %s" % self.username) except Exception, e: logger.error("Error retrieving LDAP info for: %s" % self.username) logger.error("ERR: %s" % e)
class TestMe(Document): name = StringField(required=True) address = StringField(required=True) is_active = BooleanField(default=False)