Add ioredis, add redis, api routes, controller, read from the actual redis

develop
Thomas Lynch 1 year ago
parent a8f0edba6f
commit edbe05bdc6
  1. 3
      .env.example
  2. 8
      api.js
  3. 75
      controllers/dns.js
  4. 79
      package-lock.json
  5. 1
      package.json
  6. 33
      pages/dns/[domain]/[zone]/[type].js
  7. 32
      pages/dns/[domain]/index.js
  8. 47
      redis.js
  9. 7
      router.js

@ -1,4 +1,7 @@
COOKIE_SECRET="changeme"
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASS=
DB_URL="mongodb://localhost:27017"
NEXT_PUBLIC_CUSTOM_BACKENDS_ENABLED="true"
CUSTOM_BACKENDS_ENABLED="true"

@ -36,6 +36,14 @@ export async function deleteDomain(body, dispatch, errorCallback, router) {
return ApiCall('/forms/domain/delete', 'POST', body, dispatch, errorCallback, router, 0.5);
}
// Dns
export async function getDnsDomain(domain, dispatch, errorCallback, router) {
return ApiCall(`/dns/${domain}.json`, 'GET', null, dispatch, errorCallback, router);
}
export async function getDnsRecords(domain, zone, dispatch, errorCallback, router) {
return ApiCall(`/dns/${domain}/${zone}.json`, 'GET', null, dispatch, errorCallback, router);
}
// Certs
export async function getCerts(dispatch, errorCallback, router) {
return ApiCall('/certs.json', 'GET', null, dispatch, errorCallback, router);

@ -0,0 +1,75 @@
const db = require('../db.js');
const redis = require('../redis.js');
const url = require('url');
const { dynamicResponse } = require('../util.js');
/**
* GET /dns/:domain
* domains page
*/
exports.dnsDomainPage = async (app, req, res) => {
if (!res.locals.user.domains.includes(req.params.domain)) {
return res.redirect('/domains');
}
const recordSetsRaw = await redis.hgetall(`${req.params.domain}.`);
const recordSets = recordSetsRaw && Object.keys(recordSetsRaw)
.map(k => {
return { [k]: JSON.parse(recordSetsRaw[k]) };
}) || [];
return app.render(req, res, `/dns/${req.params.domain}`, {
csrf: req.csrfToken(),
recordSets,
});
};
/**
* GET /dns/:domain/:zone/:type
* domains page
*/
exports.dnsRecordPage = async (app, req, res) => {
if (!res.locals.user.domains.includes(req.params.domain)) {
return res.redirect('/domains');
}
const recordSet = await redis.hget(`${req.params.domain}.`, req.params.zone);
return app.render(req, res, `/dns/${req.params.domain}/${req.params.zone}/${req.params.type}`, {
csrf: req.csrfToken(),
recordSets: [{ [req.params.zone]: recordSet||{} }],
});
};
/**
* GET /dns/:domain.json
* domains json data
*/
exports.dnsDomainJson = async (req, res) => {
if (!res.locals.user.domains.includes(req.params.domain)) {
return dynamicResponse(req, res, 403, { error: 'No permission for this domain' });
}
const recordSetsRaw = await redis.hgetall(`${req.params.domain}.`);
const recordSets = recordSetsRaw && Object.keys(recordSetsRaw)
.map(k => {
return { [k]: JSON.parse(recordSetsRaw[k]) };
}) || [];
return res.json({
csrf: req.csrfToken(),
user: res.locals.user,
recordSets,
});
};
/**
* GET /dns/:domain/:zone.json
* domains json data
*/
exports.dnsRecordJson = async (req, res) => {
if (!res.locals.user.domains.includes(req.params.domain)) {
return dynamicResponse(req, res, 403, { error: 'No permission for this domain' });
}
const recordSet = await redis.hget(`${req.params.domain}.`, req.params.zone);
return res.json({
csrf: req.csrfToken(),
user: res.locals.user,
recordSets: [{ [req.params.zone]: recordSet||{} }],
});
};

79
package-lock.json generated

@ -23,6 +23,7 @@
"express-session": "^1.17.3",
"fs-extra": "^10.1.0",
"gulp": "^4.0.2",
"ioredis": "^5.3.2",
"ip6addr": "^0.2.5",
"next": "^12.3.4",
"node-fetch": "^2.6.9",
@ -1231,6 +1232,11 @@
"resolved": "https://registry.npmjs.org/@influxdata/influxdb-client/-/influxdb-client-1.33.2.tgz",
"integrity": "sha512-RT5SxH+grHAazo/YK3UTuWK/frPWRM0N7vkrCUyqVprDgQzlLP+bSK4ak2Jv3QVF/pazTnsxWjvtKZdwskV5Xw=="
},
"node_modules/@ioredis/commands": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
},
"node_modules/@mapbox/node-pre-gyp": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz",
@ -2847,6 +2853,14 @@
"readable-stream": "^2.3.5"
}
},
"node_modules/cluster-key-slot": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@ -3265,6 +3279,14 @@
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
},
"node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
"engines": {
"node": ">=0.10"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@ -5459,6 +5481,29 @@
"node": ">=0.10.0"
}
},
"node_modules/ioredis": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz",
"integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==",
"dependencies": {
"@ioredis/commands": "^1.1.1",
"cluster-key-slot": "^1.1.0",
"debug": "^4.3.4",
"denque": "^2.1.0",
"lodash.defaults": "^4.2.0",
"lodash.isarguments": "^3.1.0",
"redis-errors": "^1.2.0",
"redis-parser": "^3.0.0",
"standard-as-callback": "^2.1.0"
},
"engines": {
"node": ">=12.22.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/ioredis"
}
},
"node_modules/ip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
@ -6201,6 +6246,16 @@
"node": ">=0.10.0"
}
},
"node_modules/lodash.defaults": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
},
"node_modules/lodash.isarguments": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@ -7913,6 +7968,25 @@
"node": ">= 0.10"
}
},
"node_modules/redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
"engines": {
"node": ">=4"
}
},
"node_modules/redis-parser": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
"dependencies": {
"redis-errors": "^1.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
@ -8696,6 +8770,11 @@
"node": "*"
}
},
"node_modules/standard-as-callback": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
},
"node_modules/static-extend": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",

