-// There was a problem when trying to authenticate. Please contact us if this
-// error persists. Unique error code:{" "}
-// Configuration
-//
-// ),
-// }
-//
-// export default function AuthErrorPage() {
-// const search = useSearchParams()
-// const error = search.get("error") as Error
-//
-// return (
-//
- There was a problem when trying to authenticate. Please contact us if this
- error persists. Unique error code:{" "}
- Configuration
-
- ),
-}
-
-function AuthErrorPageContent() {
- const search = useSearchParams()
- const error = search.get("error") as Error
-
- return (
-
-
-
-
Not found
-
The content you are trying to view is not available.
-
-
Go home
-
+ return (
+
+
+
+
+ Not found
+
+
+ The content you are trying to view is not available.
+
- )
+
Go home
+
+
+ );
}
diff --git a/app/providers.tsx b/app/providers.tsx
index d4f513de..ce7f26a0 100644
--- a/app/providers.tsx
+++ b/app/providers.tsx
@@ -1,30 +1,28 @@
"use client";
-import {PropsWithChildren, Suspense} from "react";
-import {ThemeProvider} from "@/features/theme/theme-provider";
-
-import {Toaster} from "@/components/ui/sonner";
-import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
-import {ThemeMetaUpdaterRoot} from "@/features/browser/theme-meta-updater-root";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { type PropsWithChildren, Suspense } from "react";
+import { Toaster } from "@/components/ui/sonner";
+import { ErrorLayout } from "@/components/wrappers/common/error-layout";
+import { ThemeMetaUpdaterRoot } from "@/features/browser/theme-meta-updater-root";
+import { ThemeProvider } from "@/features/theme/theme-provider";
export type ProviderProps = PropsWithChildren<{}>;
const queryClient = new QueryClient();
export const Providers = (props: ProviderProps) => {
- return (
-
-
-
-
-
- {props.children}
-
-
-
- );
+ return (
+
+
+
+
+
+
+ {props.children}
+
+
+
+
+ );
};
diff --git a/src/env.mjs b/src/env.mjs
index 3c87ff86..65bf7e82 100644
--- a/src/env.mjs
+++ b/src/env.mjs
@@ -29,7 +29,6 @@ export const env = createEnv({
AUTH_GOOGLE_ID: z.string().optional(),
AUTH_GOOGLE_SECRET: z.string().optional(),
- AUTH_GOOGLE_METHOD: z.boolean().default(false),
AUTH_GITHUB_ID: z.string().optional(),
AUTH_GITHUB_SECRET: z.string().optional(),
@@ -69,7 +68,7 @@ export const env = createEnv({
AUTH_SYNC_OIDC_ROLES_ON_LOGIN: z.enum(["true", "false"]).default("true"),
AUTH_ROLE_MAP: z.string().optional(),
- AUTH_DEFAULT_ROLE: z.string().optional(),
+ AUTH_DEFAULT_ROLE: z.string().optional().default("pending"),
AUTH_ALLOW_LINKING: z.enum(["true", "false"]).default("false"),
AUTH_ALLOW_UNLINKING: z.enum(["true", "false"]).default("false"),
@@ -110,6 +109,12 @@ export const env = createEnv({
AUTH_OIDC_JWKS_ENDPOINT: process.env.AUTH_OIDC_JWKS_ENDPOINT,
AUTH_OIDC_PKCE: process.env.AUTH_OIDC_PKCE,
+ AUTH_GOOGLE_ID: process.env.AUTH_GOOGLE_ID,
+ AUTH_GOOGLE_SECRET: process.env.AUTH_GOOGLE_SECRET,
+
+ AUTH_GITHUB_ID: process.env.AUTH_GITHUB_ID,
+ AUTH_GITHUB_SECRET: process.env.AUTH_GITHUB_SECRET,
+
AUTH_SOCIAL_ID: process.env.AUTH_SOCIAL_ID,
AUTH_SOCIAL_TITLE: process.env.AUTH_SOCIAL_TITLE,
AUTH_SOCIAL_DESC: process.env.AUTH_SOCIAL_DESC,
diff --git a/src/lib/auth/auth.ts b/src/lib/auth/auth.ts
index f2379f3a..0e5759f2 100644
--- a/src/lib/auth/auth.ts
+++ b/src/lib/auth/auth.ts
@@ -45,7 +45,7 @@ const oidcProviders = getOidcProviders();
export const auth = betterAuth({
onAPIError: {
- errorURL: "/dashboard/home",
+ errorURL: "/error",
onError: (error, ctx) => {
//todo: capture errors in a monitoring service
},
diff --git a/src/lib/auth/oauth.ts b/src/lib/auth/oauth.ts
index dee4543a..fcd6a10b 100644
--- a/src/lib/auth/oauth.ts
+++ b/src/lib/auth/oauth.ts
@@ -56,6 +56,38 @@ function getProviderIcon(providerId: string, envIcon?: string): string {
export function getOAuthProviders(): OAuthProvider[] {
const providers: OAuthProvider[] = [];
+ if (env.AUTH_GOOGLE_ID && env.AUTH_GOOGLE_SECRET) {
+ providers.push({
+ id: "google",
+ title: "Google",
+ description: "Sign in with your Google account.",
+ icon: getProviderIcon("google"),
+ client: env.AUTH_GOOGLE_ID,
+ secret: env.AUTH_GOOGLE_SECRET,
+ allowedGroup: env.ALLOWED_GROUP,
+ roleMap: env.AUTH_ROLE_MAP ?? undefined,
+ defaultRole: env.AUTH_DEFAULT_ROLE ?? "pending",
+ allowLinking: env.AUTH_ALLOW_LINKING !== "false",
+ allowUnlinking: env.AUTH_ALLOW_UNLINKING !== "false",
+ });
+ }
+
+ if (env.AUTH_GITHUB_ID && env.AUTH_GITHUB_SECRET) {
+ providers.push({
+ id: "github",
+ title: "GitHub",
+ description: "Sign in with your GitHub account.",
+ icon: getProviderIcon("github"),
+ client: env.AUTH_GITHUB_ID,
+ secret: env.AUTH_GITHUB_SECRET,
+ allowedGroup: env.ALLOWED_GROUP,
+ roleMap: env.AUTH_ROLE_MAP,
+ defaultRole: env.AUTH_DEFAULT_ROLE,
+ allowLinking: env.AUTH_ALLOW_LINKING !== "false",
+ allowUnlinking: env.AUTH_ALLOW_UNLINKING !== "false",
+ });
+ }
+
if (env.AUTH_SOCIAL_CLIENT && env.AUTH_SOCIAL_ID) {
providers.push({
id: env.AUTH_SOCIAL_ID,
diff --git a/src/utils/init.ts b/src/utils/init.ts
index 75dbaf58..dc6d95b6 100644
--- a/src/utils/init.ts
+++ b/src/utils/init.ts
@@ -1,127 +1,138 @@
-import {env} from "@/env.mjs";
-import {db, makeMigration} from "@/db";
-import {eq} from "drizzle-orm";
+import { env } from "@/env.mjs";
+import { db, makeMigration } from "@/db";
+import { eq } from "drizzle-orm";
import * as drizzleDb from "@/db";
-import {cleaningJob, retentionJob} from "@/lib/tasks";
-import {generateRSAKeys, getOrCreateMasterKey} from "@/utils/rsa-keys";
-import {StorageProviderKind} from "@/features/storages/types";
-
+import { cleaningJob, retentionJob } from "@/lib/tasks";
+import { generateRSAKeys, getOrCreateMasterKey } from "@/utils/rsa-keys";
+import { StorageProviderKind } from "@/features/storages/types";
export async function init() {
- consoleAscii();
- console.log("====Init Functions====");
- await getOrCreateMasterKey();
- await generateRSAKeys();
- await makeMigration();
- await createDefaultOrganization();
- await createSettingsIfNotExist()
- console.log("====Initialization completed====");
- await setupCronJobs()
- await setupCleaningJobs()
+ consoleAscii();
+ console.log("====Init Functions====");
+ await getOrCreateMasterKey();
+ await generateRSAKeys();
+ await makeMigration();
+ await createDefaultOrganization();
+ await createSettingsIfNotExist();
+ console.log("====Initialization completed====");
+ await setupCronJobs();
+ await setupCleaningJobs();
+
+ if (
+ (env.AUTH_GOOGLE_ID && env.AUTH_GOOGLE_SECRET) ||
+ (env.AUTH_GITHUB_ID && env.AUTH_GITHUB_SECRET)
+ ) {
+ console.warn(
+ "[Deprecation Warning] You have set up OAuth credentials in your environment variables, but the format is now different. Please update your environment variables to use the new format. For example, if you were using AUTH_GOOGLE_ID and AUTH_GOOGLE_SECRET, you should now use AUTH_GOOGLE_CLIENT and AUTH_GOOGLE_SECRET. Please refer to the documentation for more details.",
+ );
+ }
}
async function setupCronJobs() {
- console.log("==== Setting up Cron Jobs ====");
- retentionJob.start();
- console.log("==== Cron job started ====");
+ console.log("==== Setting up Cron Jobs ====");
+ retentionJob.start();
+ console.log("==== Cron job started ====");
}
async function setupCleaningJobs() {
- console.log("==== Setting up Cleaning Jobs ====");
- cleaningJob.start();
- console.log("==== Cleaning job started ====");
+ console.log("==== Setting up Cleaning Jobs ====");
+ cleaningJob.start();
+ console.log("==== Cleaning job started ====");
}
async function createSettingsIfNotExist() {
- await db.transaction(async (tx) => {
- const systemSettingsValues = {
- name: "system",
- smtpPassword: env.SMTP_PASSWORD ?? null,
- smtpFrom: env.SMTP_FROM ?? null,
- smtpHost: env.SMTP_HOST ?? null,
- smtpPort: env.SMTP_PORT ?? null,
- smtpUser: env.SMTP_USER ?? null,
- smtpSecure: env.SMTP_SECURE ?? false,
- };
-
- const [systemSetting] = await tx
- .select()
- .from(drizzleDb.schemas.setting)
- .where(eq(drizzleDb.schemas.setting.name, "system"))
- .limit(1);
-
- const [finalSystemSetting] = systemSetting
- ? await tx
- .update(drizzleDb.schemas.setting)
- .set(systemSettingsValues)
- .where(eq(drizzleDb.schemas.setting.name, "system"))
- .returning()
- : await tx
- .insert(drizzleDb.schemas.setting)
- .values(systemSettingsValues)
- .returning();
-
-
- const localStorageValues = {
- provider: "local" as StorageProviderKind,
- enabled: true,
- name: "System",
- config: {},
- };
-
- const [existingLocalStorage] = await tx
- .select()
- .from(drizzleDb.schemas.storageChannel)
- .where(eq(drizzleDb.schemas.storageChannel.provider, "local"))
- .limit(1);
-
- const [localStorage] = existingLocalStorage
- ? await tx
- .update(drizzleDb.schemas.storageChannel)
- .set(localStorageValues)
- .where(eq(drizzleDb.schemas.storageChannel.provider, "local"))
- .returning()
- : await tx
- .insert(drizzleDb.schemas.storageChannel)
- .values(localStorageValues)
- .returning();
-
-
- if (!finalSystemSetting.defaultStorageChannelId) {
- await tx
- .update(drizzleDb.schemas.setting)
- .set({defaultStorageChannelId: localStorage.id})
- .where(eq(drizzleDb.schemas.setting.id, finalSystemSetting.id));
- }
- });
-}
-
-
-async function createDefaultOrganization() {
- const defaultOrganizationConf = {
- slug: "default",
- name: "Default Organization",
- createdAt: new Date(),
+ await db.transaction(async (tx) => {
+ const systemSettingsValues = {
+ name: "system",
+ smtpPassword: env.SMTP_PASSWORD ?? null,
+ smtpFrom: env.SMTP_FROM ?? null,
+ smtpHost: env.SMTP_HOST ?? null,
+ smtpPort: env.SMTP_PORT ?? null,
+ smtpUser: env.SMTP_USER ?? null,
+ smtpSecure: env.SMTP_SECURE ?? false,
};
- const [existing] = await db.select().from(drizzleDb.schemas.organization).where(eq(drizzleDb.schemas.organization.slug, "default")).limit(1);
+ const [systemSetting] = await tx
+ .select()
+ .from(drizzleDb.schemas.setting)
+ .where(eq(drizzleDb.schemas.setting.name, "system"))
+ .limit(1);
- if (!existing) {
- console.log("==== Creating default Organization... ====");
- await db.insert(drizzleDb.schemas.organization).values(defaultOrganizationConf);
+ const [finalSystemSetting] = systemSetting
+ ? await tx
+ .update(drizzleDb.schemas.setting)
+ .set(systemSettingsValues)
+ .where(eq(drizzleDb.schemas.setting.name, "system"))
+ .returning()
+ : await tx
+ .insert(drizzleDb.schemas.setting)
+ .values(systemSettingsValues)
+ .returning();
+
+ const localStorageValues = {
+ provider: "local" as StorageProviderKind,
+ enabled: true,
+ name: "System",
+ config: {},
+ };
+
+ const [existingLocalStorage] = await tx
+ .select()
+ .from(drizzleDb.schemas.storageChannel)
+ .where(eq(drizzleDb.schemas.storageChannel.provider, "local"))
+ .limit(1);
+
+ const [localStorage] = existingLocalStorage
+ ? await tx
+ .update(drizzleDb.schemas.storageChannel)
+ .set(localStorageValues)
+ .where(eq(drizzleDb.schemas.storageChannel.provider, "local"))
+ .returning()
+ : await tx
+ .insert(drizzleDb.schemas.storageChannel)
+ .values(localStorageValues)
+ .returning();
+
+ if (!finalSystemSetting.defaultStorageChannelId) {
+ await tx
+ .update(drizzleDb.schemas.setting)
+ .set({ defaultStorageChannelId: localStorage.id })
+ .where(eq(drizzleDb.schemas.setting.id, finalSystemSetting.id));
}
+ });
+}
+
+async function createDefaultOrganization() {
+ const defaultOrganizationConf = {
+ slug: "default",
+ name: "Default Organization",
+ createdAt: new Date(),
+ };
+
+ const [existing] = await db
+ .select()
+ .from(drizzleDb.schemas.organization)
+ .where(eq(drizzleDb.schemas.organization.slug, "default"))
+ .limit(1);
+
+ if (!existing) {
+ console.log("==== Creating default Organization... ====");
+ await db
+ .insert(drizzleDb.schemas.organization)
+ .values(defaultOrganizationConf);
+ }
}
function consoleAscii() {
- console.log(
- " \n" +
- " ____ __ __ \n" +
- " / __ \\____ _____/ /_____ _/ /_ ____ _________ \n" +
- " / /_/ / __ \\/ ___/ __/ __ / __ \\/ __ / ___/ _ \\ \n" +
- " / ____/ /_/ / / / /_/ /_/ / /_/ / /_/ (__ ) __/ \n" +
- " /_/ \\____/_/ \\__/\\__,_/_.___/\\__,_/____/\\___/ \n" +
- " \n" +
- ` Community Edition v${env.NEXT_PUBLIC_PROJECT_VERSION} \n ` +
- " \n"
- )
+ console.log(
+ " \n" +
+ " ____ __ __ \n" +
+ " / __ \\____ _____/ /_____ _/ /_ ____ _________ \n" +
+ " / /_/ / __ \\/ ___/ __/ __ / __ \\/ __ / ___/ _ \\ \n" +
+ " / ____/ /_/ / / / /_/ /_/ / /_/ / /_/ (__ ) __/ \n" +
+ " /_/ \\____/_/ \\__/\\__,_/_.___/\\__,_/____/\\___/ \n" +
+ " \n" +
+ ` Community Edition v${env.NEXT_PUBLIC_PROJECT_VERSION} \n ` +
+ " \n",
+ );
}