Skip to content

Commit

Permalink
Merge pull request #65 from tegonal/fix/BO-192_profile_image
Browse files Browse the repository at this point in the history
Fix/bo 192 profile image
  • Loading branch information
toggm authored Jan 9, 2025
2 parents a945cb1 + 6b9f9e9 commit a1f7e00
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 177 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
POSTGRES_URI=postgres://postgres:postgres@localhost:5432/tegonal-cv
PAYLOAD_SECRET=secret
PRINTER_SECRET=secret
# Use this flag with caution. This will prevent checking existence of PRINTER_SECRET in header. Use for local debug mode only
ALLOW_UNSECURED_CV_ACCESS=false

S3_ENDPOINT=http://localhost:9000
S3_BUCKET=tegonal-cv
Expand Down
8 changes: 5 additions & 3 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ services:
MINIO_ROOT_PASSWORD: secret1234
volumes:
- minio-data:/data
command: server /data --console-address ":9001"
command: server --console-address ":9001" /data

createbucket:
image: minio/mc
Expand Down Expand Up @@ -73,15 +73,17 @@ services:
- "--prometheus-disable-collect=true"
- "--webhook-disable=true"
- "--pdfengines-disable-routes=true"
- "--api-port=3030"
environment:
- "TZ=Europe/Zurich"
ports:
- "3030:3000"
- "3030:3030"
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:3000/health" ]
test: [ "CMD", "curl", "-f", "http://localhost:3030/health" ]
interval: 30s
timeout: 20s
retries: 3
network_mode: "host"

volumes:
mailpit-data:
Expand Down
16 changes: 16 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ const nextConfig = {
},
];
},
images: {
remotePatterns: [
{
protocol: "https",
hostname: "cvman-prod.jcloud.ik-server.com",
port: "",
pathname: "/api/media/file/**",
},
{
protocol: "http",
hostname: "localhost",
port: "3000",
pathname: "/api/media/file/**",
},
],
}
};

