Initial commit

This commit is contained in:
paul 2018-04-22 16:55:50 +02:00
commit 2422e3108f
37 changed files with 12691 additions and 0 deletions

28
assets/dev.go Normal file
View file

@ -0,0 +1,28 @@
// +build dev
package assets
import (
"go/build"
"log"
"net/http"
"github.com/shurcooL/httpfs/union"
)
// Assets contains project assets.
var Assets = union.New(map[string]http.FileSystem{
"/static": http.Dir(importPathToDir("git.klink.asia/paul/certman/assets/static")),
"/templates": http.Dir(importPathToDir("git.klink.asia/paul/certman/assets/templates")),
})
// importPathToDir is a helper function that resolves the absolute path of
// modules, so they can be used both in dev mode (`-tags="dev"`) or with a
// generated static asset file (`go generate`).
func importPathToDir(importPath string) string {
p, err := build.Import(importPath, "", build.FindOnly)
if err != nil {
log.Fatalln(err)
}
return p.Dir
}

6
assets/doc.go Normal file
View file

@ -0,0 +1,6 @@
//go:generate vfsgendev -source="git.klink.asia/paul/certman/assets".Assets
// Package assets contains assets the service, that will be embedded into
// the binary.
// Regenerate by running `go generate git.klink.asia/paul/certman/assets`.
package assets

View file

View file

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
height="119.99999"
width="540"
xml:space="preserve"
viewBox="0 0 540 119.99999"
y="0px"
x="0px"
id="Ebene_1"
version="1.1"><metadata
id="metadata22"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title>ONEOFF</dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs20" /><style
id="style2"
type="text/css">
.st0{fill:#143C78;}
</style><g
transform="matrix(4,0,0,4,-365.2,-639.99996)"
id="XMLID_14_" /><title
id="title5">ONEOFF</title><desc
id="desc7">Created with Sketch.</desc><g
transform="matrix(1.1233618,0,0,1.0968921,-102.56293,-88.409503)"
id="XMLID_2_"><path
style="fill:#f9f9f9"
d="m 492.9,95.3 h -44 c -4.8,0 -8.7,3.9 -8.7,8.7 v 61.9 c 0,4.8 3.9,8.6 8.7,8.6 4.8,0 8.7,-3.8 8.7,-8.6 v -22.5 h 30.2 c 4.4,0 7.9,-3.5 7.9,-7.9 0,-4.4 -3.5,-7.9 -7.9,-7.9 H 457.6 V 111 h 35.2 c 4.4,0 7.9,-3.5 7.9,-7.9 0,-4.3 -3.5,-7.8 -7.8,-7.8 z"
class="st0"
id="XMLID_13_" /><path
style="fill:#f9f9f9"
d="m 564.1,111 c 4.4,0 7.9,-3.5 7.9,-7.9 0,-4.4 -3.5,-7.9 -7.9,-7.9 h -44 c -4.8,0 -8.4,3.9 -8.4,8.7 v 61.9 c 0,4.8 3.7,8.6 8.5,8.6 4.8,0 8.5,-3.8 8.5,-8.6 V 143.3 H 559 c 4.4,0 7.9,-3.5 7.9,-7.9 0,-4.4 -3.5,-7.9 -7.9,-7.9 H 528.7 V 111 Z"
class="st0"
id="XMLID_12_" /><path
style="fill:#f9f9f9"
d="m 386.6,94 c -21.6,0 -38.1,14.6 -41.3,33.6 h -14.9 c -3.9,0.1 -7,3.3 -7,7.2 0,3.9 3.1,7.1 7,7.2 h 14.9 c 3.3,18.9 19.5,33.1 41.1,33.1 24.2,0 41.9,-18.3 41.9,-40.6 0,-22.4 -17.5,-40.5 -41.7,-40.5 z m 23.4,40.8 c 0,13.5 -9.6,24.5 -23.5,24.5 -11.2,0 -19.8,-7.3 -22.7,-17.2 h 22.7 c 4,0 7.3,-3.1 7.3,-7.2 0,-4 -3.3,-7.3 -7.3,-7.3 h -22.9 c 2.6,-10.2 11.2,-17.7 22.7,-17.7 13.9,0 23.7,11.2 23.7,24.7 z"
class="st0"
id="XMLID_9_" /><path
style="fill:#f9f9f9"
d="m 342.5,80.7 -10.8,16 c -11.7,0 -49.1,-0.1 -49.3,-0.1 -3.8,0.2 -6.8,3.4 -6.8,7.2 0,4 3.2,7.2 7.2,7.2 0.1,0 29.7,0 39.1,0 l -11.1,16.4 c -8.6,0 -28.1,0 -28.2,0 h -0.2 v -0.1 c -3.8,0.1 -7,3.3 -7,7.2 0,3.9 3.1,7.1 7,7.2 H 301 l -11.7,17.4 h -6.5 c -4,0 -7.3,3.2 -7.3,7.2 0,3 1.9,5.6 4.5,6.7 l -11.4,17 h 1 L 343.3,80.6 h -0.8 z"
class="st0"
id="XMLID_8_" /><path
style="fill:#f9f9f9"
d="m 133.1,94 c -24.2,0 -41.8,18.3 -41.8,40.6 v 0.2 c 0,22.3 17.4,40.4 41.6,40.4 24.2,0 41.8,-18.3 41.8,-40.6 v -0.2 C 174.7,112.1 157.3,94 133.1,94 Z m 23.7,40.8 c 0,13.5 -9.8,24.5 -23.7,24.5 -13.9,0 -23.9,-11.2 -23.9,-24.7 v -0.2 c 0,-13.5 9.8,-24.5 23.7,-24.5 13.9,0 23.9,11.2 23.9,24.7 z"
class="st0"
id="XMLID_5_" /><circle
style="fill:#f9f9f9"
r="7.4000001"
cy="134.60001"
cx="132.5"
class="st0"
id="XMLID_4_" /><path
style="fill:#f9f9f9"
d="m 250.8,94.7 c -4.7,0 -8.5,3.8 -8.5,8.5 v 40.5 L 209.1,99.9 c -2.4,-3 -4.7,-5.1 -8.9,-5.1 h -1.8 c -4.8,0 -8.8,3.9 -8.8,8.7 V 166 c 0,4.7 4,8.5 8.7,8.5 4.7,0 8.7,-3.8 8.7,-8.5 v -42 l 34.5,45.4 c 2.4,3 4.7,5.1 8.9,5.1 h 0.6 c 4.8,0 8.5,-3.9 8.5,-8.8 v -62.5 c -0.1,-4.7 -3.9,-8.5 -8.7,-8.5 z"
class="st0"
id="XMLID_3_" /></g></svg>

After

(image error) Size: 3.4 KiB

6
assets/static/js/main.js Normal file
View file

@ -0,0 +1,6 @@
$.ajaxSetup({
// Initialize headers from the csrf-token meta tag.
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});

10663
assets/static/vendor/bulma.css vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,20 @@
{{ define "meta" }}
<title>Insufficient permissions</title>
{{ end }}
{{ define "content" }}
<section class="hero is-info is-fullheight">
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column is-8-desktop is-offset-2-desktop">
<h1 class="title is-2 is-spaced">Insufficient permissions</h1>
<h2 class="subtitle is-4">
Sorry, you don't have permissione to access this ressource.
</h2>
</div>
</div>
</div>
</div>
</section>
{{ end }}

View file

@ -0,0 +1,21 @@
{{ define "meta" }}
<title>Forbidden</title>
{{ end }}
{{ define "content" }}
<section class="hero is-warning is-fullheight">
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column is-8-desktop is-offset-2-desktop">
<h1 class="title is-2 is-spaced">Forbidden</h1>
<h2 class="subtitle is-4">
The received the request was not processed.
For example, the CSRF validation may have failed.
</h2>
</div>
</div>
</div>
</div>
</section>
{{ end }}

View file

@ -0,0 +1,20 @@
{{ define "meta" }}
<title>Page not found</title>
{{ end }}
{{ define "content" }}
<section class="hero is-info is-fullheight">
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column is-8-desktop is-offset-2-desktop">
<h1 class="title is-2 is-spaced">Page not found</h1>
<h2 class="subtitle is-4">
You requested a page that could not be fetched by the web server.
</h2>
</div>
</div>
</div>
</div>
</section>
{{ end }}

View file

@ -0,0 +1,21 @@
{{ define "meta" }}
<title>Sorry, something went wrong.</title>
{{ end }}
{{ define "content" }}
<section class="hero is-warning is-fullheight">
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column is-8-desktop is-offset-2-desktop">
<h1 class="title is-2 is-spaced">Sorry, there was an error while processing your request.</h1>
<h2 class="subtitle is-4">
Maybe you can try again at a later time.<br>
We have logged the error and will try to make sure that this does not happen in the future.
</h2>
</div>
</div>
</div>
</div>
</section>
{{ end }}

View file

@ -0,0 +1,69 @@
{{ define "base" }}# Client configuration for {{ .User }}@{{ .Name }}
client
dev tun
remote ovpn.zom.bi 1194 udp
resolv-retry infinite
nobind
persist-key
persist-tun
cipher AES-256-CBC
auth SHA512
ns-cert-type server
key-direction 1
tls-version-min 1.2
;comp-lzo
verb 3
<ca>
-----BEGIN CERTIFICATE-----
MIIDszCCApugAwIBAgIJAKuS+fLPTpC7MA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
BAYTAkRFMQ8wDQYDVQQIDAZTYXhvbnkxEDAOBgNVBAcMB0RyZXNkZW4xDjAMBgNV
BAoMBVpvbWJpMRUwEwYDVQQLDAxJVC1BYnRlaWx1bmcxFzAVBgNVBAMMDmNhLWNl
cnRpZmljYXRlMB4XDTE0MDQyMzIxNDQ1NloXDTE5MDQyMjIxNDQ1NlowcDELMAkG
A1UEBhMCREUxDzANBgNVBAgMBlNheG9ueTEQMA4GA1UEBwwHRHJlc2RlbjEOMAwG
A1UECgwFWm9tYmkxFTATBgNVBAsMDElULUFidGVpbHVuZzEXMBUGA1UEAwwOY2Et
Y2VydGlmaWNhdGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFW6ZC
zvTKCXoKKrb5ZKBWcQ55Fk57AJsMdqBv2TsTeDKPYONBh60cBgnhpFtkU8beetFT
1AQ0jwiyzaIqniSojBoUaWELxX5/w3qs9GPF4lkaBmZjQXnw1CRTZqJLccXmukIk
KkYKjMx+UVUAu6tMh5xMSml70ElDdHIgA33E+u1PvNW5hd3qQ+uNepqmKOROnjXb
Z6NghGR+26JmGRodKaPgY3VUe4s4QV1EnhaD8d43DgA0DsnrgO5X/RJVAwbXf9r6
Tqn6wE+v/VPH5xeo4RJegQuUfbY1A+z6odED+5OnNRuWQ3lp8GBfh7EThgBlfsin
jeFEkj6niOmCwnnnAgMBAAGjUDBOMB0GA1UdDgQWBBRKFc5tXx14eIKvtkEsi5EU
a0g1ADAfBgNVHSMEGDAWgBRKFc5tXx14eIKvtkEsi5EUa0g1ADAMBgNVHRMEBTAD
AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAT2xjVkrQpzHsF3naK/yYCKykfNHKv9BZD
iubiunvNKM47PWPjOMJvwktbbSOoOEsA9yJwCJFB0U9MMRb+FQorfRrv3J6T+QpP
F2HruMkqf7Fd20Gjhrcerl+dfN2aJf4cC7podTiK0w0kskzApeXmILdeA1x5iu8R
DweGc77S1GXIB+ep6DRvTnZ0IR4y4h2gOwnFWQagMt+v8gx3iOn8zjf+qIflXbbO
rNPAsF0k4gtin6uALQRx4NH63jA6mYZIcgOR9fmJHGhsE6qPLMjZHe8JWyaTbcye
7JZ7/q02vooEWWBtkQwRgBQ/pXgYagzjW4237TgNT53vkrtU+fzt
-----END CERTIFICATE-----
</ca>
<cert>
{{ .Cert | html }}</cert>
<key>
{{ .Key | html }}</key>
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
158130f54e0d350c24974fc0d28ea5a7
432e63ebfa30bf912dc0405a848767a5
53940a8fff3f9bd19e2fb7cdb9d9de60
8dbe2d849c01a9ac79c6843eb4362fc3
3718c68cd0d7966616c49dce38a6a9b9
e3d8ff7bb49ff6c236e5d8d87b6bb693
d6ced44bbc13755aeb85d8848d3c37fa
21b5bdd05333cdd4e785658c1e549097
213005010a27ecf025eda44b14401ae0
f0abfc74a0bdc1fa081be748b21f5a4c
3e5f15eb666e94978be136cac5245976
6559f70dc37306376e3f08ce6267c1bc
04bdfa14488a124a3a5c595287fd3013
50940b53c784092759601c3c3c51fb6e
e248834d37e6cba41f9e908b216930b5
2e040f8472b460b37d72cc648784d0b4
-----END OpenVPN Static key V1-----
</tls-auth>
{{ end }}

View file

@ -0,0 +1,45 @@
{{ define "base" }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ .csrfToken }}" />
<meta name="csrf-param" content="csrf_token" />
<link rel="stylesheet" href='{{ asset "vendor/bulma.css" }}'>
<link rel="stylesheet" href='{{ asset "css/style.css" }}'>
{{ template "meta" . }}
{{ if eq .Meta.Env "production" }}
<!-- Add meta tags specific to production environment (analytics etc) -->
{{ end }}
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"
integrity="sha384-0AJY8UERsBUKdWcyF3o2kisLKeIo6G4Tbd8Y6fbyw6qYmn4WBuqcvxokp8m2UzSD"
crossorigin="anonymous"></script>
</head>
<body>
{{ if .flashes}}
<div id="flash-container">
{{range .flashes}}
{{ .Render }}
{{end}}
</div>
{{ end }}
<div class="main-container">
{{ template "content" . }}
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="{{ asset "vendor/jquery-3.2.1.min.js" }}"><\/script>')</script>
<script src='{{ asset "js/main.js" }}' async></script>
</body>
</html>
{{ end }}
{{ define "meta"}}{{end}}
{{ define "content"}}{{end}}

View file

@ -0,0 +1,56 @@
{{ define "base" }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ .csrfToken }}" />
<meta name="csrf-param" content="csrf_token" />
<link rel="stylesheet" href='{{ asset "vendor/bulma.css" }}'>
<link rel="stylesheet" href='{{ asset "css/style.css" }}'>
{{ template "meta" . }}
{{ if eq .Meta.Env "production" }}
<!-- Add meta tags specific to production environment (analytics etc) -->
{{ end }}
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"
integrity="sha384-0AJY8UERsBUKdWcyF3o2kisLKeIo6G4Tbd8Y6fbyw6qYmn4WBuqcvxokp8m2UzSD"
crossorigin="anonymous"></script>
</head>
<body>
<section class="hero is-info is-bold is-fullheight">
{{ if .flashes}}
<div class="hero-head" id="flash-container">
{{range .flashes}}
{{ .Render }}
{{end}}
</div>
{{ end }}
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
<div class="column is-one-third">
<div class="columns is-centered">
<div class="column is-half is-half-mobile is-offset-one-quarter-mobile">
<img src="{{ asset "img/logo.svg" }}"/>
</div>
</div>
{{ template "content" . }}
</div>
</div>
</div>
</div>
</section>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="{{ asset "vendor/jquery-3.2.1.min.js" }}"><\/script>')</script>
<script src='{{ asset "js/main.js" }}' async></script>
</body>
</html>
{{ end }}
{{ define "meta"}}{{end}}

View file

@ -0,0 +1,68 @@
{{ define "meta" }}
<title>Certificate List</title>
{{ end}}
{{ define "content" }}
<section class="content">
<div class="section">
<div class="container">
<div class="columns">
<div class="column">
<h1 class="title">Certificates for {{ .username }}:</h1>
<table class="table">
<thead>
<th>Device</th>
<th width="20%">Created</th>
<th width="20%" class="has-text-centered">Actions</th>
</thead>
<tfoot>
<form action="/certs/new" method="POST">
<th colspan="2">
<div class="field has-addons">
<p class="control is-marginless">
<a class="button is-static">
{{ $.username }}@
</a>
</p>
<p class="control is-marginless is-expanded">
<input name="certname" class="input" type="text" placeholder="Certificate name (e.g. Laptop)">
</p>
</div>
</th>
<th>{{ .csrfField }}<input type="submit" class="button is-success is-fullwidth" value="Create"/></th>
</form>
</tfoot>
<tbody>
{{ range .Clients }}
<tr>
<td class="is-vcentered"><p>{{ .User }}@{{ .Name }}</p></td>
<td><time title="{{ .CreatedAt.UTC }}">{{ .CreatedAt | humanDate }}</time></td>
<td>
<div class="field has-addons">
<p class="control is-marginless is-expanded">
<a href="/certs/download/{{ .Name }}" class="button is-primary is-fullwidth">Download</a>
</p>
<div class="control is-marginless">
<form action="/certs/delete/{{ .Name }}" method="POST">
{{ $.csrfField }}
<button class="button is-danger" type="submit">
<span class="icon is-small">
<i class="fas fa-trash"></i>
</span>
</button>
</form>
</div>
</div>
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
{{ end}}

View file

@ -0,0 +1,41 @@
{{ define "meta" }}<title>Log In</title>{{ end }}
{{ define "content" }}
<div class="box is-shadowless">
<div class="content has-text-centered" style="padding: 0 40px;">
<h1 class="title has-text-dark">Log In</h1>
<form action="" method="POST" class="control">
<div class="field">
<label for="email" class="label is-hidden">Email Address</label>
<div class="control has-icons-left">
<input class="input is-medium is-shadowless" id="email" name="email" spellcheck="false" label="false" type="" placeholder="Email Address" value="" autofocus />
<span class="icon is-medium is-left">
<i class="fas fa-at"></i>
</span>
</div>
</div>
<div class="field">
<label for="password" class="label is-hidden">Password</label>
<div class="control has-icons-left">
<input class="input is-medium is-shadowless" id="password" name="password" type="password" placeholder="Password" value=""/>
<span class="icon is-medium is-left">
<i class="fas fa-key"></i>
</span>
</div>
</div>
{{ .csrfField }}
<div class="field is-grouped-right">
<input class="button is-success is-fullwidth is-medium" type="submit" value="Log In">
</div>
<div class="field has-text-centered">
<p><a href="/forgot-password">Forgot Password?</a></p>
</div>
</form>
</div>
</div>
<div class="field">
<p class="has-text-white has-text-centered">
Don't have an account? <a class="has-text-weight-bold" href="/register">Sign Up</a>
</p>
</div>
{{ end }}