diff --git a/apps/api/requirements.txt b/apps/api/requirements.txt
index b361beec..4c38a422 100644
--- a/apps/api/requirements.txt
+++ b/apps/api/requirements.txt
@@ -11,6 +11,8 @@ botocore
python-jose
passlib
fastapi-jwt-auth
+pytest
+httpx
faker
requests
pyyaml
diff --git a/apps/api/src/db/courses.py b/apps/api/src/db/courses.py
index 7cc950b1..fade9b48 100644
--- a/apps/api/src/db/courses.py
+++ b/apps/api/src/db/courses.py
@@ -40,7 +40,7 @@ class CourseUpdate(CourseBase):
class CourseRead(CourseBase):
id: int
org_id: int = Field(default=None, foreign_key="organization.id")
- authors: List[UserRead]
+ authors: List[UserRead]
course_uuid: str
creation_date: str
update_date: str
@@ -49,22 +49,22 @@ class CourseRead(CourseBase):
class FullCourseRead(CourseBase):
id: int
- course_uuid: str
- creation_date: str
- update_date: str
+ course_uuid: Optional[str]
+ creation_date: Optional[str]
+ update_date: Optional[str]
# Chapters, Activities
chapters: List[ChapterRead]
- authors: List[UserRead]
+ authors: List[UserRead]
pass
class FullCourseReadWithTrail(CourseBase):
id: int
- course_uuid: str
- creation_date: str
- update_date: str
+ course_uuid: Optional[str]
+ creation_date: Optional[str]
+ update_date: Optional[str]
org_id: int = Field(default=None, foreign_key="organization.id")
- authors: List[UserRead]
+ authors: List[UserRead]
# Chapters, Activities
chapters: List[ChapterRead]
# Trail
diff --git a/apps/api/src/db/trail_runs.py b/apps/api/src/db/trail_runs.py
index e160a790..26bfec8f 100644
--- a/apps/api/src/db/trail_runs.py
+++ b/apps/api/src/db/trail_runs.py
@@ -47,10 +47,10 @@ class TrailRunRead(BaseModel):
org_id: int = Field(default=None, foreign_key="organization.id")
user_id: int = Field(default=None, foreign_key="user.id")
# course object
- course: dict
+ course: Optional[dict]
# timestamps
- creation_date: str
- update_date: str
+ creation_date: Optional[str]
+ update_date: Optional[str]
# number of activities in course
course_total_steps: int
steps: list[TrailStep]
diff --git a/apps/api/src/db/trails.py b/apps/api/src/db/trails.py
index c59697ef..e29f241f 100644
--- a/apps/api/src/db/trails.py
+++ b/apps/api/src/db/trails.py
@@ -23,11 +23,11 @@ class TrailCreate(TrailBase):
# trick because Lists are not supported in SQLModel (runs: list[TrailRun] )
class TrailRead(BaseModel):
id: Optional[int] = Field(default=None, primary_key=True)
- trail_uuid: str
+ trail_uuid: Optional[str]
org_id: int = Field(default=None, foreign_key="organization.id")
user_id: int = Field(default=None, foreign_key="user.id")
- creation_date: str
- update_date: str
+ creation_date: Optional[str]
+ update_date: Optional[str]
runs: list[TrailRunRead]
class Config:
diff --git a/apps/api/src/db/users.py b/apps/api/src/db/users.py
index 79ee9788..95f263f2 100644
--- a/apps/api/src/db/users.py
+++ b/apps/api/src/db/users.py
@@ -1,6 +1,10 @@
from typing import Optional
+from pydantic import BaseModel
from sqlmodel import Field, SQLModel
+from src.db.roles import RoleRead
+from src.db.organizations import OrganizationRead
+
class UserBase(SQLModel):
username: str
@@ -33,14 +37,27 @@ class UserRead(UserBase):
id: int
user_uuid: str
+
class PublicUser(UserRead):
pass
+
+class UserRoleWithOrg(BaseModel):
+ role: RoleRead
+ org: OrganizationRead
+
+
+class UserSession(BaseModel):
+ user: UserRead
+ roles: list[UserRoleWithOrg]
+
+
class AnonymousUser(SQLModel):
id: int = 0
user_uuid: str = "user_anonymous"
username: str = "anonymous"
+
class User(UserBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
password: str = ""
diff --git a/apps/api/src/routers/users.py b/apps/api/src/routers/users.py
index 71ec2741..808f77b5 100644
--- a/apps/api/src/routers/users.py
+++ b/apps/api/src/routers/users.py
@@ -9,6 +9,7 @@ from src.db.users import (
User,
UserCreate,
UserRead,
+ UserSession,
UserUpdate,
UserUpdatePassword,
)
@@ -17,6 +18,7 @@ from src.services.users.users import (
create_user,
create_user_without_org,
delete_user_by_id,
+ get_user_session,
read_user_by_id,
read_user_by_uuid,
update_user,
@@ -35,6 +37,18 @@ async def api_get_current_user(current_user: User = Depends(get_current_user)):
return current_user.dict()
+@router.get("/session")
+async def api_get_current_user_session(
+ request: Request,
+ db_session: Session = Depends(get_db_session),
+ current_user: PublicUser = Depends(get_current_user),
+) -> UserSession:
+ """
+ Get current user
+ """
+ return await get_user_session(request, db_session, current_user)
+
+
@router.get("/authorize/ressource/{ressource_uuid}/action/{action}")
async def api_get_authorization_status(
request: Request,
diff --git a/apps/api/src/security/rbac/rbac.py b/apps/api/src/security/rbac/rbac.py
index 3d6872b5..6aec4117 100644
--- a/apps/api/src/security/rbac/rbac.py
+++ b/apps/api/src/security/rbac/rbac.py
@@ -21,6 +21,7 @@ async def authorization_verify_if_element_is_public(
# Verifies if the element is public
if element_nature == ("courses" or "collections") and action == "read":
if element_nature == "courses":
+ print("looking for course")
statement = select(Course).where(
Course.public is True, Course.course_uuid == element_uuid
)
@@ -28,10 +29,7 @@ async def authorization_verify_if_element_is_public(
if course:
return True
else:
- raise HTTPException(
- status_code=status.HTTP_403_FORBIDDEN,
- detail="User rights (public content) : You don't have the right to perform this action",
- )
+ return False
if element_nature == "collections":
statement = select(Collection).where(
@@ -42,15 +40,9 @@ async def authorization_verify_if_element_is_public(
if collection:
return True
else:
- raise HTTPException(
- status_code=status.HTTP_403_FORBIDDEN,
- detail="User rights (public content) : You don't have the right to perform this action",
- )
+ return False
else:
- raise HTTPException(
- status_code=status.HTTP_403_FORBIDDEN,
- detail="User rights (public content) : You don't have the right to perform this action",
- )
+ return False
# Tested and working
diff --git a/apps/api/src/services/courses/activities/activities.py b/apps/api/src/services/courses/activities/activities.py
index 0acae6b3..58e7de7d 100644
--- a/apps/api/src/services/courses/activities/activities.py
+++ b/apps/api/src/services/courses/activities/activities.py
@@ -3,6 +3,7 @@ from sqlmodel import Session, select
from src.db.chapters import Chapter
from src.security.rbac.rbac import (
authorization_verify_based_on_roles_and_authorship,
+ authorization_verify_if_element_is_public,
authorization_verify_if_user_is_anon,
)
from src.db.activities import ActivityCreate, Activity, ActivityRead, ActivityUpdate
@@ -212,20 +213,33 @@ async def get_activities(
async def rbac_check(
request: Request,
- course_id: str,
+ course_uuid: str,
current_user: PublicUser | AnonymousUser,
action: Literal["create", "read", "update", "delete"],
db_session: Session,
):
- await authorization_verify_if_user_is_anon(current_user.id)
+ if action == "read":
+ if current_user.id == 0: # Anonymous user
+ res = await authorization_verify_if_element_is_public(
+ request, course_uuid, action, db_session
+ )
+ print('res',res)
+ return res
+ else:
+ res = await authorization_verify_based_on_roles_and_authorship(
+ request, current_user.id, action, course_uuid, db_session
+ )
+ return res
+ else:
+ await authorization_verify_if_user_is_anon(current_user.id)
- await authorization_verify_based_on_roles_and_authorship(
- request,
- current_user.id,
- action,
- course_id,
- db_session,
- )
+ await authorization_verify_based_on_roles_and_authorship(
+ request,
+ current_user.id,
+ action,
+ course_uuid,
+ db_session,
+ )
## 🔒 RBAC Utils ##
diff --git a/apps/api/src/services/courses/chapters.py b/apps/api/src/services/courses/chapters.py
index 1e166d74..5d5b78ca 100644
--- a/apps/api/src/services/courses/chapters.py
+++ b/apps/api/src/services/courses/chapters.py
@@ -5,6 +5,7 @@ from sqlmodel import Session, select
from src.db.users import AnonymousUser
from src.security.rbac.rbac import (
authorization_verify_based_on_roles_and_authorship,
+ authorization_verify_if_element_is_public,
authorization_verify_if_user_is_anon,
)
from src.db.course_chapters import CourseChapter
@@ -207,6 +208,10 @@ async def get_course_chapters(
page: int = 1,
limit: int = 10,
) -> List[ChapterRead]:
+
+ statement = select(Course).where(Course.id == course_id)
+ course = db_session.exec(statement).first()
+
statement = (
select(Chapter)
.join(CourseChapter, Chapter.id == CourseChapter.chapter_id)
@@ -220,7 +225,7 @@ async def get_course_chapters(
chapters = [ChapterRead(**chapter.dict(), activities=[]) for chapter in chapters]
# RBAC check
- await rbac_check(request, "chapter_x", current_user, "read", db_session)
+ await rbac_check(request, course.course_uuid, current_user, "read", db_session)
# Get activities for each chapter
for chapter in chapters:
@@ -532,20 +537,33 @@ async def reorder_chapters_and_activities(
async def rbac_check(
request: Request,
- course_id: str,
+ course_uuid: str,
current_user: PublicUser | AnonymousUser,
action: Literal["create", "read", "update", "delete"],
db_session: Session,
):
- await authorization_verify_if_user_is_anon(current_user.id)
+ if action == "read":
+ if current_user.id == 0: # Anonymous user
+ res = await authorization_verify_if_element_is_public(
+ request, course_uuid, action, db_session
+ )
+ print('res',res)
+ return res
+ else:
+ res = await authorization_verify_based_on_roles_and_authorship(
+ request, current_user.id, action, course_uuid, db_session
+ )
+ return res
+ else:
+ await authorization_verify_if_user_is_anon(current_user.id)
- await authorization_verify_based_on_roles_and_authorship(
- request,
- current_user.id,
- action,
- course_id,
- db_session,
- )
+ await authorization_verify_based_on_roles_and_authorship(
+ request,
+ current_user.id,
+ action,
+ course_uuid,
+ db_session,
+ )
## 🔒 RBAC Utils ##
diff --git a/apps/api/src/services/courses/collections.py b/apps/api/src/services/courses/collections.py
index 3a8c8810..e04e5c3d 100644
--- a/apps/api/src/services/courses/collections.py
+++ b/apps/api/src/services/courses/collections.py
@@ -5,6 +5,7 @@ from sqlmodel import Session, select
from src.db.users import AnonymousUser
from src.security.rbac.rbac import (
authorization_verify_based_on_roles_and_authorship,
+ authorization_verify_if_element_is_public,
authorization_verify_if_user_is_anon,
)
from src.db.collections import (
@@ -245,20 +246,34 @@ async def get_collections(
async def rbac_check(
request: Request,
- course_id: str,
+ collection_uuid: str,
current_user: PublicUser | AnonymousUser,
action: Literal["create", "read", "update", "delete"],
db_session: Session,
):
- await authorization_verify_if_user_is_anon(current_user.id)
+ if action == "read":
+ if current_user.id == 0: # Anonymous user
+ res = await authorization_verify_if_element_is_public(
+ request, collection_uuid, action, db_session
+ )
+ print('res',res)
+ return res
+ else:
+ res = await authorization_verify_based_on_roles_and_authorship(
+ request, current_user.id, action, collection_uuid, db_session
+ )
+ return res
+ else:
+ await authorization_verify_if_user_is_anon(current_user.id)
- await authorization_verify_based_on_roles_and_authorship(
- request,
- current_user.id,
- action,
- course_id,
- db_session,
- )
+ await authorization_verify_based_on_roles_and_authorship(
+ request,
+ current_user.id,
+ action,
+ collection_uuid,
+ db_session,
+ )
## 🔒 RBAC Utils ##
+
diff --git a/apps/api/src/services/courses/courses.py b/apps/api/src/services/courses/courses.py
index d7366503..72d78d01 100644
--- a/apps/api/src/services/courses/courses.py
+++ b/apps/api/src/services/courses/courses.py
@@ -96,11 +96,16 @@ async def get_course_meta(
chapters = await get_course_chapters(request, course.id, db_session, current_user)
# Trail
- trail = await get_user_trail_with_orgid(
- request, current_user, course.org_id, db_session
- )
+ trail = None
+
+ if isinstance(current_user, AnonymousUser):
+ trail = None
+ else:
+ trail = await get_user_trail_with_orgid(
+ request, current_user, course.org_id, db_session
+ )
+ trail = TrailRead.from_orm(trail)
- trail = TrailRead.from_orm(trail)
return FullCourseReadWithTrail(
**course.dict(),
@@ -359,7 +364,6 @@ async def get_courses_orgslug(
## 🔒 RBAC Utils ##
-
async def rbac_check(
request: Request,
course_uuid: str,
@@ -369,13 +373,16 @@ async def rbac_check(
):
if action == "read":
if current_user.id == 0: # Anonymous user
- await authorization_verify_if_element_is_public(
+ res = await authorization_verify_if_element_is_public(
request, course_uuid, action, db_session
)
+ print('res',res)
+ return res
else:
- await authorization_verify_based_on_roles_and_authorship(
+ res = await authorization_verify_based_on_roles_and_authorship(
request, current_user.id, action, course_uuid, db_session
)
+ return res
else:
await authorization_verify_if_user_is_anon(current_user.id)
diff --git a/apps/api/src/services/install/install.py b/apps/api/src/services/install/install.py
index b4538b28..bc079957 100644
--- a/apps/api/src/services/install/install.py
+++ b/apps/api/src/services/install/install.py
@@ -93,7 +93,7 @@ async def update_install_instance(
# Install Default roles
-async def install_default_elements(request: Request, data: dict, db_session: Session):
+async def install_default_elements( data: dict, db_session: Session):
# remove all default roles
statement = select(Role).where(Role.role_type == RoleTypeEnum.TYPE_GLOBAL)
roles = db_session.exec(statement).all()
@@ -279,7 +279,7 @@ async def install_default_elements(request: Request, data: dict, db_session: Ses
# Organization creation
async def install_create_organization(
- request: Request, org_object: OrganizationCreate, db_session: Session
+ org_object: OrganizationCreate, db_session: Session
):
org = Organization.from_orm(org_object)
@@ -296,7 +296,7 @@ async def install_create_organization(
async def install_create_organization_user(
- request: Request, user_object: UserCreate, org_slug: str, db_session: Session
+ user_object: UserCreate, org_slug: str, db_session: Session
):
user = User.from_orm(user_object)
diff --git a/apps/api/src/services/trail/trail.py b/apps/api/src/services/trail/trail.py
index 973575a7..0b1ee454 100644
--- a/apps/api/src/services/trail/trail.py
+++ b/apps/api/src/services/trail/trail.py
@@ -8,7 +8,7 @@ from src.db.courses import Course
from src.db.trail_runs import TrailRun, TrailRunRead
from src.db.trail_steps import TrailStep
from src.db.trails import Trail, TrailCreate, TrailRead
-from src.db.users import PublicUser
+from src.db.users import AnonymousUser, PublicUser
async def create_user_trail(
@@ -17,7 +17,7 @@ async def create_user_trail(
trail_object: TrailCreate,
db_session: Session,
) -> Trail:
- statement = select(Trail).where(Trail.org_id == trail_object.org_id)
+ statement = select(Trail).where(Trail.org_id == trail_object.org_id, Trail.user_id == user.id)
trail = db_session.exec(statement).first()
if trail:
@@ -103,7 +103,7 @@ async def check_trail_presence(
user: PublicUser,
db_session: Session,
):
- statement = select(Trail).where(Trail.org_id == org_id, Trail.user_id == user.id)
+ statement = select(Trail).where(Trail.org_id == org_id, Trail.user_id == user_id)
trail = db_session.exec(statement).first()
if not trail:
@@ -122,9 +122,15 @@ async def check_trail_presence(
async def get_user_trail_with_orgid(
- request: Request, user: PublicUser, org_id: int, db_session: Session
+ request: Request, user: PublicUser | AnonymousUser, org_id: int, db_session: Session
) -> TrailRead:
+ if isinstance(user, AnonymousUser):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Anonymous users cannot access this endpoint",
+ )
+
trail = await check_trail_presence(
org_id=org_id,
user_id=user.id,
diff --git a/apps/api/src/services/users/users.py b/apps/api/src/services/users/users.py
index 4a9c5ee6..cc6fbca5 100644
--- a/apps/api/src/services/users/users.py
+++ b/apps/api/src/services/users/users.py
@@ -3,17 +3,20 @@ from typing import Literal
from uuid import uuid4
from fastapi import HTTPException, Request, status
from sqlmodel import Session, select
+from src.db.roles import Role, RoleRead
from src.security.rbac.rbac import (
authorization_verify_based_on_roles_and_authorship,
authorization_verify_if_user_is_anon,
)
-from src.db.organizations import Organization
+from src.db.organizations import Organization, OrganizationRead
from src.db.users import (
AnonymousUser,
PublicUser,
User,
UserCreate,
UserRead,
+ UserRoleWithOrg,
+ UserSession,
UserUpdate,
UserUpdatePassword,
)
@@ -279,6 +282,57 @@ async def read_user_by_uuid(
return user
+async def get_user_session(
+ request: Request,
+ db_session: Session,
+ current_user: PublicUser | AnonymousUser,
+) -> UserSession:
+ # Get user
+ statement = select(User).where(User.user_uuid == current_user.user_uuid)
+ user = db_session.exec(statement).first()
+
+ if not user:
+ raise HTTPException(
+ status_code=400,
+ detail="User does not exist",
+ )
+
+ user = UserRead.from_orm(user)
+
+ # Get roles and orgs
+ statement = (
+ select(UserOrganization)
+ .where(UserOrganization.user_id == user.id)
+ .join(Organization)
+ )
+ user_organizations = db_session.exec(statement).all()
+
+ roles = []
+
+ for user_organization in user_organizations:
+ role_statement = select(Role).where(Role.id == user_organization.role_id)
+ role = db_session.exec(role_statement).first()
+
+ org_statement = select(Organization).where(
+ Organization.id == user_organization.org_id
+ )
+ org = db_session.exec(org_statement).first()
+
+ roles.append(
+ UserRoleWithOrg(
+ role=RoleRead.from_orm(role),
+ org=OrganizationRead.from_orm(org),
+ )
+ )
+
+ user_session = UserSession(
+ user=user,
+ roles=roles,
+ )
+
+ return user_session
+
+
async def authorize_user_action(
request: Request,
db_session: Session,
diff --git a/apps/api/src/tests/test_main.py b/apps/api/src/tests/test_main.py
new file mode 100644
index 00000000..22a02f5f
--- /dev/null
+++ b/apps/api/src/tests/test_main.py
@@ -0,0 +1,50 @@
+from fastapi.testclient import TestClient
+from sqlalchemy import create_engine
+from sqlalchemy.pool import StaticPool
+from sqlmodel import SQLModel, Session
+from src.tests.utils.init_data_for_tests import create_initial_data_for_tests
+from src.core.events.database import get_db_session
+import pytest
+import asyncio
+from app import app
+
+client = TestClient(app)
+
+# TODO : fix this later https://stackoverflow.com/questions/10253826/path-issue-with-pytest-importerror-no-module-named
+
+
+@pytest.fixture(name="session", scope="session")
+def session_fixture():
+ engine = create_engine(
+ "sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool
+ )
+ SQLModel.metadata.create_all(engine)
+ with Session(engine) as session:
+ yield session
+
+
+@pytest.fixture(name="client")
+def client_fixture(session: Session):
+ def get_session_override():
+ return session
+
+ app.dependency_overrides[get_db_session] = get_session_override
+
+ client = TestClient(app)
+ yield client
+ app.dependency_overrides.clear()
+
+
+@pytest.fixture(scope="session", autouse=True)
+def execute_before_all_tests(session: Session):
+ # This function will run once before all tests.
+ asyncio.run(create_initial_data_for_tests(session))
+
+
+def test_create_default_elements(client: TestClient, session: Session):
+
+ response = client.get(
+ "/api/v1/orgs/slug/wayne",
+ )
+
+ assert response.status_code == 200
diff --git a/apps/api/src/tests/test_rbac.py b/apps/api/src/tests/test_rbac.py
new file mode 100644
index 00000000..e69de29b
diff --git a/apps/api/src/tests/utils/__init__.py b/apps/api/src/tests/utils/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/apps/api/src/tests/utils/init_data_for_tests.py b/apps/api/src/tests/utils/init_data_for_tests.py
new file mode 100644
index 00000000..8229cfe2
--- /dev/null
+++ b/apps/api/src/tests/utils/init_data_for_tests.py
@@ -0,0 +1,57 @@
+from sqlmodel import Session, select
+from src.db.user_organizations import UserOrganization
+from src.db.organizations import OrganizationCreate
+from src.db.users import User, UserCreate
+from src.services.install.install import (
+ install_create_organization,
+ install_create_organization_user,
+ install_default_elements,
+)
+
+
+async def create_initial_data_for_tests(db_session: Session):
+ # Install default elements
+ await install_default_elements({}, db_session)
+
+ # Initiate test Organization
+ test_org = OrganizationCreate(
+ name="Wayne Enterprises",
+ description=None,
+ slug="wayne",
+ email="hello@wayne.dev",
+ logo_image=None,
+ )
+
+ # Create test organization
+ await install_create_organization(test_org, db_session)
+
+ users = [
+ UserCreate(
+ username="batman",
+ first_name="Bruce",
+ last_name="Wayne",
+ email="bruce@wayne.com",
+ password="imbatman",
+ ),
+ UserCreate(
+ username="robin",
+ first_name="Richard John",
+ last_name="Grayson",
+ email="robin@wayne.com",
+ password="secret",
+ ),
+ ]
+
+ # Create 2 users in that Organization
+ for user in users:
+ await install_create_organization_user(user, "wayne", db_session)
+
+ # Make robin a normal user
+ statement = select(UserOrganization).join(User).where(User.username == "robin")
+ user_org = db_session.exec(statement).first()
+
+ user_org.role_id = 3 # type: ignore
+ db_session.add(user_org)
+ db_session.commit()
+
+ return True
diff --git a/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx
index 55948525..06483373 100644
--- a/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx
+++ b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx
@@ -1,5 +1,4 @@
import { default as React, } from "react";
-import AuthProvider from "@components/Security/AuthProviderDepreceated";
import EditorWrapper from "@components/Objects/Editor/EditorWrapper";
import { getCourseMetadataWithAuthHeader } from "@services/courses/courses";
import { cookies } from "next/headers";
@@ -7,6 +6,7 @@ import { Metadata } from "next";
import { getActivityWithAuthHeader } from "@services/courses/activities";
import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshTokenServer } from "@services/auth/auth";
import { getOrganizationContextInfo, getOrganizationContextInfoWithId } from "@services/organizations/orgs";
+import SessionProvider from "@components/Contexts/SessionContext";
type MetadataProps = {
params: { orgslug: string, courseid: string, activityid: string };
@@ -35,13 +35,13 @@ const EditActivity = async (params: any) => {
const courseInfo = await getCourseMetadataWithAuthHeader(courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null)
const activity = await getActivityWithAuthHeader(activityuuid, { revalidate: 0, tags: ['activities'] }, access_token ? access_token : null)
const org = await getOrganizationContextInfoWithId(courseInfo.org_id, { revalidate: 1800, tags: ['organizations'] });
- console.log('courseInfo', courseInfo )
+ console.log('courseInfo', courseInfo)
return (
);
}
diff --git a/apps/web/app/organizations/page.tsx b/apps/web/app/organizations/page.tsx
index 009c0b19..00120e03 100644
--- a/apps/web/app/organizations/page.tsx
+++ b/apps/web/app/organizations/page.tsx
@@ -5,7 +5,6 @@ import { deleteOrganizationFromBackend } from "@services/organizations/orgs";
import useSWR, { mutate } from "swr";
import { swrFetcher } from "@services/utils/ts/requests";
import { getAPIUrl, getUriWithOrg } from "@services/config/config";
-import AuthProvider from "@components/Security/AuthProviderDepreceated";
const Organizations = () => {
const { data: organizations, error } = useSWR(`${getAPIUrl()}orgs/user/page/1/limit/10`, swrFetcher)
@@ -17,7 +16,6 @@ const Organizations = () => {
return (
<>
-
Your Organizations{" "}
diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/collections/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/collections/page.tsx
index ee4890b7..7a65ca2c 100644
--- a/apps/web/app/orgs/[orgslug]/(withmenu)/collections/page.tsx
+++ b/apps/web/app/orgs/[orgslug]/(withmenu)/collections/page.tsx
@@ -57,7 +57,7 @@ const CollectionsPage = async (params: any) => {
@@ -85,7 +85,7 @@ const CollectionsPage = async (params: any) => {
Create a collection to group courses together
diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/course.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/course.tsx
index f23c9404..bd391921 100644
--- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/course.tsx
+++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/course.tsx
@@ -42,9 +42,9 @@ const CourseClient = (props: any) => {
}
function isCourseStarted() {
- const runs = course.trail.runs;
- // checks if one of the obejcts in the array has the property "STATUS_IN_PROGRESS"
- return runs.some((run: any) => run.status === "STATUS_IN_PROGRESS");
+ const runs = course.trail?.runs;
+ if (!runs) return false;
+ return runs.some((run: any) => run.status === "STATUS_IN_PROGRESS" && run.course_id === course.id);
}
async function quitCourse() {
@@ -193,11 +193,10 @@ const CourseClient = (props: any) => {
Author
-
{course.authors[0].first_name} {course.authors[0].last_name} { (course.authors[0].first_name && course.authors[0].last_name) ? course.authors[0].first_name + ' ' + course.authors[0].last_name : course.authors[0].username }
+
{course.authors[0].first_name} {course.authors[0].last_name} {(course.authors[0].first_name && course.authors[0].last_name) ? course.authors[0].first_name + ' ' + course.authors[0].last_name : course.authors[0].username}
}
- {console.log(course)}
{isCourseStarted() ? (