GithubHelp home page GithubHelp logo

fastapi-users / fastapi-users-db-sqlalchemy Goto Github PK

View Code? Open in Web Editor NEW
21.0 21.0 11.0 105 KB

FastAPI Users - Database adapter for SQLAlchemy + encode/databases

License: MIT License

Makefile 1.23% Python 98.77%
fastapi-users

fastapi-users-db-sqlalchemy's Introduction

FastAPI Users

FastAPI Users

Ready-to-use and customizable users management for FastAPI

build codecov PyPI version Downloads

All Contributors

Subscribe


Documentation: https://fastapi-users.github.io/fastapi-users/

Source Code: https://github.com/fastapi-users/fastapi-users


Add quickly a registration and authentication system to your FastAPI project. FastAPI Users is designed to be as customizable and adaptable as possible.

Features

  • Extensible base user model
  • Ready-to-use register, login, reset password and verify e-mail routes
  • Ready-to-use social OAuth2 login flow
  • Dependency callables to inject current user in route
  • Pluggable password validation
  • Customizable database backend
  • Multiple customizable authentication backends
    • Transports: Authorization header, Cookie
    • Strategies: JWT, Database, Redis
  • Full OpenAPI schema support, even with several authentication backends

In a hurry? Discover Fief, the open-source authentication platform

Fief

Fief

Implementing registration, login, social auth is hard and painful. We know it. With our highly secure and open-source users management platform, you can focus on your app while staying in control of your users data.

  • Based on FastAPI Users!
  • Open-source: self-host it for free
  • Pre-built login and registration pages: clean and fast authentication so you don't have to do it yourself
  • Official Python client with built-in FastAPI integration

It's free!

Contributors and sponsors ✨☕️

Thanks goes to these wonderful people (emoji key):

François Voron
François Voron

🚧
Paolo Dina
Paolo Dina

💵 💻
Dmytro Ohorodnik
Dmytro Ohorodnik

🐛
Matthew D. Scholefield
Matthew D. Scholefield

🐛 💻
roywes
roywes

🐛 💻
Satwik Kansal
Satwik Kansal

📖
Edd Salkield
Edd Salkield

💻 📖
mark-todd
mark-todd

💻 📖
lill74
lill74

🐛 💻 📖
SelfhostedPro
SelfhostedPro

🛡️ 💻
Oskar Gmerek
Oskar Gmerek

📖
Martin Collado
Martin Collado

🐛 💻
Eric Lopes
Eric Lopes

📖 🛡️
Beau Breon
Beau Breon

💻
Niyas Mohammed
Niyas Mohammed

📖
prostomarkeloff
prostomarkeloff

📖 💻
Marius Mézerette
Marius Mézerette

🐛 🤔
Nickolas Grigoriadis
Nickolas Grigoriadis

🐛
Open Data Coder
Open Data Coder

🤔
Mohammed Alshehri
Mohammed Alshehri

🤔
Tyler Renelle
Tyler Renelle

🤔
collerek
collerek

💻
Robert Bracco
Robert Bracco

💵
Augusto Herrmann
Augusto Herrmann

📖
Smithybrewer
Smithybrewer

🐛
silllli
silllli

📖
alexferrari88
alexferrari88

💵
sandalwoodbox
sandalwoodbox

🐛 📖
Vlad Hoi
Vlad Hoi

📖
Joe Nudell
Joe Nudell

🐛
Ben
Ben

💻
BoYanZh
BoYanZh

📖
David Brochart
David Brochart

📖 💻
Daan Beverdam
Daan Beverdam

💻
Stéphane Raimbault
Stéphane Raimbault

⚠️ 🐛
Sondre Lillebø Gundersen
Sondre Lillebø Gundersen

📖
Maxim
Maxim

📖 🐛
scottdavort
scottdavort

💵
John Dukewich
John Dukewich

📖
Yasser Tahiri
Yasser Tahiri

💻
Brandon H. Goding
Brandon H. Goding

💻 📖
PovilasK
PovilasK

💻
Just van den Broecke
Just van den Broecke

💵
jakemanger
jakemanger

🐛 💻
Ikko Ashimine
Ikko Ashimine

💻
Matyáš Richter
Matyáš Richter

💻
Hazedd
Hazedd

🐛 📖
Luis Roel
Luis Roel

💵
Alexandr Makurin
Alexandr Makurin

💻 🐛
Leon Thurner
Leon Thurner

