main.rs 2.12 KB
Newer Older
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
1 2 3
#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
4 5 6
#[macro_use] extern crate rocket_contrib;
#[macro_use] extern crate diesel;

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
7
use rocket::State;
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
8
use rocket::http::Status;
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
9

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
10 11 12 13
use rocket_contrib::json::Json;

use trust_dns_client::client::{Client, SyncClient};
use trust_dns_client::tcp::TcpClientConnection;
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
14
use trust_dns_client::op::{DnsResponse, ResponseCode};
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
15
use trust_dns_client::rr::{DNSClass, Name, RecordType};
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
16

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
17
mod models;
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
18
mod config;
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
19 20
mod auth;
mod schema;
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
21

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
22
use models::errors::ErrorResponse;
23
use models::users::UserInfo;
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
24 25
use auth::routes::*;

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
26

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
27 28
#[database("db")]
pub struct DbConn(diesel::SqliteConnection);
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
29

30

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
31
#[get("/zones/<zone>/records")]
32 33 34 35 36 37
fn get_zone_records(
    client: State<SyncClient<TcpClientConnection>>,
    _user_info: UserInfo,
    zone: String
) -> Result<Json<Vec<models::dns::Record>>, ErrorResponse<()>> {

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
38
    // TODO: Implement FromParam for Name
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
39
    let name = Name::from_utf8(&zone).unwrap();
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
40

41
    let response: DnsResponse = client.query(&name, DNSClass::IN, RecordType::AXFR).unwrap();
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
42 43 44 45 46 47 48 49

    if response.response_code() != ResponseCode::NoError {
        return ErrorResponse::new(
            Status::NotFound,
            format!("zone {} could not be found", name.to_utf8())
        ).err()
    }

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
50
    let answers = response.answers();
51
    let mut records: Vec<_> = answers.to_vec().into_iter()
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
52
        .map(|record| models::dns::Record::from(record))
53
        .filter(|record| match record.rdata {
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
54
            models::dns::RData::NULL { .. } | models::dns::RData::DNSSEC(_) => false,
55 56 57 58 59
            _ => true,
        }).collect();

    // AXFR response ends with SOA, we remove it so it is not doubled in the response.
    records.pop();
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
60

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
61
    Ok(Json(records))
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
62 63
}

64 65
#[launch]
fn rocket() -> rocket::Rocket {
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
66
    let app_config = config::load("config.toml".into());
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
67
    println!("{:#?}", app_config);
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
68

Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
69
    let conn = TcpClientConnection::new(app_config.dns.server).unwrap();
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
70 71 72 73
    let client = SyncClient::new(conn);

    rocket::ignite()
        .manage(client)
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
74
        .manage(app_config)
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
75
        .attach(DbConn::fairing())
76
        .mount("/api/v1", routes![get_zone_records, create_auth_token, create_user])
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
77
}