def test_prevent_rollback(self):
        with transaction.atomic():
            Reporter.objects.create(first_name="Tintin")
            sid = transaction.savepoint()
            # trigger a database error inside an inner atomic without savepoint
            with self.assertRaises(DatabaseError):
                with transaction.atomic(savepoint=False):
                    connection.cursor().execute(
                        "SELECT no_such_col FROM transactions_reporter"
                    )
            # prevent atomic from rolling back since we're recovering manually
            self.assertTrue(transaction.get_rollback())
            transaction.set_rollback(False)
            transaction.savepoint_rollback(sid)
        self.assertQuerysetEqual(Reporter.objects.all(),
                                 ['<Reporter: Tintin>'])
        self.assertAtomicSignalCalls(
            # Enter atomic transaction block.
            enter_block_atomic_signal_call_sequence(True) +

            # Create Reporter.
            create_model_atomic_signal_call_sequence() +

            # Enter and leave atomic transaction block.
            enter_block_atomic_signal_call_sequence(False, savepoint=False) +
            leave_block_atomic_signal_call_sequence(False, False,
                                                    savepoint=False) +

            # Leave atomic transaction with recovered rollback.
            leave_block_atomic_signal_call_sequence(True, True)
        )
Beispiel #2
0
 def test_force_rollback(self):
     with transaction.atomic():
         Reporter.objects.create(first_name="Tintin")
         # atomic block shouldn't rollback, but force it.
         self.assertFalse(transaction.get_rollback())
         transaction.set_rollback(True)
     self.assertQuerysetEqual(Reporter.objects.all(), [])
Beispiel #3
0
 def test_ticket_11101(self):
     """Test that fixtures can be rolled back (ticket #11101)."""
     with transaction.atomic():
         management.call_command("loaddata", "thingy.json", verbosity=0)
         self.assertEqual(Thingy.objects.count(), 1)
         transaction.set_rollback(True)
     self.assertEqual(Thingy.objects.count(), 0)
Beispiel #4
0
 def one(output):
     with transaction.atomic():
         output.append(('one', 'begin'))
         value = get_next_value()
         output.append(('one', value))
         time.sleep(0.2)
         transaction.set_rollback(True)
         output.append(('one', 'rollback'))
     connection.close()
    def handle_exception(self, *args, **kwargs):
        """Handle exception with transaction rollback."""
        response = super(AtomicMixin, self).handle_exception(*args, **kwargs)

        if getattr(response, 'exception'):
            # We've suppressed the exception but still need to rollback any transaction.
            transaction.set_rollback(True)

        return response
Beispiel #6
0
        def wrapped_func(*args, **kwargs):

            with atomic(using=using):
                res = func(*args, **kwargs)

                if not isinstance(res, HttpResponse) or res.status_code < 200 or res.status_code >= 400:
                    set_rollback(True, using=using)

            return res
Beispiel #7
0
 def test_atomic_allows_queries_after_fixing_transaction(self):
     r1 = Reporter.objects.create(first_name="Archibald", last_name="Haddock")
     with transaction.atomic():
         r2 = Reporter(first_name="Cuthbert", last_name="Calculus", id=r1.id)
         with self.assertRaises(IntegrityError):
             r2.save(force_insert=True)
         # Mark the transaction as no longer needing rollback.
         transaction.set_rollback(False)
         r2.save(force_update=True)
     self.assertEqual(Reporter.objects.get(pk=r1.pk).last_name, "Calculus")
Beispiel #8
0
 def test_prevent_rollback(self):
     with transaction.atomic():
         Reporter.objects.create(first_name="Tintin")
         sid = transaction.savepoint()
         # trigger a database error inside an inner atomic without savepoint
         with self.assertRaises(DatabaseError), transaction.atomic(savepoint=False):
             connection.cursor().execute(
                     "SELECT no_such_col FROM transactions_reporter")
         transaction.savepoint_rollback(sid)
         # atomic block should rollback, but prevent it, as we just did it.
         self.assertTrue(transaction.get_rollback())
         transaction.set_rollback(False)
     self.assertQuerysetEqual(Reporter.objects.all(), ['<Reporter: Tintin>'])
Beispiel #9
0
 def run():
     try:
         with transaction.atomic():
             for f in active_fixtures():
                 assert f is not self
                 if f.template == template:
                     return False
                 f()
             result = self.constraint(self.strategy.reify(template))
             transaction.set_rollback(True)
         return result
     except UnsatisfiedAssumption:
         return False
Beispiel #10
0
 def test_prevent_rollback(self):
     with transaction.atomic():
         Reporter.objects.create(first_name="Tintin")
         sid = transaction.savepoint()
         # trigger a database error inside an inner atomic without savepoint
         with self.assertRaises(DatabaseError):
             with transaction.atomic(savepoint=False):
                 connection.cursor().execute("SELECT no_such_col FROM transactions_reporter")
         # prevent atomic from rolling back since we're recovering manually
         self.assertTrue(transaction.get_rollback())
         transaction.set_rollback(False)
         transaction.savepoint_rollback(sid)
     self.assertQuerysetEqual(Reporter.objects.all(), ["<Reporter: Tintin>"])
Beispiel #11
0
 def get_ticket(self):
     try:
         return self._internal_get_ticket()
     except exceptions:
         connection = connections[self.db]
         # If the transaction is in an `atomic` block, and needs a rollback,
         # we should mark the database as rolled back. This is because the
         # database backend may not prevent running SQL queries in broken
         # transactions, in which case we need to say that we have handled
         # the rollback so we can try one more time.
         if (connection.in_atomic_block
                 and transaction.get_rollback(using=self.db)):
             transaction.set_rollback(False, using=self.db)
         return self._internal_get_ticket()
def set_rollback():
    if hasattr(transaction, 'set_rollback'):
        if connection.settings_dict.get('ATOMIC_REQUESTS', False):
            # If running in >=1.6 then mark a rollback as required,
            # and allow it to be handled by Django.
            transaction.set_rollback(True)
    elif transaction.is_managed():
        # Otherwise handle it explicitly if in managed mode.
        if transaction.is_dirty():
            transaction.rollback()
        transaction.leave_transaction_management()
    else:
        # transaction not managed
        pass
    def process_view(self, request, view_func, view_args, view_kwargs):
        user = None
        if request.user.is_authenticated():
            user = request.user

        if request.method == "GET":
            logger.debug("Start query request on the view %s." % view_func.__name__)
            # NOTE: We do not need create a changeset when we just SELECT somw records.
            response = view_func(request, *view_args, **view_kwargs)
        else:
            # trap the request and give response when the method is not defined in HTTP/1.1
            if request.method not in ["HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT", "PATCH", "OPTIONS"]:
                logger.error('Wrong method %s specified when calling %s', request.method.decode("utf-8"), request.path,
                             exc_info=sys.exc_info())
                response_data = json.dumps({"detail": 'Method "{method}" not allowed.'.format(method=request.method)},
                                           ensure_ascii=False)
                response = HttpResponse(response_data, content_type='application/json')
                response.status_code = status.HTTP_405_METHOD_NOT_ALLOWED
                return response

            logger.debug("Start write request on the view %s." % view_func.__name__)
            try:
                with transaction.atomic():
                    comment = request.META.get("HTTP_PDC_CHANGE_COMMENT", None)
                    request.changeset = models.Changeset(author=user, comment=comment)
                    request.changeset.requested_on = datetime.now()
                    response = view_func(request, *view_args, **view_kwargs)
                    # response.exception=True means there is an error occurs.
                    if getattr(response, 'exception', 0) or (
                        hasattr(response, 'status_code') and response.status_code >= 400
                    ):
                        # avoid recording changeset on server error, also
                        # abort the transaction so that no modifications are
                        # done to database
                        request.changeset.reset()
                        transaction.set_rollback(True)
                    else:
                        request.changeset.commit()
                        self._may_announce_big_change(request.changeset, request)
            except:
                # NOTE: catch all errors that were raised by view.
                # And log the trace back to the file.
                logger.error('View Function Error: %s', request.path,
                             exc_info=sys.exc_info())
                # we do not want to break the default exception processing chains,
                # so re-raise the exception to the upper level.
                raise

        return response
Beispiel #14
0
 def test_check_constraints(self):
     """
     Constraint checks should raise an IntegrityError when bad data is in the DB.
     """
     with transaction.atomic():
         # Create an Article.
         models.Article.objects.create(headline="Test article", pub_date=datetime.datetime(2010, 9, 4), reporter=self.r)
         # Retrieve it from the DB
         a = models.Article.objects.get(headline="Test article")
         a.reporter_id = 30
         with connection.constraint_checks_disabled():
             a.save()
             with self.assertRaises(IntegrityError):
                 connection.check_constraints()
         transaction.set_rollback(True)
def _update_stock(request, change_type):
    products = Product.objects.all().filter(discontinued=False).order_by('name')
    if request.method == 'GET':
        users = User.objects.all().filter(is_active=True).order_by('username')
        context = {'sellables': products.filter(category=0), #FIXME: Magic numbers
                   'refundables': products.filter(category=1),
                   'names': users}
        return render(request, change_type + ".html", context)
    elif request.method == 'POST':
        if len(request.POST.getlist("who")) == 0:
            return HttpResponse("From validation error: no users selected")

        with transaction.atomic():
            updated = []
            for p in products:
                req_qty = int(request.POST[str(p.pk) + "_qty"])
                changed = req_qty != p.quantity
                updated.append((p, req_qty, changed))
                # TODO: Tell the user whats wrong in a nicer way
                if not (req_qty >= 0 and
                        qty_verify_funs[change_type][p.category](req_qty, p.quantity)):
                    transaction.set_rollback(True)
                    return HttpResponse("Form validation error: Invalid product quantity");

            if any(map(lambda t: t[2], updated)):
                # TODO: Do something better with EventType handling
                event = Event(description = request.POST['what'],
                              event_type = EventType.objects.get(tag = change_type),
                              logged_user = request.user)
                event.save()
                for u in request.POST.getlist("who"):
                    event.eventbyuser_set.add(EventByUser(
                        name = User.objects.get(pk = u)),
                                            bulk=False)

                for p, req_qty, changed in updated:
                    event.change_set.add(Change(product = p,
                                                quantity = req_qty,
                                                delta = req_qty - p.quantity),
                                         bulk=False)
                    if changed:
                        p.quantity = req_qty
                        p.save()

                return HttpResponseRedirect("/"+ change_type)
            else:
                transaction.set_rollback(True)
                return HttpResponse("Form validation error: No quantities changed")
Beispiel #16
0
 def test_disable_constraint_checks_context_manager(self):
     """
     When constraint checks are disabled (using context manager), should be able to write bad data without IntegrityErrors.
     """
     with transaction.atomic():
         # Create an Article.
         models.Article.objects.create(headline="Test article", pub_date=datetime.datetime(2010, 9, 4), reporter=self.r)
         # Retrieve it from the DB
         a = models.Article.objects.get(headline="Test article")
         a.reporter_id = 30
         try:
             with connection.constraint_checks_disabled():
                 a.save()
         except IntegrityError:
             self.fail("IntegrityError should not have occurred.")
         transaction.set_rollback(True)
    def test_force_rollback(self):
        with transaction.atomic():
            Reporter.objects.create(first_name="Tintin")
            # atomic block shouldn't rollback, but force it.
            self.assertFalse(transaction.get_rollback())
            transaction.set_rollback(True)
        self.assertQuerysetEqual(Reporter.objects.all(), [])
        self.assertAtomicSignalCalls(
            # Enter atomic transaction block.
            enter_block_atomic_signal_call_sequence(True) +

            # Create Reporter.
            create_model_atomic_signal_call_sequence() +

            # Leave atomic transaction with forced rollback.
            leave_block_atomic_signal_call_sequence(True, False)
        )
Beispiel #18
0
            def _side_effect(*args):
                """
                We want to raise an IntegrityError only on the first call
                of our mock
                """

                def __second_side_effect(*args):
                    return None

                # change the side effect so that the next time we do not
                # raise an IntegrityError
                mock.side_effect = __second_side_effect
                # we need to manually rollback the atomic transaction
                # merely raising IntegrityError is not enough
                # doing this means that a TransactionManagementError is raised
                # if we do new queries inside the transaction.atomic block
                transaction.set_rollback(True)
                raise IntegrityError
Beispiel #19
0
def custom_exception_handler(exc):
    # If you raise an error in solitude, it comes to here and
    # we rollback the transaction.
    set_rollback(True)

    if hasattr(exc, 'formatter'):
        try:
            return Response(exc.formatter(exc).format(),
                            status=getattr(exc, 'status_code', 422))
        except:
            # If the formatter fails, fall back to the standard
            # error formatting.
            log.exception('Failed to use formatter.')

    if isinstance(exc, BangoImmediateError):
        return Response(exc.message, status=400)

    return exception_handler(exc)
Beispiel #20
0
 def test_merged_inner_savepoint_rollback(self):
     with transaction.atomic():
         Reporter.objects.create(first_name="Tintin")
         with transaction.atomic():
             Reporter.objects.create(first_name="Archibald", last_name="Haddock")
             with six.assertRaisesRegex(self, Exception, "Oops"):
                 with transaction.atomic(savepoint=False):
                     Reporter.objects.create(first_name="Calculus")
                     raise Exception("Oops, that's his last name")
             # The third insert couldn't be roll back. Temporarily mark the
             # connection as not needing rollback to check it.
             self.assertTrue(transaction.get_rollback())
             transaction.set_rollback(False)
             self.assertEqual(Reporter.objects.count(), 3)
             transaction.set_rollback(True)
         # The second block has a savepoint and must roll back.
         self.assertEqual(Reporter.objects.count(), 1)
     self.assertQuerysetEqual(Reporter.objects.all(), ['<Reporter: Tintin>'])
Beispiel #21
0
 def test_disable_constraint_checks_manually(self):
     """
     When constraint checks are disabled, should be able to write bad data
     without IntegrityErrors.
     """
     with transaction.atomic():
         # Create an Article.
         Article.objects.create(
             headline="Test article",
             pub_date=datetime.datetime(2010, 9, 4),
             reporter=self.r,
         )
         # Retrieve it from the DB
         a = Article.objects.get(headline="Test article")
         a.reporter_id = 30
         try:
             connection.disable_constraint_checking()
             a.save()
             connection.enable_constraint_checking()
         except IntegrityError:
             self.fail("IntegrityError should not have occurred.")
         transaction.set_rollback(True)
Beispiel #22
0
def _ctit_db_wrapper(trans_safe=False):
    '''
    Wrapper to avoid undesired actions by Django ORM when managing settings
    if only getting a setting, can use trans_safe=True, which will avoid
    throwing errors if the prior context was a broken transaction.
    Any database errors will be logged, but exception will be suppressed.
    '''
    rollback_set = None
    is_atomic = None
    try:
        if trans_safe:
            is_atomic = connection.in_atomic_block
            if is_atomic:
                rollback_set = transaction.get_rollback()
                if rollback_set:
                    logger.debug(
                        'Obtaining database settings in spite of broken transaction.'
                    )
                    transaction.set_rollback(False)
        yield
    except DBError as exc:
        if trans_safe:
            if 'migrate' not in sys.argv and 'check_migrations' not in sys.argv:
                level = logger.exception
                if isinstance(exc, ProgrammingError):
                    if 'relation' in str(exc) and 'does not exist' in str(exc):
                        # this generally means we can't fetch Tower configuration
                        # because the database hasn't actually finished migrating yet;
                        # this is usually a sign that a service in a container (such as ws_broadcast)
                        # has come up *before* the database has finished migrating, and
                        # especially that the conf.settings table doesn't exist yet
                        level = logger.debug
                level('Database settings are not available, using defaults.')
        else:
            logger.exception(
                'Error modifying something related to database settings.')
    finally:
        if trans_safe and is_atomic and rollback_set:
            transaction.set_rollback(rollback_set)
Beispiel #23
0
def store_export_chunk_as_blob(data_export, bytes_written, fileobj, blob_size=DEFAULT_BLOB_SIZE):
    # adapted from `putfile` in  `src/sentry/models/file.py`
    bytes_offset = 0
    while True:
        contents = fileobj.read(blob_size)
        if not contents:
            return bytes_offset

        blob_fileobj = ContentFile(contents)
        blob = FileBlob.from_file(blob_fileobj, logger=logger)
        ExportedDataBlob.objects.create(
            data_export=data_export, blob=blob, offset=bytes_written + bytes_offset
        )

        bytes_offset += blob.size

        # there is a maximum file size allowed, so we need to make sure we don't exceed it
        # NOTE: there seems to be issues with downloading files larger than 1 GB on slower
        # networks, limit the export to 1 GB for now to improve reliability
        if bytes_written + bytes_offset >= min(MAX_FILE_SIZE, 2 ** 30):
            transaction.set_rollback(True)
            return 0
Beispiel #24
0
    def handle(self, *args, **options):

        loglevel = options.get('loglevel')
        try:
            loglevel = int(loglevel)
        except ValueError as e:
            self.stderr.write(self.style.ERROR(
                f"Unable to parse loglevel='{loglevel}' to an integer.  Only numerical values accepted."))
            sys.exit(1)

        logging.disable(loglevel)

        order_no: int = options.get('order_no')[0]
        year: int = options.get('year')[0]
        commit: bool = options.get('commit', False)

        if year < 1000:
            year += 2000

        if not commit:
            self.stderr.write(self.style.WARNING("DRY RUN: No processed data will be committed."))
            self.stderr.write(self.style.WARNING("\tTo commit, pass `-c` or `--commit` flag.\n"))

        # Validate that all passed DBFs exist

        self.stdout.write("Creating transaction savepoint.")
        sp = transaction.savepoint()
        self.stdout.write(self.style.HTTP_INFO(f"Beginning EoW analysis of Year: {year}, Order: {order_no}"))
        with transaction.atomic():
            from HotBlock.analysis import hotblock_end_of_order_analysis
            hotblock_end_of_order_analysis(year, order_no, True)

            if not commit:
                self.stdout.write(self.style.WARNING("Rolling back database to generated savepoint."))
                transaction.set_rollback(True)
                self.stdout.write(self.style.SUCCESS("Database rolled back."))

        self.stdout.write(
            self.style.SUCCESS(f"Hotblock End of Week Analysis for Order `{order_no}` complete."))
Beispiel #25
0
def login(request):
	import json as j
	requestData =  j.loads(request.body.decode('utf-8'))
	user = helpers.auth_user(requestData['username'], requestData['password'])
	# if user is None:
		# return json.Response('User name or Password Wrong', False)
	if user['status']:
		return json.Response(user['error_msg'], False)
	if user['user']:
		# generate token for authenticated user
		auth_token = helpers.auth_token(user['user'], request)
		if auth_token:
			auth_token['expiry'] = int(time.time())+36000			
			user_id=User.objects.get(username=requestData['username'])
			auth_token['username'] = requestData['username']
			StoreAuthtokenTbl = AuthTokenMstr(
				user_id=user_id,
				jwt_token=auth_token['token'],
				expire_ts=int(time.time())+36000,
				created_on=int(time.time())
			)
			StoreAuthtokenTbl.save()

			user_login_history = UserLoginHistory(
			user_id=user_id,
			jwt_token=auth_token['token'],
			login_time=int(time.time()),
			expire_ts=int(time.time())+36000,
			# ip=socket.gethostbyname(socket.gethostname()),
			created_on=int(time.time())
			)
			user_login_history.save()
			return json.Response(auth_token)
		else:
			transaction.set_rollback(True)
			return json.Response('Check Headers', False)
	else:
		return json.Response('User name or Password Wrong', False)
	return json.Response('')
Beispiel #26
0
def store_export_chunk_as_blob(data_export,
                               bytes_written,
                               fileobj,
                               blob_size=DEFAULT_BLOB_SIZE):
    # adapted from `putfile` in  `src/sentry/models/file.py`
    bytes_offset = 0
    while True:
        contents = fileobj.read(blob_size)
        if not contents:
            return bytes_offset

        blob_fileobj = ContentFile(contents)
        blob = FileBlob.from_file(blob_fileobj, logger=logger)
        ExportedDataBlob.objects.create(data_export=data_export,
                                        blob=blob,
                                        offset=bytes_written + bytes_offset)

        bytes_offset += blob.size

        # there is a maximum file size allowed, so we need to make sure we don't exceed it
        if bytes_written + bytes_offset >= MAX_FILE_SIZE:
            transaction.set_rollback(True)
            return 0
    def main(self, batch_size=None, sleep=0):
        """Invoked from the management command to do all the work."""

        batch_size = batch_size or self.BATCH_SIZE

        self.last_student_module_id = self.get_last_student_module_id()
        self.load_state()

        while self.next_student_module_id <= self.last_student_module_id:
            with transaction.atomic():
                for smid in self.module_ids_to_check(batch_size):
                    try:
                        self.clean_one_student_module(smid)
                    except Exception:       # pylint: disable=broad-except
                        trace = traceback.format_exc()
                        self.say("Couldn't clean student_module_id {}:\n{}".format(smid, trace))
                if self.dry_run:
                    transaction.set_rollback(True)
                else:
                    self.say("Committing")
            self.save_state()
            if sleep:
                time.sleep(sleep)
Beispiel #28
0
 def test_check_constraints(self):
     """
     Constraint checks should raise an IntegrityError when bad data is in the DB.
     """
     with transaction.atomic():
         # Create an Article.
         Article.objects.create(
             headline="Test article",
             pub_date=datetime.datetime(2010, 9, 4),
             reporter=self.r,
         )
         # Retrieve it from the DB
         a = Article.objects.get(headline="Test article")
         a.reporter_id = 30
         with connection.constraint_checks_disabled():
             a.save()
             try:
                 connection.check_constraints(table_names=[Article._meta.db_table])
             except IntegrityError:
                 pass
             else:
                 self.skipTest("This backend does not support integrity checks.")
         transaction.set_rollback(True)
Beispiel #29
0
    def handle(self, db_path, *args, **options):
        # make the db easily accesible to all other methods
        self.db = dataset.connect("sqlite:///" + db_path)

        if not options["skip_chronicles"]:
            self.add_chronicles()

        # choose a single chronicle or iterate over all chronicles

        if not options["all"]:
            all_c = Chronicle.objects.all().values_list("name", flat=True)
            input_tex = (
                "Please choose a chronicle:\n0: all\n" +
                "\n".join([f"{i+1}: {x}" for i, x in enumerate(all_c)]) + "\n")
            chosen_c_input = input(input_tex)

        if options["all"] or chosen_c_input == "0":
            for c in Chronicle.objects.all():
                self.add_incidents_for_chronicle(c, not options["force"])
        else:
            chosen_c = Chronicle.objects.get(name=all_c[int(chosen_c_input) -
                                                        1])
            self.add_incidents_for_chronicle(chosen_c, not options["force"])

        if options["dry_run"]:
            # Return, rolling back transaction when atomic block exits
            transaction.set_rollback(True)
            return

        self.stdout.write("syncing text vector fields...")
        Incident.objects.sync()
        Location.objects.sync()

        self.stdout.write("syncing autocomplete phrases...")
        generate_phrases()

        self.stdout.write(self.style.SUCCESS("Successfully imported data"))
Beispiel #30
0
    def handle(self, *args, **options):
        outstanding_projects = Project.objects.filter(state__name__in=[
            ProjectState.PendingApproval,
            ProjectState.Approved,
            ProjectState.Extended,
            ProjectState.PassedDeadline,
        ])

        for project in outstanding_projects:
            try:
                with transaction.atomic():
                    updated = self.update_state(
                        project, send_updates=options['send_updates'])
                    if not options['update_db']:
                        transaction.set_rollback(True)

            except Exception as e:
                for l in traceback.format_exc().splitlines():
                    self.stderr.write(self.style.ERROR(l))

                self.stderr.write(
                    self.style.ERROR('Error updating %s' % project))

        self.stdout.write(self.style.SUCCESS('Processing complete'))
    def process_view(self, request, view_func, view_args, view_kwargs):
        user = None
        if request.user.is_authenticated():
            user = request.user

        if request.method == "GET":
            logger.debug("Start query request on the view %s." % view_func.__name__)
            # NOTE: We do not need create a changeset when we just SELECT somw records.
            response = view_func(request, *view_args, **view_kwargs)
        else:
            logger.debug("Start write request on the view %s." % view_func.__name__)
            try:
                with transaction.atomic():
                    request.changeset = models.Changeset(author=user)
                    response = view_func(request, *view_args, **view_kwargs)
                    # response.exception=True means there is an error occurs.
                    if getattr(response, 'exception', 0) or (
                        hasattr(response, 'status_code') and response.status_code >= 400
                    ):
                        # avoid recording changeset on server error, also
                        # abort the transaction so that no modifications are
                        # done to database
                        request.changeset.reset()
                        transaction.set_rollback(True)
                    else:
                        request.changeset.commit()
            except:
                # NOTE: catch all errors that were raised by view.
                # And log the trace back to the file.
                logger.error('View Function Error: %s', request.path,
                             exc_info=sys.exc_info())
                # we do not want to break the default exception processing chains,
                # so re-raise the exception to the upper level.
                raise

        return response
Beispiel #32
0
    def enable(self):
        """
        Mark this CloudAccount as enabled and perform operations to make it so.

        This has the side effect of calling the related content_object (e.g.
        AwsCloudAccount) to make any cloud-specific changes. If any that cloud-specific
        function fails, we rollback our state change and re-raise the exception for the
        caller to handle further.
        """
        logger.info(
            _("'is_enabled' is %(is_enabled)s before enabling %(cloudaccount)s"
              ),
            {
                "is_enabled": self.is_enabled,
                "cloudaccount": self
            },
        )
        if not self.is_enabled:
            self.is_enabled = True
            self.enabled_at = get_now()
            self.save()
        try:
            self.content_object.enable()
            # delete stale ConcurrentUsage when an clount is enabled
            ConcurrentUsage.objects.filter(user=self.user,
                                           date=get_today()).delete()
        except Exception as e:
            # All failure notifications should happen during the failure
            logger.info(e)
            transaction.set_rollback(True)
            return False

        from api.tasks import notify_application_availability_task

        notify_application_availability_task.delay(
            self.user.username, self.platform_application_id, "available")
    def handle(self, *args, **options):
        outstanding_projects = Project.objects.filter(state__name__in=[
            ProjectState.PendingApproval,
            ProjectState.Approved,
            ProjectState.Extended,
            ProjectState.PassedDeadline,
        ])

        self.stdout.write('Starting updates at %s' % timezone.now().strftime('%Y-%m-%d %H:%M:%S'))

        for project in outstanding_projects:
            try:
                with transaction.atomic():
                    updated = self.update_state(project, send_updates=options['send_updates'])
                    if not options['update_db']:
                        transaction.set_rollback(True)

            except Exception as e:
                for l in traceback.format_exc().splitlines():
                    self.stderr.write(self.style.ERROR(l))

                self.stderr.write(self.style.ERROR('Error updating %s' % project))

        self.stdout.write(self.style.SUCCESS('Processing complete'))
Beispiel #34
0
def delete_comment(request):
    # Based on variables passed in we get the comment the user is attempting to create/edit
    try:
        comment, previous_version = _get_target_comment(request)
    except InvalidCommentException as e:
        transaction.set_rollback(True)
        return JsonResponse({
            'ok': False,
            'error_message': str(e),
        })

    # Check if the user doesn't pass the appropriate permission check (on the parent_object)...
    # We call this on the parent comment because the comment itself may not have been saved yet (can't call .get_root on it)
    # TODO: Fix this for root comment? (no parent)
    parent_comment = comment.parent
    tree_root = parent_comment.get_root()
    parent_object = tree_root.content_object
    if not user_has_permission(
            request, parent_object, 'can_delete_comment', comment=comment):
        transaction.set_rollback(True)
        return JsonResponse({
            'ok':
            False,
            'error_message':
            "You do not have permission to post this comment.",
        })

    try:
        # The 'X_KWARGS' header is populated by settings.kwarg in comments.js
        kwargs = json.loads(request.META.get('HTTP_X_KWARGS', {}))
        comment_changed.send(sender=comment.__class__,
                             comment=comment,
                             request=request,
                             version_saved=None,
                             comment_action='pre_delete',
                             kwargs=kwargs)

        comment.deleted = True
        comment.save()
        for child in comment.get_children():
            child.deleted = True
            child.save()

        return JsonResponse({
            'ok': True,
        })
    except Exception as e:
        # TODO: Handle this more eloquently? Log? Probably best not to pass back raw error.
        transaction.set_rollback(True)
        return JsonResponse({
            'ok':
            False,
            'error_message':
            'There was an error deleting the selected comment(s).',
        })
Beispiel #35
0
def importHistoricalDataForStock(ticker=str):

    #if  not ticker.startswith('600'):
    #    return

    stock = Stock.objects.get(ticker=ticker)
    # Skip stocks that already loaded

    # Data source from yahoo will append record for each day even if the stock is suspended.
    # Thus, if there's any day record of the stock, there're all of them from the beginning to the latest(atomic transaction)
    if stock.dayHist.count() > 0:
        #print('{} - skip {}({}) : already loaded'.format(threading.get_ident(),stock.name,stock.ticker))
        return
    else:
        # add corresponding suffix according to the market(ss for Shanghai while sz for Shenzhen
        url = 'http://table.finance.yahoo.com/table.csv?s=' + ticker + (
            ticker.startswith('60') and '.ss' or '.sz')
        print('{} - import day quote data for {}({}) from source: {}'.format(
            threading.get_ident(), stock.name, stock.ticker, url))
        try:

            response = urllib.request.urlopen(url, timeout=30)
            reader = csv.reader(codecs.iterdecode(response, 'utf-8'))

            #skip first header row
            next(reader)
            print('start to record {}'.format(ticker))
            # save day quote data to db
            for row in reader:
                obj = DayData(stock=stock,
                              date=row[0],
                              open=row[1],
                              high=row[2],
                              low=row[3],
                              close=row[4],
                              volume=row[5],
                              adj_close=row[6])
                obj.save()
            print('{} done'.format(ticker))
            time.sleep(1)
        except (HTTPError, URLError) as error:
            print('{} - "HTTP or URL Error! - {}({})'.format(
                threading.get_ident(), stock.name, stock.ticker))
            transaction.set_rollback(True)
        except timeout:
            print('{} - "Timeout - {}({})'.format(threading.get_ident(),
                                                  stock.name, stock.ticker))
            transaction.set_rollback(True)
        except:
            print('{} - "Unknown error - {}({}) - {}'.format(
                threading.get_ident(), stock.name, stock.ticker,
                sys.exc_info()[0]))
            transaction.set_rollback(True)
