use crate::models::user::UserInfo; use uuid::Uuid; use diesel::prelude::*; use diesel::result::Error as DieselError; use serde::{Serialize, Deserialize}; use crate::schema::*; use crate::dns::name::AbsoluteName; use crate::models::user::UserZone; use crate::models::errors::UserError; #[derive(Debug, Serialize, Queryable, Identifiable, Insertable)] #[table_name = "zone"] pub struct Zone { #[serde(skip)] pub id: String, pub name: String, } #[derive(Debug, Deserialize)] pub struct AddZoneMemberRequest { pub id: String, } #[derive(Debug, Deserialize)] pub struct CreateZoneRequest { pub name: AbsoluteName, } // NOTE: Should probably not be implemented here // also, "UserError" seems like a misleading name impl Zone { pub fn get_all(conn: &diesel::SqliteConnection) -> Result, UserError> { use crate::schema::zone::dsl::*; zone.get_results(conn) .map_err(UserError::DbError) } pub fn get_by_name(conn: &diesel::SqliteConnection, zone_name: &str) -> Result { use crate::schema::zone::dsl::*; zone.filter(name.eq(zone_name)) .get_result(conn) .map_err(|e| match e { DieselError::NotFound => UserError::ZoneNotFound, other => UserError::DbError(other) }) } pub fn create_zone(conn: &diesel::SqliteConnection, zone_request: CreateZoneRequest) -> Result { use crate::schema::zone::dsl::*; let new_zone = Zone { id: Uuid::new_v4().to_simple().to_string(), name: zone_request.name.to_utf8(), }; diesel::insert_into(zone) .values(&new_zone) .execute(conn) .map_err(|e| match e { DieselError::DatabaseError(diesel::result::DatabaseErrorKind::UniqueViolation, _) => UserError::UserConflict, other => UserError::DbError(other) })?; Ok(new_zone) } pub fn add_member(&self, conn: &diesel::SqliteConnection, new_member: &UserInfo) -> Result<(), UserError> { use crate::schema::user_zone::dsl::*; let new_user_zone = UserZone { zone_id: self.id.clone(), user_id: new_member.id.clone() }; let res = diesel::insert_into(user_zone) .values(new_user_zone) .execute(conn); match res { // If user has already access to the zone, safely ignore the conflit // TODO: use 'on conflict do nothing' in postgres when we get there Err(DieselError::DatabaseError(diesel::result::DatabaseErrorKind::UniqueViolation, _)) => (), Err(e) => return Err(e.into()), Ok(_) => () }; Ok(()) } }