diff --git a/migrations/2018-07-27-125558_instance_customization/down.sql b/migrations/2018-07-27-125558_instance_customization/down.sql new file mode 100644 index 00000000..38cca3cd --- /dev/null +++ b/migrations/2018-07-27-125558_instance_customization/down.sql @@ -0,0 +1,5 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE instances DROP COLUMN open_registrations; +ALTER TABLE instances DROP COLUMN short_description; +ALTER TABLE instances DROP COLUMN long_description; +ALTER TABLE instances DROP COLUMN default_license; diff --git a/migrations/2018-07-27-125558_instance_customization/up.sql b/migrations/2018-07-27-125558_instance_customization/up.sql new file mode 100644 index 00000000..1efde74c --- /dev/null +++ b/migrations/2018-07-27-125558_instance_customization/up.sql @@ -0,0 +1,5 @@ +-- Your SQL goes here +ALTER TABLE instances ADD COLUMN open_registrations BOOLEAN NOT NULL DEFAULT 't'; +ALTER TABLE instances ADD COLUMN short_description TEXT NOT NULL DEFAULT ''; +ALTER TABLE instances ADD COLUMN long_description TEXT NOT NULL DEFAULT ''; +ALTER TABLE instances ADD COLUMN default_license TEXT NOT NULL DEFAULT 'CC-0'; diff --git a/plume-models/src/admin.rs b/plume-models/src/admin.rs new file mode 100644 index 00000000..8d85c3bd --- /dev/null +++ b/plume-models/src/admin.rs @@ -0,0 +1,19 @@ +use rocket::{Outcome, http::Status, request::{self, FromRequest, Request}}; + +use users::User; + +/// Wrapper around User to use as a request guard on pages reserved to admins. +pub struct Admin(pub User); + +impl<'a, 'r> FromRequest<'a, 'r> for Admin { + type Error = (); + + fn from_request(request: &'a Request<'r>) -> request::Outcome { + let user = request.guard::()?; + if user.is_admin { + Outcome::Success(Admin(user)) + } else { + Outcome::Failure((Status::Unauthorized, ())) + } + } +} diff --git a/plume-models/src/blogs.rs b/plume-models/src/blogs.rs index be8f544d..324b60ec 100644 --- a/plume-models/src/blogs.rs +++ b/plume-models/src/blogs.rs @@ -140,7 +140,12 @@ impl Blog { Instance::insert(conn, NewInstance { public_domain: inst.clone(), name: inst.clone(), - local: false + local: false, + // We don't really care about all the following for remote instances + long_description: String::new(), + short_description: String::new(), + default_license: String::new(), + open_registrations: true }) } }; diff --git a/plume-models/src/instance.rs b/plume-models/src/instance.rs index 8eef2254..36f38470 100644 --- a/plume-models/src/instance.rs +++ b/plume-models/src/instance.rs @@ -13,7 +13,11 @@ pub struct Instance { pub name: String, pub local: bool, pub blocked: bool, - pub creation_date: NaiveDateTime + pub creation_date: NaiveDateTime, + pub open_registrations: bool, + pub short_description: String, + pub long_description: String, + pub default_license : String } #[derive(Insertable)] @@ -21,7 +25,11 @@ pub struct Instance { pub struct NewInstance { pub public_domain: String, pub name: String, - pub local: bool + pub local: bool, + pub open_registrations: bool, + pub short_description: String, + pub long_description: String, + pub default_license : String } impl Instance { @@ -68,4 +76,15 @@ impl Instance { box_name = box_name )) } + + pub fn update(&self, conn: &PgConnection, name: String, open_registrations: bool, short_description: String, long_description: String) -> Instance { + 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), + )).get_result::(conn) + .expect("Couldn't update instance") + } } diff --git a/plume-models/src/lib.rs b/plume-models/src/lib.rs index 5d15fc2c..e0bd5b20 100644 --- a/plume-models/src/lib.rs +++ b/plume-models/src/lib.rs @@ -103,6 +103,7 @@ pub fn ap_url(url: String) -> String { format!("{}://{}", scheme, url) } +pub mod admin; pub mod blog_authors; pub mod blogs; pub mod comments; diff --git a/plume-models/src/schema.rs b/plume-models/src/schema.rs index fce52e1e..47ed12dd 100644 --- a/plume-models/src/schema.rs +++ b/plume-models/src/schema.rs @@ -53,6 +53,10 @@ table! { local -> Bool, blocked -> Bool, creation_date -> Timestamp, + open_registrations -> Bool, + short_description -> Text, + long_description -> Text, + default_license -> Text, } } diff --git a/plume-models/src/users.rs b/plume-models/src/users.rs index 332d7580..9878cec9 100644 --- a/plume-models/src/users.rs +++ b/plume-models/src/users.rs @@ -184,7 +184,12 @@ impl User { Instance::insert(conn, NewInstance { name: inst.clone(), public_domain: inst.clone(), - local: false + local: false, + // We don't really care about all the following for remote instances + long_description: String::new(), + short_description: String::new(), + default_license: String::new(), + open_registrations: true }) } }; diff --git a/po/de.po b/po/de.po index 921b90c3..907385db 100644 --- a/po/de.po +++ b/po/de.po @@ -377,3 +377,9 @@ msgstr "" msgid "Matrix room" msgstr "" + +msgid "Administration" +msgstr "" + +msgid "Instance settings" +msgstr "" diff --git a/po/en.po b/po/en.po index bc06fe64..6b46a0b8 100644 --- a/po/en.po +++ b/po/en.po @@ -364,3 +364,9 @@ msgstr "" msgid "Matrix room" msgstr "" + +msgid "Administration" +msgstr "" + +msgid "Instance settings" +msgstr "" diff --git a/po/fr.po b/po/fr.po index c5a80b64..f6d0a96f 100644 --- a/po/fr.po +++ b/po/fr.po @@ -373,3 +373,9 @@ msgstr "" msgid "Matrix room" msgstr "" + +msgid "Administration" +msgstr "" + +msgid "Instance settings" +msgstr "" diff --git a/po/pl.po b/po/pl.po index 3f792357..37a8fd29 100644 --- a/po/pl.po +++ b/po/pl.po @@ -382,5 +382,11 @@ msgstr "" msgid "Matrix room" msgstr "" +msgid "Administration" +msgstr "" + +msgid "Instance settings" +msgstr "" + #~ msgid "Logowanie" #~ msgstr "Zaloguj się" diff --git a/po/plume.pot b/po/plume.pot index 5617ce09..58b1ea3a 100644 --- a/po/plume.pot +++ b/po/plume.pot @@ -357,3 +357,9 @@ msgstr "" msgid "Matrix room" msgstr "" + +msgid "Administration" +msgstr "" + +msgid "Instance settings" +msgstr "" diff --git a/src/main.rs b/src/main.rs index 463c857a..2e0c76fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,6 +50,8 @@ fn main() { routes::instance::paginated_index, routes::instance::index, + routes::instance::admin, + routes::instance::update_settings, routes::instance::shared_inbox, routes::instance::nodeinfo, diff --git a/src/routes/instance.rs b/src/routes/instance.rs index 475d69cf..e3b46d90 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -1,8 +1,11 @@ use gettextrs::gettext; +use rocket::{request::LenientForm, response::Redirect}; use rocket_contrib::{Json, Template}; use serde_json; +use validator::{Validate}; use plume_models::{ + admin::Admin, comments::Comment, db_conn::DbConn, posts::Post, @@ -39,6 +42,48 @@ fn index(conn: DbConn, user: Option) -> Template { paginated_index(conn, user, Page::first()) } +#[get("/admin")] +fn admin(conn: DbConn, admin: Admin) -> Template { + Template::render("instance/admin", json!({ + "account": admin.0, + "instance": Instance::get_local(&*conn), + "errors": null, + "form": null + })) +} + +#[derive(FromForm, Validate, Serialize)] +struct InstanceSettingsForm { + #[validate(length(min = "1"))] + name: String, + open_registrations: bool, + short_description: String, + long_description: String, + #[validate(length(min = "1"))] + default_license: String +} + +#[post("/admin", data = "
")] +fn update_settings(conn: DbConn, admin: Admin, form: LenientForm) -> Result { + let form = form.get(); + form.validate() + .map(|_| { + let instance = Instance::get_local(&*conn).unwrap(); + instance.update(&*conn, + form.name.clone(), + form.open_registrations, + form.short_description.clone(), + form.long_description.clone()); + Redirect::to(uri!(admin)) + }) + .map_err(|e| Template::render("instance/admin", json!({ + "account": admin.0, + "instance": Instance::get_local(&*conn), + "errors": e.inner(), + "form": form + }))) +} + #[post("/inbox", data = "")] fn shared_inbox(conn: DbConn, data: String) -> String { let act: serde_json::Value = serde_json::from_str(&data[..]).unwrap(); diff --git a/src/setup.rs b/src/setup.rs index 45378eed..1da87610 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -151,7 +151,11 @@ fn quick_setup(conn: DbConn) { let instance = Instance::insert(&*conn, NewInstance { public_domain: domain, name: name, - local: true + local: true, + long_description: String::new(), + short_description: String::new(), + default_license: String::from("CC-0"), + open_registrations: true }); println!("{}\n", " ✔️ Your instance was succesfully created!".green()); diff --git a/static/main.css b/static/main.css index 1f8dcd0e..481291fe 100644 --- a/static/main.css +++ b/static/main.css @@ -362,7 +362,14 @@ textarea { font-size: 1.1em; line-height: 1.5em; } - + +input[type="checkbox"] { + display: inline; + margin: initial; + min-width: initial; + width: initial; +} + /* Button & Submit */ .button, input[type="submit"], button { diff --git a/templates/base.html.tera b/templates/base.html.tera index 5f4fed4f..f5c19712 100644 --- a/templates/base.html.tera +++ b/templates/base.html.tera @@ -36,6 +36,11 @@ Plume 0.1.0 {{ "Source code" | _ }} {{ "Matrix room" | _ }} + {% if account %} + {% if account.is_admin %} + {{ "Administration" | _ }} + {% endif %} + {% endif %} diff --git a/templates/instance/admin.html.tera b/templates/instance/admin.html.tera new file mode 100644 index 00000000..14b4e816 --- /dev/null +++ b/templates/instance/admin.html.tera @@ -0,0 +1,34 @@ +{% extends "base" %} +{% import "macros" as macros %} + +{% block title %} +Administration of {{ instance.name }} +{% endblock title %} + +{% block content %} +

{{ "Administration" | _ }}

+ +

{{ "Instance settings" | _ }}

+ + {{ macros::input(name="name", label="Name", errors=errors, form=form, props='minlenght="1"', default=instance) }} + + + + + + + + + + {{ macros::input(name="default_license", label="Default license", errors=errors, form=form, props='minlenght="1"', default=instance) }} + + + +{% endblock content %} diff --git a/templates/macros.html.tera b/templates/macros.html.tera index 07ced606..0f9dbf69 100644 --- a/templates/macros.html.tera +++ b/templates/macros.html.tera @@ -17,7 +17,7 @@

{% endmacro post_card %} -{% macro input(name, label, errors, form, type="text", props="", optional=false) %} +{% macro input(name, label, errors, form, type="text", props="", optional=false, default='') %}