Fix rustfmt formatting in server and kiosk
Claude-Session: https://claude.ai/code/session_01RoC1ENJv254orkm7vZCQc3
This commit is contained in:
@@ -95,12 +95,12 @@ impl RoomHandle {
|
|||||||
|
|
||||||
fn handle_event(app: &AppHandle, generation: u64, event: RoomEvent) {
|
fn handle_event(app: &AppHandle, generation: u64, event: RoomEvent) {
|
||||||
match event {
|
match event {
|
||||||
RoomEvent::Connected { .. } => emit_status(app, generation, StatusPayload::new("connected")),
|
RoomEvent::Connected { .. } => {
|
||||||
|
emit_status(app, generation, StatusPayload::new("connected"))
|
||||||
RoomEvent::Reconnecting => {
|
|
||||||
emit_status(app, generation, StatusPayload::new("reconnecting"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RoomEvent::Reconnecting => emit_status(app, generation, StatusPayload::new("reconnecting")),
|
||||||
|
|
||||||
RoomEvent::Reconnected => emit_status(app, generation, StatusPayload::new("connected")),
|
RoomEvent::Reconnected => emit_status(app, generation, StatusPayload::new("connected")),
|
||||||
|
|
||||||
RoomEvent::Disconnected { reason } => {
|
RoomEvent::Disconnected { reason } => {
|
||||||
|
|||||||
@@ -29,13 +29,7 @@ pub const PRIORITY_SCREEN: u8 = 2;
|
|||||||
///
|
///
|
||||||
/// Frames are converted to BGRA, which on a little endian machine is the same layout as
|
/// Frames are converted to BGRA, which on a little endian machine is the same layout as
|
||||||
/// cairo's ARgb32, and handed to the native drawing surface sitting under the webview.
|
/// cairo's ARgb32, and handed to the native drawing surface sitting under the webview.
|
||||||
pub fn start(
|
pub fn start(app: AppHandle, generation: u64, track: RemoteVideoTrack, priority: u8, sid: String) {
|
||||||
app: AppHandle,
|
|
||||||
generation: u64,
|
|
||||||
track: RemoteVideoTrack,
|
|
||||||
priority: u8,
|
|
||||||
sid: String,
|
|
||||||
) {
|
|
||||||
// A camera must not displace a screen share that is already on the display.
|
// A camera must not displace a screen share that is already on the display.
|
||||||
if IS_STREAMING.load(Ordering::SeqCst) && CURRENT_PRIORITY.load(Ordering::SeqCst) > priority {
|
if IS_STREAMING.load(Ordering::SeqCst) && CURRENT_PRIORITY.load(Ordering::SeqCst) > priority {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+8
-2
@@ -81,7 +81,10 @@ pub struct KioskIdentity {
|
|||||||
impl FromRequestParts<AppState> for AdminIdentity {
|
impl FromRequestParts<AppState> for AdminIdentity {
|
||||||
type Rejection = AppError;
|
type Rejection = AppError;
|
||||||
|
|
||||||
async fn from_request_parts(parts: &mut Parts, state: &AppState) -> Result<Self, Self::Rejection> {
|
async fn from_request_parts(
|
||||||
|
parts: &mut Parts,
|
||||||
|
state: &AppState,
|
||||||
|
) -> Result<Self, Self::Rejection> {
|
||||||
let token = bearer_token(parts)?;
|
let token = bearer_token(parts)?;
|
||||||
let data = decode::<AdminClaims>(
|
let data = decode::<AdminClaims>(
|
||||||
&token,
|
&token,
|
||||||
@@ -100,7 +103,10 @@ impl FromRequestParts<AppState> for AdminIdentity {
|
|||||||
impl FromRequestParts<AppState> for KioskIdentity {
|
impl FromRequestParts<AppState> for KioskIdentity {
|
||||||
type Rejection = AppError;
|
type Rejection = AppError;
|
||||||
|
|
||||||
async fn from_request_parts(parts: &mut Parts, state: &AppState) -> Result<Self, Self::Rejection> {
|
async fn from_request_parts(
|
||||||
|
parts: &mut Parts,
|
||||||
|
state: &AppState,
|
||||||
|
) -> Result<Self, Self::Rejection> {
|
||||||
let token = bearer_token(parts)?;
|
let token = bearer_token(parts)?;
|
||||||
let token_hash = hash_opaque_token(&token);
|
let token_hash = hash_opaque_token(&token);
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,9 @@ fn apply_defaults(kiosk_id: &str, mut layout: Value) -> Value {
|
|||||||
.entry("foregroundColor")
|
.entry("foregroundColor")
|
||||||
.or_insert_with(|| json!("#f4f6f8"));
|
.or_insert_with(|| json!("#f4f6f8"));
|
||||||
object.entry("widgetOpacity").or_insert_with(|| json!(0.5));
|
object.entry("widgetOpacity").or_insert_with(|| json!(0.5));
|
||||||
object.entry("background").or_insert_with(default_background);
|
object
|
||||||
|
.entry("background")
|
||||||
|
.or_insert_with(default_background);
|
||||||
object.entry("nightMode").or_insert_with(default_night_mode);
|
object.entry("nightMode").or_insert_with(default_night_mode);
|
||||||
object.entry("widgets").or_insert_with(|| json!([]));
|
object.entry("widgets").or_insert_with(|| json!([]));
|
||||||
object
|
object
|
||||||
@@ -160,10 +162,11 @@ fn fill_nested_defaults(target: Option<&mut Value>, defaults: Value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn load_layout(db: &SqlitePool, kiosk_id: &str) -> AppResult<Value> {
|
pub async fn load_layout(db: &SqlitePool, kiosk_id: &str) -> AppResult<Value> {
|
||||||
let row: Option<(String,)> = sqlx::query_as("SELECT data FROM kiosk_layouts WHERE kiosk_id = ?")
|
let row: Option<(String,)> =
|
||||||
.bind(kiosk_id)
|
sqlx::query_as("SELECT data FROM kiosk_layouts WHERE kiosk_id = ?")
|
||||||
.fetch_optional(db)
|
.bind(kiosk_id)
|
||||||
.await?;
|
.fetch_optional(db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let stored = match row {
|
let stored = match row {
|
||||||
Some((data,)) => serde_json::from_str(&data).unwrap_or_else(|_| default_layout(kiosk_id)),
|
Some((data,)) => serde_json::from_str(&data).unwrap_or_else(|_| default_layout(kiosk_id)),
|
||||||
|
|||||||
+4
-1
@@ -75,7 +75,10 @@ async fn main() {
|
|||||||
.nest("/api/kiosk", routes::kiosk_router().layer(kiosk_cors))
|
.nest("/api/kiosk", routes::kiosk_router().layer(kiosk_cors))
|
||||||
.nest("/api", routes::api_router().layer(cors))
|
.nest("/api", routes::api_router().layer(cors))
|
||||||
.nest_service("/media", ServeDir::new(state.config.media_dir.clone()))
|
.nest_service("/media", ServeDir::new(state.config.media_dir.clone()))
|
||||||
.nest_service("/downloads", ServeDir::new(state.config.package_dir.clone()))
|
.nest_service(
|
||||||
|
"/downloads",
|
||||||
|
ServeDir::new(state.config.package_dir.clone()),
|
||||||
|
)
|
||||||
.layer(TraceLayer::new_for_http())
|
.layer(TraceLayer::new_for_http())
|
||||||
.with_state(state);
|
.with_state(state);
|
||||||
|
|
||||||
|
|||||||
@@ -39,9 +39,7 @@ impl From<KioskRow> for KioskView {
|
|||||||
status: row.status,
|
status: row.status,
|
||||||
last_seen_at: row.last_seen_at,
|
last_seen_at: row.last_seen_at,
|
||||||
created_at: row.created_at,
|
created_at: row.created_at,
|
||||||
metrics: row
|
metrics: row.metrics.and_then(|raw| serde_json::from_str(&raw).ok()),
|
||||||
.metrics
|
|
||||||
.and_then(|raw| serde_json::from_str(&raw).ok()),
|
|
||||||
metrics_at: row.metrics_at,
|
metrics_at: row.metrics_at,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-7
@@ -24,13 +24,15 @@ pub async fn issue_pin(
|
|||||||
let expires_at = issued_at + seconds_to_ms(rotation_seconds + grace_seconds);
|
let expires_at = issued_at + seconds_to_ms(rotation_seconds + grace_seconds);
|
||||||
let pin = allocate_unique_pin(db, issued_at).await?;
|
let pin = allocate_unique_pin(db, issued_at).await?;
|
||||||
|
|
||||||
sqlx::query("INSERT INTO kiosk_pins (pin, kiosk_id, issued_at, expires_at) VALUES (?, ?, ?, ?)")
|
sqlx::query(
|
||||||
.bind(&pin)
|
"INSERT INTO kiosk_pins (pin, kiosk_id, issued_at, expires_at) VALUES (?, ?, ?, ?)",
|
||||||
.bind(kiosk_id)
|
)
|
||||||
.bind(issued_at)
|
.bind(&pin)
|
||||||
.bind(expires_at)
|
.bind(kiosk_id)
|
||||||
.execute(db)
|
.bind(issued_at)
|
||||||
.await?;
|
.bind(expires_at)
|
||||||
|
.execute(db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(IssuedPin {
|
Ok(IssuedPin {
|
||||||
pin,
|
pin,
|
||||||
|
|||||||
@@ -85,10 +85,11 @@ async fn list_kiosks(
|
|||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
_admin: AdminIdentity,
|
_admin: AdminIdentity,
|
||||||
) -> AppResult<Json<KioskListResponse>> {
|
) -> AppResult<Json<KioskListResponse>> {
|
||||||
let rows: Vec<KioskRow> =
|
let rows: Vec<KioskRow> = sqlx::query_as(&format!(
|
||||||
sqlx::query_as(&format!("SELECT {KIOSK_COLUMNS} FROM kiosks ORDER BY created_at"))
|
"SELECT {KIOSK_COLUMNS} FROM kiosks ORDER BY created_at"
|
||||||
.fetch_all(&state.db)
|
))
|
||||||
.await?;
|
.fetch_all(&state.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let now = now_ms();
|
let now = now_ms();
|
||||||
let kiosks = rows
|
let kiosks = rows
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ fn resolve_server_url(state: &AppState, headers: &HeaderMap) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !state.config.public_api_url.is_empty() {
|
if !state.config.public_api_url.is_empty() {
|
||||||
return state.config.public_api_url.trim_end_matches('/').to_string();
|
return state
|
||||||
|
.config
|
||||||
|
.public_api_url
|
||||||
|
.trim_end_matches('/')
|
||||||
|
.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
"http://localhost:8080".to_string()
|
"http://localhost:8080".to_string()
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use axum::{Json, Router};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
|
|
||||||
use crate::auth::{generate_opaque_token, hash_opaque_token, KioskIdentity};
|
use crate::auth::{generate_opaque_token, hash_opaque_token, KioskIdentity};
|
||||||
use crate::clock::now_ms;
|
use crate::clock::now_ms;
|
||||||
use crate::error::{AppError, AppResult};
|
use crate::error::{AppError, AppResult};
|
||||||
|
|||||||
@@ -34,22 +34,29 @@ pub async fn store_image(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if body.len() > MAX_UPLOAD_BYTES {
|
if body.len() > MAX_UPLOAD_BYTES {
|
||||||
return Err(AppError::BadRequest("images must be 8 MB or smaller".into()));
|
return Err(AppError::BadRequest(
|
||||||
|
"images must be 8 MB or smaller".into(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let content_type = headers
|
let content_type = headers
|
||||||
.get(axum::http::header::CONTENT_TYPE)
|
.get(axum::http::header::CONTENT_TYPE)
|
||||||
.and_then(|value| value.to_str().ok())
|
.and_then(|value| value.to_str().ok())
|
||||||
.map(|value| value.split(';').next().unwrap_or(value).trim().to_lowercase())
|
.map(|value| {
|
||||||
|
value
|
||||||
|
.split(';')
|
||||||
|
.next()
|
||||||
|
.unwrap_or(value)
|
||||||
|
.trim()
|
||||||
|
.to_lowercase()
|
||||||
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let extension = ALLOWED_TYPES
|
let extension = ALLOWED_TYPES
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(mime, _)| *mime == content_type)
|
.find(|(mime, _)| *mime == content_type)
|
||||||
.map(|(_, extension)| *extension)
|
.map(|(_, extension)| *extension)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| AppError::BadRequest("images must be a PNG, JPEG, WEBP or GIF".into()))?;
|
||||||
AppError::BadRequest("images must be a PNG, JPEG, WEBP or GIF".into())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let directory = std::path::Path::new(&state.config.media_dir);
|
let directory = std::path::Path::new(&state.config.media_dir);
|
||||||
tokio::fs::create_dir_all(directory)
|
tokio::fs::create_dir_all(directory)
|
||||||
|
|||||||
Reference in New Issue
Block a user