Skip to content

Commit

Permalink
Merge pull request #215 from SelfhostedPro/auth_rewrite
Browse files Browse the repository at this point in the history
Auth rewrite
  • Loading branch information
SelfhostedPro authored Jan 6, 2021
2 parents 5ee97ed + 345ac0e commit 141b4b9
Show file tree
Hide file tree
Showing 39 changed files with 2,610 additions and 1,889 deletions.
5 changes: 3 additions & 2 deletions backend/alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@

from api.db import models
from api.settings import Settings
from api.auth import Base

print("--- MODELS ---")
print(models)
# Combine metadata from auth and containers/templates
combined_meta_data = MetaData()
for declarative_base in [models.Base, Base]:
for declarative_base in [models.Base]:
for (table_name, table) in declarative_base.metadata.tables.items():
combined_meta_data._add_table(table_name, table.schema, table)

Expand Down
8 changes: 3 additions & 5 deletions backend/api/actions/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,18 +297,16 @@ def check_self_update():
yacht = dclient.containers.get(yacht_id)
except Exception as exc:
print(exc)
if hasattr(exc, 'response') and exc.response.status_code == 404:
if hasattr(exc, "response") and exc.response.status_code == 404:
raise HTTPException(
status_code=exc.response.status_code,
detail="Unable to get Yacht container ID",
)
elif hasattr(exc, 'response'):
elif hasattr(exc, "response"):
raise HTTPException(
status_code=exc.response.status_code, detail=exc.explanation
)
else:
raise HTTPException(
status_code=400, detail=exc.args
)
raise HTTPException(status_code=400, detail=exc.args)

return _update_check(yacht.image.tags[0])
4 changes: 4 additions & 0 deletions backend/api/actions/compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,18 @@ def get_compose(name):
networks.append(network)
for service in loaded_compose.get("services"):
services[service] = loaded_compose["services"][service]
_content = open(file)
content = _content.read()
compose_object = {
"name": project,
"path": file,
"version": loaded_compose["version"],
"services": services,
"volumes": volumes,
"networks": networks,
"content": content,
}
print(compose_object["content"])
return compose_object
else:
raise HTTPException(404, "Project " + name + " not found")
Expand Down
2 changes: 1 addition & 1 deletion backend/api/actions/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def get_networks():
if attrs.get("inUse") == None:
attrs.update({"inUse": False})
if attrs.get("Labels", {}).get("com.docker.compose.project"):
attrs.update({'Project': attrs['Labels']['com.docker.compose.project']})
attrs.update({"Project": attrs["Labels"]["com.docker.compose.project"]})
network_list.append(attrs)
return network_list

Expand Down
92 changes: 19 additions & 73 deletions backend/api/auth/auth.py
Original file line number Diff line number Diff line change
@@ -1,88 +1,34 @@
import databases
import sqlalchemy
from fastapi import FastAPI
from fastapi_users import models
from fastapi_users.db import SQLAlchemyBaseUserTable, SQLAlchemyUserDatabase
from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base
from fastapi_users.db import BaseUserDatabase
from fastapi_users.authentication import CookieAuthentication
from fastapi_users import FastAPIUsers
from fastapi_users.password import get_password_hash
from typing import Tuple

from ..settings import Settings

settings = Settings()

SECRET = settings.SECRET_KEY

auth_backends = []

cookie_authentication = CookieAuthentication(
secret=SECRET, lifetime_seconds=3600, cookie_secure=False
)

auth_backends.append(cookie_authentication)


class User(models.BaseUser):
pass


class UserCreate(models.BaseUserCreate):
pass


class UserUpdate(User, models.BaseUserUpdate):
pass
from fastapi import Depends
from fastapi_jwt_auth import AuthJWT

from passlib import pwd
from passlib.context import CryptContext

class UserDB(User, models.BaseUserDB):
pass
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")


DATABASE_URL = settings.SQLALCHEMY_DATABASE_URI

database = databases.Database(DATABASE_URL)

Base: DeclarativeMeta = declarative_base()


