feat: added device models
parent
1f4b0c35c5
commit
993e58babf
|
@ -0,0 +1 @@
|
|||
drop table devices;
|
|
@ -0,0 +1,13 @@
|
|||
create table devices (
|
||||
id integer primary key not null,
|
||||
|
||||
device_id text not null,
|
||||
user_id bigint not null
|
||||
references users (id)
|
||||
on delete cascade,
|
||||
|
||||
caption text not null,
|
||||
type text not null,
|
||||
|
||||
unique (user_id, device_id)
|
||||
);
|
|
@ -1,6 +1,7 @@
|
|||
pub mod models;
|
||||
mod schema;
|
||||
|
||||
pub use models::device::{Device, NewDevice};
|
||||
pub use models::session::Session;
|
||||
pub use models::user::{NewUser, User};
|
||||
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
use std::{fmt, str::FromStr};
|
||||
|
||||
use diesel::{
|
||||
deserialize::{FromSql, FromSqlRow},
|
||||
expression::AsExpression,
|
||||
prelude::*,
|
||||
serialize::ToSql,
|
||||
sql_types::Text,
|
||||
sqlite::{Sqlite, SqliteValue},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::db::{schema::*, DbPool, DbResult};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Queryable, Selectable)]
|
||||
#[diesel(table_name = devices)]
|
||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||
pub struct Device {
|
||||
id: i64,
|
||||
device_id: String,
|
||||
user_id: i64,
|
||||
caption: String,
|
||||
type_: DeviceType,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Insertable)]
|
||||
#[diesel(table_name = devices)]
|
||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||
pub struct NewDevice {
|
||||
device_id: String,
|
||||
user_id: i64,
|
||||
caption: String,
|
||||
type_: DeviceType,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, FromSqlRow, Debug, AsExpression, Clone)]
|
||||
#[diesel(sql_type = Text)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum DeviceType {
|
||||
Desktop,
|
||||
Laptop,
|
||||
Mobile,
|
||||
Server,
|
||||
Other,
|
||||
}
|
||||
|
||||
impl Device {
|
||||
pub fn for_user(pool: &DbPool, user_id: i64) -> DbResult<Vec<Self>> {
|
||||
Ok(devices::dsl::devices
|
||||
.select(Self::as_select())
|
||||
.filter(devices::user_id.eq(user_id))
|
||||
.get_results(&mut pool.get()?)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DeviceType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Self::Desktop => "desktop",
|
||||
Self::Laptop => "laptop",
|
||||
Self::Mobile => "mobile",
|
||||
Self::Server => "server",
|
||||
Self::Other => "other",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DeviceTypeParseErr(String);
|
||||
|
||||
impl fmt::Display for DeviceTypeParseErr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "invalid device type '{}'", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for DeviceTypeParseErr {}
|
||||
|
||||
impl FromStr for DeviceType {
|
||||
type Err = DeviceTypeParseErr;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"desktop" => Ok(Self::Desktop),
|
||||
"laptop" => Ok(Self::Laptop),
|
||||
"mobile" => Ok(Self::Mobile),
|
||||
"server" => Ok(Self::Server),
|
||||
"other" => Ok(Self::Other),
|
||||
_ => Err(DeviceTypeParseErr(s.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql<Text, Sqlite> for DeviceType {
|
||||
fn from_sql(bytes: SqliteValue) -> diesel::deserialize::Result<Self> {
|
||||
let s = <String as FromSql<Text, Sqlite>>::from_sql(bytes)?;
|
||||
|
||||
Ok(s.as_str().parse()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSql<Text, Sqlite> for DeviceType {
|
||||
fn to_sql<'b>(
|
||||
&'b self,
|
||||
out: &mut diesel::serialize::Output<'b, '_, Sqlite>,
|
||||
) -> diesel::serialize::Result {
|
||||
out.set_value(self.to_string());
|
||||
|
||||
Ok(diesel::serialize::IsNull::No)
|
||||
}
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
pub mod device;
|
||||
pub mod session;
|
||||
pub mod user;
|
||||
|
|
|
@ -23,15 +23,16 @@ impl Session {
|
|||
.get_result(&mut pool.get()?)?)
|
||||
}
|
||||
|
||||
pub fn user_from_id(pool: &DbPool, id: i64) -> DbResult<super::user::User> {
|
||||
pub fn user_from_id(pool: &DbPool, id: i64) -> DbResult<Option<super::user::User>> {
|
||||
Ok(sessions::dsl::sessions
|
||||
.inner_join(users::table)
|
||||
.filter(sessions::id.eq(id))
|
||||
.select(User::as_select())
|
||||
.get_result(&mut pool.get()?)?)
|
||||
.get_result(&mut pool.get()?)
|
||||
.optional()?)
|
||||
}
|
||||
|
||||
pub fn user(&self, pool: &DbPool) -> DbResult<super::user::User> {
|
||||
pub fn user(&self, pool: &DbPool) -> DbResult<Option<super::user::User>> {
|
||||
Self::user_from_id(pool, self.id)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
devices (id) {
|
||||
id -> BigInt,
|
||||
device_id -> Text,
|
||||
user_id -> BigInt,
|
||||
caption -> Text,
|
||||
#[sql_name = "type"]
|
||||
type_ -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
sessions (id) {
|
||||
id -> BigInt,
|
||||
|
@ -15,9 +26,11 @@ diesel::table! {
|
|||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(devices -> users (user_id));
|
||||
diesel::joinable!(sessions -> users (user_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
devices,
|
||||
sessions,
|
||||
users,
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue