delete multiple records at once
This commit is contained in:
parent
176a3f66b0
commit
cc2f4fea84
13
README.md
13
README.md
@ -88,7 +88,7 @@ Returns all of `:domain`'s DNS records or performs a search based on provided qu
|
|||||||
```
|
```
|
||||||
|
|
||||||
### `POST /zone/records/:domain`
|
### `POST /zone/records/:domain`
|
||||||
Updates a single or multiple DNS records of `:domain` at `index`.
|
Updates or marks for deletion a single or multiple DNS records of `:domain` at `index`.
|
||||||
|
|
||||||
**Body:**
|
**Body:**
|
||||||
```typescript
|
```typescript
|
||||||
@ -98,6 +98,7 @@ Updates a single or multiple DNS records of `:domain` at `index`.
|
|||||||
name?: string;
|
name?: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
|
forDeletion?: boolean;
|
||||||
} | {...}[];
|
} | {...}[];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -143,12 +144,12 @@ Creates a single or multiple new DNS records for `:domain`.
|
|||||||
```
|
```
|
||||||
|
|
||||||
### `DELETE /zone/records/:domain`
|
### `DELETE /zone/records/:domain`
|
||||||
Deletes a DNS record from `:domain` at `index`. **Warning:** Deleting an index that is not at the end of the record causes following records' indexes to shift back by one.
|
Deletes a single or multiple DNS records from `:domain` at `index`. **Warning:** Deleting an index that is not at the end of the record causes following records' indexes to shift back by one. Refresh your indexes after every addition and deletion!
|
||||||
|
|
||||||
**Body:**
|
**Body:**
|
||||||
```typescript
|
```typescript
|
||||||
{
|
{
|
||||||
index: number;
|
index: number | number[];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -157,7 +158,11 @@ Deletes a DNS record from `:domain` at `index`. **Warning:** Deleting an index t
|
|||||||
{
|
{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
message: string;
|
message: string;
|
||||||
record: DNSRecord;
|
deleted: DNSRecord[];
|
||||||
|
errors: {
|
||||||
|
message: string;
|
||||||
|
record: DNSRecord;
|
||||||
|
}[];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -107,9 +107,13 @@ export class DNSCache {
|
|||||||
throw new Error('No such cached zone file!');
|
throw new Error('No such cached zone file!');
|
||||||
}
|
}
|
||||||
|
|
||||||
zone.changed = new Date();
|
// Delete marked-for-deletion records
|
||||||
|
zone.zone.records = zone.zone.records.filter((record) => record.forDeletion !== true);
|
||||||
|
|
||||||
|
// Set new serial
|
||||||
const soa = zone.zone.records.find((record) => record.type === DNSRecordType.SOA) as SOARecord;
|
const soa = zone.zone.records.find((record) => record.type === DNSRecordType.SOA) as SOARecord;
|
||||||
soa.serial = Math.floor(Date.now() / 1000);
|
soa.serial = Math.floor(Date.now() / 1000);
|
||||||
|
zone.changed = new Date();
|
||||||
|
|
||||||
this.set(name, zone);
|
this.set(name, zone);
|
||||||
await this.save(name);
|
await this.save(name);
|
||||||
|
56
src/index.ts
56
src/index.ts
@ -107,6 +107,7 @@ api.get('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
|||||||
* name?: string;
|
* name?: string;
|
||||||
* type?: DNSRecordType;
|
* type?: DNSRecordType;
|
||||||
* value?: string;
|
* value?: string;
|
||||||
|
* forDeletion?: boolean;
|
||||||
* }[];
|
* }[];
|
||||||
*/
|
*/
|
||||||
api.post('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
api.post('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
||||||
@ -166,8 +167,18 @@ api.post('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (record.type === DNSRecordType.SOA && setter.forDeletion) {
|
||||||
|
errors.push({
|
||||||
|
message: 'Cannot delete the Start Of Authority record.',
|
||||||
|
record
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
keys.forEach((key) => {
|
keys.forEach((key) => {
|
||||||
if (record[key]) {
|
if (key === 'forDeletion') {
|
||||||
|
record.forDeletion = true;
|
||||||
|
} else if (record[key]) {
|
||||||
record[key] = setter[key];
|
record[key] = setter[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -201,23 +212,50 @@ api.post('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
|||||||
*/
|
*/
|
||||||
api.delete('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
api.delete('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
||||||
const domain = req.params.domain;
|
const domain = req.params.domain;
|
||||||
const index = parseInt(req.body.index, 10);
|
let indexes = req.body.index;
|
||||||
|
|
||||||
const cached = await getOrLoad(domain);
|
const cached = await getOrLoad(domain);
|
||||||
const { zone } = cached;
|
const { zone } = cached;
|
||||||
if (!index || isNaN(index) || !zone.records[index]) {
|
|
||||||
throw new Error('Invalid record index.');
|
if (!Array.isArray(indexes)) {
|
||||||
|
indexes = [indexes];
|
||||||
}
|
}
|
||||||
|
|
||||||
const record = zone.records[index];
|
const deleted = [];
|
||||||
if (record.type === DNSRecordType.SOA) {
|
const errors = [];
|
||||||
throw new Error('Cannot delete the Start Of Authority record.');
|
|
||||||
|
for (const number of indexes) {
|
||||||
|
const index = parseInt(number, 10);
|
||||||
|
if (index == null || isNaN(index) || !zone.records[index]) {
|
||||||
|
errors.push({
|
||||||
|
message: 'Invalid record index.',
|
||||||
|
record: { index }
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const record = zone.records[index];
|
||||||
|
if (record.type === DNSRecordType.SOA) {
|
||||||
|
errors.push({
|
||||||
|
message: 'Cannot delete the Start Of Authority record.',
|
||||||
|
record
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zone.records[index].forDeletion = true;
|
||||||
|
deleted.push(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
zone.records.splice(index, 1);
|
|
||||||
await cache.update(domain, cached);
|
await cache.update(domain, cached);
|
||||||
|
|
||||||
res.json({ success: true, message: 'Record deleted successfully.', record });
|
if (!deleted.length && errors.length) {
|
||||||
|
res.status(400).json({ success: false, message: 'Deleting record(s) failed.', deleted, errors });
|
||||||
|
} else if (deleted.length) {
|
||||||
|
res.json({ success: true, message: 'Record(s) deleted successfully.', deleted, errors });
|
||||||
|
} else {
|
||||||
|
res.json({ success: true, message: 'Nothing was deleted.', deleted, errors });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { DNSRecordType } from "../dns/records";
|
import { DNSRecordType } from "../dns/records";
|
||||||
|
|
||||||
export interface DNSRecord {
|
export interface DNSRecord {
|
||||||
[key: string]: string | number;
|
[key: string]: string | number | boolean | undefined;
|
||||||
name: string;
|
name: string;
|
||||||
type: DNSRecordType;
|
type: DNSRecordType;
|
||||||
value: string;
|
value: string;
|
||||||
|
forDeletion?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SOARecord extends DNSRecord {
|
export interface SOARecord extends DNSRecord {
|
||||||
|
Reference in New Issue
Block a user