Beispiel #36
0
 def test_merged_outer_rollback(self):
     with transaction.atomic():
         Reporter.objects.create(first_name="Tintin")
         with transaction.atomic(savepoint=False):
             Reporter.objects.create(first_name="Archibald", last_name="Haddock")
             with six.assertRaisesRegex(self, Exception, "Oops"):
                 with transaction.atomic(savepoint=False):
                     Reporter.objects.create(first_name="Calculus")
                     raise Exception("Oops, that's his last name")
             # The third insert couldn't be roll back. Temporarily mark the
             # connection as not needing rollback to check it.
             self.assertTrue(transaction.get_rollback())
             transaction.set_rollback(False)
             self.assertEqual(Reporter.objects.count(), 3)
             transaction.set_rollback(True)
         # The second insert couldn't be roll back. Temporarily mark the
         # connection as not needing rollback to check it.
         self.assertTrue(transaction.get_rollback())
         transaction.set_rollback(False)
         self.assertEqual(Reporter.objects.count(), 3)
         transaction.set_rollback(True)
     # The first block has a savepoint and must roll back.
     self.assertQuerysetEqual(Reporter.objects.all(), [])
Beispiel #37
0
    def retrieve(self, request, *args, **kwargs):
        """执行retrieve操作

        Args:
            request(Request): DRF Request
            *args(list): 可变参数
            **kwargs(dict): 可变关键字参数

        Returns:
            response(Response): 对请求的响应
        """
        # 查询预处理
        error, reason = self._pre_process_retrieve(request, *args, **kwargs)
        if error:
            transaction.set_rollback(True)
            return self.set_response(error,
                                     reason,
                                     status=drf_status.HTTP_400_BAD_REQUEST)

        # 获取model instance
        instance = self.get_object(*args, **kwargs)

        # 查询
        error, reason, response = self._perform_retrieve(
            request, instance, *args, **kwargs)
        if error:
            transaction.set_rollback(True)
            return self.set_response(error,
                                     reason,
                                     status=drf_status.HTTP_400_BAD_REQUEST)

        # 查询后处理
        error, reason = self._post_process_retrieve(request, instance, *args,
                                                    **kwargs)
        if error:
            transaction.set_rollback(True)
            return self.set_response(error,
                                     reason,
                                     status=drf_status.HTTP_400_BAD_REQUEST)

        return response
Beispiel #38
0
    def post(self, request):
        with transaction.atomic():
            try:
                patient = self.__get_or_create_patient(request.POST)
                if isinstance(patient, str):
                    transaction.set_rollback(True)
                    return HttpResponseBadRequest(patient)
                case = self.__get_or_create_case(request.POST, patient)
                if isinstance(case, str):
                    transaction.set_rollback(True)
                    return HttpResponseBadRequest(case)

                uploader = User.objects.get(username='******')
                lab_info_id = request.POST['labinfo']
                lab_info = LabInfo.objects.get(pk=lab_info_id)
                format = request.POST['format']
                type = request.POST['type']
                uploaded_dt = datetime.now()

                file = request.FILES['file']
                size = file.size
                name = file.name

                res = File.objects.update_or_create(file=file,
                                                    case=case,
                                                    uploader=uploader,
                                                    lab_info=lab_info,
                                                    format=format,
                                                    type=type,
                                                    uploaded_dt=uploaded_dt,
                                                    size=size,
                                                    name=name)
                return HttpResponseRedirect(
                    reverse('file', kwargs={'file_id': res[0].pk}))
            except MultiValueDictKeyError as e:
                logger.error(str(e))
                transaction.set_rollback(True)
                return HttpResponseBadRequest("Malformed upload")
Beispiel #39
0
    def list(self, request, *args, **kwargs):
        """list请求,设置事务,并在异常的时候进行回滚

        Args:
            request(Request): DRF Request
            *args(list): 可变参数
            **kwargs(dict): 可变关键字参数

        Returns:
            response(Response): 响应数据
        """
        # list请求预处理
        error, reason = self._pre_process_list(request, *args, **kwargs)
        if error:
            transaction.set_rollback(True)
            return self.set_response(error,
                                     reason,
                                     status=drf_status.HTTP_400_BAD_REQUEST)

        # list请求
        try:
            response = self._perform_list(request, *args, **kwargs)
        except Exception as error:
            transaction.set_rollback(True)
            return self.set_response('Failed to get model list',
                                     f'获取资源数据列表失败,错误信息为{error}',
                                     status=drf_status.HTTP_400_BAD_REQUEST)

        # list请求后处理
        error, reason, response = self._post_process_list(
            request, response, *args, **kwargs)
        if error:
            transaction.set_rollback(True)
            return self.set_response(error,
                                     reason,
                                     status=drf_status.HTTP_400_BAD_REQUEST)
        return response
Beispiel #40
0
 def rollback(self):
     from django.db import transaction as db_transaction
     db_transaction.set_rollback(True)
Beispiel #41
0
 def _rollback_atomics(cls, atomics):
     """Rollback atomic blocks opened through the previous method"""
     for db_name in reversed(cls._databases_names()):
         transaction.set_rollback(True, using=db_name)
         atomics[db_name].__exit__(None, None, None)
Beispiel #42
0
def confirm_email_change(request, key):  # pylint: disable=unused-argument
    """
    User requested a new e-mail. This is called when the activation
    link is clicked. We confirm with the old e-mail, and update
    """
    if waffle().is_enabled(PREVENT_AUTH_USER_WRITES):
        return render_to_response('email_change_failed.html',
                                  {'err_msg': SYSTEM_MAINTENANCE_MSG})

    with transaction.atomic():
        try:
            pec = PendingEmailChange.objects.get(activation_key=key)
        except PendingEmailChange.DoesNotExist:
            response = render_to_response("invalid_email_key.html", {})
            transaction.set_rollback(True)
            return response

        user = pec.user
        address_context = {'old_email': user.email, 'new_email': pec.new_email}

        if len(User.objects.filter(email=pec.new_email)) != 0:
            response = render_to_response("email_exists.html", {})
            transaction.set_rollback(True)
            return response

        subject = render_to_string('emails/email_change_subject.txt',
                                   address_context)
        subject = ''.join(subject.splitlines())
        message = render_to_string('emails/confirm_email_change.txt',
                                   address_context)
        u_prof = UserProfile.objects.get(user=user)
        meta = u_prof.get_meta()
        if 'old_emails' not in meta:
            meta['old_emails'] = []
        meta['old_emails'].append(
            [user.email, datetime.datetime.now(UTC).isoformat()])
        u_prof.set_meta(meta)
        u_prof.save()
        # Send it to the old email...
        try:
            user.email_user(
                subject, message,
                configuration_helpers.get_value('email_from_address',
                                                settings.DEFAULT_FROM_EMAIL))
        except Exception:  # pylint: disable=broad-except
            log.warning('Unable to send confirmation email to old address',
                        exc_info=True)
            response = render_to_response("email_change_failed.html",
                                          {'email': user.email})
            transaction.set_rollback(True)
            return response

        user.email = pec.new_email
        user.save()
        pec.delete()
        # And send it to the new email...
        try:
            user.email_user(
                subject, message,
                configuration_helpers.get_value('email_from_address',
                                                settings.DEFAULT_FROM_EMAIL))
        except Exception:  # pylint: disable=broad-except
            log.warning('Unable to send confirmation email to new address',
                        exc_info=True)
            response = render_to_response("email_change_failed.html",
                                          {'email': pec.new_email})
            transaction.set_rollback(True)
            return response

        response = render_to_response("email_change_successful.html",
                                      address_context)
        return response
Beispiel #43
0
def confirm_email_change(request, key):  # pylint: disable=unused-argument
    """
    User requested a new e-mail. This is called when the activation
    link is clicked. We confirm with the old e-mail, and update
    """
    if waffle().is_enabled(PREVENT_AUTH_USER_WRITES):
        return render_to_response('email_change_failed.html', {'err_msg': SYSTEM_MAINTENANCE_MSG})

    with transaction.atomic():
        try:
            pec = PendingEmailChange.objects.get(activation_key=key)
        except PendingEmailChange.DoesNotExist:
            response = render_to_response("invalid_email_key.html", {})
            transaction.set_rollback(True)
            return response

        user = pec.user
        address_context = {
            'old_email': user.email,
            'new_email': pec.new_email
        }

        if len(User.objects.filter(email=pec.new_email)) != 0:
            response = render_to_response("email_exists.html", {})
            transaction.set_rollback(True)
            return response

        use_https = request.is_secure()
        if settings.FEATURES['ENABLE_MKTG_SITE']:
            contact_link = marketing_link('CONTACT')
        else:
            contact_link = '{protocol}://{site}{link}'.format(
                protocol='https' if use_https else 'http',
                site=configuration_helpers.get_value('SITE_NAME', settings.SITE_NAME),
                link=reverse('contact'),
            )

        site = Site.objects.get_current()
        message_context = get_base_template_context(site)
        message_context.update({
            'old_email': user.email,
            'new_email': pec.new_email,
            'contact_link': contact_link,
            'from_address': configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL),
        })

        msg = EmailChangeConfirmation().personalize(
            recipient=Recipient(user.username, user.email),
            language=preferences_api.get_user_preference(user, LANGUAGE_KEY),
            user_context=message_context,
        )

        u_prof = UserProfile.objects.get(user=user)
        meta = u_prof.get_meta()
        if 'old_emails' not in meta:
            meta['old_emails'] = []
        meta['old_emails'].append([user.email, datetime.datetime.now(UTC).isoformat()])
        u_prof.set_meta(meta)
        u_prof.save()
        # Send it to the old email...
        try:
            ace.send(msg)
        except Exception:    # pylint: disable=broad-except
            log.warning('Unable to send confirmation email to old address', exc_info=True)
            response = render_to_response("email_change_failed.html", {'email': user.email})
            transaction.set_rollback(True)
            return response

        user.email = pec.new_email
        user.save()
        pec.delete()
        # And send it to the new email...
        msg.recipient = Recipient(user.username, pec.new_email)
        try:
            ace.send(msg)
        except Exception:  # pylint: disable=broad-except
            log.warning('Unable to send confirmation email to new address', exc_info=True)
            response = render_to_response("email_change_failed.html", {'email': pec.new_email})
            transaction.set_rollback(True)
            return response

        response = render_to_response("email_change_successful.html", address_context)
        return response
 def signal_handler(signal, frame):
     transaction.set_rollback(True)
     raise Exception('Received interrupt signal. Aborting...')
Beispiel #45
0
def view(request):
    data = {}
    data['permite_modificar'] = True
    if request.method == 'POST':
        if 'user' in request.session:
            if 'action' in request.POST:
                action = request.POST['action']
                if action == 'add_pais':
                    try:
                        vali = PaisForm(request.POST, request.FILES)
                        if vali.is_valid():
                            pais = Pais(nombre=vali.cleaned_data['nombre'],
                                        estado=vali.cleaned_data['estado'])
                            pais.save()
                            if 'imagen' in request.FILES:
                                foto = request.FILES['imagen']
                                if foto.name.find(".") > 0:
                                    ext = foto.name[foto.name.rfind("."):]
                                    if ext != 'jpeg' or ext != 'jpg' or ext != 'png':
                                        return JsonResponse({
                                            "result":
                                            "error",
                                            "mensaje":
                                            'No es un archivo valido.'
                                        })
                                else:
                                    return JsonResponse({
                                        "result":
                                        "error",
                                        "mensaje":
                                        'No es un archivo valido.'
                                    })
                                foto.name = "imagen_pais_%s_%s" % (pais.id,
                                                                   ext)
                                pais.imagen = foto
                                pais.save()
                            return JsonResponse({"result": "ok"})
                        else:
                            return JsonResponse({
                                "result":
                                "error",
                                "mensaje":
                                'datos erroneos en el formulario.'
                            })
                    except Exception as ex:
                        transaction.set_rollback(True)
                        return JsonResponse({
                            "result":
                            "error",
                            "mensaje":
                            'Ocurrio un problema contacte con el administrador.'
                        })

                elif action == 'edit_pais':
                    try:
                        vali = PaisForm(request.POST, request.FILES)
                        if vali.is_valid():
                            pais = Pais.objects.get(pk=int(request.POST['id']))
                            pais.nombre = vali.cleaned_data['nombre']
                            pais.estado = vali.cleaned_data['estado']
                            if 'imagen' in request.FILES:
                                foto = request.FILES['imagen']
                                if foto.name.find(".") > 0:
                                    ext = foto.name[foto.name.rfind("."):]
                                else:
                                    return JsonResponse({
                                        "result":
                                        "error",
                                        "mensaje":
                                        'No es un archivo valido.'
                                    })
                                foto.name = "imagen_pais_%s_%s" % (pais.id,
                                                                   ext)
                                pais.imagen = foto
                            pais.save()
                            return JsonResponse({"result": "ok"})
                        else:
                            return JsonResponse({
                                "result":
                                "error",
                                "mensaje":
                                'datos erroneos en el formulario. %s' %
                                vali._errors
                            })
                    except Exception as ex:
                        transaction.set_rollback(True)
                        return JsonResponse({
                            "result":
                            "error",
                            "mensaje":
                            'Ocurrio un problema contacte con el administrador. %s'
                            % ex
                        })

                elif action == 'del_pais':
                    try:
                        pais = Pais.objects.get(pk=int(request.POST['id']))
                        pais.delete()
                        return JsonResponse({"result": "ok"})
                    except Exception as ex:
                        transaction.set_rollback(True)
                        return JsonResponse({
                            "result":
                            "error",
                            "mensaje":
                            'Ocurrio un problema contacte con el administrador.'
                        })

                return JsonResponse({
                    "result": "bad",
                    "mensaje": u"Solicitud Incorrecta."
                })
        else:
            return JsonResponse({"result": "session"})
    else:
        if 'action' in request.GET:
            action = request.GET['action']
            if action == 'add_pais':
                try:
                    data['title'] = u'Agregar Pais'
                    data['form'] = PaisForm(initial={'estado': True})
                    return render(request, "add_pais.html", data)
                except Exception as ex:
                    pass

            elif action == 'edit_pais':
                try:
                    data['title'] = u'Editar Pais'
                    data['pais'] = pais = Pais.objects.get(
                        pk=int(request.GET['id']))
                    data['form'] = PaisForm(initial={
                        'nombre': pais.nombre,
                        'estado': pais.estado
                    })
                    return render(request, "add_pais.html", data)
                except Exception as ex:
                    pass

            elif action == 'del_pais':
                try:
                    data['title'] = u'Eliminar Pais'
                    data['pais'] = Pais.objects.get(pk=int(request.GET['id']))
                    return render(request, "del_pais.html", data)
                except Exception as ex:
                    pass
Beispiel #46
0
 def endTransaction(self):
     """Rollback transaction using Django's `atomic`."""
     transaction.set_rollback(True)
     self.__atomic.__exit__(None, None, None)
     self.assertNotInTransaction()
