use chrono::NaiveDateTime; use diesel::{self, QueryDsl, RunQueryDsl, ExpressionMethods}; use std::iter::Iterator; use plume_common::utils::md_to_html; use Connection; use safe_string::SafeString; use ap_url; use users::User; use schema::{instances, users}; #[derive(Clone, Identifiable, Queryable, Serialize)] pub struct Instance { pub id: i32, pub public_domain: String, pub name: String, pub local: bool, pub blocked: bool, pub creation_date: NaiveDateTime, pub open_registrations: bool, pub short_description: SafeString, pub long_description: SafeString, pub default_license : String, pub long_description_html: String, pub short_description_html: String } #[derive(Insertable)] #[table_name = "instances"] pub struct NewInstance { pub public_domain: String, pub name: String, pub local: bool, pub open_registrations: bool, pub short_description: SafeString, pub long_description: SafeString, pub default_license : String, pub long_description_html: String, pub short_description_html: String } impl Instance { pub fn get_local(conn: &Connection) -> Option { instances::table.filter(instances::local.eq(true)) .limit(1) .load::(conn) .expect("Instance::get_local: loading error") .into_iter().nth(0) } pub fn get_remotes(conn: &Connection) -> Vec { instances::table.filter(instances::local.eq(false)) .load::(conn) .expect("Instance::get_remotes: loading error") } pub fn page(conn: &Connection, (min, max): (i32, i32)) -> Vec { instances::table.order(instances::public_domain.asc()) .offset(min.into()) .limit((max - min).into()) .load::(conn) .expect("Instance::page: loading error") } pub fn local_id(conn: &Connection) -> i32 { Instance::get_local(conn).expect("Instance::local_id: local instance not found error").id } insert!(instances, NewInstance); get!(instances); find_by!(instances, find_by_domain, public_domain as String); pub fn toggle_block(&self, conn: &Connection) { diesel::update(self) .set(instances::blocked.eq(!self.blocked)) .execute(conn) .expect("Instance::toggle_block: update error"); } /// id: AP object id pub fn is_blocked(conn: &Connection, id: String) -> bool { for block in instances::table.filter(instances::blocked.eq(true)) .get_results::(conn) .expect("Instance::is_blocked: loading error") { if id.starts_with(format!("https://{}", block.public_domain).as_str()) { return true; } } false } pub fn has_admin(&self, conn: &Connection) -> bool { users::table.filter(users::instance_id.eq(self.id)) .filter(users::is_admin.eq(true)) .load::(conn) .expect("Instance::has_admin: loading error") .len() > 0 } pub fn main_admin(&self, conn: &Connection) -> User { users::table.filter(users::instance_id.eq(self.id)) .filter(users::is_admin.eq(true)) .limit(1) .get_result::(conn) .expect("Instance::main_admin: loading error") } pub fn compute_box(&self, prefix: &'static str, name: String, box_name: &'static str) -> String { ap_url(format!( "{instance}/{prefix}/{name}/{box_name}", instance = self.public_domain, prefix = prefix, name = name, box_name = box_name )) } pub fn update(&self, conn: &Connection, name: String, open_registrations: bool, short_description: SafeString, long_description: SafeString) { let (sd, _) = md_to_html(short_description.as_ref()); let (ld, _) = md_to_html(long_description.as_ref()); diesel::update(self) .set(( instances::name.eq(name), instances::open_registrations.eq(open_registrations), instances::short_description.eq(short_description), instances::long_description.eq(long_description), instances::short_description_html.eq(sd), instances::long_description_html.eq(ld) )).execute(conn) .expect("Instance::update: update error"); } pub fn count(conn: &Connection) -> i64 { instances::table.count().get_result(conn).expect("Instance::count: counting error") } }