tokens, ttl update
This commit is contained in:
parent
97d0a13165
commit
2dbb759b14
@ -25,7 +25,7 @@ function parseRecordLine(line: string, index: number, lines: string[]): DNSRecor
|
||||
actualLine = clean;
|
||||
}
|
||||
|
||||
const split = actualLine.split(' ');
|
||||
const split = actualLine.replace(/"\s"/g, '').split(' ');
|
||||
if (split[0] === 'IN' && split[1] === 'NS') {
|
||||
return {
|
||||
name: '',
|
||||
|
@ -27,6 +27,7 @@ function createSOAString(record: SOARecord, padI: number, padJ: number): string[
|
||||
export function createZoneFile(zone: DNSZone, preferredLineLength = 120): string[] {
|
||||
const file: string[] = [];
|
||||
file.push(`$TTL ${zone.ttl}`);
|
||||
file.push(`; GENERATED BY icy-dyndns`);
|
||||
|
||||
let longestName = 0;
|
||||
let longestType = 0;
|
||||
@ -57,6 +58,8 @@ export function createZoneFile(zone: DNSZone, preferredLineLength = 120): string
|
||||
file.push(`$INCLUDE ${include}`);
|
||||
});
|
||||
|
||||
file.push('');
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
93
src/index.ts
93
src/index.ts
@ -1,11 +1,11 @@
|
||||
import express, { ErrorRequestHandler, NextFunction, Request, Response } from 'express';
|
||||
import express, { ErrorRequestHandler, NextFunction, Request, RequestHandler, Response } from 'express';
|
||||
import 'express-async-errors';
|
||||
import path from 'path';
|
||||
import { DNSCache } from './dns/cache';
|
||||
import { DNSRecordType } from './dns/records';
|
||||
import { createZoneFile } from './dns/writer';
|
||||
import { fromRequest } from './ip/from-request';
|
||||
import { CachedZone, DNSRecord } from './models/interfaces';
|
||||
import { CachedZone } from './models/interfaces';
|
||||
|
||||
const port = parseInt(process.env.PORT || '9129', 10);
|
||||
const dir = process.env.ZONEFILES || '.';
|
||||
@ -16,11 +16,14 @@ const api = express.Router();
|
||||
app.use(express.json());
|
||||
|
||||
const cache = new DNSCache();
|
||||
const weHave = ['lunasqu.ee'];
|
||||
const authentic: {[x: string]: string} = {
|
||||
'testing-token-auth-aaaa': 'lunasqu.ee',
|
||||
'aaa': 'lol'
|
||||
};
|
||||
|
||||
async function getOrLoad(domain: string): Promise<CachedZone> {
|
||||
if (!cache.has(domain)) {
|
||||
if (!weHave.includes(domain)) {
|
||||
if (!Object.values(authentic).includes(domain)) {
|
||||
throw new Error('Invalid domain.');
|
||||
}
|
||||
return cache.load(domain, path.resolve(dir, `${domain}.zone`));
|
||||
@ -35,13 +38,43 @@ async function getOrLoad(domain: string): Promise<CachedZone> {
|
||||
return get;
|
||||
}
|
||||
|
||||
api.get('/records/:domain/download', async (req, res) => {
|
||||
const domain = req.params.domain;
|
||||
const cached = await getOrLoad(domain);
|
||||
res.send(createZoneFile(cached.zone).join('\n'));
|
||||
api.use((req, res, next) => {
|
||||
const authHeader = req.get('authorization');
|
||||
if (!authHeader) {
|
||||
res.status(400).json({ success: false, message: 'Missing Authorization header' });
|
||||
return;
|
||||
}
|
||||
|
||||
const parts = authHeader.split(' ');
|
||||
if (parts[0].toLowerCase() !== 'bearer') {
|
||||
res.status(400).json({ success: false, message: 'Invalid Authorization header' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parts[1] || !authentic[parts[1]]) {
|
||||
res.status(401).json({ success: false, message: 'Unauthorized' });
|
||||
return;
|
||||
}
|
||||
|
||||
res.locals.token = parts[1];
|
||||
next();
|
||||
});
|
||||
|
||||
api.get('/records/:domain', async (req, res) => {
|
||||
const domainAuthorization: RequestHandler = (req, res, next) => {
|
||||
if (!req.params.domain || !res.locals.token) {
|
||||
next(new Error('Unexpected bad request'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (authentic[res.locals.token] !== req.params.domain) {
|
||||
res.status(401).json({ success: false, message: 'Unauthorized access to domain' });
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
api.get('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
||||
const domain = req.params.domain;
|
||||
const cached = await getOrLoad(domain);
|
||||
|
||||
@ -79,10 +112,10 @@ api.get('/records/:domain', async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
res.json(cached.zone);
|
||||
res.json(cached.zone.records);
|
||||
});
|
||||
|
||||
api.post('/records/:domain', async (req, res) => {
|
||||
api.post('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
||||
const domain = req.params.domain;
|
||||
const index = parseInt(req.body.index, 10);
|
||||
const setters = req.body.record;
|
||||
@ -122,7 +155,7 @@ api.post('/records/:domain', async (req, res) => {
|
||||
res.json({ success: true, message: 'Record changed successfully.', record });
|
||||
});
|
||||
|
||||
api.delete('/records/:domain', async (req, res) => {
|
||||
api.delete('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
||||
const domain = req.params.domain;
|
||||
const index = parseInt(req.body.index, 10);
|
||||
|
||||
@ -143,7 +176,7 @@ api.delete('/records/:domain', async (req, res) => {
|
||||
res.json({ success: true, message: 'Record deleted successfully.', record });
|
||||
});
|
||||
|
||||
api.put('/records/:domain', async (req, res) => {
|
||||
api.put('/zone/records/:domain', domainAuthorization, async (req, res) => {
|
||||
const domain = req.params.domain;
|
||||
const setter = req.body.record;
|
||||
|
||||
@ -172,13 +205,45 @@ api.put('/records/:domain', async (req, res) => {
|
||||
const cached = await getOrLoad(domain);
|
||||
const { zone } = cached;
|
||||
const newRecord = { name, type: upperType, value };
|
||||
|
||||
zone.records.push(newRecord);
|
||||
|
||||
await cache.update(domain, cached);
|
||||
res.status(201).json({ success: true, message: 'Record added.', record: newRecord });
|
||||
});
|
||||
|
||||
api.post('/dyndns/:domain', async (req, res) => {
|
||||
api.get('/zone/:domain/download', domainAuthorization, async (req, res) => {
|
||||
const domain = req.params.domain;
|
||||
const cached = await getOrLoad(domain);
|
||||
res.send(createZoneFile(cached.zone).join('\n'));
|
||||
});
|
||||
|
||||
api.get('/zone/:domain', domainAuthorization, async (req, res) => {
|
||||
const domain = req.params.domain;
|
||||
const cached = await getOrLoad(domain);
|
||||
res.json(cached.zone);
|
||||
});
|
||||
|
||||
api.post('/zone/:domain', domainAuthorization, async (req, res) => {
|
||||
const domain = req.params.domain;
|
||||
const cached = await getOrLoad(domain);
|
||||
|
||||
if (!req.body.ttl) {
|
||||
res.json({ success: true, message: 'Nothing was changed.' });
|
||||
return;
|
||||
}
|
||||
|
||||
const numTTL = parseInt(req.body.TTL, 10);
|
||||
if (!isNaN(numTTL)) {
|
||||
cached.zone.ttl = numTTL;
|
||||
}
|
||||
|
||||
await cache.update(domain, cached);
|
||||
|
||||
res.json({ success: true, message: 'TTL changed successfully.', ttl: cached.zone.ttl });
|
||||
});
|
||||
|
||||
api.post('/dyndns/:domain', domainAuthorization, async (req, res) => {
|
||||
const domain = req.params.domain;
|
||||
const subdomain = req.body.subdomain || '@';
|
||||
const waitPartial = req.body.dualRequest === true;
|
||||
|
Reference in New Issue
Block a user