mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
wip: initiate user creation
This commit is contained in:
parent
afaf1d6dfe
commit
732b14866c
10 changed files with 126 additions and 11 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request
|
||||||
from config.config import LearnHouseConfig, get_learnhouse_config
|
from config.config import LearnHouseConfig, get_learnhouse_config
|
||||||
from src.core.events.events import shutdown_app, startup_app
|
from src.core.events.events import shutdown_app, startup_app
|
||||||
from src.router import v1_router
|
from src.router import v1_router, rewrite
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
@ -60,6 +60,7 @@ app.mount("/content", StaticFiles(directory="content"), name="content")
|
||||||
|
|
||||||
# Global Routes
|
# Global Routes
|
||||||
app.include_router(v1_router)
|
app.include_router(v1_router)
|
||||||
|
app.include_router(rewrite)
|
||||||
|
|
||||||
# General Routes
|
# General Routes
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
fastapi==0.101.1
|
fastapi==0.101.1
|
||||||
pydantic>=1.8.0,<2.0.0
|
pydantic>=1.8.0,<2.0.0
|
||||||
|
sqlmodel==0.0.10
|
||||||
uvicorn==0.23.2
|
uvicorn==0.23.2
|
||||||
pymongo==4.3.3
|
pymongo==4.3.3
|
||||||
motor==3.1.1
|
motor==3.1.1
|
||||||
|
psycopg2
|
||||||
python-multipart
|
python-multipart
|
||||||
boto3
|
boto3
|
||||||
botocore
|
botocore
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,27 @@
|
||||||
import logging
|
import logging
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
import motor.motor_asyncio
|
import motor.motor_asyncio
|
||||||
|
from sqlmodel import Field, SQLModel, Session, create_engine
|
||||||
|
from src.rewrite.services.db import users
|
||||||
|
|
||||||
|
engine = create_engine('postgresql://learnhouse:learnhouse@db:5432/learnhouse', echo=True)
|
||||||
|
SQLModel.metadata.create_all(engine)
|
||||||
|
|
||||||
async def connect_to_db(app: FastAPI):
|
async def connect_to_db(app: FastAPI):
|
||||||
logging.info("Connecting to database...")
|
app.db_engine = engine # type: ignore
|
||||||
try:
|
logging.info("LearnHouse database has been started.")
|
||||||
app.mongodb_client = motor.motor_asyncio.AsyncIOMotorClient( # type: ignore
|
|
||||||
app.learnhouse_config.database_config.mongodb_connection_string) # type: ignore
|
|
||||||
app.db = app.mongodb_client["learnhouse"] # type: ignore
|
|
||||||
logging.info("Connected to database!")
|
|
||||||
except Exception as e:
|
|
||||||
logging.error("Failed to connect to database!")
|
|
||||||
logging.error(e)
|
|
||||||
|
|
||||||
|
|
||||||
|
SQLModel.metadata.create_all(engine)
|
||||||
|
|
||||||
|
# mongodb
|
||||||
|
app.mongodb_client = motor.motor_asyncio.AsyncIOMotorClient( # type: ignore
|
||||||
|
app.learnhouse_config.database_config.mongodb_connection_string) # type: ignore
|
||||||
|
app.db = app.mongodb_client["learnhouse"] # type: ignore
|
||||||
|
|
||||||
|
def get_db_session():
|
||||||
|
with Session(engine) as session:
|
||||||
|
yield session
|
||||||
|
|
||||||
async def close_database(app: FastAPI):
|
async def close_database(app: FastAPI):
|
||||||
app.mongodb_client.close() # type: ignore
|
app.mongodb_client.close() # type: ignore
|
||||||
|
|
|
||||||
0
apps/api/src/rewrite/__init__.py
Normal file
0
apps/api/src/rewrite/__init__.py
Normal file
23
apps/api/src/rewrite/routers/users.py
Normal file
23
apps/api/src/rewrite/routers/users.py
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
from fastapi import APIRouter, Depends, Request
|
||||||
|
from sqlmodel import Session
|
||||||
|
from src.core.events.database import get_db_session
|
||||||
|
|
||||||
|
from src.rewrite.services.db.users import UserCreate, UserRead
|
||||||
|
from src.rewrite.services.users.users import create_user
|
||||||
|
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/", response_model=UserRead, tags=["users"])
|
||||||
|
async def api_create_user(
|
||||||
|
*,
|
||||||
|
request: Request,
|
||||||
|
db_session: Session = Depends(get_db_session),
|
||||||
|
user_object: UserCreate,
|
||||||
|
org_slug: str
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Create new user
|
||||||
|
"""
|
||||||
|
return await create_user(request, db_session, None, user_object, org_slug)
|
||||||
0
apps/api/src/rewrite/services/db/__init__.py
Normal file
0
apps/api/src/rewrite/services/db/__init__.py
Normal file
32
apps/api/src/rewrite/services/db/users.py
Normal file
32
apps/api/src/rewrite/services/db/users.py
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
from typing import Optional
|
||||||
|
from sqlmodel import Field, Session, SQLModel, create_engine, select
|
||||||
|
|
||||||
|
|
||||||
|
class UserBase(SQLModel):
|
||||||
|
username: str
|
||||||
|
first_name: str
|
||||||
|
last_name: str
|
||||||
|
email: str
|
||||||
|
avatar_image: Optional[str] = ""
|
||||||
|
bio: Optional[str] = ""
|
||||||
|
|
||||||
|
|
||||||
|
class UserCreate(UserBase):
|
||||||
|
password: str
|
||||||
|
|
||||||
|
|
||||||
|
class UserUpdate(UserBase):
|
||||||
|
password: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class UserRead(UserBase):
|
||||||
|
id: int
|
||||||
|
|
||||||
|
|
||||||
|
class User(UserBase, table=True):
|
||||||
|
id: Optional[int] = Field(default=None, primary_key=True)
|
||||||
|
password: str = ""
|
||||||
|
user_uuid: str = ""
|
||||||
|
email_verified: bool = False
|
||||||
|
creation_date: str = ""
|
||||||
|
update_date: str = ""
|
||||||
43
apps/api/src/rewrite/services/users/users.py
Normal file
43
apps/api/src/rewrite/services/users/users.py
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
from datetime import datetime
|
||||||
|
from uuid import uuid4
|
||||||
|
from fastapi import Depends, Request
|
||||||
|
from sqlmodel import Session
|
||||||
|
from src.rewrite.services.db.users import User, UserCreate
|
||||||
|
from src.security.security import security_hash_password
|
||||||
|
from src.services.users.schemas.users import PublicUser
|
||||||
|
|
||||||
|
|
||||||
|
async def create_user(
|
||||||
|
request: Request,
|
||||||
|
db_session: Session,
|
||||||
|
current_user: PublicUser | None,
|
||||||
|
user_object: UserCreate,
|
||||||
|
org_slug: str,
|
||||||
|
):
|
||||||
|
user = User.from_orm(user_object)
|
||||||
|
|
||||||
|
# Complete the user object
|
||||||
|
user.user_uuid = f"user_{uuid4()}"
|
||||||
|
user.password = await security_hash_password(user_object.password)
|
||||||
|
user.email_verified = False
|
||||||
|
user.creation_date = str(datetime.now())
|
||||||
|
user.update_date = str(datetime.now())
|
||||||
|
|
||||||
|
# Verifications
|
||||||
|
#todo: add username uniqueness verification
|
||||||
|
#todo: add email uniqueness verification
|
||||||
|
|
||||||
|
|
||||||
|
#todo: add user to org as member if org is not None
|
||||||
|
|
||||||
|
# Exclude unset values
|
||||||
|
user_data = user.dict(exclude_unset=True)
|
||||||
|
for key, value in user_data.items():
|
||||||
|
setattr(user, key, value)
|
||||||
|
|
||||||
|
# Add user to database
|
||||||
|
db_session.add(user)
|
||||||
|
db_session.commit()
|
||||||
|
db_session.refresh(user)
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
from fastapi import APIRouter, Depends
|
from fastapi import APIRouter, Depends
|
||||||
|
from src import rewrite
|
||||||
from src.routers import blocks, dev, trail, users, auth, orgs, roles
|
from src.routers import blocks, dev, trail, users, auth, orgs, roles
|
||||||
|
from src.rewrite.routers import users as rw_users
|
||||||
from src.routers.courses import chapters, collections, courses, activities
|
from src.routers.courses import chapters, collections, courses, activities
|
||||||
from src.routers.install import install
|
from src.routers.install import install
|
||||||
from src.services.dev.dev import isDevModeEnabledOrRaise
|
from src.services.dev.dev import isDevModeEnabledOrRaise
|
||||||
|
|
@ -7,6 +9,7 @@ from src.services.install.install import isInstallModeEnabled
|
||||||
|
|
||||||
|
|
||||||
v1_router = APIRouter(prefix="/api/v1")
|
v1_router = APIRouter(prefix="/api/v1")
|
||||||
|
rewrite = APIRouter(prefix="/api/rewrite")
|
||||||
|
|
||||||
|
|
||||||
# API Routes
|
# API Routes
|
||||||
|
|
@ -35,3 +38,6 @@ v1_router.include_router(
|
||||||
tags=["install"],
|
tags=["install"],
|
||||||
dependencies=[Depends(isInstallModeEnabled)],
|
dependencies=[Depends(isInstallModeEnabled)],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Rewrite Routes
|
||||||
|
rewrite.include_router(rw_users.router, prefix="/users", tags=["users"])
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ services:
|
||||||
- .:/usr/learnhouse
|
- .:/usr/learnhouse
|
||||||
environment:
|
environment:
|
||||||
- LEARNHOUSE_COOKIE_DOMAIN=.localhost
|
- LEARNHOUSE_COOKIE_DOMAIN=.localhost
|
||||||
postgresql:
|
db:
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue