main.rs 2.1 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

#[get("/zones/<zone>/records")]
31 32 33 34 35 36
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
37
    // TODO: Implement FromParam for Name
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
38
    let name = Name::from_utf8(&zone).unwrap();
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
39

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

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

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

fn main() {
    let app_config = config::load("config.toml".into());
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
65
    println!("{:#?}", app_config);
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
66

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

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