Update proxying, swap /zammad and /link
This commit is contained in:
parent
2fd85f045c
commit
9283227074
24 changed files with 3317 additions and 2822 deletions
|
|
@ -29,6 +29,7 @@ build-all:
|
||||||
- main
|
- main
|
||||||
- develop
|
- develop
|
||||||
- tags
|
- tags
|
||||||
|
- base-url-changes
|
||||||
script:
|
script:
|
||||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||||
- DOCKER_BUILDKIT=1 docker build --pull --no-cache -t ${DOCKER_NS}:${DOCKER_TAG} -f ${DOCKERFILE_PATH} ${DOCKER_CONTEXT}
|
- DOCKER_BUILDKIT=1 docker build --pull --no-cache -t ${DOCKER_NS}:${DOCKER_TAG} -f ${DOCKERFILE_PATH} ${DOCKER_CONTEXT}
|
||||||
|
|
@ -46,6 +47,7 @@ build-all:
|
||||||
- main
|
- main
|
||||||
- develop
|
- develop
|
||||||
- tags
|
- tags
|
||||||
|
- base-url-changes
|
||||||
script:
|
script:
|
||||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||||
- docker pull ${DOCKER_NS}:${DOCKER_TAG}
|
- docker pull ${DOCKER_NS}:${DOCKER_TAG}
|
||||||
|
|
|
||||||
|
|
@ -14,27 +14,27 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@auth/kysely-adapter": "^1.5.2",
|
"@auth/kysely-adapter": "^1.5.2",
|
||||||
|
"@link-stack/bridge-common": "*",
|
||||||
|
"@link-stack/bridge-ui": "*",
|
||||||
|
"@link-stack/ui": "*",
|
||||||
"@mui/icons-material": "^5",
|
"@mui/icons-material": "^5",
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/material-nextjs": "^5",
|
"@mui/material-nextjs": "^5",
|
||||||
"@mui/x-license": "^7.18.0",
|
"@mui/x-license": "^7.18.0",
|
||||||
"@link-stack/bridge-common": "*",
|
"next": "^14.2.23",
|
||||||
"@link-stack/bridge-ui": "*",
|
|
||||||
"next": "14.2.13",
|
|
||||||
"next-auth": "^4.24.8",
|
"next-auth": "^4.24.8",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
"tsx": "^4.19.1",
|
"tsx": "^4.19.1"
|
||||||
"@link-stack/ui": "*"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@link-stack/eslint-config": "*",
|
||||||
|
"@link-stack/typescript-config": "*",
|
||||||
"@types/node": "^22",
|
"@types/node": "^22",
|
||||||
"@types/pg": "^8.11.10",
|
"@types/pg": "^8.11.10",
|
||||||
"@types/react": "^18",
|
"@types/react": "^18",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
"@link-stack/eslint-config": "*",
|
|
||||||
"@link-stack/typescript-config": "*",
|
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"http-proxy-middleware": "^3.0.2",
|
"http-proxy-middleware": "^3.0.2",
|
||||||
"material-ui-popup-state": "^5.3.1",
|
"material-ui-popup-state": "^5.3.1",
|
||||||
"next": "14.2.13",
|
"next": "^14.2.23",
|
||||||
"next-auth": "^4.24.8",
|
"next-auth": "^4.24.8",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-cookie": "^7.2.0",
|
"react-cookie": "^7.2.0",
|
||||||
|
|
@ -39,11 +39,11 @@
|
||||||
"uuid": "^10.0.0"
|
"uuid": "^10.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@link-stack/eslint-config": "*",
|
||||||
|
"@link-stack/typescript-config": "*",
|
||||||
"@types/node": "^22.7.3",
|
"@types/node": "^22.7.3",
|
||||||
"@types/react": "18.3.9",
|
"@types/react": "18.3.9",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"@link-stack/eslint-config": "*",
|
|
||||||
"@link-stack/typescript-config": "*",
|
|
||||||
"typescript": "5.6.2"
|
"typescript": "5.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -477,14 +477,6 @@ export const Sidebar: FC<SidebarProps> = ({
|
||||||
/>
|
/>
|
||||||
</List>
|
</List>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
<MenuItem
|
|
||||||
name="Knowledge Base"
|
|
||||||
href="/knowledge"
|
|
||||||
Icon={SchoolIcon}
|
|
||||||
iconSize={20}
|
|
||||||
selected={pathname.endsWith("/knowledge")}
|
|
||||||
open={open}
|
|
||||||
/>
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
name="Documentation"
|
name="Documentation"
|
||||||
href="/docs"
|
href="/docs"
|
||||||
|
|
@ -493,14 +485,6 @@ export const Sidebar: FC<SidebarProps> = ({
|
||||||
selected={pathname.endsWith("/docs")}
|
selected={pathname.endsWith("/docs")}
|
||||||
open={open}
|
open={open}
|
||||||
/>
|
/>
|
||||||
<MenuItem
|
|
||||||
name="Reporting"
|
|
||||||
href="/reporting"
|
|
||||||
Icon={AssessmentIcon}
|
|
||||||
iconSize={20}
|
|
||||||
selected={pathname.endsWith("/reporting")}
|
|
||||||
open={open}
|
|
||||||
/>
|
|
||||||
{leafcutterEnabled && (
|
{leafcutterEnabled && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
name="Leafcutter"
|
name="Leafcutter"
|
||||||
|
|
@ -557,14 +541,6 @@ export const Sidebar: FC<SidebarProps> = ({
|
||||||
/>
|
/>
|
||||||
</List>
|
</List>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
<MenuItem
|
|
||||||
name="Profile"
|
|
||||||
href="/profile"
|
|
||||||
Icon={PersonIcon}
|
|
||||||
iconSize={20}
|
|
||||||
selected={pathname.endsWith("/profile")}
|
|
||||||
open={open}
|
|
||||||
/>
|
|
||||||
{roles.includes("admin") && (
|
{roles.includes("admin") && (
|
||||||
<>
|
<>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|
@ -631,36 +607,10 @@ export const Sidebar: FC<SidebarProps> = ({
|
||||||
/>
|
/>
|
||||||
</List>
|
</List>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
<MenuItem
|
|
||||||
name="Zammad Settings"
|
|
||||||
href="/admin/zammad"
|
|
||||||
Icon={FeaturedPlayListIcon}
|
|
||||||
iconSize={0}
|
|
||||||
selected={pathname.endsWith("/admin/zammad")}
|
|
||||||
open={open}
|
|
||||||
/>
|
|
||||||
{roles.includes("label_studio") && (
|
|
||||||
<MenuItem
|
|
||||||
name="Label Studio"
|
|
||||||
href="/admin/label-studio"
|
|
||||||
Icon={FeaturedPlayListIcon}
|
|
||||||
iconSize={0}
|
|
||||||
selected={pathname.endsWith("/admin/label-studio")}
|
|
||||||
open={open}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</List>
|
</List>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<MenuItem
|
|
||||||
name="Zammad Interface"
|
|
||||||
href="/zammad"
|
|
||||||
Icon={DvrIcon}
|
|
||||||
iconSize={20}
|
|
||||||
open={open}
|
|
||||||
target="_blank"
|
|
||||||
/>
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
name="Logout"
|
name="Logout"
|
||||||
href="/logout"
|
href="/logout"
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ export const MultiProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||||
const locale = "en";
|
const locale = "en";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SessionProvider>
|
<SessionProvider basePath="/link/api/auth">
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<ZammadLoginProvider>
|
<ZammadLoginProvider>
|
||||||
<CookiesProvider>
|
<CookiesProvider>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { withAuth, NextRequestWithAuth } from "next-auth/middleware";
|
import { withAuth, NextRequestWithAuth } from "next-auth/middleware";
|
||||||
|
|
||||||
|
/*
|
||||||
const rewriteURL = (
|
const rewriteURL = (
|
||||||
request: NextRequestWithAuth,
|
request: NextRequestWithAuth,
|
||||||
originBaseURL: string,
|
originBaseURL: string,
|
||||||
|
|
@ -25,31 +26,16 @@ const rewriteURL = (
|
||||||
request: { headers: requestHeaders },
|
request: { headers: requestHeaders },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
const checkRewrites = async (request: NextRequestWithAuth) => {
|
const checkRewrites = async (request: NextRequestWithAuth) => {
|
||||||
const linkBaseURL = process.env.LINK_URL ?? "http://localhost:3000";
|
// const linkBaseURL = process.env.LINK_URL ?? "http://localhost:3000";
|
||||||
const zammadURL = process.env.ZAMMAD_URL ?? "http://zammad-nginx:8080";
|
|
||||||
|
|
||||||
const zammadPaths = [
|
|
||||||
"/zammad",
|
|
||||||
"/auth/sso",
|
|
||||||
"/assets",
|
|
||||||
"/mobile",
|
|
||||||
"/graphql",
|
|
||||||
"/cable",
|
|
||||||
];
|
|
||||||
const { token } = request.nextauth;
|
const { token } = request.nextauth;
|
||||||
const email = token?.email?.toLowerCase() ?? "unknown";
|
const email = token?.email?.toLowerCase() ?? "unknown";
|
||||||
let headers = { "x-forwarded-user": email };
|
// let headers = { "x-forwarded-user": email };
|
||||||
|
|
||||||
if (request.nextUrl.pathname.startsWith("/zammad")) {
|
const isDev = process.env.NODE_ENV === "development";
|
||||||
return rewriteURL(request, `${linkBaseURL}/zammad`, zammadURL, headers);
|
const nonce = Buffer.from(crypto.randomUUID()).toString("base64");
|
||||||
} else if (zammadPaths.some((p) => request.nextUrl.pathname.startsWith(p))) {
|
const cspHeader = `
|
||||||
return rewriteURL(request, linkBaseURL, zammadURL, headers);
|
|
||||||
} else {
|
|
||||||
const isDev = process.env.NODE_ENV === "development";
|
|
||||||
const nonce = Buffer.from(crypto.randomUUID()).toString("base64");
|
|
||||||
const cspHeader = `
|
|
||||||
default-src 'self';
|
default-src 'self';
|
||||||
connect-src 'self';
|
connect-src 'self';
|
||||||
script-src 'self' 'nonce-${nonce}' 'strict-dynamic' ${isDev ? "'unsafe-eval'" : ""};
|
script-src 'self' 'nonce-${nonce}' 'strict-dynamic' ${isDev ? "'unsafe-eval'" : ""};
|
||||||
|
|
@ -62,30 +48,29 @@ const checkRewrites = async (request: NextRequestWithAuth) => {
|
||||||
frame-ancestors 'none';
|
frame-ancestors 'none';
|
||||||
upgrade-insecure-requests;
|
upgrade-insecure-requests;
|
||||||
`;
|
`;
|
||||||
const contentSecurityPolicyHeaderValue = cspHeader
|
const contentSecurityPolicyHeaderValue = cspHeader
|
||||||
.replace(/\s{2,}/g, " ")
|
.replace(/\s{2,}/g, " ")
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
const requestHeaders = new Headers(request.headers);
|
const requestHeaders = new Headers(request.headers);
|
||||||
requestHeaders.set("x-nonce", nonce);
|
requestHeaders.set("x-nonce", nonce);
|
||||||
requestHeaders.set(
|
requestHeaders.set(
|
||||||
"Content-Security-Policy",
|
"Content-Security-Policy",
|
||||||
contentSecurityPolicyHeaderValue,
|
contentSecurityPolicyHeaderValue,
|
||||||
);
|
);
|
||||||
|
|
||||||
const response = NextResponse.next({
|
const response = NextResponse.next({
|
||||||
request: {
|
request: {
|
||||||
headers: requestHeaders,
|
headers: requestHeaders,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
response.headers.set(
|
response.headers.set(
|
||||||
"Content-Security-Policy",
|
"Content-Security-Policy",
|
||||||
contentSecurityPolicyHeaderValue,
|
contentSecurityPolicyHeaderValue,
|
||||||
);
|
);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withAuth(checkRewrites, {
|
export default withAuth(checkRewrites, {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
|
basePath: '/link',
|
||||||
poweredByHeader: false,
|
poweredByHeader: false,
|
||||||
transpilePackages: [
|
transpilePackages: [
|
||||||
"@link-stack/leafcutter-ui",
|
"@link-stack/leafcutter-ui",
|
||||||
|
|
@ -30,20 +31,6 @@ const nextConfig = {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
rewrites: async () => {
|
|
||||||
return {
|
|
||||||
beforeFiles: [
|
|
||||||
{
|
|
||||||
source: "/api/v1/:path*",
|
|
||||||
destination: `${process.env.ZAMMAD_URL ?? "http://zammad-nginx:8080"}/api/v1/:path*`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
source: "/ws",
|
|
||||||
destination: `${process.env.ZAMMAD_URL ?? "http://zammad-nginx:8080"}/ws`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"graphql-request": "^7.1.0",
|
"graphql-request": "^7.1.0",
|
||||||
"mui-chips-input": "^2.1.5",
|
"mui-chips-input": "^2.1.5",
|
||||||
"next": "14.2.13",
|
"next": "^14.2.23",
|
||||||
"next-auth": "^4.24.8",
|
"next-auth": "^4.24.8",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-cookie": "^7.2.0",
|
"react-cookie": "^7.2.0",
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,24 @@ x-global-vars: &common-global-variables
|
||||||
TZ: Etc/UTC
|
TZ: Etc/UTC
|
||||||
|
|
||||||
x-bridge-vars: &common-bridge-variables
|
x-bridge-vars: &common-bridge-variables
|
||||||
DATABASE_HOST: "bridge-postgresql"
|
DATABASE_HOST: "postgresql"
|
||||||
DATABASE_NAME: "bridge"
|
DATABASE_NAME: "cdr"
|
||||||
|
DATABASE_USER: ${DATABASE_USER}
|
||||||
DATABASE_ROOT_OWNER: "root"
|
DATABASE_ROOT_OWNER: "root"
|
||||||
DATABASE_ROOT_PASSWORD: ${BRIDGE_DATABASE_ROOT_PASSWORD}
|
DATABASE_ROOT_PASSWORD: ${BRIDGE_DATABASE_ROOT_PASSWORD}
|
||||||
DATABASE_OWNER: "bridge"
|
DATABASE_OWNER: ${DATABASE_USER}
|
||||||
DATABASE_PASSWORD: ${BRIDGE_DATABASE_PASSWORD}
|
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
|
||||||
DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/bridge"
|
DATABASE_URL: "postgresql://bridge:${DATABASE_PASSWORD}@postgresql/cdr"
|
||||||
WORKER_DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/bridge"
|
WORKER_DATABASE_URL: "postgresql://bridge:${DATABASE_PASSWORD}@postgresql/cdr"
|
||||||
SHADOW_DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/bridge_shadow"
|
SHADOW_DATABASE_URL: "postgresql://bridge:${DATABASE_PASSWORD}@postgresql/cdr_shadow"
|
||||||
ROOT_DATABASE_URL: "postgresql://bridge:${BRIDGE_DATABASE_PASSWORD}@bridge-postgresql/template1"
|
ROOT_DATABASE_URL: "postgresql://bridge:${DATABASE_PASSWORD}@postgresql/template1"
|
||||||
APP_ROOT_DATABASE_URL: "postgresql://root:${BRIDGE_DATABASE_ROOT_PASSWORD}@bridge-postgresql/bridge"
|
APP_ROOT_DATABASE_URL: "postgresql://root:${BRIDGE_DATABASE_ROOT_PASSWORD}@postgresql/bridge"
|
||||||
DATABASE_AUTH_URL: "postgresql://app_graphile_auth:${BRIDGE_DATABASE_AUTHENTICATOR_PASSWORD}@bridge-postgresql/bridge"
|
DATABASE_AUTH_URL: "postgresql://app_graphile_auth:${BRIDGE_DATABASE_AUTHENTICATOR_PASSWORD}@postgresql/cdr"
|
||||||
FRONTEND_URL: ${BRIDGE_DOMAIN}
|
FRONTEND_URL: ${BRIDGE_DOMAIN}
|
||||||
API_URL: "http://bridge-api:3001"
|
API_URL: "http://bridge-api:3001"
|
||||||
NEXTAUTH_URL: ${BRIDGE_DOMAIN}
|
NEXTAUTH_URL: ${BRIDGE_DOMAIN}
|
||||||
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
||||||
|
BRIDGE_SIGNAL_URL: ${BRIDGE_SIGNAL_URL}
|
||||||
|
|
||||||
services:
|
services:
|
||||||
bridge-frontend:
|
bridge-frontend:
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,22 @@ services:
|
||||||
environment:
|
environment:
|
||||||
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: http://localhost:3000
|
LINK_URL: ${LINK_URL}
|
||||||
LEAFCUTTER_URL: https://lc.digiresilience.org
|
LEAFCUTTER_URL: https://lc.digiresilience.org
|
||||||
BRIDGE_URL: http://bridge-frontend:3000
|
BRIDGE_URL: http://bridge-frontend:3000
|
||||||
|
BRIDGE_SIGNAL_URL: http://signal-cli-rest-api:8080
|
||||||
|
BRIDGE_WHATSAPP_URL: http://bridge-whatsapp:3000
|
||||||
ZAMMAD_URL: http://zammad-nginx:8080
|
ZAMMAD_URL: http://zammad-nginx:8080
|
||||||
NEXTAUTH_URL: ${LINK_URL}
|
NEXTAUTH_URL: ${LINK_URL}/api/auth
|
||||||
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
|
||||||
NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
|
NEXTAUTH_AUDIENCE: ${NEXTAUTH_AUDIENCE}
|
||||||
NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
|
NEXTAUTH_SIGNING_KEY_B64: ${NEXTAUTH_SIGNING_KEY_B64}
|
||||||
NEXTAUTH_ENCRYPTION_KEY_B64: ${NEXTAUTH_ENCRYPTION_KEY_B64}
|
NEXTAUTH_ENCRYPTION_KEY_B64: ${NEXTAUTH_ENCRYPTION_KEY_B64}
|
||||||
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
|
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
|
||||||
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
|
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
|
||||||
|
DATABASE_HOST: ${DATABASE_HOST}
|
||||||
|
DATABASE_NAME: ${DATABASE_NAME}
|
||||||
|
DATABASE_PORT: ${DATABASE_PORT}
|
||||||
|
DATABASE_USER: ${DATABASE_USER}
|
||||||
|
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
|
||||||
|
DATABASE_URL: ${DATABASE_URL}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ services:
|
||||||
image: registry.gitlab.com/digiresilience/link/link-stack/signal-cli-rest-api:develop
|
image: registry.gitlab.com/digiresilience/link/link-stack/signal-cli-rest-api:develop
|
||||||
platform: linux/amd64
|
platform: linux/amd64
|
||||||
environment:
|
environment:
|
||||||
- MODE=json-rpc
|
- MODE=normal
|
||||||
volumes:
|
volumes:
|
||||||
- signal-cli-rest-api-data:/home/.local/share/signal-cli
|
- signal-cli-rest-api-data:/home/.local/share/signal-cli
|
||||||
ports:
|
ports:
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,6 @@ services:
|
||||||
- postgresql
|
- postgresql
|
||||||
environment:
|
environment:
|
||||||
<<: [*common-global-variables, *common-zammad-variables]
|
<<: [*common-global-variables, *common-zammad-variables]
|
||||||
RAILS_RELATIVE_URL_ROOT: /zammad
|
|
||||||
build:
|
build:
|
||||||
context: ../zammad
|
context: ../zammad
|
||||||
args:
|
args:
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
FROM opensearchproject/opensearch-dashboards:2.17.0
|
FROM opensearchproject/opensearch-dashboards:2.18.0
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
FROM opensearchproject/opensearch:2.17.0
|
FROM opensearchproject/opensearch:2.18.0
|
||||||
RUN /usr/share/opensearch/bin/opensearch-plugin install ingest-attachment -b
|
RUN /usr/share/opensearch/bin/opensearch-plugin install ingest-attachment -b
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ const files = {
|
||||||
all: ["zammad", "postgresql", "bridge", "opensearch", "leafcutter", "link", "signal-cli-rest-api"],
|
all: ["zammad", "postgresql", "bridge", "opensearch", "leafcutter", "link", "signal-cli-rest-api"],
|
||||||
linkDev: ["zammad", "postgresql", "opensearch"],
|
linkDev: ["zammad", "postgresql", "opensearch"],
|
||||||
link: ["zammad", "postgresql", "opensearch", "link"],
|
link: ["zammad", "postgresql", "opensearch", "link"],
|
||||||
|
linkOnly: ["link"],
|
||||||
leafcutterDev: ["opensearch"],
|
leafcutterDev: ["opensearch"],
|
||||||
leafcutter: ["opensearch", "leafcutter"],
|
leafcutter: ["opensearch", "leafcutter"],
|
||||||
opensearch: ["opensearch"],
|
opensearch: ["opensearch"],
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,15 @@ USER root
|
||||||
RUN sed -i '/script\/build\/cleanup\.sh/d' contrib/docker/setup.sh
|
RUN sed -i '/script\/build\/cleanup\.sh/d' contrib/docker/setup.sh
|
||||||
RUN contrib/docker/setup.sh builder
|
RUN contrib/docker/setup.sh builder
|
||||||
ARG EMBEDDED=false
|
ARG EMBEDDED=false
|
||||||
RUN if [ "$EMBEDDED" = "true" ] ; then sed -i '/proxy_set_header X-Forwarded-User "";/d' ${ZAMMAD_DIR}/contrib/nginx/zammad.conf; fi
|
RUN if [ "$EMBEDDED" = "true" ] ; then sed -i '/location \/ {/i \
|
||||||
|
\ \n\
|
||||||
|
\ location /link {\n\
|
||||||
|
\ proxy_pass http://link;\n\
|
||||||
|
\ proxy_set_header Host $host;\n\
|
||||||
|
\ proxy_set_header X-Real-IP $remote_addr;\n\
|
||||||
|
\ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n\
|
||||||
|
\ proxy_set_header X-Forwarded-Proto https;\n\
|
||||||
|
\ }\n' ${ZAMMAD_DIR}/contrib/nginx/zammad.conf; fi
|
||||||
RUN sed -i '/^[[:space:]]*# es config/a\
|
RUN sed -i '/^[[:space:]]*# es config/a\
|
||||||
echo "about to reinstall..."\n\
|
echo "about to reinstall..."\n\
|
||||||
bundle exec rails runner /opt/zammad/contrib/link/setup.rb\n\
|
bundle exec rails runner /opt/zammad/contrib/link/setup.rb\n\
|
||||||
|
|
|
||||||
5880
package-lock.json
generated
5880
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -20,6 +20,7 @@
|
||||||
"docker:link:up": "node docker/scripts/docker.js link up",
|
"docker:link:up": "node docker/scripts/docker.js link up",
|
||||||
"docker:link:down": "node docker/scripts/docker.js link down",
|
"docker:link:down": "node docker/scripts/docker.js link down",
|
||||||
"docker:link:build": "node docker/scripts/docker.js link build",
|
"docker:link:build": "node docker/scripts/docker.js link build",
|
||||||
|
"docker:linkonly:build": "node docker/scripts/docker.js linkOnly build",
|
||||||
"docker:opensearch:up": "node docker/scripts/docker.js opensearch up",
|
"docker:opensearch:up": "node docker/scripts/docker.js opensearch up",
|
||||||
"docker:opensearch:down": "node docker/scripts/docker.js opensearch down",
|
"docker:opensearch:down": "node docker/scripts/docker.js opensearch down",
|
||||||
"docker:opensearch:build": "node docker/scripts/docker.js opensearch build",
|
"docker:opensearch:build": "node docker/scripts/docker.js opensearch build",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { ServiceConfig } from "../lib/service";
|
import { ServiceConfig } from "../lib/service";
|
||||||
|
|
||||||
const getQRCode = async (token: string): Promise<Record<string, string>> => {
|
const getQRCode = async (token: string): Promise<Record<string, string>> => {
|
||||||
const url = `/api/signal/bots/${token}`;
|
const url = `/link/api/signal/bots/${token}`;
|
||||||
const result = await fetch(url, { cache: "no-store" });
|
const result = await fetch(url, { cache: "no-store" });
|
||||||
const { qr } = await result.json();
|
const { qr } = await result.json();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { ServiceConfig } from "../lib/service";
|
||||||
// import { generateSelectOneAction } from "../lib/actions";
|
// import { generateSelectOneAction } from "../lib/actions";
|
||||||
|
|
||||||
const getQRCode = async (token: string) => {
|
const getQRCode = async (token: string) => {
|
||||||
const url = `/api/whatsapp/bots/${token}`;
|
const url = `/link/api/whatsapp/bots/${token}`;
|
||||||
const result = await fetch(url, { cache: "no-store" });
|
const result = await fetch(url, { cache: "no-store" });
|
||||||
const { qr } = await result.json();
|
const { qr } = await result.json();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/x-data-grid-pro": "^7.18.0",
|
"@mui/x-data-grid-pro": "^7.18.0",
|
||||||
"kysely": "0.26.1",
|
"kysely": "0.26.1",
|
||||||
"next": "14.2.13",
|
"next": "^14.2.23",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-qr-code": "^2.0.15"
|
"react-qr-code": "^2.0.15"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
"@mui/x-data-grid-pro": "^7.18.0",
|
"@mui/x-data-grid-pro": "^7.18.0",
|
||||||
"@mui/x-date-pickers-pro": "^7.18.0",
|
"@mui/x-date-pickers-pro": "^7.18.0",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"next": "14.2.13",
|
"next": "^14.2.23",
|
||||||
"next-auth": "^4.24.8",
|
"next-auth": "^4.24.8",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-cookie": "^7.2.0",
|
"react-cookie": "^7.2.0",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/x-data-grid-pro": "^7.18.0",
|
"@mui/x-data-grid-pro": "^7.18.0",
|
||||||
"@mui/x-license": "^7.18.0",
|
"@mui/x-license": "^7.18.0",
|
||||||
"next": "14.2.13",
|
"next": "^14.2.23",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1"
|
"react-dom": "18.3.1"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,20 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import { promises as fs } from "fs";
|
import { promises as fs } from "fs";
|
||||||
import { promisify } from "util";
|
import { glob } from "glob";
|
||||||
import glob from "glob";
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
|
|
||||||
const packageFile = async (actualPath: string): Promise<any> => {
|
const packageFile = async (actualPath: string): Promise<any> => {
|
||||||
console.log(`Packaging: ${actualPath}`);
|
console.info(`Packaging: ${actualPath}`);
|
||||||
const packagePath = actualPath.slice(4);
|
const packagePath = actualPath.slice(4);
|
||||||
const data = await fs.readFile(actualPath, "utf-8");
|
const data = await fs.readFile(actualPath, "utf-8");
|
||||||
const content = Buffer.from(data, "utf-8").toString("base64");
|
const content = Buffer.from(data, "utf-8").toString("base64");
|
||||||
const fileStats = await fs.stat(actualPath);
|
const fileStats = await fs.stat(actualPath);
|
||||||
const permission = parseInt((fileStats.mode & 0o777).toString(8).slice(-3), 10);
|
const permission = parseInt(
|
||||||
|
(fileStats.mode & 0o777).toString(8).slice(-3),
|
||||||
|
10,
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
location: packagePath,
|
location: packagePath,
|
||||||
permission,
|
permission,
|
||||||
|
|
@ -23,7 +25,12 @@ const packageFile = async (actualPath: string): Promise<any> => {
|
||||||
|
|
||||||
const packageFiles = async () => {
|
const packageFiles = async () => {
|
||||||
const packagedFiles: any[] = [];
|
const packagedFiles: any[] = [];
|
||||||
const ignoredPatterns = [/\.gitkeep/, /Gemfile/, /Gemfile.lock/, /\.ruby-version/];
|
const ignoredPatterns = [
|
||||||
|
/\.gitkeep/,
|
||||||
|
/Gemfile/,
|
||||||
|
/Gemfile.lock/,
|
||||||
|
/\.ruby-version/,
|
||||||
|
];
|
||||||
|
|
||||||
const processDir = async (dir: string) => {
|
const processDir = async (dir: string) => {
|
||||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
@ -43,7 +50,11 @@ const packageFiles = async () => {
|
||||||
return packagedFiles;
|
return packagedFiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createZPM = async ({ name, displayName, version }: Record<string, string>) => {
|
export const createZPM = async ({
|
||||||
|
name,
|
||||||
|
displayName,
|
||||||
|
version,
|
||||||
|
}: Record<string, string>) => {
|
||||||
const files = await packageFiles();
|
const files = await packageFiles();
|
||||||
const skeleton = {
|
const skeleton = {
|
||||||
name: displayName,
|
name: displayName,
|
||||||
|
|
@ -53,29 +64,32 @@ export const createZPM = async ({ name, displayName, version }: Record<string, s
|
||||||
url: `https://gitlab.com/digiresilience/link/link-stack/packages/${name}`,
|
url: `https://gitlab.com/digiresilience/link/link-stack/packages/${name}`,
|
||||||
buildhost: os.hostname(),
|
buildhost: os.hostname(),
|
||||||
builddate: new Date().toISOString(),
|
builddate: new Date().toISOString(),
|
||||||
files
|
files,
|
||||||
};
|
};
|
||||||
const pkg = JSON.stringify(skeleton, null, 2);
|
const pkg = JSON.stringify(skeleton, null, 2);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const gs = promisify(glob);
|
const files = await glob(`../../docker/zammad/addons/${name}-v*.zpm`, {});
|
||||||
const files = await gs(`../../docker/zammad/addons/${name}-v*.zpm`);
|
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
await fs.unlink(file);
|
await fs.unlink(file);
|
||||||
console.log(`${file} was deleted`);
|
console.info(`${file} was deleted`);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
await fs.writeFile(`../../docker/zammad/addons/${name}-v${version}.zpm`, pkg, 'utf-8');
|
await fs.writeFile(
|
||||||
|
`../../docker/zammad/addons/${name}-v${version}.zpm`,
|
||||||
|
pkg,
|
||||||
|
"utf-8",
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
const packageJSON = JSON.parse(await fs.readFile("./package.json", "utf-8"));
|
const packageJSON = JSON.parse(await fs.readFile("./package.json", "utf-8"));
|
||||||
const { name: fullName, displayName, version } = packageJSON;
|
const { name: fullName, displayName, version } = packageJSON;
|
||||||
console.log(`Building addon ${displayName} v${version}`);
|
console.info(`Building addon ${displayName} v${version}`);
|
||||||
const name = fullName.split("/").pop();
|
const name = fullName.split("/").pop();
|
||||||
await createZPM({ name, displayName, version });
|
await createZPM({ name, displayName, version });
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue