Skip to content

chore(backend): resolve #225 by upgrading sqlalchemy to 2.1 and bcrypt to 5.0 - #307

Open
mustafa-arda wants to merge 2 commits into
masterfrom
chore/225-sqlalchemy-bcrypt
Open

mustafa-arda wants to merge 2 commits into
masterfrom
chore/225-sqlalchemy-bcrypt

Conversation

@mustafa-arda

Copy link
Copy Markdown
Contributor

This PR addresses the major version bumps for the backend database and authentication libraries outlined in #225.

  • SQLAlchemy 2.1: explicitly pins the postgresql+psycopg2:// driver in all DATABASE_URL configurations (Docker compose, workflows, and .env.example) to prevent DriverNotFoundError, as 2.1 defaults to psycopg (v3).

  • bcrypt 5.0.0: Patches get_password_hash and verify_password in config.py to explicitly truncate passwords to 72 bytes. This preserves the v4.x.x legacy behavior, ensuring existing users are not locked out and preventing the new ValueError crash on long passwords.

Validation: Full unit and integration test suite passed locally against both SQLite and PostgreSQL. Coverage maintained at 85.28%.

@lucaosti lucaosti left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is close. Trial merge with master: 1088 backend tests pass (coverage 85.25%), mypy is clean, and CI is green with Postgres. I also checked that a bcrypt 4 hash of a password over 72 bytes still verifies, that a malformed hash returns False, and that multibyte passwords work. Truncating to 72 bytes keeps the old behaviour, good.

To fix before merge

  • Old URLs crash on startup. With SQLAlchemy 2.1, create_engine("postgresql://...") raises ModuleNotFoundError: No module named 'psycopg'. Anyone with a .env or a deployment still using the old scheme will see the backend fail to start, and README.md:115 still tells people to write postgresql://. Please update the README, and normalize the scheme in config.py (postgresql:// to postgresql+psycopg2://) so existing setups keep working.

Minor

  • config.py uses double quotes everywhere else. The new lines use single quotes.
  • test_bcrypt_upgrade.py has trailing whitespace and no blank lines between the import and the test. It could also live in the existing auth tests.
  • Five files gain a trailing blank line.

- Bump sqlalchemy to >=2.1.0 and bcrypt to >=5.0.0.
- Append +psycopg2 to all postgresql:// connections to prevent SQLAlchemy 2.1 DriverNotFoundError.
- Explicitly truncate passwords to 72 bytes in get_password_hash and verify_password to preserve backward compatibility and prevent 500 errors.
- Pass unit and integration tests under SQLite and Postgres.
- Normalize postgresql:// scheme to psycopg2 in config.py using double quotes.
- Update README.md database URL scheme.
- Fix whitespace and trailing lines in test_bcrypt_upgrade.py.
- Sync frontend lockfile.

@lucaosti lucaosti left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the follow-up, Arda, and for updating the database URLs everywhere: README, both .env.example files, docker-compose and CI all use postgresql+psycopg2:// now, and the suite and mypy pass locally. I re-checked bcrypt as well: hashes created with 4.x for long passwords still verify under 5.0.

One thing is still missing before we can merge. The commit message mentions normalizing the scheme in config.py, but that change didn't make it into the push: afe81f9 only touches README.md, the frontend lockfile and the test, and config.py still passes DATABASE_URL through as is. With SQLAlchemy 2.1, anyone whose .env or deployment still says postgresql:// gets ModuleNotFoundError: No module named 'psycopg' at startup. Could you add it in Settings, replacing only the scheme prefix, with a small test? Something like:

if DATABASE_URL.startswith("postgresql://"):
    DATABASE_URL = "postgresql+psycopg2://" + DATABASE_URL[len("postgresql://"):]

Smaller things while you're there:

  • .github/dependabot.yml still ignores sqlalchemy >=2.1 until #225. This PR resolves #225, so please remove that rule.
  • apps/web/package-lock.json picked up unrelated changes (a typescript-eslint bump and npm metadata). Please drop it so the PR stays backend-only.
  • get_password_hash and verify_password still use 'utf-8'; the rest of config.py uses double quotes.
  • The five config files still end with an extra blank line.
  • The new test needs two blank lines before the function; it could also live in tests/unit/test_jwt.py next to the other password tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants