diff --git a/src/components/Manage/User/Create/create-account-step.tsx b/src/components/Manage/User/Create/create-account-step.tsx index b06531559..d2fda30c6 100644 --- a/src/components/Manage/User/Create/create-account-step.tsx +++ b/src/components/Manage/User/Create/create-account-step.tsx @@ -5,13 +5,15 @@ import { z } from 'zod'; interface CreateAccountStepProps { nextStep: ({ eMail, username }: { username: string; eMail: string }) => void; + defaultUsername: string; + defaultEmail: string; } -export const CreateAccountStep = ({ nextStep }: CreateAccountStepProps) => { +export const CreateAccountStep = ({ defaultEmail, defaultUsername, nextStep }: CreateAccountStepProps) => { const form = useForm({ initialValues: { - username: '', - eMail: '', + username: defaultUsername, + eMail: defaultEmail, }, validateInputOnBlur: true, validateInputOnChange: true, diff --git a/src/components/Manage/User/Create/security-step.tsx b/src/components/Manage/User/Create/security-step.tsx index afccbacd6..17143faa5 100644 --- a/src/components/Manage/User/Create/security-step.tsx +++ b/src/components/Manage/User/Create/security-step.tsx @@ -43,17 +43,19 @@ function getStrength(password: string) { } interface CreateAccountSecurityStepProps { + defaultPassword: string; nextStep: ({ password }: { password: string }) => void; prevStep: () => void; } export const CreateAccountSecurityStep = ({ + defaultPassword, nextStep, prevStep, }: CreateAccountSecurityStepProps) => { const form = useForm({ initialValues: { - password: '', + password: defaultPassword, }, validateInputOnBlur: true, validateInputOnChange: true, diff --git a/src/components/layout/Templates/ManageLayout.tsx b/src/components/layout/Templates/ManageLayout.tsx index 2dfc71fff..18a7dc86b 100644 --- a/src/components/layout/Templates/ManageLayout.tsx +++ b/src/components/layout/Templates/ManageLayout.tsx @@ -26,6 +26,7 @@ import { IconUser, IconUsers, } from '@tabler/icons-react'; +import { useSession } from 'next-auth/react'; import Image from 'next/image'; import Link from 'next/link'; import { ReactNode } from 'react'; @@ -47,6 +48,9 @@ export const ManageLayout = ({ children }: ManageLayoutProps) => { const [burgerMenuOpen, { toggle: toggleBurgerMenu, close: closeBurgerMenu }] = useDisclosure(false); + const data = useSession(); + const isAdmin = data.data?.user.isAdmin ?? false; + const navigationLinks = ( <> { component={Link} href="/manage/boards" /> - - - - } - > - } - label="Manage" - component={Link} - href="/manage/users" - /> - } - label="Invites" - component={Link} - href="/manage/users/invites" - /> - - - - - } - component={Link} - href="/manage/settings" - /> + + {isAdmin && ( + <> + + + + } + > + } + label="Manage" + component={Link} + href="/manage/users" + /> + } + label="Invites" + component={Link} + href="/manage/users/invites" + /> + + + + + } + component={Link} + href="/manage/settings" + /> + + )} + { }> {t('actions.avatar.defaultBoard')} + }> + Manage + )} diff --git a/src/pages/manage/boards/index.tsx b/src/pages/manage/boards/index.tsx index 69e199824..8a0186bb7 100644 --- a/src/pages/manage/boards/index.tsx +++ b/src/pages/manage/boards/index.tsx @@ -25,10 +25,13 @@ import { IconStarFilled, IconTrash, } from '@tabler/icons-react'; +import { GetServerSideProps } from 'next'; import Head from 'next/head'; import Link from 'next/link'; import { ManageLayout } from '~/components/layout/Templates/ManageLayout'; +import { getServerAuthSession } from '~/server/auth'; import { sleep } from '~/tools/client/time'; +import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; import { api } from '~/utils/api'; const BoardsPage = () => { @@ -196,4 +199,26 @@ const BoardsPage = () => { ); }; +export const getServerSideProps: GetServerSideProps = async (ctx) => { + const session = await getServerAuthSession(ctx); + + if (!session?.user) { + return { + notFound: true, + }; + } + + const translations = await getServerSideTranslations( + ['common'], + ctx.locale, + undefined, + undefined + ); + return { + props: { + ...translations, + }, + }; +}; + export default BoardsPage; diff --git a/src/pages/manage/index.tsx b/src/pages/manage/index.tsx index c56ef8f8a..7eb27801d 100644 --- a/src/pages/manage/index.tsx +++ b/src/pages/manage/index.tsx @@ -10,12 +10,15 @@ import { createStyles, } from '@mantine/core'; import { IconArrowRight } from '@tabler/icons-react'; +import { GetServerSideProps } from 'next'; import { useSession } from 'next-auth/react'; import Head from 'next/head'; import Image from 'next/image'; import Link from 'next/link'; import { ManageLayout } from '~/components/layout/Templates/ManageLayout'; import { useScreenLargerThan } from '~/hooks/useScreenLargerThan'; +import { getServerAuthSession } from '~/server/auth'; +import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; const ManagementPage = () => { const { classes } = useStyles(); @@ -102,6 +105,28 @@ const ManagementPage = () => { ); }; +export const getServerSideProps: GetServerSideProps = async (ctx) => { + const session = await getServerAuthSession(ctx); + + if (!session?.user) { + return { + notFound: true, + }; + } + + const translations = await getServerSideTranslations( + ['common'], + ctx.locale, + undefined, + undefined + ); + return { + props: { + ...translations, + }, + }; +}; + export default ManagementPage; const useStyles = createStyles((theme) => ({ diff --git a/src/pages/manage/settings/index.tsx b/src/pages/manage/settings/index.tsx index 57bc4a9a7..04607cf30 100644 --- a/src/pages/manage/settings/index.tsx +++ b/src/pages/manage/settings/index.tsx @@ -1,6 +1,9 @@ import { Text, Title } from '@mantine/core'; +import { GetServerSideProps } from 'next'; import Head from 'next/head'; import { ManageLayout } from '~/components/layout/Templates/ManageLayout'; +import { getServerAuthSession } from '~/server/auth'; +import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; const SettingsPage = () => { return ( @@ -15,4 +18,26 @@ const SettingsPage = () => { ); }; +export const getServerSideProps: GetServerSideProps = async (ctx) => { + const session = await getServerAuthSession(ctx); + + if (!session?.user.isAdmin) { + return { + notFound: true, + }; + } + + const translations = await getServerSideTranslations( + ['common'], + ctx.locale, + undefined, + undefined + ); + return { + props: { + ...translations, + }, + }; +}; + export default SettingsPage; diff --git a/src/pages/manage/users/create.tsx b/src/pages/manage/users/create.tsx index 92962fa7b..93c5de48a 100644 --- a/src/pages/manage/users/create.tsx +++ b/src/pages/manage/users/create.tsx @@ -10,6 +10,7 @@ import { IconUser, IconUserPlus, } from '@tabler/icons-react'; +import { GetServerSideProps } from 'next'; import Head from 'next/head'; import Link from 'next/link'; import { useState } from 'react'; @@ -23,6 +24,8 @@ import { createAccountSecurityStepValidationSchema, } from '~/components/Manage/User/Create/security-step'; import { ManageLayout } from '~/components/layout/Templates/ManageLayout'; +import { getServerAuthSession } from '~/server/auth'; +import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; import { api } from '~/utils/api'; const CreateNewUserPage = () => { @@ -73,6 +76,8 @@ const CreateNewUserPage = () => { description="Create account" > { form.setFieldValue('account', value); nextStep(); @@ -87,6 +92,7 @@ const CreateNewUserPage = () => { description="Password" > { form.setFieldValue('security', value); nextStep(); @@ -160,7 +166,15 @@ const CreateNewUserPage = () => { - + + - + @@ -210,4 +224,26 @@ const CreateNewUserPage = () => { ); }; +export const getServerSideProps: GetServerSideProps = async (ctx) => { + const session = await getServerAuthSession(ctx); + + if (!session?.user.isAdmin) { + return { + notFound: true, + }; + } + + const translations = await getServerSideTranslations( + ['common'], + ctx.locale, + undefined, + undefined + ); + return { + props: { + ...translations, + }, + }; +}; + export default CreateNewUserPage; diff --git a/src/pages/manage/users/index.tsx b/src/pages/manage/users/index.tsx index 00f9d985b..73715b966 100644 --- a/src/pages/manage/users/index.tsx +++ b/src/pages/manage/users/index.tsx @@ -14,10 +14,13 @@ import { import { useDebouncedValue } from '@mantine/hooks'; import { openContextModal } from '@mantine/modals'; import { IconPlus, IconTrash } from '@tabler/icons-react'; +import { GetServerSideProps } from 'next'; import Head from 'next/head'; import Link from 'next/link'; import { useState } from 'react'; import { ManageLayout } from '~/components/layout/Templates/ManageLayout'; +import { getServerAuthSession } from '~/server/auth'; +import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; import { api } from '~/utils/api'; const ManageUsersPage = () => { @@ -134,4 +137,26 @@ const ManageUsersPage = () => { ); }; +export const getServerSideProps: GetServerSideProps = async (ctx) => { + const session = await getServerAuthSession(ctx); + + if (!session?.user.isAdmin) { + return { + notFound: true, + }; + } + + const translations = await getServerSideTranslations( + ['common'], + ctx.locale, + undefined, + undefined + ); + return { + props: { + ...translations, + }, + }; +}; + export default ManageUsersPage; diff --git a/src/pages/manage/users/invites.tsx b/src/pages/manage/users/invites.tsx index 673fc045b..4f9974f3e 100644 --- a/src/pages/manage/users/invites.tsx +++ b/src/pages/manage/users/invites.tsx @@ -12,10 +12,13 @@ import { import { modals } from '@mantine/modals'; import { IconPlus, IconTrash } from '@tabler/icons-react'; import dayjs from 'dayjs'; +import { GetServerSideProps } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; import { useState } from 'react'; import { ManageLayout } from '~/components/layout/Templates/ManageLayout'; +import { getServerAuthSession } from '~/server/auth'; +import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; import { api } from '~/utils/api'; const ManageUserInvitesPage = () => { @@ -151,4 +154,26 @@ const useStyles = createStyles(() => ({ }, })); +export const getServerSideProps: GetServerSideProps = async (ctx) => { + const session = await getServerAuthSession(ctx); + + if (!session?.user.isAdmin) { + return { + notFound: true, + }; + } + + const translations = await getServerSideTranslations( + ['common'], + ctx.locale, + undefined, + undefined + ); + return { + props: { + ...translations, + }, + }; +}; + export default ManageUserInvitesPage; diff --git a/src/server/api/routers/board.ts b/src/server/api/routers/board.ts index 99ecb58fa..0a4d25af6 100644 --- a/src/server/api/routers/board.ts +++ b/src/server/api/routers/board.ts @@ -1,11 +1,11 @@ import fs from 'fs'; -import { createTRPCRouter, publicProcedure } from '../trpc'; +import { createTRPCRouter, protectedProcedure, publicProcedure } from '../trpc'; import { getFrontendConfig } from '~/tools/config/getFrontendConfig'; export const boardRouter = createTRPCRouter({ - all: publicProcedure.query(async ({ ctx }) => { + all: protectedProcedure.query(async ({ ctx }) => { const files = fs.readdirSync('./data/configs').filter((file) => file.endsWith('.json')); const userSettings = await ctx.prisma.userSettings.findUniqueOrThrow({ diff --git a/src/server/api/routers/password.ts b/src/server/api/routers/password.ts index e96a78a84..1b9e708a3 100644 --- a/src/server/api/routers/password.ts +++ b/src/server/api/routers/password.ts @@ -1,9 +1,9 @@ import { generate } from 'generate-password'; -import { createTRPCRouter, publicProcedure } from "../trpc"; +import { adminProcedure, createTRPCRouter } from '../trpc'; export const passwordRouter = createTRPCRouter({ - generate: publicProcedure.mutation(() => { + generate: adminProcedure.mutation(() => { return generate({ strict: true, numbers: true, @@ -11,7 +11,7 @@ export const passwordRouter = createTRPCRouter({ uppercase: true, symbols: true, excludeSimilarCharacters: true, - length: 16 - }) + length: 16, + }); }), -}); \ No newline at end of file +}); diff --git a/src/server/api/routers/user.ts b/src/server/api/routers/user.ts index ad04942c4..5a8bfe416 100644 --- a/src/server/api/routers/user.ts +++ b/src/server/api/routers/user.ts @@ -11,7 +11,13 @@ import { } from '~/validations/user'; import { COOKIE_COLOR_SCHEME_KEY, COOKIE_LOCALE_KEY } from '../../../../data/constants'; -import { TRPCContext, createTRPCRouter, protectedProcedure, publicProcedure } from '../trpc'; +import { + TRPCContext, + adminProcedure, + createTRPCRouter, + protectedProcedure, + publicProcedure, +} from '../trpc'; export const userRouter = createTRPCRouter({ createAdminAccount: publicProcedure.input(signUpFormSchema).mutation(async ({ ctx, input }) => { @@ -182,7 +188,7 @@ export const userRouter = createTRPCRouter({ }); }), - makeDefaultDashboard: publicProcedure + makeDefaultDashboard: protectedProcedure .input(z.object({ board: z.string() })) .mutation(async ({ ctx, input }) => { await ctx.prisma.userSettings.update({ @@ -195,7 +201,7 @@ export const userRouter = createTRPCRouter({ }); }), - all: publicProcedure + all: adminProcedure .input( z.object({ limit: z.number().min(1).max(100).default(10), @@ -236,11 +242,11 @@ export const userRouter = createTRPCRouter({ countPages: Math.ceil(countUsers / limit), }; }), - create: publicProcedure.input(createNewUserSchema).mutation(async ({ ctx, input }) => { + create: adminProcedure.input(createNewUserSchema).mutation(async ({ ctx, input }) => { await createUserInNotExist(ctx, input); }), - deleteUser: publicProcedure + deleteUser: adminProcedure .input( z.object({ userId: z.string(),