mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: init roles + authorship detection
This commit is contained in:
parent
38288e8a57
commit
0595bfdb3f
16 changed files with 109 additions and 236 deletions
|
|
@ -1,18 +0,0 @@
|
||||||
from typing import Optional
|
|
||||||
from sqlmodel import Field, SQLModel
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class CourseAuthorshipEnum(str, Enum):
|
|
||||||
CREATOR = "CREATOR"
|
|
||||||
MAINTAINER = "MAINTAINER"
|
|
||||||
REPORTER = "REPORTER"
|
|
||||||
|
|
||||||
|
|
||||||
class CourseAuthor(SQLModel, table=True):
|
|
||||||
id: Optional[int] = Field(default=None, primary_key=True)
|
|
||||||
course_id: int = Field(default=None, foreign_key="course.id")
|
|
||||||
user_id: int = Field(default=None, foreign_key="user.id")
|
|
||||||
authorship: CourseAuthorshipEnum = CourseAuthorshipEnum.CREATOR
|
|
||||||
creation_date: str
|
|
||||||
update_date: str
|
|
||||||
20
apps/api/src/db/resource_authors.py
Normal file
20
apps/api/src/db/resource_authors.py
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Optional, Union
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from sqlalchemy import JSON, Column
|
||||||
|
from sqlmodel import Field, SQLModel
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceAuthorshipEnum(str, Enum):
|
||||||
|
CREATOR = "CREATOR"
|
||||||
|
MAINTAINER = "MAINTAINER"
|
||||||
|
REPORTER = "REPORTER"
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceAuthor(SQLModel, table=True):
|
||||||
|
id: Optional[int] = Field(default=None, primary_key=True)
|
||||||
|
resource_uuid: str
|
||||||
|
user_id: int = Field(default=None, foreign_key="user.id")
|
||||||
|
authorship: ResourceAuthorshipEnum = ResourceAuthorshipEnum.CREATOR
|
||||||
|
creation_date: str = ""
|
||||||
|
update_date: str = ""
|
||||||
|
|
@ -36,7 +36,7 @@ class UserRead(UserBase):
|
||||||
class PublicUser(UserRead):
|
class PublicUser(UserRead):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class AnonymousUser(UserRead):
|
class AnonymousUser(SQLModel):
|
||||||
id: str = "anonymous"
|
id: str = "anonymous"
|
||||||
username: str = "anonymous"
|
username: str = "anonymous"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from src.core.events.database import get_db_session
|
||||||
from src.db.roles import RoleCreate, RoleUpdate
|
from src.db.roles import RoleCreate, RoleUpdate
|
||||||
from src.security.auth import get_current_user
|
from src.security.auth import get_current_user
|
||||||
from src.services.roles.roles import create_role, delete_role, read_role, update_role
|
from src.services.roles.roles import create_role, delete_role, read_role, update_role
|
||||||
from src.services.users.schemas.users import PublicUser
|
from src.db.users import PublicUser
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from sqlmodel import Session
|
from sqlmodel import Session
|
||||||
from src.core.events.database import get_db_session
|
from src.core.events.database import get_db_session
|
||||||
from src.db.users import User, UserRead
|
from src.db.users import AnonymousUser, User, UserRead
|
||||||
from src.services.users.users import security_get_user
|
from src.services.users.users import security_get_user
|
||||||
from config.config import get_learnhouse_config
|
from config.config import get_learnhouse_config
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
@ -9,7 +9,6 @@ from fastapi.security import OAuth2PasswordBearer
|
||||||
from jose import JWTError, jwt
|
from jose import JWTError, jwt
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from src.services.dev.dev import isDevModeEnabled
|
from src.services.dev.dev import isDevModeEnabled
|
||||||
from src.services.users.schemas.users import AnonymousUser, PublicUser
|
|
||||||
from src.services.users.users import security_verify_password
|
from src.services.users.users import security_verify_password
|
||||||
from src.security.security import ALGORITHM, SECRET_KEY
|
from src.security.security import ALGORITHM, SECRET_KEY
|
||||||
from fastapi_jwt_auth import AuthJWT
|
from fastapi_jwt_auth import AuthJWT
|
||||||
|
|
@ -100,6 +99,6 @@ async def get_current_user(
|
||||||
return AnonymousUser()
|
return AnonymousUser()
|
||||||
|
|
||||||
|
|
||||||
async def non_public_endpoint(current_user: PublicUser):
|
async def non_public_endpoint(current_user: UserRead | AnonymousUser):
|
||||||
if isinstance(current_user, AnonymousUser):
|
if isinstance(current_user, AnonymousUser):
|
||||||
raise HTTPException(status_code=401, detail="Not authenticated")
|
raise HTTPException(status_code=401, detail="Not authenticated")
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,24 @@
|
||||||
|
from math import e
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
from fastapi import HTTPException, status, Request
|
from fastapi import HTTPException, status, Request
|
||||||
from src.security.rbac.utils import check_element_type, get_id_identifier_of_element
|
from sqlalchemy import func, null, or_
|
||||||
from src.services.roles.schemas.roles import RoleInDB
|
from sqlmodel import Session, select
|
||||||
from src.services.users.schemas.users import UserRolesInOrganization
|
from src.db.collections import Collection
|
||||||
|
from src.db.courses import Course
|
||||||
|
from src.db.resource_authors import ResourceAuthor, ResourceAuthorshipEnum
|
||||||
|
from src.db.roles import Role
|
||||||
|
from src.db.user_organizations import UserOrganization
|
||||||
|
from src.security.rbac.utils import check_element_type
|
||||||
|
|
||||||
|
|
||||||
async def authorization_verify_if_element_is_public(
|
async def authorization_verify_if_element_is_public(
|
||||||
request,
|
request,
|
||||||
element_id: str,
|
element_uuid: str,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
action: Literal["read"],
|
action: Literal["read"],
|
||||||
|
db_session: Session,
|
||||||
):
|
):
|
||||||
element_nature = await check_element_type(element_id)
|
element_nature = await check_element_type(element_uuid)
|
||||||
|
|
||||||
# Verifies if the element is public
|
# Verifies if the element is public
|
||||||
if (
|
if (
|
||||||
|
|
@ -20,10 +27,12 @@ async def authorization_verify_if_element_is_public(
|
||||||
and user_id == "anonymous"
|
and user_id == "anonymous"
|
||||||
):
|
):
|
||||||
if element_nature == "courses":
|
if element_nature == "courses":
|
||||||
courses = request.app.db["courses"]
|
statement = select(Course).where(
|
||||||
course = await courses.find_one({"course_id": element_id})
|
Course.public == True, Course.course_uuid == element_uuid
|
||||||
|
)
|
||||||
|
course = db_session.exec(statement).first()
|
||||||
|
|
||||||
if course["public"]:
|
if course:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -32,10 +41,12 @@ async def authorization_verify_if_element_is_public(
|
||||||
)
|
)
|
||||||
|
|
||||||
if element_nature == "collections":
|
if element_nature == "collections":
|
||||||
collections = request.app.db["collections"]
|
statement = select(Collection).where(
|
||||||
collection = await collections.find_one({"collection_id": element_id})
|
Collection.public == True, Collection.collection_uuid == element_uuid
|
||||||
|
)
|
||||||
|
collection = db_session.exec(statement).first()
|
||||||
|
|
||||||
if collection["public"]:
|
if collection:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -53,67 +64,65 @@ async def authorization_verify_if_user_is_author(
|
||||||
request,
|
request,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
action: Literal["read", "update", "delete", "create"],
|
action: Literal["read", "update", "delete", "create"],
|
||||||
element_id: str,
|
element_uuid: str,
|
||||||
|
db_session: Session,
|
||||||
):
|
):
|
||||||
if action == "update" or "delete" or "read":
|
if action == "update" or "delete" or "read":
|
||||||
element_nature = await check_element_type(element_id)
|
statement = select(ResourceAuthor).where(
|
||||||
elements = request.app.db[element_nature]
|
ResourceAuthor.resource_uuid == element_uuid
|
||||||
element_identifier = await get_id_identifier_of_element(element_id)
|
)
|
||||||
element = await elements.find_one({element_identifier: element_id})
|
resource_author = db_session.exec(statement).first()
|
||||||
if user_id in element["authors"]:
|
|
||||||
return True
|
if resource_author:
|
||||||
|
if resource_author.user_id == user_id:
|
||||||
|
if (resource_author.authorship == ResourceAuthorshipEnum.CREATOR) or (
|
||||||
|
resource_author.authorship == ResourceAuthorshipEnum.MAINTAINER
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="User rights (authorship) : You don't have the right to perform this action",
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return False
|
raise HTTPException(
|
||||||
else:
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
return False
|
detail="Wrong action (create)",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def authorization_verify_based_on_roles(
|
async def authorization_verify_based_on_roles(
|
||||||
request: Request,
|
request: Request,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
action: Literal["read", "update", "delete", "create"],
|
action: Literal["read", "update", "delete", "create"],
|
||||||
roles_list: list[UserRolesInOrganization],
|
element_uuid: str,
|
||||||
element_id: str,
|
db_session: Session,
|
||||||
):
|
):
|
||||||
element_type = await check_element_type(element_id)
|
element_type = await check_element_type(element_uuid)
|
||||||
element = request.app.db[element_type]
|
|
||||||
roles = request.app.db["roles"]
|
|
||||||
|
|
||||||
# Get the element
|
# Get user roles bound to an organization and standard roles
|
||||||
element_identifier = await get_id_identifier_of_element(element_id)
|
statement = (
|
||||||
element = await element.find_one({element_identifier: element_id})
|
select(Role)
|
||||||
|
.join(UserOrganization)
|
||||||
|
.where(UserOrganization.user_id == user_id)
|
||||||
|
.where((UserOrganization.id == Role.org_id) | (UserOrganization.id == null))
|
||||||
|
)
|
||||||
|
|
||||||
# Get the roles of the user
|
user_roles_in_organization_and_standard_roles = db_session.exec(statement).all()
|
||||||
roles_id_list = [role["role_id"] for role in roles_list]
|
|
||||||
roles = await roles.find({"role_id": {"$in": roles_id_list}}).to_list(length=100)
|
|
||||||
|
|
||||||
async def checkRoles():
|
# Find in roles list if there is a role that matches users action for this type of element
|
||||||
# Check Roles
|
for role in user_roles_in_organization_and_standard_roles:
|
||||||
for role in roles:
|
role = Role.from_orm(role)
|
||||||
role = RoleInDB(**role)
|
if role.rights:
|
||||||
if role.elements[element_type][f"action_{action}"] is True:
|
rights = role.rights
|
||||||
|
if rights[element_type][f"action_{action}"] is True:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def checkOrgRoles():
|
|
||||||
# Check Org Roles
|
|
||||||
users = request.app.db["users"]
|
|
||||||
user = await users.find_one({"user_id": user_id})
|
|
||||||
if element is not None:
|
|
||||||
for org in user["orgs"]:
|
|
||||||
if org["org_id"] == element["org_id"]:
|
|
||||||
if org["org_role"] == "owner" or org["org_role"] == "editor":
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if await checkRoles() or await checkOrgRoles():
|
|
||||||
return True
|
|
||||||
else:
|
else:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_403_FORBIDDEN,
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
detail="User rights (roless) : You don't have the right to perform this action",
|
detail="User rights (roles) : You don't have the right to perform this action",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -121,15 +130,15 @@ async def authorization_verify_based_on_roles_and_authorship(
|
||||||
request: Request,
|
request: Request,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
action: Literal["read", "update", "delete", "create"],
|
action: Literal["read", "update", "delete", "create"],
|
||||||
roles_list: list[UserRolesInOrganization],
|
element_uuid: str,
|
||||||
element_id: str,
|
db_session: Session,
|
||||||
):
|
):
|
||||||
isAuthor = await authorization_verify_if_user_is_author(
|
isAuthor = await authorization_verify_if_user_is_author(
|
||||||
request, user_id, action, element_id
|
request, user_id, action, element_uuid, db_session
|
||||||
)
|
)
|
||||||
|
|
||||||
isRole = await authorization_verify_based_on_roles(
|
isRole = await authorization_verify_based_on_roles(
|
||||||
request, user_id, action, roles_list, element_id
|
request, user_id, action, element_uuid, db_session
|
||||||
)
|
)
|
||||||
|
|
||||||
if isAuthor or isRole:
|
if isAuthor or isRole:
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import json
|
import json
|
||||||
|
import resource
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
from src.db.course_authors import CourseAuthor, CourseAuthorshipEnum
|
from src import db
|
||||||
|
from src.db.resource_authors import ResourceAuthor, ResourceAuthorshipEnum
|
||||||
from src.db.users import PublicUser, AnonymousUser
|
from src.db.users import PublicUser, AnonymousUser
|
||||||
from src.db.courses import Course, CourseCreate, CourseRead, CourseUpdate
|
from src.db.courses import Course, CourseCreate, CourseRead, CourseUpdate
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
|
|
@ -60,7 +62,7 @@ async def create_course(
|
||||||
|
|
||||||
# Complete course object
|
# Complete course object
|
||||||
course.org_id = course.org_id
|
course.org_id = course.org_id
|
||||||
course.course_uuid = str(uuid4())
|
course.course_uuid = str(f"course_{uuid4()}")
|
||||||
course.creation_date = str(datetime.now())
|
course.creation_date = str(datetime.now())
|
||||||
course.update_date = str(datetime.now())
|
course.update_date = str(datetime.now())
|
||||||
|
|
||||||
|
|
@ -76,18 +78,18 @@ async def create_course(
|
||||||
db_session.refresh(course)
|
db_session.refresh(course)
|
||||||
|
|
||||||
# Make the user the creator of the course
|
# Make the user the creator of the course
|
||||||
course_author = CourseAuthor(
|
resource_author = ResourceAuthor(
|
||||||
course_id=course.id if course.id else 0,
|
resource_uuid=course.course_uuid,
|
||||||
user_id=current_user.id,
|
user_id=current_user.id,
|
||||||
authorship=CourseAuthorshipEnum.CREATOR,
|
authorship=ResourceAuthorshipEnum.CREATOR,
|
||||||
creation_date=str(datetime.now()),
|
creation_date=str(datetime.now()),
|
||||||
update_date=str(datetime.now()),
|
update_date=str(datetime.now()),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Insert course author
|
# Insert course author
|
||||||
db_session.add(course_author)
|
db_session.add(resource_author)
|
||||||
db_session.commit()
|
db_session.commit()
|
||||||
db_session.refresh(course_author)
|
db_session.refresh(resource_author)
|
||||||
|
|
||||||
return CourseRead.from_orm(course)
|
return CourseRead.from_orm(course)
|
||||||
|
|
||||||
|
|
@ -241,26 +243,23 @@ async def verify_rights(
|
||||||
course_id: str,
|
course_id: str,
|
||||||
current_user: PublicUser | AnonymousUser,
|
current_user: PublicUser | AnonymousUser,
|
||||||
action: Literal["create", "read", "update", "delete"],
|
action: Literal["create", "read", "update", "delete"],
|
||||||
|
db_session: Session,
|
||||||
):
|
):
|
||||||
if action == "read":
|
if action == "read":
|
||||||
if current_user.id == "anonymous":
|
if current_user.id == "anonymous":
|
||||||
await authorization_verify_if_element_is_public(
|
await authorization_verify_if_element_is_public(
|
||||||
request, course_id, str(current_user.id), action
|
request, course_id, str(current_user.id), action, db_session
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
users = request.app.db["users"]
|
|
||||||
user = await users.find_one({"user_id": str(current_user.id)})
|
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request,
|
request,
|
||||||
str(current_user.id),
|
str(current_user.id),
|
||||||
action,
|
action,
|
||||||
user["roles"],
|
|
||||||
course_id,
|
course_id,
|
||||||
|
db_session,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
users = request.app.db["users"]
|
|
||||||
user = await users.find_one({"user_id": str(current_user.id)})
|
|
||||||
|
|
||||||
await authorization_verify_if_user_is_anon(str(current_user.id))
|
await authorization_verify_if_user_is_anon(str(current_user.id))
|
||||||
|
|
||||||
|
|
@ -268,8 +267,8 @@ async def verify_rights(
|
||||||
request,
|
request,
|
||||||
str(current_user.id),
|
str(current_user.id),
|
||||||
action,
|
action,
|
||||||
user["roles"],
|
|
||||||
course_id,
|
course_id,
|
||||||
|
db_session,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,10 @@ async def get_orgs_by_user(
|
||||||
statement = (
|
statement = (
|
||||||
select(Organization)
|
select(Organization)
|
||||||
.join(UserOrganization)
|
.join(UserOrganization)
|
||||||
.where(Organization.id == UserOrganization.org_id)
|
.where(
|
||||||
|
Organization.id == UserOrganization.org_id,
|
||||||
|
UserOrganization.user_id == user_id,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
result = db_session.exec(statement)
|
result = db_session.exec(statement)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
from typing import Optional
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
#### Classes ####################################################
|
|
||||||
|
|
||||||
|
|
||||||
class Organization(BaseModel):
|
|
||||||
name: str
|
|
||||||
description: str
|
|
||||||
email: str
|
|
||||||
slug: str
|
|
||||||
logo: Optional[str]
|
|
||||||
default: Optional[bool] = False
|
|
||||||
|
|
||||||
|
|
||||||
class OrganizationInDB(Organization):
|
|
||||||
org_id: str
|
|
||||||
|
|
||||||
|
|
||||||
class PublicOrganization(Organization):
|
|
||||||
name: str
|
|
||||||
description: str
|
|
||||||
email: str
|
|
||||||
slug: str
|
|
||||||
org_id: str
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return getattr(self, item)
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
|
from src.db.users import PublicUser
|
||||||
from src.db.roles import Role, RoleCreate, RoleUpdate
|
from src.db.roles import Role, RoleCreate, RoleUpdate
|
||||||
from src.services.users.schemas.users import PublicUser
|
|
||||||
from fastapi import HTTPException, Request
|
from fastapi import HTTPException, Request
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
from typing import Literal
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
# Database Models
|
|
||||||
|
|
||||||
class Permission(BaseModel):
|
|
||||||
action_create: bool
|
|
||||||
action_read: bool
|
|
||||||
action_update: bool
|
|
||||||
action_delete: bool
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return getattr(self, item)
|
|
||||||
|
|
||||||
|
|
||||||
class Elements(BaseModel):
|
|
||||||
courses: Permission
|
|
||||||
users: Permission
|
|
||||||
houses: Permission
|
|
||||||
collections: Permission
|
|
||||||
organizations: Permission
|
|
||||||
coursechapters: Permission
|
|
||||||
activities: Permission
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return getattr(self, item)
|
|
||||||
|
|
||||||
|
|
||||||
class Role(BaseModel):
|
|
||||||
name: str
|
|
||||||
description: str
|
|
||||||
elements : Elements
|
|
||||||
org_id: str | Literal["*"]
|
|
||||||
|
|
||||||
|
|
||||||
class RoleInDB(Role):
|
|
||||||
role_id: str
|
|
||||||
created_at: str
|
|
||||||
updated_at: str
|
|
||||||
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
from typing import Literal
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
class UserOrganization(BaseModel):
|
|
||||||
org_id: str
|
|
||||||
org_role: Literal['owner', 'editor', 'member']
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return getattr(self, item)
|
|
||||||
|
|
||||||
class UserRolesInOrganization(BaseModel):
|
|
||||||
org_id: str
|
|
||||||
role_id: str
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return getattr(self, item)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class User(BaseModel):
|
|
||||||
username: str
|
|
||||||
email: str
|
|
||||||
full_name: str | None = None
|
|
||||||
avatar_url: str | None = None
|
|
||||||
bio: str | None = None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UserWithPassword(User):
|
|
||||||
password: str
|
|
||||||
|
|
||||||
|
|
||||||
class UserInDB(User):
|
|
||||||
user_id: str
|
|
||||||
password: str
|
|
||||||
verified: bool | None = False
|
|
||||||
disabled: bool | None = False
|
|
||||||
orgs: list[UserOrganization] = []
|
|
||||||
roles: list[UserRolesInOrganization] = []
|
|
||||||
creation_date: str
|
|
||||||
update_date: str
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return getattr(self, item)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PublicUser(User):
|
|
||||||
user_id: str
|
|
||||||
orgs: list[UserOrganization] = []
|
|
||||||
roles: list[UserRolesInOrganization] = []
|
|
||||||
creation_date: str
|
|
||||||
update_date: str
|
|
||||||
|
|
||||||
class AnonymousUser(BaseModel):
|
|
||||||
user_id: str = "anonymous"
|
|
||||||
username: str = "anonymous"
|
|
||||||
roles: list[UserRolesInOrganization] = [
|
|
||||||
UserRolesInOrganization(org_id="anonymous", role_id="role_anonymous")
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Forms ####################################################
|
|
||||||
|
|
||||||
class PasswordChangeForm(BaseModel):
|
|
||||||
old_password: str
|
|
||||||
new_password: str
|
|
||||||
|
|
@ -4,6 +4,7 @@ from fastapi import HTTPException, Request, status
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
from src.db.organizations import Organization
|
from src.db.organizations import Organization
|
||||||
from src.db.users import (
|
from src.db.users import (
|
||||||
|
PublicUser,
|
||||||
User,
|
User,
|
||||||
UserCreate,
|
UserCreate,
|
||||||
UserRead,
|
UserRead,
|
||||||
|
|
@ -12,7 +13,6 @@ from src.db.users import (
|
||||||
)
|
)
|
||||||
from src.db.user_organizations import UserOrganization
|
from src.db.user_organizations import UserOrganization
|
||||||
from src.security.security import security_hash_password, security_verify_password
|
from src.security.security import security_hash_password, security_verify_password
|
||||||
from src.services.users.schemas.users import PublicUser
|
|
||||||
|
|
||||||
|
|
||||||
async def create_user(
|
async def create_user(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue