Dump changes

This commit is contained in:
Andrey Chervyakov 2021-10-09 21:33:03 +06:00
parent b49c6ced26
commit a4b572dcc7
40 changed files with 186 additions and 37 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,6 @@
from app.user.model import User
def has_role(name: str, user: User):
if user.role.name != name:
raise Exception()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -10,8 +10,8 @@ from app.auth.dto import Credentials
from app.config import config
from app.user.service import get_user_by_username, passwords_match
JWT_SECRET = config["CGNO_ID_JWT_SECRET"]
JWT_ISSUER = "Energia"
JWT_SECRET = config["JWT_SECRET"]
JWT_ISSUER = "cognio ID"
def authenticate(credentials: Credentials, db: Session) -> Optional[str]:

View file

@ -4,7 +4,7 @@ from sqlalchemy.orm import sessionmaker
from app.config import config
DATABASE_URL = f"postgresql://{config['CGNO_ID_DB_USERNAME']}:{config['CGNO_ID_DB_PASSWORD']}@{config['CGNO_ID_DB_HOST']}/{config['CGNO_ID_DB_NAME']}"
DATABASE_URL = f"postgresql://{config['DB_USERNAME']}:{config['DB_PASSWORD']}@{config['DB_HOST']}/{config['DB_NAME']}"
engine = create_engine(DATABASE_URL)

23
app/init.py Normal file
View file

@ -0,0 +1,23 @@
from app.config import config
from app.db import session_factory
from app.role.service import create_admin_role
from app.user.service import create_root_user
def init_root_user():
db = session_factory()
root_email = config["ROOT_EMAIL"]
root_password = config["ROOT_PASSWORD"]
create_root_user(db, root_email, root_password)
db.close()
def init_admin_role():
db = session_factory()
create_admin_role(db)
db.close()

View file

