Add webonly build and push options to Makefile

Change container repo to private Gitea
Add webonly build Dockerfile
Add .node-version for fnm
Do not route settings, config, or logs to non admin users
Do not show settings, system logs, system restart or config editor links to non admin users
Add list of admin usernames to user.ts
This commit is contained in:
Chris King
2025-01-21 10:51:54 -08:00
parent f4f3cfa911
commit e36dc576d3
6 changed files with 116 additions and 55 deletions

View File

@@ -2,7 +2,8 @@ default_target: local
COMMIT_HASH := $(shell git log -1 --pretty=format:"%h"|tail -1)
VERSION = 0.14.1
IMAGE_REPO ?= ghcr.io/blakeblackshear/frigate
#IMAGE_REPO ?= ghcr.io/blakeblackshear/frigate
IMAGE_REPO ?= gitea.tremendousturtle.tools/chris/frigate
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
CURRENT_UID := $(shell id -u)
CURRENT_GID := $(shell id -g)
@@ -23,15 +24,24 @@ local: version
amd64:
docker buildx build --platform linux/amd64 --target=frigate --tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) --file docker/main/Dockerfile .
amd64_web:
docker buildx build --platform linux/amd64 --target=frigate --tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) --file docker/main/Dockerfile .
arm64:
docker buildx build --platform linux/arm64 --target=frigate --tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) --file docker/main/Dockerfile .
docker buildx build --platform linux/arm64 --target=frigate --tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) --file docker/webonly/Dockerfile .
build: version amd64 arm64
docker buildx build --platform linux/arm64/v8,linux/amd64 --target=frigate --tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) --file docker/main/Dockerfile .
build_web: version amd64 arm64
docker buildx build --platform linux/arm64/v8,linux/amd64 --target=frigate --tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) --file docker/webonly/Dockerfile .
push: push-boards
docker buildx build --push --platform linux/arm64/v8,linux/amd64 --target=frigate --tag $(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH) --file docker/main/Dockerfile .
push_web: push-boards
docker buildx build --push --platform linux/arm64/v8,linux/amd64 --target=frigate --tag $(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH) --file docker/webonly/Dockerfile .
run: local
docker run --rm --publish=5000:5000 --volume=${PWD}/config:/config frigate:latest

