<commit_before>use bodyparser;
use iron::{BeforeMiddleware, IronError, IronResult, Request};
use iron::typemap::Key;
use plugin::{Pluggable, Plugin};
use serde_json::Value;

use authentication::{AuthParams, InteractiveAuth, PasswordAuthParams};
use db::get_connection;
use error::APIError;
use user::User;

/// Handles Matrix's interactive authentication protocol for all API endpoints that require it.
#[derive(Debug)]
pub struct UIAuth {
    interactive_auth: InteractiveAuth,
}

#[derive(Debug)]
pub struct AuthRequest;

impl UIAuth {
    pub fn new(interactive_auth: InteractiveAuth) -> Self {
        UIAuth {
            interactive_auth: interactive_auth,
        }
    }
}

impl BeforeMiddleware for UIAuth {
    fn before(&self, request: &mut Request) -> IronResult<()> {
        match request.get::<AuthRequest>() {
            Ok(_) => Ok(()),
            Err(error) => Err(IronError::new(error.clone(), error)),
        }
    }
}

impl Key for AuthRequest {
    type Value = User;
}

impl<'a, 'b> Plugin<Request<'a, 'b>> for AuthRequest {
    type Error = APIError;

    fn eval(request: &mut Request) -> Result<Self::Value, Self::Error> {
        let json = request
            .get::<bodyparser::Json>()
            .expect("bodyparser failed to parse")
            .expect("bodyparser did not find JSON in the body");

        debug!("checking for auth key");
        if let Some(auth_json) = json.find("auth") {
            debug!("about to call is_m_login_password");
            if is_m_login_password(auth_json) {
                debug!("about to call get_user_and_password");
                if let Some((user, password)) = get_user_and_password(auth_json) {
                    debug!("about to construct auth_params");
                    let auth_params = AuthParams::Password(PasswordAuthParams {
                        password: password,
                        user: user,
                    });

                    debug!("about to call get_connection");
                    let connection = try!(get_connection(request));

                    debug!("about to call auth_params.authenticate");
                    return auth_params.authenticate(&connection);
                }
            }
        }

        Err(APIError::unauthorized())
    }
}

fn get_user_and_password(json: &Value) -> Option<(String, String)> {
    let user = json.find("user").and_then(|user_json| user_json.as_string());
    let password = json.find("password").and_then(|password_json| password_json.as_string());

    match (user, password) {
        (Some(user), Some(password)) => Some((user.to_string(), password.to_string())),
        _ => None,
    }
}

fn is_m_login_password(json: &Value) -> bool {
    if let Some(type_string) = json.find("type").and_then(|type_json| type_json.as_string()) {
        return type_string == "m.login.password";
    }

    false
}
<commit_msg>Remove debug logging in auth middleware.<commit_after>use bodyparser;
use iron::{BeforeMiddleware, IronError, IronResult, Request};
use iron::typemap::Key;
use plugin::{Pluggable, Plugin};
use serde_json::Value;

use authentication::{AuthParams, InteractiveAuth, PasswordAuthParams};
use db::get_connection;
use error::APIError;
use user::User;

/// Handles Matrix's interactive authentication protocol for all API endpoints that require it.
#[derive(Debug)]
pub struct UIAuth {
    interactive_auth: InteractiveAuth,
}

#[derive(Debug)]
pub struct AuthRequest;

impl UIAuth {
    pub fn new(interactive_auth: InteractiveAuth) -> Self {
        UIAuth {
            interactive_auth: interactive_auth,
        }
    }
}

impl BeforeMiddleware for UIAuth {
    fn before(&self, request: &mut Request) -> IronResult<()> {
        match request.get::<AuthRequest>() {
            Ok(_) => Ok(()),
            Err(error) => Err(IronError::new(error.clone(), error)),
        }
    }
}

impl Key for AuthRequest {
    type Value = User;
}

impl<'a, 'b> Plugin<Request<'a, 'b>> for AuthRequest {
    type Error = APIError;

    fn eval(request: &mut Request) -> Result<Self::Value, Self::Error> {
        let json = request
            .get::<bodyparser::Json>()
            .expect("bodyparser failed to parse")
            .expect("bodyparser did not find JSON in the body");

        if let Some(auth_json) = json.find("auth") {
            if is_m_login_password(auth_json) {
                if let Some((user, password)) = get_user_and_password(auth_json) {
                    let auth_params = AuthParams::Password(PasswordAuthParams {
                        password: password,
                        user: user,
                    });

                    let connection = try!(get_connection(request));

                    return auth_params.authenticate(&connection);
                }
            }
        }

        Err(APIError::unauthorized())
    }
}

fn get_user_and_password(json: &Value) -> Option<(String, String)> {
    let user = json.find("user").and_then(|user_json| user_json.as_string());
    let password = json.find("password").and_then(|password_json| password_json.as_string());

    match (user, password) {
        (Some(user), Some(password)) => Some((user.to_string(), password.to_string())),
        _ => None,
    }
}

fn is_m_login_password(json: &Value) -> bool {
    if let Some(type_string) = json.find("type").and_then(|type_json| type_json.as_string()) {
        return type_string == "m.login.password";
    }

    false
}

{'fraction_non_alphanumeric': 0.1312316715542522, 'fraction_numerical': 0.0, 'mean_word_length': 2.6673387096774195, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5878655', 'n_tokens_mistral': 1588, 'n_tokens_neox': 1567, 'n_words': 367}