mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-13 06:35:24 +03:00
Implement VAPID key generation
This commit is contained in:
parent
d40f177b77
commit
afe2032085
@ -37,3 +37,5 @@ chromadb == 0.5.0
|
|||||||
google-generativeai == 0.6.*
|
google-generativeai == 0.6.*
|
||||||
ollama == 0.2.*
|
ollama == 0.2.*
|
||||||
openai == 1.30.*
|
openai == 1.30.*
|
||||||
|
# push notifications
|
||||||
|
py-vapid == 1.9.*
|
||||||
@ -1,14 +1,19 @@
|
|||||||
"""Notification apis."""
|
"""Notification apis."""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
from flask import (
|
from flask import (
|
||||||
Blueprint,
|
Blueprint,
|
||||||
|
current_app,
|
||||||
jsonify,
|
jsonify,
|
||||||
|
make_response,
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
from peewee import DoesNotExist
|
from peewee import DoesNotExist
|
||||||
|
from py_vapid import Vapid01
|
||||||
|
|
||||||
|
from frigate.const import CONFIG_DIR
|
||||||
from frigate.models import User
|
from frigate.models import User
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -16,6 +21,18 @@ logger = logging.getLogger(__name__)
|
|||||||
NotificationBp = Blueprint("notifications", __name__)
|
NotificationBp = Blueprint("notifications", __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@NotificationBp.route("/notifications/pubkey", methods=["GET"])
|
||||||
|
def get_vapid_pub_key():
|
||||||
|
if not current_app.frigate_config.notifications.enabled:
|
||||||
|
return make_response(
|
||||||
|
jsonify({"success": False, "message": "Notifications are not enabled."}),
|
||||||
|
400,
|
||||||
|
)
|
||||||
|
|
||||||
|
key = Vapid01.from_file(os.path.join(CONFIG_DIR, "notifications.pem"))
|
||||||
|
return jsonify(key.public_key), 200
|
||||||
|
|
||||||
|
|
||||||
@NotificationBp.route("/notifications/register", methods=["POST"])
|
@NotificationBp.route("/notifications/register", methods=["POST"])
|
||||||
def register_notifications():
|
def register_notifications():
|
||||||
username = request.headers.get("remote-user", type=str) or "admin"
|
username = request.headers.get("remote-user", type=str) or "admin"
|
||||||
@ -29,6 +46,10 @@ def register_notifications():
|
|||||||
User.update(notification_tokens=User.notification_tokens.append(token)).where(
|
User.update(notification_tokens=User.notification_tokens.append(token)).where(
|
||||||
User.username == username
|
User.username == username
|
||||||
).execute()
|
).execute()
|
||||||
return jsonify({"success": True, "message": "Successfully saved token."}), 200
|
return make_response(
|
||||||
|
jsonify({"success": True, "message": "Successfully saved token."}), 200
|
||||||
|
)
|
||||||
except DoesNotExist:
|
except DoesNotExist:
|
||||||
return jsonify({"success": False, "message": "Could not find user."}), 404
|
return make_response(
|
||||||
|
jsonify({"success": False, "message": "Could not find user."}), 404
|
||||||
|
)
|
||||||
|
|||||||
@ -2,10 +2,14 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
from py_vapid import Vapid01
|
||||||
|
|
||||||
from frigate.comms.dispatcher import Communicator
|
from frigate.comms.dispatcher import Communicator
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
|
from frigate.const import CONFIG_DIR
|
||||||
from frigate.models import User
|
from frigate.models import User
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -16,7 +20,9 @@ class WebPushClient(Communicator): # type: ignore[misc]
|
|||||||
|
|
||||||
def __init__(self, config: FrigateConfig) -> None:
|
def __init__(self, config: FrigateConfig) -> None:
|
||||||
self.config = config
|
self.config = config
|
||||||
# TODO check for VAPID key
|
|
||||||
|
# Pull keys from PEM or generate if they do not exist
|
||||||
|
self.key = Vapid01.from_file(os.path.join(CONFIG_DIR, "notifications.pem"))
|
||||||
|
|
||||||
self.tokens = []
|
self.tokens = []
|
||||||
self.invalid_tokens = []
|
self.invalid_tokens = []
|
||||||
|
|||||||
@ -5,11 +5,27 @@ import { Toaster } from "@/components/ui/sonner";
|
|||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import { FrigateConfig } from "@/types/frigateConfig";
|
import { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
const NOTIFICATION_SERVICE_WORKER = "notifications-worker.ts";
|
||||||
|
|
||||||
export default function NotificationView() {
|
export default function NotificationView() {
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
|
|
||||||
|
// notification state
|
||||||
|
|
||||||
|
const [notificationsSubscribed, setNotificationsSubscribed] =
|
||||||
|
useState<boolean>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
navigator.serviceWorker
|
||||||
|
.getRegistration(NOTIFICATION_SERVICE_WORKER)
|
||||||
|
.then((worker) => {
|
||||||
|
setNotificationsSubscribed(worker != null);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex size-full flex-col md:flex-row">
|
<div className="flex size-full flex-col md:flex-row">
|
||||||
@ -48,12 +64,13 @@ export default function NotificationView() {
|
|||||||
// TODO make the notifications button show enable / disable depending on current state
|
// TODO make the notifications button show enable / disable depending on current state
|
||||||
}
|
}
|
||||||
<Button
|
<Button
|
||||||
|
disabled={notificationsSubscribed == undefined}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
Notification.requestPermission().then((permission) => {
|
Notification.requestPermission().then((permission) => {
|
||||||
console.log("notification permissions are ", permission);
|
console.log("notification permissions are ", permission);
|
||||||
if (permission === "granted") {
|
if (permission === "granted") {
|
||||||
navigator.serviceWorker
|
navigator.serviceWorker
|
||||||
.register("notifications-worker.ts")
|
.register(NOTIFICATION_SERVICE_WORKER)
|
||||||
.then((registration) => {
|
.then((registration) => {
|
||||||
registration.pushManager
|
registration.pushManager
|
||||||
.subscribe()
|
.subscribe()
|
||||||
@ -68,7 +85,7 @@ export default function NotificationView() {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Enable Notifications
|
{`${notificationsSubscribed ? "Disable" : "Enable"} Notifications`}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user