Compare commits
1 Commits
v0.15.5
...
ldap-insec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ee05a9355 |
@@ -4,7 +4,8 @@ DATABASE_URL="file:./database/db.sqlite"
|
|||||||
# You can generate a new secret on the command line with:
|
# You can generate a new secret on the command line with:
|
||||||
# openssl rand -base64 32
|
# openssl rand -base64 32
|
||||||
# https://next-auth.js.org/configuration/options#secret
|
# https://next-auth.js.org/configuration/options#secret
|
||||||
AUTH_TRUST_HOST="true"
|
NEXTAUTH_URL="http://localhost:3000"
|
||||||
|
|
||||||
NEXTAUTH_SECRET="anything"
|
NEXTAUTH_SECRET="anything"
|
||||||
|
|
||||||
# Disable analytics
|
# Disable analytics
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ EXPOSE $PORT
|
|||||||
ENV PORT=${PORT}
|
ENV PORT=${PORT}
|
||||||
|
|
||||||
ENV DATABASE_URL "file:/data/db.sqlite"
|
ENV DATABASE_URL "file:/data/db.sqlite"
|
||||||
ENV AUTH_TRUST_HOST="true"
|
ENV NEXTAUTH_URL "http://localhost:7575"
|
||||||
ENV PORT 7575
|
ENV PORT 7575
|
||||||
ENV NEXTAUTH_SECRET NOT_IN_USE_BECAUSE_JWTS_ARE_UNUSED
|
ENV NEXTAUTH_SECRET NOT_IN_USE_BECAUSE_JWTS_ARE_UNUSED
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "homarr",
|
"name": "homarr",
|
||||||
"version": "0.15.5",
|
"version": "0.15.4",
|
||||||
"description": "Homarr - A homepage for your server.",
|
"description": "Homarr - A homepage for your server.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "NEXTAUTH_SECRET=WILL_BE_OVERWRITTEN next build",
|
"build": "NEXTAUTH_SECRET=WILL_BE_OVERWRITTEN next build",
|
||||||
"analyze": "ANALYZE=true next build",
|
"analyze": "ANALYZE=true next build",
|
||||||
"turbo": "DATABASE_URL=file:WILL_BE_OVERWRITTEN.sqlite turbo build",
|
"turbo": "DATABASE_URL=file:WILL_BE_OVERWRITTEN.sqlite NEXTAUTH_URL=http://WILL_BE_OVERWRITTEN turbo build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"export": "next build && next export",
|
"export": "next build && next export",
|
||||||
@@ -244,4 +244,4 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
},
|
},
|
||||||
"info": {
|
"info": {
|
||||||
"uptime": "Χρόνος Λειτουργίας",
|
"uptime": "Χρόνος Λειτουργίας",
|
||||||
"uptimeFormat": "{{days}} ημέρες, {{hours}} ώρες, {{minutes}} λεπτά",
|
"uptimeFormat": "",
|
||||||
"updates": "Διαθέσιμες ενημερώσεις",
|
"updates": "Διαθέσιμες ενημερώσεις",
|
||||||
"reboot": "Επανεκκίνηση"
|
"reboot": "Επανεκκίνηση"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"afterLoginRedirection": "Après la connexion, vous serez redirigé vers {{url}}",
|
"afterLoginRedirection": "Après la connexion, vous serez redirigé vers {{url}}",
|
||||||
"providersEmpty": {
|
"providersEmpty": {
|
||||||
"title": "Erreur du fournisseur d'authentification",
|
"title": "Erreur de fournisseur d'authentification",
|
||||||
"message": "Le(s) fournisseur(s) n'est (ne sont) pas défini(s), veuillez vérifier les journaux pour plus d'informations."
|
"message": "Le(s) fournisseur(s) n'est (ne sont) pas défini(s), veuillez vérifier les journaux pour plus d'informations."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"backToBoard": "Retour au tableau de bord",
|
"backToBoard": "Retour au tableau de bord",
|
||||||
"settings": {
|
"settings": {
|
||||||
"appearance": {
|
"appearance": {
|
||||||
"primaryColor": "Couleur principale",
|
"primaryColor": "Couleur primaire",
|
||||||
"secondaryColor": "Couleur secondaire"
|
"secondaryColor": "Couleur secondaire"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -108,11 +108,18 @@ const usePing = (app: AppType) => {
|
|||||||
configName: name ?? '',
|
configName: name ?? '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
retry: false,
|
retry: true,
|
||||||
enabled: isActive,
|
enabled: isActive,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
refetchInterval: 1000 * 60,
|
refetchInterval: 1000 * 60,
|
||||||
cacheTime: 1000 * 30,
|
retryDelay(failureCount, error) {
|
||||||
|
console.error(`Unable to retry app ping for app '${app.name}' (${app.id})`, error);
|
||||||
|
if (failureCount > 3) {
|
||||||
|
return 60 * 1000;
|
||||||
|
}
|
||||||
|
return 3 * 1000;
|
||||||
|
},
|
||||||
|
cacheTime: 1000 * 60,
|
||||||
retryOnMount: true,
|
retryOnMount: true,
|
||||||
select: (data) => {
|
select: (data) => {
|
||||||
const isOk = isStatusOk(app, data.status);
|
const isOk = isStatusOk(app, data.status);
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ export const AppTile = ({ className, app }: AppTileProps) => {
|
|||||||
<UnstyledButton
|
<UnstyledButton
|
||||||
style={{ pointerEvents: isEditMode ? 'none' : 'auto' }}
|
style={{ pointerEvents: isEditMode ? 'none' : 'auto' }}
|
||||||
component="a"
|
component="a"
|
||||||
rel="noreferrer"
|
|
||||||
href={href}
|
href={href}
|
||||||
target={app.behaviour.isOpeningNewTab ? '_blank' : '_self'}
|
target={app.behaviour.isOpeningNewTab ? '_blank' : '_self'}
|
||||||
className={`${classes.button} ${classes.base}`}
|
className={`${classes.button} ${classes.base}`}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { useTranslation } from 'next-i18next';
|
|||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { ReactNode, forwardRef, useMemo, useRef, useState } from 'react';
|
import { ReactNode, forwardRef, useMemo, useRef, useState } from 'react';
|
||||||
import { useConfigContext } from '~/config/provider';
|
import { useConfigContext } from '~/config/provider';
|
||||||
import { useGetExternalUrl } from '~/hooks/useExternalUrl';
|
|
||||||
import { api } from '~/utils/api';
|
import { api } from '~/utils/api';
|
||||||
|
|
||||||
import { MovieModal } from './Search/MovieModal';
|
import { MovieModal } from './Search/MovieModal';
|
||||||
@@ -142,7 +141,6 @@ const getItemComponent = (icon: SearchAutoCompleteItem['icon']) => {
|
|||||||
|
|
||||||
const useConfigApps = (search: string) => {
|
const useConfigApps = (search: string) => {
|
||||||
const { config } = useConfigContext();
|
const { config } = useConfigContext();
|
||||||
const getHref = useGetExternalUrl();
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
if (search.trim().length === 0) return [];
|
if (search.trim().length === 0) return [];
|
||||||
const apps = config?.apps.filter((app) =>
|
const apps = config?.apps.filter((app) =>
|
||||||
@@ -155,7 +153,7 @@ const useConfigApps = (search: string) => {
|
|||||||
value: app.name,
|
value: app.name,
|
||||||
sort: 'app',
|
sort: 'app',
|
||||||
metaData: {
|
metaData: {
|
||||||
url: getHref(app),
|
url: app.behaviour.externalUrl,
|
||||||
},
|
},
|
||||||
})) ?? []
|
})) ?? []
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -37,6 +37,13 @@ const env = createEnv({
|
|||||||
DATABASE_URL: z.string().url().default('file:../database/db.sqlite'),
|
DATABASE_URL: z.string().url().default('file:../database/db.sqlite'),
|
||||||
NEXTAUTH_SECRET:
|
NEXTAUTH_SECRET:
|
||||||
process.env.NODE_ENV === 'production' ? z.string().min(1) : z.string().min(1).optional(),
|
process.env.NODE_ENV === 'production' ? z.string().min(1) : z.string().min(1).optional(),
|
||||||
|
NEXTAUTH_URL: z.preprocess(
|
||||||
|
// This makes Vercel deployments not fail if you don't set NEXTAUTH_URL
|
||||||
|
// Since NextAuth.js automatically uses the VERCEL_URL if present.
|
||||||
|
(str) => process.env.VERCEL_URL ?? str,
|
||||||
|
// VERCEL_URL doesn't include `https` so it cant be validated as a URL
|
||||||
|
process.env.VERCEL ? z.string().min(1) : z.string().url()
|
||||||
|
),
|
||||||
DOCKER_HOST: z.string().optional(),
|
DOCKER_HOST: z.string().optional(),
|
||||||
DOCKER_PORT: portSchema,
|
DOCKER_PORT: portSchema,
|
||||||
DEMO_MODE: z.string().optional(),
|
DEMO_MODE: z.string().optional(),
|
||||||
@@ -129,6 +136,7 @@ const env = createEnv({
|
|||||||
runtimeEnv: {
|
runtimeEnv: {
|
||||||
DATABASE_URL: process.env.DATABASE_URL,
|
DATABASE_URL: process.env.DATABASE_URL,
|
||||||
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
|
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
|
||||||
|
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
|
||||||
NEXT_PUBLIC_DISABLE_ANALYTICS: process.env.DISABLE_ANALYTICS,
|
NEXT_PUBLIC_DISABLE_ANALYTICS: process.env.DISABLE_ANALYTICS,
|
||||||
DOCKER_HOST: process.env.DOCKER_HOST,
|
DOCKER_HOST: process.env.DOCKER_HOST,
|
||||||
DOCKER_PORT: process.env.DOCKER_PORT,
|
DOCKER_PORT: process.env.DOCKER_PORT,
|
||||||
|
|||||||
@@ -3,10 +3,6 @@ import * as tldts from 'tldts';
|
|||||||
import { AppType } from '~/types/app';
|
import { AppType } from '~/types/app';
|
||||||
|
|
||||||
export const useGetExternalUrl = () => {
|
export const useGetExternalUrl = () => {
|
||||||
if (typeof window === 'undefined') {
|
|
||||||
return (appType: AppType) => appType.behaviour.externalUrl || appType.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsedUrl = useMemo(() => {
|
const parsedUrl = useMemo(() => {
|
||||||
try {
|
try {
|
||||||
return tldts.parse(window.location.toString());
|
return tldts.parse(window.location.toString());
|
||||||
|
|||||||
@@ -106,17 +106,6 @@ export const constructAuthOptions = async (
|
|||||||
},
|
},
|
||||||
adapter: adapter as Adapter,
|
adapter: adapter as Adapter,
|
||||||
providers: [...(await getProviders(req.headers)), EmptyNextAuthProvider()],
|
providers: [...(await getProviders(req.headers)), EmptyNextAuthProvider()],
|
||||||
cookies: {
|
|
||||||
sessionToken: {
|
|
||||||
name: 'next-auth.session-token',
|
|
||||||
options: {
|
|
||||||
httpOnly: true,
|
|
||||||
sameSite: 'lax',
|
|
||||||
path: '/',
|
|
||||||
secure: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
jwt: {
|
jwt: {
|
||||||
async encode(params) {
|
async encode(params) {
|
||||||
if (!isCredentialsRequest(req)) {
|
if (!isCredentialsRequest(req)) {
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ const ldapLogin = (username: string, password: string) =>
|
|||||||
const client = ldap.createClient({
|
const client = ldap.createClient({
|
||||||
url: env.AUTH_LDAP_URI,
|
url: env.AUTH_LDAP_URI,
|
||||||
});
|
});
|
||||||
client.bind(username, password, (error, res) => {
|
client.bind(username, password, (error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject('Invalid username or password');
|
reject(`Invalid username or password. ${error.code}-${error.name}:${error.message}`);
|
||||||
} else {
|
} else {
|
||||||
resolve(client);
|
resolve(client);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,20 +279,18 @@ function DnsHoleControlsWidgetTile({ widget }: DnsHoleControlsWidgetProps) {
|
|||||||
{t(dnsHole.status)}
|
{t(dnsHole.status)}
|
||||||
</Badge>
|
</Badge>
|
||||||
</UnstyledButton>
|
</UnstyledButton>
|
||||||
{enableControls && (
|
<ActionIcon
|
||||||
<ActionIcon
|
size={20}
|
||||||
size={20}
|
radius="xl"
|
||||||
radius="xl"
|
top="2.67px"
|
||||||
top="2.67px"
|
variant="default"
|
||||||
variant="default"
|
onClick={() => {
|
||||||
onClick={() => {
|
setAppId(app.id);
|
||||||
setAppId(app.id);
|
open();
|
||||||
open();
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<IconClockPause size={20} color="red" />
|
||||||
<IconClockPause size={20} color="red" />
|
</ActionIcon>
|
||||||
</ActionIcon>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
Reference in New Issue
Block a user