add delete route
This commit is contained in:
parent
5f18e32615
commit
bc77bb16d4
6 changed files with 124 additions and 10 deletions
12
api.yml
12
api.yml
|
@ -423,3 +423,15 @@ paths:
|
||||||
'200':
|
'200':
|
||||||
description: ''
|
description: ''
|
||||||
|
|
||||||
|
delete:
|
||||||
|
security:
|
||||||
|
- ApiToken: []
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/RecordList'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: ''
|
||||||
|
|
||||||
|
|
25
e2e/zones.py
25
e2e/zones.py
|
@ -117,7 +117,7 @@ class TestZones(unittest.TestCase):
|
||||||
type='TXT'
|
type='TXT'
|
||||||
)
|
)
|
||||||
|
|
||||||
self.api.zones_zone_records_post(zone='example.com.', record_list=RecordList(value=[old_record]))
|
self.api.zones_zone_records_post(zone='example.com.', record_list=RecordList([old_record]))
|
||||||
|
|
||||||
update_records_request = UpdateRecordsRequest(
|
update_records_request = UpdateRecordsRequest(
|
||||||
old_records=RecordList([old_record]),
|
old_records=RecordList([old_record]),
|
||||||
|
@ -133,4 +133,25 @@ class TestZones(unittest.TestCase):
|
||||||
self.assertEqual(record.text, new_record.text, msg='New record does not have the expected value')
|
self.assertEqual(record.text, new_record.text, msg='New record does not have the expected value')
|
||||||
found = True
|
found = True
|
||||||
|
|
||||||
self.assertTrue(found, msg='New record not found in zone records')
|
self.assertTrue(found, msg='Updated record not found in zone records')
|
||||||
|
|
||||||
|
def test_delete_records(self):
|
||||||
|
name = random_name('example.com.')
|
||||||
|
record = RecordTypeTXT(
|
||||||
|
_class='IN',
|
||||||
|
ttl=300,
|
||||||
|
name=name,
|
||||||
|
text=random_string(32),
|
||||||
|
type='TXT'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.api.zones_zone_records_post(zone='example.com.', record_list=RecordList([record]))
|
||||||
|
self.api.zones_zone_records_delete(zone='example.com.', record_list=RecordList([record]))
|
||||||
|
|
||||||
|
records = self.api.zones_zone_records_get(zone='example.com.')
|
||||||
|
found = False
|
||||||
|
for record in records.value:
|
||||||
|
if type(record) is RecordTypeTXT and record.name == name:
|
||||||
|
found = True
|
||||||
|
|
||||||
|
self.assertFalse(found, msg='Delete record found in zone records')
|
|
@ -11,6 +11,7 @@ pub trait RecordApi {
|
||||||
async fn get_records(&mut self, zone: dns::Name, class: dns::DNSClass) -> Result<Vec<dns::Record>, Self::Error>;
|
async fn get_records(&mut self, zone: dns::Name, class: dns::DNSClass) -> Result<Vec<dns::Record>, Self::Error>;
|
||||||
async fn add_records(&mut self, zone: dns::Name, class: dns::DNSClass, new_records: Vec<dns::Record>) -> Result<(), Self::Error>;
|
async fn add_records(&mut self, zone: dns::Name, class: dns::DNSClass, new_records: Vec<dns::Record>) -> Result<(), Self::Error>;
|
||||||
async fn update_records(&mut self, zone: dns::Name, class: dns::DNSClass, old_records: Vec<dns::Record>, new_records: Vec<dns::Record>) -> Result<(), Self::Error>;
|
async fn update_records(&mut self, zone: dns::Name, class: dns::DNSClass, old_records: Vec<dns::Record>, new_records: Vec<dns::Record>) -> Result<(), Self::Error>;
|
||||||
|
async fn delete_records(&mut self, zone: dns::Name, class: dns::DNSClass, records: Vec<dns::Record>) -> Result<(), Self::Error>;
|
||||||
// delete_records
|
// delete_records
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,9 @@ use super::client::{ClientResponse, DnsClient};
|
||||||
use super::api::{RecordApi, ZoneApi};
|
use super::api::{RecordApi, ZoneApi};
|
||||||
|
|
||||||
|
|
||||||
|
const MAX_PAYLOAD_LEN: u16 = 1232;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum DnsApiError {
|
pub enum DnsApiError {
|
||||||
ClientError(ClientError),
|
ClientError(ClientError),
|
||||||
|
@ -82,7 +85,7 @@ impl RecordApi for DnsApiClient {
|
||||||
|
|
||||||
{
|
{
|
||||||
let edns = message.edns_mut();
|
let edns = message.edns_mut();
|
||||||
edns.set_max_payload(1232);
|
edns.set_max_payload(MAX_PAYLOAD_LEN);
|
||||||
edns.set_version(0);
|
edns.set_version(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,12 +103,11 @@ impl RecordApi for DnsApiClient {
|
||||||
|
|
||||||
async fn update_records(&mut self, zone: Name, class: DNSClass, old_records: Vec<Record>, new_records: Vec<Record>) -> Result<(), Self::Error>
|
async fn update_records(&mut self, zone: Name, class: DNSClass, old_records: Vec<Record>, new_records: Vec<Record>) -> Result<(), Self::Error>
|
||||||
{
|
{
|
||||||
|
|
||||||
// Taken from trust_dns_client::op::update_message::compare_and_swap
|
// Taken from trust_dns_client::op::update_message::compare_and_swap
|
||||||
// The original function can not be used as is because it takes a RecordSet and not a Record list
|
// The original function can not be used as is because it takes a RecordSet and not a Record list
|
||||||
|
|
||||||
// for updates, the query section is used for the zone
|
// for updates, the query section is used for the zone
|
||||||
let mut zone_query: Query = Query::new();
|
let mut zone_query = Query::new();
|
||||||
zone_query.set_name(zone.clone())
|
zone_query.set_name(zone.clone())
|
||||||
.set_query_class(class)
|
.set_query_class(class)
|
||||||
.set_query_type(RecordType::SOA);
|
.set_query_type(RecordType::SOA);
|
||||||
|
@ -130,8 +132,8 @@ impl RecordApi for DnsApiClient {
|
||||||
|
|
||||||
// add the delete for the old record
|
// add the delete for the old record
|
||||||
let mut delete = old_records;
|
let mut delete = old_records;
|
||||||
// the class must be none for delete
|
|
||||||
for record in delete.iter_mut() {
|
for record in delete.iter_mut() {
|
||||||
|
// the class must be none for delete
|
||||||
record.set_dns_class(DNSClass::NONE);
|
record.set_dns_class(DNSClass::NONE);
|
||||||
// the TTL should be 0
|
// the TTL should be 0
|
||||||
record.set_ttl(0);
|
record.set_ttl(0);
|
||||||
|
@ -144,7 +146,7 @@ impl RecordApi for DnsApiClient {
|
||||||
// Extended dns
|
// Extended dns
|
||||||
{
|
{
|
||||||
let edns = message.edns_mut();
|
let edns = message.edns_mut();
|
||||||
edns.set_max_payload(1232);
|
edns.set_max_payload(MAX_PAYLOAD_LEN);
|
||||||
edns.set_version(0);
|
edns.set_version(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +161,55 @@ impl RecordApi for DnsApiClient {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn delete_records(&mut self, zone: Name, class: DNSClass, records: Vec<Record>) -> Result<(), Self::Error>
|
||||||
|
{
|
||||||
|
// for updates, the query section is used for the zone
|
||||||
|
let mut zone_query = Query::new();
|
||||||
|
zone_query.set_name(zone.clone())
|
||||||
|
.set_query_class(class)
|
||||||
|
.set_query_type(RecordType::SOA);
|
||||||
|
|
||||||
|
let mut message: Message = Message::new();
|
||||||
|
|
||||||
|
// build the message
|
||||||
|
// TODO: set random / time based id
|
||||||
|
message
|
||||||
|
.set_id(0)
|
||||||
|
.set_message_type(MessageType::Query)
|
||||||
|
.set_op_code(OpCode::Update)
|
||||||
|
.set_recursion_desired(false);
|
||||||
|
message.add_zone(zone_query);
|
||||||
|
|
||||||
|
let mut delete = records;
|
||||||
|
|
||||||
|
for record in delete.iter_mut() {
|
||||||
|
// the class must be none for delete
|
||||||
|
record.set_dns_class(DNSClass::NONE);
|
||||||
|
// the TTL should be 0
|
||||||
|
record.set_ttl(0);
|
||||||
|
}
|
||||||
|
message.add_updates(delete);
|
||||||
|
|
||||||
|
// Extended dns
|
||||||
|
{
|
||||||
|
let edns = message.edns_mut();
|
||||||
|
edns.set_max_payload(MAX_PAYLOAD_LEN);
|
||||||
|
edns.set_version(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let response = ClientResponse(self.client.send(message)).await.map_err(|e| DnsApiError::ClientError(e))?;
|
||||||
|
|
||||||
|
if response.response_code() != ResponseCode::NoError {
|
||||||
|
return Err(DnsApiError::ResponceNotOk {
|
||||||
|
code: response.response_code(),
|
||||||
|
zone: zone,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,11 @@ async fn rocket() -> rocket::Rocket {
|
||||||
get_zone_records,
|
get_zone_records,
|
||||||
create_zone_records,
|
create_zone_records,
|
||||||
update_zone_records,
|
update_zone_records,
|
||||||
|
delete_zone_records,
|
||||||
get_zones,
|
get_zones,
|
||||||
create_zone,
|
create_zone,
|
||||||
add_member_to_zone,
|
add_member_to_zone,
|
||||||
create_auth_token,
|
create_auth_token,
|
||||||
create_user
|
create_user,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,6 @@ pub async fn create_zone_records(
|
||||||
}
|
}
|
||||||
}).await?;
|
}).await?;
|
||||||
|
|
||||||
|
|
||||||
let mut dns_api = DnsApiClient::new(client);
|
let mut dns_api = DnsApiClient::new(client);
|
||||||
|
|
||||||
dns_api.add_records(
|
dns_api.add_records(
|
||||||
|
@ -90,7 +89,6 @@ pub async fn update_zone_records(
|
||||||
}
|
}
|
||||||
}).await?;
|
}).await?;
|
||||||
|
|
||||||
|
|
||||||
let mut dns_api = DnsApiClient::new(client);
|
let mut dns_api = DnsApiClient::new(client);
|
||||||
|
|
||||||
dns_api.update_records(
|
dns_api.update_records(
|
||||||
|
@ -103,6 +101,36 @@ pub async fn update_zone_records(
|
||||||
return Ok(Json(()));
|
return Ok(Json(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[delete("/zones/<zone>/records", data = "<records>")]
|
||||||
|
pub async fn delete_zone_records(
|
||||||
|
client: DnsClient,
|
||||||
|
conn: DbConn,
|
||||||
|
user_info: Result<models::UserInfo, models::ErrorResponse>,
|
||||||
|
zone: models::AbsoluteName,
|
||||||
|
records: Json<models::RecordList>
|
||||||
|
) -> Result<Json<()>, models::ErrorResponse> {
|
||||||
|
|
||||||
|
let user_info = user_info?;
|
||||||
|
let zone_name = zone.to_utf8();
|
||||||
|
|
||||||
|
conn.run(move |c| {
|
||||||
|
if user_info.is_admin() {
|
||||||
|
models::Zone::get_by_name(c, &zone_name)
|
||||||
|
} else {
|
||||||
|
user_info.get_zone(c, &zone_name)
|
||||||
|
}
|
||||||
|
}).await?;
|
||||||
|
|
||||||
|
let mut dns_api = DnsApiClient::new(client);
|
||||||
|
|
||||||
|
dns_api.delete_records(
|
||||||
|
zone.clone(),
|
||||||
|
models::DNSClass::IN.into(),
|
||||||
|
records.into_inner().try_into_dns_type(zone.into_inner(), models::DNSClass::IN.into())?
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
return Ok(Json(()));
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/zones")]
|
#[get("/zones")]
|
||||||
pub async fn get_zones(
|
pub async fn get_zones(
|
||||||
|
|
Loading…
Reference in a new issue