More route refactoring.

This commit is contained in:
Rasmus Kaj 2022-02-17 22:28:18 +01:00
parent ceacabb30f
commit 63acefb97c
4 changed files with 108 additions and 52 deletions

View File

@ -12,7 +12,8 @@ use warp::filters::method::get;
use warp::filters::BoxedFilter;
use warp::path::{end, path};
use warp::query::query;
use warp::{reply, Filter, Reply};
use warp::reply::{json, Json};
use warp::{Filter, Reply};
pub fn routes(s: BoxedFilter<(Context,)>) -> BoxedFilter<(impl Reply,)> {
end()
@ -20,26 +21,26 @@ pub fn routes(s: BoxedFilter<(Context,)>) -> BoxedFilter<(impl Reply,)> {
.and(s.clone())
.and(query())
.map(auto_complete_any)
.map(wrap)
.or(path("tag")
.and(get())
.and(s.clone())
.and(query())
.map(auto_complete_tag)
.map(wrap))
.map(auto_complete_tag))
.unify()
.or(path("person")
.and(get())
.and(s)
.and(query())
.map(auto_complete_person)
.map(wrap))
.map(auto_complete_person))
.unify()
.map(wrap)
.boxed()
}
sql_function!(fn lower(string: Text) -> Text);
sql_function!(fn strpos(string: Text, substring: Text) -> Integer);
pub fn auto_complete_any(context: Context, query: AcQ) -> Result<impl Reply> {
pub fn auto_complete_any(context: Context, query: AcQ) -> Result<Json> {
let qq = query.q.to_lowercase();
let tpos = strpos(lower(t::tag_name), &qq);
@ -115,12 +116,10 @@ pub fn auto_complete_any(context: Context, query: AcQ) -> Result<impl Reply> {
.map(|(t, s, p)| (SearchTag { k: 'l', t, s }, p))
});
tags.sort_by(|a, b| a.1.cmp(&b.1).then_with(|| a.0.cmp(&b.0)));
Ok(reply::json(
&tags.iter().map(|(t, _)| t).collect::<Vec<_>>(),
))
Ok(json(&tags.iter().map(|(t, _)| t).collect::<Vec<_>>()))
}
pub fn auto_complete_tag(context: Context, query: AcQ) -> Result<impl Reply> {
pub fn auto_complete_tag(context: Context, query: AcQ) -> Result<Json> {
use crate::schema::tags::dsl::{tag_name, tags};
let tpos = strpos(lower(tag_name), query.q.to_lowercase());
let q = tags
@ -128,13 +127,10 @@ pub fn auto_complete_tag(context: Context, query: AcQ) -> Result<impl Reply> {
.filter((&tpos).gt(0))
.order((&tpos, tag_name))
.limit(10);
Ok(reply::json(&q.load::<String>(&context.db()?)?))
Ok(json(&q.load::<String>(&context.db()?)?))
}
pub fn auto_complete_person(
context: Context,
query: AcQ,
) -> Result<impl Reply> {
pub fn auto_complete_person(context: Context, query: AcQ) -> Result<Json> {
use crate::schema::people::dsl::{people, person_name};
let mpos = strpos(lower(person_name), query.q.to_lowercase());
let q = people
@ -142,7 +138,7 @@ pub fn auto_complete_person(
.filter((&mpos).gt(0))
.order((&mpos, person_name))
.limit(10);
Ok(reply::json(&q.load::<String>(&context.db()?)?))
Ok(json(&q.load::<String>(&context.db()?)?))
}
#[derive(Deserialize)]

View File

@ -1,24 +1,39 @@
use super::{BuilderExt, Context, RenderRucte, Result};
use super::{wrap, BuilderExt, Context, ContextFilter, RenderRucte, Result};
use crate::templates;
use diesel::prelude::*;
use log::info;
use serde::Deserialize;
use warp::filters::BoxedFilter;
use warp::http::header;
use warp::http::response::Builder;
use warp::path::end;
use warp::query::query;
use warp::reply::Response;
use warp::{body, get, path, post, Filter};
pub fn get_login(context: Context, param: NextQ) -> Result<Response> {
pub fn routes(s: ContextFilter) -> BoxedFilter<(Response,)> {
let s = move || s.clone();
let get_form = get().and(s()).and(query()).map(get_login);
let post_form = post().and(s()).and(body::form()).map(post_login);
let login = path("login")
.and(end())
.and(get_form.or(post_form).unify().map(wrap));
let logout = path("logout").and(end()).and(s()).map(logout);
login.or(logout).unify().boxed()
}
fn get_login(context: Context, param: NextQ) -> Result<Response> {
info!("Got request for login form. Param: {:?}", param);
let next = sanitize_next(param.next.as_ref().map(AsRef::as_ref));
Ok(Builder::new().html(|o| templates::login(o, &context, next, None))?)
}
#[derive(Debug, Default, Deserialize)]
pub struct NextQ {
struct NextQ {
next: Option<String>,
}
pub fn post_login(context: Context, form: LoginForm) -> Result<Response> {
fn post_login(context: Context, form: LoginForm) -> Result<Response> {
let next = sanitize_next(form.next.as_ref().map(AsRef::as_ref));
if let Some(user) = form.validate(&*context.db()?) {
let token = context.make_token(&user)?;
@ -105,7 +120,7 @@ fn test_sanitize_good_2() {
assert_eq!(Some("/2017/7/15"), sanitize_next(Some("/2017/7/15")))
}
pub fn logout(_context: Context) -> Response {
fn logout(_context: Context) -> Response {
Builder::new()
.header(
header::SET_COOKIE,

View File

@ -21,7 +21,7 @@ pub use self::photolink::PhotoLink;
use self::render_ructe::BuilderExt;
use self::search::*;
use self::views_by_category::*;
use self::views_by_date::*;
use self::views_by_date::monthname;
use super::{CacheOpt, DbOpt, DirOpt};
use crate::adm::result::Error;
use crate::fetch_places::OverpassOpt;
@ -78,7 +78,7 @@ pub async fn run(args: &Args) -> Result<(), Error> {
let s = move || session_filter.clone();
use warp::filters::query::query;
use warp::path::{end, param};
use warp::{body, get, path, post};
use warp::{get, path};
let static_routes = path("static")
.and(path::tail())
.and(get())
@ -87,29 +87,17 @@ pub async fn run(args: &Args) -> Result<(), Error> {
#[rustfmt::skip]
let routes = warp::any()
.and(static_routes)
.or(path("login").and(end()).and(
get().and(s()).and(query()).map(login::get_login)
.or(post().and(s()).and(body::form()).map(login::post_login))
.unify()
.map(wrap)))
.or(path("logout").and(end()).and(s()).map(login::logout))
.or(end().and(get()).and(s()).map(all_years).map(wrap))
.or(login::routes(s()))
.or(path("img").and(
param().and(end()).and(get()).and(s()).map(photo_details)
.or(param().and(end()).and(get()).and(s()).then(image::show_image))
.unify()
.map(wrap)))
.or(path("0").and(end()).and(get()).and(s()).map(all_null_date).map(wrap))
.or(param().and(end()).and(get()).and(s()).map(months_in_year).map(wrap))
.or(param().and(param()).and(end()).and(get()).and(s()).map(days_in_month).map(wrap))
.or(param().and(param()).and(param()).and(end()).and(query()).and(get()).and(s()).map(all_for_day).map(wrap))
.or(views_by_date::routes(s()))
.or(path("person").and(person_routes(s())))
.or(path("place").and(place_routes(s())))
.or(path("tag").and(tag_routes(s())))
.or(path("random").and(end()).and(get()).and(s()).map(random_image).map(wrap))
.or(path("thisday").and(end()).and(get()).and(s()).map(on_this_day).map(wrap))
.or(path("next").and(end()).and(get()).and(s()).and(query()).map(next_image).map(wrap))
.or(path("prev").and(end()).and(get()).and(s()).and(query()).map(prev_image).map(wrap))
.or(path("ac").and(autocomplete::routes(s())))
.or(path("search").and(end()).and(get()).and(s()).and(query()).map(search).map(wrap))
.or(path("api").and(api::routes(s())))

View File

@ -1,6 +1,7 @@
use super::splitlist::links_by_time;
use super::{
redirect_to_img, Context, ImgRange, Link, PhotoLink, Result, ViewError,
redirect_to_img, wrap, Context, ContextFilter, ImgRange, Link, PhotoLink,
Result, ViewError,
};
use crate::models::{Photo, SizeTag};
use crate::templates::{self, RenderRucte};
@ -10,10 +11,70 @@ use diesel::dsl::sql;
use diesel::prelude::*;
use diesel::sql_types::{BigInt, Integer, Nullable};
use serde::Deserialize;
use warp::filters::BoxedFilter;
use warp::http::response::Builder;
use warp::path::{end, param};
use warp::query::query;
use warp::reply::Response;
use warp::{get, path, Filter};
pub fn all_years(context: Context) -> Result<Response> {
pub fn routes(s: ContextFilter) -> BoxedFilter<(Response,)> {
let s = move || s.clone();
let root = end().and(get()).and(s()).map(all_years);
let nodate = path("0").and(end()).and(get()).and(s()).map(all_null_date);
let year = param().and(end()).and(get()).and(s()).map(months_in_year);
let month = param()
.and(param())
.and(end())
.and(get())
.and(s())
.map(days_in_month);
let day = param()
.and(param())
.and(param())
.and(end())
.and(query())
.and(get())
.and(s())
.map(all_for_day);
let this = path("thisday")
.and(end())
.and(get())
.and(s())
.map(on_this_day);
let next = path("next")
.and(end())
.and(get())
.and(s())
.and(query())
.map(next_image);
let prev = path("prev")
.and(end())
.and(get())
.and(s())
.and(query())
.map(prev_image);
root.or(nodate)
.unify()
.or(year)
.unify()
.or(month)
.unify()
.or(day)
.unify()
.or(this)
.unify()
.or(next)
.unify()
.or(prev)
.unify()
.map(wrap)
.boxed()
}
fn all_years(context: Context) -> Result<Response> {
use crate::schema::photos::dsl::{date, grade};
let db = context.db()?;
let groups = Photo::query(context.is_authorized())
@ -57,7 +118,7 @@ fn start_of_year(year: i32) -> NaiveDateTime {
NaiveDate::from_ymd(year, 1, 1).and_hms(0, 0, 0)
}
pub fn months_in_year(year: i32, context: Context) -> Result<Response> {
fn months_in_year(year: i32, context: Context) -> Result<Response> {
use crate::schema::photos::dsl::{date, grade};
let title: String = format!("Photos from {}", year);
@ -123,11 +184,7 @@ fn start_of_month(year: i32, month: u32) -> NaiveDateTime {
date.and_hms(0, 0, 0)
}
pub fn days_in_month(
year: i32,
month: u32,
context: Context,
) -> Result<Response> {
fn days_in_month(year: i32, month: u32, context: Context) -> Result<Response> {
use crate::schema::photos::dsl::{date, grade};
let lpath: Vec<Link> = vec![Link::year(year)];
@ -187,7 +244,7 @@ pub fn days_in_month(
}
}
pub fn all_null_date(context: Context) -> Result<Response> {
fn all_null_date(context: Context) -> Result<Response> {
use crate::schema::photos::dsl::{date, path};
let images = Photo::query(context.is_authorized())
.filter(date.is_null())
@ -209,7 +266,7 @@ pub fn all_null_date(context: Context) -> Result<Response> {
})?)
}
pub fn all_for_day(
fn all_for_day(
year: i32,
month: u32,
day: u32,
@ -240,7 +297,7 @@ pub fn all_for_day(
}
}
pub fn on_this_day(context: Context) -> Result<Response> {
fn on_this_day(context: Context) -> Result<Response> {
use crate::schema::photos::dsl::{date, grade};
use crate::schema::positions::dsl::{
latitude, longitude, photo_id, positions,
@ -305,7 +362,7 @@ pub fn on_this_day(context: Context) -> Result<Response> {
})?)
}
pub fn next_image(context: Context, param: FromParam) -> Result<Response> {
fn next_image(context: Context, param: FromParam) -> Result<Response> {
use crate::schema::photos::dsl::{date, id};
let db = context.db()?;
let from_date = or_404!(date_of_img(&db, param.from), context);
@ -323,7 +380,7 @@ pub fn next_image(context: Context, param: FromParam) -> Result<Response> {
Ok(redirect_to_img(photo))
}
pub fn prev_image(context: Context, param: FromParam) -> Result<Response> {
fn prev_image(context: Context, param: FromParam) -> Result<Response> {
use crate::schema::photos::dsl::{date, id};
let db = context.db()?;
let from_date = or_404!(date_of_img(&db, param.from), context);
@ -342,7 +399,7 @@ pub fn prev_image(context: Context, param: FromParam) -> Result<Response> {
}
#[derive(Deserialize)]
pub struct FromParam {
struct FromParam {
from: i32,
}