mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
fix: courses visibility issue
This commit is contained in:
parent
b3f1a4a7c5
commit
96e453a4de
12 changed files with 97 additions and 98 deletions
|
|
@ -142,7 +142,7 @@ async def authorization_verify_based_on_org_admin_status(
|
||||||
|
|
||||||
|
|
||||||
# Tested and working
|
# Tested and working
|
||||||
async def authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
async def authorization_verify_based_on_roles_and_authorship(
|
||||||
request: Request,
|
request: Request,
|
||||||
user_id: int,
|
user_id: int,
|
||||||
action: Literal["read", "update", "delete", "create"],
|
action: Literal["read", "update", "delete", "create"],
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from sqlmodel import Session, select
|
||||||
from src.db.courses.courses import Course
|
from src.db.courses.courses import Course
|
||||||
from src.db.courses.chapters import Chapter
|
from src.db.courses.chapters import Chapter
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_element_is_public,
|
authorization_verify_if_element_is_public,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
|
|
@ -270,14 +270,14 @@ async def rbac_check(
|
||||||
)
|
)
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
res = await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
res = await authorization_verify_based_on_roles_and_authorship(
|
||||||
request, current_user.id, action, course_uuid, db_session
|
request, current_user.id, action, course_uuid, db_session
|
||||||
)
|
)
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request,
|
request,
|
||||||
current_user.id,
|
current_user.id,
|
||||||
action,
|
action,
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ from src.security.features_utils.usage import (
|
||||||
increase_feature_usage,
|
increase_feature_usage,
|
||||||
)
|
)
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_element_is_public,
|
authorization_verify_if_element_is_public,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
|
|
@ -1666,7 +1666,7 @@ async def rbac_check(
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
res = (
|
res = (
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request, current_user.id, action, course_uuid, db_session
|
request, current_user.id, action, course_uuid, db_session
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -1674,7 +1674,7 @@ async def rbac_check(
|
||||||
else:
|
else:
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request,
|
request,
|
||||||
current_user.id,
|
current_user.id,
|
||||||
action,
|
action,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from src.db.courses.courses import Course
|
||||||
from src.db.organizations import Organization
|
from src.db.organizations import Organization
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
from src.db.courses.chapters import Chapter
|
from src.db.courses.chapters import Chapter
|
||||||
|
|
@ -150,7 +150,7 @@ async def rbac_check(
|
||||||
):
|
):
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request,
|
request,
|
||||||
current_user.id,
|
current_user.id,
|
||||||
action,
|
action,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from src.db.organizations import Organization
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
from src.db.courses.chapters import Chapter
|
from src.db.courses.chapters import Chapter
|
||||||
|
|
@ -232,7 +232,7 @@ async def rbac_check(
|
||||||
):
|
):
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request,
|
request,
|
||||||
current_user.id,
|
current_user.id,
|
||||||
action,
|
action,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from uuid import uuid4
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
from src.db.users import AnonymousUser
|
from src.db.users import AnonymousUser
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_element_is_public,
|
authorization_verify_if_element_is_public,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
|
|
@ -561,14 +561,14 @@ async def rbac_check(
|
||||||
)
|
)
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
res = await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
res = await authorization_verify_based_on_roles_and_authorship(
|
||||||
request, current_user.id, action, course_uuid, db_session
|
request, current_user.id, action, course_uuid, db_session
|
||||||
)
|
)
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request,
|
request,
|
||||||
current_user.id,
|
current_user.id,
|
||||||
action,
|
action,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from uuid import uuid4
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
from src.db.users import AnonymousUser
|
from src.db.users import AnonymousUser
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_element_is_public,
|
authorization_verify_if_element_is_public,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
|
|
@ -300,7 +300,7 @@ async def rbac_check(
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
res = (
|
res = (
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request, current_user.id, action, collection_uuid, db_session
|
request, current_user.id, action, collection_uuid, db_session
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -308,7 +308,7 @@ async def rbac_check(
|
||||||
else:
|
else:
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request,
|
request,
|
||||||
current_user.id,
|
current_user.id,
|
||||||
action,
|
action,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
from typing import Literal
|
from typing import Literal, List
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from sqlalchemy import union
|
from sqlmodel import Session, select, or_, and_
|
||||||
from sqlmodel import Session, select
|
|
||||||
from src.db.usergroup_resources import UserGroupResource
|
from src.db.usergroup_resources import UserGroupResource
|
||||||
from src.db.usergroup_user import UserGroupUser
|
from src.db.usergroup_user import UserGroupUser
|
||||||
from src.db.organizations import Organization
|
from src.db.organizations import Organization
|
||||||
|
|
@ -21,7 +20,7 @@ from src.db.courses.courses import (
|
||||||
FullCourseReadWithTrail,
|
FullCourseReadWithTrail,
|
||||||
)
|
)
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_element_is_public,
|
authorization_verify_if_element_is_public,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
|
|
@ -151,6 +150,69 @@ async def get_course_meta(
|
||||||
trail=trail if trail else None,
|
trail=trail if trail else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def get_courses_orgslug(
|
||||||
|
request: Request,
|
||||||
|
current_user: PublicUser | AnonymousUser,
|
||||||
|
org_slug: str,
|
||||||
|
db_session: Session,
|
||||||
|
page: int = 1,
|
||||||
|
limit: int = 10,
|
||||||
|
) -> List[CourseRead]:
|
||||||
|
offset = (page - 1) * limit
|
||||||
|
|
||||||
|
# Base query
|
||||||
|
query = (
|
||||||
|
select(Course)
|
||||||
|
.join(Organization)
|
||||||
|
.where(Organization.slug == org_slug)
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(current_user, AnonymousUser):
|
||||||
|
# For anonymous users, only show public courses
|
||||||
|
query = query.where(Course.public == True)
|
||||||
|
else:
|
||||||
|
# For authenticated users, show:
|
||||||
|
# 1. Public courses
|
||||||
|
# 2. Courses not in any UserGroup
|
||||||
|
# 3. Courses in UserGroups where the user is a member
|
||||||
|
# 4. Courses where the user is a resource author
|
||||||
|
query = (
|
||||||
|
query
|
||||||
|
.outerjoin(UserGroupResource, UserGroupResource.resource_uuid == Course.course_uuid) # type: ignore
|
||||||
|
.outerjoin(UserGroupUser, and_(
|
||||||
|
UserGroupUser.usergroup_id == UserGroupResource.usergroup_id,
|
||||||
|
UserGroupUser.user_id == current_user.id
|
||||||
|
))
|
||||||
|
.outerjoin(ResourceAuthor, ResourceAuthor.resource_uuid == Course.course_uuid) # type: ignore
|
||||||
|
.where(or_(
|
||||||
|
Course.public == True,
|
||||||
|
UserGroupResource.resource_uuid == None, # Courses not in any UserGroup # noqa: E711
|
||||||
|
UserGroupUser.user_id == current_user.id, # Courses in UserGroups where user is a member
|
||||||
|
ResourceAuthor.user_id == current_user.id # Courses where user is a resource author
|
||||||
|
))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply pagination
|
||||||
|
query = query.offset(offset).limit(limit).distinct()
|
||||||
|
|
||||||
|
courses = db_session.exec(query).all()
|
||||||
|
|
||||||
|
# Fetch authors for each course
|
||||||
|
course_reads = []
|
||||||
|
for course in courses:
|
||||||
|
authors_query = (
|
||||||
|
select(User)
|
||||||
|
.join(ResourceAuthor, ResourceAuthor.user_id == User.id) # type: ignore
|
||||||
|
.where(ResourceAuthor.resource_uuid == course.course_uuid)
|
||||||
|
)
|
||||||
|
authors = db_session.exec(authors_query).all()
|
||||||
|
|
||||||
|
course_read = CourseRead.model_validate(course)
|
||||||
|
course_read.authors = [UserRead.model_validate(author) for author in authors]
|
||||||
|
course_reads.append(course_read)
|
||||||
|
|
||||||
|
return course_reads
|
||||||
|
|
||||||
|
|
||||||
async def create_course(
|
async def create_course(
|
||||||
request: Request,
|
request: Request,
|
||||||
|
|
@ -366,72 +428,7 @@ async def delete_course(
|
||||||
return {"detail": "Course deleted"}
|
return {"detail": "Course deleted"}
|
||||||
|
|
||||||
|
|
||||||
async def get_courses_orgslug(
|
|
||||||
request: Request,
|
|
||||||
current_user: PublicUser | AnonymousUser,
|
|
||||||
org_slug: str,
|
|
||||||
db_session: Session,
|
|
||||||
page: int = 1,
|
|
||||||
limit: int = 10,
|
|
||||||
):
|
|
||||||
|
|
||||||
# TODO : This entire function is a mess. It needs to be rewritten.
|
|
||||||
|
|
||||||
# Query for public courses
|
|
||||||
statement_public = (
|
|
||||||
select(Course)
|
|
||||||
.join(Organization)
|
|
||||||
.where(Organization.slug == org_slug, Course.public == True)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Query for courses where the current user is an author
|
|
||||||
statement_author = (
|
|
||||||
select(Course)
|
|
||||||
.join(Organization)
|
|
||||||
.join(ResourceAuthor, ResourceAuthor.user_id == current_user.id) # type: ignore
|
|
||||||
.where(
|
|
||||||
Organization.slug == org_slug,
|
|
||||||
ResourceAuthor.resource_uuid == Course.course_uuid,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Query for courses where the current user is in a user group that has access to the course
|
|
||||||
statement_usergroup = (
|
|
||||||
select(Course)
|
|
||||||
.join(Organization)
|
|
||||||
.join(UserGroupResource, UserGroupResource.resource_uuid == Course.course_uuid) # type: ignore
|
|
||||||
.join(
|
|
||||||
UserGroupUser, UserGroupUser.usergroup_id == UserGroupResource.usergroup_id # type: ignore
|
|
||||||
)
|
|
||||||
.where(Organization.slug == org_slug, UserGroupUser.user_id == current_user.id)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Combine the results
|
|
||||||
statement_complete = union(
|
|
||||||
statement_public, statement_author, statement_usergroup
|
|
||||||
).subquery()
|
|
||||||
|
|
||||||
# TODO: migrate this to exec
|
|
||||||
courses = db_session.execute(select(statement_complete)).all() # type: ignore
|
|
||||||
|
|
||||||
# TODO: I have no idea why this is necessary, but it is
|
|
||||||
courses = [CourseRead(**course._asdict(), authors=[]) for course in courses]
|
|
||||||
|
|
||||||
# for every course, get the authors
|
|
||||||
for course in courses:
|
|
||||||
authors_statement = (
|
|
||||||
select(User)
|
|
||||||
.join(ResourceAuthor)
|
|
||||||
.where(ResourceAuthor.resource_uuid == course.course_uuid)
|
|
||||||
)
|
|
||||||
authors = db_session.exec(authors_statement).all()
|
|
||||||
|
|
||||||
# convert from User to UserRead
|
|
||||||
authors = [UserRead.model_validate(author) for author in authors]
|
|
||||||
|
|
||||||
course.authors = authors
|
|
||||||
|
|
||||||
return courses
|
|
||||||
|
|
||||||
|
|
||||||
## 🔒 RBAC Utils ##
|
## 🔒 RBAC Utils ##
|
||||||
|
|
@ -452,7 +449,7 @@ async def rbac_check(
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
res = (
|
res = (
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request, current_user.id, action, course_uuid, db_session
|
request, current_user.id, action, course_uuid, db_session
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -460,7 +457,7 @@ async def rbac_check(
|
||||||
else:
|
else:
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request,
|
request,
|
||||||
current_user.id,
|
current_user.id,
|
||||||
action,
|
action,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from typing import Literal
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from sqlmodel import Session, select
|
from sqlmodel import Session, select
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
from src.db.users import AnonymousUser, PublicUser
|
from src.db.users import AnonymousUser, PublicUser
|
||||||
|
|
@ -133,7 +133,7 @@ async def rbac_check(
|
||||||
):
|
):
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request, current_user.id, action, role_uuid, db_session
|
request, current_user.id, action, role_uuid, db_session
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ from src.security.features_utils.usage import (
|
||||||
increase_feature_usage,
|
increase_feature_usage,
|
||||||
)
|
)
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
from src.db.usergroup_resources import UserGroupResource
|
from src.db.usergroup_resources import UserGroupResource
|
||||||
|
|
@ -492,7 +492,7 @@ async def rbac_check(
|
||||||
):
|
):
|
||||||
await authorization_verify_if_user_is_anon(current_user.id)
|
await authorization_verify_if_user_is_anon(current_user.id)
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request,
|
request,
|
||||||
current_user.id,
|
current_user.id,
|
||||||
action,
|
action,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ from src.services.orgs.invites import get_invite_code
|
||||||
from src.services.users.avatars import upload_avatar
|
from src.services.users.avatars import upload_avatar
|
||||||
from src.db.roles import Role, RoleRead
|
from src.db.roles import Role, RoleRead
|
||||||
from src.security.rbac.rbac import (
|
from src.security.rbac.rbac import (
|
||||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
authorization_verify_based_on_roles_and_authorship,
|
||||||
authorization_verify_if_user_is_anon,
|
authorization_verify_if_user_is_anon,
|
||||||
)
|
)
|
||||||
from src.db.organizations import Organization, OrganizationRead
|
from src.db.organizations import Organization, OrganizationRead
|
||||||
|
|
@ -491,7 +491,7 @@ async def authorize_user_action(
|
||||||
|
|
||||||
# RBAC check
|
# RBAC check
|
||||||
authorized = (
|
authorized = (
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request, current_user.id, action, resource_uuid, db_session
|
request, current_user.id, action, resource_uuid, db_session
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -564,7 +564,7 @@ async def rbac_check(
|
||||||
if current_user.id == 0: # if user is anonymous
|
if current_user.id == 0: # if user is anonymous
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request, current_user.id, "create", "user_x", db_session
|
request, current_user.id, "create", "user_x", db_session
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -575,7 +575,7 @@ async def rbac_check(
|
||||||
if current_user.user_uuid == user_uuid:
|
if current_user.user_uuid == user_uuid:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
await authorization_verify_based_on_roles_and_authorship_and_usergroups(
|
await authorization_verify_based_on_roles_and_authorship(
|
||||||
request, current_user.id, action, user_uuid, db_session
|
request, current_user.id, action, user_uuid, db_session
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,8 +110,10 @@ function InviteOnlySignUpComponent(props: InviteOnlySignUpProps) {
|
||||||
<div className="font-bold text-sm">{message}</div>
|
<div className="font-bold text-sm">{message}</div>
|
||||||
</div>
|
</div>
|
||||||
<hr className="border-green-900/20 800 w-40 border" />
|
<hr className="border-green-900/20 800 w-40 border" />
|
||||||
<Link className="flex space-x-2 items-center" href={'/login'}>
|
<Link className="flex space-x-2 items-center" href={
|
||||||
<User size={14} /> <div>Login </div>
|
`/login?orgslug=${org?.slug}`
|
||||||
|
} >
|
||||||
|
<User size={14} /> <div>Login to your account</div>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue