Merge pull request #375 from linkwarden/dev

Dev
This commit is contained in:
Daniel 2023-12-29 23:59:34 -05:00 committed by GitHub
commit e24ae15a73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 712 additions and 493 deletions

View File

@ -1,22 +1,22 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the // For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node // README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{ {
"name": "Node.js & TypeScript", "name": "Node.js & TypeScript",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye", "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",
// Features to add to the dev container. More info: https://containers.dev/features. // Features to add to the dev container. More info: https://containers.dev/features.
// "features": {}, // "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally. // Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [], // "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created. // Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install", // "postCreateCommand": "yarn install",
// Configure tool-specific properties. // Configure tool-specific properties.
// "customizations": {}, // "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
"remoteUser": "root" "remoteUser": "root"
} }

View File

@ -18,6 +18,7 @@ RE_ARCHIVE_LIMIT=
NEXT_PUBLIC_MAX_FILE_SIZE= NEXT_PUBLIC_MAX_FILE_SIZE=
MAX_LINKS_PER_USER= MAX_LINKS_PER_USER=
ARCHIVE_TAKE_COUNT= ARCHIVE_TAKE_COUNT=
BROWSER_TIMEOUT=
# AWS S3 Settings # AWS S3 Settings
SPACES_KEY= SPACES_KEY=

11
.prettierignore Normal file
View File

@ -0,0 +1,11 @@
node_modules
.next
public
*.lock
*.log
.github
data
pgdata

4
.prettierrc.json Normal file
View File

@ -0,0 +1,4 @@
{
"trailingComma": "es5",
"tabWidth": 2
}

View File

@ -22,9 +22,7 @@ export default function FilterSearchDropdown({
role="button" role="button"
className="btn btn-sm btn-square btn-ghost" className="btn btn-sm btn-square btn-ghost"
> >
<i <i className="bi-funnel text-neutral text-2xl"></i>
className="bi-funnel text-neutral text-2xl"
></i>
</div> </div>
<ul className="dropdown-content z-[30] menu shadow bg-base-200 border border-neutral-content rounded-box w-44 mt-1"> <ul className="dropdown-content z-[30] menu shadow bg-base-200 border border-neutral-content rounded-box w-44 mt-1">
<li> <li>

View File

@ -1,7 +1,9 @@
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global"; import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
import React from "react"; import React from "react";
export default function LinkDate({ link }: { export default function LinkDate({
link,
}: {
link: LinkIncludingShortenedCollectionAndTags; link: LinkIncludingShortenedCollectionAndTags;
}) { }) {
const formattedDate = new Date(link.createdAt as string).toLocaleString( const formattedDate = new Date(link.createdAt as string).toLocaleString(
@ -10,7 +12,7 @@ export default function LinkDate({ link }: {
year: "numeric", year: "numeric",
month: "short", month: "short",
day: "numeric", day: "numeric",
}, }
); );
return ( return (

View File

@ -49,7 +49,7 @@ export default function DeleteLinkModal({ onClose, activeLink }: Props) {
<p>Are you sure you want to delete this Link?</p> <p>Are you sure you want to delete this Link?</p>
<div role="alert" className="alert alert-warning"> <div role="alert" className="alert alert-warning">
<i className="bi-exclamation-triangle text-xl"/> <i className="bi-exclamation-triangle text-xl" />
<span> <span>
<b>Warning:</b> This action is irreversible! <b>Warning:</b> This action is irreversible!
</span> </span>
@ -64,7 +64,7 @@ export default function DeleteLinkModal({ onClose, activeLink }: Props) {
className={`ml-auto btn w-fit text-white flex items-center gap-2 duration-100 bg-red-500 hover:bg-red-400 hover:dark:bg-red-600 cursor-pointer`} className={`ml-auto btn w-fit text-white flex items-center gap-2 duration-100 bg-red-500 hover:bg-red-400 hover:dark:bg-red-600 cursor-pointer`}
onClick={deleteLink} onClick={deleteLink}
> >
<i className="bi-trash text-xl"/> <i className="bi-trash text-xl" />
Delete Delete
</button> </button>
</div> </div>

View File

@ -227,10 +227,10 @@ export default function EditCollectionSharingModal({
e.canCreate && e.canUpdate && e.canDelete e.canCreate && e.canUpdate && e.canDelete
? "Admin" ? "Admin"
: e.canCreate && !e.canUpdate && !e.canDelete : e.canCreate && !e.canUpdate && !e.canDelete
? "Contributor" ? "Contributor"
: !e.canCreate && !e.canUpdate && !e.canDelete : !e.canCreate && !e.canUpdate && !e.canDelete
? "Viewer" ? "Viewer"
: undefined; : undefined;
return ( return (
<> <>

View File

@ -86,7 +86,7 @@ export default function EditLinkModal({ onClose, activeLink }: Props) {
title={link.url} title={link.url}
target="_blank" target="_blank"
> >
<i className="bi-link-45deg text-xl"/> <i className="bi-link-45deg text-xl" />
<p>{shortendURL}</p> <p>{shortendURL}</p>
</Link> </Link>
) : undefined} ) : undefined}
@ -116,13 +116,13 @@ export default function EditLinkModal({ onClose, activeLink }: Props) {
defaultValue={ defaultValue={
link.collection.id link.collection.id
? { ? {
value: link.collection.id, value: link.collection.id,
label: link.collection.name, label: link.collection.name,
} }
: { : {
value: null as unknown as number, value: null as unknown as number,
label: "Unorganized", label: "Unorganized",
} }
} }
/> />
) : null} ) : null}

View File

@ -102,9 +102,9 @@ export default function PreservedFormatRow({
) : undefined} ) : undefined}
<Link <Link
href={`${isPublic ? "/public" : ""}/preserved/${ href={`${
link?.id isPublic ? "/public" : ""
}?format=${format}`} }/preserved/${link?.id}?format=${format}`}
target="_blank" target="_blank"
className="btn btn-sm btn-square" className="btn btn-sm btn-square"
> >

View File

@ -47,11 +47,11 @@ export default function SearchBar({ placeholder }: Props) {
"/public/collections/" + "/public/collections/" +
router.query.id + router.query.id +
"?q=" + "?q=" +
encodeURIComponent(searchQuery || ""), encodeURIComponent(searchQuery || "")
); );
} else { } else {
return router.push( return router.push(
"/search?q=" + encodeURIComponent(searchQuery), "/search?q=" + encodeURIComponent(searchQuery)
); );
} }
} }

View File

