Skip to content

Commit

Permalink
Added: basic current user functionality (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
signebedi committed Mar 28, 2024
1 parent acd197d commit 228c51b
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 5 deletions.
71 changes: 68 additions & 3 deletions libreforms_fastapi/app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import re, os, json, tempfile, logging, sys, asyncio
import re, os, json, tempfile, logging, sys, asyncio, jwt
from datetime import datetime, timedelta
from typing import Dict, Optional
from typing import Dict, Optional, Annotated
from markupsafe import escape
from bson import ObjectId

Expand All @@ -16,7 +16,11 @@
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.security import APIKeyHeader
from fastapi.security import (
APIKeyHeader,
OAuth2PasswordBearer,
OAuth2PasswordRequestForm,
)

from sqlalchemy import (
create_engine,
Expand Down Expand Up @@ -121,6 +125,36 @@
},
)

# Here we instantiate our oauth object, see
# https://github.com/signebedi/libreforms-fastapi/issues/19
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/auth/login")

async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
try:
payload = jwt.decode(token, config.SECRET_KEY, algorithms=['HS256'])
with SessionLocal() as session:
user = session.query(User).filter_by(id=payload.get("id", None)).first()

except:
raise HTTPException(
status_code=401,
detail="Incorrect username or password"
)

if not user:
raise HTTPException(
status_code=401,
detail="Incorrect username or password"
)

if not user.active:
raise HTTPException(
status_code=401,
detail="Unable to login at this time"
)

return user


# Set up logger, see https://github.com/signebedi/libreforms-fastapi/issues/26,
# again using a factory pattern defined in libreforms_fastapi.utis.logging.
Expand Down Expand Up @@ -1469,6 +1503,37 @@ async def api_auth_get(
# @app.patch("/api/auth/forgot_password/{single_use_token}")
# async def api_auth_forgot_password_confirm(user_request: CreateUserRequest, session: SessionLocal = Depends(get_db)):

# Login, uses OAUTH and current_user functionality, see
# https://github.com/signebedi/libreforms-fastapi/issues/19
@app.post('/api/auth/login')
async def api_auth_login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]):
with SessionLocal() as session:
user = session.query(User).filter_by(username=form_data.username.lower()).first()

if not user:
raise HTTPException(status_code=400, detail="Incorrect username or password")

if not check_password_hash(user.password, form_data.password):
raise HTTPException(status_code=400, detail="Incorrect username or password")

user_dict = {
"id": user.id,
"email": user.email,
"username": user.username,
"active": user.active,
}

token = jwt.encode(user_dict, config.SECRET_KEY)

return {"access_token": token, "token_type": "bearer"}


# @app.get("/users/me")
# async def read_users_me(
# current_user: Annotated[User, Depends(get_current_user)]
# ):
# return current_user



##########################
Expand Down
4 changes: 2 additions & 2 deletions libreforms_fastapi/utils/sqlalchemy_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
JSON,
LargeBinary,
)
from sqlalchemy.orm import relationship, declarative_base
from sqlalchemy.inspection import inspect
from sqlalchemy.orm import relationship, declarative_base, class_mapper

from sqlalchemy_signing import create_signing_class

Expand Down Expand Up @@ -108,7 +109,6 @@ def compile_permissions(self) -> dict:
return permissions_dict



# Allow admins to define custom groups, see
# https://github.com/signebedi/libreforms-fastapi/issues/22
class Group(Base):
Expand Down
2 changes: 2 additions & 0 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ fuzzywuzzy<1.0.0
Jinja2<4.0.0
passlib[bcrypt]<2.0.0
pydantic-settings<3.0.0
PyJWT<3.0.0
pymongo<5.0.0
python-Levenshtein<1.0.0
python-multipart<1.0.0
SQLAlchemy<3.0.0
sqlalchemy-signing<2.0.0
tinydb<5.0.0
Expand Down
2 changes: 2 additions & 0 deletions requirements/latest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ fuzzywuzzy
Jinja2
passlib[bcrypt]
pydantic-settings
PyJWT
pymongo
python-Levenshtein
python-multipart
SQLAlchemy
sqlalchemy-signing
tinydb
Expand Down

0 comments on commit 228c51b

Please sign in to comment.