Beispiel #47
0
def configure_content(instance: CourseInstance,
                      url: str) -> Tuple[bool, List[str]]:
    """
    Configures course content by trusted remote URL.
    """
    if not url:
        return False, [_('COURSE_CONFIG_URL_REQUIRED')]

    # save the url before fetching config. The JWT system requires this to be
    # set, so that A+ knows which service to trust to have access to the course
    # instance. The aplus config url might need access to the course instance.
    # The other service might also need to have access to the course instance
    # before it can be configured from the url.
    instance.configure_url = url
    instance.save()

    try:
        url = url.strip()
        permissions = Permissions()
        permissions.instances.add(Permission.READ, id=instance.id)
        permissions.instances.add(Permission.WRITE, id=instance.id)
        response = aplus_get(url, permissions=permissions)
        response.raise_for_status()
    except Exception as e:
        return False, [
            format_lazy(
                _('COURSE_CONFIG_ERROR_REQUEST_FAILED -- {error!s}'),
                error=e,
            )
        ]

    try:
        config = json.loads(response.text)
    except Exception as e:
        return False, [
            format_lazy(
                _('COURSE_CONFIG_ERROR_JSON_PARSER_FAILED -- {error!s}'),
                error=e,
            )
        ]

    if not isinstance(config, dict):
        return False, [_("COURSE_CONFIG_ERROR_INVALID_JSON")]

    errors = config.get('errors', [])
    if not isinstance(errors, list):
        errors = [str(errors)]

    if not config.get('success', True):
        errors.insert(0, _("COURSE_CONFIG_ERROR_SERVICE_FAILED_TO_EXPORT"))
        return False, errors

    # wrap everything in a transaction to make sure invalid configuration isn't saved
    with transaction.atomic():
        # Configure course instance attributes.
        if "start" in config:
            dt = parse_date(config["start"], errors)
            if dt:
                instance.starting_time = dt
        if "end" in config:
            dt = parse_date(config["end"], errors)
            if dt:
                instance.ending_time = dt
        if "enrollment_start" in config:
            instance.enrollment_starting_time = parse_date(
                config["enrollment_start"], errors, allow_null=True)
        if "enrollment_end" in config:
            instance.enrollment_ending_time = parse_date(
                config["enrollment_end"], errors, allow_null=True)
        if "lifesupport_time" in config:
            instance.lifesupport_time = parse_date(config["lifesupport_time"],
                                                   errors,
                                                   allow_null=True)
        if "archive_time" in config:
            instance.archive_time = parse_date(config["archive_time"],
                                               errors,
                                               allow_null=True)
        if "enrollment_audience" in config:
            enroll_audience = parse_choices(
                config["enrollment_audience"], {
                    'internal':
                    CourseInstance.ENROLLMENT_AUDIENCE.INTERNAL_USERS,
                    'external':
                    CourseInstance.ENROLLMENT_AUDIENCE.EXTERNAL_USERS,
                    'all': CourseInstance.ENROLLMENT_AUDIENCE.ALL_USERS,
                }, "enrollment_audience", errors)
            if enroll_audience is not None:
                instance.enrollment_audience = enroll_audience
        if "view_content_to" in config:
            view_content_to = parse_choices(
                config["view_content_to"], {
                    'enrolled': CourseInstance.VIEW_ACCESS.ENROLLED,
                    'enrollment_audience':
                    CourseInstance.VIEW_ACCESS.ENROLLMENT_AUDIENCE,
                    'all_registered':
                    CourseInstance.VIEW_ACCESS.ALL_REGISTERED,
                    'public': CourseInstance.VIEW_ACCESS.PUBLIC,
                }, "view_content_to", errors)
            if view_content_to is not None:
                instance.view_content_to = view_content_to
        if "index_mode" in config:
            index_mode = parse_choices(
                config["index_mode"], {
                    'results': CourseInstance.INDEX_TYPE.RESULTS,
                    'toc': CourseInstance.INDEX_TYPE.TOC,
                    'last': CourseInstance.INDEX_TYPE.LAST,
                    'experimental': CourseInstance.INDEX_TYPE.EXPERIMENT,
                }, "index_mode", errors)
            if index_mode is not None:
                instance.index_mode = index_mode

        numbering_choices = {
            'none': CourseInstance.CONTENT_NUMBERING.NONE,
            'arabic': CourseInstance.CONTENT_NUMBERING.ARABIC,
            'roman': CourseInstance.CONTENT_NUMBERING.ROMAN,
            'hidden': CourseInstance.CONTENT_NUMBERING.HIDDEN,
        }
        if "content_numbering" in config:
            numbering = parse_choices(config["content_numbering"],
                                      numbering_choices, "content_numbering",
                                      errors)
            if numbering is not None:
                instance.content_numbering = numbering
        if "module_numbering" in config:
            numbering = parse_choices(config["module_numbering"],
                                      numbering_choices, "module_numbering",
                                      errors)
            if numbering is not None:
                instance.module_numbering = numbering
        if "course_description" in config:
            # Course index.yaml files have previously used the field "description"
            # for a hidden description, so we use "course_description" for
            # the visible description.
            instance.description = str(config["course_description"])
        if "course_footer" in config:
            instance.footer = str(config["course_footer"])
        if "lang" in config:
            langs = config["lang"]
            if isinstance(langs, list):
                langs = [
                    lang for lang in langs if instance.is_valid_language(lang)
                ]
                if langs:
                    instance.language = "|{}|".format("|".join(langs))
            elif instance.is_valid_language(langs):
                instance.language = str(langs)[:5]
        if "contact" in config:
            instance.technical_error_emails = str(config["contact"])
        if "head_urls" in config:
            head_urls = config["head_urls"]
            instance.head_urls = "\n".join(head_urls) if isinstance(
                head_urls, list) else str(head_urls)
        if "assistants" in config:
            if not isinstance(config["assistants"], list):
                errors.append(_('COURSE_CONFIG_ERROR_ASSISTANTS_AS_SID_ARRAY'))
            else:
                assistants = []
                for sid in config["assistants"]:
                    try:
                        profile = UserProfile.get_by_student_id(student_id=sid)
                    except UserProfile.DoesNotExist as err:
                        errors.append(
                            format_lazy(
                                _('COURSE_CONFIG_ERROR_ASSISTANT_NO_USER_WITH_SID -- {id}'
                                  ),
                                id=sid,
                            ))
                    else:
                        assistants.append(profile)
                instance.set_assistants(assistants)
        instance.build_log_url = str(
            config['build_log_url']) if 'build_log_url' in config else ''
        # configure_url excluded from validation because the default Django URL
        # validation does not accept dotless domain names such as "grader"
        instance.full_clean(exclude=['configure_url', 'build_log_url'])
        instance.save()

        if not "categories" in config or not isinstance(
                config["categories"], dict):
            errors.append(_('COURSE_CONFIG_ERROR_CATEGORIES_REQUIRED_OBJECT'))
            transaction.set_rollback(True)
            return False, errors
        if not "modules" in config or not isinstance(config["modules"], list):
            errors.append(_('COURSE_CONFIG_ERROR_MODULES_REQUIRED_ARRAY'))
            transaction.set_rollback(True)
            return False, errors

        # Configure learning object categories.
        category_map = {}
        seen = []
        for key, c in config.get("categories", {}).items():
            if not "name" in c:
                errors.append(_('COURSE_CONFIG_ERROR_CATEGORY_REQUIRES_NAME'))
                continue
            try:
                category = instance.categories.get(
                    name=format_localization(c["name"]))
            except LearningObjectCategory.DoesNotExist:
                category = LearningObjectCategory(course_instance=instance,
                                                  name=format_localization(
                                                      c["name"]))
            if "status" in c:
                category.status = str(c["status"])
            if "description" in c:
                category.description = str(c["description"])
            if "points_to_pass" in c:
                i = parse_int(c["points_to_pass"], errors)
                if not i is None:
                    category.points_to_pass = i
            for field in [
                    "confirm_the_level",
                    "accept_unofficial_submits",
            ]:
                if field in c:
                    setattr(category, field, parse_bool(c[field]))
            category.full_clean()
            category.save()
            category_map[key] = category
            seen.append(category.id)

        for category in instance.categories.all():
            if not category.id in seen:
                category.status = LearningObjectCategory.STATUS.HIDDEN
                category.save()

        # Configure course modules.
        seen_modules = []
        seen_objects = []
        nn = 0
        n = 0
        for m in config.get("modules", []):
            if not "key" in m:
                errors.append(_('COURSE_CONFIG_ERROR_MODULE_REQUIRES_KEY'))
                continue
            try:
                module = instance.course_modules.get(url=str(m["key"]))
            except CourseModule.DoesNotExist:
                module = CourseModule(course_instance=instance,
                                      url=str(m["key"]))

            if "order" in m:
                module.order = parse_int(m["order"], errors)
            else:
                n += 1
                module.order = n

            if "title" in m:
                module.name = format_localization(m["title"])
            elif "name" in m:
                module.name = format_localization(m["name"])
            if not module.name:
                module.name = "-"
            if "status" in m:
                module.status = str(m["status"])
            if "points_to_pass" in m:
                i = parse_int(m["points_to_pass"], errors)
                if not i is None:
                    module.points_to_pass = i
            if "introduction" in m:
                module.introduction = str(m["introduction"])

            if "open" in m:
                dt = parse_date(m["open"], errors)
                if dt:
                    module.opening_time = dt
            if not module.opening_time:
                module.opening_time = instance.starting_time

            if "close" in m:
                dt = parse_date(m["close"], errors)
                if dt:
                    module.closing_time = dt
            elif "duration" in m:
                dt = parse_duration(module.opening_time, m["duration"], errors)
                if dt:
                    module.closing_time = dt
            if not module.closing_time:
                module.closing_time = instance.ending_time

            if "read-open" in m:
                module.reading_opening_time = parse_date(m["read-open"],
                                                         errors,
                                                         allow_null=True)

            if "late_close" in m:
                dt = parse_date(m["late_close"], errors)
                if dt:
                    module.late_submission_deadline = dt
                    module.late_submissions_allowed = True
            elif "late_duration" in m:
                dt = parse_duration(module.closing_time, m["late_duration"],
                                    errors)
                if dt:
                    module.late_submission_deadline = dt
                    module.late_submissions_allowed = True
            if "late_penalty" in m:
                f = parse_float(m["late_penalty"], errors)
                if not f is None:
                    module.late_submission_penalty = f

            module.full_clean()
            module.save()
            seen_modules.append(module.id)

            if not ("numerate_ignoring_modules" in config \
                    and parse_bool(config["numerate_ignoring_modules"])):
                nn = 0
            if "children" in m:
                nn = configure_learning_objects(category_map, module,
                                                m["children"], None,
                                                seen_objects, errors, nn)

        for module in instance.course_modules.all():
            # cache invalidation uses the parent when learning object is saved:
            # prefetch parent so that it wont be fetched after the it was deleted
            for lobject in module.learning_objects.all().prefetch_related(
                    'parent'):
                if lobject.id not in seen_objects:
                    exercise = lobject.as_leaf_class()
                    if (not isinstance(exercise, BaseExercise)
                            or exercise.submissions.count() == 0):
                        exercise.delete()
                    else:
                        lobject.status = LearningObject.STATUS.HIDDEN
                        lobject.order = 9999
                        # .parent may have been deleted: only save status and order
                        lobject.save(update_fields=["status", "order"])
            if module.id not in seen_modules:
                if module.learning_objects.count() == 0:
                    module.delete()
                else:
                    module.status = CourseModule.STATUS.HIDDEN
                    module.save()

        # Clean up obsolete categories.
        for category in instance.categories.filter(
                status=LearningObjectCategory.STATUS.HIDDEN):
            if category.learning_objects.count() == 0:
                category.delete()

        if "publish_url" in config:
            success = False
            publish_errors = []
            try:
                permissions = Permissions()
                permissions.instances.add(Permission.READ, id=instance.id)
                permissions.instances.add(Permission.WRITE, id=instance.id)
                response = aplus_get(config["publish_url"],
                                     permissions=permissions)
            except ConnectionError as e:
                publish_errors = [str(e)]
            else:
                if response.status_code != 200:
                    publish_errors = [
                        format_lazy(
                            _("PUBLISH_RESPONSE_NON_200 -- {status_code}"),
                            status_code=response.status_code)
                    ]

                if response.text:
                    try:
                        publish_errors = json.loads(response.text)
                    except Exception as e:
                        publish_errors = [
                            format_lazy(_(
                                "PUBLISH_ERROR_JSON_PARSER_FAILED -- {e}, {text}"
                            ),
                                        e=e,
                                        text=response.text)
                        ]
                    else:
                        if isinstance(publish_errors, dict):
                            success = publish_errors.get("success", True)
                            publish_errors = publish_errors.get("errors", [])

                        if isinstance(publish_errors, list):
                            publish_errors = (str(e) for e in publish_errors)
                        else:
                            publish_errors = [str(publish_errors)]

            if publish_errors:
                if not success:
                    errors.append(
                        format_lazy(
                            _("PUBLISHED_WITH_ERRORS -- {publish_url}"),
                            publish_url=config['publish_url']))
                errors.extend(str(e) for e in publish_errors)

            if not success:
                transaction.set_rollback(True)
                return False, errors

    return True, errors
Beispiel #48
0
def post_comment(request, send_signal=True):
    """
    View function that handles inserting new/editing previously existing comments via Ajax
    """
    # Based on variables passed in we get the comment the user is attempting to create/edit
    try:
        comment, previous_version = get_comment(request)
    except InvalidCommentException as e:
        transaction.rollback()
        return JsonResponse({
            'ok': False,
            'error_message': str(e),
        })

    # Check if the user doesn't pass the appropriate permission check (on the parent_object)...
    # We call this on the parent comment because the comment itself may not have been saved yet (can't call .get_root on it)
    # TODO: Fix this for root comment? (no parent)
    parent_comment = comment.parent
    tree_root = parent_comment.get_root()
    parent_object = tree_root.content_object
    if not user_can_post_comment(request, comment):
        transaction.set_rollback(True)
        return JsonResponse({
            'ok':
            False,
            'error_message':
            "You do not have permission to post this comment.",
        })

    # Check to make sure we are not trying to save a comment "deeper" than we are allowed...
    if is_past_max_depth(comment):
        transaction.set_rollback(True)
        return JsonResponse({
            'ok':
            False,
            'error_message':
            "You cannot respond to this comment.",
        })

    # If the comment object (NOT the message) hasn't been saved yet...
    if comment._state.adding == True:
        comment = add_comment(comment)

    # Now that we have a comment object, we get a 'lock' on it to prevent a race condition
    try:
        lock_comment(comment)
    except DatabaseError:
        transaction.set_rollback(True)
        # Someone is already trying to update this comment, so we need to return an appropriate error
        return JsonResponse({
            'ok':
            False,
            'error_message':
            "Someone else is currently editing this comment. Please refresh your page and try again.",
        })

    # Now we know we have sole access to the comment object at the moment so we need to check if we are editing the most recent version
    if not_most_recent_version(comment, previous_version):
        transaction.set_rollback(True)
        return JsonResponse({
            'ok':
            False,
            'error_message':
            "You are not editing the most recent version of this comment. Please refresh your page and try again.",
        })

    # Everything has checked out, so we save the new version and return the appropriate response
    version_form, new_version = create_new_version(request, comment)
    if version_form.is_valid():
        comment_template, kwargs = get_template(request,
                                                comment,
                                                parent_object,
                                                tree_root,
                                                new_version,
                                                previous_version,
                                                send_signal=send_signal)

        return JsonResponse({
            'ok':
            True,
            'html_content':
            loader.render_to_string(comment_template, context=kwargs)
        })
    else:
        transaction.set_rollback(True)
        return JsonResponse({
            'ok':
            False,
            'error_message':
            "There were errors in your submission. Please correct them and resubmit.",
        })
