Merge pull request #2157 from ajnart/dev

* fix: app ping retry interval

* Bugfix for dynamic urls not properly replaces on Search (#2124)

* Bugfix for search items

* Fixing server side rendering issues

* Add rel="noreferrer" to link AppTile.tsx (#2126)

reference: 
Issue: https://github.com/ajnart/homarr/issues/1933
PR comment: https://github.com/ajnart/homarr/pull/2048#issuecomment-2113238216

* fix: Make timer button show only to admins (#2143)

* fix: wrong redirect url for oidc requests #1909 (#2149)

* fix: wrong redirect url for oidc requests #1909

* fix: login not working with https

* chore: New Crowdin updates (#2123)

* New translations health-monitoring.json (Greek)

* New translations login.json (French)

* New translations customize.json (French)

---------

Co-authored-by: Manuel <30572287+manuel-rw@users.noreply.github.com>
Co-authored-by: Jelte Lagendijk <j3lte@users.noreply.github.com>
Co-authored-by: Boyd <bebsworthy@gmail.com>
Co-authored-by: SeDemal <Tagaishi@hotmail.ch>
Co-authored-by: Thomas Camlong <thomas@ajnart.fr>
This commit is contained in:
Meier Lukas
2024-10-18 18:55:22 +02:00
committed by GitHub
13 changed files with 43 additions and 39 deletions

View File

@@ -4,8 +4,7 @@ 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
NEXTAUTH_URL="http://localhost:3000" AUTH_TRUST_HOST="true"
NEXTAUTH_SECRET="anything" NEXTAUTH_SECRET="anything"
# Disable analytics # Disable analytics

View File

@@ -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 NEXTAUTH_URL "http://localhost:7575" ENV AUTH_TRUST_HOST="true"
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

View File

@@ -1,6 +1,6 @@
{ {
"name": "homarr", "name": "homarr",
"version": "0.15.4", "version": "0.15.5",
"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 NEXTAUTH_URL=http://WILL_BE_OVERWRITTEN turbo build", "turbo": "DATABASE_URL=file:WILL_BE_OVERWRITTEN.sqlite 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 @@
] ]
} }
} }
} }

View File

@@ -86,7 +86,7 @@
}, },
"info": { "info": {
"uptime": "Χρόνος Λειτουργίας", "uptime": "Χρόνος Λειτουργίας",
"uptimeFormat": "", "uptimeFormat": "{{days}} ημέρες, {{hours}} ώρες, {{minutes}} λεπτά",
"updates": "Διαθέσιμες ενημερώσεις", "updates": "Διαθέσιμες ενημερώσεις",
"reboot": "Επανεκκίνηση" "reboot": "Επανεκκίνηση"
}, },

View File

@@ -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 de fournisseur d'authentification", "title": "Erreur du 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."
} }
}, },

View File

@@ -4,7 +4,7 @@
"backToBoard": "Retour au tableau de bord", "backToBoard": "Retour au tableau de bord",
"settings": { "settings": {
"appearance": { "appearance": {
"primaryColor": "Couleur primaire", "primaryColor": "Couleur principale",
"secondaryColor": "Couleur secondaire" "secondaryColor": "Couleur secondaire"
} }
}, },

View File

@@ -108,18 +108,11 @@ const usePing = (app: AppType) => {
configName: name ?? '', configName: name ?? '',
}, },
{ {
retry: true, retry: false,
enabled: isActive, enabled: isActive,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
refetchInterval: 1000 * 60, refetchInterval: 1000 * 60,
retryDelay(failureCount, error) { cacheTime: 1000 * 30,
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);

View File

@@ -89,6 +89,7 @@ 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}`}

View File

@@ -13,6 +13,7 @@ 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';
@@ -141,6 +142,7 @@ 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) =>
@@ -153,7 +155,7 @@ const useConfigApps = (search: string) => {
value: app.name, value: app.name,
sort: 'app', sort: 'app',
metaData: { metaData: {
url: app.behaviour.externalUrl, url: getHref(app),
}, },
})) ?? [] })) ?? []
); );

View File

@@ -37,13 +37,6 @@ 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(),
@@ -136,7 +129,6 @@ 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,

View File

@@ -3,6 +3,10 @@ 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());

View File

@@ -106,6 +106,17 @@ 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)) {

View File

@@ -279,18 +279,20 @@ function DnsHoleControlsWidgetTile({ widget }: DnsHoleControlsWidgetProps) {
{t(dnsHole.status)} {t(dnsHole.status)}
</Badge> </Badge>
</UnstyledButton> </UnstyledButton>
<ActionIcon {enableControls && (
size={20} <ActionIcon
radius="xl" size={20}
top="2.67px" radius="xl"
variant="default" top="2.67px"
onClick={() => { variant="default"
setAppId(app.id); onClick={() => {
open(); setAppId(app.id);
}} open();
> }}
<IconClockPause size={20} color="red" /> >
</ActionIcon> <IconClockPause size={20} color="red" />
</ActionIcon>
)}
</Flex> </Flex>
</Stack> </Stack>
</Group> </Group>