@ -29,6 +29,7 @@
"express-session": "^1.17.3",
"fs-extra": "^10.1.0",
"gulp": "^4.0.2",
"ioredis": "^5.3.2",
"ip6addr": "^0.2.5",
"next": "^12.3.4",
"node-fetch": "^2.6.9",

@ -1,7 +1,6 @@
import { useRouter } from "next/router";
import React, { useState, useEffect } from 'react';
import Head from 'next/head';
import RecordSetRow from '../../../../components/RecordSetRow.js';
import BackButton from '../../../../components/BackButton.js';
import ErrorAlert from '../../../../components/ErrorAlert.js';
import * as API from '../../../../api.js';
@ -12,42 +11,12 @@ const DnsEditRecordPage = (props) => {
const { domain, zone, type } = router.query;
const [state, dispatch] = useState({
...props,
recordSets: [
{
"@": {
"a": [
{ "id": "a", "ttl": 300, "ip": "203.28.238.247", "geok": "cn", "geov": ["OC"], "h": true, "fb": ["b", "c"], "sel": 1, "bsel": 3 },
{ "id": "b", "ttl": 300, "ip": "38.60.199.224", "geok": "cn", "geov": ["AS"], "h": false, "fb": ["a", "c"], "sel": 1, "bsel": 3 },
{ "id": "c", "ttl": 300, "ip": "45.88.201.168", "geok": "cn", "geov": ["NA"], "h": true, "fb": ["e", "d"], "sel": 1, "bsel": 3 },
{ "id": "d", "ttl": 300, "ip": "185.125.168.21", "geok": "cn", "geov": ["EU", "AF"], "h": true, "fb": ["c"], "sel": 1, "bsel": 3 },
{ "id": "e", "ttl": 300, "ip": "38.54.57.171", "geok": "cn", "geov": ["SA", "AF"], "h": true, "fb": [], "sel": 1, "bsel": 3 }
],
"aaaa": [
{ "id": "a", "ttl": 300, "ip": "2a03:94e0:ffff:185:125:168:0:21", "geok": "cn", "geov": ["EU", "AF"], "h": true, "fb": ["b"], "sel": 1, "bsel": 3 },
{ "id": "b", "ttl": 300, "ip": "2a03:94e1:ffff:45:88:201:0:168", "geok": "cn", "geov": ["NA", "SA", "AS", "OC"], "h": true, "fb": ["a"], "sel": 1, "bsel": 3 }
],
"caa": [
{ "flag": 0, "tag": "issue", "value": "letsencrypt.org" },
{ "flag": 0, "tag": "iodef", "value": "mailto:tom@69420.me" }
],
"soa": { "ttl": 86400, "minttl": 30, "mbox": "root.basedflare.com.", "ns": "esther.kikeflare.com.", "refresh": 86400, "retry": 7200, "expire": 3600 },
"txt": [
{ "ttl": 300, "text": "v=spf1 -all" }
],
"ns": [
{ "ttl": 86400, "host": "esther.kikeflare.com." },
{ "ttl": 86400, "host": "aronowitz.bfcdn.host." },
{ "ttl": 86400, "host": "goldberg.fatpeople.lol." }
]
}
}
]
});
const [error, setError] = useState();
useEffect(() => {
if (!state.recordSets) {
// API.getDomainRecordSets(domain, dispatch, setError, router);
API.getDnsRecords(domain, zone, dispatch, setError, router);
}
}, [state.recordSets, domain, router]);

@ -12,42 +12,12 @@ const DnsDomainIndexPage = (props) => {
const { domain } = router.query;
const [state, dispatch] = useState({
...props,
recordSets: [
{
"@": {
"a": [
{ "id": "a", "ttl": 300, "ip": "203.28.238.247", "geok": "cn", "geov": ["OC"], "h": true, "fb": ["b", "c"], "sel": 1, "bsel": 3 },
{ "id": "b", "ttl": 300, "ip": "38.60.199.224", "geok": "cn", "geov": ["AS"], "h": false, "fb": ["a", "c"], "sel": 1, "bsel": 3 },
{ "id": "c", "ttl": 300, "ip": "45.88.201.168", "geok": "cn", "geov": ["NA"], "h": true, "fb": ["e", "d"], "sel": 1, "bsel": 3 },
{ "id": "d", "ttl": 300, "ip": "185.125.168.21", "geok": "cn", "geov": ["EU", "AF"], "h": true, "fb": ["c"], "sel": 1, "bsel": 3 },
{ "id": "e", "ttl": 300, "ip": "38.54.57.171", "geok": "cn", "geov": ["SA", "AF"], "h": true, "fb": [], "sel": 1, "bsel": 3 }
],
"aaaa": [
{ "id": "a", "ttl": 300, "ip": "2a03:94e0:ffff:185:125:168:0:21", "geok": "cn", "geov": ["EU", "AF"], "h": true, "fb": ["b"], "sel": 1, "bsel": 3 },
{ "id": "b", "ttl": 300, "ip": "2a03:94e1:ffff:45:88:201:0:168", "geok": "cn", "geov": ["NA", "SA", "AS", "OC"], "h": true, "fb": ["a"], "sel": 1, "bsel": 3 }
],
"caa": [
{ "flag": 0, "tag": "issue", "value": "letsencrypt.org" },
{ "flag": 0, "tag": "iodef", "value": "mailto:tom@69420.me" }
],
"soa": { "ttl": 86400, "minttl": 30, "mbox": "root.basedflare.com.", "ns": "esther.kikeflare.com.", "refresh": 86400, "retry": 7200, "expire": 3600 },
"txt": [
{ "ttl": 300, "text": "v=spf1 -all" }
],
"ns": [
{ "ttl": 86400, "host": "esther.kikeflare.com." },
{ "ttl": 86400, "host": "aronowitz.bfcdn.host." },
{ "ttl": 86400, "host": "goldberg.fatpeople.lol." }
]
}
}
]
});
const [error, setError] = useState();
useEffect(() => {
if (!state.recordSets) {
// API.getDomainRecordSets(domain, dispatch, setError, router);
API.getDnsDomain(domain, dispatch, setError, router);
}
}, [state.recordSets, domain, router]);

@ -0,0 +1,47 @@
'use strict';
const Redis = require('ioredis')
, client = new Redis({
host: process.env.REDIS_HOST || '127.0.0.1',
port: process.env.REDIS_PORT || 6379,
password: process.env.REDIS_PASS || '',
});
module.exports = {
client,
close: () => {
client.quit();
},
//get a value with key
get: (key) => {
return client.get(key).then(res => { return JSON.parse(res); });
},
//get a hash value
hgetall: (key) => {
return client.hgetall(key).then(res => { return res });
},
//get a hash value
hget: (key, hash) => {
return client.hget(key, hash).then(res => { return JSON.parse(res); });
},
//set a value on key
set: (key, value) => {
return client.set(key, JSON.stringify(value));
},
//delete value with key
del: (keyOrKeys) => {
if (Array.isArray(keyOrKeys)) {
return client.del(...keyOrKeys);
} else {
return client.del(keyOrKeys);
}
},
};

@ -74,7 +74,7 @@ const testRouter = (server, app) => {
const csrfMiddleware = csrf();
//dataplaneapi middleware
const useHaproxy = async (req, res, next) => {
const useHaproxy = (req, res, next) => {
if (res.locals.clusters.length === 0) {
return next();
}
@ -139,6 +139,7 @@ const testRouter = (server, app) => {
, mapsController = require('./controllers/maps')
, clustersController = require('./controllers/clusters')
, certsController = require('./controllers/certs')
, dnsController = require('./controllers/dns')
, domainsController = require('./controllers/domains');
//unauthed pages
@ -165,6 +166,10 @@ const testRouter = (server, app) => {
server.get('/clusters.json', useSession, fetchSession, checkSession, csrfMiddleware, clustersController.clustersJson);
server.get('/domains', useSession, fetchSession, checkSession, csrfMiddleware, domainsController.domainsPage.bind(null, app));
server.get('/domains.json', useSession, fetchSession, checkSession, csrfMiddleware, domainsController.domainsJson);
server.get('/dns/:domain([a-zA-Z0-9-\.]+).json', useSession, fetchSession, checkSession, csrfMiddleware, dnsController.dnsDomainJson);
server.get('/dns/:domain([a-zA-Z0-9-\.]+)', useSession, fetchSession, checkSession, csrfMiddleware, dnsController.dnsDomainPage.bind(null, app));
server.get('/dns/:domain([a-zA-Z0-9-\.]+)/:zone([a-zA-Z0-9-\.@]+).json', useSession, fetchSession, checkSession, csrfMiddleware, dnsController.dnsRecordJson);
server.get('/dns/:domain([a-zA-Z0-9-\.]+)/:zone([a-zA-Z0-9-\.@]+)/:type([a-z]+)', useSession, fetchSession, checkSession, csrfMiddleware, dnsController.dnsRecordPage.bind(null, app));
server.get('/certs', useSession, fetchSession, checkSession, useHaproxy, csrfMiddleware, certsController.certsPage.bind(null, app));
server.get('/certs.json', useSession, fetchSession, checkSession, useHaproxy, csrfMiddleware, certsController.certsJson);
// server.get('/stats', useSession, fetchSession, checkSession, useHaproxy, csrfMiddleware, accountController.statsPage.bind(null, app));

Loading…
Cancel
Save