Middleware and login updates

This commit is contained in:
Darren Clarke 2023-02-22 13:05:52 +00:00
parent 484e8689a4
commit 4517241ead
23 changed files with 144 additions and 112 deletions

1
.vscode/swissknifeDecorators.json vendored Normal file
View file

@ -0,0 +1 @@
[]

View file

@ -62,8 +62,8 @@ force-run-migrations:
docker-compose -p link-docker-compose exec zammad-railsserver bundle exec rails r 'require "/opt/zammad/db/addon/cdr_signal/20210525091356_cdr_signal_channel.rb";require "/opt/zammad/db/addon/cdr_voice/20210525091357_cdr_voice_channel.rb";require "/opt/zammad/db/addon/cdr_whatsapp/20210525091358_cdr_whatsapp_channel.rb"; require "/opt/zammad/db/addon/pgpsupport/20220403000001_pgpsupport.rb";CdrSignalChannel.new.up;CdrVoiceChannel.new.up;CdrWhatsappChannel.new.up;PGPSupport.new.up;' docker-compose -p link-docker-compose exec zammad-railsserver bundle exec rails r 'require "/opt/zammad/db/addon/cdr_signal/20210525091356_cdr_signal_channel.rb";require "/opt/zammad/db/addon/cdr_voice/20210525091357_cdr_voice_channel.rb";require "/opt/zammad/db/addon/cdr_whatsapp/20210525091358_cdr_whatsapp_channel.rb"; require "/opt/zammad/db/addon/pgpsupport/20220403000001_pgpsupport.rb";CdrSignalChannel.new.up;CdrVoiceChannel.new.up;CdrWhatsappChannel.new.up;PGPSupport.new.up;'
sso: sso:
docker-compose -p link-shell exec zammad-nginx sed -i '/proxy_set_header X-Forwarded-User "";/d' /opt/zammad/contrib/nginx/zammad.conf; docker-compose exec zammad-nginx sed -i '/proxy_set_header X-Forwarded-User "";/d' /opt/zammad/contrib/nginx/zammad.conf;
docker-compose -p link-shell exec zammad-nginx service nginx restart; docker-compose exec zammad-nginx service nginx restart;
start: start:
CURRENT_UID=$(CURRENT_UID) docker-compose up -d CURRENT_UID=$(CURRENT_UID) docker-compose up -d

2
apps/link/.dockerignore Normal file
View file

@ -0,0 +1,2 @@
node_modules
.next

View file

@ -24,6 +24,7 @@ import { useRouter } from "next/router";
import Link from "next/link"; import Link from "next/link";
import Image from "next/image"; import Image from "next/image";
import LinkLogo from "public/link-logo-small.png"; import LinkLogo from "public/link-logo-small.png";
import { useSession } from "next-auth/react";
const openWidth = 270; const openWidth = 270;
const closedWidth = 100; const closedWidth = 100;
@ -152,7 +153,8 @@ interface SidebarProps {
export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => { export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
const { pathname } = useRouter(); const { pathname } = useRouter();
const [username, setUsername] = useState("Nicholas Smith"); const { data: session } = useSession()
const username = session?.user?.name || "User"
return ( return (
<Drawer <Drawer
@ -273,9 +275,9 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
{open {open
? username ? username
: username : username
.split(" ") .split(" ")
.map((name) => name.substring(0, 1)) .map((name) => name.substring(0, 1))
.join("")} .join("")}
</Typography> </Typography>
</Grid> </Grid>
<Grid item> <Grid item>
@ -384,10 +386,10 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
/> />
<MenuItem <MenuItem
name="New Ticket UI" name="New Ticket UI"
href="/tickets/181" href="/tickets/2"
Icon={SettingsIcon} Icon={SettingsIcon}
iconSize={0} iconSize={0}
selected={pathname.endsWith("/tickets/181")} selected={pathname.endsWith("/tickets/2")}
open={open} open={open}
/> />
</List> </List>

View file

@ -2,24 +2,26 @@ import { FC, useState } from "react";
import Iframe from "react-iframe"; import Iframe from "react-iframe";
type ZammadWrapperProps = { type ZammadWrapperProps = {
url: string; path: string;
hideSidebar?: boolean; hideSidebar?: boolean;
}; };
export const ZammadWrapper: FC<ZammadWrapperProps> = ({ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
url, path,
hideSidebar = true, hideSidebar = true,
}) => { }) => {
const [display, setDisplay] = useState("inherit"); const [display, setDisplay] = useState("hidden");
const url = `https://redaranj-bookish-tribble-56jwjx5wh4j4w-8003.preview.app.github.dev/zammad${path}`;
console.log({ base: process.env.LINK_URL, path, url })
return ( return (
<Iframe < Iframe
id="link" id="link"
url={url} url={url}
width="100%" width="100%"
height="100%" height="100%"
frameBorder={0} frameBorder={0}
styles={{ display }} styles={{ display }
}
onLoad={() => { onLoad={() => {
const linkElement = document.querySelector("iframe"); const linkElement = document.querySelector("iframe");
if ( if (

View file

@ -1,19 +1,31 @@
// middleware.ts // middleware.ts
import { NextResponse } from 'next/server' import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server' import type { NextRequest } from 'next/server'
import { withAuth } from "next-auth/middleware"
// This function can be marked `async` if using `await` inside export default withAuth((request: NextRequest) => {
export function middleware(request: NextRequest) { if (request.nextUrl.pathname.startsWith('/login')) {
return NextResponse.next()
}
// @ts-expect-error
if (!request.nextauth.token) {
return NextResponse.redirect("/login")
}
// @ts-expect-error
console.log({ token: request.nextauth.token })
console.log("INTO middleware") console.log("INTO middleware")
const path = request.nextUrl.pathname const path = request.nextUrl.pathname
console.log({ path }) console.log({ path })
if (path.startsWith('/zammad')) { const zammadPaths = ['/zammad', '/assets', '/api/v1', '/auth/sso'];
console.log("INTO middleware 2") if (zammadPaths.some((p) => path.startsWith(p))) {
console.log("MATCHED ZAMMAD PATH")
const finalURL = new URL(path.replace("/zammad", ""), process.env.ZAMMAD_URL) const finalURL = new URL(path.replace("/zammad", ""), process.env.ZAMMAD_URL)
console.log(finalURL.toString()) console.log(finalURL.toString())
const requestHeaders = new Headers() const requestHeaders = new Headers(request.headers)
requestHeaders.set('X-Forwarded-User', 'darren@redaranj.com') // @ts-expect-error
requestHeaders.set('X-Forwarded-User', request.nextauth.token?.email)
requestHeaders.set('Host', 'zammad.example.com') requestHeaders.set('Host', 'zammad.example.com')
console.log(requestHeaders) console.log(requestHeaders)
@ -23,7 +35,11 @@ export function middleware(request: NextRequest) {
} }
}) })
} else { } else {
console.log("INTO middleware 3") console.log("DID NOT MATCH ZAMMAD PATH")
return NextResponse.next() return NextResponse.next()
} }
} }, {
pages: {
signIn: '/login',
}
})

View file

@ -3,6 +3,7 @@ module.exports = {
locales: ["en", "fr"], locales: ["en", "fr"],
defaultLocale: "en", defaultLocale: "en",
}, },
/*
async redirects() { async redirects() {
return [ return [
{ {
@ -13,15 +14,17 @@ module.exports = {
]; ];
}, },
async rewrites() { async rewrites() {
return [ return {
{ beforeFiles: [
source: "/zammad", {
destination: `http://link-shell-zammad-proxy-1:3000`, source: "/assets/:path*",
}, destination: `/zammad/assets/:path*`,
{ },
source: "/zammad/:path*", {
destination: `http://link-shell-zammad-proxy-1:3000/:path*`, source: "/api/v1/:path*",
}, destination: `/zammad/api/v1/:path*`,
]; },
}, ],
};
}, */
}; };

View file

@ -22,7 +22,7 @@ const Link = () => (
}} }}
> >
<ZammadWrapper <ZammadWrapper
url="http://localhost:3000/zammad/#manage" path="/#manage"
hideSidebar={false} hideSidebar={false}
/> />
</Grid> </Grid>

View file

@ -1,6 +1,6 @@
import NextAuth from "next-auth"; import NextAuth from "next-auth";
import Google from "next-auth/providers/google"; import Google from "next-auth/providers/google";
import Apple from "next-auth/providers/apple"; // import Apple from "next-auth/providers/apple";
export default NextAuth({ export default NextAuth({
providers: [ providers: [
@ -8,10 +8,12 @@ export default NextAuth({
clientId: process.env.GOOGLE_CLIENT_ID, clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET, clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}), }),
/*
Apple({ Apple({
clientId: process.env.APPLE_CLIENT_ID, clientId: process.env.APPLE_CLIENT_ID,
clientSecret: process.env.APPLE_CLIENT_SECRET clientSecret: process.env.APPLE_CLIENT_SECRET
}), }),
*/
], ],
secret: process.env.NEXTAUTH_SECRET, secret: process.env.NEXTAUTH_SECRET,
}); });

