Files
oott/backend/src/model/notifications.rs
T
rzuastiandClaude Sonnet 4.6 44d593fccc Add OpenAPI documentation via Utoipa
Annotates all API handlers and model structs with Utoipa macros to generate
an OpenAPI 3.0 spec at runtime. Serves an interactive Swagger UI at /api/docs
and the raw JSON spec at /api/docs/openapi.json, both publicly accessible
outside the auth middleware.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:36:05 -04:00

111 lines
3.0 KiB
Rust

use crate::utils::date_serializer;
use chrono::{DateTime, Utc};
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};
use serde::{Deserialize, Serialize};
use std::{error::Error, fmt, str::FromStr};
use utoipa::ToSchema;
#[derive(Clone, Serialize, Deserialize, ToSchema)]
pub struct Notification {
pub id: i64,
#[serde(with = "date_serializer")]
#[schema(value_type = String, format = DateTime)]
pub created_on: DateTime<Utc>,
pub notification_type: NotificationType,
pub title: String,
pub body: String,
pub is_new: bool,
}
impl Notification {
pub fn new(
created_on: DateTime<Utc>,
notification_type: NotificationType,
title: String,
body: String,
is_new: bool,
) -> Self {
Self {
id: -1,
created_on: created_on,
notification_type: notification_type,
title: title,
body: body,
is_new: is_new,
}
}
}
impl fmt::Display for Notification {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"id={}, created_on={}, notification_type={}, is_new={}\ntitle={}\nbody={}",
self.id, self.created_on, self.notification_type, self.is_new, self.title, self.body
)
}
}
impl PartialEq for Notification {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
pub enum NotificationType {
NewDeviceFound,
DeviceOnlineAfterTime,
DeviceChanged,
Other,
}
impl fmt::Display for NotificationType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::NewDeviceFound => write!(f, "NewDeviceFound"),
Self::DeviceOnlineAfterTime => write!(f, "DeviceOnlineAfterTime"),
Self::DeviceChanged => write!(f, "DeviceChanged"),
Self::Other => write!(f, "Other"),
}
}
}
#[derive(Debug)]
pub struct NotificationTypeParseError;
impl fmt::Display for NotificationTypeParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Error parsing notification type")
}
}
impl Error for NotificationTypeParseError {}
impl FromStr for NotificationType {
type Err = NotificationTypeParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"NewDeviceFound" => Ok(NotificationType::NewDeviceFound),
"DeviceOnlineAfterTime" => Ok(NotificationType::DeviceOnlineAfterTime),
_ => Ok(NotificationType::Other),
}
}
}
impl ToSql for NotificationType {
fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
Ok(self.to_string().into())
}
}
impl FromSql for NotificationType {
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
value
.as_str()?
.parse()
.map_err(|e| FromSqlError::Other(Box::new(e)))
}
}