Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:e2nIEE/pandahub into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
vogt31337 committed Nov 27, 2023
2 parents 8db0b10 + a225584 commit 8d59489
Show file tree
Hide file tree
Showing 23 changed files with 804 additions and 304 deletions.
2 changes: 1 addition & 1 deletion pandahub/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.2.8"
__version__ = "0.3.0"

from pandahub.lib.PandaHub import PandaHub, PandaHubError
from pandahub.client.PandaHubClient import PandaHubClient
Expand Down
4 changes: 2 additions & 2 deletions pandahub/api/dependencies.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from fastapi import Depends

from pandahub import PandaHub
from .internal.models import UserDB
from .internal.db import User
from .internal.users import fastapi_users

current_active_user = fastapi_users.current_user(active=True)


def pandahub(user: UserDB = Depends(current_active_user)):
def pandahub(user: User = Depends(current_active_user)):
return PandaHub(user_id=str(user.id))
53 changes: 22 additions & 31 deletions pandahub/api/internal/db.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,40 @@
import asyncio
import uuid

import motor.motor_asyncio
from fastapi_users.db import MongoDBUserDatabase
from fastapi_users_db_mongodb.access_token import MongoDBAccessTokenDatabase
from beanie import Document
from fastapi_users.db import BeanieBaseUser, BeanieUserDatabase
from fastapi_users_db_beanie.access_token import (
BeanieAccessTokenDatabase,
BeanieBaseAccessToken,
)

from pandahub.api.internal import settings
from pandahub.api.internal.models import AccessToken, UserDB
from pydantic import Field

mongo_client_args = {"host": settings.MONGODB_URL, "uuidRepresentation": "standard", "connect": False}
if settings.MONGODB_USER:
mongo_client_args |= {"username": settings.MONGODB_USER, "password": settings.MONGODB_PASSWORD}

client = motor.motor_asyncio.AsyncIOMotorClient(**mongo_client_args)

client.get_io_loop = asyncio.get_event_loop

db = client["user_management"]
collection = db["users"]
access_tokens_collection = db["access_tokens"]

class User(BeanieBaseUser, Document):
# pass
# id: Optional[UUID4] = Field(alias="id")
id: uuid.UUID = Field(default_factory=uuid.uuid4)
class Settings(BeanieBaseUser.Settings):
name = "users"

async def get_user_db():
if settings.COSMOSDB_COMPAT:
yield MongoDBUserDatabaseCosmos(UserDB, collection)
else:
yield MongoDBUserDatabase(UserDB, collection)

class AccessToken(BeanieBaseAccessToken, Document):
user_id: uuid.UUID = Field(default_factory=uuid.uuid4)
class Settings(BeanieBaseAccessToken.Settings):
name = "access_tokens"

async def get_user_db():
yield BeanieUserDatabase(User)

async def get_access_token_db():
yield MongoDBAccessTokenDatabase(AccessToken, access_tokens_collection)

class MongoDBUserDatabaseCosmos(MongoDBUserDatabase):
from typing import Optional
from fastapi_users.models import UD
async def get_by_email(self, email: str) -> Optional[UD]:
await self._initialize()

user = await self.collection.find_one(
{"email": email}
)
return self.user_db_model(**user) if user else None

async def _initialize(self):
if not self.initialized:
if "email_1" not in await self.collection.index_information():
await self.collection.create_index("id", unique=True)
await self.collection.create_index("email", unique=True)
self.initialized = True
yield BeanieAccessTokenDatabase(AccessToken)
24 changes: 0 additions & 24 deletions pandahub/api/internal/models.py

This file was deleted.

14 changes: 14 additions & 0 deletions pandahub/api/internal/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import uuid

from fastapi_users import schemas
from pandahub.api.internal.settings import REGISTRATION_ADMIN_APPROVAL


class UserRead(schemas.BaseUser[uuid.UUID]):
pass

class UserCreate(schemas.BaseUserCreate):
is_active: bool = not REGISTRATION_ADMIN_APPROVAL

class UserUpdate(schemas.BaseUserUpdate):
pass
6 changes: 3 additions & 3 deletions pandahub/api/internal/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def get_secret(key, default=None):
MAIL_PASSWORD = os.getenv("MAIL_PASSWORD") or ""
MAIL_PORT = os.getenv("MAIL_PORT") or 587
MAIL_SMTP_SERVER = os.getenv("MAIL_SMTP_SERVER") or ""
MAIL_TLS = os.getenv("MAIL_TLS") or True
MAIL_SSL = os.getenv("MAIL_SSL") or False
MAIL_STARTTLS = os.getenv("MAIL_STARTTLS") or True
MAIL_SSL_TLS = os.getenv("MAIL_SSL_TLS") or False

PASSWORD_RESET_URL = os.getenv("PASSWORD_RESET_URL") or ""
EMAIL_VERIFY_URL = os.getenv("EMAIL_VERIFY_URL") or ""
Expand All @@ -48,4 +48,4 @@ def get_secret(key, default=None):
REGISTRATION_ADMIN_APPROVAL = settings_bool("REGISTRATION_ADMIN_APPROVAL", default=False)

DATATYPES_MODULE = os.getenv("DATATYPES_MODULE") or "pandahub.lib.datatypes"
COSMOSDB_COMPAT = settings_bool("COSMOSDB_COMPAT", default=False)
CREATE_INDEXES_WITH_PROJECT=settings_bool("CREATE_INDEXES_WITH_PROJECT", default=False)
4 changes: 2 additions & 2 deletions pandahub/api/internal/toolbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
MAIL_FROM=settings.MAIL_USERNAME,
MAIL_PORT=settings.MAIL_PORT,
MAIL_SERVER=settings.MAIL_SMTP_SERVER,
MAIL_TLS=settings.MAIL_TLS,
MAIL_SSL=settings.MAIL_SSL
MAIL_SSL_TLS=settings.MAIL_SSL_TLS,
MAIL_STARTTLS=settings.MAIL_STARTTLS,
)