@ -1,9 +1,10 @@
import uvicorn
from fastapi import FastAPI, APIRouter
from starlette.middleware.cors import CORSMiddleware
from app.user.handlers import router as user_router
from app.auth.handlers import router as auth_router
from app.user.root import init_root_user
from app.init import init_root_user, init_admin_role
def main_router() -> APIRouter:
@ -15,6 +16,7 @@ def main_router() -> APIRouter:
app = FastAPI(title="cognio ID API")
app.add_event_handler("startup", init_admin_role)
app.add_event_handler("startup", init_root_user)
app.add_middleware(
CORSMiddleware,
@ -25,3 +27,6 @@ app.add_middleware(
)
app.include_router(main_router())
if __name__ == "__main__":
uvicorn.run("app.main:app")

Binary file not shown.

View file

@ -9,8 +9,9 @@ from alembic import context
sys.path.append(str(pathlib.Path(__file__).resolve().parents[2]))
from app.db import DATABASE_URL
from app.db import DATABASE_URL, EntityBase
from app.user.model import User
from app.role.model import Role
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
@ -24,7 +25,7 @@ fileConfig(config.config_file_name)
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = [User.metadata]
target_metadata = EntityBase.metadata
# other values from the config, defined by the needs of env.py,
# can be acquired:

View file

@ -0,0 +1,39 @@
"""Add roles
Revision ID: 2a84260bc774
Revises: 646ae6f3e17a
Create Date: 2021-02-28 23:06:29.207602
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '2a84260bc774'
down_revision = '646ae6f3e17a'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('roles',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=64), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('creation_date', sa.DateTime(), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.add_column('users', sa.Column('role_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'users', 'roles', ['role_id'], ['id'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'users', type_='foreignkey')
op.drop_column('users', 'role_id')
op.drop_table('roles')
# ### end Alembic commands ###

0
app/role/__init__.py Normal file
View file

Binary file not shown.

Binary file not shown.

Binary file not shown.

14
app/role/model.py Normal file
View file

@ -0,0 +1,14 @@
from datetime import datetime
from sqlalchemy import Column, Integer, String, DateTime, Text
from app.db import EntityBase
class Role(EntityBase):
__tablename__ = "roles"
id = Column(Integer, primary_key=True)
name = Column(String(64), unique=True, nullable=False)
description = Column(Text)
creation_date = Column(DateTime, nullable=False, default=datetime.utcnow())

49
app/role/service.py Normal file
View file

@ -0,0 +1,49 @@
from typing import Optional
from sqlalchemy.orm import Session
from app.role.model import Role
def create_role(db: Session, role: Role) -> Role:
role.name = role.name.lower()
if get_role_by_name(db, role.name) is not None:
raise Exception()
db.add(role)
db.commit()
db.refresh(role)
return role
def get_role_by_name(db: Session, name: str) -> Optional[Role]:
return db.query(Role).filter(Role.name == name).one_or_none()
def get_role_by_id(db: Session, id: int) -> Optional[Role]:
return db.query(Role).filter(Role.id == id).one_or_none()
def get_roles(db: Session) -> list[Role]:
return db.query(Role).all()
def create_admin_role(db: Session):
admin_role = get_role_by_name(db, "admin")
if admin_role is None:
db.add(Role(name="admin"))
db.commit()
def delete_role_by_id(db: Session, id: int):
role = get_role_by_id(db, id)
if role.name == "admin":
return
if role is not None:
db.delete(role)
db.commit()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -4,6 +4,7 @@ from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from starlette.responses import Response
from app.access_control.role import has_role
from app.auth.middleware import get_auth_user
from app.user.dto import UserCreationModel, UserResourceModel
from app.user.model import User
@ -21,6 +22,7 @@ async def create_user(
) -> UserResourceModel:
user = model.to_entity()
created_user = user_service.create_user(db, user)
return UserResourceModel.from_entity(created_user)

View file

@ -1,9 +1,11 @@
import enum
from datetime import datetime
from sqlalchemy import Column, String, Integer, DateTime, Enum, Date
from sqlalchemy import Column, String, Integer, DateTime, Enum, Date, ForeignKey
from sqlalchemy.orm import relationship
from app.db import EntityBase
from app.role.model import Role
class Sex(enum.Enum):
@ -22,8 +24,14 @@ class User(EntityBase):
username = Column(String(length=32), unique=True, nullable=False)
email = Column(String, unique=True, nullable=False)
password = Column(String, nullable=False)
role_id = Column(Integer, ForeignKey("roles.id"))
given_name = Column(String(length=32), nullable=False)
family_name = Column(String(length=32))
sex = Column(Enum(Sex), nullable=False, default=Sex.NOT_KNOWN)
birthdate = Column(Date)
creation_date = Column(DateTime, nullable=False, default=datetime.utcnow())
role = relationship("Role", back_populates="users")
Role.users = relationship("User", back_populates="role")

View file

@ -1,21 +0,0 @@
from datetime import date
from app.config import config
from app.db import session_factory
from app.user import service as user_service
from app.user.model import User
def init_root_user():
db = session_factory()
root_user = user_service.get_user_by_username(db, "root")
if root_user is None:
user_service.create_user(db, User(
username="root",
email=config["CGNO_ROOT_EMAIL"],
password=config["CGNO_ROOT_PASSWORD"],
given_name="Root",
birthdate=date.today()
))
db.close()

View file

@ -1,15 +1,18 @@
from datetime import date
from typing import Optional
from passlib.context import CryptContext
from sqlalchemy.orm import Session
from app.user.model import User
from app.role import service as role_service
pwd_context = CryptContext(schemes=["bcrypt"])
def create_user(db: Session, user: User) -> User:
if get_user_by_username_or_email(db, user.username, user.email) is not None:
existing_user = get_user_by_username_or_email(db, user.username, user.email)
if existing_user is not None:
raise Exception()
user.password = pwd_context.hash(user.password)
@ -31,8 +34,28 @@ def get_user_by_username_or_email(db: Session, username: str, email: str) -> Opt
return db.query(User).filter(User.username == username, User.email == email).one_or_none()
def create_root_user(db: Session, root_email: str, root_password: str):
root_user = get_user_by_username(db, "root")
admin_role = role_service.get_role_by_name(db, "admin")
if root_user is None:
root_user = User(
username="root",
email=root_email,
password=root_password,
given_name="Root",
role=admin_role,
birthdate=date.today()
)
create_user(db, root_user)
def delete_user_by_id(db: Session, id: int):
user = get_user_by_id(db, id)
if user.username == "root":
raise Exception()
if user is not None:
db.delete(user)
db.commit()