Beispiel #49
0
def confirm_email_change(request, key):  # pylint: disable=unused-argument
    """
    User requested a new e-mail. This is called when the activation
    link is clicked. We confirm with the old e-mail, and update
    """
    if waffle().is_enabled(PREVENT_AUTH_USER_WRITES):
        return render_to_response('email_change_failed.html', {'err_msg': SYSTEM_MAINTENANCE_MSG})

    with transaction.atomic():
        try:
            pec = PendingEmailChange.objects.get(activation_key=key)
        except PendingEmailChange.DoesNotExist:
            response = render_to_response("invalid_email_key.html", {})
            transaction.set_rollback(True)
            return response

        user = pec.user
        address_context = {
            'old_email': user.email,
            'new_email': pec.new_email
        }

        if len(User.objects.filter(email=pec.new_email)) != 0:
            response = render_to_response("email_exists.html", {})
            transaction.set_rollback(True)
            return response

        subject = render_to_string('emails/email_change_subject.txt', address_context)
        subject = ''.join(subject.splitlines())
        message = render_to_string('emails/confirm_email_change.txt', address_context)
        u_prof = UserProfile.objects.get(user=user)
        meta = u_prof.get_meta()
        if 'old_emails' not in meta:
            meta['old_emails'] = []
        meta['old_emails'].append([user.email, datetime.datetime.now(UTC).isoformat()])
        u_prof.set_meta(meta)
        u_prof.save()
        # Send it to the old email...
        try:
            user.email_user(
                subject,
                message,
                configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
            )
        except Exception:    # pylint: disable=broad-except
            log.warning('Unable to send confirmation email to old address', exc_info=True)
            response = render_to_response("email_change_failed.html", {'email': user.email})
            transaction.set_rollback(True)
            return response

        user.email = pec.new_email
        user.save()
        pec.delete()
        # And send it to the new email...
        try:
            user.email_user(
                subject,
                message,
                configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
            )
        except Exception:  # pylint: disable=broad-except
            log.warning('Unable to send confirmation email to new address', exc_info=True)
            response = render_to_response("email_change_failed.html", {'email': pec.new_email})
            transaction.set_rollback(True)
            return response

        response = render_to_response("email_change_successful.html", address_context)
        return response
Beispiel #50
0
    def handle(self, *args, **options):

        loglevel = options.get('loglevel')
        try:
            loglevel = int(loglevel)
        except ValueError as e:
            self.stderr.write(
                self.style.ERROR(
                    f"Unable to parse loglevel='{loglevel}' to an integer.  Only numerical values accepted."
                ))
            sys.exit(1)

        logging.disable(loglevel)

        order_no: int = options.get('order_no')[0]
        year: int = options.get('year')[0]
        commit: bool = options.get('commit', False)
        skip_errors: bool = options.get('skip', False)

        if year < 1000:
            year += 2000

        if not commit:
            self.stderr.write(
                self.style.WARNING(
                    "DRY RUN: No processed data will be committed."))
            self.stderr.write(
                self.style.WARNING(
                    "\tTo commit, pass `-c` or `--commit` flag.\n"))

        # Validate that all passed DBFs exist

        self.stdout.write("Creating transaction savepoint.")
        sp = transaction.savepoint()
        self.stdout.write(
            self.style.HTTP_INFO(
                f"Beginning order input for Year: `{year}`, Order: `{order_no}`"
            ))
        with transaction.atomic():

            import os
            from math import ceil
            from django.conf import settings
            from Braumat.parser import parse_dbf
            from HotBlock.analysis import hotblock_analysis
            from HotBlock.models import Batch

            rootpath = os.path.join(
                os.path.split(settings.BASE_DIR)[0], '_data', '_hotblock',
                f'SRJA_{year % 1000}')
            filepath = os.path.join(
                f'ANR0{int(ceil(order_no / 50)) * 50:04d}',
                f'S{year % 1000}00{order_no:03d}.DBF',
            )

            hotblock_production = os.path.join(rootpath, 'REZ_001', filepath)
            hotblock_fmb = os.path.join(rootpath, 'REZ_004', filepath)
            coldblock_wortline = os.path.join(
                rootpath.replace('_hot', '_cold'), 'REZ_001', filepath)

            for f in (hotblock_production, hotblock_fmb, coldblock_wortline):
                if os.path.isfile(f):
                    _logger.debug(f"File found at f=`{f}`")
                    self.stdout.write(
                        self.style.HTTP_INFO(
                            f"Being parse of file located at `{f}`"))
                    parse_dbf(f, skip_errors)
                    self.stdout.write(
                        self.style.SUCCESS('\tFile parsed successfully.'))
                else:
                    self.stderr.write(
                        self.style.ERROR(
                            f"Unable to locate Data file expected at: `{f}`"))
                    _logger.debug(
                        f"Unable to locate Data file expected at: `{f}`")

            self.stdout.write(
                self.style.HTTP_INFO(
                    "Beginning HotBlock Analysis of unlocked, unanalyzed batches..."
                ))

            batches = Batch.objects.filter(date__year=year,
                                           order=order_no,
                                           locked=False,
                                           analyzed=False)
            self.stdout.write(self.style.HTTP_INFO(f'{len(batches)} found.'))
            for batch in batches:
                hotblock_analysis(batch, True)

            if not commit:
                self.stdout.write(
                    self.style.WARNING(
                        "Rolling back database to generated savepoint."))
                transaction.set_rollback(True)
                self.stdout.write(self.style.SUCCESS("Database rolled back."))

        self.stdout.write(
            self.style.SUCCESS(
                f"Hotblock End of Week Analysis for Order `{order_no}` complete."
            ))
Beispiel #51
0
def _ctit_db_wrapper(trans_safe=False):
    '''
    Wrapper to avoid undesired actions by Django ORM when managing settings
    if only getting a setting, can use trans_safe=True, which will avoid
    throwing errors if the prior context was a broken transaction.
    Any database errors will be logged, but exception will be suppressed.
    '''
    rollback_set = None
    is_atomic = None
    try:
        if trans_safe:
            is_atomic = connection.in_atomic_block
            if is_atomic:
                rollback_set = transaction.get_rollback()
                if rollback_set:
                    logger.debug(
                        'Obtaining database settings in spite of broken transaction.'
                    )
                    transaction.set_rollback(False)
        yield
    except DBError:
        if 'migrate' in sys.argv and get_tower_migration_version() < '310':
            logger.info('Using default settings until version 3.1 migration.')
        else:
            # We want the _full_ traceback with the context
            # First we get the current call stack, which constitutes the "top",
            # it has the context up to the point where the context manager is used
            top_stack = StringIO()
            traceback.print_stack(file=top_stack)
            top_lines = top_stack.getvalue().strip('\n').split('\n')
            top_stack.close()
            # Get "bottom" stack from the local error that happened
            # inside of the "with" block this wraps
            exc_type, exc_value, exc_traceback = sys.exc_info()
            bottom_stack = StringIO()
            traceback.print_tb(exc_traceback, file=bottom_stack)
            bottom_lines = bottom_stack.getvalue().strip('\n').split('\n')
            # Glue together top and bottom where overlap is found
            bottom_cutoff = 0
            for i, line in enumerate(bottom_lines):
                if line in top_lines:
                    # start of overlapping section, take overlap from bottom
                    top_lines = top_lines[:top_lines.index(line)]
                    bottom_cutoff = i
                    break
            bottom_lines = bottom_lines[bottom_cutoff:]
            tb_lines = top_lines + bottom_lines

            tb_string = '\n'.join(
                ['Traceback (most recent call last):'] + tb_lines +
                ['{}: {}'.format(exc_type.__name__, str(exc_value))])
            bottom_stack.close()
            # Log the combined stack
            if trans_safe:
                if 'check_migrations' not in sys.argv:
                    logger.warning(
                        'Database settings are not available, using defaults, error:\n{}'
                        .format(tb_string))
            else:
                logger.error(
                    'Error modifying something related to database settings.\n{}'
                    .format(tb_string))
    finally:
        if trans_safe and is_atomic and rollback_set:
            transaction.set_rollback(rollback_set)
Beispiel #52
0
def db(db_setup):
    with transaction.atomic():
        yield None
        transaction.set_rollback(True)
 def signal_handler(signal, frame):
     transaction.set_rollback(True)
     raise Exception("Received interrupt signal. Aborting...")
