feat: combine app data into rubble data
This commit is contained in:
parent
41d3c21404
commit
a9836cf0c3
21
src/data.rs
Normal file
21
src/data.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use crate::pg_pool::{ManagedPgConn, Pool};
|
||||
use diesel::prelude::PgConnection;
|
||||
use r2d2::PooledConnection;
|
||||
use std::sync::Arc;
|
||||
use tera::{Context, Tera};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RubbleData {
|
||||
pub pool: Pool,
|
||||
pub tera: Arc<Tera>,
|
||||
}
|
||||
|
||||
impl RubbleData {
|
||||
pub fn postgres(&self) -> PooledConnection<ManagedPgConn> {
|
||||
let pool = self.pool.clone();
|
||||
pool.get().unwrap()
|
||||
}
|
||||
pub fn render(&self, template_name: &str, data: &Context) -> String {
|
||||
self.tera.render(template_name, data).unwrap()
|
||||
}
|
||||
}
|
18
src/main.rs
18
src/main.rs
@ -16,6 +16,7 @@ use actix_web::{
|
||||
|
||||
use dotenv::dotenv;
|
||||
|
||||
use crate::data::RubbleData;
|
||||
use crate::pg_pool::database_pool_establish;
|
||||
use actix_web::web::route;
|
||||
use rand::prelude::*;
|
||||
@ -24,6 +25,7 @@ use std::sync::Arc;
|
||||
use tera::compile_templates;
|
||||
use time::Duration;
|
||||
|
||||
mod data;
|
||||
mod models;
|
||||
mod pg_pool;
|
||||
mod routers;
|
||||
@ -38,18 +40,18 @@ fn main() {
|
||||
pretty_env_logger::init();
|
||||
|
||||
let database_url = std::env::var("DATABASE_URL").expect("database_url must be set");
|
||||
let pool = database_pool_establish(&database_url);
|
||||
|
||||
embedded_migrations::run(&pool.get().expect("cannot get connection"));
|
||||
|
||||
let tera = Arc::new(compile_templates!("templates/**/*.html"));
|
||||
|
||||
let random_cookie_key: Vec<u8> = (0..32).map(|_| rand::random::<u8>()).collect();
|
||||
|
||||
let data = RubbleData {
|
||||
pool: database_pool_establish(&database_url),
|
||||
tera: Arc::new(compile_templates!("templates/**/*.html")),
|
||||
};
|
||||
|
||||
embedded_migrations::run(&data.pool.get().expect("cannot get connection"));
|
||||
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.data(pool.clone())
|
||||
.data(tera.clone())
|
||||
.data(data.clone())
|
||||
.wrap(Logger::default())
|
||||
.wrap(Cors::default())
|
||||
.wrap(IdentityService::new(
|
||||
|
@ -3,7 +3,7 @@ use diesel::r2d2::ConnectionManager;
|
||||
use r2d2;
|
||||
use std::ops::Deref;
|
||||
|
||||
type ManagedPgConn = ConnectionManager<PgConnection>;
|
||||
pub type ManagedPgConn = ConnectionManager<PgConnection>;
|
||||
|
||||
pub type Pool = r2d2::Pool<ManagedPgConn>;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::models::article::{Article, NewArticle};
|
||||
|
||||
use crate::data::RubbleData;
|
||||
use crate::models::setting::Setting;
|
||||
use crate::models::user::User;
|
||||
use crate::models::CRUD;
|
||||
@ -29,21 +30,15 @@ pub fn redirect_to_admin_panel() -> impl Responder {
|
||||
}
|
||||
|
||||
#[get("/panel")]
|
||||
pub fn admin_panel(
|
||||
id: Identity,
|
||||
tera: web::Data<Arc<Tera>>,
|
||||
conn: web::Data<Pool>,
|
||||
) -> impl Responder {
|
||||
let connection = conn.get().unwrap();
|
||||
|
||||
pub fn admin_panel(id: Identity, data: web::Data<RubbleData>) -> impl Responder {
|
||||
if id.identity().is_none() {
|
||||
return RubbleResponder::Redirect("/admin/login".into());
|
||||
}
|
||||
|
||||
let articles = Article::read(&connection);
|
||||
let settings = Setting::load(&connection);
|
||||
let articles = Article::read(&data.postgres());
|
||||
let settings = Setting::load(&data.postgres());
|
||||
|
||||
let admin = User::find_by_username(&*connection, &id.identity().unwrap())
|
||||
let admin = User::find_by_username(&data.postgres(), &id.identity().unwrap())
|
||||
.expect("cannot found this user");
|
||||
|
||||
let mut context = Context::new();
|
||||
@ -51,14 +46,14 @@ pub fn admin_panel(
|
||||
context.insert("articles", &articles);
|
||||
context.insert("admin", &admin);
|
||||
|
||||
RubbleResponder::Html(tera.render("admin/panel.html", &context).unwrap())
|
||||
RubbleResponder::Html(data.render("admin/panel.html", &context))
|
||||
}
|
||||
|
||||
#[get("/login")]
|
||||
pub fn admin_login(id: Identity, tera: web::Data<Arc<Tera>>) -> impl Responder {
|
||||
pub fn admin_login(id: Identity, data: web::Data<RubbleData>) -> impl Responder {
|
||||
match id.identity() {
|
||||
Some(_) => RubbleResponder::Redirect("/admin/panel".into()),
|
||||
None => RubbleResponder::Html(tera.render("admin/login.html", &Context::new()).unwrap()),
|
||||
None => RubbleResponder::Html(data.render("admin/login.html", &Context::new())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,11 +61,9 @@ pub fn admin_login(id: Identity, tera: web::Data<Arc<Tera>>) -> impl Responder {
|
||||
pub fn admin_authentication(
|
||||
id: Identity,
|
||||
user: Form<LoginForm>,
|
||||
conn: web::Data<Pool>,
|
||||
data: web::Data<RubbleData>,
|
||||
) -> impl Responder {
|
||||
let connection = conn.get().unwrap();
|
||||
|
||||
let fetched_user = User::find_by_username(&connection, &user.username);
|
||||
let fetched_user = User::find_by_username(&data.postgres(), &user.username);
|
||||
|
||||
match fetched_user {
|
||||
Ok(login_user) => {
|
||||
@ -87,17 +80,12 @@ pub fn admin_authentication(
|
||||
}
|
||||
|
||||
#[get("/article/new")]
|
||||
pub fn article_creation(
|
||||
id: Identity,
|
||||
tera: web::Data<Arc<Tera>>,
|
||||
conn: web::Data<Pool>,
|
||||
) -> impl Responder {
|
||||
pub fn article_creation(id: Identity, data: web::Data<RubbleData>) -> impl Responder {
|
||||
if id.identity().is_none() {
|
||||
return RubbleResponder::Redirect("/admin/login".into());
|
||||
}
|
||||
let connection = conn.get().unwrap();
|
||||
|
||||
let admin = User::find_by_username(&*connection, &id.identity().unwrap())
|
||||
let admin = User::find_by_username(&data.postgres(), &id.identity().unwrap())
|
||||
.expect("cannot found this user");
|
||||
|
||||
let mut context = Context::new();
|
||||
@ -113,31 +101,29 @@ pub fn article_creation(
|
||||
};
|
||||
|
||||
context.insert("article", &article);
|
||||
RubbleResponder::Html(tera.render("admin/article_add.html", &context).unwrap())
|
||||
RubbleResponder::Html(data.render("admin/article_add.html", &context))
|
||||
}
|
||||
|
||||
#[get("/article/{article_id}")]
|
||||
pub fn article_edit(
|
||||
id: Identity,
|
||||
article_id: web::Path<i32>,
|
||||
tera: web::Data<Arc<Tera>>,
|
||||
conn: web::Data<Pool>,
|
||||
data: web::Data<RubbleData>,
|
||||
) -> impl Responder {
|
||||
if id.identity().is_none() {
|
||||
return RubbleResponder::Redirect("/admin/login".into());
|
||||
}
|
||||
let connection = conn.get().unwrap();
|
||||
|
||||
let admin = User::find_by_username(&*connection, &id.identity().unwrap())
|
||||
let admin = User::find_by_username(&data.postgres(), &id.identity().unwrap())
|
||||
.expect("cannot found this user");
|
||||
|
||||
let result = Article::get_by_pk(&connection, article_id.into_inner());
|
||||
let result = Article::get_by_pk(&data.postgres(), article_id.into_inner());
|
||||
|
||||
match result {
|
||||
Ok(article) => {
|
||||
let mut context = Context::new();
|
||||
context.insert("article", &article);
|
||||
RubbleResponder::Html(tera.render("admin/article_add.html", &context).unwrap())
|
||||
RubbleResponder::Html(data.render("admin/article_add.html", &context))
|
||||
}
|
||||
Err(_) => RubbleResponder::Redirect("/admin/panel".into()),
|
||||
}
|
||||
@ -146,22 +132,20 @@ pub fn article_edit(
|
||||
#[post("/article")]
|
||||
pub fn article_save(
|
||||
id: Identity,
|
||||
tera: web::Data<Arc<Tera>>,
|
||||
conn: web::Data<Pool>,
|
||||
article: Form<NewArticle>,
|
||||
data: web::Data<RubbleData>,
|
||||
) -> impl Responder {
|
||||
if id.identity().is_none() {
|
||||
return RubbleResponder::Redirect("/admin/login".into());
|
||||
}
|
||||
let connection = conn.get().unwrap();
|
||||
|
||||
let admin = User::find_by_username(&*connection, &id.identity().unwrap())
|
||||
let admin = User::find_by_username(&data.postgres(), &id.identity().unwrap())
|
||||
.expect("cannot found this user");
|
||||
|
||||
let res = if let Some(article_id) = article.id {
|
||||
Article::update(&connection, article_id, &article)
|
||||
Article::update(&data.postgres(), article_id, &article)
|
||||
} else {
|
||||
Article::create(&connection, &article)
|
||||
Article::create(&data.postgres(), &article)
|
||||
};
|
||||
RubbleResponder::Redirect("/admin/panel".into())
|
||||
}
|
||||
@ -169,17 +153,16 @@ pub fn article_save(
|
||||
pub fn article_deletion(
|
||||
id: Identity,
|
||||
article_id: web::Path<i32>,
|
||||
conn: web::Data<Pool>,
|
||||
data: web::Data<RubbleData>,
|
||||
) -> impl Responder {
|
||||
if id.identity().is_none() {
|
||||
return RubbleResponder::Redirect("/admin/login".into());
|
||||
}
|
||||
let connection = conn.get().unwrap();
|
||||
|
||||
let admin = User::find_by_username(&*connection, &id.identity().unwrap())
|
||||
let admin = User::find_by_username(&data.postgres(), &id.identity().unwrap())
|
||||
.expect("cannot found this user");
|
||||
|
||||
Article::delete(&connection, article_id.into_inner());
|
||||
Article::delete(&data.postgres(), article_id.into_inner());
|
||||
RubbleResponder::Redirect("/admin/panel".into())
|
||||
}
|
||||
|
||||
@ -187,17 +170,16 @@ pub fn article_deletion(
|
||||
pub fn change_password(
|
||||
id: Identity,
|
||||
password: web::Form<NewPassword>,
|
||||
conn: web::Data<Pool>,
|
||||
data: web::Data<RubbleData>,
|
||||
) -> impl Responder {
|
||||
if id.identity().is_none() {
|
||||
return RubbleResponder::Redirect("/admin/login".into());
|
||||
}
|
||||
let connection = conn.get().unwrap();
|
||||
|
||||
let mut admin = User::find_by_username(&*connection, &id.identity().unwrap())
|
||||
let mut admin = User::find_by_username(&data.postgres(), &id.identity().unwrap())
|
||||
.expect("cannot found this user");
|
||||
admin.password = User::password_generate(&password.password).to_string();
|
||||
User::update(&connection, admin.id, &admin);
|
||||
User::update(&data.postgres(), admin.id, &admin);
|
||||
id.forget();
|
||||
RubbleResponder::Redirect("/admin/panel".into())
|
||||
}
|
||||
@ -206,17 +188,16 @@ pub fn change_password(
|
||||
pub fn change_setting(
|
||||
id: Identity,
|
||||
setting: web::Form<Setting>,
|
||||
conn: web::Data<Pool>,
|
||||
data: web::Data<RubbleData>,
|
||||
) -> impl Responder {
|
||||
if id.identity().is_none() {
|
||||
return RubbleResponder::Redirect("/admin/login".into());
|
||||
}
|
||||
let connection = conn.get().unwrap();
|
||||
|
||||
let mut admin = User::find_by_username(&*connection, &id.identity().unwrap())
|
||||
let mut admin = User::find_by_username(&data.postgres(), &id.identity().unwrap())
|
||||
.expect("cannot found this user");
|
||||
|
||||
Setting::update(&connection, setting.name.clone(), &setting);
|
||||
Setting::update(&data.postgres(), setting.name.clone(), &setting);
|
||||
|
||||
RubbleResponder::Redirect("/admin/panel".into())
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::data::RubbleData;
|
||||
use crate::models::article::Article;
|
||||
use crate::models::setting::Setting;
|
||||
use crate::models::CRUD;
|
||||
@ -9,34 +10,26 @@ use std::sync::Arc;
|
||||
use tera::{Context, Tera};
|
||||
|
||||
#[get("/")]
|
||||
pub fn homepage(tera: web::Data<Arc<Tera>>, conn: web::Data<Pool>) -> impl Responder {
|
||||
let connection = conn.get().unwrap();
|
||||
let vec: Vec<Article> = Article::read(&connection);
|
||||
|
||||
pub fn homepage(data: web::Data<RubbleData>) -> impl Responder {
|
||||
let vec: Vec<Article> = Article::read(&data.postgres());
|
||||
let article_view: Vec<_> = vec
|
||||
.iter()
|
||||
.filter(|article| article.published == true)
|
||||
.map(ArticleView::from)
|
||||
.collect();
|
||||
|
||||
// let articles: Vec<ArticleView> = vec.iter().map(ArticleView::from).collect();
|
||||
let settings = Setting::load(&connection);
|
||||
let settings = Setting::load(&data.postgres());
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("setting", &settings);
|
||||
context.insert("articles", &article_view);
|
||||
|
||||
RubbleResponder::Html(tera.render("homepage.html", &context).unwrap())
|
||||
RubbleResponder::Html(data.render("homepage.html", &context))
|
||||
}
|
||||
|
||||
#[get("/archives/{archives_id}")]
|
||||
pub fn single_article(
|
||||
archives_id: web::Path<i32>,
|
||||
tera: web::Data<Arc<Tera>>,
|
||||
conn: web::Data<Pool>,
|
||||
) -> impl Responder {
|
||||
let connection = conn.get().unwrap();
|
||||
let article = Article::get_by_pk(&connection, archives_id.into_inner());
|
||||
pub fn single_article(archives_id: web::Path<i32>, data: web::Data<RubbleData>) -> impl Responder {
|
||||
let article = Article::get_by_pk(&data.postgres(), archives_id.into_inner());
|
||||
|
||||
if let Err(e) = article {
|
||||
return RubbleResponder::NotFound;
|
||||
@ -44,30 +37,25 @@ pub fn single_article(
|
||||
let article1 = article.unwrap();
|
||||
|
||||
if let Some(ref to) = article1.url {
|
||||
if to.len()!= 0 {
|
||||
if to.len() != 0 {
|
||||
return RubbleResponder::Redirect(format!("/{}", to));
|
||||
}
|
||||
}
|
||||
|
||||
let view = ArticleView::from(&article1);
|
||||
|
||||
let settings = Setting::load(&connection);
|
||||
let settings = Setting::load(&data.postgres());
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("setting", &settings);
|
||||
context.insert("article", &view);
|
||||
|
||||
RubbleResponder::Html(tera.render("archives.html", &context).unwrap())
|
||||
RubbleResponder::Html(data.render("archives.html", &context))
|
||||
}
|
||||
|
||||
#[get("/{url}")]
|
||||
pub fn get_article_by_url(
|
||||
url: web::Path<String>,
|
||||
tera: web::Data<Arc<Tera>>,
|
||||
conn: web::Data<Pool>,
|
||||
) -> impl Responder {
|
||||
let connection = conn.get().unwrap();
|
||||
let article = Article::find_by_url(&connection, &url.into_inner());
|
||||
pub fn get_article_by_url(url: web::Path<String>, data: web::Data<RubbleData>) -> impl Responder {
|
||||
let article = Article::find_by_url(&data.postgres(), &url.into_inner());
|
||||
|
||||
if let Err(e) = article {
|
||||
return RubbleResponder::NotFound;
|
||||
@ -76,11 +64,11 @@ pub fn get_article_by_url(
|
||||
|
||||
let view = ArticleView::from(&article1);
|
||||
|
||||
let settings = Setting::load(&connection);
|
||||
let settings = Setting::load(&data.postgres());
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert("setting", &settings);
|
||||
context.insert("article", &view);
|
||||
|
||||
RubbleResponder::Html(tera.render("archives.html", &context).unwrap())
|
||||
RubbleResponder::Html(data.render("archives.html", &context))
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::data::RubbleData;
|
||||
use crate::models::{article::Article, setting::Setting, CRUD};
|
||||
use crate::pg_pool::Pool;
|
||||
use crate::view::article::ArticleView;
|
||||
@ -6,22 +7,17 @@ use rss::{Channel, ChannelBuilder, Item, ItemBuilder};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[get("/rss")]
|
||||
pub fn rss_page(conn: web::Data<Pool>) -> impl Responder {
|
||||
let connection = conn.get().unwrap();
|
||||
let articles = Article::read(&connection);
|
||||
let setting = Setting::load(&connection);
|
||||
pub fn rss_page(data: web::Data<RubbleData>) -> impl Responder {
|
||||
let articles = Article::read(&data.postgres());
|
||||
let setting = Setting::load(&data.postgres());
|
||||
|
||||
let items: Vec<Item> = articles
|
||||
.iter()
|
||||
.map(ArticleView::from)
|
||||
.map(|item| {
|
||||
let url = match item.article.url.clone() {
|
||||
Some(ref content) if content.len() != 0 => format!("{}/{}", setting.url, content),
|
||||
_ => format!("{}/archives/{}", setting.url, item.article.id),
|
||||
};
|
||||
ItemBuilder::default()
|
||||
.title(item.article.title.clone())
|
||||
.link(url)
|
||||
.link(format!("{}{}", setting.url, item.article.link()))
|
||||
.description(item.description)
|
||||
.content(item.markdown_content)
|
||||
.pub_date(item.article.publish_at.to_string())
|
||||
|
Loading…
Reference in New Issue
Block a user