📖
Goran Mekić
Goran Mekić

📦
Gaganpreet
Gaganpreet

💻
Joe Taylor
Joe Taylor

💻
Richard Friberg
Richard Friberg

🐛
Kenton Parton
Kenton Parton

💵
Adrian Ciołek
Adrian Ciołek

🐛
⭕Alexander Rymdeko-Harvey
⭕Alexander Rymdeko-Harvey

📖
schwannden
schwannden

🚧 💻
Jimmy Angel Pérez Díaz
Jimmy Angel Pérez Díaz

🛡️
Austin Orr
Austin Orr

🚧
Carlo Eugster
Carlo Eugster

🛡️
Vittorio Zamboni
Vittorio Zamboni

💻
Andrey
Andrey

📖
Can H. Tartanoglu
Can H. Tartanoglu

🐛
Filipe Nascimento
Filipe Nascimento

🛡️
dudulu
dudulu

💵 🐛 💬
Toni Alatalo
Toni Alatalo

💻 📖
Börge Kiss
Börge Kiss

📖
Guilherme Caminha
Guilherme Caminha

📖
Téva KRIEF
Téva KRIEF

💻
Essa Alshammri
Essa Alshammri

📖
0xJan
0xJan

🐛
Justin Thomas
Justin Thomas

💻
Adam Israel
Adam Israel

💻
Nerixjk
Nerixjk

🐛 💻
Mike Fotinakis
Mike Fotinakis

💻 🐛
lifengmds
lifengmds

💵
raindata5
raindata5

📖
Mark Donnelly
Mark Donnelly

📖

This project follows the all-contributors specification. Contributions of any kind welcome!

Development

Setup environment

We use Hatch to manage the development environment and production build. Ensure it's installed on your system.

Run unit tests

You can run all the tests with:

hatch run test:test

Format the code

Execute the following command to apply linting and check typing:

hatch run lint

Serve the documentation

You can serve the documentation locally with the following command:

hatch run docs

The documentation will be available on http://localhost:8000.

License

This project is licensed under the terms of the MIT license.

fastapi-users-db-sqlalchemy's People

Contributors

dipwave avatar frankie567 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

fastapi-users-db-sqlalchemy's Issues

User returned from register endpoint actually is the same as the user passed

Describe the bug

User create endpoint returns user that have been sent, not the user that was created at database.

To Reproduce

Just add custom column to User database model and set it's server_default or default value.
When creating new user don't set that columns' value. Than in response this value will not have default value but sent value.

Simple reproducable example.

Database User model:

class User(Base, SQLAlchemyBaseUserTable):
    """Table for storing users"""

    created_at = Column(DateTime, default=datetime.now, nullable=False)

Pydantic User schemas:

class User(models.BaseUser):
    """User fetch pydantic model"""

    created_at: datetime | None  # None is to create users without Pydantic's validation exception


class UserCreate(models.BaseUserCreate):
    """User's creation pydantic scheme"""


class UserUpdate(models.BaseUserUpdate):
    """User's update pydantic scheme"""


class UserDB(User, models.BaseUserDB):
    """User stored in DB pydantic model"""

Than add registration router and test.

Request and response examples

Request:

{
  "email": "[email protected]",
  "password": "some-password",
  "is_active": true,
  "is_superuser": true,
  "is_verified": true
}

Response:

{
  "id": "ecdd896e-2c76-42ba-b374-d5281e588e87",
  "email": "[email protected]",
  "is_active": true,
  "is_superuser": false,
  "is_verified": false,
  "created_at": null
}

Expected behavior

Successful user creation with automatically set created_at returned from registration endpoint.

For above request expected response is:

{
  "id": "ecdd896e-2c76-42ba-b374-d5281e588e87",
  "email": "[email protected]",
  "is_active": true,
  "is_superuser": false,
  "is_verified": false,
  "created_at": "2022-01-16T00:16:22.626191"
}

Configuration

  • Python version : 3.10.1
  • FastAPI version : 0.71.0
  • FastAPI Users version : 9.2.2

FastAPI Users configuration

Standard configuration from docs

_get_user() fails when no user in db

    async def _get_user(self, statement: Select) -> Optional[UP]:
        results = await self.session.execute(statement)
        user = results.first()

fails at .first() when there is no records in user table and then results is None

can guid impl be changed?

Hi there,
While testing fastapi-users [sqlalchemy] along with sqladmin I bumped on this

  File "/mnt/1T/work/user-management/.venv/lib/python3.8/site-packages/sqladmin/forms.py", line 78, in get_converter
    raise Exception(  # pragma: nocover
Exception: Could not find field converter for column id (<class 'fastapi_users_db_sqlalchemy.guid.GUID'>).

I understand that sqladmin does not know how to handle this since it does not have converter for UUIDChar (https://github.com/aminalaee/sqladmin/blob/main/sqladmin/forms.py#L78). It does handle UUID though.

This is provoqued by the following line at fastapi-users-db-sqlalchemy/

.venv/lib/python3.8/site-packages/fastapi_users_db_sqlalchemy/guid.py
image

Is impl = UUIDChar a "standard" implementation or it should be named impl = UUID instead?

Otherwise, any way can I overwrite this?

The email index is not used by `get_by_email()` method

Describe the bug

An index is created on the email field:
https://github.com/fastapi-users/fastapi-users-db-sqlalchemy/blob/main/fastapi_users_db_sqlalchemy/__init__.py#L61

but the index can't be used by the get_by_email() method because the filtering uses a function on the SQL field.

To Reproduce

explain analyze 
SELECT auth_user.hashed_password, auth_user.is_active, auth_user.is_superuser, auth_user.is_verified, auth_user.id, auth_user.email, auth_user.first_name, auth_user.last_name 
FROM auth_user 
WHERE lower(auth_user.email) = lower('[email protected]');
Seq Scan on auth_user  (cost=0.00..10.90 rows=1 width=1245) (actual time=0.030..0.030 rows=0 loops=1)
   Filter: (lower((email)::text) = '[email protected]'::text)

Sequential scan is used instead of index scan.

Expected behavior

explain analyze 
SELECT auth_user.hashed_password, auth_user.is_active, auth_user.is_superuser, auth_user.is_verified, auth_user.id, auth_user.email, auth_user.first_name, auth_user.last_name 
FROM auth_user 
WHERE auth_user.email = lower('[email protected]');
Index Scan using ix_auth_user_email on auth_user  (cost=0.14..2.36 rows=1 width=1245) (actual time=0.044..0.045 rows=0 loops=1)
   Index Cond: ((email)::text = '[email protected]'::text)

There is several ways to fix the issue:

  1. use CIText extension but it's not standard in SQLAlchemy (https://pypi.org/project/sqlalchemy-citext/).
  2. create a functional index: CREATE INDEX ix_auth_user ON auth_user (lower(email) text_pattern_ops);
  3. store email in lower case (my favorite even though on rare occasions, an outdated server or program might not interpret the capitalization correctly).

I can provide a PR when we'll agree on a solution.

Configuration

  • FastAPI Users version : 0.7

SQLAlchemy ORM implementation repository needed 🗡️ Provided draft implementation

Hi!

Thanks for your great work!. As a short background, I made small minimal repo with template for async starter for FastAPI (based on official template) and got a question about including FastAPI Users. I like async style of 1.4 SQLAlchemy ORM and prefer it over whatsoever databases.

But in the docs:
image

Here's the working adapter for SQLAlchemy ORM: https://github.com/rafsaf/fastapi_users_db_sqlalchemy_orm

I tried to implement it first before creating an issue, seems to be working just fine, it's not very much different from this repo implementation, I of course changed pytest fixtures (sqlalchemy orm + aiosqlite instead of databases) but the tests logic is the same. Disclaimer: I didn't spend a lot of time on it, review is a must (It's only a piece of code, not a full repo setup too)

The docs like here for new adapter may look like that

import asyncio

from fastapi_users.db import SQLAlchemyORMBaseUserTable, SQLAlchemyORMUserDatabase
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base
from sqlalchemy.orm.session import sessionmaker

from .models import UserDB

DATABASE_URL = "sqlite+aiosqlite:///./test.db"

Base: DeclarativeMeta = declarative_base()

class UserTable(Base, SQLAlchemyORMBaseUserTable):
    pass

async_engine = create_async_engine(DATABASE_URL, pool_pre_ping=True)
async_session = sessionmaker(async_engine, expire_on_commit=False, class_=AsyncSession)


async def setup():
    async with async_engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

asyncio.run(setup())


async def get_user_db():
    async with async_session() as session:
        yield SQLAlchemyORMUserDatabase(UserDB, session, UserTable)

I'm waiting for your opinion about moving/creating new adapter in another repository so this topic can be continued :) Thanks a lot 👍

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.