forked from Github/frigate
Implement support for notifications (#12523)
* Setup basic notification page * Add basic notification implementation * Register for push notifications * Implement dispatching * Add fields * Handle image and link * Add notification config * Add field for users notification tokens * Implement saving of notification tokens * Implement VAPID key generation * Implement public key encoding * Implement webpush from server * Implement push notification handling * Make notifications config only * Add maskable icon * Use zod form to control notification settings in the UI * Use js * Always open notification * Support multiple endpoints * Handle cleaning up expired notification registrations * Correctly unsubscribe notifications * Change ttl dynamically * Add note about notification latency and features * Cleanup docs * Fix firefox pushes * Add links to docs and improve formatting * Improve wording * Fix docstring Co-authored-by: Blake Blackshear <blake@frigate.video> * Handle case where native auth is not enabled * Show errors in UI --------- Co-authored-by: Blake Blackshear <blake@frigate.video>
This commit is contained in:
@@ -19,6 +19,7 @@ from frigate.api.auth import AuthBp, get_jwt_secret, limiter
|
||||
from frigate.api.event import EventBp
|
||||
from frigate.api.export import ExportBp
|
||||
from frigate.api.media import MediaBp
|
||||
from frigate.api.notification import NotificationBp
|
||||
from frigate.api.preview import PreviewBp
|
||||
from frigate.api.review import ReviewBp
|
||||
from frigate.config import FrigateConfig
|
||||
@@ -48,6 +49,7 @@ bp.register_blueprint(MediaBp)
|
||||
bp.register_blueprint(PreviewBp)
|
||||
bp.register_blueprint(ReviewBp)
|
||||
bp.register_blueprint(AuthBp)
|
||||
bp.register_blueprint(NotificationBp)
|
||||
|
||||
|
||||
def create_app(
|
||||
|
||||
65
frigate/api/notification.py
Normal file
65
frigate/api/notification.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""Notification apis."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from flask import (
|
||||
Blueprint,
|
||||
current_app,
|
||||
jsonify,
|
||||
make_response,
|
||||
request,
|
||||
)
|
||||
from peewee import DoesNotExist
|
||||
from py_vapid import Vapid01, utils
|
||||
|
||||
from frigate.const import CONFIG_DIR
|
||||
from frigate.models import User
|
||||
|
||||
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"))
|
||||
raw_pub = key.public_key.public_bytes(
|
||||
serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint
|
||||
)
|
||||
return jsonify(utils.b64urlencode(raw_pub)), 200
|
||||
|
||||
|
||||
@NotificationBp.route("/notifications/register", methods=["POST"])
|
||||
def register_notifications():
|
||||
if current_app.frigate_config.auth.enabled:
|
||||
username = request.headers.get("remote-user", type=str) or "admin"
|
||||
else:
|
||||
username = "admin"
|
||||
|
||||
json: dict[str, any] = request.get_json(silent=True) or {}
|
||||
sub = json.get("sub")
|
||||
|
||||
if not sub:
|
||||
return jsonify(
|
||||
{"success": False, "message": "Subscription must be provided."}
|
||||
), 400
|
||||
|
||||
try:
|
||||
User.update(notification_tokens=User.notification_tokens.append(sub)).where(
|
||||
User.username == username
|
||||
).execute()
|
||||
return make_response(
|
||||
jsonify({"success": True, "message": "Successfully saved token."}), 200
|
||||
)
|
||||
except DoesNotExist:
|
||||
return make_response(
|
||||
jsonify({"success": False, "message": "Could not find user."}), 404
|
||||
)
|
||||
Reference in New Issue
Block a user