def migrate_task_priority_choices_backward(apps, schema_editor): RevisionModelMixin.set_enabled(False) db_alias = schema_editor.connection.alias # Task = apps.get_model('shared_elements', 'Task') with DisableSignals(): # avoid permission/lock checks Task.objects.using(db_alias).filter( priority=Task.TASK_PRIORITY_VERY_HIGH).update( priority=OLD_TASK_PRIORITY_VERY_HIGH) Task.objects.using(db_alias).filter( priority=Task.TASK_PRIORITY_HIGH).update( priority=OLD_TASK_PRIORITY_HIGH) Task.objects.using(db_alias).filter( priority=Task.TASK_PRIORITY_NORMAL).update( priority=OLD_TASK_PRIORITY_NORMAL) Task.objects.using(db_alias).filter( priority=Task.TASK_PRIORITY_LOW).update( priority=OLD_TASK_PRIORITY_LOW) Task.objects.using(db_alias).filter( priority=Task.TASK_PRIORITY_VERY_LOW).update( priority=OLD_TASK_PRIORITY_VERY_LOW) RevisionModelMixin.set_enabled(True)
def preview(self, request, format=None, *args, **kwargs): version = self.get_object() # Creating a preview based on an actual model is not a trivial task. # Problem: # Django persists changes to relations immediately -> a preview would cause the actual data to change. # It is not possible to just use a temporary clone of the model, because for the ORM referencing to work, # the model has to be saved. Saving the clone is not entirely possible tho, because the clone has the same # references to and from other entities -> 1-1 and 1-* relations are violated. # Solution: # To avoid all the problems, we actually restore the version # and rollback all the changes after generating the output data. with transaction.atomic(): # create a savepoint, so that we can restore the original state after generating the preview data savepoint_id = transaction.savepoint() model = self.parent_object # disable all signals (e.g., permission checks, lock checks) for all models, so users with readonly-access # can always see the preview - they might not be able to actually restore it because of locks/permissions with DisableSignals(): model.restore_metadata(version.metadata) data = self.serialize_model(request, model, version) # the preview data has been generated, now rollback all changes transaction.savepoint_rollback(savepoint_id) return Response(data)
def remove_calendaraccess_and_full_access(apps, schema_editor): """ Remove all entity permission assignments :param apps: :param schema_editor: :return: """ RevisionModelMixin.set_enabled(False) db_alias = schema_editor.connection.alias CalendarAccess = apps.get_model('shared_elements', 'CalendarAccess') ContentType = apps.get_model('contenttypes', "ContentType") ModelPrivilege = apps.get_model('model_privileges', 'ModelPrivilege') # get content type calendaraccess_content_type = ContentType.objects.using(db_alias).get( app_label='shared_elements', model='calendaraccess') with DisableSignals(): # remove all CalendarAccess objects CalendarAccess.objects.using(db_alias).all().delete() # remove all ModelPrivilege objects where the content_type is that of the CalendarAccess ModelPrivilege.objects.using(db_alias).all().filter( content_type=calendaraccess_content_type, ).delete() RevisionModelMixin.set_enabled(True)
def handle(self, *args, **options): now = timezone.now() # get all files where title, name and original_filename start wit "~$", which are MS Office temp files unneeded_tmp_files = File.objects.all().filter( title__startswith=OFFICE_TEMP_FILE_PREFIX, name__startswith=OFFICE_TEMP_FILE_PREFIX, original_filename__startswith=OFFICE_TEMP_FILE_PREFIX, last_modified_at__lte=now - timedelta(seconds=60), deleted=False, imported=False, ) # get a list of Q queries with all extensions, that can later be used in filters. clauses = (Q(original_filename__endswith=extension) for extension in MS_OFFICE_EXTENSIONS) extension_query = reduce(operator.or_, clauses) # filter the file list, that only files with MS Office extensions remain unneeded_tmp_files = unneeded_tmp_files.filter(extension_query) # now loop over the files and sanity check that there exists a file without the temp file prefix as well # if the check is successful then the unneeded_tmp_file is trashed (deleted=True) for unneeded_tmp_file in unneeded_tmp_files: proper_file_exists = File.objects.filter( name=unneeded_tmp_file.name[2:], deleted=False, imported=False, ).exists() if proper_file_exists: logger.info( f"Command trash_unneeded_tmp_files: Trashing {unneeded_tmp_file.name}" ) # with disable_permission_checks(File): with DisableSignals(): try: unneeded_tmp_file.trash() except FileNotFoundError: unneeded_tmp_file.delete()
def migrate_study_room_data_backwards(apps, schema_editor): StudyRoom = apps.get_model("resources", "StudyRoom") # re-fill old resource fields from new StudyRoom data with DisableSignals(): # prevent locking for study_room in StudyRoom.objects.all(): resource = study_room.resource resource.study_room = True resource.branch_library = study_room.branch_library resource.save()
def migrate_resource_usage_settings_fields_backward(apps, schema_editor): RevisionModelMixin.set_enabled(False) db_alias = schema_editor.connection.alias # Resource = apps.get_model('shared_elements', 'Resource') with DisableSignals(): # avoid permission/lock checks Resource.objects.using(db_alias).filter( general_usage_setting=Resource.SELECTED_GROUPS).update( general_usage_setting=OLD_SELECTED_GROUPS) Resource.objects.using(db_alias).filter( general_usage_setting=Resource.GLOBAL).update( general_usage_setting=OLD_GLOBAL) RevisionModelMixin.set_enabled(True)
def create_calendaraccess_and_full_access(apps, schema_editor): RevisionModelMixin.set_enabled(False) db_alias = schema_editor.connection.alias ContentType = apps.get_model('contenttypes', "ContentType") User = apps.get_model('auth', 'User') CalendarAccess = apps.get_model('shared_elements', 'CalendarAccess') ModelPrivilege = apps.get_model('model_privileges', 'ModelPrivilege') # get content type calendaraccess_content_type = ContentType.objects.get_for_model( CalendarAccess) # iterate over all Users, create a CalendarAccess and give the user full_access # If the user never logged in we don't do anything here. # There is still a handler that does the same on authentication for "new" users. with DisableSignals(): # avoid permission/lock checks for user in User.objects.using(db_alias).filter( last_login__isnull=False): # check if a CalendarAccess already exists for this user privilege_exists = CalendarAccess.objects.using( db_alias).all().filter(created_by=user, ) if not privilege_exists: new_privilege = CalendarAccess.objects.using(db_alias).create() # set created_by and last_modified_by to the user, so the CalendarAccess is his/hers new_privilege.created_by = user new_privilege.last_modified_by = user new_privilege.save() # now give the user full_access to his calendar perm = ModelPrivilege(user=user, full_access_privilege="AL", content_type=calendaraccess_content_type, object_id=new_privilege.pk) perm.save() RevisionModelMixin.set_enabled(True)
def clean_workbench_models(request, *args, **kwargs): """ Purges data from all workbench models. """ if not hasattr(settings, 'CLEAN_ALL_WORKBENCH_MODELS' ) or not settings.CLEAN_ALL_WORKBENCH_MODELS: return Response({'error': 'Operation is not enabled in settings.'}, status=status.HTTP_404_NOT_FOUND) if not request.user.is_authenticated: return Response({'error': 'You need to be logged in.'}, status=status.HTTP_401_UNAUTHORIZED) all_workbench_models = get_all_workbench_models(WorkbenchEntityMixin) # disable all model-receivers (e.g. check_model_privileges, which may block the deletion) with DisableSignals(): for model in all_workbench_models: model.objects.all().delete() for record in Project.objects.all(): record.trash() Version.objects.all().delete() Metadata.objects.all().delete() return Response({'status': 'ok'}, status=200)