19
docker/webonly/Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
# syntax=docker/dockerfile:1.6
# Frigate web build
# This should be architecture agnostic, so speed up the build on multiarch by not using QEMU.
FROM --platform=$BUILDPLATFORM node:20 AS web-build
WORKDIR /work
COPY web/package.json web/package-lock.json ./
RUN npm install
COPY web/ ./
RUN npm run build \
&& mv dist/BASE_PATH/monacoeditorwork/* dist/assets/ \
&& rm -rf dist/BASE_PATH
FROM --platform=$BUILDPLATFORM ghcr.io/blakeblackshear/frigate:stable AS frigate
WORKDIR /opt/frigate/
RUN rm -rf web/ && mkdir web
COPY --from=web-build /work/dist/ web/

1
web/.node-version Normal file
View File

@@ -0,0 +1 @@
20

View File

@@ -10,6 +10,8 @@ import { Suspense, lazy } from "react";
import { Redirect } from "./components/navigation/Redirect";
import { cn } from "./lib/utils";
import { isPWA } from "./utils/isPWA";
import { ADMIN_USERS } from "@/types/user";
import useSWR from "swr";
const Live = lazy(() => import("@/pages/Live"));
const Events = lazy(() => import("@/pages/Events"));
@@ -22,6 +24,7 @@ const UIPlayground = lazy(() => import("@/pages/UIPlayground"));
const Logs = lazy(() => import("@/pages/Logs"));
function App() {
const { data: profile } = useSWR("profile");
return (
<Providers>
<BrowserRouter basename={window.baseUrl}>
@@ -47,9 +50,13 @@ function App() {
<Route path="/export" element={<Exports />} />
<Route path="/plus" element={<SubmitPlus />} />
<Route path="/system" element={<System />} />
<Route path="/settings" element={<Settings />} />
<Route path="/config" element={<ConfigEditor />} />
<Route path="/logs" element={<Logs />} />
{ADMIN_USERS.includes(profile?.username) && (
<>
<Route path="/settings" element={<Settings />} />
<Route path="/config" element={<ConfigEditor />} />
<Route path="/logs" element={<Logs />} />
</>
)}
<Route path="/playground" element={<UIPlayground />} />
<Route path="*" element={<Redirect to="/" />} />
</Routes>

View File

@@ -68,6 +68,8 @@ import {
import { TooltipPortal } from "@radix-ui/react-tooltip";
import { cn } from "@/lib/utils";
import { baseUrl } from "@/api/baseUrl";
import useSWR from "swr";
import { ADMIN_USERS } from "@/types/user";
type GeneralSettingsProps = {
className?: string;
@@ -80,6 +82,8 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) {
const { send: sendRestart } = useRestart();
const { data: profile } = useSWR("profile");
useEffect(() => {
let countdownInterval: NodeJS.Timeout;
@@ -169,48 +173,58 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) {
<span>System metrics</span>
</MenuItem>
</Link>
<Link to="/logs">
<MenuItem
className={
isDesktop
? "cursor-pointer"
: "flex w-full items-center p-2 text-sm"
}
>
<LuList className="mr-2 size-4" />
<span>System logs</span>
</MenuItem>
</Link>
{ADMIN_USERS.includes(profile?.username) && (
<Link to="/logs">
<MenuItem
className={
isDesktop
? "cursor-pointer"
: "flex w-full items-center p-2 text-sm"
}
>
<LuList className="mr-2 size-4" />
<span>System logs</span>
</MenuItem>
</Link>
)}
</DropdownMenuGroup>
<DropdownMenuLabel className={isDesktop ? "mt-3" : "mt-1"}>
Configuration
</DropdownMenuLabel>
<DropdownMenuSeparator />
{ADMIN_USERS.includes(profile?.username) && (
<>
<DropdownMenuLabel className={isDesktop ? "mt-3" : "mt-1"}>
Configuration
</DropdownMenuLabel>
<DropdownMenuSeparator />
</>
)}
<DropdownMenuGroup>
<Link to="/settings">
<MenuItem
className={
isDesktop
? "cursor-pointer"
: "flex w-full items-center p-2 text-sm"
}
>
<LuSettings className="mr-2 size-4" />
<span>Settings</span>
</MenuItem>
</Link>
<Link to="/config">
<MenuItem
className={
isDesktop
? "cursor-pointer"
: "flex w-full items-center p-2 text-sm"
}
>
<LuPenSquare className="mr-2 size-4" />
<span>Configuration editor</span>
</MenuItem>
</Link>
{ADMIN_USERS.includes(profile?.username) && (
<>
<Link to="/settings">
<MenuItem
className={
isDesktop
? "cursor-pointer"
: "flex w-full items-center p-2 text-sm"
}
>
<LuSettings className="mr-2 size-4" />
<span>Settings</span>
</MenuItem>
</Link>
<Link to="/config">
<MenuItem
className={
isDesktop
? "cursor-pointer"
: "flex w-full items-center p-2 text-sm"
}
>
<LuPenSquare className="mr-2 size-4" />
<span>Configuration editor</span>
</MenuItem>
</Link>
</>
)}
<DropdownMenuLabel className={isDesktop ? "mt-3" : "mt-1"}>
Appearance
</DropdownMenuLabel>
@@ -358,16 +372,24 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) {
<span>GitHub</span>
</MenuItem>
</a>
<DropdownMenuSeparator className={isDesktop ? "mt-3" : "mt-1"} />
<MenuItem
className={
isDesktop ? "cursor-pointer" : "flex items-center p-2 text-sm"
}
onClick={() => setRestartDialogOpen(true)}
>
<LuRotateCw className="mr-2 size-4" />
<span>Restart Frigate</span>
</MenuItem>
{ADMIN_USERS.includes(profile?.username) && (
<>
<DropdownMenuSeparator
className={isDesktop ? "mt-3" : "mt-1"}
/>
<MenuItem
className={
isDesktop
? "cursor-pointer"
: "flex items-center p-2 text-sm"
}
onClick={() => setRestartDialogOpen(true)}
>
<LuRotateCw className="mr-2 size-4" />
<span>Restart Frigate</span>
</MenuItem>
</>
)}
</div>
</Content>
</Container>

View File

@@ -1,3 +1,5 @@
export type User = {
username: string;
};
export const ADMIN_USERS: string[] = ["admin", "cking91977", "akadmin"];