Skip to content
Clone
a06673b
75 lines 2.4 KB Rust
use db::conn::sea_orm::{
ActiveModelTrait, EntityTrait, QueryFilter, QueryOrder, Set,
};
use uuid::Uuid;
use crate::error::{UserError, UserResult};
use crate::features::UserService;
use super::types::{DeviceView, UpdateDeviceCmd};
const MAX_DEVICE_NAME: usize = 128;
pub async fn list(svc: &UserService, caller: Uuid) -> UserResult<Vec<DeviceView>> {
let db = svc.db.reader();
let rows = db::user::user_devices::Entity::find()
.filter(db::user::user_devices::COLUMN.user_id.eq(caller))
.order_by_desc(db::user::user_devices::COLUMN.last_seen_at)
.all(&db)
.await?;
Ok(rows.into_iter().map(DeviceView::from).collect())
}
pub async fn update(
svc: &UserService,
caller: Uuid,
device_id: Uuid,
cmd: UpdateDeviceCmd,
) -> UserResult<DeviceView> {
if let Some(Some(ref name)) = cmd.device_name
&& (name.is_empty() || name.len() > MAX_DEVICE_NAME) {
return Err(UserError::BadRequest(format!(
"device_name length must be 1..={MAX_DEVICE_NAME}"
)));
}
let writer = svc.db.writer();
let row = db::user::user_devices::Entity::find_by_id(device_id)
.one(&writer)
.await?
.ok_or_else(|| UserError::NotFound(format!("device {device_id}")))?;
if row.user_id != caller {
return Err(UserError::Forbidden("cannot modify other user's device".into()));
}
let mut active: db::user::user_devices::ActiveModel = row.into();
if let Some(v) = cmd.device_name {
active.device_name = Set(v);
}
if let Some(v) = cmd.is_trusted {
active.is_trusted = Set(v);
}
active.updated_at = Set(time::OffsetDateTime::now_utc());
let saved = active.update(&writer).await?;
Ok(DeviceView::from(saved))
}
pub async fn delete(svc: &UserService, caller: Uuid, device_id: Uuid) -> UserResult<()> {
let writer = svc.db.writer();
let row = db::user::user_devices::Entity::find_by_id(device_id)
.one(&writer)
.await?
.ok_or_else(|| UserError::NotFound(format!("device {device_id}")))?;
if row.user_id != caller {
return Err(UserError::Forbidden("cannot delete other user's device".into()));
}
db::user::user_devices::Entity::delete_by_id(device_id)
.exec(&writer)
.await?;
Ok(())
}
#[allow(dead_code)]
fn _now_utc() -> time::OffsetDateTime {
time::OffsetDateTime::now_utc()
}