Beispiel #54
0
def cct_fermenter_analysis(batch: FermBatch, commit: bool = False) -> FermBatch:
    from django.db.models import OuterRef, Subquery
    from Braumat.constants.sequences import WORT_LINE
    from Braumat.constants.dfm import PV_WORT_LINE_CCT
    from HotBlock.models import Batch as HotBatch, StepRecord as HotStepRecord

    _logger.info(f'{batch}: Found category=`{CR.CCTS_FERM}`')

    if batch.tank is None:
        _logger.info(f'{batch}: No tank found on batch.  Assigning Tank.')
        try:
            batch.tank = batch.steprecord_set.select_related('step__sequence').prefetch_related('step__sequence__tank_set').first().step.sequence.tank_set.first()
        except AttributeError as e:
            _logger.critical(f'{batch}: {e}')
            raise e

    tankstr = f'{batch.tank.cellar}{batch.tank.number:02d}'
    _logger.info(f'Querying HotBlock for batches with WORT-LINE Tank=`{tankstr}`')

    tank_sub = Subquery(HotStepRecord.objects.filter(batch=OuterRef('pk'), step__sequence__id=WORT_LINE._PK, step__number=WORT_LINE.Transfer).values(PV_WORT_LINE_CCT)[:1])
    hotbatches = HotBatch.objects.annotate(tank=tank_sub).filter(order=batch.order, date__year=batch.date.year, batch__range=(batch.batch, batch.batch + 20), tank=f'{tankstr}')

    if hotbatches.count() < 1:
        _logger.error(f'{batch}: No HotBlock FermBatches found with a related tank=`{tankstr}`')
    else:
        hotbatches.update(fermbatch=batch)
        _logger.debug(f'{batch} Updated ColdBlock batch for `{hotbatches.count()}` HotBlock batches in tank=`{tankstr}`')

    initial_volume = hotbatches.aggregate(iv=models.Sum('bbls'))
    basestep = batch.steprecord_set.order_by('-end_time').filter(step__sequence=getattr(batch.tank, 'sequence', None))
    end_filling_step = basestep.filter(step__number=CCT_GENERAL.Filling)
    start_ferm_step = basestep.order_by('start_time').filter(step__number=CCT_GENERAL.Start_ferm)
    if hotbatches.count() > 0 and ( end_filling_step.exists() or start_ferm_step.exists() ):
        from Braumat.constants.dfm import GET_FIELD_DATA
        from Braumat.constants.sequences import WORT_COOLER
        from HotBlock.models import StepRecord as HotStepRecord
        
        batch.time_start = HotStepRecord.objects.filter(
            batch=batch.hotbatch_set.order_by('brew_number').only('pk').first().pk,
            step__sequence=WORT_COOLER._PK, step__number=WORT_COOLER.Temp_stabilisation).order_by('start_time').values_list('start_time', flat=True)[0]
        batch.time_full = end_filling_step.values_list('end_time', flat=True)[0] if end_filling_step.exists() else start_ferm_step.values_list('start_time', flat=True)[0]
        batch.initial_volume = initial_volume['iv']

        end_filling_step = end_filling_step.first()
        start_ferm_step = start_ferm_step.first()
        try:
            filling_step = end_filling_step if end_filling_step.end_time > start_ferm_step.start_time else start_ferm_step
        except AttributeError:
            filling_step = end_filling_step if end_filling_step else start_ferm_step
        pv_volume = GET_FIELD_DATA(filling_step, 'process_value_04', True)


        if abs(batch.initial_volume - pv_volume)/pv_volume < 0.2 and batch.recipe is not None:
            _logger.debug(f'{batch}: Critera met. Setting anaylzed=`{True}`')
            batch.analyzed = True
        elif batch.recipe is not None:
            warning = create_warning(batch, WR.AnalysisError, f'{batch}: Batch initial_volume=`{batch.initial_volume}` is in excess of 20% error from step Process Value Volume=`{pv_volume}` at {abs(batch.initial_volume - pv_volume)/pv_volume * 100}%')
            warning.save()
            _logger.warning(warning.log_str())
    else:
        warning = create_warning(batch, WR.AnalysisError, f'{batch}: No `Filling` or `Start Ferm` step found.')
        warning.save()
        _logger.error(warning.log_str())
    batch.save()

    if not commit:
        transaction.set_rollback(True)

    return batch
Beispiel #55
0
def _update_stock(request, change_type):
    products = Product.objects.all().filter(
        discontinued=False).order_by('name')
    if request.method == 'GET':
        if change_type == 'replenish':
            products = products.filter(quantity__gt=0)

        users = User.objects.all().filter(is_active=True).order_by('username')
        context = {
            'sellables': products.filter(category=0),  # FIXME: Magic numbers
            'refundables': products.filter(category=1),
            'names': users
        }
        return render(request, change_type + ".html", context)
    elif request.method == 'POST':
        if len(request.POST.getlist("who")) == 0:
            return HttpResponse("From validation error: no users selected")

        with transaction.atomic():
            updated = []
            for p in products:
                p_qty = str(p.pk) + "_qty"
                if p_qty in request.POST:
                    req_qty = int(request.POST[p_qty])
                else:
                    continue
                changed = req_qty != p.quantity
                updated.append((p, req_qty, changed))
                # TODO: Tell the user whats wrong in a nicer way
                if not (req_qty >= 0
                        and qty_verify_funs[change_type][p.category](
                            req_qty, p.quantity)):
                    transaction.set_rollback(True)
                    return HttpResponse(
                        "Form validation error: Invalid product quantity")

            if any(map(lambda t: t[2], updated)):
                # TODO: Do something better with EventType handling
                event = Event(
                    description=request.POST['what'],
                    event_type=EventType.objects.get(tag=change_type),
                    logged_user=request.user)
                event.save()
                for u in request.POST.getlist("who"):
                    event.eventbyuser_set.add(
                        EventByUser(name=User.objects.get(pk=u)), bulk=False)

                for p, req_qty, changed in updated:
                    event.change_set.add(Change(product=p,
                                                quantity=req_qty,
                                                delta=req_qty - p.quantity),
                                         bulk=False)
                    if changed:
                        p.quantity = req_qty
                        p.save()

                return HttpResponseRedirect("/" + change_type)
            else:
                transaction.set_rollback(True)
                return HttpResponse(
                    "Form validation error: No quantities changed")
Beispiel #56
0
def confirm_email_change(request, key):  # pylint: disable=unused-argument
    """
    User requested a new e-mail. This is called when the activation
    link is clicked. We confirm with the old e-mail, and update
    """
    if waffle().is_enabled(PREVENT_AUTH_USER_WRITES):
        return render_to_response('email_change_failed.html',
                                  {'err_msg': SYSTEM_MAINTENANCE_MSG})

    with transaction.atomic():
        try:
            pec = PendingEmailChange.objects.get(activation_key=key)
        except PendingEmailChange.DoesNotExist:
            response = render_to_response("invalid_email_key.html", {})
            transaction.set_rollback(True)
            return response

        user = pec.user
        address_context = {'old_email': user.email, 'new_email': pec.new_email}

        if len(User.objects.filter(email=pec.new_email)) != 0:
            response = render_to_response("email_exists.html", {})
            transaction.set_rollback(True)
            return response

        use_https = request.is_secure()
        if settings.FEATURES['ENABLE_MKTG_SITE']:
            contact_link = marketing_link('CONTACT')
        else:
            contact_link = '{protocol}://{site}{link}'.format(
                protocol='https' if use_https else 'http',
                site=configuration_helpers.get_value('SITE_NAME',
                                                     settings.SITE_NAME),
                link=reverse('contact'),
            )

        site = Site.objects.get_current()
        message_context = get_base_template_context(site)
        message_context.update({
            'old_email':
            user.email,
            'new_email':
            pec.new_email,
            'contact_link':
            contact_link,
            'from_address':
            configuration_helpers.get_value('email_from_address',
                                            settings.DEFAULT_FROM_EMAIL),
        })

        msg = EmailChangeConfirmation().personalize(
            recipient=Recipient(user.username, user.email),
            language=preferences_api.get_user_preference(user, LANGUAGE_KEY),
            user_context=message_context,
        )

        u_prof = UserProfile.objects.get(user=user)
        meta = u_prof.get_meta()
        if 'old_emails' not in meta:
            meta['old_emails'] = []
        meta['old_emails'].append(
            [user.email, datetime.datetime.now(UTC).isoformat()])
        u_prof.set_meta(meta)
        u_prof.save()
        # Send it to the old email...
        try:
            ace.send(msg)
        except Exception:  # pylint: disable=broad-except
            log.warning('Unable to send confirmation email to old address',
                        exc_info=True)
            response = render_to_response("email_change_failed.html",
                                          {'email': user.email})
            transaction.set_rollback(True)
            return response

        user.email = pec.new_email
        user.save()
        pec.delete()
        # And send it to the new email...
        msg.recipient = Recipient(user.username, pec.new_email)
        try:
            ace.send(msg)
        except Exception:  # pylint: disable=broad-except
            log.warning('Unable to send confirmation email to new address',
                        exc_info=True)
            response = render_to_response("email_change_failed.html",
                                          {'email': pec.new_email})
            transaction.set_rollback(True)
            return response

        response = render_to_response("email_change_successful.html",
                                      address_context)
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        user = None
        if request.user.is_authenticated():
            user = request.user

        if request.method == "GET":
            logger.debug("Start query request on the view %s." %
                         view_func.__name__)
            # NOTE: We do not need create a changeset when we just SELECT somw records.
            response = view_func(request, *view_args, **view_kwargs)
        else:
            # trap the request and give response when the method is not defined in HTTP/1.1
            if request.method not in [
                    "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT",
                    "PATCH", "OPTIONS"
            ]:
                logger.error('Wrong method %s specified when calling %s',
                             request.method.decode("utf-8"),
                             request.path,
                             exc_info=sys.exc_info())
                response_data = json.dumps(
                    {
                        "detail":
                        'Method "{method}" not allowed.'.format(
                            method=request.method)
                    },
                    ensure_ascii=False)
                response = HttpResponse(response_data,
                                        content_type='application/json')
                response.status_code = status.HTTP_405_METHOD_NOT_ALLOWED
                return response

            logger.debug("Start write request on the view %s." %
                         view_func.__name__)
            try:
                with transaction.atomic():
                    comment = request.META.get("HTTP_PDC_CHANGE_COMMENT", None)
                    request.changeset = models.Changeset(author=user,
                                                         comment=comment)
                    request.changeset.requested_on = datetime.now()
                    response = view_func(request, *view_args, **view_kwargs)
                    # response.exception=True means there is an error occurs.
                    if getattr(response, 'exception',
                               0) or (hasattr(response, 'status_code')
                                      and response.status_code >= 400):
                        # avoid recording changeset on server error, also
                        # abort the transaction so that no modifications are
                        # done to database
                        request.changeset.reset()
                        transaction.set_rollback(True)
                    else:
                        request.changeset.commit()
                        self._may_announce_big_change(request.changeset,
                                                      request)
            except Exception:
                # NOTE: catch all errors that were raised by view.
                # And log the trace back to the file.
                logger.error('View Function Error: %s',
                             request.path,
                             exc_info=sys.exc_info())
                # we do not want to break the default exception processing chains,
                # so re-raise the exception to the upper level.
                raise

        return response
Beispiel #58
0
def set_rollback():
    atomic_requests = connection.settings_dict.get('ATOMIC_REQUESTS', False)
    if atomic_requests and connection.in_atomic_block:
        transaction.set_rollback(True)
Beispiel #59
0
def set_rollback():
    atomic_requests = connection.settings_dict.get('ATOMIC_REQUESTS', False)
    if atomic_requests and connection.in_atomic_block:
        transaction.set_rollback(True)