domain registration, start on DNS
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
node_modules
|
node_modules
|
||||||
ndm.db
|
ndm.db
|
||||||
|
*.env
|
||||||
@@ -68,6 +68,86 @@ body {
|
|||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.InsetContentBox {
|
||||||
|
border: 1px inset;
|
||||||
|
min-height: 200px;
|
||||||
|
background-color: white;
|
||||||
|
display: inline-block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ContentBox {
|
||||||
|
border: 2px solid #4682b4;
|
||||||
|
min-height: 200px;
|
||||||
|
background-color: white;
|
||||||
|
display: inline-block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#DomainOptions {
|
||||||
|
text-align: center;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#DomainSelection {
|
||||||
|
overflow: scroll;
|
||||||
|
zoom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#DomainSelection li:hover {
|
||||||
|
background-color: #2e69cb;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SelectedListItem {
|
||||||
|
background-color: #2e69cb;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style: none;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MutedText {
|
||||||
|
color: #afafaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TitleText {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #0000ee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DefaultButton {
|
||||||
|
background-color: #f5cd2f;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.VerticalInputForm {
|
.VerticalInputForm {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// This script is designed to support at a minimum IE 6
|
||||||
|
//
|
||||||
|
// All menu functions are defined outside of initMenu.
|
||||||
|
//
|
||||||
|
// This is so I'm not duplicating functions between-
|
||||||
|
// checks for what browser we have
|
||||||
|
|
||||||
|
function resetSelection() {
|
||||||
|
var elements = document.getElementsByName("domain_selection");
|
||||||
|
|
||||||
|
for (var i = 0; i < elements.length; i++) {
|
||||||
|
(function(li) {
|
||||||
|
li.className = "";
|
||||||
|
|
||||||
|
|
||||||
|
})(elements[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleSelection(li) {
|
||||||
|
var domainId = li.value;
|
||||||
|
var editDNS = document.getElementById("options_edit_dns");
|
||||||
|
var unreg = document.getElementById("options_unregister");
|
||||||
|
|
||||||
|
if(li.className == "SelectedListItem") {
|
||||||
|
editDNS.className = "Hidden";
|
||||||
|
unreg.className = "Hidden";
|
||||||
|
li.className = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetSelection();
|
||||||
|
|
||||||
|
li.className = "SelectedListItem";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
editDNS.className = "";
|
||||||
|
editDNS.href = "/dns/edit/" + domainId;
|
||||||
|
|
||||||
|
unreg.className = "";
|
||||||
|
unreg.href = "/domains/unregister/" + domainId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the page has fully loaded, connect each button to its code
|
||||||
|
function initDomainSelection() {
|
||||||
|
// Register selection events
|
||||||
|
var elements = document.getElementsByName("domain_selection");
|
||||||
|
|
||||||
|
for (var i = 0; i < elements.length; i++) {
|
||||||
|
(function(li) {
|
||||||
|
if(window.addEventListener) {
|
||||||
|
li.addEventListener("click", function() {
|
||||||
|
toggleSelection(li);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
li.attachEvent("onclick", function() {
|
||||||
|
toggleSelection(li);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})(elements[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register load / onload event
|
||||||
|
if(window.addEventListener) {
|
||||||
|
window.addEventListener('load', initDomainSelection);
|
||||||
|
} else if(window.attachEvent) {
|
||||||
|
window.attachEvent('onload', initDomainSelection);
|
||||||
|
} else {
|
||||||
|
alert("Unsupported browser.");
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
function FQDNToCoreDNSPath(fqdn) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function RegisterNewDomain(domainLabel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetAllRecords() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function CreateARecord(domain, host) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function DeleteARecord(domain, host) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function UpdateARecord(domain, host) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function CreateMXRecord(domain, host) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function DeleteMXRecord(domain, host) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function UpdateMXRecord(domain, host) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
RegisterNewDomain,
|
||||||
|
GetAllRecords,
|
||||||
|
CreateARecord,
|
||||||
|
DeleteARecord
|
||||||
|
}
|
||||||
+12
-2
@@ -34,13 +34,23 @@ const User = seqConn.define('User', {
|
|||||||
const RegisteredDomain = seqConn.define('RegisteredDomain', {
|
const RegisteredDomain = seqConn.define('RegisteredDomain', {
|
||||||
domain: {
|
domain: {
|
||||||
type: Sequelize.TEXT,
|
type: Sequelize.TEXT,
|
||||||
unique: true,
|
allowNull: false
|
||||||
|
},
|
||||||
|
tld: {
|
||||||
|
type: Sequelize.TEXT,
|
||||||
allowNull: false
|
allowNull: false
|
||||||
},
|
},
|
||||||
owner: {
|
owner: {
|
||||||
type: Sequelize.BIGINT.UNSIGNED,
|
type: Sequelize.BIGINT.UNSIGNED,
|
||||||
allowNull: false
|
allowNull: false
|
||||||
}
|
},
|
||||||
|
}, {
|
||||||
|
indexes: [
|
||||||
|
{
|
||||||
|
unique: true,
|
||||||
|
fields: ['domain', 'tld'],
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
////// Exports //////
|
////// Exports //////
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const domainValidator = require('../validators/domain');
|
||||||
|
const authMw = require('../session');
|
||||||
|
const database = require('../database.js');
|
||||||
|
const dbConnection = database.db;
|
||||||
|
const Sequelize = require('sequelize');
|
||||||
|
const pageTitle = 'Domain Manager | Edit DNS';
|
||||||
|
|
||||||
|
|
||||||
|
// Manage domains
|
||||||
|
router.get('/dns/edit/:domainId', authMw.AllowIfAuthenticated, async (req, res, next) => {
|
||||||
|
const result = await dbConnection.transaction(async(t) => {
|
||||||
|
const ownedDomain = await database.models.RegisteredDomain.findOne({
|
||||||
|
where: {
|
||||||
|
id: req.params.domainId,
|
||||||
|
owner: req.session.userId
|
||||||
|
}
|
||||||
|
}, {transaction: t});
|
||||||
|
|
||||||
|
return ownedDomain;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
return next();
|
||||||
|
|
||||||
|
res.render('dns', {title: pageTitle, domain: result});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const domainValidator = require('../validators/domain');
|
||||||
|
const authMw = require('../session');
|
||||||
|
const database = require('../database.js');
|
||||||
|
const dbConnection = database.db;
|
||||||
|
const Sequelize = require('sequelize');
|
||||||
|
const pageTitle = 'Domain Manager | Register New Domain';
|
||||||
|
|
||||||
|
const supportedTLDs = [
|
||||||
|
"local",
|
||||||
|
"tomato",
|
||||||
|
"secret",
|
||||||
|
"money",
|
||||||
|
"lol",
|
||||||
|
"lmao"
|
||||||
|
];
|
||||||
|
|
||||||
|
// Manage domains
|
||||||
|
router.get('/domains', authMw.AllowIfAuthenticated, async (req, res) => {
|
||||||
|
const result = await dbConnection.transaction(async(t) => {
|
||||||
|
const ownedDomains = await database.models.RegisteredDomain.findAll({
|
||||||
|
where: {
|
||||||
|
owner: req.session.userId
|
||||||
|
}
|
||||||
|
}, {transaction: t});
|
||||||
|
|
||||||
|
return ownedDomains;
|
||||||
|
});
|
||||||
|
|
||||||
|
let registeredDomains = result;
|
||||||
|
|
||||||
|
res.render('domains', {title: 'Domain Manager | Your Domains', registeredDomains: registeredDomains});
|
||||||
|
});
|
||||||
|
|
||||||
|
//// Register domains ////
|
||||||
|
|
||||||
|
// GET
|
||||||
|
// Frontend page to register a new domain
|
||||||
|
router.get('/domains/new', authMw.AllowIfAuthenticated, async(req, res) => {
|
||||||
|
res.render('newdomain', {title: 'Domain Manager | Register Domain', supportedTLDs: supportedTLDs});
|
||||||
|
});
|
||||||
|
|
||||||
|
// POST
|
||||||
|
// Backend post handler to register the domain
|
||||||
|
router.post('/domains/new', authMw.AllowIfAuthenticated, async(req, res, next) => {
|
||||||
|
const reqBody = req.body;
|
||||||
|
const validationResult = domainValidator.test(reqBody);
|
||||||
|
const validationError = validationResult.error;
|
||||||
|
let errors = [];
|
||||||
|
|
||||||
|
if(validationError !== undefined)
|
||||||
|
errors = validationError.details;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(errors.length === 0) {
|
||||||
|
const result = await dbConnection.transaction(async(t) => {
|
||||||
|
const newDomain = await database.models.RegisteredDomain.create({
|
||||||
|
domain: reqBody.register_domain_label,
|
||||||
|
tld: reqBody.register_domain_tld,
|
||||||
|
owner: req.session.userId
|
||||||
|
}, {transaction: t});
|
||||||
|
|
||||||
|
return newDomain;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(result !== undefined) {
|
||||||
|
return res.redirect('/domains');
|
||||||
|
} else {
|
||||||
|
errors.push({message: 'Failed to register new domain.'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(error) {
|
||||||
|
if(error instanceof Sequelize.UniqueConstraintError) {
|
||||||
|
errors.push({message: 'Domain is not available.'});
|
||||||
|
} else {
|
||||||
|
error.status = 500;
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we're here we failed, I specify true for csrfToken to force reset it
|
||||||
|
return res.render('newdomain', {title: pageTitle, supportedTLDs: supportedTLDs, errors: errors, csrfToken: req.csrfToken(true) });
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
const Joi = require('joi');
|
||||||
|
const domainRegistrySchema = Joi.object().keys({
|
||||||
|
register_domain_label: Joi.string().alphanum().min(1).max(63).required(),
|
||||||
|
register_domain_tld: Joi.string().valid("local", "tomato", "secret", "money", "lol", "lmao").required()
|
||||||
|
}).unknown(true);
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
test: (body) => {
|
||||||
|
return domainRegistrySchema.validate(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<p>Configuring DNS records for {{domain.domain}}.{{domain.tld}}</p>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{{{getScript "/scripts/domainmgmt.js" nonce}}}
|
||||||
|
|
||||||
|
<p>Manage your registered domains</p>
|
||||||
|
|
||||||
|
{{#if errors}}
|
||||||
|
<ul>
|
||||||
|
{{#each errors}}
|
||||||
|
<li>{{this.message}}</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="InsetContentBox" id="DomainSelection">
|
||||||
|
<div style="width: 600px;"></div>
|
||||||
|
<ul>
|
||||||
|
{{#if (lenEq registeredDomains 0)}}
|
||||||
|
<li class="MutedText">You don't currently have any registered domains</li>
|
||||||
|
{{else}}
|
||||||
|
{{#each registeredDomains}}
|
||||||
|
<li name="domain_selection" value="{{this.id}}">{{this.domain}}.{{this.tld}}</li>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ContentBox" id="DomainOptions">
|
||||||
|
<div style="width: 200px;"></div>
|
||||||
|
<p class="TitleText">Options</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/domains/new">Register New Domain</a></li>
|
||||||
|
<li><a class="Hidden" href="/dns/edit" id="options_edit_dns">Edit DNS</a></li>
|
||||||
|
<li><a class="Hidden" href="/domains/unregister" id="options_unregister">Unregister Domain</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
@@ -16,33 +16,32 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div id="PageContent">
|
<div id="PageContent">
|
||||||
<div id="Logo">
|
<div id="Logo">
|
||||||
<p>Domain Manager</p>
|
<p>Domain Manager</p>
|
||||||
</div>
|
|
||||||
<div id="Header">
|
|
||||||
<div id="Header-Left">
|
|
||||||
<a href="/">Home</a>
|
|
||||||
{{#if isLoggedIn}}
|
|
||||||
<span>|</span>
|
|
||||||
<a href="/dns">DNS</a>
|
|
||||||
<span>|</span>
|
|
||||||
<a href="/domains">Domains</a>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div id="Header">
|
||||||
|
<div id="Header-Left">
|
||||||
|
<a href="/">Home</a>
|
||||||
|
{{#if isLoggedIn}}
|
||||||
|
<span>|</span>
|
||||||
|
<a href="/domains">Domains</a>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="Header-Right">
|
<div id="Header-Right">
|
||||||
{{#unless isLoggedIn}}
|
{{#unless isLoggedIn}}
|
||||||
<a href="/login">Login</a>
|
<a href="/login">Login</a>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<a href="/register">Register</a>
|
<a href="/register">Register</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{username}}</span>
|
<span>{{username}}</span>
|
||||||
<span>|</span>
|
<span>|</span>
|
||||||
<a id="Menu_Auth_Logout" href="javascript://void();">Logout</a>
|
<a id="Menu_Auth_Logout" href="javascript://void();">Logout</a>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<hr>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
{{{body}}}
|
{{{body}}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<p>Register a new domain</p>
|
||||||
|
|
||||||
|
{{#if errors}}
|
||||||
|
<ul>
|
||||||
|
{{#each errors}}
|
||||||
|
<li>{{this.message}}</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<form action="/domains/new" method="post">
|
||||||
|
<input type="hidden" name="_csrf" value="{{csrfToken}}">
|
||||||
|
<input type="text" name="register_domain_label">
|
||||||
|
<select name="register_domain_tld">
|
||||||
|
{{#each supportedTLDs}}
|
||||||
|
<option value="{{this}}">.{{this}}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
<br><br>
|
||||||
|
<input type="submit" class="DefaultButton" value="Register">
|
||||||
|
</form>
|
||||||
Reference in New Issue
Block a user