class UserTable(Base, SQLAlchemyBaseUserTable):
pass
settings = Settings()


engine = sqlalchemy.create_engine(
DATABASE_URL, connect_args={"check_same_thread": False}
)
def verify_and_update_password(
plain_password: str, hashed_password: str
) -> Tuple[bool, str]:
return pwd_context.verify_and_update(plain_password, hashed_password)

Base.metadata.create_all(engine)

users = UserTable.__table__
user_db = SQLAlchemyUserDatabase(UserDB, database, users)
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)

app = FastAPI()

fastapi_users = FastAPIUsers(
user_db, auth_backends, User, UserCreate, UserUpdate, UserDB,
)
def generate_password() -> str:
return pwd.genword()


async def fake_get_active_user():
DISABLE_AUTH = settings.DISABLE_AUTH
if DISABLE_AUTH == "True":
return True
def auth_check(Authorize):
if settings.DISABLE_AUTH == "True":
return
else:
await fastapi_users.get_current_active_user()


if settings.DISABLE_AUTH != "True":
get_active_user = fastapi_users.get_current_active_user
else:
get_active_user = fake_get_active_user
# get_active_user = fastapi_users.get_current_active_user
get_auth_router = fastapi_users.get_auth_router
get_password_hash = get_password_hash


async def user_create(UD):
await fastapi_users.db.create(UD)
return Authorize.jwt_required()
1 change: 1 addition & 0 deletions backend/api/db/crud/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .templates import *
from .settings import *
from .users import *
51 changes: 51 additions & 0 deletions backend/api/db/crud/users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from sqlalchemy.orm import Session
from passlib.context import CryptContext
from . import models, schemas
from fastapi.exceptions import HTTPException

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")


def get_user(db: Session, user_id: int):
return db.query(models.User).filter(models.User.id == user_id).first()


def get_user_by_name(db: Session, username: str):
return db.query(models.User).filter(models.User.username == username).first()


def get_users(db: Session, skip: int = 0, limit: int = 100):
return db.query(models.User).offset(skip).limit(limit).all()


def create_user(db: Session, user: schemas.UserCreate):
_hashed_password = get_password_hash(user.password)
db_user = models.User(username=user.username, hashed_password=_hashed_password)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user


def update_user(db: Session, user: schemas.UserCreate, current_user):
_hashed_password = get_password_hash(user.password)
_user = get_user_by_name(db=db, username=current_user)
if _user and _user.is_active:
print(_user)
_user.username = user.username
_user.hashed_password = _hashed_password
try:
db.add(_user)
db.commit()
db.refresh(_user)
except Exception as exc:
raise HTTPException(status_code=400, detail=exc)
return _user


def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
return pwd_context.hash(password)
12 changes: 11 additions & 1 deletion backend/api/db/models/users.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from ..database import Base
from fastapi_users.db import SQLAlchemyBaseUserTable


class User(Base):
__tablename__ = "user"

id = Column(Integer, primary_key=True, index=True)
username = Column("email", String, unique=True, index=True, nullable=False)
hashed_password = Column(String(length=72), nullable=False)
is_active = Column(Boolean, default=True, nullable=False)
is_superuser = Column(Boolean, default=False, nullable=False)
2 changes: 2 additions & 0 deletions backend/api/db/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
from .apps import *
from .templates import *
from .users import *
from .compose import *
14 changes: 14 additions & 0 deletions backend/api/db/schemas/compose.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pydantic import BaseModel
from typing import Any, Optional


class Compose(BaseModel):
name: str


class ComposeWrite(Compose):
content: Optional[Any]


class ComposeRead(ComposeWrite):
path: str
18 changes: 17 additions & 1 deletion backend/api/db/schemas/users.py
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
from fastapi_users import models
from pydantic import BaseModel


class UserBase(BaseModel):
username: str


class UserCreate(UserBase):
password: str


class User(UserBase):
id: int
is_active: bool

class Config:
orm_mode = True
Loading

0 comments on commit 141b4b9

Please sign in to comment.