fast_mail = FastMail(email_conf)
Expand Down
42 changes: 20 additions & 22 deletions pandahub/api/internal/users.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,51 @@
import uuid

from typing import Optional

from fastapi import Depends, Request
from fastapi_users import BaseUserManager, FastAPIUsers
from fastapi_users import BaseUserManager, FastAPIUsers, UUIDIDMixin
from fastapi_users.authentication import AuthenticationBackend, BearerTransport
from fastapi_users.authentication.strategy.db import AccessTokenDatabase, DatabaseStrategy
from fastapi_users.db import MongoDBUserDatabase
from fastapi_users.authentication.strategy.db import (
AccessTokenDatabase,
DatabaseStrategy,
)
from fastapi_users.db import BeanieUserDatabase

from ..internal import settings
from ..internal.db import get_user_db, get_access_token_db
from ..internal.models import User, UserCreate, UserDB, UserUpdate, AccessToken
from ..internal.db import get_user_db, get_access_token_db, User, AccessToken
from ..internal.toolbox import send_password_reset_mail, send_verification_email


class UserManager(BaseUserManager[UserCreate, UserDB]):
user_db_model = UserDB
class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
if settings.SECRET is None:
raise UserWarning("You must specify a SECRET in the environment variables or .env file")
raise UserWarning(
"You must specify a SECRET in the environment variables or .env file"
)
reset_password_token_secret = settings.SECRET
verification_token_secret = settings.SECRET

async def on_after_register(self, user: UserDB, request: Optional[Request] = None):
if (settings.EMAIL_VERIFICATION_REQUIRED):
async def on_after_register(self, user: User, request: Optional[Request] = None):
if settings.EMAIL_VERIFICATION_REQUIRED:
await self.request_verify(user)
print(f"User {user.id} has registered.")

async def on_after_forgot_password(
self, user: UserDB, token: str, request: Optional[Request] = None
self, user: User, token: str, request: Optional[Request] = None
):
await send_password_reset_mail(user, token)

# print(f"User {user.id} has forgot their password. Reset token: {token}")

async def on_after_request_verify(
self, user: UserDB, token: str, request: Optional[Request] = None
self, user: User, token: str, request: Optional[Request] = None
):
await send_verification_email(user, token)


# print(f"Verification requested for user {user.id}. Verification token: {token}")


async def get_user_manager(user_db: MongoDBUserDatabase = Depends(get_user_db)):
async def get_user_manager(user_db:BeanieUserDatabase = Depends(get_user_db)):
yield UserManager(user_db)


Expand All @@ -49,7 +54,7 @@ async def get_user_manager(user_db: MongoDBUserDatabase = Depends(get_user_db)):

def get_database_strategy(
access_token_db: AccessTokenDatabase[AccessToken] = Depends(get_access_token_db),
) -> DatabaseStrategy[UserCreate, UserDB, AccessToken]:
) -> DatabaseStrategy:
return DatabaseStrategy(access_token_db)


Expand All @@ -58,11 +63,4 @@ def get_database_strategy(
transport=bearer_transport,
get_strategy=get_database_strategy,
)
fastapi_users = FastAPIUsers(
get_user_manager,
[auth_backend],
User,
UserCreate,
UserUpdate,
UserDB,
)
fastapi_users = FastAPIUsers(get_user_manager, [auth_backend])
19 changes: 17 additions & 2 deletions pandahub/api/main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
from contextlib import asynccontextmanager

import uvicorn
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse

from pandahub.lib.PandaHub import PandaHubError
from pandahub.api.routers import net, projects, timeseries, users, auth, variants
from pandahub.api.internal.db import User, db, AccessToken
from beanie import init_beanie

@asynccontextmanager
async def lifespan(app: FastAPI):
await init_beanie(
database=db,
document_models=[
User,
AccessToken
],
)
yield

app = FastAPI()
app = FastAPI(lifespan=lifespan)

origins = [
"http://localhost:8080",
Expand All @@ -23,7 +38,7 @@
app.include_router(net.router)
app.include_router(projects.router)
app.include_router(timeseries.router)
app.include_router(users.router)
app.include_router(User.router)
app.include_router(auth.router)
app.include_router(variants.router)

Expand Down
19 changes: 6 additions & 13 deletions pandahub/api/routers/auth.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
from fastapi import APIRouter

from pandahub.api.internal.users import auth_backend, fastapi_users

from pandahub.api.internal.schemas import UserCreate, UserRead
from pandahub.api.internal.settings import REGISTRATION_ENABLED

router = APIRouter(
prefix="/auth",
tags=["auth"]
)
router = APIRouter(prefix="/auth", tags=["auth"])

router.include_router(
fastapi_users.get_auth_router(auth_backend)
)
router.include_router(fastapi_users.get_auth_router(auth_backend))

router.include_router(
fastapi_users.get_reset_password_router()
)
router.include_router(fastapi_users.get_reset_password_router())

if REGISTRATION_ENABLED:
router.include_router(
fastapi_users.get_register_router()
fastapi_users.get_register_router(UserRead, UserCreate),
)

router.include_router(
fastapi_users.get_verify_router()
fastapi_users.get_verify_router(UserRead),
)
Loading

0 comments on commit 8d59489

Please sign in to comment.