zones.rs 1.48 KB
Newer Older
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
1
2
3
4
use rocket::http::Status;

use rocket_contrib::json::Json;

5
use trust_dns_client::client::ClientHandle;
6
use trust_dns_client::op::ResponseCode;
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
7
use trust_dns_client::rr::{DNSClass, RecordType};
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
8

9
use crate::{DbConn, models::dns};
10
use crate::models::errors::{ErrorResponse, make_500};
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
11
12
13
14
use crate::models::users::UserInfo;


#[get("/zones/<zone>/records")]
15
pub async fn get_zone_records(
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
16
    mut client: dns::DnsClient,
17
    conn: DbConn,
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
18
    user_info: Result<UserInfo, ErrorResponse>,
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
19
    zone: dns::AbsoluteName
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
20
) -> Result<Json<Vec<dns::Record>>, ErrorResponse> {
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
21

22
23
24
25
26
27
28
29
30
31
    let user_info = user_info?;

    if !user_info.is_admin() {
        let zone_name = zone.clone().to_string();
        conn.run(move |c| {
            dbg!(user_info.get_zone(c, &zone_name))
        }).await?;
    }

    let response = {
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
32
        let query = client.query((*zone).clone(), DNSClass::IN, RecordType::AXFR);
33
34
        query.await.map_err(make_500)?
    };
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
35
36
37
38

    if response.response_code() != ResponseCode::NoError {
        return ErrorResponse::new(
            Status::NotFound,
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
39
            format!("zone {} could not be found", *zone)
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
40
41
42
43
44
        ).err()
    }

    let answers = response.answers();
    let mut records: Vec<_> = answers.to_vec().into_iter()
45
46
47
        .map(dns::Record::from)
        .filter(|record| !matches!(record.rdata, dns::RData::NULL { .. } | dns::RData::DNSSEC(_)))
        .collect();
Gaël Berthaud-Müller's avatar
Gaël Berthaud-Müller committed
48
49
50
51
52
53

    // AXFR response ends with SOA, we remove it so it is not doubled in the response.
    records.pop();

    Ok(Json(records))
}