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,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,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue