G’day all,
I have a branch in my Django project, it’s called otp
and it is for offering TOTP authentication to users. I last worked on this branch some weeks ago and I was running some of the tests for features on which I was working. The tests were working well for the entire app.
I’m using the Django OTP package to provide the TOTP functionality and so far things are working well. My project runs, I can login with TOTP and the entire project app looks to be perfectly fine. Running my tests is a completely different story.
Running manage.py test user_auth
generates the following exception (debug turned on)
2021-10-01 21:57:18,884 django.db.backends.schema DEBUG CREATE TABLE "django_otp_staticdevice" ("id" serial NOT NULL PRIMARY KEY, "user_id" uuid NOT NULL, "name" varchar(64) NOT NULL, "confirmed" boolean NOT NULL, "throttling_failure_timestamp" timestamp with time zone NULL, "throttling_failure_count" integer NOT NULL CHECK ("throttling_failure_count" >= 0)); (params None)
2021-10-01 21:57:18,891 django.db.backends.schema DEBUG CREATE TABLE "django_otp_statictoken" ("id" serial NOT NULL PRIMARY KEY, "device_id" integer NOT NULL, "token" varchar(16) NOT NULL); (params None)
2021-10-01 21:57:18,894 django.db.backends.schema DEBUG ALTER TABLE "django_otp_staticdevice" ADD CONSTRAINT "django_otp_staticdevice_user_id_9631127e_fk_users_customuser_id" FOREIGN KEY ("user_id") REFERENCES "users_customuser" ("id") DEFERRABLE INITIALLY DEFERRED; (params ())
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedTable: relation "users_customuser" does not exist`
If I run my tests for some other project specific apps, then that app’s tests run just fine. If I run tests in either of the apps registration
or user_auth
then I get the above message.
Now, it seems quite clear what the issue is, and that is the django-otp package migration’s are trying to reference users.customuser
which doesn’t exist.
Where I’m stumped is that I can’t work out why it is happening for some apps and not for others, and it also isn’t happening in my main development branch where I have the django_otp
and django_otp.plugins.otp_totp
installed, albeit it without the code which provides the TOTP login and the corresponding tests.
The main difference between the apps other than the views and tests is that there is one migration which has been made in the otp
branch. The model is for providing a token post username and password auth. The token is used to permit a user to attempt to verify her TOTP device. The model looks like this:
class OTPAllowedToken(Token): # token is a class provided by the app registration
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
def key_expired(self):
expiration_date = self.created + timedelta(
minutes=settings.POST_LOGIN_VALIDITY
)
return expiration_date <= timezone.now()
I had already created a Token model in my registration app, and it is this Token
from which my OTPAllowedToken
inherits.
class Token(models.Model):
key = models.CharField(_("Key"), max_length=40, primary_key=True)
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
related_name="token",
on_delete=models.CASCADE,
verbose_name=_("User"),
)
created = models.DateTimeField(_("Created"), auto_now_add=True)
class Meta:
verbose_name = "Token"
verbose_name_plural = "Tokens"
get_latest_by = ["created"]
I fear this is in some sort of clash or migration confusement happening when the OTPAllowedToken
is referencing the Token
from registration.
As a test, I rolled my migration back to the migration before the OTPAllowedToken
. I then declared my OTPAllowedToken
as inheriting from models.Model
and added the necessary attributes, effectively just copying what I already had in my Token
model. This is the only migration I have made in this branch and the error remains after making the changes just described.
So that’s where I am. My app run’s well but my test suite fails because of this issue. I don’t understand why the django-otp migrations and my local app’s tests fail, and I’d love to hear any and all ideas.
Thank you.
Cheers,
Conor