From 5b3a236194884243038cb0479c4f1dff770c5133 Mon Sep 17 00:00:00 2001
From: Manuel <30572287+manuel-rw@users.noreply.github.com>
Date: Fri, 27 Oct 2023 23:10:42 +0200
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20401=20page=20(#1508)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../en/layout/errors/access-denied.json | 5 ++
src/images/undraw_secure_login_pdn4.svg | 1 +
src/pages/401.tsx | 55 +++++++++++++++++++
src/pages/board/[slug]/customize.tsx | 23 ++++----
src/pages/board/index.tsx | 13 ++---
src/pages/manage/index.tsx | 8 +--
src/pages/manage/tools/docker.tsx | 20 +++----
src/pages/manage/users/index.tsx | 9 ++-
src/pages/manage/users/invites.tsx | 9 ++-
src/tools/server/loginBuilder.ts | 8 ++-
src/tools/server/translation-namespaces.ts | 2 +
11 files changed, 107 insertions(+), 46 deletions(-)
create mode 100644 public/locales/en/layout/errors/access-denied.json
create mode 100644 src/images/undraw_secure_login_pdn4.svg
create mode 100644 src/pages/401.tsx
diff --git a/public/locales/en/layout/errors/access-denied.json b/public/locales/en/layout/errors/access-denied.json
new file mode 100644
index 000000000..d1132e481
--- /dev/null
+++ b/public/locales/en/layout/errors/access-denied.json
@@ -0,0 +1,5 @@
+{
+ "title": "Access denied",
+ "text": "You do not have sufficient permissions to access this page. If you believe, that this is not intentional, please contact your administrator.",
+ "switchAccount": "Switch to a different account"
+}
\ No newline at end of file
diff --git a/src/images/undraw_secure_login_pdn4.svg b/src/images/undraw_secure_login_pdn4.svg
new file mode 100644
index 000000000..97c35f957
--- /dev/null
+++ b/src/images/undraw_secure_login_pdn4.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/pages/401.tsx b/src/pages/401.tsx
new file mode 100644
index 000000000..e9bf268bb
--- /dev/null
+++ b/src/pages/401.tsx
@@ -0,0 +1,55 @@
+import { Button, Center, Stack, Title, Text, createStyles } from "@mantine/core";
+import { useTranslation } from "next-i18next";
+import Image from "next/image";
+import Head from "next/head";
+import { MainLayout } from "~/components/layout/Templates/MainLayout";
+import Link from "next/link";
+
+import imageAccessDenied from '~/images/undraw_secure_login_pdn4.svg';
+import { pageAccessDeniedNamespaces } from "~/tools/server/translation-namespaces";
+import { getServerSideTranslations } from "~/tools/server/getServerSideTranslations";
+import { GetServerSidePropsContext } from "next";
+
+export default function Custom401() {
+ const { classes } = useStyles();
+ const { t } = useTranslation('layout/errors/access-denied');
+ return (
+
+
+
+ Access denied • Homarr
+
+
+
+ {t('title')}
+ {t('text')}
+
+
+
+
+
+ )
+}
+
+export async function getStaticProps({ req, res, locale }: GetServerSidePropsContext) {
+ const translations = await getServerSideTranslations(
+ [...pageAccessDeniedNamespaces, 'common'],
+ locale,
+ req,
+ res
+ );
+ return {
+ props: {
+ ...translations,
+ },
+ };
+}
+
+const useStyles = createStyles(() => ({
+ image: {
+ margin: '0 auto',
+ display: 'block',
+ },
+}));
\ No newline at end of file
diff --git a/src/pages/board/[slug]/customize.tsx b/src/pages/board/[slug]/customize.tsx
index bb78e96ff..45d465b54 100644
--- a/src/pages/board/[slug]/customize.tsx
+++ b/src/pages/board/[slug]/customize.tsx
@@ -44,6 +44,7 @@ import { MainLayout } from '~/components/layout/Templates/MainLayout';
import { createTrpcServersideHelpers } from '~/server/api/helper';
import { getServerAuthSession } from '~/server/auth';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
+import { checkForSessionOrAskForLogin } from '~/tools/server/loginBuilder';
import { firstUpperCase } from '~/tools/shared/strings';
import { api } from '~/utils/api';
import { useI18nZodResolver } from '~/utils/i18n-zod-resolver';
@@ -275,22 +276,22 @@ const routeParamsSchema = z.object({
slug: z.string(),
});
-export const getServerSideProps: GetServerSideProps = async ({ req, res, locale, params }) => {
- const routeParams = routeParamsSchema.safeParse(params);
+export const getServerSideProps: GetServerSideProps = async (context) => {
+ const routeParams = routeParamsSchema.safeParse(context.params);
if (!routeParams.success) {
return {
notFound: true,
};
}
- const session = await getServerAuthSession({ req, res });
- if (!session?.user.isAdmin) {
- return {
- notFound: true,
- };
+ const session = await getServerAuthSession({ req: context.req, res: context.res });
+
+ const result = checkForSessionOrAskForLogin(context, session, () => session?.user.isAdmin == true);
+ if (result) {
+ return result;
}
- const helpers = await createTrpcServersideHelpers({ req, res });
+ const helpers = await createTrpcServersideHelpers({ req: context.req, res: context.res });
const config = await helpers.config.byName.fetch({ name: routeParams.data.slug });
@@ -305,9 +306,9 @@ export const getServerSideProps: GetServerSideProps = async ({ req, res, locale,
'settings/customization/gridstack',
'settings/customization/access',
],
- locale,
- req,
- res
+ context.locale,
+ context.req,
+ context.res
);
return {
diff --git a/src/pages/board/index.tsx b/src/pages/board/index.tsx
index 6a283e919..95f100d33 100644
--- a/src/pages/board/index.tsx
+++ b/src/pages/board/index.tsx
@@ -11,6 +11,7 @@ import { getDefaultBoardAsync } from '~/server/db/queries/userSettings';
import { userSettings } from '~/server/db/schema';
import { getFrontendConfig } from '~/tools/config/getFrontendConfig';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
+import { checkForSessionOrAskForLogin } from '~/tools/server/loginBuilder';
import { boardNamespaces } from '~/tools/server/translation-namespaces';
import { ConfigType } from '~/types/config';
@@ -45,15 +46,9 @@ export const getServerSideProps: GetServerSideProps = a
);
const config = await getFrontendConfig(boardName);
- if (!config?.settings?.access?.allowGuests && !session?.user) {
- return {
- notFound: true,
- props: {
- primaryColor: config.settings.customization.colors.primary,
- secondaryColor: config.settings.customization.colors.secondary,
- primaryShade: config.settings.customization.colors.shade,
- },
- };
+ const result = checkForSessionOrAskForLogin(ctx, session, () => true);
+ if (result) {
+ return result;
}
return {
diff --git a/src/pages/manage/index.tsx b/src/pages/manage/index.tsx
index 0386a274b..281a7ef8d 100644
--- a/src/pages/manage/index.tsx
+++ b/src/pages/manage/index.tsx
@@ -23,6 +23,7 @@ import { getServerSideTranslations } from '~/tools/server/getServerSideTranslati
import { OnlyKeysWithStructure } from '~/types/helpers';
import { type quickActions } from '../../../public/locales/en/manage/index.json';
+import { checkForSessionOrAskForLogin } from '~/tools/server/loginBuilder';
const ManagementPage = () => {
const { t } = useTranslation('manage/index');
@@ -118,10 +119,9 @@ const QuickActionCard = ({ type, href }: QuickActionCardProps) => {
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
- if (!session?.user) {
- return {
- notFound: true,
- };
+ const result = checkForSessionOrAskForLogin(ctx, session, () => true);
+ if (result) {
+ return result;
}
const translations = await getServerSideTranslations(
diff --git a/src/pages/manage/tools/docker.tsx b/src/pages/manage/tools/docker.tsx
index 90793a973..f0cc714d4 100644
--- a/src/pages/manage/tools/docker.tsx
+++ b/src/pages/manage/tools/docker.tsx
@@ -11,6 +11,7 @@ import { ManageLayout } from '~/components/layout/Templates/ManageLayout';
import { dockerRouter } from '~/server/api/routers/docker/router';
import { getServerAuthSession } from '~/server/auth';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
+import { checkForSessionOrAskForLogin } from '~/tools/server/loginBuilder';
import { boardNamespaces } from '~/tools/server/translation-namespaces';
import { api } from '~/utils/api';
@@ -54,24 +55,23 @@ export default function DockerPage({
);
}
-export const getServerSideProps: GetServerSideProps = async ({ locale, req, res }) => {
- const session = await getServerAuthSession({ req, res });
- if (!session?.user.isAdmin) {
- return {
- notFound: true,
- };
+export const getServerSideProps: GetServerSideProps = async (context) => {
+ const session = await getServerAuthSession({ req: context.req, res: context.res });
+ const result = checkForSessionOrAskForLogin(context, session, () => session?.user.isAdmin == true);
+ if (result) {
+ return result;
}
const caller = dockerRouter.createCaller({
session: session,
- cookies: req.cookies,
+ cookies: context.req.cookies,
});
const translations = await getServerSideTranslations(
[...boardNamespaces, 'layout/manage', 'tools/docker'],
- locale,
- req,
- res
+ context.locale,
+ context.req,
+ context.res
);
let containers = [];
diff --git a/src/pages/manage/users/index.tsx b/src/pages/manage/users/index.tsx
index fcf32d686..4a3b3176b 100644
--- a/src/pages/manage/users/index.tsx
+++ b/src/pages/manage/users/index.tsx
@@ -26,6 +26,7 @@ import { openDeleteUserModal } from '~/components/Manage/User/delete-user.modal'
import { ManageLayout } from '~/components/layout/Templates/ManageLayout';
import { getServerAuthSession } from '~/server/auth';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
+import { checkForSessionOrAskForLogin } from '~/tools/server/loginBuilder';
import { manageNamespaces } from '~/tools/server/translation-namespaces';
import { api } from '~/utils/api';
@@ -180,11 +181,9 @@ const ManageUsersPage = () => {
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
-
- if (!session?.user.isAdmin) {
- return {
- notFound: true,
- };
+ const result = checkForSessionOrAskForLogin(ctx, session, () => session?.user.isAdmin == true);
+ if (result) {
+ return result;
}
const translations = await getServerSideTranslations(
diff --git a/src/pages/manage/users/invites.tsx b/src/pages/manage/users/invites.tsx
index 5d491337f..526524633 100644
--- a/src/pages/manage/users/invites.tsx
+++ b/src/pages/manage/users/invites.tsx
@@ -20,6 +20,7 @@ import { openCreateInviteModal } from '~/components/Manage/User/Invite/create-in
import { ManageLayout } from '~/components/layout/Templates/ManageLayout';
import { getServerAuthSession } from '~/server/auth';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
+import { checkForSessionOrAskForLogin } from '~/tools/server/loginBuilder';
import { manageNamespaces } from '~/tools/server/translation-namespaces';
import { api } from '~/utils/api';
@@ -152,11 +153,9 @@ const useStyles = createStyles(() => ({
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
-
- if (!session?.user.isAdmin) {
- return {
- notFound: true,
- };
+ const result = checkForSessionOrAskForLogin(ctx, session, () => session?.user.isAdmin == true);
+ if (result) {
+ return result;
}
const translations = await getServerSideTranslations(
diff --git a/src/tools/server/loginBuilder.ts b/src/tools/server/loginBuilder.ts
index 3f84f2b7e..297076c47 100644
--- a/src/tools/server/loginBuilder.ts
+++ b/src/tools/server/loginBuilder.ts
@@ -4,7 +4,9 @@ import {
GetServerSidePropsResult,
PreviewData,
} from 'next';
+
import { Session } from 'next-auth';
+
import { ParsedUrlQuery } from 'querystring';
export const checkForSessionOrAskForLogin = (
@@ -13,7 +15,6 @@ export const checkForSessionOrAskForLogin = (
accessCallback: () => boolean
): GetServerSidePropsResult | undefined => {
if (!session?.user) {
- console.log('detected logged out user!');
return {
props: {},
redirect: {
@@ -26,7 +27,10 @@ export const checkForSessionOrAskForLogin = (
if (!accessCallback()) {
return {
props: {},
- notFound: true,
+ redirect: {
+ destination: '/401',
+ permanent: false
+ }
};
}
diff --git a/src/tools/server/translation-namespaces.ts b/src/tools/server/translation-namespaces.ts
index 695edcb2d..138a0a962 100644
--- a/src/tools/server/translation-namespaces.ts
+++ b/src/tools/server/translation-namespaces.ts
@@ -51,3 +51,5 @@ export const manageNamespaces = [
export const loginNamespaces = ['authentication/login'];
export const pageNotFoundNamespaces = ['layout/errors/not-found'];
+
+export const pageAccessDeniedNamespaces = ['layout/errors/access-denied'];