summaryrefslogtreecommitdiff
path: root/src/server.rs
blob: f34489fc396e87c75df5c909b63484ed8726f9cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
extern crate iron_sessionstorage;
use iron_sessionstorage::traits::*;
use iron_sessionstorage::SessionStorage;
use iron_sessionstorage::backends::SignedCookieBackend;
use iron::status;
use iron::modifiers::Header;
use iron::headers::ContentType;
use iron::{Iron, IronError, Request, IronResult, Response, Chain, Listening};
use iron::error::{HttpResult};
use router::Router;
use systemd::unit;
use systemd::journal;
use render;
use staticfile::Static;
use regex::Regex;

struct Login {
    user: String,
}

impl iron_sessionstorage::Value for Login {
    fn get_key() -> &'static str {
        "login"
    }
    fn into_raw(self) -> String {
        self.user
    }
    fn from_raw(v: String) -> Option<Self> {
        Some(Login{ user: v })
    }
}

fn overview(r: &mut Request) -> IronResult<Response> {
    let mut _value = try!(r.session().get::<Login>());

    let units = unit::get_units("*").unwrap();

    let sections = ["service", "timer", "socket", "target", "slice", "mount",
                    "path"];
    let units_by_section = sections.iter().map(|&s| {
        (s.to_owned(),
         units.iter().filter(|&u| &u.type_ == s).collect::<Vec<&unit::Unit>>())
    }).collect::<Vec<_>>();

    // let res = Ok(Response::with((status::Ok,
    //                              Header(ContentType::html()),
    //                              render_message(&format!("Hello, {} ({})",
    //                                                      name,
    //                                                      session_value.0),
    //                                             &units))));

    // info!("Updating session value. Current value: {}", session_value.0);
    // session_value.0.push('a');
    // try!(r.session().set(session_value));
    Ok(Response::with((status::Ok,
                       Header(ContentType::html()),
                       render::system_status(&units_by_section))))
}

fn journal(r: &mut Request) -> IronResult<Response> {
    let unit = iexpect!(r.extensions
                        .get::<Router>()
                        .unwrap()
                        .find("unit"), status::BadRequest);
    let re = Regex::new(r"[-_\w\d]*").unwrap();
    if !re.is_match(unit) {
        return Ok(Response::with(
            (status::BadRequest,
             format!("Unit ({}) does not match {}",
                     unit, re))));
    }
    Ok(Response::with((status::Ok,
                       itry!(journal::get_log(unit, 100)))))
}

fn unit_status(r: &mut Request) -> IronResult<Response> {
    let unit_name = iexpect!(r.extensions
                             .get::<Router>()
                             .unwrap()
                             .find("unit"), status::BadRequest);
    let re = Regex::new(r"[-_\w\d]*").unwrap();
    if !re.is_match(unit_name) {
        return Ok(Response::with(
            (status::BadRequest,
             format!("Unit ({}) does not match {}",
                     unit_name, re))));
    }
    let ref unit = itry!(unit::get_units(unit_name))[0];
    let log = itry!(journal::get_log(unit_name, 15));
    Ok(Response::with((status::Ok,
                       Header(ContentType::html()),
                       render::unit_status(&unit, &log))))
}

fn login(r: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok,
                       Header(ContentType::html()),
                      render::login_page())))
}

fn login_submit(r: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok,
                       Header(ContentType::plaintext()),
                       "login")))
    // TODO: Need this to get params:
    // https://github.com/iron/params
}

pub fn serve(port: u16) -> HttpResult<Listening> {
    let secret = b"secret2".to_vec();
    let router = router!(
        root: get "/" => overview,
        login: get "/login" => login,
        login_submit: post "/login" => login_submit,
        details: get "/status/:unit" => unit_status,
        journal: get "/journal/:unit" => journal,
        css: get "/static/main.css" => Static::new(""),
    );
    let mut chain = Chain::new(router);
    chain.link_around(SessionStorage::new(SignedCookieBackend::new(secret)));
    let bind_address = format!("{}:{}", "::", port);
    Iron::new(chain).http(bind_address.as_str())
}