feat: init roles + authorship detection

This commit is contained in:
swve 2023-11-27 22:16:22 +01:00
parent 38288e8a57
commit 0595bfdb3f
16 changed files with 109 additions and 236 deletions

View file

@ -1,8 +1,10 @@
import json
import resource
from typing import Literal
from uuid import uuid4
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.courses import Course, CourseCreate, CourseRead, CourseUpdate
from src.security.rbac.rbac import (
@ -60,7 +62,7 @@ async def create_course(
# Complete course object
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.update_date = str(datetime.now())
@ -76,18 +78,18 @@ async def create_course(
db_session.refresh(course)
# Make the user the creator of the course
course_author = CourseAuthor(
course_id=course.id if course.id else 0,
resource_author = ResourceAuthor(
resource_uuid=course.course_uuid,
user_id=current_user.id,
authorship=CourseAuthorshipEnum.CREATOR,
authorship=ResourceAuthorshipEnum.CREATOR,
creation_date=str(datetime.now()),
update_date=str(datetime.now()),
)
# Insert course author
db_session.add(course_author)
db_session.add(resource_author)
db_session.commit()
db_session.refresh(course_author)
db_session.refresh(resource_author)
return CourseRead.from_orm(course)
@ -241,26 +243,23 @@ async def verify_rights(
course_id: str,
current_user: PublicUser | AnonymousUser,
action: Literal["create", "read", "update", "delete"],
db_session: Session,
):
if action == "read":
if current_user.id == "anonymous":
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:
users = request.app.db["users"]
user = await users.find_one({"user_id": str(current_user.id)})
await authorization_verify_based_on_roles_and_authorship(
request,
str(current_user.id),
action,
user["roles"],
course_id,
db_session,
)
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))
@ -268,8 +267,8 @@ async def verify_rights(
request,
str(current_user.id),
action,
user["roles"],
course_id,
db_session,
)

View file

@ -214,7 +214,10 @@ async def get_orgs_by_user(
statement = (
select(Organization)
.join(UserOrganization)
.where(Organization.id == UserOrganization.org_id)
.where(
Organization.id == UserOrganization.org_id,
UserOrganization.user_id == user_id,
)
)
result = db_session.exec(statement)

View file

@ -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)

View file

@ -1,7 +1,7 @@
from uuid import uuid4
from sqlmodel import Session, select
from src.db.users import PublicUser
from src.db.roles import Role, RoleCreate, RoleUpdate
from src.services.users.schemas.users import PublicUser
from fastapi import HTTPException, Request
from datetime import datetime

View file

@ -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

View file

@ -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

View file

@ -4,6 +4,7 @@ from fastapi import HTTPException, Request, status
from sqlmodel import Session, select
from src.db.organizations import Organization
from src.db.users import (
PublicUser,
User,
UserCreate,
UserRead,
@ -12,7 +13,6 @@ from src.db.users import (
)
from src.db.user_organizations import UserOrganization
from src.security.security import security_hash_password, security_verify_password
from src.services.users.schemas.users import PublicUser
async def create_user(