Frontend + hostname validation

This commit is contained in:
Philipp Böhm 2014-07-16 01:10:35 +02:00
parent 3015b873cb
commit f5ee141894
2 changed files with 78 additions and 30 deletions

View File

@ -121,39 +121,20 @@
<hr /> <hr />
<form class="form-inline" role="form"> <form class="form-inline" role="form">
<div class="form-group"> <div id="hostname_input" class="form-group">
<div class="input-group"> <div class="input-group">
<input class="form-control input-lg" type="text" placeholder="my-own-hostname"> <input id="hostname" class="form-control input-lg" type="text" placeholder="my-own-hostname">
<div class="input-group-addon input-lg">{{.domain}}</div> <div class="input-group-addon input-lg">{{.domain}}</div>
</div> </div>
</div> </div>
</form> </form>
<hr />
<input type="button" id="register" class="btn btn-primary disabled" value="Register Host" />
</div> </div>
<div class="row marketing"> <div id="command_output"></div>
<div class="col-lg-6">
<h4>Own Domain with NS delegation</h4>
<p>You have to own a domain where your Registrar allows you
to add NS-Records for Subdomains, as this is handled by
DDNS.</p>
<h4>Running Server</h4>
<p>You should have a server running continously. Go, Redis
and PowerDNS have to be supported by the running OS.</p>
</div>
<div class="col-lg-6">
<h4>Redis</h4>
<p>Redis is used as the data store with features like
automatic expiration of hosts ...</p>
<h4>PowerDNS</h4>
<p>PowerDNS is the DNS server software used by DDNS to handle
the DNS requests for your subdomain. DDNS provides a suitable
backend software for PowerDNS.</p>
</div>
</div>
<div class="footer"> <div class="footer">
<p>&copy; Philipp Böhm</p> <p>&copy; Philipp Böhm</p>
@ -166,5 +147,55 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Latest compiled and minified JavaScript --> <!-- Latest compiled and minified JavaScript -->
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script type="text/javascript" charset="utf-8">
function isValid() {
$('#register').removeClass("disabled");
$('#hostname_input').removeClass("has-error");
$('#hostname_input').addClass("has-success");
}
function isNotValid(argument) {
$('#register').addClass("disabled");
$('#hostname_input').removeClass("has-success");
$('#hostname_input').addClass("has-error");
}
function validate() {
var hostname = $('#hostname').val();
$.getJSON("/available/" + hostname + "/", function( data ) {
if (data.available) {
isValid();
} else {
isNotValid();
}
}).error(function(){ isNotValid(); });
}
$(document).ready(function() {
var timer = null;
$('#hostname').on('keydown', function () {
clearTimeout(timer);
timer = setTimeout(validate, 1000)
});
$('#register').click(function() {
var hostname = $("#hostname").val();
$.getJSON("/new/" + hostname + "/", function( data ) {
console.log(data);
var host = location.protocol + '//' + location.host;
$("#command_output").append(
"<pre>curl \"" + host +
data.update_link + "\"</pre>");
})
});
});
</script>
</body> </body>
</html> </html>

25
web.go
View File

@ -7,6 +7,7 @@ import (
"html/template" "html/template"
"net" "net"
"net/http" "net/http"
"regexp"
) )
func RunWebService(conn *connection.RedisConnection) { func RunWebService(conn *connection.RedisConnection) {
@ -18,15 +19,20 @@ func RunWebService(conn *connection.RedisConnection) {
}) })
r.GET("/available/:hostname", func(c *gin.Context) { r.GET("/available/:hostname", func(c *gin.Context) {
hostname := c.Params.ByName("hostname") hostname, valid := ValidHostname(c.Params.ByName("hostname"))
c.JSON(200, gin.H{ c.JSON(200, gin.H{
"available": !conn.HostExist(hostname), "available": valid && !conn.HostExist(hostname),
}) })
}) })
r.GET("/new/:hostname", func(c *gin.Context) { r.GET("/new/:hostname", func(c *gin.Context) {
hostname := c.Params.ByName("hostname") hostname, valid := ValidHostname(c.Params.ByName("hostname"))
if !valid {
c.JSON(404, gin.H{"error": "This hostname is not valid"})
return
}
if conn.HostExist(hostname) { if conn.HostExist(hostname) {
c.JSON(403, gin.H{ c.JSON(403, gin.H{
@ -48,9 +54,14 @@ func RunWebService(conn *connection.RedisConnection) {
}) })
r.GET("/update/:hostname/:token", func(c *gin.Context) { r.GET("/update/:hostname/:token", func(c *gin.Context) {
hostname := c.Params.ByName("hostname") hostname, valid := ValidHostname(c.Params.ByName("hostname"))
token := c.Params.ByName("token") token := c.Params.ByName("token")
if !valid {
c.JSON(404, gin.H{"error": "This hostname is not valid"})
return
}
if !conn.HostExist(hostname) { if !conn.HostExist(hostname) {
c.JSON(404, gin.H{ c.JSON(404, gin.H{
"error": "This hostname has not been registered or is expired.", "error": "This hostname has not been registered or is expired.",
@ -111,3 +122,9 @@ func BuildTemplate() *template.Template {
return html return html
} }
func ValidHostname(host string) (string, bool) {
valid, _ := regexp.Match("^[a-z0-9]{1,32}$", []byte(host))
return host, valid
}