Working on role in workspace.

This commit is contained in:
charles-gauthereau
2024-12-31 10:54:18 +01:00
parent e1a7ca8558
commit 6f75079a40
29 changed files with 464 additions and 124 deletions
@@ -21,8 +21,6 @@ export default async function RoutePage(props: PageParams<{}>) {
} }
}) })
console.log(users)
const settings = await prisma.settings.findUnique({ const settings = await prisma.settings.findUnique({
where: { where: {
name: "system" name: "system"
@@ -1,7 +1,6 @@
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 {AgentForm} from "@/components/wrappers/dashboard/agent/AgentForm/AgentForm"; import {AgentForm} from "@/components/wrappers/dashboard/agent/AgentForm/AgentForm";
import {requiredCurrentUser} from "@/auth/current-user";
import {prisma} from "@/prisma"; import {prisma} from "@/prisma";
import {notFound} from "next/navigation"; import {notFound} from "next/navigation";
@@ -11,8 +10,6 @@ export default async function RoutePage(props: PageParams<{
}>) { }>) {
const {agentId} = await props.params const {agentId} = await props.params
const user = await requiredCurrentUser()
const agent = await prisma.agent.findUnique({ const agent = await prisma.agent.findUnique({
where: { where: {
id: agentId, id: agentId,
@@ -23,7 +20,6 @@ export default async function RoutePage(props: PageParams<{
notFound(); notFound();
} }
return ( return (
<Page> <Page>
<PageHeader> <PageHeader>
@@ -1,14 +1,11 @@
import Link from "next/link"; import Link from "next/link";
import {GearIcon} from "@radix-ui/react-icons"; import {GearIcon} from "@radix-ui/react-icons";
import {KeyRound} from "lucide-react";
import {prisma} from "@/prisma"; import {prisma} from "@/prisma";
import {PageParams} from "@/types/next"; import {PageParams} from "@/types/next";
import {Page, PageActions, PageContent, PageDescription, PageTitle} from "@/features/layout/page"; import {Page, PageContent, PageDescription, PageTitle} from "@/features/layout/page";
import {formatDateLastContact} from "@/utils/date-formatting"; import {formatDateLastContact} from "@/utils/date-formatting";
import {Button, buttonVariants} from "@/components/ui/button"; import {buttonVariants} from "@/components/ui/button";
import {Card, CardContent, CardHeader} from "@/components/ui/card"; import {Card, CardContent, CardHeader} from "@/components/ui/card";
import {AgentModalKey} from "@/components/wrappers/dashboard/agent/AgentModalKey/AgentModalKey";
import {CardsWithPagination} from "@/components/wrappers/common/cards-with-pagination"; import {CardsWithPagination} from "@/components/wrappers/common/cards-with-pagination";
import {DatabaseCard} from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectDatabaseCard"; import {DatabaseCard} from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectDatabaseCard";
import {AgentCardKey} from "@/components/wrappers/dashboard/agent/AgentCardKey/AgentCardKey"; import {AgentCardKey} from "@/components/wrappers/dashboard/agent/AgentCardKey/AgentCardKey";
@@ -1,10 +1,18 @@
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 {AgentForm} from "@/components/wrappers/dashboard/agent/AgentForm/AgentForm"; import {AgentForm} from "@/components/wrappers/dashboard/agent/AgentForm/AgentForm";
import {currentUser} from "@/auth/current-user";
import {notFound} from "next/navigation";
export default async function RoutePage(props: PageParams<{}>) { export default async function RoutePage(props: PageParams<{}>) {
const user = await currentUser();
if(user.role != "admin"){
notFound()
}
return ( return (
<Page> <Page>
<PageHeader> <PageHeader>
@@ -5,20 +5,14 @@ import {CardsWithPagination} from "@/components/wrappers/common/cards-with-pagin
import {Button} from "@/components/ui/button"; import {Button} from "@/components/ui/button";
import Link from 'next/link' import Link from 'next/link'
import {Page, PageActions, PageContent, PageHeader, PageTitle} from "@/features/layout/page"; import {Page, PageActions, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
// import {db} from "@/db";
import {enhance} from "@zenstackhq/runtime";
import {currentUser} from "@/auth/current-user"; import {currentUser} from "@/auth/current-user";
import {db} from "@/db";
export default async function RoutePage(props: PageParams<{}>) { export default async function RoutePage(props: PageParams<{}>) {
const user = await currentUser();
const db = enhance(prisma, {user: user});
const agents = await db.agent.findMany() const agents = await db.agent.findMany()
console.log("aaaa", agents)
return ( return (
<Page> <Page>
<PageHeader> <PageHeader>
@@ -0,0 +1,16 @@
import React from "react";
import {currentUser} from "@/auth/current-user";
import {notFound} from "next/navigation";
export default async function Layout({children}: { children: React.ReactNode }) {
const user = await currentUser()
if(user.role != "admin"){
notFound()
}
return (
<>
{children}
</>
)
}
@@ -3,15 +3,12 @@ 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 {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 {getCurrentOrganizationId, getCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie"; import {getCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie";
import {Button, buttonVariants} from "@/components/ui/button";
import {ButtonWithConfirm} from "@/components/wrappers/common/button/button-with-confirm";
import { import {
DeleteOrganizationButton DeleteOrganizationButton
} from "@/components/wrappers/dashboard/organization/DeleteOrganization/DeleteOrganizationButton"; } from "@/components/wrappers/dashboard/organization/DeleteOrganization/DeleteOrganizationButton";
import {GearIcon} from "@radix-ui/react-icons";
import Link from "next/link";
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<{}>) {
@@ -22,21 +19,27 @@ export default async function RoutePage(props: PageParams<{}>) {
const organization = await prisma.organization.findUnique({ const organization = await prisma.organization.findUnique({
where: { where: {
slug: currentOrganizationSlug, slug: currentOrganizationSlug,
},
include: {
users:{
include:{
user: {}
}
}
} }
}) })
const users = await prisma.user.findMany({ const currentOrganizationUser = await prisma.userOrganization.findFirst({
where: { where:{
organizations: { userId: user.id,
some: { organization:{
organizationId: organization.id slug: currentOrganizationSlug != "" ? currentOrganizationSlug : "default",
}, }
},
deleted: {not: true},
} }
}) })
if (currentOrganizationUser.role != "admin") {
notFound()
}
const settings = await prisma.settings.findUnique({ const settings = await prisma.settings.findUnique({
@@ -64,7 +67,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={users}/> <SettingsTabs settings={settings} currentUser={user} users={organization.users}/>
</PageContent> </PageContent>
</Page> </Page>
) )
+4 -1
View File
@@ -1,9 +1,12 @@
import {PageParams} from "@/types/next"; import {PageParams} from "@/types/next";
import {redirect} from "next/navigation"; import {redirect} from "next/navigation";
import {getCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie"; import {getCurrentOrganizationSlug, setCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie";
export default async function RoutePage(props: PageParams<{}>) { export default async function RoutePage(props: PageParams<{}>) {
const currentOrganizationSlug = await getCurrentOrganizationSlug() const currentOrganizationSlug = await getCurrentOrganizationSlug()
if (currentOrganizationSlug == "") {
redirect(`/dashboard/default/projects`)
}
redirect(`/dashboard/${currentOrganizationSlug}/projects`) redirect(`/dashboard/${currentOrganizationSlug}/projects`)
} }
+1 -1
View File
@@ -1,7 +1,7 @@
export default function Home() { export default function Home() {
return ( return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]"> <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<h1 className="text-3xl font-bold text-4xl leading-tight">Text</h1> <h1 className="text-3xl font-bold text-4xl leading-tight">Home landing page</h1>
</div> </div>
); );
} }
@@ -0,0 +1,11 @@
/*
Warnings:
- Added the required column `role` to the `users_organisations` table without a default value. This is not possible if the table is not empty.
*/
-- CreateEnum
CREATE TYPE "OrganizationRole" AS ENUM ('member', 'admin');
-- AlterTable
ALTER TABLE "users_organisations" ADD COLUMN "role" "OrganizationRole" NOT NULL;
+11 -5
View File
@@ -19,6 +19,11 @@ enum Role {
admin admin
} }
enum OrganizationRole {
member
admin
}
enum Dbms { enum Dbms {
postgresql postgresql
mysql mysql
@@ -115,13 +120,14 @@ model Organization {
} }
model UserOrganization { model UserOrganization {
id String @id() @default(cuid()) id String @id() @default(cuid())
createdAt DateTime @default(now()) @map("created_at") createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime? @updatedAt() @map("updated_at") updatedAt DateTime? @updatedAt() @map("updated_at")
userId String userId String
organizationId String organizationId String
user User @relation(fields: [userId], references: [id]) user User @relation(fields: [userId], references: [id])
organization Organization @relation(fields: [organizationId], references: [id]) organization Organization @relation(fields: [organizationId], references: [id])
role OrganizationRole
@@unique([userId, organizationId]) @@unique([userId, organizationId])
@@map("users_organisations") @@map("users_organisations")
+7
View File
@@ -112,11 +112,18 @@ model Organization extends Base {
@@map("organizations") @@map("organizations")
} }
enum OrganizationRole {
member
admin
}
model UserOrganization extends Base { model UserOrganization extends Base {
userId String userId String
organizationId String organizationId String
user User @relation(fields: [userId], references: [id]) user User @relation(fields: [userId], references: [id])
organization Organization @relation(fields: [organizationId], references: [id]) organization Organization @relation(fields: [organizationId], references: [id])
role OrganizationRole
@@unique([userId, organizationId]) @@unique([userId, organizationId])
@@map("users_organisations") @@map("users_organisations")
+10 -6
View File
@@ -117,14 +117,18 @@ export const {handlers, auth: baseAuth, signIn, signOut} = NextAuth({
const defaultOrganization = await prisma.organization.findUnique({ const defaultOrganization = await prisma.organization.findUnique({
where: {slug: "default"}, where: {slug: "default"},
include: {users: {}}
}); });
await prisma.userOrganization.create({ const organizationRole = defaultOrganization.users.length > 0 ? "member" : "admin"
data: {
userId: newUser.id, await prisma.userOrganization.create({
organizationId: defaultOrganization.id data: {
}, userId: newUser.id,
}); organizationId: defaultOrganization.id,
role: organizationRole
},
});
return role !== "pending"; return role !== "pending";
@@ -32,10 +32,13 @@ export const registerUserAction = action
where: {slug: "default"}, where: {slug: "default"},
}); });
const organizationRole = users.length > 0 ? "member" : "admin"
await prisma.userOrganization.create({ await prisma.userOrganization.create({
data: { data: {
userId: newUser.id, userId: newUser.id,
organizationId: defaultOrganization.id organizationId: defaultOrganization.id,
role:organizationRole
}, },
}); });
@@ -1,6 +1,6 @@
import {flexRender, Row, RowData} from "@tanstack/react-table"; import {flexRender, Row, RowData} from "@tanstack/react-table";
import {User} from "@prisma/client"; import {User, UserOrganization} from "@prisma/client";
import {DataTableWithPagination} from "@/components/wrappers/common/table/data-table-with-pagination"; import {DataTableWithPagination} from "@/components/wrappers/common/table/data-table-with-pagination";
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table"; import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
import {cn} from "@/lib/utils"; import {cn} from "@/lib/utils";
@@ -23,7 +23,7 @@ export const AdminUsersTable = (props: AdminUsersTableProps) => {
<DataTableWithPagination <DataTableWithPagination
columns={usersColumnsAdmin} columns={usersColumnsAdmin}
data={users} data={users}
DataTable={UsersDataTable} DataTable={UsersDataTableAdmin}
dataTableProps={{currentUser}} dataTableProps={{currentUser}}
/> />
</div> </div>
@@ -37,7 +37,7 @@ export type usersDataTableProps = {
table: any, table: any,
} }
export const UsersDataTable = ({currentUser, table}: usersDataTableProps) => { export const UsersDataTableAdmin = ({currentUser, table}: usersDataTableProps) => {
return ( return (
<div className="rounded-md border w-full "> <div className="rounded-md border w-full ">
@@ -62,22 +62,26 @@ export const UsersDataTable = ({currentUser, table}: usersDataTableProps) => {
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{table.getRowModel().rows?.length ? ( {table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row: Row<User>) => ( table.getRowModel().rows.map((row: Row<User>) => {
<TableRow return(
className={cn(row.original.id === currentUser.id ? "opacity-40 pointer-events-none" : "")} <TableRow
key={row.id} className={cn((row.original.id) === currentUser.id ? "opacity-40 pointer-events-none" : "")}
data-state={row.getIsSelected() && "selected"} key={row.id}
> data-state={row.getIsSelected() && "selected"}
{row.getVisibleCells().map((cell) => ( >
<TableCell key={cell.id}> {row.getVisibleCells().map((cell) => (
{flexRender( <TableCell key={cell.id}>
cell.column.columnDef.cell, {flexRender(
cell.getContext(), cell.column.columnDef.cell,
)} 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.
@@ -14,7 +14,7 @@ export const LoggedInButton = async () => {
return ( return (
<LoggedInDropdown> <LoggedInDropdown user={user}>
<SidebarMenuButton> <SidebarMenuButton>
<Avatar className="size-6"> <Avatar className="size-6">
<AvatarFallback>{user.name?.[0]}</AvatarFallback> <AvatarFallback>{user.name?.[0]}</AvatarFallback>
@@ -5,8 +5,11 @@ import {DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger
import {signOutAction} from "@/features/auth/auth.action"; import {signOutAction} from "@/features/auth/auth.action";
import {redirect} from "next/navigation"; import {redirect} from "next/navigation";
import {CircleUser, LogOut, ShieldHalf} from "lucide-react"; import {CircleUser, LogOut, ShieldHalf} from "lucide-react";
import {User} from "@prisma/client";
export type LoggedInDropdownProps = PropsWithChildren<{}> export type LoggedInDropdownProps = PropsWithChildren<{
user: User
}>
export const LoggedInDropdown = (props: LoggedInDropdownProps) => { export const LoggedInDropdown = (props: LoggedInDropdownProps) => {
@@ -27,14 +30,16 @@ export const LoggedInDropdown = (props: LoggedInDropdownProps) => {
<span>Account</span> <span>Account</span>
</div> </div>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={() => { {props.user.role == "admin" ?
redirect("/dashboard/admin") <DropdownMenuItem onClick={() => {
}}> redirect("/dashboard/admin")
<div className="flex justify-start items-center gap-2"> }}>
<ShieldHalf size={16}/> <div className="flex justify-start items-center gap-2">
<span>Administration Panel</span> <ShieldHalf size={16}/>
</div> <span>Administration Panel</span>
</DropdownMenuItem> </div>
</DropdownMenuItem>
: null}
<DropdownMenuItem onClick={() => { <DropdownMenuItem onClick={() => {
signOutAction() signOutAction()
}}> }}>
@@ -44,7 +44,8 @@ export const createOrganizationAction = userAction
await prisma.userOrganization.create({ await prisma.userOrganization.create({
data: { data: {
userId: ctx.user.id, userId: ctx.user.id,
organizationId: organization.id organizationId: organization.id,
role: "admin"
}, },
}); });
@@ -113,6 +114,7 @@ export const updateOrganizationAction = userAction
data: usersToAdd.map((userId) => ({ data: usersToAdd.map((userId) => ({
userId: userId, userId: userId,
organizationId: organization.id, organizationId: organization.id,
role: "member"
})), })),
skipDuplicates: true, // Optional: to avoid duplicate insertion errors skipDuplicates: true, // Optional: to avoid duplicate insertion errors
}); });
@@ -17,7 +17,7 @@ export const ButtonDeleteProject = (props: ButtonDeleteProjectProps) => {
const mutation = useMutation({ const mutation = useMutation({
mutationFn: () => deleteProjectAction(props.projectId), mutationFn: () => deleteProjectAction(props.projectId),
onSuccess: async (result) => { onSuccess: async (result) => {
router.push("/dashboard/projects") router.push("/dashboard")
if(result.data.success) { if(result.data.success) {
toast.success(result.data.actionSuccess.message); toast.success(result.data.actionSuccess.message);
} }
@@ -1,18 +1,12 @@
"use client" "use client"
import {Tabs, TabsContent, TabsList, TabsTrigger} from "@/components/ui/tabs"; import {User, Settings, 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 {User, Settings} from "@prisma/client";
import {backupColumns} from "@/features/backup/columns";
import {SettingsEmailTab} from "@/components/wrappers/dashboard/admin/AdminEmailTab/SettingsEmailTab";
import {SettingsStorageTab} from "@/components/wrappers/dashboard/admin/AdminStorageTab/SettingsStorageTab";
import {SettingsUsersTab} from "@/components/wrappers/dashboard/settings/SettingsUsersTab/SettingsUsersTab"; import {SettingsUsersTab} from "@/components/wrappers/dashboard/settings/SettingsUsersTab/SettingsUsersTab";
export type SettingsTabsProps = { export type SettingsTabsProps = {
currentUser: User; currentUser: User;
users: User[]; users: UserOrganization[];
settings: Settings; settings: Settings;
} }
@@ -1,12 +1,14 @@
import {User} from "@prisma/client"; import {User, UserOrganization} from "@prisma/client";
import {DataTableWithPagination} from "@/components/wrappers/common/table/data-table-with-pagination"; 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 {UsersDataTable} from "@/components/wrappers/dashboard/admin/admin-user-table"; import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
import {flexRender, Row} from "@tanstack/react-table";
import {cn} from "@/lib/utils";
export type SettingsUsersTabProps = { export type SettingsUsersTabProps = {
currentUser: User; currentUser: User;
users: User[] users: UserOrganization[]
} }
export const SettingsUsersTab = (props: SettingsUsersTabProps) => { export const SettingsUsersTab = (props: SettingsUsersTabProps) => {
@@ -28,4 +30,68 @@ export const SettingsUsersTab = (props: SettingsUsersTabProps) => {
</div> </div>
</div> </div>
) )
} }
export type usersDataTableProps = {
currentUser: User;
table: any,
}
export const UsersDataTable = ({currentUser, table}: usersDataTableProps) => {
return (
<div className="rounded-md border w-full ">
<Table className="w-full">
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
)
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row: Row<UserOrganization>) => {
return(
<TableRow
className={cn((row.original.userId) === currentUser.id ? "opacity-40 pointer-events-none" : "")}
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
)
}
)) : (
<TableRow>
<TableCell colSpan={table.getAllColumns().length} className="h-24 text-center">
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
)
}
@@ -2,7 +2,7 @@
import {ColumnDef} from "@tanstack/react-table" import {ColumnDef} from "@tanstack/react-table"
import {Badge} from "@/components/ui/badge"; import {Badge} from "@/components/ui/badge";
import {User} from "@prisma/client"; import {User, UserOrganization} from "@prisma/client";
import {updateUserAction} from "@/components/wrappers/dashboard/profile/UserForm/user-form.action"; import {updateUserAction} from "@/components/wrappers/dashboard/profile/UserForm/user-form.action";
import {useMutation} from "@tanstack/react-query"; import {useMutation} from "@tanstack/react-query";
import {toast} from "sonner"; import {toast} from "sonner";
@@ -12,7 +12,7 @@ import {Trash2} from "lucide-react";
import {deleteUserAction} from "@/components/wrappers/dashboard/profile/ButtonDeleteAccount/delete-account.action"; import {deleteUserAction} from "@/components/wrappers/dashboard/profile/ButtonDeleteAccount/delete-account.action";
import {ButtonWithLoading} from "@/components/wrappers/common/button/button-with-loading"; import {ButtonWithLoading} from "@/components/wrappers/common/button/button-with-loading";
export const usersColumns: ColumnDef<User>[] = [ export const usersColumns: ColumnDef<UserOrganization>[] = [
{ {
accessorKey: "role", accessorKey: "role",
header: "Role", header: "Role",
@@ -20,24 +20,24 @@ export const usersColumns: ColumnDef<User>[] = [
const router = useRouter(); const router = useRouter();
const [role, setRole] = useState<string>(row.getValue("role")) const [role, setRole] = useState<string>(row.getValue("role"))
const updateMutation = useMutation({ // const updateMutation = useMutation({
mutationFn: () => updateUserAction({id: row.original.id, data: {role: role}}), // mutationFn: () => updateUserAction({id: row.original.id, data: {role: role}}),
onSuccess: () => { // onSuccess: () => {
toast.success(`User updated successfully.`); // toast.success(`User updated successfully.`);
router.refresh() // router.refresh()
//
}, // },
onError: () => { // onError: () => {
toast.error(`An error occurred while updating user information.`); // toast.error(`An error occurred while updating user information.`);
}, // },
}); // });
const handleUpdateRole = async () => { const handleUpdateRole = async () => {
const nextRole = role === "admin" ? "pending" const nextRole = role === "admin" ? "member"
: role === "pending" ? "user" : role === "member" ? "user"
: "admin"; : "admin";
setRole(nextRole); setRole(nextRole);
await updateMutation.mutateAsync() // await updateMutation.mutateAsync()
}; };
return <Badge return <Badge
@@ -47,11 +47,11 @@ export const usersColumns: ColumnDef<User>[] = [
}, },
}, },
{ {
accessorKey: "name", accessorKey: "user.name",
header: "Name" header: "Name"
}, },
{ {
accessorKey: "email", accessorKey: "user.email",
header: "Email" header: "Email"
}, },
{ {
@@ -7,9 +7,11 @@ import {cn} from "@/lib/utils";
import {buttonVariants} from "@/components/ui/button"; import {buttonVariants} from "@/components/ui/button";
import {ChartArea, Layers, Settings, ShieldHalf} from "lucide-react"; import {ChartArea, Layers, Settings, ShieldHalf} from "lucide-react";
import {usePathname} from "next/navigation"; import {usePathname} from "next/navigation";
import {UserOrganization} from "@prisma/client";
export type SidebarMenuCustomProps = { export type SidebarMenuCustomProps = {
currentOrganizationSlug: string currentOrganizationSlug: string,
currentOrganizationUser: UserOrganization,
} }
export const SidebarMenuCustom = (props: SidebarMenuCustomProps) => { export const SidebarMenuCustom = (props: SidebarMenuCustomProps) => {
@@ -27,13 +29,17 @@ export const SidebarMenuCustom = (props: SidebarMenuCustomProps) => {
title: "Statistics", title: "Statistics",
url: "statistics", url: "statistics",
icon: ChartArea, icon: ChartArea,
}, }
{ ]
if (props.currentOrganizationUser.role === "admin") {
items.push({
title: "Settings", title: "Settings",
url: "settings", url: "settings",
icon: Settings, icon: Settings,
}, },)
] }
useEffect(() => { useEffect(() => {
const currentUrl = pathname; const currentUrl = pathname;
@@ -37,6 +37,15 @@ export async function AppSidebar() {
}) })
const currentOrganizationUser = await prisma.userOrganization.findFirst({
where:{
userId: user.id,
organization:{
slug: currentOrganizationSlug != "" ? currentOrganizationSlug : "default",
}
}
})
return ( return (
<Sidebar collapsible="icon"> <Sidebar collapsible="icon">
@@ -57,7 +66,7 @@ export async function AppSidebar() {
<SidebarGroup> <SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel> <SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent> <SidebarGroupContent>
<SidebarMenuCustom currentOrganizationSlug={currentOrganizationSlug}/> <SidebarMenuCustom currentOrganizationUser={currentOrganizationUser} currentOrganizationSlug={currentOrganizationSlug}/>
</SidebarGroupContent> </SidebarGroupContent>
</SidebarGroup> </SidebarGroup>
{user.role == "admin" ? {user.role == "admin" ?
+17 -6
View File
@@ -3,6 +3,7 @@
import {redirect} from "next/navigation"; import {redirect} from "next/navigation";
import {signIn, signOut} from "@/auth/auth"; import {signIn, signOut} from "@/auth/auth";
import {getServerUrl} from "@/utils/get-server-url"; import {getServerUrl} from "@/utils/get-server-url";
import {deleteOrganizationCookie} from "@/features/dashboard/organization-cookie";
// //
// const baseUrl = getServerUrl(); // const baseUrl = getServerUrl();
// async function fetchCsrfToken() { // async function fetchCsrfToken() {
@@ -35,13 +36,23 @@ import {getServerUrl} from "@/utils/get-server-url";
// } // }
// } // }
// //
export const signOutAction = async () => { export const signOutAction = async () => {
// await manualSignOut() const deleteCookieResponse = await deleteOrganizationCookie();
await signOut({redirectTo: '/', redirect: true}) await signOut({ redirectTo: '/', redirect: true });
window.location.reload();
} if (typeof window !== 'undefined') {
window.location.reload();
}
return deleteCookieResponse;
};
//
// export const signOutAction = async () => {
// // await manualSignOut()
// await signOut({redirectTo: '/', redirect: true})
// await deleteOrganizationCookie()
// window.location.reload();
// }
export const signInAction = async (type: string, formData?: any) => { export const signInAction = async (type: string, formData?: any) => {
if (type === "google") { if (type === "google") {
await signIn(type, {redirectTo: '/dashboard'}) await signIn(type, {redirectTo: '/dashboard'})
@@ -2,7 +2,6 @@
import {cookies} from 'next/headers'; import {cookies} from 'next/headers';
const COOKIE_NAME = 'PORTABASE_ORGANIZATION_SLUG'; const COOKIE_NAME = 'PORTABASE_ORGANIZATION_SLUG';
export async function getCurrentOrganizationSlug() { export async function getCurrentOrganizationSlug() {
@@ -11,4 +10,8 @@ export async function getCurrentOrganizationSlug() {
export async function setCurrentOrganizationSlug(slug: string) { export async function setCurrentOrganizationSlug(slug: string) {
return (await cookies()).set(COOKIE_NAME, slug).get(COOKIE_NAME)?.value; return (await cookies()).set(COOKIE_NAME, slug).get(COOKIE_NAME)?.value;
} }
export async function deleteOrganizationCookie() {
return (await cookies()).delete(COOKIE_NAME);
}
+3
View File
@@ -346,6 +346,9 @@ const metadata = {
backLink: 'users', backLink: 'users',
isRelationOwner: true, isRelationOwner: true,
foreignKeyMapping: { "id": "organizationId" }, foreignKeyMapping: { "id": "organizationId" },
}, role: {
name: "role",
type: "OrganizationRole",
}, },
} }
, uniqueConstraints: { , uniqueConstraints: {
+2 -1
View File
@@ -327,8 +327,9 @@ export function useSuspenseCountUserOrganization<TArgs extends Prisma.UserOrgani
const { endpoint, fetch } = getHooksContext(); const { endpoint, fetch } = getHooksContext();
return useSuspenseModelQuery<TQueryFnData, TData, TError>('UserOrganization', `${endpoint}/userOrganization/count`, args, options, fetch); return useSuspenseModelQuery<TQueryFnData, TData, TError>('UserOrganization', `${endpoint}/userOrganization/count`, args, options, fetch);
} }
import type { OrganizationRole } from '@prisma/client';
export function useCheckUserOrganization<TError = DefaultError>(args: { operation: PolicyCrudKind; where?: { id?: string; userId?: string; organizationId?: string }; }, options?: (Omit<UseQueryOptions<boolean, TError, boolean>, 'queryKey'> & ExtraQueryOptions)) { export function useCheckUserOrganization<TError = DefaultError>(args: { operation: PolicyCrudKind; where?: { id?: string; userId?: string; organizationId?: string; role?: OrganizationRole }; }, options?: (Omit<UseQueryOptions<boolean, TError, boolean>, 'queryKey'> & ExtraQueryOptions)) {
const { endpoint, fetch } = getHooksContext(); const { endpoint, fetch } = getHooksContext();
return useModelQuery<boolean, boolean, TError>('UserOrganization', `${endpoint}/userOrganization/check`, args, options, fetch); return useModelQuery<boolean, boolean, TError>('UserOrganization', `${endpoint}/userOrganization/check`, args, options, fetch);
} }
+190
View File
@@ -35,6 +35,11 @@ components:
- pending - pending
- user - user
- admin - admin
OrganizationRole:
type: string
enum:
- member
- admin
Dbms: Dbms:
type: string type: string
enum: enum:
@@ -119,6 +124,7 @@ components:
- updatedAt - updatedAt
- userId - userId
- organizationId - organizationId
- role
ProjectScalarFieldEnum: ProjectScalarFieldEnum:
type: string type: string
enum: enum:
@@ -434,6 +440,8 @@ components:
$ref: "#/components/schemas/User" $ref: "#/components/schemas/User"
organization: organization:
$ref: "#/components/schemas/Organization" $ref: "#/components/schemas/Organization"
role:
$ref: "#/components/schemas/OrganizationRole"
required: required:
- id - id
- createdAt - createdAt
@@ -441,6 +449,7 @@ components:
- organizationId - organizationId
- user - user
- organization - organization
- role
Project: Project:
type: object type: object
properties: properties:
@@ -1823,6 +1832,10 @@ components:
oneOf: oneOf:
- $ref: "#/components/schemas/StringFilter" - $ref: "#/components/schemas/StringFilter"
- type: string - type: string
role:
oneOf:
- $ref: "#/components/schemas/EnumOrganizationRoleFilter"
- $ref: "#/components/schemas/OrganizationRole"
user: user:
oneOf: oneOf:
- $ref: "#/components/schemas/UserScalarRelationFilter" - $ref: "#/components/schemas/UserScalarRelationFilter"
@@ -1846,6 +1859,8 @@ components:
$ref: "#/components/schemas/SortOrder" $ref: "#/components/schemas/SortOrder"
organizationId: organizationId:
$ref: "#/components/schemas/SortOrder" $ref: "#/components/schemas/SortOrder"
role:
$ref: "#/components/schemas/SortOrder"
user: user:
$ref: "#/components/schemas/UserOrderByWithRelationInput" $ref: "#/components/schemas/UserOrderByWithRelationInput"
organization: organization:
@@ -1893,6 +1908,10 @@ components:
oneOf: oneOf:
- $ref: "#/components/schemas/StringFilter" - $ref: "#/components/schemas/StringFilter"
- type: string - type: string
role:
oneOf:
- $ref: "#/components/schemas/EnumOrganizationRoleFilter"
- $ref: "#/components/schemas/OrganizationRole"
user: user:
oneOf: oneOf:
- $ref: "#/components/schemas/UserScalarRelationFilter" - $ref: "#/components/schemas/UserScalarRelationFilter"
@@ -1943,6 +1962,10 @@ components:
oneOf: oneOf:
- $ref: "#/components/schemas/StringWithAggregatesFilter" - $ref: "#/components/schemas/StringWithAggregatesFilter"
- type: string - type: string
role:
oneOf:
- $ref: "#/components/schemas/EnumOrganizationRoleWithAggregatesFilter"
- $ref: "#/components/schemas/OrganizationRole"
ProjectWhereInput: ProjectWhereInput:
type: object type: object
properties: properties:
@@ -4093,11 +4116,14 @@ components:
- type: "null" - type: "null"
- type: string - type: string
format: date-time format: date-time
role:
$ref: "#/components/schemas/OrganizationRole"
user: user:
$ref: "#/components/schemas/UserCreateNestedOneWithoutOrganizationsInput" $ref: "#/components/schemas/UserCreateNestedOneWithoutOrganizationsInput"
organization: organization:
$ref: "#/components/schemas/OrganizationCreateNestedOneWithoutUsersInput" $ref: "#/components/schemas/OrganizationCreateNestedOneWithoutUsersInput"
required: required:
- role
- user - user
- organization - organization
UserOrganizationUpdateInput: UserOrganizationUpdateInput:
@@ -4118,6 +4144,10 @@ components:
format: date-time format: date-time
- $ref: "#/components/schemas/NullableDateTimeFieldUpdateOperationsInput" - $ref: "#/components/schemas/NullableDateTimeFieldUpdateOperationsInput"
- type: "null" - type: "null"
role:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/EnumOrganizationRoleFieldUpdateOperationsInput"
user: user:
$ref: "#/components/schemas/UserUpdateOneRequiredWithoutOrganizationsNestedInpu\ $ref: "#/components/schemas/UserUpdateOneRequiredWithoutOrganizationsNestedInpu\
t" t"
@@ -4141,9 +4171,12 @@ components:
type: string type: string
organizationId: organizationId:
type: string type: string
role:
$ref: "#/components/schemas/OrganizationRole"
required: required:
- userId - userId
- organizationId - organizationId
- role
UserOrganizationUpdateManyMutationInput: UserOrganizationUpdateManyMutationInput:
type: object type: object
properties: properties:
@@ -4162,6 +4195,10 @@ components:
format: date-time format: date-time
- $ref: "#/components/schemas/NullableDateTimeFieldUpdateOperationsInput" - $ref: "#/components/schemas/NullableDateTimeFieldUpdateOperationsInput"
- type: "null" - type: "null"
role:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/EnumOrganizationRoleFieldUpdateOperationsInput"
ProjectCreateInput: ProjectCreateInput:
type: object type: object
properties: properties:
@@ -5642,6 +5679,23 @@ components:
properties: properties:
_count: _count:
$ref: "#/components/schemas/SortOrder" $ref: "#/components/schemas/SortOrder"
EnumOrganizationRoleFilter:
type: object
properties:
equals:
$ref: "#/components/schemas/OrganizationRole"
in:
type: array
items:
$ref: "#/components/schemas/OrganizationRole"
notIn:
type: array
items:
$ref: "#/components/schemas/OrganizationRole"
not:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/NestedEnumOrganizationRoleFilter"
OrganizationScalarRelationFilter: OrganizationScalarRelationFilter:
type: object type: object
properties: properties:
@@ -5659,6 +5713,29 @@ components:
required: required:
- userId - userId
- organizationId - organizationId
EnumOrganizationRoleWithAggregatesFilter:
type: object
properties:
equals:
$ref: "#/components/schemas/OrganizationRole"
in:
type: array
items:
$ref: "#/components/schemas/OrganizationRole"
notIn:
type: array
items:
$ref: "#/components/schemas/OrganizationRole"
not:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/NestedEnumOrganizationRoleWithAggregatesFilter"
_count:
$ref: "#/components/schemas/NestedIntFilter"
_min:
$ref: "#/components/schemas/NestedEnumOrganizationRoleFilter"
_max:
$ref: "#/components/schemas/NestedEnumOrganizationRoleFilter"
BoolFilter: BoolFilter:
type: object type: object
properties: properties:
@@ -7025,6 +7102,11 @@ components:
$ref: "#/components/schemas/OrganizationCreateOrConnectWithoutUsersInput" $ref: "#/components/schemas/OrganizationCreateOrConnectWithoutUsersInput"
connect: connect:
$ref: "#/components/schemas/OrganizationWhereUniqueInput" $ref: "#/components/schemas/OrganizationWhereUniqueInput"
EnumOrganizationRoleFieldUpdateOperationsInput:
type: object
properties:
set:
$ref: "#/components/schemas/OrganizationRole"
UserUpdateOneRequiredWithoutOrganizationsNestedInput: UserUpdateOneRequiredWithoutOrganizationsNestedInput:
type: object type: object
properties: properties:
@@ -8654,6 +8736,46 @@ components:
$ref: "#/components/schemas/NestedBoolNullableFilter" $ref: "#/components/schemas/NestedBoolNullableFilter"
_max: _max:
$ref: "#/components/schemas/NestedBoolNullableFilter" $ref: "#/components/schemas/NestedBoolNullableFilter"
NestedEnumOrganizationRoleFilter:
type: object
properties:
equals:
$ref: "#/components/schemas/OrganizationRole"
in:
type: array
items:
$ref: "#/components/schemas/OrganizationRole"
notIn:
type: array
items:
$ref: "#/components/schemas/OrganizationRole"
not:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/NestedEnumOrganizationRoleFilter"
NestedEnumOrganizationRoleWithAggregatesFilter:
type: object
properties:
equals:
$ref: "#/components/schemas/OrganizationRole"
in:
type: array
items:
$ref: "#/components/schemas/OrganizationRole"
notIn:
type: array
items:
$ref: "#/components/schemas/OrganizationRole"
not:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/NestedEnumOrganizationRoleWithAggregatesFilter"
_count:
$ref: "#/components/schemas/NestedIntFilter"
_min:
$ref: "#/components/schemas/NestedEnumOrganizationRoleFilter"
_max:
$ref: "#/components/schemas/NestedEnumOrganizationRoleFilter"
NestedBoolFilter: NestedBoolFilter:
type: object type: object
properties: properties:
@@ -9535,9 +9657,12 @@ components:
- type: "null" - type: "null"
- type: string - type: string
format: date-time format: date-time
role:
$ref: "#/components/schemas/OrganizationRole"
organization: organization:
$ref: "#/components/schemas/OrganizationCreateNestedOneWithoutUsersInput" $ref: "#/components/schemas/OrganizationCreateNestedOneWithoutUsersInput"
required: required:
- role
- organization - organization
UserOrganizationUncheckedCreateWithoutUserInput: UserOrganizationUncheckedCreateWithoutUserInput:
type: object type: object
@@ -9554,8 +9679,11 @@ components:
format: date-time format: date-time
organizationId: organizationId:
type: string type: string
role:
$ref: "#/components/schemas/OrganizationRole"
required: required:
- organizationId - organizationId
- role
UserOrganizationCreateOrConnectWithoutUserInput: UserOrganizationCreateOrConnectWithoutUserInput:
type: object type: object
properties: properties:
@@ -9878,6 +10006,10 @@ components:
oneOf: oneOf:
- $ref: "#/components/schemas/StringFilter" - $ref: "#/components/schemas/StringFilter"
- type: string - type: string
role:
oneOf:
- $ref: "#/components/schemas/EnumOrganizationRoleFilter"
- $ref: "#/components/schemas/OrganizationRole"
ProjectCreateWithoutOrganizationInput: ProjectCreateWithoutOrganizationInput:
type: object type: object
properties: properties:
@@ -9965,9 +10097,12 @@ components:
- type: "null" - type: "null"
- type: string - type: string
format: date-time format: date-time
role:
$ref: "#/components/schemas/OrganizationRole"
user: user:
$ref: "#/components/schemas/UserCreateNestedOneWithoutOrganizationsInput" $ref: "#/components/schemas/UserCreateNestedOneWithoutOrganizationsInput"
required: required:
- role
- user - user
UserOrganizationUncheckedCreateWithoutOrganizationInput: UserOrganizationUncheckedCreateWithoutOrganizationInput:
type: object type: object
@@ -9984,8 +10119,11 @@ components:
format: date-time format: date-time
userId: userId:
type: string type: string
role:
$ref: "#/components/schemas/OrganizationRole"
required: required:
- userId - userId
- role
UserOrganizationCreateOrConnectWithoutOrganizationInput: UserOrganizationCreateOrConnectWithoutOrganizationInput:
type: object type: object
properties: properties:
@@ -12664,8 +12802,11 @@ components:
format: date-time format: date-time
organizationId: organizationId:
type: string type: string
role:
$ref: "#/components/schemas/OrganizationRole"
required: required:
- organizationId - organizationId
- role
AccountUpdateWithoutUserInput: AccountUpdateWithoutUserInput:
type: object type: object
properties: properties:
@@ -12960,6 +13101,10 @@ components:
format: date-time format: date-time
- $ref: "#/components/schemas/NullableDateTimeFieldUpdateOperationsInput" - $ref: "#/components/schemas/NullableDateTimeFieldUpdateOperationsInput"
- type: "null" - type: "null"
role:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/EnumOrganizationRoleFieldUpdateOperationsInput"
organization: organization:
$ref: "#/components/schemas/OrganizationUpdateOneRequiredWithoutUsersNestedInpu\ $ref: "#/components/schemas/OrganizationUpdateOneRequiredWithoutUsersNestedInpu\
t" t"
@@ -12985,6 +13130,10 @@ components:
oneOf: oneOf:
- type: string - type: string
- $ref: "#/components/schemas/StringFieldUpdateOperationsInput" - $ref: "#/components/schemas/StringFieldUpdateOperationsInput"
role:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/EnumOrganizationRoleFieldUpdateOperationsInput"
UserOrganizationUncheckedUpdateManyWithoutUserInput: UserOrganizationUncheckedUpdateManyWithoutUserInput:
type: object type: object
properties: properties:
@@ -13007,6 +13156,10 @@ components:
oneOf: oneOf:
- type: string - type: string
- $ref: "#/components/schemas/StringFieldUpdateOperationsInput" - $ref: "#/components/schemas/StringFieldUpdateOperationsInput"
role:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/EnumOrganizationRoleFieldUpdateOperationsInput"
ProjectCreateManyOrganizationInput: ProjectCreateManyOrganizationInput:
type: object type: object
properties: properties:
@@ -13044,8 +13197,11 @@ components:
format: date-time format: date-time
userId: userId:
type: string type: string
role:
$ref: "#/components/schemas/OrganizationRole"
required: required:
- userId - userId
- role
ProjectUpdateWithoutOrganizationInput: ProjectUpdateWithoutOrganizationInput:
type: object type: object
properties: properties:
@@ -13159,6 +13315,10 @@ components:
format: date-time format: date-time
- $ref: "#/components/schemas/NullableDateTimeFieldUpdateOperationsInput" - $ref: "#/components/schemas/NullableDateTimeFieldUpdateOperationsInput"
- type: "null" - type: "null"
role:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/EnumOrganizationRoleFieldUpdateOperationsInput"
user: user:
$ref: "#/components/schemas/UserUpdateOneRequiredWithoutOrganizationsNestedInpu\ $ref: "#/components/schemas/UserUpdateOneRequiredWithoutOrganizationsNestedInpu\
t" t"
@@ -13184,6 +13344,10 @@ components:
oneOf: oneOf:
- type: string - type: string
- $ref: "#/components/schemas/StringFieldUpdateOperationsInput" - $ref: "#/components/schemas/StringFieldUpdateOperationsInput"
role:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/EnumOrganizationRoleFieldUpdateOperationsInput"
UserOrganizationUncheckedUpdateManyWithoutOrganizationInput: UserOrganizationUncheckedUpdateManyWithoutOrganizationInput:
type: object type: object
properties: properties:
@@ -13206,6 +13370,10 @@ components:
oneOf: oneOf:
- type: string - type: string
- $ref: "#/components/schemas/StringFieldUpdateOperationsInput" - $ref: "#/components/schemas/StringFieldUpdateOperationsInput"
role:
oneOf:
- $ref: "#/components/schemas/OrganizationRole"
- $ref: "#/components/schemas/EnumOrganizationRoleFieldUpdateOperationsInput"
DatabaseCreateManyProjectInput: DatabaseCreateManyProjectInput:
type: object type: object
properties: properties:
@@ -14377,6 +14545,8 @@ components:
oneOf: oneOf:
- type: boolean - type: boolean
- $ref: "#/components/schemas/OrganizationArgs" - $ref: "#/components/schemas/OrganizationArgs"
role:
type: boolean
ProjectSelect: ProjectSelect:
type: object type: object
properties: properties:
@@ -14897,6 +15067,8 @@ components:
type: boolean type: boolean
organizationId: organizationId:
type: boolean type: boolean
role:
type: boolean
_all: _all:
type: boolean type: boolean
UserOrganizationMinAggregateInput: UserOrganizationMinAggregateInput:
@@ -14912,6 +15084,8 @@ components:
type: boolean type: boolean
organizationId: organizationId:
type: boolean type: boolean
role:
type: boolean
UserOrganizationMaxAggregateInput: UserOrganizationMaxAggregateInput:
type: object type: object
properties: properties:
@@ -14925,6 +15099,8 @@ components:
type: boolean type: boolean
organizationId: organizationId:
type: boolean type: boolean
role:
type: boolean
ProjectCountAggregateInput: ProjectCountAggregateInput:
type: object type: object
properties: properties:
@@ -15674,6 +15850,8 @@ components:
type: string type: string
organizationId: organizationId:
type: string type: string
role:
$ref: "#/components/schemas/OrganizationRole"
_count: _count:
oneOf: oneOf:
- type: "null" - type: "null"
@@ -15691,6 +15869,7 @@ components:
- createdAt - createdAt
- userId - userId
- organizationId - organizationId
- role
AggregateProject: AggregateProject:
type: object type: object
properties: properties:
@@ -16666,6 +16845,8 @@ components:
type: integer type: integer
organizationId: organizationId:
type: integer type: integer
role:
type: integer
_all: _all:
type: integer type: integer
required: required:
@@ -16674,6 +16855,7 @@ components:
- updatedAt - updatedAt
- userId - userId
- organizationId - organizationId
- role
- _all - _all
UserOrganizationMinAggregateOutputType: UserOrganizationMinAggregateOutputType:
type: object type: object
@@ -16700,6 +16882,10 @@ components:
oneOf: oneOf:
- type: "null" - type: "null"
- type: string - type: string
role:
oneOf:
- type: "null"
- $ref: "#/components/schemas/OrganizationRole"
UserOrganizationMaxAggregateOutputType: UserOrganizationMaxAggregateOutputType:
type: object type: object
properties: properties:
@@ -16725,6 +16911,10 @@ components:
oneOf: oneOf:
- type: "null" - type: "null"
- type: string - type: string
role:
oneOf:
- type: "null"
- $ref: "#/components/schemas/OrganizationRole"
ProjectCountAggregateOutputType: ProjectCountAggregateOutputType:
type: object type: object
properties: properties: