Merge branch 'shell-updates' into 'main'

Shell updates

See merge request digiresilience/link/link-stack!1
This commit is contained in:
Darren Clarke 2023-06-14 06:09:33 +00:00
commit 8949b10671
25 changed files with 3980 additions and 4813 deletions

View file

@ -18,6 +18,7 @@ COPY --from=builder ${APP_DIR}/out/package-lock.json ./package-lock.json
RUN npm ci --omit=dev
COPY --from=builder ${APP_DIR}/out/full/ .
ARG LINK_EMBEDDED=true
RUN npm i -g turbo
RUN turbo run build --filter=leafcutter

View file

@ -11,9 +11,7 @@ import { useAppContext } from "./AppProvider";
export const Layout: FC<PropsWithChildren> = ({ children }) => {
const [cookies, setCookie] = useCookies(["cookieConsent"]);
const consentGranted = cookies.cookieConsent === "true";
const {
publicRuntimeConfig: { embedded },
} = getConfig();

View file

@ -395,11 +395,21 @@
"display": "LGBT / Gender / Sexuality",
"description": ""
},
"male": {
"category": "",
"display": "Male",
"description": ""
},
"media": {
"category": "",
"display": "Media",
"description": ""
},
"non-binary": {
"category": "",
"display": "Non-binary",
"description": ""
},
"policy-politics": {
"category": "",
"display": "Policy / Politics",
@ -415,6 +425,11 @@
"display": "Refugees",
"description": ""
},
"transgender": {
"category": "",
"display": "Transgender",
"description": ""
},
"womens-rights": {
"category": "",
"display": "Womens' Rights",

View file

@ -1,6 +1,6 @@
module.exports = {
publicRuntimeConfig: {
embedded: Boolean(process.env.LINK_EMBEDDED),
embedded: true
},
basePath: "/proxy/leafcutter",
assetPrefix: "/proxy/leafcutter",

View file

@ -1,4 +1,5 @@
import { FC, useState } from "react";
import useSWR from "swr";
import {
Box,
Grid,
@ -19,12 +20,14 @@ import {
Cottage as CottageIcon,
Settings as SettingsIcon,
ExpandCircleDown as ExpandCircleDownIcon,
Dvr as DvrIcon,
} from "@mui/icons-material";
import { useRouter } from "next/router";
import Link from "next/link";
import Image from "next/image";
import LinkLogo from "public/link-logo-small.png";
import { useSession } from "next-auth/react";
import { useSession, signOut } from "next-auth/react";
import { getTicketOverviewCountsQuery } from "graphql/getTicketOverviewCountsQuery";
const openWidth = 270;
const closedWidth = 100;
@ -38,8 +41,9 @@ const MenuItem = ({
selected = false,
open = true,
badge,
target = "_self",
}: any) => (
<Link href={href}>
<Link href={href} target={target}>
<ListItemButton
sx={{
p: 0,
@ -124,7 +128,7 @@ const MenuItem = ({
}
/>
)}
{badge && (
{badge && badge > 0 ? (
<ListItemSecondaryAction>
<Typography
color="textSecondary"
@ -142,7 +146,7 @@ const MenuItem = ({
{badge}
</Typography>
</ListItemSecondaryAction>
)}
) : null}
</ListItemButton>
</Link>
);
@ -153,9 +157,28 @@ interface SidebarProps {
}
export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
const { pathname } = useRouter();
const router = useRouter();
const { pathname } = router;
const { data: session } = useSession();
const username = session?.user?.name || "User";
const { data: overviewData, error: overviewError }: any = useSWR(
{
document: getTicketOverviewCountsQuery,
},
{ refreshInterval: 10000 }
);
const findOverviewCountByID = (id: number) =>
overviewData?.ticketOverviews?.edges?.find((overview: any) =>
overview.node.id.endsWith(`/${id}`)
)?.node?.ticketCount ?? 0;
const assignedCount = findOverviewCountByID(1);
const urgentCount = findOverviewCountByID(7);
const pendingCount = findOverviewCountByID(3);
const unassignedCount = findOverviewCountByID(2);
const logout = () => {
signOut({ callbackUrl: "/login" });
};
return (
<Drawer
@ -341,7 +364,6 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
iconSize={20}
open={open}
/>
<Collapse
in={pathname.startsWith("/tickets")}
timeout="auto"
@ -355,7 +377,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
Icon={FeaturedPlayListIcon}
iconSize={0}
selected={pathname.endsWith("/tickets/assigned")}
badge={3}
badge={assignedCount}
open={open}
/>
<MenuItem
@ -364,7 +386,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
Icon={FeaturedPlayListIcon}
iconSize={0}
selected={pathname.endsWith("/tickets/urgent")}
badge={1}
badge={urgentCount}
open={open}
/>
<MenuItem
@ -373,7 +395,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
Icon={FeaturedPlayListIcon}
iconSize={0}
selected={pathname.endsWith("/tickets/pending")}
badge={9}
badge={pendingCount}
open={open}
/>
<MenuItem
@ -381,21 +403,12 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
href="/tickets/unassigned"
Icon={FeaturedPlayListIcon}
iconSize={0}
selected={pathname.endsWith("/tickets/unnassigned")}
badge={27}
open={open}
/>
<MenuItem
name="New Ticket UI"
href="/tickets/2"
Icon={SettingsIcon}
iconSize={0}
selected={pathname.endsWith("/tickets/2")}
selected={pathname.endsWith("/tickets/unassigned")}
badge={unassignedCount}
open={open}
/>
</List>
</Collapse>
<MenuItem
name="Knowledge Base"
href="/knowledge"
@ -406,7 +419,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
/>
<MenuItem
name="Leafcutter"
href="/leafcutter"
href="/leafcutter/about"
Icon={AnalyticsIcon}
iconSize={20}
selected={pathname.endsWith("/leafcutter")}
@ -419,6 +432,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
onClick={undefined}
>
<List component="div" disablePadding>
{/*
<MenuItem
name="Dashboard"
href="/leafcutter"
@ -442,7 +456,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
selected={pathname.endsWith("/leafcutter/trends")}
open={open}
/>
*/}
<MenuItem
name="FAQ"
href="/leafcutter/faq"
@ -509,13 +523,21 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
/>
</List>
</Collapse>
<MenuItem
name="Zammad Interface"
href="/proxy/zammad"
Icon={DvrIcon}
iconSize={20}
open={open}
target="_blank"
/>
<MenuItem
name="Logout"
href="/logout"
Icon={LogoutIcon}
iconSize={20}
open={open}
onClick={logout}
/>
</List>
</Grid>

View file

@ -0,0 +1,84 @@
import { FC } from "react";
import { Box } from "@mui/material";
import {
DataGridPro,
GridColDef,
GridColumnVisibilityModel,
GridRowSelectionModel,
} from "@mui/x-data-grid-pro";
import { useCookies } from "react-cookie";
interface StyledDataGridProps {
name: string;
columns: GridColDef[];
rows: any[];
// eslint-disable-next-line no-unused-vars
onRowClick?: (row: any) => void;
height?: string;
selectedRows?: GridRowSelectionModel;
// eslint-disable-next-line no-unused-vars
setSelectedRows?: (rows: GridRowSelectionModel) => void;
}
export const StyledDataGrid: FC<StyledDataGridProps> = ({
name,
columns,
rows,
onRowClick,
height = "calc(100vh - 20px)",
selectedRows,
setSelectedRows,
}) => {
const cookieName = `${name}DataGridColumnState`;
const [cookies, setCookie] = useCookies([cookieName]);
const handleColumnVisibilityChange = (model: GridColumnVisibilityModel) =>
setCookie(cookieName, model, { path: "/" });
return (
<Box
sx={{
backgroundColor: "#ddd",
border: 0,
width: "100%",
height,
".MuiDataGrid-row:nth-of-type(1n)": {
backgroundColor: "#f3f3f3",
},
".MuiDataGrid-row:nth-of-type(2n)": {
backgroundColor: "#fff",
},
".MuiDataGrid-columnHeaderTitle": {
color: "#333",
fontWeight: "bold",
fontSize: 11,
margin: "0 auto",
},
".MuiDataGrid-columnHeader": {
backgroundColor: "#ccc",
border: 0,
borderBottom: "3px solid #ddd",
},
}}
>
<DataGridPro
rows={rows}
columns={columns}
density="compact"
hideFooter
sx={{ height }}
rowBuffer={30}
checkboxSelection={!!setSelectedRows}
onRowSelectionModelChange={setSelectedRows}
rowSelectionModel={selectedRows}
rowHeight={46}
scrollbarSize={0}
disableVirtualization
columnVisibilityModel={
(cookies[cookieName] as GridColumnVisibilityModel) ?? undefined
}
onColumnVisibilityModelChange={handleColumnVisibilityChange}
onRowClick={onRowClick}
/>
</Box>
);
};

View file

@ -0,0 +1,71 @@
import { FC } from "react";
import { Grid, Box } from "@mui/material";
import { GridColDef } from "@mui/x-data-grid-pro";
import { StyledDataGrid } from "./StyledDataGrid";
import { typography } from "styles/theme";
import { useRouter } from "next/router";
interface TicketListProps {
title: string;
tickets: any;
}
export const TicketList: FC<TicketListProps> = ({ title, tickets }) => {
const router = useRouter();
let gridColumns: GridColDef[] = [
{
field: "number",
headerName: "Number",
flex: 1,
},
{
field: "title",
headerName: "Title",
flex: 1,
},
{
field: "customer",
headerName: "Sender",
valueGetter: (params) => params.row?.customer?.fullname,
flex: 1,
},
{
field: "group",
headerName: "Group",
valueGetter: (params) => params.row?.group?.name,
flex: 1,
},
];
console.log({ tickets });
const rowClick = ({ row }) => {
router.push(`/tickets/${row.internalId}`);
};
return (
<Box sx={{ height: "100vh", backgroundColor: "#ddd", p: 3 }}>
<Grid container direction="column">
<Grid item>
<Box
sx={{
backgroundColor: "#ddd",
px: "8px",
pb: "16px",
...typography.h4,
fontSize: 24,
}}
>
{title}
</Box>
</Grid>
<Grid item>
<StyledDataGrid
name={title}
columns={gridColumns}
rows={tickets}
onRowClick={rowClick}
/>
</Grid>
</Grid>
</Box>
);
};

View file

@ -0,0 +1,19 @@
import { gql } from 'graphql-request';
export const getTicketOverviewCountsQuery = gql`
query ticketOverviewTicketCount {
ticketOverviews {
edges {
node {
id
name
ticketCount
}
cursor
}
pageInfo {
endCursor
hasNextPage
}
}
}`;

View file

@ -0,0 +1,60 @@
import { gql } from 'graphql-request';
export const getTicketsByOverviewQuery = gql`
query ticketsByOverview($overviewId: ID!, $orderBy: String, $orderDirection: EnumOrderDirection, $cursor: String, $showPriority: Boolean = false, $showUpdatedBy: Boolean = false, $pageSize: Int = 10) {
ticketsByOverview(
overviewId: $overviewId
orderBy: $orderBy
orderDirection: $orderDirection
after: $cursor
first: $pageSize
) {
totalCount
edges {
node {
id
internalId
number
title
createdAt
updatedAt
updatedBy @include(if: $showUpdatedBy) {
id
fullname
}
customer {
id
firstname
lastname
fullname
}
organization {
id
name
}
state {
id
name
stateType {
name
}
}
group {
id
name
}
priority @include(if: $showPriority) {
id
name
uiColor
defaultCreate
}
}
cursor
}
pageInfo {
endCursor
hasNextPage
}
}
}`;

View file

@ -1,9 +1,12 @@
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { withAuth } from "next-auth/middleware";
import { getToken } from "next-auth/jwt";
import { withAuth, NextRequestWithAuth } from "next-auth/middleware";
const rewriteURL = (request: NextRequest, originBaseURL: string, destinationBaseURL: string, headers: any = {}) => {
if (request.nextUrl.protocol.startsWith('ws')) {
return NextResponse.next();
}
if (request.nextUrl.pathname.includes('/_next/static/development/')) {
return NextResponse.next();
}
@ -11,31 +14,54 @@ const rewriteURL = (request: NextRequest, originBaseURL: string, destinationBase
const destinationURL = request.url.replace(originBaseURL, destinationBaseURL);
console.log(`Rewriting ${request.url} to ${destinationURL}`);
return NextResponse.rewrite(new URL(destinationURL), { ...request.headers, ...headers });
const requestHeaders = new Headers(request.headers);
for (const [key, value] of Object.entries(headers)) {
// @ts-ignore
requestHeaders.set(key, value);
}
requestHeaders.delete('connection');
console.log({ finalHeaders: requestHeaders });
return NextResponse.rewrite(new URL(destinationURL), { request: { headers: requestHeaders } });
};
const checkRewrites = async (request: NextRequest) => {
const checkRewrites = async (request: NextRequestWithAuth) => {
console.log({ currentURL: request.nextUrl.href });
const linkBaseURL = process.env.LINK_URL ?? "http://localhost:3000";
const zammadURL = process.env.ZAMMAD_URL ?? "http://zammad-nginx:8080";
const leafcutterURL = process.env.LEAFCUTTER_URL ?? "http://leafcutter:3000";
const metamigoURL = process.env.METAMIGO_URL ?? "http://metamigo:3000";
if (request.nextUrl.pathname.startsWith('/proxy/leafcutter')) {
return rewriteURL(request, process.env.LINK_URL, process.env.LEAFCUTTER_URL);
return rewriteURL(request, linkBaseURL, leafcutterURL);
} else if (request.nextUrl.pathname.startsWith('/proxy/metamigo')) {
return rewriteURL(request, process.env.LINK_URL, process.env.METAMIGO_URL);
return rewriteURL(request, linkBaseURL, metamigoURL);
} else if (request.nextUrl.pathname.startsWith('/proxy/zammad')) {
const session = await getToken({
req: request,
secret: process.env.NEXTAUTH_SECRET,
});
console.log('proxying to zammad');
const { token } = request.nextauth;
console.log({ nextauth: request.nextauth });
const headers = {
'X-Forwarded-User': session.email.toLowerCase(),
host: 'zammad.example.com'
'X-Forwarded-User': token.email.toLowerCase(),
host: 'link-stack-dev.digiresilience.org'
};
return rewriteURL(request, `${process.env.LINK_URL}/proxy/zammad`, process.env.ZAMMAD_URL, headers);
} else if (request.nextUrl.pathname.startsWith('/assets')) {
console.log({ headers });
return rewriteURL(request, `${linkBaseURL}/proxy/zammad`, zammadURL, headers);
} else if (request.nextUrl.pathname.startsWith('/assets') || request.nextUrl.pathname.startsWith('/api/v1')) {
console.log('asset');
return rewriteURL(request, `${process.env.LINK_URL}`, process.env.ZAMMAD_URL);
} else if (request.nextUrl.pathname.startsWith('/proxy/assets') || request.nextUrl.pathname.startsWith('/proxy/api')) {
return rewriteURL(request, linkBaseURL, zammadURL);
} else if (request.nextUrl.pathname.startsWith('/proxy/assets')) {
console.log('proxy asset');
return rewriteURL(request, `${process.env.LINK_URL}/proxy`, process.env.ZAMMAD_URL);
return rewriteURL(request, `${linkBaseURL}/proxy`, zammadURL);
} else if (request.nextUrl.pathname.startsWith('/proxy/api')) {
console.log('proxy api');
return rewriteURL(request, `${linkBaseURL}/proxy`, zammadURL);
}
};
@ -71,4 +97,3 @@ export default withAuth(
}
}
);

View file

@ -5,6 +5,17 @@ const nextConfig = {
linkURL: process.env.LINK_URL,
leafcutterURL: process.env.LEAFCUTTER_URL,
metamigoURL: process.env.METAMIGO_URL,
muiLicenseKey: process.env.MUI_LICENSE_KEY,
},
async rewrites() {
return {
fallback: [
{
source: "/:path*",
destination: `/proxy/zammad/:path*`,
},
],
};
},
};

View file

@ -16,8 +16,10 @@ import "styles/global.css";
import { LicenseInfo } from "@mui/x-data-grid-pro";
import { SWRConfig } from "swr";
import { GraphQLClient } from "graphql-request";
import getConfig from "next/config";
LicenseInfo.setLicenseKey(process.env.MUI_LICENSE_KEY);
const { publicRuntimeConfig } = getConfig();
LicenseInfo.setLicenseKey(publicRuntimeConfig.muiLicenseKey);
const clientSideEmotionCache: any = createEmotionCache();

View file

@ -0,0 +1,5 @@
import { NextApiRequest, NextApiResponse } from 'next';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.redirect(307, '/proxy/zammad/api/v1' + req.url.substring('/api/v1'.length));
}

View file

@ -49,7 +49,7 @@ const Login: FC<LoginProps> = ({ session }) => {
sx={buttonStyles}
onClick={() =>
signIn("google", {
callbackUrl: `${origin}/auth/sso`,
callbackUrl: `${origin}/proxy/zammad/auth/sso`,
})
}
>

View file

@ -1,31 +1,32 @@
import { FC } from "react";
import Head from "next/head";
import { Grid } from "@mui/material";
import useSWR from "swr";
import { NextPage } from "next";
import { Layout } from "components/Layout";
import { ZammadWrapper } from "components/ZammadWrapper";
import { TicketList } from "components/TicketList";
import { getTicketsByOverviewQuery } from "graphql/getTicketsByOverviewQuery";
const Assigned: FC = () => (
<Layout>
<Head>
<title>Link Shell</title>
</Head>
<Grid
container
spacing={0}
sx={{ height: "100%", width: "100%" }}
direction="column"
>
<Grid
item
sx={{
height: "100%",
width: "100%",
}}
>
<ZammadWrapper path="/#ticket/view/my_assigned" />
</Grid>
</Grid>
</Layout>
);
const Assigned: NextPage = () => {
const { data: ticketData, error: ticketError }: any = useSWR(
{
document: getTicketsByOverviewQuery,
variables: { overviewId: "gid://zammad/Overview/1" },
},
{ refreshInterval: 10000 }
);
const shouldRender = !ticketError && ticketData;
const tickets =
ticketData?.ticketsByOverview?.edges.map((edge: any) => edge.node) || [];
return (
<Layout>
<Head>
<title>Link Shell Assigned Tickets</title>
</Head>
{shouldRender && <TicketList title="Assigned" tickets={tickets} />}
{ticketError && <div>{ticketError.toString()}</div>}
</Layout>
);
};
export default Assigned;

View file

@ -1,31 +1,32 @@
import { FC } from "react";
import Head from "next/head";
import { Grid } from "@mui/material";
import useSWR from "swr";
import { NextPage } from "next";
import { Layout } from "components/Layout";
import { ZammadWrapper } from "components/ZammadWrapper";
import { TicketList } from "components/TicketList";
import { getTicketsByOverviewQuery } from "graphql/getTicketsByOverviewQuery";
const Pending: FC = () => (
<Layout>
<Head>
<title>Link Shell</title>
</Head>
<Grid
container
spacing={0}
sx={{ height: "100%", width: "100%" }}
direction="column"
>
<Grid
item
sx={{
height: "100%",
width: "100%",
}}
>
<ZammadWrapper path="/#ticket/view/my_pending_reached" />
</Grid>
</Grid>
</Layout>
);
const Pending: NextPage = () => {
const { data: ticketData, error: ticketError }: any = useSWR(
{
document: getTicketsByOverviewQuery,
variables: { overviewId: "gid://zammad/Overview/3" },
},
{ refreshInterval: 10000 }
);
const shouldRender = !ticketError && ticketData;
const tickets =
ticketData?.ticketsByOverview?.edges.map((edge: any) => edge.node) || [];
return (
<Layout>
<Head>
<title>Link Shell Assigned Tickets</title>
</Head>
{shouldRender && <TicketList title="Pending" tickets={tickets} />}
{ticketError && <div>{ticketError.toString()}</div>}
</Layout>
);
};
export default Pending;

View file

@ -1,31 +1,32 @@
import { FC } from "react";
import Head from "next/head";
import { Grid } from "@mui/material";
import useSWR from "swr";
import { NextPage } from "next";
import { Layout } from "components/Layout";
import { ZammadWrapper } from "components/ZammadWrapper";
import { TicketList } from "components/TicketList";
import { getTicketsByOverviewQuery } from "graphql/getTicketsByOverviewQuery";
const Unassigned: FC = () => (
<Layout>
<Head>
<title>Link Shell</title>
</Head>
<Grid
container
spacing={0}
sx={{ height: "100%", width: "100%" }}
direction="column"
>
<Grid
item
sx={{
height: "100%",
width: "100%",
}}
>
<ZammadWrapper path="/#ticket/view/all_unassigned" />
</Grid>
</Grid>
</Layout>
);
const Unassigned: NextPage = () => {
const { data: ticketData, error: ticketError }: any = useSWR(
{
document: getTicketsByOverviewQuery,
variables: { overviewId: "gid://zammad/Overview/2" },
},
{ refreshInterval: 10000 }
);
const shouldRender = !ticketError && ticketData;
const tickets =
ticketData?.ticketsByOverview?.edges.map((edge: any) => edge.node) || [];
return (
<Layout>
<Head>
<title>Link Shell Assigned Tickets</title>
</Head>
{shouldRender && <TicketList title="Unassigned" tickets={tickets} />}
{ticketError && <div>{ticketError.toString()}</div>}
</Layout>
);
};
export default Unassigned;

View file

@ -1,31 +1,32 @@
import { FC } from "react";
import Head from "next/head";
import { Grid } from "@mui/material";
import useSWR from "swr";
import { NextPage } from "next";
import { Layout } from "components/Layout";
import { ZammadWrapper } from "components/ZammadWrapper";
import { TicketList } from "components/TicketList";
import { getTicketsByOverviewQuery } from "graphql/getTicketsByOverviewQuery";
const Urgent: FC = () => (
<Layout>
<Head>
<title>Link Shell</title>
</Head>
<Grid
container
spacing={0}
sx={{ height: "100%", width: "100%" }}
direction="column"
>
<Grid
item
sx={{
height: "100%",
width: "100%",
}}
>
<ZammadWrapper path="/#ticket/view/all_escalated" />
</Grid>
</Grid>
</Layout>
);
const Urgent: NextPage = () => {
const { data: ticketData, error: ticketError }: any = useSWR(
{
document: getTicketsByOverviewQuery,
variables: { overviewId: "gid://zammad/Overview/7" },
},
{ refreshInterval: 10000 }
);
const shouldRender = !ticketError && ticketData;
const tickets =
ticketData?.ticketsByOverview?.edges.map((edge: any) => edge.node) || [];
return (
<Layout>
<Head>
<title>Link Shell Urgent Tickets</title>
</Head>
{shouldRender && <TicketList title="Urgent" tickets={tickets} />}
{ticketError && <div>{ticketError.toString()}</div>}
</Layout>
);
};
export default Urgent;

View file

@ -38,6 +38,7 @@
"pg": "^8.11.0",
"pg-monitor": "^2.0.0",
"pg-promise": "^11.4.3",
"postgraphile": "4.12.3",
"postgraphile-plugin-connection-filter": "^2.3.0",
"remeda": "^1.18.1",
"twilio": "^4.11.1",

View file

@ -6,7 +6,6 @@ import {
TextField,
EmailField,
BooleanField,
ListProps,
} from "react-admin";
const UserList = () => (

View file

@ -7,7 +7,6 @@ import Cognito from "next-auth/providers/cognito";
import { loadConfig, IAppConfig } from "@digiresilience/metamigo-config";
import { MetamigoAdapter } from "../../../lib/nextauth-adapter";
import { CloudflareAccessProvider } from "../../../lib/cloudflare";
import { AdapterSession, AdapterUser } from "next-auth/adapters";
const nextAuthOptions = (config: IAppConfig, req: NextApiRequest) => {
const { nextAuth, cfaccess } = config;
@ -70,8 +69,8 @@ const nextAuthOptions = (config: IAppConfig, req: NextApiRequest) => {
providers,
adapter,
callbacks: {
async session({session, token, user}) {
session.user.id = user.id
async session({ session, user }: any) {
session.user.id = user.id;
session.user.userRole = user.userRole;
return session;
},

View file

@ -62,7 +62,7 @@ services:
depends_on:
- zammad-postgresql
environment:
<<: [*common-zammad-variables, *common-global-variables]
<<: [ *common-zammad-variables, *common-global-variables ]
POSTGRESQL_USER: zammad
POSTGRESQL_PASS: ${ZAMMAD_DATABASE_PASSWORD}
build: ./docker/zammad
@ -124,7 +124,7 @@ services:
- zammad-postgresql
- zammad-redis
environment:
<<: [*common-global-variables, *common-zammad-variables]
<<: [ *common-global-variables, *common-zammad-variables ]
build: ./docker/zammad
image: registry.gitlab.com/digiresilience/link/link-stack/zammad
restart: ${RESTART}
@ -137,7 +137,7 @@ services:
image: registry.gitlab.com/digiresilience/link/link-stack/zammad-redis
restart: ${RESTART}
environment:
<<: *common-global-variables
<<: *common-global-variables
zammad-scheduler:
platform: linux/x86_64
@ -148,7 +148,7 @@ services:
- zammad-railsserver
- zammad-redis
environment:
<<: [*common-global-variables, *common-zammad-variables]
<<: [ *common-global-variables, *common-zammad-variables ]
build: ./docker/zammad
image: registry.gitlab.com/digiresilience/link/link-stack/zammad
restart: ${RESTART}
@ -164,13 +164,24 @@ services:
- zammad-railsserver
- zammad-redis
environment:
<<: [*common-global-variables, *common-zammad-variables]
<<: [ *common-global-variables, *common-zammad-variables ]
build: ./docker/zammad
image: registry.gitlab.com/digiresilience/link/link-stack/zammad
restart: ${RESTART}
volumes:
- zammad-data:/opt/zammad
opensearch:
container_name: opensearch
build: ./docker/opensearch
restart: ${RESTART}
volumes:
- opensearch-data:/usr/share/opensearch/data
opensearch-dashboards:
container_name: opensearch-dashboards
build: ./docker/opensearch-dashboards
restart: ${RESTART}
metamigo-postgresql:
build: ./docker/postgresql
@ -245,7 +256,7 @@ services:
volumes:
- ./signald-state:/signald
environment:
<<: *common-global-variables
<<: *common-global-variables
# nginx-proxy:
# container_name: nginx-proxy
@ -256,40 +267,49 @@ services:
# volumes:
# - /var/run/docker.sock:/tmp/docker.sock:ro
# link:
# container_name: link
# build:
# context: .
# dockerfile: ./apps/link/Dockerfile
# expose:
# - "3000"
# ports:
# - "8003:3000"
# environment:
# <<: *common-global-variables
# ZAMMAD_PROXY_URL: ${ZAMMAD_PROXY_URL}
# ZAMMAD_URL: ${ZAMMAD_URL}
# ZAMMAD_API_TOKEN: ${ZAMMAD_API_TOKEN}
# ZAMMAD_VIRUAL_HOST: ${ZAMMAD_VIRTUAL_HOST}
# LINK_URL: ${LINK_URL}
# NEXTAUTH_URL: ${LINK_URL}
# NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
# NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
# NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
# NEXTAUTH_ENCRYPTION_KEY_B64: ${NEXTAUTH_ENCRYPTION_KEY_B64}
# GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
# GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
link:
container_name: link
restart: ${RESTART}
build:
context: .
dockerfile: ./apps/link/Dockerfile
expose:
- "3000"
ports:
- "8003:3000"
environment:
ZAMMAD_PROXY_URL: ${ZAMMAD_PROXY_URL}
ZAMMAD_API_TOKEN: ${ZAMMAD_API_TOKEN}
ZAMMAD_VIRUAL_HOST: ${ZAMMAD_VIRTUAL_HOST}
LINK_URL: ${LINK_URL}
LEAFCUTTER_URL: http://leafcutter:3000
METAMIGO_URL: http://metamigo-frontend:3000
ZAMMAD_URL: http://localhost:8001
NEXTAUTH_URL: ${LINK_URL}
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
NEXTAUTH_ENCRYPTION_KEY_B64: ${NEXTAUTH_ENCRYPTION_KEY_B64}
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
# leafcutter:
# container_name: leafcutter
# build:
# context: .
# dockerfile: ./apps/leafcutter/Dockerfile
# ports:
# - "8004:3000"
# environment:
# <<: *common-global-variables
# LINK_EMBEDDED: "true"
leafcutter:
container_name: leafcutter
restart: ${RESTART}
build:
context: .
dockerfile: ./apps/leafcutter/Dockerfile
expose:
- "3000"
ports:
- "8004:3000"
environment:
LINK_EMBEDDED: "true"
NEXTAUTH_URL: ${LINK_URL}
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
NEXTAUTH_ENCRYPTION_KEY_B64: ${NEXTAUTH_ENCRYPTION_KEY_B64}
volumes:
elasticsearch-data:
@ -300,3 +320,5 @@ volumes:
driver: local
metamigo-data:
driver: local
opensearch-data:
driver: local

View file

@ -0,0 +1 @@
FROM opensearchproject/opensearch-dashboards:2.8.0

View file

@ -0,0 +1 @@
FROM opensearchproject/opensearch:2.8.0

8067
package-lock.json generated

File diff suppressed because it is too large Load diff