Working on the Portabase debug.

This commit is contained in:
charlesgauthereau
2025-05-18 20:46:59 +02:00
parent 6f2523e524
commit 405de7b323
13 changed files with 240 additions and 281 deletions
@@ -7,23 +7,22 @@ import { ButtonDeleteProject } from "@/components/wrappers/dashboard/projects/Bu
import { CardsWithPagination } from "@/components/wrappers/common/cards-with-pagination"; import { CardsWithPagination } from "@/components/wrappers/common/cards-with-pagination";
import { ProjectDatabaseCard } from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectDatabaseCard"; import { ProjectDatabaseCard } from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectDatabaseCard";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import { getCurrentOrganizationSlug } from "@/features/dashboard/organization-cookie";
import { db } from "@/db"; import { db } from "@/db";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { organization as drizzleOrganization } from "@/db/schema"; import { organization as drizzleOrganization } from "@/db/schema";
import {getOrganization} from "@/lib/auth/auth";
export default async function RoutePage(props: PageParams<{ slug: string; projectId: string }>) { export default async function RoutePage(props: PageParams<{ slug: string; projectId: string }>) {
const { slug: organizationSlug, projectId } = await props.params; const { slug: organizationSlug, projectId } = await props.params;
const currentOrganizationSlug = await getCurrentOrganizationSlug(); const organization = await getOrganization({organizationSlug});
if (currentOrganizationSlug !== organizationSlug) { if (!organization || organization?.slug !== organizationSlug) {
notFound(); notFound();
} }
const org = await db.query.organization.findFirst({ const org = await db.query.organization.findFirst({
where: eq(drizzleOrganization.slug, currentOrganizationSlug), where: eq(drizzleOrganization.slug, organization.slug),
}); });
if (!org) notFound(); if (!org) notFound();
@@ -42,7 +41,7 @@ export default async function RoutePage(props: PageParams<{ slug: string; projec
<div className="justify-between gap-2 sm:flex"> <div className="justify-between gap-2 sm:flex">
<PageTitle className="flex items-center"> <PageTitle className="flex items-center">
{proj.name} {proj.name}
<Link className={buttonVariants({ variant: "outline" })} href={`/dashboard/${currentOrganizationSlug}/projects/${proj.id}/edit`}> <Link className={buttonVariants({ variant: "outline" })} href={`/dashboard/${organization.slug}/projects/${proj.id}/edit`}>
<GearIcon className="w-7 h-7" /> <GearIcon className="w-7 h-7" />
</Link> </Link>
</PageTitle> </PageTitle>
@@ -1,36 +1,36 @@
import { PageParams } from "@/types/next"; import {PageParams} from "@/types/next";
import { Page, PageContent, PageHeader, PageTitle } from "@/features/layout/page"; import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
import { ProjectForm } from "@/components/wrappers/dashboard/projects/ProjectsForm/ProjectForm"; import {ProjectForm} from "@/components/wrappers/dashboard/projects/ProjectsForm/ProjectForm";
import { notFound } from "next/navigation"; import {notFound} from "next/navigation";
import { getCurrentOrganizationSlug } from "@/features/dashboard/organization-cookie"; import {db} from "@/db";
import {DatabaseWith, organization as drizzleOrganization} from "@/db/schema";
import { db } from "@/db"; import {eq} from "drizzle-orm";
import { DatabaseWith, organization as drizzleOrganization } from "@/db/schema"; import {getOrganization} from "@/lib/auth/auth";
import { eq } from "drizzle-orm";
export default async function RoutePage(props: PageParams<{ slug: string }>) { export default async function RoutePage(props: PageParams<{ slug: string }>) {
const { slug: organizationSlug } = await props.params; const {slug: organizationSlug} = await props.params;
const currentOrganizationSlug = await getCurrentOrganizationSlug(); const organization = await getOrganization({organizationSlug});
if (currentOrganizationSlug !== organizationSlug) {
if (!organization || organization?.slug !== organizationSlug) {
notFound(); notFound();
} }
const availableDatabases = ( const availableDatabases = (
await db.query.database.findMany({ await db.query.database.findMany({
where: (db, { isNull }) => isNull(db.projectId), where: (db, {isNull}) => isNull(db.projectId),
with: { with: {
agent: true, agent: true,
project: true, project: true,
backups: true, backups: true,
restorations: true, restorations: true,
}, },
orderBy: (db, { desc }) => [desc(db.createdAt)], orderBy: (db, {desc}) => [desc(db.createdAt)],
}) })
).filter((db) => db.project !== null) as DatabaseWith[]; ).filter((db) => db.project !== null) as DatabaseWith[];
const org = await db.query.organization.findFirst({ const org = await db.query.organization.findFirst({
where: eq(drizzleOrganization.slug, currentOrganizationSlug), where: eq(drizzleOrganization.slug, organization.slug),
}); });
if (!org) notFound(); if (!org) notFound();
@@ -41,7 +41,7 @@ export default async function RoutePage(props: PageParams<{ slug: string }>) {
<PageTitle>Create new project</PageTitle> <PageTitle>Create new project</PageTitle>
</PageHeader> </PageHeader>
<PageContent> <PageContent>
<ProjectForm databases={availableDatabases} organization={org} /> <ProjectForm databases={availableDatabases} organization={org}/>
</PageContent> </PageContent>
</Page> </Page>
); );
@@ -1,25 +1,29 @@
import Link from "next/link"; import Link from "next/link";
import { PageParams } from "@/types/next"; import {PageParams} from "@/types/next";
import { CardsWithPagination } from "@/components/wrappers/common/cards-with-pagination"; import {CardsWithPagination} from "@/components/wrappers/common/cards-with-pagination";
import { Button } from "@/components/ui/button"; import {Button} from "@/components/ui/button";
import { Page, PageActions, PageContent, PageHeader, PageTitle } from "@/features/layout/page"; import {Page, PageActions, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
import { ProjectCard } from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectCard"; import {ProjectCard} from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectCard";
import { db } from "@/db"; import {db} from "@/db";
import { notFound } from "next/navigation"; import {notFound} from "next/navigation";
import { getOrganization } from "@/lib/auth/auth"; import {getOrganization} from "@/lib/auth/auth";
export default async function RoutePage(props: PageParams<{ slug: string }>) { export default async function RoutePage(props: PageParams<{ slug: string }>) {
const { slug: organizationSlug } = await props.params; const {slug: organizationSlug} = await props.params;
const organization = await getOrganization(organizationSlug); const organization = await getOrganization({organizationSlug});
if (!organization || organization?.slug !== organizationSlug) { if (!organization || organization?.slug !== organizationSlug) {
notFound(); notFound();
} }
const projects = await db.query.project.findMany({ const projects = await db.query.project.findMany({
where: (project, { eq, and, not }) => and(eq(project.organizationId, organization.id), not(eq(project.isArchived, true))), where: (project, {
eq,
and,
not
}) => and(eq(project.organizationId, organization.id), not(eq(project.isArchived, true))),
with: { with: {
databases: true, databases: true,
}, },
@@ -40,7 +44,8 @@ export default async function RoutePage(props: PageParams<{ slug: string }>) {
<PageContent className="mt-10"> <PageContent className="mt-10">
{projects.length > 0 ? ( {projects.length > 0 ? (
<CardsWithPagination organizationSlug={organizationSlug} data={projects} cardItem={ProjectCard} cardsPerPage={4} numberOfColumns={1} /> <CardsWithPagination organizationSlug={organizationSlug} data={projects} cardItem={ProjectCard}
cardsPerPage={4} numberOfColumns={1}/>
) : ( ) : (
<Link <Link
href={`/dashboard/${organizationSlug}/projects/new`} href={`/dashboard/${organizationSlug}/projects/new`}
@@ -5,47 +5,21 @@ import {prisma} from "@/prisma";
import {requiredCurrentUser} from "@/auth/current-user"; import {requiredCurrentUser} from "@/auth/current-user";
import {notFound} from "next/navigation"; import {notFound} from "next/navigation";
import {OrganizationForm} from "@/components/wrappers/dashboard/organization/OrganizationForm/OrganizationForm"; import {OrganizationForm} from "@/components/wrappers/dashboard/organization/OrganizationForm/OrganizationForm";
import {getOrganization} from "@/lib/auth/auth";
export default async function RoutePage(props: PageParams<{ export default async function RoutePage(props: PageParams<{
slug: string; slug: string;
}>) { }>) {
const {slug: organizationSlug} = await props.params
const currentOrganizationSlug = await getCurrentOrganizationSlug() const {slug: organizationSlug} = await props.params;
const user = await requiredCurrentUser()
if(currentOrganizationSlug != organizationSlug) { const organization = await getOrganization({organizationSlug});
if (!organization) {
notFound() notFound()
} }
const organization = await prisma.organization.findUnique({
where:{
slug: currentOrganizationSlug,
},
include:{
users:{
include:{
user:{
}
},
where: {
user: {
id: {
not: user.id, // Exclude user with id: 1
},
},
},
}
}
})
const users = await prisma.user.findMany({
where: {
deleted: {not: true},
id: {not: user.id}
}
})
return( return(
<Page> <Page>
@@ -55,7 +29,7 @@ export default async function RoutePage(props: PageParams<{
</PageTitle> </PageTitle>
</PageHeader> </PageHeader>
<PageContent> <PageContent>
<OrganizationForm users={users} defaultValues={organization}/> <OrganizationForm members={organization.members} defaultValues={organization}/>
</PageContent> </PageContent>
</Page> </Page>
) )
@@ -1,6 +1,8 @@
import {prisma} from "@/prisma";
import {PageParams} from "@/types/next"; import {PageParams} from "@/types/next";
import {Page, PageActions, PageContent, PageDescription, PageHeader, PageTitle} from "@/features/layout/page"; import {Page, PageActions, PageContent, PageDescription, PageHeader, PageTitle} from "@/features/layout/page";
import {currentUser} from "@/lib/auth/current-user";
import {getOrganization} from "@/lib/auth/auth";
import {notFound} from "next/navigation";
import {requiredCurrentUser} from "@/auth/current-user"; import {requiredCurrentUser} from "@/auth/current-user";
import {SettingsTabs} from "@/components/wrappers/dashboard/settings/SettingsTabs/SettingsTabs"; import {SettingsTabs} from "@/components/wrappers/dashboard/settings/SettingsTabs/SettingsTabs";
import {getCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie"; import {getCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie";
@@ -8,45 +10,52 @@ import {
DeleteOrganizationButton DeleteOrganizationButton
} from "@/components/wrappers/dashboard/organization/DeleteOrganization/DeleteOrganizationButton"; } from "@/components/wrappers/dashboard/organization/DeleteOrganization/DeleteOrganizationButton";
import {EditButtonSettings} from "@/components/wrappers/dashboard/settings/EditButtonSettings/EditButtonSettings"; import {EditButtonSettings} from "@/components/wrappers/dashboard/settings/EditButtonSettings/EditButtonSettings";
import {notFound} from "next/navigation";
export default async function RoutePage(props: PageParams<{}>) { export default async function RoutePage(props: PageParams<{ slug: string }>) {
const user = await requiredCurrentUser() const {slug: organizationSlug} = await props.params;
const currentOrganizationSlug = await getCurrentOrganizationSlug() const user = await currentUser();
const organization = await prisma.organization.findUnique({ const organization = await getOrganization({organizationSlug});
where: {
slug: currentOrganizationSlug,
},
include: {
users:{
include:{
user: {}
}
}
}
})
const currentOrganizationUser = await prisma.userOrganization.findFirst({ if (!organization || organization?.slug !== organizationSlug) {
where:{ notFound();
userId: user.id,
organization:{
slug: currentOrganizationSlug != "" ? currentOrganizationSlug : "default",
}
}
})
if (currentOrganizationUser.role != "admin") {
notFound()
} }
const settings = await prisma.settings.findUnique({
where: { // const organization = await prisma.organization.findUnique({
name: "system" // where: {
} // slug: currentOrganizationSlug,
}) // },
// include: {
// users:{
// include:{
// user: {}
// }
// }
// }
// })
//
// const currentOrganizationUser = await prisma.userOrganization.findFirst({
// where:{
// userId: user.id,
// organization:{
// slug: currentOrganizationSlug != "" ? currentOrganizationSlug : "default",
// }
// }
// })
// if (currentOrganizationUser.role != "admin") {
// notFound()
// }
//
//
// const settings = await prisma.settings.findUnique({
// where: {
// name: "system"
// }
// })
return ( return (
<Page> <Page>
@@ -59,7 +68,7 @@ export default async function RoutePage(props: PageParams<{}>) {
</PageTitle> </PageTitle>
<PageActions> <PageActions>
{organization.slug != "default" ? {organization.slug != "default" ?
<DeleteOrganizationButton organizationSlug={currentOrganizationSlug}/> <DeleteOrganizationButton organizationSlug={organization.slug}/>
: null} : null}
</PageActions> </PageActions>
</PageHeader> </PageHeader>
@@ -67,7 +76,7 @@ export default async function RoutePage(props: PageParams<{}>) {
Manage your organization settings. Manage your organization settings.
</PageDescription> </PageDescription>
<PageContent> <PageContent>
<SettingsTabs settings={settings} currentUser={user} users={organization.users}/> {/*<SettingsTabs settings={settings} currentUser={user} users={organization.users}/>*/}
</PageContent> </PageContent>
</Page> </Page>
) )
-4
View File
@@ -12,8 +12,6 @@ export default async function Layout({ children }: { children: React.ReactNode }
if (!user) redirect("/login"); if (!user) redirect("/login");
return ( return (
// <HydrationZustand>
// <GlobalStoreProvider>
<> <>
<SidebarProvider> <SidebarProvider>
<div className="flex flex-col lg:flex-row w-full"> <div className="flex flex-col lg:flex-row w-full">
@@ -25,7 +23,5 @@ export default async function Layout({ children }: { children: React.ReactNode }
</div> </div>
</SidebarProvider> </SidebarProvider>
</> </>
// </GlobalStoreProvider>
// </HydrationZustand>
); );
} }
@@ -7,36 +7,36 @@ import { Form } from "@/components/ui/form";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { useMutation } from "@tanstack/react-query"; import { useMutation } from "@tanstack/react-query";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { Organization, User } from "@prisma/client";
import { MultiSelect } from "@/components/wrappers/common/multiselect/multi-select"; import { MultiSelect } from "@/components/wrappers/common/multiselect/multi-select";
import { OrganizationFormSchema, OrganizationFormType } from "@/components/wrappers/dashboard/organization/OrganizationForm/organization-form.schema"; import { OrganizationFormSchema, OrganizationFormType } from "@/components/wrappers/dashboard/organization/OrganizationForm/organization-form.schema";
import { createOrganizationAction, updateOrganizationAction } from "@/components/wrappers/dashboard/organization/organization.action"; import { updateOrganizationAction } from "@/components/wrappers/dashboard/organization/organization.action";
import { toast } from "sonner"; import { toast } from "sonner";
import {Member, Organization} from "better-auth/plugins";
export type organizationFormProps = { export type organizationFormProps = {
defaultValues?: Organization; defaultValues?: Organization;
users: User[]; members: Member[];
}; };
export const OrganizationForm = (props: organizationFormProps) => { export const OrganizationForm = (props: organizationFormProps) => {
const router = useRouter(); const router = useRouter();
const isCreate = !Boolean(props.defaultValues); const isCreate = !Boolean(props.defaultValues);
const formatUsersList = (users: User[]) => { const formatUsersList = (members: Member[]) => {
return users.map((user) => ({ return members.map((member) => ({
value: user.id, value: member.id,
label: `${user.name} | ${user.email}`, label: `${member.user.name} | ${member.user.email}`,
})); }));
}; };
const formatDefaultUsers = (users: OrganizationFormType["users"]): string[] => { const formatDefaultUsers = (members: OrganizationFormType["members"]): string[] => {
console.log(users); console.log(members);
return users.map((user) => user.userId); return members.map((member) => member.userId);
}; };
const formattedDefaultValues = { const formattedDefaultValues = {
...props.defaultValues, ...props.defaultValues,
users: !isCreate ? formatDefaultUsers(props.defaultValues?.users) : [], users: !isCreate ? formatDefaultUsers(props.defaultValues?.members) : [],
}; };
const form = useZodForm({ const form = useZodForm({
@@ -47,15 +47,15 @@ export const OrganizationForm = (props: organizationFormProps) => {
const mutation = useMutation({ const mutation = useMutation({
mutationFn: async (values: OrganizationFormType) => { mutationFn: async (values: OrganizationFormType) => {
console.log(values); console.log(values);
const organization = await updateOrganizationAction({ data: values, organizationId: props.defaultValues.id }); // const organization = await updateOrganizationAction({ data: values, organizationId: props.defaultValues.id });
console.log(organization); // console.log(organization);
if (organization.data.success) { // if (organization.data.success) {
toast.success(organization.data.actionSuccess.message); // // toast.success(organization.data.actionSuccess.message);
router.push(`/dashboard/${organization.data.value.slug}/settings`); // // router.push(`/dashboard/${organization.data.value.slug}/settings`);
router.refresh(); // // router.refresh();
} else { // } else {
toast.success(organization.data.actionError.message); // // toast.success(organization.data.actionError.message);
} // }
}, },
}); });
@@ -113,7 +113,7 @@ export const OrganizationForm = (props: organizationFormProps) => {
<FormLabel>Databases</FormLabel> <FormLabel>Databases</FormLabel>
<FormControl> <FormControl>
<MultiSelect <MultiSelect
options={formatUsersList(props.users)} options={formatUsersList(props.members)}
onValueChange={field.onChange} onValueChange={field.onChange}
defaultValue={field.value ?? []} defaultValue={field.value ?? []}
placeholder="Select databases" placeholder="Select databases"
@@ -7,7 +7,7 @@ export const OrganizationFormSchema = z.object({
.regex(/^[a-zA-Z0-9_-]*$/, 'Slug can only contain letters, numbers, underscores, and hyphens') .regex(/^[a-zA-Z0-9_-]*$/, 'Slug can only contain letters, numbers, underscores, and hyphens')
.min(5, 'Slug must be at least 5 characters long') .min(5, 'Slug must be at least 5 characters long')
.max(20, 'Slug must be at most 20 characters long'), .max(20, 'Slug must be at most 20 characters long'),
users: z.array(z.string()), members: z.array(z.string()),
}); });
@@ -1,5 +1,3 @@
import {User, UserOrganization} from "@prisma/client";
import {DataTableWithPagination} from "@/components/wrappers/common/table/data-table-with-pagination";
import {usersColumns} from "@/components/wrappers/dashboard/settings/SettingsUsersTab/columns-users-settings"; import {usersColumns} from "@/components/wrappers/dashboard/settings/SettingsUsersTab/columns-users-settings";
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table"; import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
import {flexRender, Row} from "@tanstack/react-table"; import {flexRender, Row} from "@tanstack/react-table";
@@ -7,13 +5,13 @@ import {cn} from "@/lib/utils";
export type SettingsUsersTabProps = { export type SettingsUsersTabProps = {
currentUser: User; // currentUser: User;
users: UserOrganization[] // users: UserOrganization[]
} }
export const SettingsUsersTab = (props: SettingsUsersTabProps) => { export const SettingsUsersTab = (props: SettingsUsersTabProps) => {
const {currentUser, users} = props; // const {currentUser, users} = props;
return ( return (
<div className="flex flex-col h-full py-4"> <div className="flex flex-col h-full py-4">
@@ -21,12 +19,12 @@ export const SettingsUsersTab = (props: SettingsUsersTabProps) => {
<h1>List of organization's users</h1> <h1>List of organization's users</h1>
</div> </div>
<div className="mt-5"> <div className="mt-5">
<DataTableWithPagination {/*<DataTableWithPagination*/}
columns={usersColumns} {/* columns={usersColumns}*/}
data={users} {/* data={users}*/}
DataTable={UsersDataTable} {/* DataTable={UsersDataTable}*/}
dataTableProps={{currentUser}} {/* dataTableProps={{currentUser}}*/}
/> {/*/>*/}
</div> </div>
</div> </div>
) )
@@ -35,63 +33,65 @@ export const SettingsUsersTab = (props: SettingsUsersTabProps) => {
export type usersDataTableProps = { export type usersDataTableProps = {
currentUser: User; // currentUser: User;
table: any, // table: any,
} }
export const UsersDataTable = ({currentUser, table}: usersDataTableProps) => { export const UsersDataTable = (
// {currentUser, table}: usersDataTableProps
) => {
return ( return (
<div className="rounded-md border w-full "> <div className="rounded-md border w-full ">
<Table className="w-full"> {/*<Table className="w-full">*/}
<TableHeader> {/* <TableHeader>*/}
{table.getHeaderGroups().map((headerGroup) => ( {/* {table.getHeaderGroups().map((headerGroup) => (*/}
<TableRow key={headerGroup.id}> {/* <TableRow key={headerGroup.id}>*/}
{headerGroup.headers.map((header) => { {/* {headerGroup.headers.map((header) => {*/}
return ( {/* return (*/}
<TableHead key={header.id}> {/* <TableHead key={header.id}>*/}
{header.isPlaceholder {/* {header.isPlaceholder*/}
? null {/* ? null*/}
: flexRender( {/* : flexRender(*/}
header.column.columnDef.header, {/* header.column.columnDef.header,*/}
header.getContext() {/* header.getContext()*/}
)} {/* )}*/}
</TableHead> {/* </TableHead>*/}
) {/* )*/}
})} {/* })}*/}
</TableRow> {/* </TableRow>*/}
))} {/* ))}*/}
</TableHeader> {/* </TableHeader>*/}
<TableBody> {/* <TableBody>*/}
{table.getRowModel().rows?.length ? ( {/* {table.getRowModel().rows?.length ? (*/}
table.getRowModel().rows.map((row: Row<UserOrganization>) => { {/* table.getRowModel().rows.map((row: Row<UserOrganization>) => {*/}
return( {/* return(*/}
<TableRow {/* <TableRow*/}
className={cn((row.original.userId) === currentUser.id ? "opacity-40 pointer-events-none" : "")} {/* className={cn((row.original.userId) === currentUser.id ? "opacity-40 pointer-events-none" : "")}*/}
key={row.id} {/* key={row.id}*/}
data-state={row.getIsSelected() && "selected"} {/* data-state={row.getIsSelected() && "selected"}*/}
> {/* >*/}
{row.getVisibleCells().map((cell) => ( {/* {row.getVisibleCells().map((cell) => (*/}
<TableCell key={cell.id}> {/* <TableCell key={cell.id}>*/}
{flexRender( {/* {flexRender(*/}
cell.column.columnDef.cell, {/* cell.column.columnDef.cell,*/}
cell.getContext(), {/* cell.getContext(),*/}
)} {/* )}*/}
</TableCell> {/* </TableCell>*/}
))} {/* ))}*/}
</TableRow> {/* </TableRow>*/}
) {/* )*/}
} {/* }*/}
)) : ( {/* )) : (*/}
<TableRow> {/* <TableRow>*/}
<TableCell colSpan={table.getAllColumns().length} className="h-24 text-center"> {/* <TableCell colSpan={table.getAllColumns().length} className="h-24 text-center">*/}
No results. {/* No results.*/}
</TableCell> {/* </TableCell>*/}
</TableRow> {/* </TableRow>*/}
)} {/* )}*/}
</TableBody> {/* </TableBody>*/}
</Table> {/*</Table>*/}
</div> </div>
) )
} }
@@ -9,17 +9,19 @@ import {
SidebarMenu as SM, SidebarMenu as SM,
SidebarMenuItem, SidebarMenuItem,
} from "@/components/ui/sidebar"; } from "@/components/ui/sidebar";
import { SidebarItem, SidebarMenu } from "@/components/wrappers/dashboard/sideBar/SideBarMenu/SideBarMenu"; import {SidebarItem, SidebarMenu} from "@/components/wrappers/dashboard/sideBar/SideBarMenu/SideBarMenu";
import { OrganizationCombobox } from "@/components/wrappers/dashboard/organization/organization-combobox"; import {OrganizationCombobox} from "@/components/wrappers/dashboard/organization/organization-combobox";
import { SideBarLogo } from "@/components/wrappers/dashboard/sideBar/SideBarLogo/SideBarLogo"; import {SideBarLogo} from "@/components/wrappers/dashboard/sideBar/SideBarLogo/SideBarLogo";
import { SideBarFooterCredit } from "@/components/wrappers/dashboard/sideBar/SideBarFooterCredit/SideBarFooterCredit"; import {SideBarFooterCredit} from "@/components/wrappers/dashboard/sideBar/SideBarFooterCredit/SideBarFooterCredit";
import { LoggedInButton } from "@/components/wrappers/dashboard/loggedInButton/LoggedInButton"; import {LoggedInButton} from "@/components/wrappers/dashboard/loggedInButton/LoggedInButton";
import { Layers, ChartArea, Settings, ShieldHalf } from "lucide-react"; import {Layers, ChartArea, Settings, ShieldHalf} from "lucide-react";
import { authClient } from "@/lib/auth/auth-client"; import {authClient} from "@/lib/auth/auth-client";
import { SidebarContentA } from "./sidebar-content"; import {SidebarContentA} from "./sidebar-content";
import {getActiveMember, getOrganization} from "@/lib/auth/auth";
import {notFound} from "next/navigation";
export async function AppSidebar() { export async function AppSidebar() {
/*const member = await getActiveMember(); const member = await getActiveMember();
console.log("member", member); console.log("member", member);
@@ -27,31 +29,33 @@ export async function AppSidebar() {
return notFound(); return notFound();
} }
const organization = await getOrganization(member.organizationId); const organization = await getOrganization({organizationId: member.organizationId});
//todo: à revoir //todo: à revoir
console.log("memebrer", member); console.log("membrer", member);
console.log("aoaoaoaoaoa", organization);*/ console.log("aoaoaoaoaoa", organization);
return ( return (
<Sidebar collapsible="icon"> <Sidebar collapsible="icon">
<SidebarHeader> <SidebarHeader>
<SideBarLogo /> <SideBarLogo/>
<SM> <SM>
<SidebarMenuItem> <SidebarMenuItem>
<OrganizationCombobox /> <OrganizationCombobox/>
</SidebarMenuItem> </SidebarMenuItem>
</SM> </SM>
</SidebarHeader> </SidebarHeader>
<SidebarContentA /> <SidebarContent>
<SidebarContentA/>
</SidebarContent>
<SidebarFooter> <SidebarFooter>
<SM> <SM>
<SidebarMenuItem> <SidebarMenuItem>
<LoggedInButton /> <LoggedInButton/>
</SidebarMenuItem> </SidebarMenuItem>
</SM> </SM>
<SideBarFooterCredit /> <SideBarFooterCredit/>
</SidebarFooter> </SidebarFooter>
</Sidebar> </Sidebar>
); );
@@ -7,10 +7,9 @@ import { SidebarItem, SidebarMenu } from "./SideBarMenu/SideBarMenu";
export const SidebarContentA = () => { export const SidebarContentA = () => {
const { data: activeOrganization } = authClient.useActiveOrganization(); const { data: activeOrganization } = authClient.useActiveOrganization();
const { data: organizations } = authClient.useListOrganizations(); const { data: organizations } = authClient.useListOrganizations();
const { data: session } = useSession(); const { data: session } = useSession();
const member = authClient.useActiveMember(); // Moved here — always called
console.log("sesssssion", session);
const appItems: SidebarItem[] = [ const appItems: SidebarItem[] = [
{ {
@@ -31,19 +30,15 @@ export const SidebarContentA = () => {
}, },
]; ];
if (activeOrganization) { if (activeOrganization && member?.data?.role === "admin" || member?.data?.role === "owner") {
const member = authClient.useActiveMember(); appItems.push({
type: "list",
if (member && member.data && (member.data.role === "admin" || member.data.role === "owner")) { content: {
appItems.push({ title: "Settings",
type: "list", url: "settings",
content: { icon: <Settings />,
title: "Settings", },
url: "settings", });
icon: <Settings />,
},
});
}
} }
const adminItems: SidebarItem[] = [ const adminItems: SidebarItem[] = [
@@ -67,22 +62,13 @@ export const SidebarContentA = () => {
return ( return (
activeOrganization && ( activeOrganization && (
<SidebarContent>
<SidebarGroup> <SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel> <SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent> <SidebarGroupContent>
<SidebarMenu items={appItems} baseUrl={`/dashboard/${activeOrganization.slug}`} /> <SidebarMenu items={appItems} baseUrl={`/dashboard/${activeOrganization.slug}`} />
</SidebarGroupContent> </SidebarGroupContent>
</SidebarGroup> </SidebarGroup>
{/*(user.role === "superadmin" || user.role === "admin") && (
<SidebarGroup>
<SidebarGroupLabel>Administration</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu items={adminItems} baseUrl={`/dashboard/${organization.slug}`} />
</SidebarGroupContent>
</SidebarGroup>
)*/}
</SidebarContent>
) )
); );
}; };
-15
View File
@@ -5,10 +5,6 @@ import packageJson from "../package.json" with { type: "json" };
const { version } = packageJson; const { version } = packageJson;
export const env = createEnv({ export const env = createEnv({
/*
* Serverside Environment variables, not available on the client.
* Will throw if you access these variables on the client.
*/
server: { server: {
NODE_ENV: z.enum(["development", "production"]).optional(), NODE_ENV: z.enum(["development", "production"]).optional(),
DATABASE_URL: z.string().url().optional(), DATABASE_URL: z.string().url().optional(),
@@ -36,23 +32,12 @@ export const env = createEnv({
STORAGE_TYPE: z.string().optional(), STORAGE_TYPE: z.string().optional(),
}, },
/*
* Environment variables available on the client (and server).
*
* 💡 You'll get type errors if these are not prefixed with NEXT_PUBLIC_.
*/
client: { client: {
NEXT_PUBLIC_PROJECT_NAME: z.string().optional(), NEXT_PUBLIC_PROJECT_NAME: z.string().optional(),
NEXT_PUBLIC_PROJECT_DESCRIPTION: z.string().optional(), NEXT_PUBLIC_PROJECT_DESCRIPTION: z.string().optional(),
NEXT_PUBLIC_PROJECT_URL: z.string(), NEXT_PUBLIC_PROJECT_URL: z.string(),
NEXT_PUBLIC_PROJECT_VERSION: z.string(), NEXT_PUBLIC_PROJECT_VERSION: z.string(),
}, },
/*
* Due to how Next.js bundles environment variables on Edge and Client,
* we need to manually destructure them to make sure all are included in bundle.
*
* 💡 You'll get type errors if not all variables from `server` & `client` are included here.
*/
runtimeEnv: { runtimeEnv: {
NEXT_PUBLIC_PROJECT_NAME: process.env.NEXT_PUBLIC_PROJECT_NAME, NEXT_PUBLIC_PROJECT_NAME: process.env.NEXT_PUBLIC_PROJECT_NAME,
NEXT_PUBLIC_PROJECT_DESCRIPTION: process.env.NEXT_PUBLIC_PROJECT_DESCRIPTION, NEXT_PUBLIC_PROJECT_DESCRIPTION: process.env.NEXT_PUBLIC_PROJECT_DESCRIPTION,
+35 -34
View File
@@ -1,13 +1,13 @@
import { betterAuth } from "better-auth"; import {betterAuth} from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle"; import {drizzleAdapter} from "better-auth/adapters/drizzle";
import { db } from "@/db"; import {db} from "@/db";
import { env } from "@/env.mjs"; import {env} from "@/env.mjs";
import { nextCookies } from "better-auth/next-js"; import {nextCookies} from "better-auth/next-js";
import { admin as adminPlugin, openAPI, organization } from "better-auth/plugins"; import {admin as adminPlugin, openAPI, organization} from "better-auth/plugins";
import { ac, admin, user, pending, superadmin, orgOwner, orgAdmin, orgMember } from "@/lib/auth/permissions"; import {ac, admin, orgAdmin, orgMember, orgOwner, pending, superadmin, user} from "@/lib/auth/permissions";
import { headers } from "next/headers"; import {headers} from "next/headers";
import { count, eq } from "drizzle-orm"; import {count, eq} from "drizzle-orm";
import * as drizzleUser from "@/db/schema/01_user"; import * as drizzleUser from "@/db/schema/01_user";
import * as drizzleOrganization from "@/db/schema/02_organization"; import * as drizzleOrganization from "@/db/schema/02_organization";
@@ -140,7 +140,7 @@ export const signInUser = async (email: string, password: string) => {
};*/ };*/
export const createUser = async (name: string, email: string, password: string, role: "user" | "pending" | "admin" | "superadmin" = "pending") => { export const createUser = async (name: string, email: string, password: string, role: "user" | "pending" | "admin" | "superadmin" = "pending") => {
const user = await auth.api.createUser({ return await auth.api.createUser({
headers: await headers(), headers: await headers(),
body: { body: {
name, name,
@@ -149,24 +149,18 @@ export const createUser = async (name: string, email: string, password: string,
role, role,
}, },
}); });
return user;
}; };
export const getSessions = async () => { export const getSessions = async () => {
const sessions = await auth.api.listSessions({ return await auth.api.listSessions({
headers: await headers(), headers: await headers(),
}); });
return sessions;
}; };
export const getSession = async () => { export const getSession = async () => {
const session = await auth.api.getSession({ return await auth.api.getSession({
headers: await headers(), headers: await headers(),
}); });
return session;
}; };
export const revokeSession = async (e: string) => { export const revokeSession = async (e: string) => {
@@ -182,11 +176,9 @@ export const revokeSession = async (e: string) => {
}; };
export const getAccounts = async () => { export const getAccounts = async () => {
const sessions = await auth.api.listUserAccounts({ return await auth.api.listUserAccounts({
headers: await headers(), headers: await headers(),
}); });
return sessions;
}; };
export const unlinkAccount = async (provider: string, account: string) => { export const unlinkAccount = async (provider: string, account: string) => {
@@ -203,26 +195,35 @@ export const unlinkAccount = async (provider: string, account: string) => {
} catch (e) {} } catch (e) {}
}; };
export const getOrganization = async (organizationSlug?: string) => { export const getOrganization = async ({
try { organizationId,
const organization = await auth.api.getFullOrganization({ organizationSlug,
headers: await headers(), }: {
query: { organizationId?: string;
organizationSlug, organizationSlug?: string;
}, }) => {
}); const query = organizationId
? { organizationId }
: { organizationSlug };
return organization; console.log(query);
} catch (e) {}
try {
return await auth.api.getFullOrganization({
headers: await headers(),
query,
});
} catch (e) {
console.error(e);
return null;
}
}; };
export const listOrganizations = async () => { export const listOrganizations = async () => {
try { try {
const organizations = await auth.api.listOrganizations({ return await auth.api.listOrganizations({
headers: await headers(), headers: await headers(),
}); });
return organizations;
} catch (e) {} } catch (e) {}
}; };