nomilo/src/routes/zones.rs

155 lines
4.3 KiB
Rust
Raw Normal View History

2021-07-01 18:45:49 +00:00
use std::convert::TryInto;
2022-03-03 23:44:29 +00:00
use serde_json::json;
2021-05-02 13:56:42 +00:00
use rocket::Response;
2021-04-02 20:09:51 +00:00
use rocket::http::Status;
use rocket_contrib::json::Json;
2022-03-04 16:17:15 +00:00
use crate::DbConn;
use crate::models;
use crate::dns;
use crate::dns::{RecordApi, ZoneApi};
2021-04-02 20:09:51 +00:00
#[get("/zones/<zone>/records")]
pub async fn get_zone_records(
client: dns::client::DnsClient,
2021-04-05 22:56:15 +00:00
conn: DbConn,
2022-03-04 16:17:15 +00:00
user_info: Result<models::UserInfo, models::ErrorResponse>,
zone: models::AbsoluteName
) -> Result<Json<Vec<models::Record>>, models::ErrorResponse> {
2021-04-02 20:09:51 +00:00
2021-04-05 22:56:15 +00:00
let user_info = user_info?;
2021-05-02 15:19:32 +00:00
let zone_name = zone.to_string();
2021-04-05 22:56:15 +00:00
2021-05-02 15:19:32 +00:00
conn.run(move |c| {
if user_info.is_admin() {
2022-03-04 16:17:15 +00:00
models::Zone::get_by_name(c, &zone_name)
2021-05-02 15:19:32 +00:00
} else {
2021-05-02 13:56:42 +00:00
user_info.get_zone(c, &zone_name)
2021-05-02 15:19:32 +00:00
}
}).await?;
2021-04-05 22:56:15 +00:00
let mut dns_api = dns::DnsApiClient::new(client);
let dns_records = dns_api.get_records(zone.clone(), dns::DNSClass::IN).await?;
let records: Vec<_> = dns_records.into_iter().map(models::Record::from).collect();
2021-04-02 20:09:51 +00:00
Ok(Json(records))
}
2021-05-02 13:56:42 +00:00
2021-07-01 18:45:49 +00:00
#[post("/zones/<zone>/records", data = "<new_records>")]
pub async fn create_zone_records(
client: dns::client::DnsClient,
2021-07-01 18:45:49 +00:00
conn: DbConn,
2022-03-04 16:17:15 +00:00
user_info: Result<models::UserInfo, models::ErrorResponse>,
zone: models::AbsoluteName,
new_records: Json<Vec<models::Record>>
) -> Result<Json<()>, models::ErrorResponse> {
2021-07-01 18:45:49 +00:00
let user_info = user_info?;
let zone_name = zone.to_utf8();
conn.run(move |c| {
if user_info.is_admin() {
2022-03-04 16:17:15 +00:00
models::Zone::get_by_name(c, &zone_name)
2021-07-01 18:45:49 +00:00
} else {
user_info.get_zone(c, &zone_name)
}
}).await?;
2022-03-03 23:44:29 +00:00
2021-07-01 18:45:49 +00:00
// TODO: What about relative names (also in cnames and stuff)
2022-03-03 23:44:29 +00:00
let mut bad_records = Vec::new();
2022-03-04 16:17:15 +00:00
let mut records: Vec<dns::Record> = Vec::new();
2022-03-03 23:44:29 +00:00
for record in new_records.into_inner().into_iter() {
let this_record = record.clone();
if let Ok(record) = record.try_into() {
records.push(record);
} else {
bad_records.push(this_record.clone());
}
}
2021-07-01 18:45:49 +00:00
2022-03-03 23:44:29 +00:00
if !bad_records.is_empty() {
2022-03-04 16:17:15 +00:00
return models::ErrorResponse::new(
2022-03-03 23:44:29 +00:00
Status::BadRequest,
"Record list contains records that could not been parsed into DNS records".into()
).with_details(
json!({
"zone_name": zone.to_utf8(),
"records": bad_records
})
).err();
}
let mut dns_api = dns::DnsApiClient::new(client);
dns_api.add_records(zone.clone(), dns::DNSClass::IN, records).await?;
return Ok(Json(()));
2021-07-01 18:45:49 +00:00
}
2021-05-02 13:56:42 +00:00
#[get("/zones")]
pub async fn get_zones(
conn: DbConn,
2022-03-04 16:17:15 +00:00
user_info: Result<models::UserInfo, models::ErrorResponse>,
) -> Result<Json<Vec<models::Zone>>, models::ErrorResponse> {
2021-05-02 13:56:42 +00:00
let user_info = user_info?;
let zones = conn.run(move |c| {
if user_info.is_admin() {
2022-03-04 16:17:15 +00:00
models::Zone::get_all(c)
2021-05-02 13:56:42 +00:00
} else {
user_info.get_zones(c)
}
}).await?;
Ok(Json(zones))
}
2021-05-02 15:19:32 +00:00
#[post("/zones", data = "<zone_request>")]
pub async fn create_zone(
conn: DbConn,
client: dns::client::DnsClient,
2022-03-04 16:17:15 +00:00
user_info: Result<models::UserInfo, models::ErrorResponse>,
zone_request: Json<models::CreateZoneRequest>,
) -> Result<Json<models::Zone>, models::ErrorResponse> {
2021-05-02 15:19:32 +00:00
user_info?.check_admin()?;
let mut dns_api = dns::DnsApiClient::new(client);
dns_api.zone_exists(zone_request.name.clone(), dns::DNSClass::IN).await?;
2021-05-02 15:19:32 +00:00
let zone = conn.run(move |c| {
2022-03-04 16:17:15 +00:00
models::Zone::create_zone(c, zone_request.into_inner())
2021-05-02 15:19:32 +00:00
}).await?;
Ok(Json(zone))
}
2021-05-02 13:56:42 +00:00
#[post("/zones/<zone>/members", data = "<zone_member_request>")]
pub async fn add_member_to_zone<'r>(
conn: DbConn,
2022-03-04 16:17:15 +00:00
zone: models::AbsoluteName,
user_info: Result<models::UserInfo, models::ErrorResponse>,
zone_member_request: Json<models::AddZoneMemberRequest>
) -> Result<Response<'r>, models::ErrorResponse> {
2021-05-02 13:56:42 +00:00
let user_info = user_info?;
let zone_name = zone.to_utf8();
conn.run(move |c| {
let zone = if user_info.is_admin() {
2022-03-04 16:17:15 +00:00
models::Zone::get_by_name(c, &zone_name)
2021-05-02 13:56:42 +00:00
} else {
user_info.get_zone(c, &zone_name)
}?;
2022-03-04 16:17:15 +00:00
let new_member = models::LocalUser::get_user_by_uuid(c, &zone_member_request.id)?;
2021-05-02 13:56:42 +00:00
zone.add_member(&c, &new_member)
}).await?;
Response::build()
.status(Status::Created) // TODO: change this?
.ok()
}