| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- use uuid::Uuid;
- use serde::Serialize;
- use sqlx::{PgPool, postgres::PgQueryResult};
- use crate::app_error::AppError;
- #[derive(Serialize, sqlx::FromRow)]
- pub struct Device {
- pub id: Uuid,
- pub home_id: Uuid,
- pub name: String,
- pub description: Option<String>,
- pub device_type: DeviceType
- }
- #[derive(Serialize, sqlx::Type)]
- #[sqlx(type_name = "device_type", rename_all = "snake_case")]
- pub enum DeviceType {
- OnOffSwitch
- }
- impl Device {
- pub fn new(
- home_id: Uuid,
- name: String,
- description: Option<String>,
- device_type: String
- ) -> Result<Self, AppError> {
- Ok(Self {
- id: Uuid::now_v7(),
- home_id: home_id,
- name: name,
- description: description,
- device_type: match device_type.as_str() {
- "on_off_switch" => DeviceType::OnOffSwitch,
- _ => {return Err(AppError::invalid_input("Invalid device type"))}
- }
- })
- }
- pub async fn insert(
- &self,
- db: &PgPool,
- user_id: Uuid,
- home_id: Uuid
- ) -> Result<(), AppError> {
- let result: PgQueryResult = sqlx::query!(
- "INSERT INTO devices (id, home_id, name, description, device_type)
- SELECT $1, $2, $3, $4, $5
- WHERE EXISTS (
- SELECT 1
- FROM users_homes
- WHERE user_id = $6
- AND home_id = $2
- AND is_admin = true
- )",
- self.id,
- home_id,
- self.name,
- self.description,
- &self.device_type as &DeviceType,
- user_id
- )
- .execute(db)
- .await?;
- if result.rows_affected() == 0 {
- return Err(AppError::forbidden("Unauthorized access to home"));
- }
- Ok(())
- }
- pub async fn delete(
- db: &PgPool,
- user_id: Uuid,
- home_id: Uuid,
- device_id: Uuid
- ) -> Result<(), AppError> {
- let result = sqlx::query!(
- "DELETE FROM devices
- WHERE id = $1
- AND home_id = $2
- AND EXISTS (
- SELECT 1
- FROM users_homes
- WHERE user_id = $3
- AND home_id = $2
- AND is_admin = true
- );",
- device_id,
- home_id,
- user_id
- )
- .execute(db)
- .await?;
- if result.rows_affected() == 0 {
- return Err(AppError::forbidden("Unauthorized access to device"));
- }
- Ok(())
- }
- pub async fn find_one(
- db: &PgPool,
- user_id: Uuid,
- home_id: Uuid,
- device_id: Uuid,
- ) -> Result<Device, AppError> {
- let device = sqlx::query_as::<_, Device>(
- "SELECT devices.*
- FROM devices
- JOIN users_homes ON users_homes.home_id = devices.home_id
- WHERE devices.id = $1
- AND devices.home_id = $2
- AND users_homes.user_id = $3"
- )
- .bind(device_id)
- .bind(home_id)
- .bind(user_id)
- .fetch_optional(db)
- .await?;
- match device {
- Some(d) => Ok(d),
- None => Err(AppError::forbidden("Unauthorized access to device"))
- }
- }
- }
|