View file

@ -21,7 +21,7 @@ const Home = () => (
width: "100%", width: "100%",
}} }}
> >
<ZammadWrapper url="https://8003-digiresilienc-linkshell-c2tqwgcccbs.ws-eu86.gitpod.io/zammad/#dashboard" /> <ZammadWrapper path="/#dashboard" />
</Grid> </Grid>
</Grid> </Grid>
</Layout> </Layout>

View file

@ -21,7 +21,7 @@ const Link = () => (
width: "100%", width: "100%",
}} }}
> >
<ZammadWrapper url="http://localhost:3000/zammad/#ticket/zoom/518/1490" /> <ZammadWrapper path="/zammad/#ticket/zoom/518/1490" />
</Grid> </Grid>
</Grid> </Grid>
</Layout> </Layout>

View file

@ -40,13 +40,15 @@ const Login = ({ session }) => {
sx={buttonStyles} sx={buttonStyles}
onClick={() => onClick={() =>
signIn("google", { signIn("google", {
callbackUrl: `${window.location.origin}/setup`, callbackUrl: `https://redaranj-bookish-tribble-56jwjx5wh4j4w-8003.preview.app.github.dev/auth/sso`,
}) })
} }
> >
<GoogleIcon sx={{ mr: 1 }} /> <GoogleIcon sx={{ mr: 1 }} />
Google
</IconButton> </IconButton>
</Grid> </Grid>
{/*
<Grid item sx={{ width: "100%" }}> <Grid item sx={{ width: "100%" }}>
<IconButton <IconButton
sx={buttonStyles} sx={buttonStyles}
@ -58,7 +60,7 @@ const Login = ({ session }) => {
> >
<AppleIcon sx={{ mr: 1 }} /> <AppleIcon sx={{ mr: 1 }} />
</IconButton> </IconButton>
</Grid> </Grid>*/}
<Grid item sx={{ mt: 2 }} /> <Grid item sx={{ mt: 2 }} />
</Grid> </Grid>
) : null} ) : null}

View file

@ -22,7 +22,7 @@ const Profile = () => (
}} }}
> >
<ZammadWrapper <ZammadWrapper
url="http://localhost:3000/zammad/#profile" path="/#profile"
hideSidebar={false} hideSidebar={false}
/> />
</Grid> </Grid>

View file

@ -1,54 +0,0 @@
import Head from "next/head";
import { NextPage, GetServerSideProps, GetServerSidePropsContext } from "next";
import { Grid, Box } from "@mui/material";
import { Layout } from "components/Layout";
import { TicketDetail } from "components/TicketDetail";
import { TicketEdit } from "components/TicketEdit";
const Link: NextPage = ({ ticket, articles }: any) => (
<Layout>
<Head>
<title>Link Shell</title>
</Head>
<Grid container spacing={0} sx={{ height: "100vh" }} direction="row">
<Grid item sx={{ height: "100vh" }} xs={10}>
<TicketDetail ticket={ticket} articles={articles} />
</Grid>
<Grid item xs={2} sx={{ height: "100vh" }}>
<TicketEdit ticket={ticket} />
</Grid>
</Grid>
</Layout>
);
export const getServerSideProps: GetServerSideProps = async (
context: GetServerSidePropsContext
) => {
const {
params: { id },
} = context;
const baseURL = `${process.env.ZAMMAD_URL}/api/v1`;
const token = process.env.ZAMMAD_API_TOKEN;
const headers = { Authorization: `Token ${token}` };
const rawTicket = await fetch(`${baseURL}/tickets/${id}`, {
headers,
});
const ticket = await rawTicket.json();
const rawArticles = await fetch(
`${baseURL}/ticket_articles/by_ticket/${id}`,
{
headers,
}
);
const articles = await rawArticles.json();
console.log({ ticket, articles });
return {
props: {
ticket,
articles,
},
};
};
export default Link;

View file

