implement logout and profile

This commit is contained in:
Blake Blackshear 2024-05-15 07:33:29 -05:00
parent 35f02bd505
commit 19d1aa1f79
5 changed files with 110 additions and 34 deletions

View File

@ -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": {

View File

@ -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():

View File

@ -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>
); );
} }

View File

@ -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");
}
}); });
}, []); }, []);

View File

@ -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,
}, },