mirror of
https://github.com/gethomepage/homepage.git
synced 2026-10-02 17:01:15 -07:00
Merge branch 'dev' into feature/mcp
Docker CI / Docker Build & Push (push) Has been cancelled
Lint / Linting Checks (push) Has been cancelled
Tests / vitest (1) (push) Has been cancelled
Tests / vitest (2) (push) Has been cancelled
Tests / vitest (3) (push) Has been cancelled
Tests / vitest (4) (push) Has been cancelled
Docker CI / Docker Build & Push (push) Has been cancelled
Lint / Linting Checks (push) Has been cancelled
Tests / vitest (1) (push) Has been cancelled
Tests / vitest (2) (push) Has been cancelled
Tests / vitest (3) (push) Has been cancelled
Tests / vitest (4) (push) Has been cancelled
This commit is contained in:
@@ -66,7 +66,7 @@ For configuration options, examples and more, [please check out the homepage doc
|
|||||||
Please note that when using features such as widgets, Homepage can access personal information (for example from your home automation system). To keep your information private, if Homepage is reachable from any untrusted network, it:
|
Please note that when using features such as widgets, Homepage can access personal information (for example from your home automation system). To keep your information private, if Homepage is reachable from any untrusted network, it:
|
||||||
|
|
||||||
1. **must** sit behind a reverse proxy (and/or VPN) that enforces authentication, TLS, and strictly validates Host headers.
|
1. **must** sit behind a reverse proxy (and/or VPN) that enforces authentication, TLS, and strictly validates Host headers.
|
||||||
2. An optional built-in OIDC login flow is available (opt-in) offering a simple “authenticated or not” guard.
|
2. An optional built-in OIDC login flow or simple password login is available (opt-in) offering a simple “authenticated or not” guard.
|
||||||
|
|
||||||
## With Docker
|
## With Docker
|
||||||
|
|
||||||
|
|||||||
@@ -60,4 +60,6 @@ For OIDC login (overrides password login):
|
|||||||
- `HOMEPAGE_EXTERNAL_URL` (external URL to your Homepage instance; used for callbacks)
|
- `HOMEPAGE_EXTERNAL_URL` (external URL to your Homepage instance; used for callbacks)
|
||||||
- Optional: `HOMEPAGE_OIDC_NAME` (display name), `HOMEPAGE_OIDC_SCOPE` (defaults to `openid email profile`)
|
- Optional: `HOMEPAGE_OIDC_NAME` (display name), `HOMEPAGE_OIDC_SCOPE` (defaults to `openid email profile`)
|
||||||
|
|
||||||
All app pages and `/api` routes will require a signed-in session. Static assets remain public. Homepage still does not implement per-user dashboards or roles; authentication is a simple gate only.
|
All app pages and `/api` routes except `/api/healthcheck` will require a signed-in session. Static assets remain public.
|
||||||
|
|
||||||
|
Configure your OIDC provider with the a callback URI like `https://homepage.example.com/api/auth/callback/homepage-oidc`.
|
||||||
|
|||||||
@@ -16,3 +16,5 @@ widget:
|
|||||||
key: your-api-key
|
key: your-api-key
|
||||||
fields: ["running", "stopped", "total", "image_updates"] # optional
|
fields: ["running", "stopped", "total", "image_updates"] # optional
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Using an api key for the widget requires permissions for: `containers:list` `images:list and `image-updates:read`
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ export async function middleware(req) {
|
|||||||
return NextResponse.json({ error: "Host validation failed. See logs for more details." }, { status: 400 });
|
return NextResponse.json({ error: "Host validation failed. See logs for more details." }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authEnabled) {
|
if (authEnabled && !new URL(req.url).pathname.startsWith("/api/healthcheck")) {
|
||||||
if (new URL(req.url).pathname === "/api/mcp" && hasMcpToken(req)) {
|
if (new URL(req.url).pathname === "/api/mcp" && hasMcpToken(req)) {
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,18 @@ describe("middleware", () => {
|
|||||||
expect(res).toEqual({ type: "next" });
|
expect(res).toEqual({ type: "next" });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("allows healthcheck requests without auth when host is allowed", async () => {
|
||||||
|
process.env.HOMEPAGE_AUTH_ENABLED = "true";
|
||||||
|
process.env.HOMEPAGE_AUTH_SECRET = "secret";
|
||||||
|
|
||||||
|
const middleware = await loadMiddleware();
|
||||||
|
const res = await middleware(createReq("localhost:3000", "http://localhost:3000/api/healthcheck"));
|
||||||
|
|
||||||
|
expect(getToken).not.toHaveBeenCalled();
|
||||||
|
expect(NextResponse.next).toHaveBeenCalled();
|
||||||
|
expect(res).toEqual({ type: "next" });
|
||||||
|
});
|
||||||
|
|
||||||
it("redirects to signin when auth is enabled and no token is present", async () => {
|
it("redirects to signin when auth is enabled and no token is present", async () => {
|
||||||
process.env.HOMEPAGE_AUTH_ENABLED = "true";
|
process.env.HOMEPAGE_AUTH_ENABLED = "true";
|
||||||
process.env.HOMEPAGE_AUTH_SECRET = "secret";
|
process.env.HOMEPAGE_AUTH_SECRET = "secret";
|
||||||
|
|||||||
@@ -128,8 +128,6 @@ export default function SignIn({ providers, settings }) {
|
|||||||
backgroundBrightness && `backdrop-brightness-${settings.background.brightness}`,
|
backgroundBrightness && `backdrop-brightness-${settings.background.brightness}`,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="pointer-events-none absolute -left-24 -top-20 h-64 w-64 rounded-full bg-theme-500/20 blur-3xl" />
|
|
||||||
<div className="pointer-events-none absolute -bottom-24 right-0 h-72 w-72 rounded-full bg-theme-500/10 blur-3xl" />
|
|
||||||
<div className="grid gap-10 px-8 py-12 md:grid-cols-[1.2fr_1fr] md:px-12">
|
<div className="grid gap-10 px-8 py-12 md:grid-cols-[1.2fr_1fr] md:px-12">
|
||||||
<section className="flex flex-col justify-between">
|
<section className="flex flex-col justify-between">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user