@ -8,7 +8,7 @@ import { SetStateAction, useEffect } from "react";
type Props< type Props<
T extends T extends
| CollectionIncludingMembersAndLinkCount | CollectionIncludingMembersAndLinkCount
| LinkIncludingShortenedCollectionAndTags | LinkIncludingShortenedCollectionAndTags,
> = { > = {
sortBy: Sort; sortBy: Sort;
@ -19,7 +19,7 @@ type Props<
export default function useSort< export default function useSort<
T extends T extends
| CollectionIncludingMembersAndLinkCount | CollectionIncludingMembersAndLinkCount
| LinkIncludingShortenedCollectionAndTags | LinkIncludingShortenedCollectionAndTags,
>({ sortBy, data, setData }: Props<T>) { >({ sortBy, data, setData }: Props<T>) {
useEffect(() => { useEffect(() => {
const dataArray = [...data]; const dataArray = [...data];

View File

@ -17,232 +17,260 @@ type LinksAndCollectionAndOwner = Link & {
}; };
}; };
const BROWSER_TIMEOUT = Number(process.env.BROWSER_TIMEOUT) || 5;
export default async function archiveHandler(link: LinksAndCollectionAndOwner) { export default async function archiveHandler(link: LinksAndCollectionAndOwner) {
const browser = await chromium.launch(); const browser = await chromium.launch({ headless: false });
const context = await browser.newContext(devices["Desktop Chrome"]); const context = await browser.newContext(devices["Desktop Chrome"]);
const page = await context.newPage(); const page = await context.newPage();
const timeoutPromise = new Promise((_, reject) => {
setTimeout(
() =>
reject(
new Error(
`Browser has been open for more than ${BROWSER_TIMEOUT} minutes.`
)
),
BROWSER_TIMEOUT * 60000
);
});
try { try {
const validatedUrl = link.url ? await validateUrlSize(link.url) : undefined; await Promise.race([
(async () => {
const validatedUrl = link.url
? await validateUrlSize(link.url)
: undefined;
if (validatedUrl === null) throw "File is too large to be stored."; if (validatedUrl === null) throw "File is too large to be stored.";
const contentType = validatedUrl?.get("content-type"); const contentType = validatedUrl?.get("content-type");
let linkType = "url"; let linkType = "url";
let imageExtension = "png"; let imageExtension = "png";
if (!link.url) linkType = link.type; if (!link.url) linkType = link.type;
else if (contentType === "application/pdf") linkType = "pdf"; else if (contentType === "application/pdf") linkType = "pdf";
else if (contentType?.startsWith("image")) { else if (contentType?.startsWith("image")) {
linkType = "image"; linkType = "image";
if (contentType === "image/jpeg") imageExtension = "jpeg"; if (contentType === "image/jpeg") imageExtension = "jpeg";
else if (contentType === "image/png") imageExtension = "png"; else if (contentType === "image/png") imageExtension = "png";
}
const user = link.collection?.owner;
// send to archive.org
if (user.archiveAsWaybackMachine && link.url) sendToWayback(link.url);
const targetLink = await prisma.link.update({
where: { id: link.id },
data: {
type: linkType,
image:
user.archiveAsScreenshot && !link.image?.startsWith("archive")
? "pending"
: undefined,
pdf:
user.archiveAsPDF && !link.pdf?.startsWith("archive")
? "pending"
: undefined,
readable: !link.readable?.startsWith("archive") ? "pending" : undefined,
preview: !link.readable?.startsWith("archive") ? "pending" : undefined,
lastPreserved: new Date().toISOString(),
},
});
if (linkType === "image" && !link.image?.startsWith("archive")) {
await imageHandler(link, imageExtension); // archive image (jpeg/png)
return;
} else if (linkType === "pdf" && !link.pdf?.startsWith("archive")) {
await pdfHandler(link); // archive pdf
return;
} else if (link.url) {
// archive url
await page.goto(link.url, { waitUntil: "domcontentloaded" });
const content = await page.content();
// TODO single file
// const session = await page.context().newCDPSession(page);
// const doc = await session.send("Page.captureSnapshot", {
// format: "mhtml",
// });
// const saveDocLocally = (doc: any) => {
// console.log(doc);
// return createFile({
// data: doc,
// filePath: `archives/${targetLink.collectionId}/${link.id}.mhtml`,
// });
// };
// saveDocLocally(doc.data);
// Readability
const window = new JSDOM("").window;
const purify = DOMPurify(window);
const cleanedUpContent = purify.sanitize(content);
const dom = new JSDOM(cleanedUpContent, { url: link.url || "" });
const article = new Readability(dom.window.document).parse();
const articleText = article?.textContent
.replace(/ +(?= )/g, "") // strip out multiple spaces
.replace(/(\r\n|\n|\r)/gm, " "); // strip out line breaks
if (
articleText &&
articleText !== "" &&
!link.readable?.startsWith("archive")
) {
await createFile({
data: JSON.stringify(article),
filePath: `archives/${targetLink.collectionId}/${link.id}_readability.json`,
});
await prisma.link.update({
where: { id: link.id },
data: {
readable: `archives/${targetLink.collectionId}/${link.id}_readability.json`,
textContent: articleText,
},
});
}
// Preview
const ogImageUrl = await page.evaluate(() => {
const metaTag = document.querySelector('meta[property="og:image"]');
return metaTag ? (metaTag as any).content : null;
});
createFolder({
filePath: `archives/preview/${link.collectionId}`,
});
if (ogImageUrl) {
console.log("Found og:image URL:", ogImageUrl);
// Download the image
const imageResponse = await page.goto(ogImageUrl);
// Check if imageResponse is not null
if (imageResponse && !link.preview?.startsWith("archive")) {
const buffer = await imageResponse.body();
// Check if buffer is not null
if (buffer) {
// Load the image using Jimp
Jimp.read(buffer, async (err, image) => {
if (image && !err) {
image?.resize(1280, Jimp.AUTO).quality(20);
const processedBuffer = await image?.getBufferAsync(
Jimp.MIME_JPEG
);
createFile({
data: processedBuffer,
filePath: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
}).then(() => {
return prisma.link.update({
where: { id: link.id },
data: {
preview: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
},
});
});
}
}).catch((err) => {
console.error("Error processing the image:", err);
});
} else {
console.log("No image data found.");
}
} }
await page.goBack(); const user = link.collection?.owner;
} else if (!link.preview?.startsWith("archive")) {
console.log("No og:image found"); // send to archive.org
await page if (user.archiveAsWaybackMachine && link.url) sendToWayback(link.url);
.screenshot({ type: "jpeg", quality: 20 })
.then((screenshot) => { const targetLink = await prisma.link.update({
return createFile({ where: { id: link.id },
data: screenshot, data: {
filePath: `archives/preview/${link.collectionId}/${link.id}.jpeg`, type: linkType,
image:
user.archiveAsScreenshot && !link.image?.startsWith("archive")
? "pending"
: undefined,
pdf:
user.archiveAsPDF && !link.pdf?.startsWith("archive")
? "pending"
: undefined,
readable: !link.readable?.startsWith("archive")
? "pending"
: undefined,
preview: !link.readable?.startsWith("archive")
? "pending"
: undefined,
lastPreserved: new Date().toISOString(),
},
});
if (linkType === "image" && !link.image?.startsWith("archive")) {
await imageHandler(link, imageExtension); // archive image (jpeg/png)
return;
} else if (linkType === "pdf" && !link.pdf?.startsWith("archive")) {
await pdfHandler(link); // archive pdf
return;
} else if (link.url) {
// archive url
await page.goto(link.url, { waitUntil: "domcontentloaded" });
const content = await page.content();
// TODO single file
// const session = await page.context().newCDPSession(page);
// const doc = await session.send("Page.captureSnapshot", {
// format: "mhtml",
// });
// const saveDocLocally = (doc: any) => {
// console.log(doc);
// return createFile({
// data: doc,
// filePath: `archives/${targetLink.collectionId}/${link.id}.mhtml`,
// });
// };
// saveDocLocally(doc.data);
// Readability
const window = new JSDOM("").window;
const purify = DOMPurify(window);
const cleanedUpContent = purify.sanitize(content);
const dom = new JSDOM(cleanedUpContent, { url: link.url || "" });
const article = new Readability(dom.window.document).parse();
const articleText = article?.textContent
.replace(/ +(?= )/g, "") // strip out multiple spaces
.replace(/(\r\n|\n|\r)/gm, " "); // strip out line breaks
if (
articleText &&
articleText !== "" &&
!link.readable?.startsWith("archive")
) {
await createFile({
data: JSON.stringify(article),
filePath: `archives/${targetLink.collectionId}/${link.id}_readability.json`,
}); });
})
.then(() => { await prisma.link.update({
return prisma.link.update({
where: { id: link.id }, where: { id: link.id },
data: { data: {
preview: `archives/preview/${link.collectionId}/${link.id}.jpeg`, readable: `archives/${targetLink.collectionId}/${link.id}_readability.json`,
textContent: articleText,
}, },
}); });
}
// Preview
const ogImageUrl = await page.evaluate(() => {
const metaTag = document.querySelector('meta[property="og:image"]');
return metaTag ? (metaTag as any).content : null;
}); });
}
// Screenshot/PDF createFolder({
await page.evaluate( filePath: `archives/preview/${link.collectionId}`,
autoScroll, });
Number(process.env.AUTOSCROLL_TIMEOUT) || 30
);
// Check if the user hasn't deleted the link by the time we're done scrolling if (ogImageUrl) {
const linkExists = await prisma.link.findUnique({ console.log("Found og:image URL:", ogImageUrl);
where: { id: link.id },
});
if (linkExists) {
const processingPromises = [];
if (user.archiveAsScreenshot && !link.image?.startsWith("archive")) { // Download the image
processingPromises.push( const imageResponse = await page.goto(ogImageUrl);
page.screenshot({ fullPage: true }).then((screenshot) => {
return createFile({ // Check if imageResponse is not null
data: screenshot, if (imageResponse && !link.preview?.startsWith("archive")) {
filePath: `archives/${linkExists.collectionId}/${link.id}.png`, const buffer = await imageResponse.body();
});
}) // Check if buffer is not null
); if (buffer) {
} // Load the image using Jimp
if (user.archiveAsPDF && !link.pdf?.startsWith("archive")) { Jimp.read(buffer, async (err, image) => {
processingPromises.push( if (image && !err) {
page image?.resize(1280, Jimp.AUTO).quality(20);
.pdf({ const processedBuffer = await image?.getBufferAsync(
width: "1366px", Jimp.MIME_JPEG
height: "1931px", );
printBackground: true,
margin: { top: "15px", bottom: "15px" }, createFile({
}) data: processedBuffer,
.then((pdf) => { filePath: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
}).then(() => {
return prisma.link.update({
where: { id: link.id },
data: {
preview: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
},
});
});
}
}).catch((err) => {
console.error("Error processing the image:", err);
});
} else {
console.log("No image data found.");
}
}
await page.goBack();
} else if (!link.preview?.startsWith("archive")) {
console.log("No og:image found");
await page
.screenshot({ type: "jpeg", quality: 20 })
.then((screenshot) => {
return createFile({ return createFile({
data: pdf, data: screenshot,
filePath: `archives/${linkExists.collectionId}/${link.id}.pdf`, filePath: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
}); });
}) })
.then(() => {
return prisma.link.update({
where: { id: link.id },
data: {
preview: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
},
});
});
}
// Screenshot/PDF
await page.evaluate(
autoScroll,
Number(process.env.AUTOSCROLL_TIMEOUT) || 30
); );
// Check if the user hasn't deleted the link by the time we're done scrolling
const linkExists = await prisma.link.findUnique({
where: { id: link.id },
});
if (linkExists) {
const processingPromises = [];
if (
user.archiveAsScreenshot &&
!link.image?.startsWith("archive")
) {
processingPromises.push(
page.screenshot({ fullPage: true }).then((screenshot) => {
return createFile({
data: screenshot,
filePath: `archives/${linkExists.collectionId}/${link.id}.png`,
});
})
);
}
if (user.archiveAsPDF && !link.pdf?.startsWith("archive")) {
processingPromises.push(
page
.pdf({
width: "1366px",
height: "1931px",
printBackground: true,
margin: { top: "15px", bottom: "15px" },
})
.then((pdf) => {
return createFile({
data: pdf,
filePath: `archives/${linkExists.collectionId}/${link.id}.pdf`,
});
})
);
}
await Promise.allSettled(processingPromises);
await prisma.link.update({
where: { id: link.id },
data: {
image: user.archiveAsScreenshot
? `archives/${linkExists.collectionId}/${link.id}.png`
: undefined,
pdf: user.archiveAsPDF
? `archives/${linkExists.collectionId}/${link.id}.pdf`
: undefined,
},
});
}
} }
await Promise.allSettled(processingPromises); })(),
await prisma.link.update({ timeoutPromise,
where: { id: link.id }, ]);
data: {
image: user.archiveAsScreenshot
? `archives/${linkExists.collectionId}/${link.id}.png`
: undefined,
pdf: user.archiveAsPDF
? `archives/${linkExists.collectionId}/${link.id}.pdf`
: undefined,
},
});
}
}
} catch (err) { } catch (err) {
console.log(err); console.log(err);
console.log("Failed Link details:", link); console.log("Failed Link details:", link);

View File

@ -62,8 +62,8 @@ export default async function postLink(
link.description && link.description !== "" link.description && link.description !== ""
? link.description ? link.description
: link.url : link.url
? await getTitle(link.url) ? await getTitle(link.url)
: undefined; : undefined;
const validatedUrl = link.url ? await validateUrlSize(link.url) : undefined; const validatedUrl = link.url ? await validateUrlSize(link.url) : undefined;

View File

@ -40,7 +40,10 @@ async function emptyS3Directory(bucket: string, dir: string) {
export default async function removeFolder({ filePath }: { filePath: string }) { export default async function removeFolder({ filePath }: { filePath: string }) {
if (s3Client) { if (s3Client) {
try { try {
await emptyS3Directory(process.env.SPACES_BUCKET_NAME as string, filePath); await emptyS3Directory(
process.env.SPACES_BUCKET_NAME as string,
filePath
);
} catch (err) { } catch (err) {
console.log("Error", err); console.log("Error", err);
} }

View File

@ -42,7 +42,8 @@ export default async function verifyUser({
return null; return null;
} }
if (!user.username && !ssoUser) { // SSO users don't need a username if (!user.username && !ssoUser) {
// SSO users don't need a username
res.status(401).json({ res.status(401).json({
response: "Username not found.", response: "Username not found.",
}); });

View File

@ -15,7 +15,8 @@
"worker:prod": "ts-node --transpile-only --skip-project scripts/worker.ts", "worker:prod": "ts-node --transpile-only --skip-project scripts/worker.ts",
"start": "concurrently \"next start\" \"yarn worker:prod\"", "start": "concurrently \"next start\" \"yarn worker:prod\"",
"build": "next build", "build": "next build",
"lint": "next lint" "lint": "next lint",
"format": "prettier --write \"**/*.{ts,tsx,js,json,md}\""
}, },
"dependencies": { "dependencies": {
"@auth/prisma-adapter": "^1.0.1", "@auth/prisma-adapter": "^1.0.1",
@ -69,6 +70,7 @@
"daisyui": "^4.4.2", "daisyui": "^4.4.2",
"nodemon": "^3.0.2", "nodemon": "^3.0.2",
"postcss": "^8.4.26", "postcss": "^8.4.26",
"prettier": "3.1.1",
"prisma": "^5.1.0", "prisma": "^5.1.0",
"tailwindcss": "^3.3.3", "tailwindcss": "^3.3.3",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",

View File

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import "@/styles/globals.css"; import "@/styles/globals.css";
import 'bootstrap-icons/font/bootstrap-icons.css'; import "bootstrap-icons/font/bootstrap-icons.css";
import { SessionProvider } from "next-auth/react"; import { SessionProvider } from "next-auth/react";
import type { AppProps } from "next/app"; import type { AppProps } from "next/app";
import Head from "next/head"; import Head from "next/head";

View File

@ -1,238 +1,408 @@
import type { NextApiRequest, NextApiResponse } from 'next'; import type { NextApiRequest, NextApiResponse } from "next";
import * as process from "process"; import * as process from "process";
export type ResponseData = { export type ResponseData = {
credentialsEnabled: string|undefined credentialsEnabled: string | undefined;
emailEnabled: string|undefined emailEnabled: string | undefined;
registrationDisabled: string|undefined registrationDisabled: string | undefined;
buttonAuths: { buttonAuths: {
method: string method: string;
name: string name: string;
}[] }[];
} };
export default function handler(req: NextApiRequest, res: NextApiResponse<ResponseData>) { export default function handler(
res.json(getLogins()); req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.json(getLogins());
} }
export function getLogins() { export function getLogins() {
const buttonAuths = [] const buttonAuths = [];
// 42 School // 42 School
if (process.env.NEXT_PUBLIC_FORTYTWO_ENABLED === 'true') { if (process.env.NEXT_PUBLIC_FORTYTWO_ENABLED === "true") {
buttonAuths.push({method: '42-school', name: process.env.FORTYTWO_CUSTOM_NAME ?? '42 School'}); buttonAuths.push({
} method: "42-school",
// Apple name: process.env.FORTYTWO_CUSTOM_NAME ?? "42 School",
if (process.env.NEXT_PUBLIC_APPLE_ENABLED === 'true') { });
buttonAuths.push({method: 'apple', name: process.env.APPLE_CUSTOM_NAME ?? 'Apple'}); }
} // Apple
// Atlassian if (process.env.NEXT_PUBLIC_APPLE_ENABLED === "true") {
if (process.env.NEXT_PUBLIC_ATLASSIAN_ENABLED === 'true') { buttonAuths.push({
buttonAuths.push({method: 'atlassian', name: process.env.ATLASSIAN_CUSTOM_NAME ?? 'Atlassian'}); method: "apple",
} name: process.env.APPLE_CUSTOM_NAME ?? "Apple",
// Auth0 });
if (process.env.NEXT_PUBLIC_AUTH0_ENABLED === 'true') { }
buttonAuths.push({method: 'auth0', name: process.env.AUTH0_CUSTOM_NAME ?? 'Auth0'}); // Atlassian
} if (process.env.NEXT_PUBLIC_ATLASSIAN_ENABLED === "true") {
// Authentik buttonAuths.push({
if (process.env.NEXT_PUBLIC_AUTHENTIK_ENABLED === 'true') { method: "atlassian",
buttonAuths.push({method: 'authentik', name: process.env.AUTHENTIK_CUSTOM_NAME ?? 'Authentik'}); name: process.env.ATLASSIAN_CUSTOM_NAME ?? "Atlassian",
} });
// Battle.net }
if (process.env.NEXT_PUBLIC_BATTLENET_ENABLED === 'true') { // Auth0
buttonAuths.push({method: 'battlenet', name: process.env.BATTLENET_CUSTOM_NAME ?? 'Battle.net'}); if (process.env.NEXT_PUBLIC_AUTH0_ENABLED === "true") {
} buttonAuths.push({
// Box method: "auth0",
if (process.env.NEXT_PUBLIC_BOX_ENABLED === 'true') { name: process.env.AUTH0_CUSTOM_NAME ?? "Auth0",
buttonAuths.push({method: 'box', name: process.env.BOX_CUSTOM_NAME ?? 'Box'}); });
} }
// Cognito // Authentik
if (process.env.NEXT_PUBLIC_COGNITO_ENABLED === 'true') { if (process.env.NEXT_PUBLIC_AUTHENTIK_ENABLED === "true") {
buttonAuths.push({method: 'cognito', name: process.env.COGNITO_CUSTOM_NAME ?? 'Cognito'}); buttonAuths.push({
} method: "authentik",
// Coinbase name: process.env.AUTHENTIK_CUSTOM_NAME ?? "Authentik",
if (process.env.NEXT_PUBLIC_COINBASE_ENABLED === 'true') { });
buttonAuths.push({method: 'coinbase', name: process.env.COINBASE_CUSTOM_NAME ?? 'Coinbase'}); }
} // Battle.net
// Discord if (process.env.NEXT_PUBLIC_BATTLENET_ENABLED === "true") {
if (process.env.NEXT_PUBLIC_DISCORD_ENABLED === 'true') { buttonAuths.push({
buttonAuths.push({method: 'discord', name: process.env.DISCORD_CUSTOM_NAME ?? 'Discord'}); method: "battlenet",
} name: process.env.BATTLENET_CUSTOM_NAME ?? "Battle.net",
// Dropbox });
if (process.env.NEXT_PUBLIC_DROPBOX_ENABLED === 'true') { }
buttonAuths.push({method: 'dropbox', name: process.env.DROPBOX_CUSTOM_NAME ?? 'Dropbox'}); // Box
} if (process.env.NEXT_PUBLIC_BOX_ENABLED === "true") {
// Duende IdentityServer6 buttonAuths.push({
if (process.env.NEXT_PUBLIC_DUENDE_IDS6_ENABLED === 'true') { method: "box",
buttonAuths.push({method: 'duende-identityserver6', name: process.env.DUENDE_IDS6_CUSTOM_NAME ?? 'DuendeIdentityServer6'}); name: process.env.BOX_CUSTOM_NAME ?? "Box",
} });
// EVE Online }
if (process.env.NEXT_PUBLIC_EVEONLINE_ENABLED === 'true') { // Cognito
buttonAuths.push({method: 'eveonline', name: process.env.EVEONLINE_CUSTOM_NAME ?? 'EVE Online'}); if (process.env.NEXT_PUBLIC_COGNITO_ENABLED === "true") {
} buttonAuths.push({
// Facebook method: "cognito",
if (process.env.NEXT_PUBLIC_FACEBOOK_ENABLED === 'true') { name: process.env.COGNITO_CUSTOM_NAME ?? "Cognito",
buttonAuths.push({method: 'facebook', name: process.env.FACEBOOK_CUSTOM_NAME ?? 'Facebook'}); });
} }
// FACEIT // Coinbase
if (process.env.NEXT_PUBLIC_FACEIT_ENABLED === 'true') { if (process.env.NEXT_PUBLIC_COINBASE_ENABLED === "true") {
buttonAuths.push({method: 'faceit', name: process.env.FACEIT_CUSTOM_NAME ?? 'FACEIT'}); buttonAuths.push({
} method: "coinbase",
// Foursquare name: process.env.COINBASE_CUSTOM_NAME ?? "Coinbase",
if (process.env.NEXT_PUBLIC_FOURSQUARE_ENABLED === 'true') { });
buttonAuths.push({method: 'foursquare', name: process.env.FOURSQUARE_CUSTOM_NAME ?? 'Foursquare'}); }
} // Discord
// Freshbooks if (process.env.NEXT_PUBLIC_DISCORD_ENABLED === "true") {
if (process.env.NEXT_PUBLIC_FRESHBOOKS_ENABLED === 'true') { buttonAuths.push({
buttonAuths.push({method: 'freshbooks', name: process.env.FRESHBOOKS_CUSTOM_NAME ?? 'Freshbooks'}); method: "discord",
} name: process.env.DISCORD_CUSTOM_NAME ?? "Discord",
// FusionAuth });
if (process.env.NEXT_PUBLIC_FUSIONAUTH_ENABLED === 'true') { }
buttonAuths.push({method: 'fusionauth', name: process.env.FUSIONAUTH_CUSTOM_NAME ?? 'FusionAuth'}); // Dropbox
} if (process.env.NEXT_PUBLIC_DROPBOX_ENABLED === "true") {
// GitHub buttonAuths.push({
if (process.env.NEXT_PUBLIC_GITHUB_ENABLED === 'true') { method: "dropbox",
buttonAuths.push({method: 'github', name: process.env.GITHUB_CUSTOM_NAME ?? 'GitHub'}); name: process.env.DROPBOX_CUSTOM_NAME ?? "Dropbox",
} });
// GitLab }
if (process.env.NEXT_PUBLIC_GITLAB_ENABLED === 'true') { // Duende IdentityServer6
buttonAuths.push({method: 'gitlab', name: process.env.GITLAB_CUSTOM_NAME ?? 'GitLab'}); if (process.env.NEXT_PUBLIC_DUENDE_IDS6_ENABLED === "true") {
} buttonAuths.push({
// Google method: "duende-identityserver6",
if (process.env.NEXT_PUBLIC_GOOGLE_ENABLED === 'true') { name: process.env.DUENDE_IDS6_CUSTOM_NAME ?? "DuendeIdentityServer6",
buttonAuths.push({method: 'google', name: process.env.GOOGLE_CUSTOM_NAME ?? 'Google'}); });
} }
// HubSpot // EVE Online
if (process.env.NEXT_PUBLIC_HUBSPOT_ENABLED === 'true') { if (process.env.NEXT_PUBLIC_EVEONLINE_ENABLED === "true") {
buttonAuths.push({method: 'hubspot', name: process.env.HUBSPOT_CUSTOM_NAME ?? 'HubSpot'}); buttonAuths.push({
} method: "eveonline",
// IdentityServer4 name: process.env.EVEONLINE_CUSTOM_NAME ?? "EVE Online",
if (process.env.NEXT_PUBLIC_IDS4_ENABLED === 'true') { });
buttonAuths.push({method: 'identity-server4', name: process.env.IDS4_CUSTOM_NAME ?? 'IdentityServer4'}); }
} // Facebook
// Kakao if (process.env.NEXT_PUBLIC_FACEBOOK_ENABLED === "true") {
if (process.env.NEXT_PUBLIC_KAKAO_ENABLED === 'true') { buttonAuths.push({
buttonAuths.push({method: 'kakao', name: process.env.KAKAO_CUSTOM_NAME ?? 'Kakao'}); method: "facebook",
} name: process.env.FACEBOOK_CUSTOM_NAME ?? "Facebook",
// Keycloak });
if (process.env.NEXT_PUBLIC_KEYCLOAK_ENABLED === 'true') { }
buttonAuths.push({method: 'keycloak', name: process.env.KEYCLOAK_CUSTOM_NAME ?? 'Keycloak'}); // FACEIT
} if (process.env.NEXT_PUBLIC_FACEIT_ENABLED === "true") {
// LINE buttonAuths.push({
if (process.env.NEXT_PUBLIC_LINE_ENABLED === 'true') { method: "faceit",
buttonAuths.push({method: 'line', name: process.env.LINE_CUSTOM_NAME ?? 'LINE'}); name: process.env.FACEIT_CUSTOM_NAME ?? "FACEIT",
} });
// LinkedIn }
if (process.env.NEXT_PUBLIC_LINKEDIN_ENABLED === 'true') { // Foursquare
buttonAuths.push({method: 'linkedin', name: process.env.LINKEDIN_CUSTOM_NAME ?? 'LinkedIn'}); if (process.env.NEXT_PUBLIC_FOURSQUARE_ENABLED === "true") {
} buttonAuths.push({
// MailChimp method: "foursquare",
if (process.env.NEXT_PUBLIC_MAILCHIMP_ENABLED === 'true') { name: process.env.FOURSQUARE_CUSTOM_NAME ?? "Foursquare",
buttonAuths.push({method: 'mailchimp', name: process.env.MAILCHIMP_CUSTOM_NAME ?? 'Mailchimp'}); });
} }
// Mail.ru // Freshbooks
if (process.env.NEXT_PUBLIC_MAILRU_ENABLED === 'true') { if (process.env.NEXT_PUBLIC_FRESHBOOKS_ENABLED === "true") {
buttonAuths.push({method: 'mailru', name: process.env.MAILRU_CUSTOM_NAME ?? 'Mail.ru'}); buttonAuths.push({
} method: "freshbooks",
// Naver name: process.env.FRESHBOOKS_CUSTOM_NAME ?? "Freshbooks",
if (process.env.NEXT_PUBLIC_NAVER_ENABLED === 'true') { });
buttonAuths.push({method: 'naver', name: process.env.NAVER_CUSTOM_NAME ?? 'Naver'}); }
} // FusionAuth
// Netlify if (process.env.NEXT_PUBLIC_FUSIONAUTH_ENABLED === "true") {
if (process.env.NEXT_PUBLIC_NETLIFY_ENABLED === 'true') { buttonAuths.push({
buttonAuths.push({method: 'netlify', name: process.env.NETLIFY_CUSTOM_NAME ?? 'Netlify'}); method: "fusionauth",
} name: process.env.FUSIONAUTH_CUSTOM_NAME ?? "FusionAuth",
// Okta });
if (process.env.NEXT_PUBLIC_OKTA_ENABLED === 'true') { }
buttonAuths.push({method: 'okta', name: process.env.OKTA_CUSTOM_NAME ?? 'Okta'}); // GitHub
} if (process.env.NEXT_PUBLIC_GITHUB_ENABLED === "true") {
// OneLogin buttonAuths.push({
if (process.env.NEXT_PUBLIC_ONELOGIN_ENABLED === 'true') { method: "github",
buttonAuths.push({method: 'onelogin', name: process.env.ONELOGIN_CUSTOM_NAME ?? 'OneLogin'}); name: process.env.GITHUB_CUSTOM_NAME ?? "GitHub",
} });
// Osso }
if (process.env.NEXT_PUBLIC_OSSO_ENABLED === 'true') { // GitLab
buttonAuths.push({method: 'osso', name: process.env.OSSO_CUSTOM_NAME ?? 'Osso'}); if (process.env.NEXT_PUBLIC_GITLAB_ENABLED === "true") {
} buttonAuths.push({
// osu! method: "gitlab",
if (process.env.NEXT_PUBLIC_OSU_ENABLED === 'true') { name: process.env.GITLAB_CUSTOM_NAME ?? "GitLab",
buttonAuths.push({method: 'osu', name: process.env.OSU_CUSTOM_NAME ?? 'Osu!'}); });
} }
// Patreon // Google
if (process.env.NEXT_PUBLIC_PATREON_ENABLED === 'true') { if (process.env.NEXT_PUBLIC_GOOGLE_ENABLED === "true") {
buttonAuths.push({method: 'patreon', name: process.env.PATREON_CUSTOM_NAME ?? 'Patreon'}); buttonAuths.push({
} method: "google",
// Pinterest name: process.env.GOOGLE_CUSTOM_NAME ?? "Google",
if (process.env.NEXT_PUBLIC_PINTEREST_ENABLED === 'true') { });
buttonAuths.push({method: 'pinterest', name: process.env.PINTEREST_CUSTOM_NAME ?? 'Pinterest'}); }
} // HubSpot
// Pipedrive if (process.env.NEXT_PUBLIC_HUBSPOT_ENABLED === "true") {
if (process.env.NEXT_PUBLIC_PIPEDRIVE_ENABLED === 'true') { buttonAuths.push({
buttonAuths.push({method: 'pipedrive', name: process.env.PIPEDRIVE_CUSTOM_NAME ?? 'Pipedrive'}); method: "hubspot",
} name: process.env.HUBSPOT_CUSTOM_NAME ?? "HubSpot",
// Reddit });
if (process.env.NEXT_PUBLIC_REDDIT_ENABLED === 'true') { }
buttonAuths.push({method: 'reddit', name: process.env.REDDIT_CUSTOM_NAME ?? 'Reddit'}); // IdentityServer4
} if (process.env.NEXT_PUBLIC_IDS4_ENABLED === "true") {
// Salesforce buttonAuths.push({
if (process.env.NEXT_PUBLIC_SALESFORCE_ENABLED === 'true') { method: "identity-server4",
buttonAuths.push({method: 'salesforce', name: process.env.SALESFORCE_CUSTOM_NAME ?? 'Salesforce'}); name: process.env.IDS4_CUSTOM_NAME ?? "IdentityServer4",
} });
// Slack }
if (process.env.NEXT_PUBLIC_SLACK_ENABLED === 'true') { // Kakao
buttonAuths.push({method: 'slack', name: process.env.SLACK_CUSTOM_NAME ?? 'Slack'}); if (process.env.NEXT_PUBLIC_KAKAO_ENABLED === "true") {
} buttonAuths.push({
// Spotify method: "kakao",
if (process.env.NEXT_PUBLIC_SPOTIFY_ENABLED === 'true') { name: process.env.KAKAO_CUSTOM_NAME ?? "Kakao",
buttonAuths.push({method: 'spotify', name: process.env.SPOTIFY_CUSTOM_NAME ?? 'Spotify'}); });
} }
// Strava // Keycloak
if (process.env.NEXT_PUBLIC_STRAVA_ENABLED === 'true') { if (process.env.NEXT_PUBLIC_KEYCLOAK_ENABLED === "true") {
buttonAuths.push({method: 'strava', name: process.env.STRAVA_CUSTOM_NAME ?? 'Strava'}); buttonAuths.push({
} method: "keycloak",
// Todoist name: process.env.KEYCLOAK_CUSTOM_NAME ?? "Keycloak",
if (process.env.NEXT_PUBLIC_TODOIST_ENABLED === 'true') { });
buttonAuths.push({method: 'todoist', name: process.env.TODOIST_CUSTOM_NAME ?? 'Todoist'}); }
} // LINE
// Twitch if (process.env.NEXT_PUBLIC_LINE_ENABLED === "true") {
if (process.env.NEXT_PUBLIC_TWITCH_ENABLED === 'true') { buttonAuths.push({
buttonAuths.push({method: 'twitch', name: process.env.TWITCH_CUSTOM_NAME ?? 'Twitch'}); method: "line",
} name: process.env.LINE_CUSTOM_NAME ?? "LINE",
// United Effects });
if (process.env.NEXT_PUBLIC_UNITED_EFFECTS_ENABLED === 'true') { }
buttonAuths.push({method: 'united-effects', name: process.env.UNITED_EFFECTS_CUSTOM_NAME ?? 'United Effects'}); // LinkedIn
} if (process.env.NEXT_PUBLIC_LINKEDIN_ENABLED === "true") {
// VK buttonAuths.push({
if (process.env.NEXT_PUBLIC_VK_ENABLED === 'true') { method: "linkedin",
buttonAuths.push({method: 'vk', name: process.env.VK_CUSTOM_NAME ?? 'VK'}); name: process.env.LINKEDIN_CUSTOM_NAME ?? "LinkedIn",
} });
// Wikimedia }
if (process.env.NEXT_PUBLIC_WIKIMEDIA_ENABLED === 'true') { // MailChimp
buttonAuths.push({method: 'wikimedia', name: process.env.WIKIMEDIA_CUSTOM_NAME ?? 'Wikimedia'}); if (process.env.NEXT_PUBLIC_MAILCHIMP_ENABLED === "true") {
} buttonAuths.push({
// Wordpress.com method: "mailchimp",
if (process.env.NEXT_PUBLIC_WORDPRESS_ENABLED === 'true') { name: process.env.MAILCHIMP_CUSTOM_NAME ?? "Mailchimp",
buttonAuths.push({method: 'wordpress', name: process.env.WORDPRESS_CUSTOM_NAME ?? 'WordPress.com'}); });
} }
// Yandex // Mail.ru
if (process.env.NEXT_PUBLIC_YANDEX_ENABLED === 'true') { if (process.env.NEXT_PUBLIC_MAILRU_ENABLED === "true") {
buttonAuths.push({method: 'yandex', name: process.env.YANDEX_CUSTOM_NAME ?? 'Yandex'}); buttonAuths.push({
} method: "mailru",
// Zitadel name: process.env.MAILRU_CUSTOM_NAME ?? "Mail.ru",
if (process.env.NEXT_PUBLIC_ZITADEL_ENABLED === 'true') { });
buttonAuths.push({method: 'zitadel', name: process.env.ZITADEL_CUSTOM_NAME ?? 'ZITADEL'}); }
} // Naver
// Zoho if (process.env.NEXT_PUBLIC_NAVER_ENABLED === "true") {
if (process.env.NEXT_PUBLIC_ZOHO_ENABLED === 'true') { buttonAuths.push({
buttonAuths.push({method: 'zoho', name: process.env.ZOHO_CUSTOM_NAME ?? 'Zoho'}); method: "naver",
} name: process.env.NAVER_CUSTOM_NAME ?? "Naver",
// Zoom });
if (process.env.NEXT_PUBLIC_ZOOM_ENABLED === 'true') { }
buttonAuths.push({method: 'zoom', name: process.env.ZOOM_CUSTOM_NAME ?? 'Zoom'}); // Netlify
} if (process.env.NEXT_PUBLIC_NETLIFY_ENABLED === "true") {
return { buttonAuths.push({
credentialsEnabled: (process.env.NEXT_PUBLIC_CREDENTIALS_ENABLED === 'true' || process.env.NEXT_PUBLIC_CREDENTIALS_ENABLED === undefined) ? "true" : "false", method: "netlify",
emailEnabled: (process.env.NEXT_PUBLIC_EMAIL_PROVIDER === 'true' ? 'true' : 'false'), name: process.env.NETLIFY_CUSTOM_NAME ?? "Netlify",
registrationDisabled: (process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === 'true' ? 'true' : 'false'), });
buttonAuths: buttonAuths }
}; // Okta
} if (process.env.NEXT_PUBLIC_OKTA_ENABLED === "true") {
buttonAuths.push({
method: "okta",
name: process.env.OKTA_CUSTOM_NAME ?? "Okta",
});
}
// OneLogin
if (process.env.NEXT_PUBLIC_ONELOGIN_ENABLED === "true") {
buttonAuths.push({
method: "onelogin",
name: process.env.ONELOGIN_CUSTOM_NAME ?? "OneLogin",
});
}
// Osso
if (process.env.NEXT_PUBLIC_OSSO_ENABLED === "true") {
buttonAuths.push({
method: "osso",
name: process.env.OSSO_CUSTOM_NAME ?? "Osso",
});
}
// osu!
if (process.env.NEXT_PUBLIC_OSU_ENABLED === "true") {
buttonAuths.push({
method: "osu",
name: process.env.OSU_CUSTOM_NAME ?? "Osu!",
});
}
// Patreon
if (process.env.NEXT_PUBLIC_PATREON_ENABLED === "true") {
buttonAuths.push({
method: "patreon",
name: process.env.PATREON_CUSTOM_NAME ?? "Patreon",
});
}
// Pinterest
if (process.env.NEXT_PUBLIC_PINTEREST_ENABLED === "true") {
buttonAuths.push({
method: "pinterest",
name: process.env.PINTEREST_CUSTOM_NAME ?? "Pinterest",
});
}
// Pipedrive
if (process.env.NEXT_PUBLIC_PIPEDRIVE_ENABLED === "true") {
buttonAuths.push({
method: "pipedrive",
name: process.env.PIPEDRIVE_CUSTOM_NAME ?? "Pipedrive",
});
}
// Reddit
if (process.env.NEXT_PUBLIC_REDDIT_ENABLED === "true") {
buttonAuths.push({
method: "reddit",
name: process.env.REDDIT_CUSTOM_NAME ?? "Reddit",
});
}
// Salesforce
if (process.env.NEXT_PUBLIC_SALESFORCE_ENABLED === "true") {
buttonAuths.push({
method: "salesforce",
name: process.env.SALESFORCE_CUSTOM_NAME ?? "Salesforce",
});
}
// Slack
if (process.env.NEXT_PUBLIC_SLACK_ENABLED === "true") {
buttonAuths.push({
method: "slack",
name: process.env.SLACK_CUSTOM_NAME ?? "Slack",
});
}
// Spotify
if (process.env.NEXT_PUBLIC_SPOTIFY_ENABLED === "true") {
buttonAuths.push({
method: "spotify",
name: process.env.SPOTIFY_CUSTOM_NAME ?? "Spotify",
});
}
// Strava
if (process.env.NEXT_PUBLIC_STRAVA_ENABLED === "true") {
buttonAuths.push({
method: "strava",
name: process.env.STRAVA_CUSTOM_NAME ?? "Strava",
});
}
// Todoist
if (process.env.NEXT_PUBLIC_TODOIST_ENABLED === "true") {
buttonAuths.push({
method: "todoist",
name: process.env.TODOIST_CUSTOM_NAME ?? "Todoist",
});
}
// Twitch
if (process.env.NEXT_PUBLIC_TWITCH_ENABLED === "true") {
buttonAuths.push({
method: "twitch",
name: process.env.TWITCH_CUSTOM_NAME ?? "Twitch",
});
}
// United Effects
if (process.env.NEXT_PUBLIC_UNITED_EFFECTS_ENABLED === "true") {
buttonAuths.push({
method: "united-effects",
name: process.env.UNITED_EFFECTS_CUSTOM_NAME ?? "United Effects",
});
}
// VK
if (process.env.NEXT_PUBLIC_VK_ENABLED === "true") {
buttonAuths.push({
method: "vk",
name: process.env.VK_CUSTOM_NAME ?? "VK",
});
}
// Wikimedia
if (process.env.NEXT_PUBLIC_WIKIMEDIA_ENABLED === "true") {
buttonAuths.push({
method: "wikimedia",
name: process.env.WIKIMEDIA_CUSTOM_NAME ?? "Wikimedia",
});
}
// Wordpress.com
if (process.env.NEXT_PUBLIC_WORDPRESS_ENABLED === "true") {
buttonAuths.push({
method: "wordpress",
name: process.env.WORDPRESS_CUSTOM_NAME ?? "WordPress.com",
});
}
// Yandex
if (process.env.NEXT_PUBLIC_YANDEX_ENABLED === "true") {
buttonAuths.push({
method: "yandex",
name: process.env.YANDEX_CUSTOM_NAME ?? "Yandex",
});
}
// Zitadel
if (process.env.NEXT_PUBLIC_ZITADEL_ENABLED === "true") {
buttonAuths.push({
method: "zitadel",
name: process.env.ZITADEL_CUSTOM_NAME ?? "ZITADEL",
});
}
// Zoho
if (process.env.NEXT_PUBLIC_ZOHO_ENABLED === "true") {
buttonAuths.push({
method: "zoho",
name: process.env.ZOHO_CUSTOM_NAME ?? "Zoho",
});
}
// Zoom
if (process.env.NEXT_PUBLIC_ZOOM_ENABLED === "true") {
buttonAuths.push({
method: "zoom",
name: process.env.ZOOM_CUSTOM_NAME ?? "Zoom",
});
}
return {
credentialsEnabled:
process.env.NEXT_PUBLIC_CREDENTIALS_ENABLED === "true" ||
process.env.NEXT_PUBLIC_CREDENTIALS_ENABLED === undefined
? "true"
: "false",
emailEnabled:
process.env.NEXT_PUBLIC_EMAIL_PROVIDER === "true" ? "true" : "false",
registrationDisabled:
process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === "true"
? "true"
: "false",
buttonAuths: buttonAuths,
};
}

View File

@ -57,9 +57,7 @@ export default function Delete() {
href="/settings/account" href="/settings/account"
className="absolute top-4 left-4 btn btn-ghost btn-square btn-sm" className="absolute top-4 left-4 btn btn-ghost btn-square btn-sm"
> >
<i <i className="bi-chevron-left text-neutral text-xl"></i>
className="bi-chevron-left text-neutral text-xl"
></i>
</Link> </Link>
<div className="flex items-center gap-2 w-full rounded-md h-8"> <div className="flex items-center gap-2 w-full rounded-md h-8">
<p className="text-red-500 dark:text-red-500 truncate w-full text-3xl text-center"> <p className="text-red-500 dark:text-red-500 truncate w-full text-3xl text-center">

View File

@ -1,4 +1,4 @@
import { defineConfig, devices } from '@playwright/test'; import { defineConfig, devices } from "@playwright/test";
/** /**
* Read environment variables from file. * Read environment variables from file.
@ -10,7 +10,7 @@ import { defineConfig, devices } from '@playwright/test';
* See https://playwright.dev/docs/test-configuration. * See https://playwright.dev/docs/test-configuration.
*/ */
export default defineConfig({ export default defineConfig({
testDir: './e2e', testDir: "./e2e",
/* Run tests in files in parallel */ /* Run tests in files in parallel */
fullyParallel: true, fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */ /* Fail the build on CI if you accidentally left test.only in the source code. */
@ -20,31 +20,31 @@ export default defineConfig({
/* Opt out of parallel tests on CI. */ /* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined, workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html', reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: { use: {
/* Base URL to use in actions like `await page.goto('/')`. */ /* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000', // baseURL: 'http://127.0.0.1:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry', trace: "on-first-retry",
}, },
/* Configure projects for major browsers */ /* Configure projects for major browsers */
projects: [ projects: [
{ {
name: 'chromium', name: "chromium",
use: { ...devices['Desktop Chrome'] }, use: { ...devices["Desktop Chrome"] },
}, },
{ {
name: 'firefox', name: "firefox",
use: { ...devices['Desktop Firefox'] }, use: { ...devices["Desktop Firefox"] },
}, },
{ {
name: 'webkit', name: "webkit",
use: { ...devices['Desktop Safari'] }, use: { ...devices["Desktop Safari"] },
}, },
/* Test against mobile viewports. */ /* Test against mobile viewports. */

View File

@ -3,4 +3,4 @@ module.exports = {
tailwindcss: {}, tailwindcss: {},
autoprefixer: {}, autoprefixer: {},
}, },
} };

View File

@ -1,9 +1,9 @@
import { create } from "zustand"; import { create } from "zustand";
import {ViewMode} from "@/types/global"; import { ViewMode } from "@/types/global";
type LocalSettings = { type LocalSettings = {
theme?: string; theme?: string;
viewMode?: string viewMode?: string;
}; };
type LocalSettingsStore = { type LocalSettingsStore = {

View File

@ -12,6 +12,7 @@ declare global {
NEXT_PUBLIC_MAX_FILE_SIZE?: string; NEXT_PUBLIC_MAX_FILE_SIZE?: string;
MAX_LINKS_PER_USER?: string; MAX_LINKS_PER_USER?: string;
ARCHIVE_TAKE_COUNT?: string; ARCHIVE_TAKE_COUNT?: string;
NEXT_PUBLIC_MAX_FILE_SIZE?: string;
SPACES_KEY?: string; SPACES_KEY?: string;
SPACES_SECRET?: string; SPACES_SECRET?: string;