mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-12 22:25:24 +03:00
Implement VAPID key generation
This commit is contained in:
parent
d40f177b77
commit
afe2032085
@ -36,4 +36,6 @@ chromadb == 0.5.0
|
||||
# Generative AI
|
||||
google-generativeai == 0.6.*
|
||||
ollama == 0.2.*
|
||||
openai == 1.30.*
|
||||
openai == 1.30.*
|
||||
# push notifications
|
||||
py-vapid == 1.9.*
|
||||
@ -1,14 +1,19 @@
|
||||
"""Notification apis."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from flask import (
|
||||
Blueprint,
|
||||
current_app,
|
||||
jsonify,
|
||||
make_response,
|
||||
request,
|
||||
)
|
||||
from peewee import DoesNotExist
|
||||
from py_vapid import Vapid01
|
||||
|
||||
from frigate.const import CONFIG_DIR
|
||||
from frigate.models import User
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -16,6 +21,18 @@ logger = logging.getLogger(__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"])
|
||||
def register_notifications():
|
||||
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.username == username
|
||||
).execute()
|
||||
return jsonify({"success": True, "message": "Successfully saved token."}), 200
|
||||
return make_response(
|
||||
jsonify({"success": True, "message": "Successfully saved token."}), 200
|
||||
)
|
||||
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 logging
|
||||
import os
|
||||
from typing import Any, Callable
|
||||
|
||||
from py_vapid import Vapid01
|
||||
|
||||
from frigate.comms.dispatcher import Communicator
|
||||
from frigate.config import FrigateConfig
|
||||
from frigate.const import CONFIG_DIR
|
||||
from frigate.models import User
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -16,7 +20,9 @@ class WebPushClient(Communicator): # type: ignore[misc]
|
||||
|
||||
def __init__(self, config: FrigateConfig) -> None:
|
||||
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.invalid_tokens = []
|
||||
|
||||
@ -5,11 +5,27 @@ import { Toaster } from "@/components/ui/sonner";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import axios from "axios";
|
||||
import { useEffect, useState } from "react";
|
||||
import useSWR from "swr";
|
||||
|
||||
const NOTIFICATION_SERVICE_WORKER = "notifications-worker.ts";
|
||||
|
||||
export default function NotificationView() {
|
||||
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 (
|
||||
<>
|
||||
<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
|
||||
}
|
||||
<Button
|
||||
disabled={notificationsSubscribed == undefined}
|
||||
onClick={() => {
|
||||
Notification.requestPermission().then((permission) => {
|
||||
console.log("notification permissions are ", permission);
|
||||
if (permission === "granted") {
|
||||
navigator.serviceWorker
|
||||
.register("notifications-worker.ts")
|
||||
.register(NOTIFICATION_SERVICE_WORKER)
|
||||
.then((registration) => {
|
||||
registration.pushManager
|
||||
.subscribe()
|
||||
@ -68,7 +85,7 @@ export default function NotificationView() {
|
||||
});
|
||||
}}
|
||||
>
|
||||
Enable Notifications
|
||||
{`${notificationsSubscribed ? "Disable" : "Enable"} Notifications`}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user