jazzband / djangorestframework-simplejwt

A JSON Web Token authentication plugin for the Django REST Framework.
https://django-rest-framework-simplejwt.readthedocs.io/
MIT License
4.02k stars 663 forks source link

MSSQL problems with token_blacklist migration #615

Open zeloras opened 2 years ago

zeloras commented 2 years ago

Good evening! I found one issue and it's related with migration token_blacklist.0008_migrate_to_bigautofield. It seems like mssql not really supports changing field type from Autofield to BigAutoField https://github.com/microsoft/mssql-django/blob/dev/mssql/schema.py#L299

Running migrations:
  Applying token_blacklist.0008_migrate_to_bigautofield...Traceback (most recent call last):
  File "/app/manage.py", line 22, in <module>
    main()
  File "/app/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 398, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 89, in wrapped
    res = handle_func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/migrate.py", line 244, in handle
    post_migrate_state = executor.migrate(
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/executor.py", line 227, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/migration.py", line 126, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/operations/fields.py", line 244, in database_forwards
    schema_editor.alter_field(from_model, from_field, to_field)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/schema.py", line 608, in alter_field
    self._alter_field(model, old_field, new_field, old_type, new_type,
  File "/usr/local/lib/python3.10/site-packages/mssql/schema.py", line 287, in _alter_field
    raise NotImplementedError("the backend doesn't support altering from/to %s." % t.__name__)
NotImplementedError: the backend doesn't support altering from/to AutoField.

Could you check it please?

Andrew-Chen-Wang commented 2 years ago

This is unfortunate. We may need to add an if condition for the driver in our models, but it's hacky. I never found a way to not force the auto field settings migration to allow the default again... thoughts on the best course of action?

LuisRG30 commented 2 years ago

I am having this same issue. Is it a problem with mssql or with jwt framework?

Biblebrox commented 2 years ago

same problem

Biblebrox commented 2 years ago

LuisRG30

goes like this. same error with mssql

found not the best way to fix it:

delete all migrations from jwt framework in VENV изображение

Delete string with 'ID' from venv/Lib/site-packages/rest_framework_simplejwt/token_blacklist/models.py изображение

and another one below

then try to migrate

LuisRG30 commented 2 years ago

Hahaha, yeah. Actually did that. Working ok.

El dom, 13 nov 2022 a la(s) 12:43, Semyon @.***) escribió:

jwt goes like this. same error with mssql

found not the best way to fix it

delete all migrations from jwt framework in VENV [image: изображение] https://user-images.githubusercontent.com/46165137/201536525-1d54de09-2c1f-43d1-90c0-cba4f934f456.png

Delete string with 'ID' from venv/Lib/site-packages/rest_framework_simplejwt/token_blacklist/models.py [image: изображение] https://user-images.githubusercontent.com/46165137/201536642-aa9a35d0-e46a-4cb0-88c0-6f578d362a67.png

then try to migrate

— Reply to this email directly, view it on GitHub https://github.com/jazzband/djangorestframework-simplejwt/issues/615#issuecomment-1312794940, or unsubscribe https://github.com/notifications/unsubscribe-auth/AN6ZDTCHMPUWBU2WAVMSOBLWIEZFHANCNFSM6AAAAAAQNSYEFA . You are receiving this because you commented.Message ID: @.***>

r4z33n4l1 commented 2 years ago

LuisRG30

goes like this. same error with mssql

found not the best way to fix it:

delete all migrations from jwt framework in VENV изображение

Delete string with 'ID' from venv/Lib/site-packages/rest_framework_simplejwt/token_blacklist/models.py изображение

and another one below

then try to migrate

could you elaborate on what you meant by add another one below? I am facing the same issue! could you message me on discord- r4z33n#9710

Biblebrox commented 2 years ago

LuisRG30

goes like this. same error with mssql

found not the best way to fix it:

delete all migrations from jwt framework in VENV изображение

Delete string with 'ID' from venv/Lib/site-packages/rest_framework_simplejwt/token_blacklist/models.py изображение

and another one below

then try to migrate

could you elaborate on what you meant by add another one below? I am facing the same issue!

could you message me on discord- r4z33n#9710

It means that there are several variables "ID" in

venv/Lib/site-packages/rest_framework_simplejwt/token_blacklist/models.py

and you need to delete them all.

Sorry, have no discord

Andrew-Chen-Wang commented 2 years ago

This is a problem with MSSQL; I was testing only on Postgres and SQLite.

Is this problem only encountered when upgrading between versions or is this a problem for initial migration as welll?

WhitePako commented 1 year ago

This is a problem with MSSQL; I was testing only on Postgres and SQLite.

Is this problem only encountered when upgrading between versions or is this a problem for initial migration as welll?

It's a problem at initial migration, as django goes through each migration step. At 0001_initial, the two 'id' fields are declared as AutoFields, and later on 0008 tries to alter these to BigAutoFields.

Root cause is MSSQL backend does not support altering AutoField to BigAutoField.

I've played around with the migration files so 0001 declares mentioned fields as BigAutoField (copied field settings from 0010_fix_migrate_to_bigautofield) and removed 0008 and 0010 migration steps. Also replaced dependency in 0011 from 0010 to 0007.

In 0001_initial.py: image

In 0011_linearizes_history.py: image

Don't forget to remove these from the migrations folder: image

Migration went well after these changes. Feels like 1984 though.

armin-l commented 1 year ago

The fastest fix for me was to delete all migrations and create them new with py manage.py makemigrations rest_framework_simplejwt afterwards. This gave me one clean 0001_initial.py migration with everything needed.

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion

class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name="OutstandingToken",
            fields=[
                ("id", models.BigAutoField(primary_key=True, serialize=False)),
                ("jti", models.CharField(max_length=255, unique=True)),
                ("token", models.TextField()),
                ("created_at", models.DateTimeField(blank=True, null=True)),
                ("expires_at", models.DateTimeField()),
                (
                    "user",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "ordering": ("user",),
                "abstract": False,
            },
        ),
        migrations.CreateModel(
            name="BlacklistedToken",
            fields=[
                ("id", models.BigAutoField(primary_key=True, serialize=False)),
                ("blacklisted_at", models.DateTimeField(auto_now_add=True)),
                (
                    "token",
                    models.OneToOneField(
                        on_delete=django.db.models.deletion.CASCADE,
                        to="token_blacklist.outstandingtoken",
                    ),
                ),
            ],
            options={
                "abstract": False,
            },
        ),
    ]
sajontahsen commented 1 year ago

Sadly this is still an issue. I ended up using token auth w/ Djoser. I hope the devs will have a look at this soon. I mean, it doesn't NEED to be set up as AutoField initially, right?

Andrew-Chen-Wang commented 1 year ago

The conflicting migrations forced us to set the pk attribute. If you find a backwards compatible solution, a PR is welcome. Due to time constraints, I don't have the time to support this ticket.

Erick-Alvarez92 commented 1 month ago

You can fix this by removing the unique index constraint from the token_blacklist_blacklistedtoken table in the database, which will have a name similar to this UQ_token_bl_CB3C9....... Then re-run the migrate and that's it. If you want to recreate the unique index, just run in the database: ALTER TABLE dbo.token_blacklist_blacklistedtoken ADD CONSTRAINT UQ_token_id UNIQUE (id);