Add Apprise alerting capabilities (backend)
- Add name + apprise_url columns to NotificationConfig model
- Add AdminNotificationConfig model for system-wide alert channels
- Create NotificationService with send_user_notification,
send_admin_notification, and test_notification helpers
- Replace stub notifications.py with full CRUD + /test endpoint
- Add admin notification config CRUD + /test to admin.py
- Update NotificationConfig schemas: name required, apprise_url
optional, config optional (default {})
- Add AdminNotificationConfig* schemas
- Integrate send_user_notification into process_mail_account task
for Gmail revocation, forwarding failures, and exceptions
- Update CHANGELOG.md
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
@@ -289,6 +289,11 @@ class NotificationConfig(Base):
|
||||
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
|
||||
name = Column(String(255), nullable=False, default="My Notification")
|
||||
apprise_url = Column(
|
||||
Text, nullable=True
|
||||
) # The Apprise URL e.g. tgram://token/chatid
|
||||
|
||||
# Channel details
|
||||
channel: Column[str] = Column(SQLEnum(NotificationChannel), nullable=False)
|
||||
is_enabled = Column(Boolean, default=True)
|
||||
@@ -590,3 +595,29 @@ class AppSetting(Base):
|
||||
onupdate=lambda: datetime.now(timezone.utc),
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
|
||||
class AdminNotificationConfig(Base):
|
||||
"""System-wide admin notification channels"""
|
||||
|
||||
__tablename__ = "admin_notification_configs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(255), nullable=False)
|
||||
apprise_url = Column(Text, nullable=False)
|
||||
is_enabled = Column(Boolean, default=True)
|
||||
notify_on_errors = Column(Boolean, default=True)
|
||||
notify_on_system_events = Column(Boolean, default=True)
|
||||
description = Column(Text, nullable=True)
|
||||
|
||||
created_at = Column(
|
||||
DateTime(timezone=True),
|
||||
default=lambda: datetime.now(timezone.utc),
|
||||
nullable=False,
|
||||
)
|
||||
updated_at = Column(
|
||||
DateTime(timezone=True),
|
||||
default=lambda: datetime.now(timezone.utc),
|
||||
onupdate=lambda: datetime.now(timezone.utc),
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
@@ -219,9 +219,13 @@ class ProcessingLogResponse(BaseModel):
|
||||
|
||||
# Notification Config Schemas
|
||||
class NotificationConfigBase(BaseModel):
|
||||
name: str = Field(
|
||||
..., max_length=255, description="Friendly name for this notification channel"
|
||||
)
|
||||
channel: NotificationChannel
|
||||
apprise_url: Optional[str] = Field(None, description="Apprise notification URL")
|
||||
is_enabled: bool = True
|
||||
config: Dict[str, Any]
|
||||
config: Dict[str, Any] = Field(default_factory=dict)
|
||||
notify_on_errors: bool = True
|
||||
notify_on_success: bool = False
|
||||
notify_threshold: int = Field(default=3, gt=0, le=100)
|
||||
@@ -232,6 +236,9 @@ class NotificationConfigCreate(NotificationConfigBase):
|
||||
|
||||
|
||||
class NotificationConfigUpdate(BaseModel):
|
||||
name: Optional[str] = Field(None, max_length=255)
|
||||
channel: Optional[NotificationChannel] = None
|
||||
apprise_url: Optional[str] = None
|
||||
is_enabled: Optional[bool] = None
|
||||
config: Optional[Dict[str, Any]] = None
|
||||
notify_on_errors: Optional[bool] = None
|
||||
@@ -248,6 +255,46 @@ class NotificationConfigResponse(NotificationConfigBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class NotificationTestRequest(BaseModel):
|
||||
apprise_url: str = Field(..., description="Apprise URL to test")
|
||||
|
||||
|
||||
class NotificationTestResponse(BaseModel):
|
||||
success: bool
|
||||
message: str
|
||||
|
||||
|
||||
# Admin Notification Config Schemas
|
||||
class AdminNotificationConfigBase(BaseModel):
|
||||
name: str = Field(..., max_length=255)
|
||||
apprise_url: str = Field(..., description="Apprise notification URL")
|
||||
is_enabled: bool = True
|
||||
notify_on_errors: bool = True
|
||||
notify_on_system_events: bool = True
|
||||
description: Optional[str] = None
|
||||
|
||||
|
||||
class AdminNotificationConfigCreate(AdminNotificationConfigBase):
|
||||
pass
|
||||
|
||||
|
||||
class AdminNotificationConfigUpdate(BaseModel):
|
||||
name: Optional[str] = Field(None, max_length=255)
|
||||
apprise_url: Optional[str] = None
|
||||
is_enabled: Optional[bool] = None
|
||||
notify_on_errors: Optional[bool] = None
|
||||
notify_on_system_events: Optional[bool] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
|
||||
class AdminNotificationConfigResponse(AdminNotificationConfigBase):
|
||||
id: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
# Subscription Schemas
|
||||
class SubscriptionPlanResponse(BaseModel):
|
||||
id: int
|
||||
|
||||
Reference in New Issue
Block a user