@ -0,0 +1,58 @@
import { GetServerSideProps, GetServerSidePropsContext } from "next";
import Head from "next/head";
import useSWR from "swr";
import { NextPage } from "next";
import { Grid, } from "@mui/material";
import { Layout } from "components/Layout";
import { TicketDetail } from "components/TicketDetail";
import { TicketEdit } from "components/TicketEdit";
type TicketProps = {
id: string;
};
const Ticket: NextPage<TicketProps> = ({ id }) => {
const fetcher = async (url: string) => {
const res = await fetch(url);
return res.json();
}
const { data: ticketData, error: ticketError } = useSWR(
`https://redaranj-bookish-tribble-56jwjx5wh4j4w-8003.preview.app.github.dev/api/v1/tickets/${id}`,
fetcher
);
const { data: articlesData, error: articlesError } = useSWR(
`https://redaranj-bookish-tribble-56jwjx5wh4j4w-8003.preview.app.github.dev/api/v1/ticket_articles/by_ticket/${id}`,
fetcher
);
const shouldRender = !ticketError && !articlesError && ticketData && articlesData && !ticketData.error && !articlesData.error;
return (
<Layout>
<Head>
<title>Link Shell</title>
</Head>
{shouldRender && (
<Grid container spacing={0} sx={{ height: "100vh" }} direction="row">
<Grid item sx={{ height: "100vh" }} xs={10}>
<TicketDetail ticket={ticketData} articles={articlesData} />
</Grid>
<Grid item xs={2} sx={{ height: "100vh" }}>
<TicketEdit ticket={ticketData} />
</Grid>
</Grid>)}
{ticketError && <div>{ticketError.toString()}</div>}
</Layout>
);
}
export const getServerSideProps: GetServerSideProps = async (
context: GetServerSidePropsContext) => {
const { id } = context.query;
return { props: { id } };
}
export default Ticket;

View file

@ -21,7 +21,7 @@ const Link = () => (
width: "100%", width: "100%",
}} }}
> >
<ZammadWrapper url="http://localhost:8003/zammad/#ticket/view/my_tickets" /> <ZammadWrapper path="/#ticket/view/my_tickets" />
</Grid> </Grid>
</Grid> </Grid>
</Layout> </Layout>

View file

@ -21,7 +21,7 @@ const Link = () => (
width: "100%", width: "100%",
}} }}
> >
<ZammadWrapper url="http://localhost:3000/zammad/#ticket/view/my_pending_reached" /> <ZammadWrapper path="/#ticket/view/my_pending_reached" />
</Grid> </Grid>
</Grid> </Grid>
</Layout> </Layout>

View file

@ -21,7 +21,7 @@ const Link = () => (
width: "100%", width: "100%",
}} }}
> >
<ZammadWrapper url="http://localhost:3000/zammad/#ticket/view/all_unassigned" /> <ZammadWrapper path="/#ticket/view/all_unassigned" />
</Grid> </Grid>
</Grid> </Grid>
</Layout> </Layout>

View file

@ -21,7 +21,7 @@ const Link = () => (
width: "100%", width: "100%",
}} }}
> >
<ZammadWrapper url="http://localhost:3000/zammad/#ticket/view/all_escalated" /> <ZammadWrapper path="/#ticket/view/all_escalated" />
</Grid> </Grid>
</Grid> </Grid>
</Layout> </Layout>

View file

@ -0,0 +1,2 @@
node_modules
.next

View file

@ -218,18 +218,14 @@ services:
ZAMMAD_URL: ${ZAMMAD_URL} ZAMMAD_URL: ${ZAMMAD_URL}
ZAMMAD_API_TOKEN: ${ZAMMAD_API_TOKEN} ZAMMAD_API_TOKEN: ${ZAMMAD_API_TOKEN}
ZAMMAD_VIRUAL_HOST: ${ZAMMAD_VIRTUAL_HOST} ZAMMAD_VIRUAL_HOST: ${ZAMMAD_VIRTUAL_HOST}
LINK_URL: ${LINK_URL}
zammad-proxy: NEXTAUTH_URL: ${LINK_URL}
container_name: zammad-proxy NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
build: ./apps/zammad-proxy NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
expose: NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
- "3000" NEXTAUTH_ENCRYPTION_KEY_B64: ${NEXTAUTH_ENCRYPTION_KEY_B64}
ports: GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
- "8004:3000" GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
environment:
ZAMMAD_URL: ${ZAMMAD_URL}
ZAMMAD_API_TOKEN: ${ZAMMAD_API_TOKEN}
ZAMMAD_VIRUAL_HOST: ${ZAMMAD_VIRTUAL_HOST}
volumes: volumes:
elasticsearch-data: elasticsearch-data:

View file

@ -1 +1 @@
FROM zammad/zammad-docker-compose:zammad-elasticsearch-5.2.3-32 FROM zammad/zammad-docker-compose:zammad-elasticsearch-5.2.3-31

View file

@ -1 +1 @@
FROM redis:6.2.5-alpine FROM redis:7.0.5-alpine