style(rust): Format all Rust code with rustfmt

Change-Id: Iab7e00cc26a4f9727d3ab98691ef379921a33052
Reviewed-on: https://cl.tvl.fyi/c/depot/+/5240
Tested-by: BuildkiteCI
Reviewed-by: kanepyork <rikingcoding@gmail.com>
Reviewed-by: Profpatsch <mail@profpatsch.de>
Reviewed-by: grfn <grfn@gws.fyi>
Reviewed-by: tazjin <tazjin@tvl.su>
This commit is contained in:
Vincent Ambo 2022-02-07 18:49:59 +03:00 committed by tazjin
parent 3318982f81
commit 3d8ee62087
42 changed files with 1253 additions and 876 deletions

View file

@ -28,14 +28,19 @@ fn main() {
// Otherwise ask Nix to build it and inject the result.
let output = Command::new("nix-build")
.arg("-A").arg("web.atward.indexHtml")
.arg("-A")
.arg("web.atward.indexHtml")
// ... assuming atward is at //web/atward ...
.arg("../..")
.output()
.expect(ERROR_MESSAGE);
if !output.status.success() {
eprintln!("{}\nNix output: {}", ERROR_MESSAGE, String::from_utf8_lossy(&output.stderr));
eprintln!(
"{}\nNix output: {}",
ERROR_MESSAGE,
String::from_utf8_lossy(&output.stderr)
);
return;
}

View file

@ -19,13 +19,13 @@
//! This module implements the database executor, which holds the
//! database connection and performs queries on it.
use actix::prelude::*;
use diesel::{self, sql_query};
use diesel::sql_types::Text;
use diesel::prelude::*;
use diesel::r2d2::{Pool, ConnectionManager};
use crate::models::*;
use crate::errors::{ConverseError, Result};
use crate::models::*;
use actix::prelude::*;
use diesel::prelude::*;
use diesel::r2d2::{ConnectionManager, Pool};
use diesel::sql_types::Text;
use diesel::{self, sql_query};
/// Raw PostgreSQL query used to perform full-text search on posts
/// with a supplied phrase. For now, the query language is hardcoded
@ -50,14 +50,12 @@ pub struct DbExecutor(pub Pool<ConnectionManager<PgConnection>>);
impl DbExecutor {
/// Request a list of threads.
//
// TODO(tazjin): This should support pagination.
pub fn list_threads(&self) -> Result<Vec<ThreadIndex>> {
use crate::schema::thread_index::dsl::*;
let conn = self.0.get()?;
let results = thread_index
.load::<ThreadIndex>(&conn)?;
let results = thread_index.load::<ThreadIndex>(&conn)?;
Ok(results)
}
@ -69,9 +67,7 @@ impl DbExecutor {
let conn = self.0.get()?;
let opt_user = users
.filter(email.eq(email))
.first(&conn).optional()?;
let opt_user = users.filter(email.eq(email)).first(&conn).optional()?;
if let Some(user) = opt_user {
Ok(user)
@ -93,12 +89,11 @@ impl DbExecutor {
/// Fetch a specific thread and return it with its posts.
pub fn get_thread(&self, thread_id: i32) -> Result<(Thread, Vec<SimplePost>)> {
use crate::schema::threads::dsl::*;
use crate::schema::simple_posts::dsl::id;
use crate::schema::threads::dsl::*;
let conn = self.0.get()?;
let thread_result: Thread = threads
.find(thread_id).first(&conn)?;
let thread_result: Thread = threads.find(thread_id).first(&conn)?;
let post_list = SimplePost::belonging_to(&thread_result)
.order_by(id.asc())
@ -127,8 +122,7 @@ impl DbExecutor {
/// Create a new thread.
pub fn create_thread(&self, new_thread: NewThread, post_text: String) -> Result<Thread> {
use crate::schema::threads;
use crate::schema::posts;
use crate::schema::{posts, threads};
let conn = self.0.get()?;
@ -161,20 +155,21 @@ impl DbExecutor {
let closed: bool = {
use crate::schema::threads::dsl::*;
threads.select(closed)
threads
.select(closed)
.find(new_post.thread_id)
.first(&conn)?
};
if closed {
return Err(ConverseError::ThreadClosed {
id: new_post.thread_id
})
id: new_post.thread_id,
});
}
Ok(diesel::insert_into(posts::table)
.values(&new_post)
.get_result(&conn)?)
.values(&new_post)
.get_result(&conn)?)
}
/// Search for posts.
@ -197,7 +192,6 @@ impl DbExecutor {
}
}
// Old actor implementation:
impl Actor for DbExecutor {
@ -216,9 +210,7 @@ message!(LookupOrCreateUser, Result<User>);
impl Handler<LookupOrCreateUser> for DbExecutor {
type Result = <LookupOrCreateUser as Message>::Result;
fn handle(&mut self,
_: LookupOrCreateUser,
_: &mut Self::Context) -> Self::Result {
fn handle(&mut self, _: LookupOrCreateUser, _: &mut Self::Context) -> Self::Result {
unimplemented!()
}
}
@ -238,7 +230,9 @@ impl Handler<GetThread> for DbExecutor {
/// Message used to fetch a specific post.
#[derive(Deserialize, Debug)]
pub struct GetPost { pub id: i32 }
pub struct GetPost {
pub id: i32,
}
message!(GetPost, Result<SimplePost>);
@ -296,7 +290,9 @@ impl Handler<CreatePost> for DbExecutor {
/// Message used to search for posts
#[derive(Deserialize)]
pub struct SearchPosts { pub query: String }
pub struct SearchPosts {
pub query: String,
}
message!(SearchPosts, Result<Vec<SearchResult>>);
impl Handler<SearchPosts> for DbExecutor {

View file

@ -21,17 +21,12 @@
//! are established in a similar way as was tradition in
//! `error_chain`, albeit manually.
use std::result;
use actix_web::{ResponseError, HttpResponse};
use actix_web::http::StatusCode;
use actix_web::{HttpResponse, ResponseError};
use std::result;
// Modules with foreign errors:
use actix;
use actix_web;
use askama;
use diesel;
use r2d2;
use tokio_timer;
use {actix, actix_web, askama, diesel, r2d2, tokio_timer};
pub type Result<T> = result::Result<T, ConverseError>;
pub type ConverseResult<T> = result::Result<T, ConverseError>;
@ -96,7 +91,9 @@ impl From<askama::Error> for ConverseError {
impl From<actix::MailboxError> for ConverseError {
fn from(error: actix::MailboxError) -> ConverseError {
ConverseError::Actix { error: Box::new(error) }
ConverseError::Actix {
error: Box::new(error),
}
}
}
@ -136,7 +133,7 @@ impl ResponseError for ConverseError {
.header("Location", format!("/thread/{}#post-reply", id))
.finish(),
_ => HttpResponse::build(StatusCode::INTERNAL_SERVER_ERROR)
.body(format!("An error occured: {}", self))
.body(format!("An error occured: {}", self)),
}
}
}

View file

@ -23,22 +23,22 @@
//! the tera templates stored in the `/templates` directory in the
//! project root.
use actix::prelude::*;
use actix_web::*;
use actix_web::http::Method;
use actix_web::middleware::identity::RequestIdentity;
use actix_web::middleware::{Started, Middleware};
use actix_web;
use crate::db::*;
use crate::errors::{ConverseResult, ConverseError};
use futures::Future;
use crate::errors::{ConverseError, ConverseResult};
use crate::models::*;
use crate::oidc::*;
use crate::render::*;
use actix::prelude::*;
use actix_web;
use actix_web::http::Method;
use actix_web::middleware::identity::RequestIdentity;
use actix_web::middleware::{Middleware, Started};
use actix_web::*;
use futures::Future;
use rouille::{Request, Response};
type ConverseResponse = Box<dyn Future<Item=HttpResponse, Error=ConverseError>>;
type ConverseResponse = Box<dyn Future<Item = HttpResponse, Error = ConverseError>>;
const HTML: &'static str = "text/html";
const ANONYMOUS: i32 = 1;
@ -84,23 +84,31 @@ pub fn get_user_id_rouille(_req: &Request) -> i32 {
ANONYMOUS
}
pub fn forum_thread_rouille(req: &Request, db: &DbExecutor, thread_id: i32)
-> ConverseResult<Response> {
pub fn forum_thread_rouille(
req: &Request,
db: &DbExecutor,
thread_id: i32,
) -> ConverseResult<Response> {
let user = get_user_id_rouille(&req);
let thread = db.get_thread(thread_id)?;
Ok(Response::html(thread_page(user, thread.0, thread.1)?))
}
/// This handler retrieves and displays a single forum thread.
pub fn forum_thread(_: State<AppState>,
_: HttpRequest<AppState>,
_: Path<i32>) -> ConverseResponse {
pub fn forum_thread(
_: State<AppState>,
_: HttpRequest<AppState>,
_: Path<i32>,
) -> ConverseResponse {
unimplemented!()
}
/// This handler presents the user with the "New Thread" form.
pub fn new_thread(state: State<AppState>) -> ConverseResponse {
state.renderer.send(NewThreadPage::default()).flatten()
state
.renderer
.send(NewThreadPage::default())
.flatten()
.map(|res| HttpResponse::Ok().content_type(HTML).body(res))
.responder()
}
@ -113,9 +121,9 @@ pub struct NewThreadForm {
/// This handler receives a "New thread"-form and redirects the user
/// to the new thread after creation.
pub fn submit_thread((state, input, req): (State<AppState>,
Form<NewThreadForm>,
HttpRequest<AppState>)) -> ConverseResponse {
pub fn submit_thread(
(state, input, req): (State<AppState>, Form<NewThreadForm>, HttpRequest<AppState>),
) -> ConverseResponse {
// Trim whitespace out of inputs:
let input = NewThreadForm {
title: input.title.trim().into(),
@ -124,7 +132,8 @@ pub fn submit_thread((state, input, req): (State<AppState>,
// Perform simple validation and abort here if it fails:
if input.title.is_empty() || input.post.is_empty() {
return state.renderer
return state
.renderer
.send(NewThreadPage {
alerts: vec![NEW_THREAD_LENGTH_ERR],
title: Some(input.title),
@ -147,14 +156,19 @@ pub fn submit_thread((state, input, req): (State<AppState>,
post: input.post,
};
state.db.send(msg)
state
.db
.send(msg)
.from_err()
.and_then(move |res| {
let thread = res?;
info!("Created new thread \"{}\" with ID {}", thread.title, thread.id);
info!(
"Created new thread \"{}\" with ID {}",
thread.title, thread.id
);
Ok(HttpResponse::SeeOther()
.header("Location", format!("/thread/{}", thread.id))
.finish())
.header("Location", format!("/thread/{}", thread.id))
.finish())
})
.responder()
}
@ -167,9 +181,11 @@ pub struct NewPostForm {
/// This handler receives a "Reply"-form and redirects the user to the
/// new post after creation.
pub fn reply_thread(state: State<AppState>,
input: Form<NewPostForm>,
req: HttpRequest<AppState>) -> ConverseResponse {
pub fn reply_thread(
state: State<AppState>,
input: Form<NewPostForm>,
req: HttpRequest<AppState>,
) -> ConverseResponse {
let user_id = get_user_id(&req);
let new_post = NewPost {
@ -178,14 +194,19 @@ pub fn reply_thread(state: State<AppState>,
body: input.post.trim().into(),
};
state.db.send(CreatePost(new_post))
state
.db
.send(CreatePost(new_post))
.flatten()
.from_err()
.and_then(move |post| {
info!("Posted reply {} to thread {}", post.id, post.thread_id);
Ok(HttpResponse::SeeOther()
.header("Location", format!("/thread/{}#post-{}", post.thread_id, post.id))
.finish())
.header(
"Location",
format!("/thread/{}#post-{}", post.thread_id, post.id),
)
.finish())
})
.responder()
}
@ -194,12 +215,16 @@ pub fn reply_thread(state: State<AppState>,
/// the user attempts to edit a post that they do not have access to,
/// they are currently ungracefully redirected back to the post
/// itself.
pub fn edit_form(state: State<AppState>,
req: HttpRequest<AppState>,
query: Path<GetPost>) -> ConverseResponse {
pub fn edit_form(
state: State<AppState>,
req: HttpRequest<AppState>,
query: Path<GetPost>,
) -> ConverseResponse {
let user_id = get_user_id(&req);
state.db.send(query.into_inner())
state
.db
.send(query.into_inner())
.flatten()
.from_err()
.and_then(move |post| {
@ -227,17 +252,21 @@ pub fn edit_form(state: State<AppState>,
/// This handler "executes" an edit to a post if the current user owns
/// the edited post.
pub fn edit_post(state: State<AppState>,
req: HttpRequest<AppState>,
update: Form<UpdatePost>) -> ConverseResponse {
pub fn edit_post(
state: State<AppState>,
req: HttpRequest<AppState>,
update: Form<UpdatePost>,
) -> ConverseResponse {
let user_id = get_user_id(&req);
state.db.send(GetPost { id: update.post_id })
state
.db
.send(GetPost { id: update.post_id })
.flatten()
.from_err()
.and_then(move |post| {
if user_id != 1 && post.user_id == user_id {
Ok(())
Ok(())
} else {
Err(ConverseError::PostEditForbidden {
user: user_id,
@ -247,24 +276,34 @@ pub fn edit_post(state: State<AppState>,
})
.and_then(move |_| state.db.send(update.0).from_err())
.flatten()
.map(|updated| HttpResponse::SeeOther()
.header("Location", format!("/thread/{}#post-{}",
updated.thread_id, updated.id))
.finish())
.map(|updated| {
HttpResponse::SeeOther()
.header(
"Location",
format!("/thread/{}#post-{}", updated.thread_id, updated.id),
)
.finish()
})
.responder()
}
/// This handler executes a full-text search on the forum database and
/// displays the results to the user.
pub fn search_forum(state: State<AppState>,
query: Query<SearchPosts>) -> ConverseResponse {
pub fn search_forum(state: State<AppState>, query: Query<SearchPosts>) -> ConverseResponse {
let query_string = query.query.clone();
state.db.send(query.into_inner())
state
.db
.send(query.into_inner())
.flatten()
.and_then(move |results| state.renderer.send(SearchResultPage {
results,
query: query_string,
}).from_err())
.and_then(move |results| {
state
.renderer
.send(SearchResultPage {
results,
query: query_string,
})
.from_err()
})
.flatten()
.map(|res| HttpResponse::Ok().content_type(HTML).body(res))
.responder()
@ -272,11 +311,15 @@ pub fn search_forum(state: State<AppState>,
/// This handler initiates an OIDC login.
pub fn login(state: State<AppState>) -> ConverseResponse {
state.oidc.send(GetLoginUrl)
state
.oidc
.send(GetLoginUrl)
.from_err()
.and_then(|url| Ok(HttpResponse::TemporaryRedirect()
.header("Location", url)
.finish()))
.and_then(|url| {
Ok(HttpResponse::TemporaryRedirect()
.header("Location", url)
.finish())
})
.responder()
}
@ -286,21 +329,26 @@ pub fn login(state: State<AppState>) -> ConverseResponse {
/// provider and a user lookup is performed. If a user with a matching
/// email-address is found in the database, it is logged in -
/// otherwise a new user is created.
pub fn callback(state: State<AppState>,
data: Form<CodeResponse>,
req: HttpRequest<AppState>) -> ConverseResponse {
state.oidc.send(RetrieveToken(data.0)).flatten()
pub fn callback(
state: State<AppState>,
data: Form<CodeResponse>,
req: HttpRequest<AppState>,
) -> ConverseResponse {
state
.oidc
.send(RetrieveToken(data.0))
.flatten()
.map(|author| LookupOrCreateUser {
email: author.email,
name: author.name,
})
.and_then(move |msg| state.db.send(msg).from_err()).flatten()
.and_then(move |msg| state.db.send(msg).from_err())
.flatten()
.and_then(move |user| {
info!("Completed login for user {} ({})", user.email, user.id);
req.remember(user.id.to_string());
Ok(HttpResponse::SeeOther()
.header("Location", "/")
.finish())})
Ok(HttpResponse::SeeOther().header("Location", "/").finish())
})
.responder()
}
@ -317,9 +365,7 @@ impl EmbeddedFile for App<AppState> {
fn static_file(self, path: &'static str, content: &'static [u8]) -> Self {
self.route(path, Method::GET, move |_: HttpRequest<_>| {
let mime = format!("{}", mime_guess::from_path(path).first_or_octet_stream());
HttpResponse::Ok()
.content_type(mime.as_str())
.body(content)
HttpResponse::Ok().content_type(mime.as_str()).body(content)
})
}
}
@ -327,7 +373,7 @@ impl EmbeddedFile for App<AppState> {
/// Middleware used to enforce logins unceremoniously.
pub struct RequireLogin;
impl <S> Middleware<S> for RequireLogin {
impl<S> Middleware<S> for RequireLogin {
fn start(&self, req: &HttpRequest<S>) -> actix_web::Result<Started> {
let logged_in = req.identity().is_some();
let is_oidc_req = req.path().starts_with("/oidc");
@ -336,7 +382,7 @@ impl <S> Middleware<S> for RequireLogin {
Ok(Started::Response(
HttpResponse::SeeOther()
.header("Location", "/oidc/login")
.finish()
.finish(),
))
} else {
Ok(Started::Done)

View file

@ -30,7 +30,6 @@ extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate rouille;
extern crate actix;
extern crate actix_web;
extern crate chrono;
@ -44,6 +43,7 @@ extern crate md5;
extern crate mime_guess;
extern crate r2d2;
extern crate rand;
extern crate rouille;
extern crate serde;
extern crate serde_json;
extern crate tokio;
@ -58,7 +58,7 @@ macro_rules! message {
impl Message for $t {
type Result = $r;
}
}
};
}
pub mod db;
@ -69,18 +69,18 @@ pub mod oidc;
pub mod render;
pub mod schema;
use actix::prelude::*;
use actix_web::*;
use actix_web::http::Method;
use actix_web::middleware::Logger;
use actix_web::middleware::identity::{IdentityService, CookieIdentityPolicy};
use crate::db::*;
use diesel::pg::PgConnection;
use diesel::r2d2::{ConnectionManager, Pool};
use crate::handlers::*;
use crate::oidc::OidcExecutor;
use rand::{OsRng, Rng};
use crate::render::Renderer;
use actix::prelude::*;
use actix_web::http::Method;
use actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService};
use actix_web::middleware::Logger;
use actix_web::*;
use diesel::pg::PgConnection;
use diesel::r2d2::{ConnectionManager, Pool};
use rand::{OsRng, Rng};
use std::env;
fn config(name: &str) -> String {
@ -96,16 +96,18 @@ fn start_db_executor() -> Addr<DbExecutor> {
let db_url = config("DATABASE_URL");
let manager = ConnectionManager::<PgConnection>::new(db_url);
let pool = Pool::builder().build(manager).expect("Failed to initialise DB pool");
let pool = Pool::builder()
.build(manager)
.expect("Failed to initialise DB pool");
SyncArbiter::start(2, move || DbExecutor(pool.clone()))
}
fn schedule_search_refresh(db: Addr<DbExecutor>) {
use std::thread;
use std::time::{Duration, Instant};
use tokio::prelude::*;
use tokio::timer::Interval;
use std::time::{Duration, Instant};
use std::thread;
let task = Interval::new(Instant::now(), Duration::from_secs(60))
.from_err()
@ -118,8 +120,8 @@ fn schedule_search_refresh(db: Addr<DbExecutor>) {
fn start_oidc_executor(base_url: &str) -> Addr<OidcExecutor> {
info!("Initialising OIDC integration ...");
let oidc_url = config("OIDC_DISCOVERY_URL");
let oidc_config = oidc::load_oidc(&oidc_url)
.expect("Failed to retrieve OIDC discovery document");
let oidc_config =
oidc::load_oidc(&oidc_url).expect("Failed to retrieve OIDC discovery document");
let oidc = oidc::OidcExecutor {
oidc_config,
@ -132,7 +134,7 @@ fn start_oidc_executor(base_url: &str) -> Addr<OidcExecutor> {
}
fn start_renderer() -> Addr<Renderer> {
let comrak = comrak::ComrakOptions{
let comrak = comrak::ComrakOptions {
github_pre_lang: true,
ext_strikethrough: true,
ext_table: true,
@ -143,22 +145,23 @@ fn start_renderer() -> Addr<Renderer> {
..Default::default()
};
Renderer{ comrak }.start()
Renderer { comrak }.start()
}
fn gen_session_key() -> [u8; 64] {
let mut key_bytes = [0; 64];
let mut rng = OsRng::new()
.expect("Failed to retrieve RNG for key generation");
let mut rng = OsRng::new().expect("Failed to retrieve RNG for key generation");
rng.fill_bytes(&mut key_bytes);
key_bytes
}
fn start_http_server(base_url: String,
db_addr: Addr<DbExecutor>,
oidc_addr: Addr<OidcExecutor>,
renderer_addr: Addr<Renderer>) {
fn start_http_server(
base_url: String,
db_addr: Addr<DbExecutor>,
oidc_addr: Addr<OidcExecutor>,
renderer_addr: Addr<Renderer>,
) {
info!("Initialising HTTP server ...");
let bind_host = config_default("CONVERSE_BIND_HOST", "127.0.0.1:4567");
let key = gen_session_key();
@ -175,7 +178,7 @@ fn start_http_server(base_url: String,
CookieIdentityPolicy::new(&key)
.name("converse_auth")
.path("/")
.secure(base_url.starts_with("https"))
.secure(base_url.starts_with("https")),
);
let app = App::with_state(state)
@ -183,25 +186,37 @@ fn start_http_server(base_url: String,
.middleware(identity)
.resource("/", |r| r.method(Method::GET).with(forum_index))
.resource("/thread/new", |r| r.method(Method::GET).with(new_thread))
.resource("/thread/submit", |r| r.method(Method::POST).with(submit_thread))
.resource("/thread/reply", |r| r.method(Method::POST).with(reply_thread))
.resource("/thread/submit", |r| {
r.method(Method::POST).with(submit_thread)
})
.resource("/thread/reply", |r| {
r.method(Method::POST).with(reply_thread)
})
.resource("/thread/{id}", |r| r.method(Method::GET).with(forum_thread))
.resource("/post/{id}/edit", |r| r.method(Method::GET).with(edit_form))
.resource("/post/edit", |r| r.method(Method::POST).with(edit_post))
.resource("/search", |r| r.method(Method::GET).with(search_forum))
.resource("/oidc/login", |r| r.method(Method::GET).with(login))
.resource("/oidc/callback", |r| r.method(Method::POST).with(callback))
.static_file("/static/highlight.css", include_bytes!("../static/highlight.css"))
.static_file("/static/highlight.js", include_bytes!("../static/highlight.js"))
.static_file(
"/static/highlight.css",
include_bytes!("../static/highlight.css"),
)
.static_file(
"/static/highlight.js",
include_bytes!("../static/highlight.js"),
)
.static_file("/static/styles.css", include_bytes!("../static/styles.css"));
if require_login {
app.middleware(RequireLogin)
} else {
app
}})
.bind(&bind_host).expect(&format!("Could not bind on '{}'", bind_host))
.start();
}
})
.bind(&bind_host)
.expect(&format!("Could not bind on '{}'", bind_host))
.start();
}
fn main() {

View file

@ -16,9 +16,9 @@
// along with this program. If not, see
// <https://www.gnu.org/licenses/>.
use crate::schema::{posts, simple_posts, threads, users};
use chrono::prelude::{DateTime, Utc};
use crate::schema::{users, threads, posts, simple_posts};
use diesel::sql_types::{Text, Integer};
use diesel::sql_types::{Integer, Text};
/// Represents a single user in the Converse database. Converse does
/// not handle logins itself, but rather looks them up based on the
@ -85,21 +85,21 @@ pub struct ThreadIndex {
}
#[derive(Deserialize, Insertable)]
#[table_name="threads"]
#[table_name = "threads"]
pub struct NewThread {
pub title: String,
pub user_id: i32,
}
#[derive(Deserialize, Insertable)]
#[table_name="users"]
#[table_name = "users"]
pub struct NewUser {
pub email: String,
pub name: String,
}
#[derive(Deserialize, Insertable)]
#[table_name="posts"]
#[table_name = "posts"]
pub struct NewPost {
pub thread_id: i32,
pub body: String,

View file

@ -22,12 +22,12 @@
//! Currently Converse only supports a single OIDC provider. Note that
//! this has so far only been tested with Office365.
use actix::prelude::*;
use crate::errors::*;
use actix::prelude::*;
use crimp::Request;
use curl::easy::Form;
use url::Url;
use url_serde;
use curl::easy::Form;
/// This structure represents the contents of an OIDC discovery
/// document.
@ -114,20 +114,30 @@ impl Handler<RetrieveToken> for OidcExecutor {
debug!("Received OAuth2 code, requesting access_token");
let mut form = Form::new();
form.part("client_id").contents(&self.client_id.as_bytes())
.add().expect("critical error: invalid form data");
form.part("client_id")
.contents(&self.client_id.as_bytes())
.add()
.expect("critical error: invalid form data");
form.part("client_secret").contents(&self.client_secret.as_bytes())
.add().expect("critical error: invalid form data");
form.part("client_secret")
.contents(&self.client_secret.as_bytes())
.add()
.expect("critical error: invalid form data");
form.part("grant_type").contents("authorization_code".as_bytes())
.add().expect("critical error: invalid form data");
form.part("grant_type")
.contents("authorization_code".as_bytes())
.add()
.expect("critical error: invalid form data");
form.part("code").contents(&msg.0.code.as_bytes())
.add().expect("critical error: invalid form data");
form.part("code")
.contents(&msg.0.code.as_bytes())
.add()
.expect("critical error: invalid form data");
form.part("redirect_uri").contents(&self.redirect_uri.as_bytes())
.add().expect("critical error: invalid form data");
form.part("redirect_uri")
.contents(&self.redirect_uri.as_bytes())
.add()
.expect("critical error: invalid form data");
let response = Request::post(&self.oidc_config.token_endpoint)
.user_agent(concat!("converse-", env!("CARGO_PKG_VERSION")))?
@ -142,7 +152,8 @@ impl Handler<RetrieveToken> for OidcExecutor {
.user_agent(concat!("converse-", env!("CARGO_PKG_VERSION")))?
.header("Authorization", &bearer)?
.send()?
.as_json()?.body;
.as_json()?
.body;
Ok(Author {
name: user.name,

View file

@ -20,14 +20,14 @@
//! data into whatever format is needed by the templates and rendering
//! them.
use crate::errors::*;
use crate::models::*;
use actix::prelude::*;
use askama::Template;
use crate::errors::*;
use std::fmt;
use md5;
use crate::models::*;
use chrono::prelude::{DateTime, Utc};
use comrak::{ComrakOptions, markdown_to_html};
use comrak::{markdown_to_html, ComrakOptions};
use md5;
use std::fmt;
pub struct Renderer {
pub comrak: ComrakOptions,
@ -101,7 +101,9 @@ pub enum EditingMode {
}
impl Default for EditingMode {
fn default() -> EditingMode { EditingMode::NewThread }
fn default() -> EditingMode {
EditingMode::NewThread
}
}
/// This is the template used for rendering the new thread, edit post
@ -215,19 +217,22 @@ pub fn index_page(threads: Vec<ThreadIndex>) -> Result<String> {
// Render the page of a given thread.
pub fn thread_page(user: i32, thread: Thread, posts: Vec<SimplePost>) -> Result<String> {
let posts = posts.into_iter().map(|post| {
let editable = user != 1 && post.user_id == user;
let posts = posts
.into_iter()
.map(|post| {
let editable = user != 1 && post.user_id == user;
let comrak = ComrakOptions::default(); // TODO(tazjin): cheddar
RenderablePost {
id: post.id,
body: markdown_to_html(&post.body, &comrak),
posted: FormattedDate(post.posted),
author_name: post.author_name.clone(),
author_gravatar: md5_hex(post.author_email.as_bytes()),
editable,
}
}).collect();
let comrak = ComrakOptions::default(); // TODO(tazjin): cheddar
RenderablePost {
id: post.id,
body: markdown_to_html(&post.body, &comrak),
posted: FormattedDate(post.posted),
author_name: post.author_name.clone(),
author_gravatar: md5_hex(post.author_email.as_bytes()),
editable,
}
})
.collect();
let renderable = RenderableThreadPage {
posts,

View file

@ -80,9 +80,4 @@ joinable!(posts -> users (user_id));
joinable!(threads -> users (user_id));
joinable!(simple_posts -> threads (thread_id));
allow_tables_to_appear_in_same_query!(
posts,
threads,
users,
simple_posts,
);
allow_tables_to_appear_in_same_query!(posts, threads, users, simple_posts,);