mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-11 13:45:25 +03:00
implement logout and profile
This commit is contained in:
parent
35f02bd505
commit
19d1aa1f79
@ -10,10 +10,14 @@
|
|||||||
"features": {
|
"features": {
|
||||||
"ghcr.io/devcontainers/features/common-utils:1": {}
|
"ghcr.io/devcontainers/features/common-utils:1": {}
|
||||||
},
|
},
|
||||||
"forwardPorts": [5000, 5001, 5173, 8554, 8555],
|
"forwardPorts": [8080, 5000, 5001, 5173, 8554, 8555],
|
||||||
"portsAttributes": {
|
"portsAttributes": {
|
||||||
|
"8080": {
|
||||||
|
"label": "External NGINX",
|
||||||
|
"onAutoForward": "silent"
|
||||||
|
},
|
||||||
"5000": {
|
"5000": {
|
||||||
"label": "NGINX",
|
"label": "Internal NGINX",
|
||||||
"onAutoForward": "silent"
|
"onAutoForward": "silent"
|
||||||
},
|
},
|
||||||
"5001": {
|
"5001": {
|
||||||
|
|||||||
@ -252,6 +252,20 @@ def auth():
|
|||||||
return fail_response
|
return fail_response
|
||||||
|
|
||||||
|
|
||||||
|
@AuthBp.route("/profile")
|
||||||
|
def profile():
|
||||||
|
username = request.headers.get("remote-user", type=str)
|
||||||
|
return jsonify({"username": username})
|
||||||
|
|
||||||
|
|
||||||
|
@AuthBp.route("/logout", methods=["POST"])
|
||||||
|
def logout():
|
||||||
|
JWT_COOKIE_NAME = current_app.frigate_config.auth.cookie_name
|
||||||
|
response = make_response({}, 200)
|
||||||
|
response.delete_cookie(JWT_COOKIE_NAME)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
@AuthBp.route("/login", methods=["POST"])
|
@AuthBp.route("/login", methods=["POST"])
|
||||||
@limiter.limit(get_rate_limit, deduct_when=lambda response: response.status_code == 400)
|
@limiter.limit(get_rate_limit, deduct_when=lambda response: response.status_code == 400)
|
||||||
def login():
|
def login():
|
||||||
|
|||||||
@ -7,31 +7,89 @@ import { cn } from "@/lib/utils";
|
|||||||
import { TooltipPortal } from "@radix-ui/react-tooltip";
|
import { TooltipPortal } from "@radix-ui/react-tooltip";
|
||||||
import { isDesktop } from "react-device-detect";
|
import { isDesktop } from "react-device-detect";
|
||||||
import { VscAccount } from "react-icons/vsc";
|
import { VscAccount } from "react-icons/vsc";
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuLabel,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "../ui/dropdown-menu";
|
||||||
|
import { Drawer, DrawerContent, DrawerTrigger } from "../ui/drawer";
|
||||||
|
import { DialogClose } from "../ui/dialog";
|
||||||
|
import { LuLogOut } from "react-icons/lu";
|
||||||
|
import { useCallback } from "react";
|
||||||
|
import axios from "axios";
|
||||||
|
import useSWR from "swr";
|
||||||
|
|
||||||
type AccountSettingsProps = {
|
type AccountSettingsProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
export default function AccountSettings({ className }: AccountSettingsProps) {
|
export default function AccountSettings({ className }: AccountSettingsProps) {
|
||||||
|
const { data: profile } = useSWR("profile");
|
||||||
|
|
||||||
|
const handleLogout = useCallback(() => {
|
||||||
|
axios.post(`logout`).then((response) => {
|
||||||
|
if (response.status == 200) {
|
||||||
|
window.location.href = "/";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const Container = isDesktop ? DropdownMenu : Drawer;
|
||||||
|
const Trigger = isDesktop ? DropdownMenuTrigger : DrawerTrigger;
|
||||||
|
const Content = isDesktop ? DropdownMenuContent : DrawerContent;
|
||||||
|
const MenuItem = isDesktop ? DropdownMenuItem : DialogClose;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip>
|
<div className={className}>
|
||||||
<TooltipTrigger asChild>
|
<Container>
|
||||||
<div
|
<Trigger asChild>
|
||||||
className={cn(
|
<a href="#">
|
||||||
"flex flex-col items-center justify-center",
|
<Tooltip>
|
||||||
isDesktop
|
<TooltipTrigger asChild>
|
||||||
? "cursor-pointer rounded-lg bg-secondary text-secondary-foreground hover:bg-muted"
|
<div
|
||||||
: "text-secondary-foreground",
|
className={cn(
|
||||||
className,
|
"flex flex-col items-center justify-center",
|
||||||
)}
|
isDesktop
|
||||||
|
? "cursor-pointer rounded-lg bg-secondary text-secondary-foreground hover:bg-muted"
|
||||||
|
: "text-secondary-foreground",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<VscAccount className="size-5 md:m-[6px]" />
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPortal>
|
||||||
|
<TooltipContent side="right">
|
||||||
|
<p>Account</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPortal>
|
||||||
|
</Tooltip>
|
||||||
|
</a>
|
||||||
|
</Trigger>
|
||||||
|
<Content
|
||||||
|
className={
|
||||||
|
isDesktop ? "w-72 mr-5" : "max-h-[75dvh] p-2 overflow-hidden"
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<VscAccount className="size-5 md:m-[6px]" />
|
<div className="w-full flex-col overflow-y-auto overflow-x-hidden">
|
||||||
</div>
|
<DropdownMenuLabel>
|
||||||
</TooltipTrigger>
|
Current User: {profile?.username}
|
||||||
<TooltipPortal>
|
</DropdownMenuLabel>
|
||||||
<TooltipContent side="right">
|
<DropdownMenuSeparator className={isDesktop ? "mt-3" : "mt-1"} />
|
||||||
<p>Account</p>
|
<MenuItem
|
||||||
</TooltipContent>
|
className={
|
||||||
</TooltipPortal>
|
isDesktop ? "cursor-pointer" : "p-2 flex items-center text-sm"
|
||||||
</Tooltip>
|
}
|
||||||
|
onClick={() => handleLogout()}
|
||||||
|
>
|
||||||
|
<LuLogOut className="mr-2 size-4" />
|
||||||
|
<span>Logout</span>
|
||||||
|
</MenuItem>
|
||||||
|
</div>
|
||||||
|
</Content>
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,15 +34,13 @@ export default function Authentication() {
|
|||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status == 200) {
|
if (response.status == 200) {
|
||||||
// console.log("saved");
|
setShowSetPassword(false);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((_error) => {
|
||||||
if (error.response?.data?.message) {
|
toast.error("Error setting password", {
|
||||||
// console.log("error");
|
position: "top-center",
|
||||||
} else {
|
});
|
||||||
// console.log("error");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import { defineConfig } from "vite";
|
|||||||
import react from "@vitejs/plugin-react-swc";
|
import react from "@vitejs/plugin-react-swc";
|
||||||
import monacoEditorPlugin from "vite-plugin-monaco-editor";
|
import monacoEditorPlugin from "vite-plugin-monaco-editor";
|
||||||
|
|
||||||
|
const proxyHost = "localhost:5000";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
define: {
|
define: {
|
||||||
@ -12,24 +14,24 @@ export default defineConfig({
|
|||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
"/api": {
|
"/api": {
|
||||||
target: "http://localhost:5000",
|
target: `http://${proxyHost}`,
|
||||||
ws: true,
|
ws: true,
|
||||||
},
|
},
|
||||||
"/vod": {
|
"/vod": {
|
||||||
target: "http://localhost:5000",
|
target: `http://${proxyHost}`,
|
||||||
},
|
},
|
||||||
"/clips": {
|
"/clips": {
|
||||||
target: "http://localhost:5000",
|
target: `http://${proxyHost}`,
|
||||||
},
|
},
|
||||||
"/exports": {
|
"/exports": {
|
||||||
target: "http://localhost:5000",
|
target: `http://${proxyHost}`,
|
||||||
},
|
},
|
||||||
"/ws": {
|
"/ws": {
|
||||||
target: "ws://localhost:5000",
|
target: `ws://${proxyHost}`,
|
||||||
ws: true,
|
ws: true,
|
||||||
},
|
},
|
||||||
"/live": {
|
"/live": {
|
||||||
target: "ws://localhost:5000",
|
target: `ws://${proxyHost}`,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
ws: true,
|
ws: true,
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user