export default withPayload(nextConfig);
17 changes: 8 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,21 @@
"jsonwebtoken": "^9.0.2",
"ky": "^1.7.3",
"lodash-es": "^4.17.21",
"next": "15.1.3",
"next": "15.1.4",
"nodemailer": "^6.9.16",
"payload": "3.15.1",
"payload-oauth2": "^1.0.7",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-i18next": "^15.2.0",
"react-router-dom": "7.0.2",
"react-i18next": "^15.4.0",
"react-router-dom": "7.1.1",
"sharp": "0.33.5",
"swr": "^2.2.5",
"tslog": "^4.9.3"
},
"devDependencies": {
"@payloadcms/graphql": "3.15.1",
"@swc/core": "1.10.6",
"@tailwindcss/typography": "^0.5.15",
"@tailwindcss/typography": "^0.5.16",
"@types/jsdom": "^21.1.7",
"@types/jsonwebtoken": "^9.0.7",
"@types/lodash-es": "^4.17.12",
Expand All @@ -64,20 +63,20 @@
"@types/react": "^19.0.1",
"@types/react-dom": "^19.0.2",
"@types/react-router-dom": "^5.3.3",
"@typescript-eslint/eslint-plugin": "8.18.1",
"@typescript-eslint/parser": "8.18.1",
"@typescript-eslint/eslint-plugin": "8.19.1",
"@typescript-eslint/parser": "8.19.1",
"autoprefixer": "^10.4.20",
"dotenv": "^16.4.7",
"eslint": "^9.0.0",
"eslint-config-next": "15.1.3",
"eslint-config-next": "15.1.4",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jsonc": "^2.18.2",
"eslint-plugin-prettier": "^5.2.1",
"postcss": "^8.4.49",
"prettier": "^3.4.2",
"prettier-plugin-tailwindcss": "^0.6.9",
"tailwindcss": "^3.4.16",
"typescript": "5.7.2"
"typescript": "5.7.3"
},
"overrides": {
"@types/react": "npm:[email protected]",
Expand Down
35 changes: 33 additions & 2 deletions src/app/cv/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { PayloadLexicalReactRendererContent } from '@/payload/utilities/lexical-
import { HighlightEntry } from '@/app/cv/[id]/(lib)/components/highlight';
import { capitalize, isEmpty } from 'lodash-es';
import { getPayload } from 'payload';
import ky from 'ky';
import { headers } from 'next/headers';
import * as process from 'node:process';
import { PRINTER_HEADER_KEY } from '@/payload/utilities/constants';

type Args = {
params: Promise<{
Expand Down Expand Up @@ -63,12 +67,25 @@ const hasLexicalNodes = (data: PayloadLexicalReactRendererContent) => {
};

const Page = async ({ params, searchParams }: Args) => {
if (!process.env.PRINTER_SECRET) {
throw new Error('PDF Printer: Printer secret not found. Aborting..');
}

const query = {
params: await params,
searchParams: await searchParams,
};
const locale = 'de';

const headersList = await headers();
const printerSecret = headersList.get(PRINTER_HEADER_KEY);
if (
process.env.ALLOW_UNSECURED_CV_ACCESS != 'true' &&
(!printerSecret || printerSecret !== process.env.PRINTER_SECRET)
) {
throw new Error('Unable to access cv printer data');
}

const payload = await getPayload({ config: configPromise });

if (!query.searchParams.p) {
Expand All @@ -88,10 +105,24 @@ const Page = async ({ params, searchParams }: Args) => {
},
},
locale: decodedParams.locale,
depth: 1,
})
.then((data) => data.docs[0]);

const profileImage = (cv.image as Media)?.url || '';
const profileImage = (cv.image as Media)?.url;

const kyHeaders: Record<string, string | undefined> = {};
kyHeaders[PRINTER_HEADER_KEY] = process.env.PRINTER_SECRET;
const loadImage = async (url: string) => {
const response = await ky.get(url, {
headers: kyHeaders,
});
const blob = await response.blob();
let buffer = Buffer.from(await blob.arrayBuffer());
return 'data:' + blob.type + ';base64,' + buffer.toString('base64');
};

const profileImageDataUrl: string = profileImage ? await loadImage(profileImage) : '';

const hasOverride = (key: string) => {
return key in exportOverride && exportOverride[key];
Expand Down Expand Up @@ -120,7 +151,7 @@ const Page = async ({ params, searchParams }: Args) => {
className={'circle-mask relative flex size-48 flex-row items-center justify-center'}>
<Image
className={'profile-image bg-black object-cover'}
src={profileImage}
src={profileImageDataUrl}
fill={true}
alt={cv.fullName}
priority={true}
Expand Down
3 changes: 2 additions & 1 deletion src/payload/collections/Media/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { isLoggedInAccess } from '@/payload/access/is-logged-in-access';
import { assignOrgToUpload } from '@/payload/collections/hooks/assignOrgToUpload';
import { adminSettingsField } from '@/payload/fields/admin-settings';
import { defaultCollectionAccess } from '@/payload/access/default-collection-access';
import { PRINTER_HEADER_KEY } from '@/payload/utilities/constants';

export const Media: CollectionConfig = {
slug: 'media',
access: {
read: (args) => {
const printerSecret = args.req.headers.get('x-http-pdfprinter');
const printerSecret = args.req.headers.get(PRINTER_HEADER_KEY);
if (printerSecret === process.env.PRINTER_SECRET) {
return true;
}
Expand Down
7 changes: 4 additions & 3 deletions src/payload/plugins/cv-pdf-generator/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CvPdfConfig } from '@/payload/plugins/cv-pdf-generator/types';
import { Chromiumly, UrlConverter } from 'chromiumly';
import * as process from 'node:process';
import { encodeToBase64 } from 'next/dist/build/webpack/loaders/utils';
import { PRINTER_HEADER_KEY } from '@/payload/utilities/constants';

type Props = {
id: string;
Expand Down Expand Up @@ -47,14 +48,14 @@ export const requestHandler = async (
};

const searchParamString = encodeToBase64(searchParams);
const extraHeaders: Record<string, string> = {};
extraHeaders[PRINTER_HEADER_KEY] = process.env.PRINTER_SECRET || '';

try {
const url = `${host}/cv/${id}?p=${searchParamString}`;
if (process.env.NODE_ENV !== 'production') console.log({ url });
return urlConverter.convert({
extraHttpHeaders: {
'x-http-pdfprinter': process.env.PRINTER_SECRET || '',
},
extraHttpHeaders: extraHeaders,
url,
waitDelay: '2s',
properties: {
Expand Down
2 changes: 2 additions & 0 deletions src/payload/utilities/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export const ROLE_SUPER_ADMIN = 'admin';
export const ROLE_USER = 'user';

export const PRINTER_HEADER_KEY = 'x-http-pdfprinter';
Loading

0 comments on commit a1f7e00

Please sign in to comment.