WIP: new user management and authentication system, use go 1.16 embed

This commit is contained in:
Christoph Haas
2021-02-24 21:24:45 +01:00
parent 43bab58f0a
commit 9b10d099b6
40 changed files with 2161 additions and 953 deletions

View File

@@ -53,7 +53,7 @@
}
}).tokenfield({
autocomplete: {
source: [{{range $i, $u :=.Users}}{{$u.Mail}},{{end}}],
source: [{{range $i, $u :=.Users}}{{$u.Email}},{{end}}],
delay: 100
},
showAutocompleteOnFocus: false

View File

@@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>{{ .Static.WebsiteTitle }} - Users</title>
<meta name="description" content="{{ .Static.WebsiteTitle }}">
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/css/custom.css">
</head>
<body id="page-top" class="d-flex flex-column min-vh-100">
{{template "prt_nav.html" .}}
<div class="container mt-5">
{{if eq .User.CreatedAt .Epoch}}
<h1>Create a new user</h1>
{{else}}
<h1>Edit user <strong>{{.User.Email}}</strong></h1>
{{end}}
{{template "prt_flashes.html" .}}
<form method="post" enctype="multipart/form-data">
{{if eq .User.CreatedAt .Epoch}}
<div class="form-row">
<div class="form-group required col-md-12">
<label for="inputEmail">Email</label>
<input type="text" name="email" class="form-control" id="inputEmail" value="{{.User.Email}}">
</div>
</div>
{{else}}
<input type="hidden" name="email" value="{{.User.Email}}">
{{end}}
<div class="form-row">
<div class="form-group required col-md-12">
<label for="inputFirstname">Firstname</label>
<input type="text" name="firstname" class="form-control" id="inputFirstname" value="{{.User.Firstname}}">
</div>
</div>
<div class="form-row">
<div class="form-group required col-md-12">
<label for="inputLastname">Lastname</label>
<input type="text" name="lastname" class="form-control" id="inputLastname" value="{{.User.Lastname}}">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label for="inputPhone">Phone</label>
<input type="text" name="phone" class="form-control" id="inputPhone" value="{{.User.Phone}}">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12 {{if eq .User.CreatedAt .Epoch}}required{{end}}">
<label for="inputPassword">Password</label>
<input type="password" name="password" class="form-control" id="inputPassword">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<div class="custom-control custom-switch">
<input class="custom-control-input" name="isadmin" type="checkbox" value="true" id="inputAdmin" {{if .User.IsAdmin}}checked{{end}}>
<label class="custom-control-label" for="inputAdmin">
Administrator
</label>
</div>
<div class="custom-control custom-switch">
<input class="custom-control-input" name="isdisabled" type="checkbox" value="true" id="inputDisabled" {{if .User.DeletedAt.Valid}}checked{{end}}>
<label class="custom-control-label" for="inputDisabled">
Disabled
</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Save</button>
<a href="/admin/users/" class="btn btn-secondary">Cancel</a>
</form>
</div>
{{template "prt_footer.html" .}}
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.bundle.min.js"></script>
<script src="/js/jquery.easing.js"></script>
<script src="/js/custom.js"></script>
</body>
</html>

View File

@@ -84,13 +84,11 @@
</div>
<div class="mt-4 row">
<div class="col-sm-10 col-12">
<h2 class="mt-2">Current VPN Users</h2>
<h2 class="mt-2">Current VPN Peers</h2>
</div>
<div class="col-sm-2 col-12 text-right">
{{if not .Static.LdapDisabled}}
<a href="/admin/peer/createldap" title="Add LDAP users" class="btn btn-primary"><i class="fa fa-fw fa-user-plus"></i></a>
{{end}}
<a href="/admin/peer/create" title="Manually add a user" class="btn btn-primary"><i class="fa fa-fw fa-plus"></i>M</a>
<a href="/admin/peer/createldap" title="Add multiple peers" class="btn btn-primary"><i class="fa fa-fw fa-user-plus"></i></a>
<a href="/admin/peer/create" title="Manually add a peer" class="btn btn-primary"><i class="fa fa-fw fa-plus"></i>M</a>
</div>
</div>
<div class="mt-2 table-responsive">
@@ -98,11 +96,11 @@
<thead>
<tr>
<th scope="col" class="list-image-cell"></th><!-- Status and expand -->
<th scope="col"><a href="?sort=id">Identifier <i class="fa fa-fw {{.Session.GetSortIcon "id"}}"></i></a></th>
<th scope="col"><a href="?sort=pubKey">Public Key <i class="fa fa-fw {{.Session.GetSortIcon "pubKey"}}"></i></a></th>
<th scope="col"><a href="?sort=mail">E-Mail <i class="fa fa-fw {{.Session.GetSortIcon "mail"}}"></i></a></th>
<th scope="col"><a href="?sort=ip">IP's <i class="fa fa-fw {{.Session.GetSortIcon "ip"}}"></i></a></th>
<th scope="col"><a href="?sort=handshake">Handshake <i class="fa fa-fw {{.Session.GetSortIcon "handshake"}}"></i></a></th>
<th scope="col"><a href="?sort=id">Identifier <i class="fa fa-fw {{.Session.GetSortIcon "peers" "id"}}"></i></a></th>
<th scope="col"><a href="?sort=pubKey">Public Key <i class="fa fa-fw {{.Session.GetSortIcon "peers" "pubKey"}}"></i></a></th>
<th scope="col"><a href="?sort=mail">E-Mail <i class="fa fa-fw {{.Session.GetSortIcon "peers" "mail"}}"></i></a></th>
<th scope="col"><a href="?sort=ip">IP's <i class="fa fa-fw {{.Session.GetSortIcon "peers" "ip"}}"></i></a></th>
<th scope="col"><a href="?sort=handshake">Handshake <i class="fa fa-fw {{.Session.GetSortIcon "peers" "handshake"}}"></i></a></th>
<th scope="col"></th><!-- Actions -->
</tr>
</thead>
@@ -144,15 +142,14 @@
<div class="tab-content" id="tabContent{{$p.UID}}">
<div id="t1{{$p.UID}}" class="tab-pane fade active show">
<h4>User details</h4>
{{if not $p.LdapUser}}
<p>No LDAP user-information available...</p>
{{if not $p.User}}
<p>No user information available...</p>
{{else}}
<ul>
<li>Firstname: {{$p.LdapUser.Firstname}}</li>
<li>Lastname: {{$p.LdapUser.Lastname}}</li>
<li>Phone: {{index $p.LdapUser.RawLdapData.Attributes "telephoneNumber"}}</li>
<li>Mail: {{$p.LdapUser.Mail}}</li>
<li>Department: {{index $p.LdapUser.RawLdapData.Attributes "department"}}</li>
<li>Firstname: {{$p.User.Firstname}}</li>
<li>Lastname: {{$p.User.Lastname}}</li>
<li>Phone: {{$p.User.Phone}}</li>
<li>Mail: {{$p.User.Email}}</li>
</ul>
{{end}}
<h4>Connection / Traffic</h4>

View File

@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>{{ .Static.WebsiteTitle }} - Users</title>
<meta name="description" content="{{ .Static.WebsiteTitle }}">
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/css/custom.css">
</head>
<body id="page-top" class="d-flex flex-column min-vh-100">
{{template "prt_nav.html" .}}
<div class="container mt-5">
<h1>WireGuard VPN Users</h1>
{{template "prt_flashes.html" .}}
<div class="mt-4 row">
<div class="col-sm-10 col-12">
<h2 class="mt-2">All Users</h2>
</div>
<div class="col-sm-2 col-12 text-right">
<a href="/admin/users/create" title="Add a user" class="btn btn-primary"><i class="fa fa-fw fa-plus"></i>M</a>
</div>
</div>
<div class="mt-2 table-responsive">
<table class="table table-sm" id="userTable">
<thead>
<tr>
<th scope="col"><a href="?sort=email">E-Mail <i class="fa fa-fw {{.Session.GetSortIcon "users" "email"}}"></i></a></th>
<th scope="col"><a href="?sort=lastname">Lastname <i class="fa fa-fw {{.Session.GetSortIcon "users" "lastname"}}"></i></a></th>
<th scope="col"><a href="?sort=firstname">Firstname <i class="fa fa-fw {{.Session.GetSortIcon "users" "firstname"}}"></i></a></th>
<th scope="col"><a href="?sort=source">Source <i class="fa fa-fw {{.Session.GetSortIcon "users" "source"}}"></i></a></th>
<th scope="col"><a href="?sort=admin">Is Admin <i class="fa fa-fw {{.Session.GetSortIcon "users" "admin"}}"></i></a></th>
<th scope="col"></th><!-- Actions -->
</tr>
</thead>
<tbody>
{{range $i, $u :=.Users}}
<tr id="user-pos-{{$i}}" {{if $u.DeletedAt.Valid}}class="disabled-peer"{{end}}>
<td>{{$u.Email}}</td>
<td>{{$u.Lastname}}</td>
<td>{{$u.Firstname}}</td>
<td>{{$u.Source}}</td>
<td>{{if $u.IsAdmin}}True{{else}}False{{end}}</td>
<td>
{{if eq $.Session.IsAdmin true}}
{{if eq $u.Source "db"}}
<a href="/admin/users/edit?pkey={{$u.Email}}" title="Edit user"><i class="fas fa-cog"></i></a>
{{end}}
{{end}}
</td>
</tr>
{{end}}
</tbody>
</table>
<p>Currently listed users: <strong>{{len .Users}}</strong></p>
</div>
</div>
{{template "prt_footer.html" .}}
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.bundle.min.js"></script>
<script src="/js/jquery.easing.js"></script>
<script src="/js/custom.js"></script>
</body>
</html>

View File

@@ -13,18 +13,69 @@
<body id="page-top" class="d-flex flex-column min-vh-100">
{{template "prt_nav.html" .}}
<div class="container mt-5">
<div class="container mt-2">
<div class="page-header">
<h1>WireGuard VPN Portal</h1>
</div>
{{template "prt_flashes.html" .}}
<p class="lead">WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. </p>
<h3 class="mt-3">More Information</h3>
<div class="row">
<div class="col-lg-4">
<div class="card border-secondary mb-4" style="min-height: 15rem;">
<div class="card-header">WireGuard Installation</div>
<div class="card-body">
<h4 class="card-title">Installation</h4>
<p class="card-text">Installation instructions for client software can be found on the official WireGuard website.</p>
<a href="https://www.wireguard.com/install/" title="WireGuard Installation" target="_blank" class="btn btn-primary btn-sm">Open Instructions</a>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card border-secondary mb-4" style="min-height: 15rem;">
<div class="card-header">About WireGuard</div>
<div class="card-body">
<h4 class="card-title">About</h4>
<p class="card-text">WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography.</p>
<a href="https://www.wireguard.com/" title="WireGuard" target="_blank" class="btn btn-primary btn-sm">More details</a>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card border-secondary mb-4" style="min-height: 15rem;">
<div class="card-header">About WireGuard Portal</div>
<div class="card-body">
<h4 class="card-title">WireGuard Portal</h4>
<p class="card-text">WireGuard Portal is a simple, web based configuration portal for WireGuard.</p>
<a href="https://github.com/h44z/wg-portal/" title="WireGuard Portal" target="_blank" class="btn btn-primary btn-sm">More details</a>
</div>
</div>
</div>
</div>
<h3>VPN Profiles and configuration</h3>
<p>You can access your personal VPN configurations via your Userprofile: <a href="/user/profile" class="btn btn-primary" title="User-Profile">Open Userprofile</a></p>
<div class="jumbotron jumbotron-home">
<h2 class="display-5">VPN Profiles</h2>
<p class="lead">You can access and download your personal VPN configurations via your Userprofile.</p>
<hr class="my-4">
<p>To find all your configured profiles click on the button below.</p>
<p class="lead">
<a href="/user/profile" class="btn btn-primary btn-lg" title="User-Profile">Open My Profile</a>
</p>
</div>
{{with eq $.Session.LoggedIn true}}{{with eq $.Session.IsAdmin true}}
<div class="jumbotron jumbotron-home">
<h2 class="display-5">Administration Area</h2>
<p class="lead">In the administration area you can manage WireGuard peers and the server interface as well as users that are allowed to log in to the WireGuard Portal.</p>
<hr class="my-4">
<p>To find all your configured profiles click on the button below.</p>
<p class="lead">
<a href="/admin/" class="btn btn-primary btn-lg" title="WireGuard Administration">Open WireGuard Administration</a>
<a href="/admin/users/" class="btn btn-primary btn-lg" title="User Administration">Open User Administration</a>
</p>
</div>
{{end}}{{end}}
<h3>Client Software</h3>
<p>Installation instructions for client software can be found on the official WireGuard website: <a href="https://www.wireguard.com/install/" title="WireGuard" target="_blank">https://www.wireguard.com/</a> </p>
</div>
{{template "prt_footer.html" .}}
<script src="/js/jquery.min.js"></script>

View File

@@ -7,19 +7,28 @@
<div id="topNavbar" class="navbar-collapse collapse">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-spacer"></li>
{{with eq $.Session.LoggedIn true}}{{with eq $.Session.IsAdmin true}}{{with eq $.Route "/admin/"}}
{{with eq $.Session.LoggedIn true}}{{with eq $.Session.IsAdmin true}}
{{with eq $.Route "/admin/"}}
<form class="form-inline my-2 my-lg-0" method="get">
<input class="form-control mr-sm-2" name="search" type="search" placeholder="Search" aria-label="Search" value="{{$.Session.Search}}">
<input class="form-control mr-sm-2" name="search" type="search" placeholder="Search" aria-label="Search" value="{{index $.Session.Search "peers"}}">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit"><i class="fa fa-search"></i></button>
</form>
{{end}}{{end}}{{end}}
{{end}}
{{with eq $.Route "/admin/users/"}}
<form class="form-inline my-2 my-lg-0" method="get">
<input class="form-control mr-sm-2" name="search" type="search" placeholder="Search" aria-label="Search" value="{{index $.Session.Search "users"}}">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit"><i class="fa fa-search"></i></button>
</form>
{{end}}
{{end}}{{end}}
</ul>
{{if eq $.Session.LoggedIn true}}
<div class="nav-item dropdown">
<a href="#" class="navbar-text dropdown-toggle" data-toggle="dropdown">{{$.Session.Firstname}} {{$.Session.Lastname}} <span class="caret"></span></a>
<div class="dropdown-menu">
{{with eq $.Session.LoggedIn true}}{{with eq $.Session.IsAdmin true}}
<a class="dropdown-item" href="/admin/"><i class="fas fa-file-export"></i> Administration</a>
<a class="dropdown-item" href="/admin/"><i class="fas fa-cogs"></i> Administration</a>
<a class="dropdown-item" href="/admin/users/"><i class="fas fa-users-cog"></i> User Management</a>
<div class="dropdown-divider"></div>
{{end}}{{end}}
<a class="dropdown-item" href="/user/profile"><i class="fas fa-user"></i> Profile</a>

View File

@@ -21,11 +21,11 @@
<thead>
<tr>
<th scope="col" class="list-image-cell"></th><!-- Status and expand -->
<th scope="col"><a href="?sort=id">Identifier <i class="fa fa-fw {{.Session.GetSortIcon "id"}}"></i></a></th>
<th scope="col"><a href="?sort=pubKey">Public Key <i class="fa fa-fw {{.Session.GetSortIcon "pubKey"}}"></i></a></th>
<th scope="col"><a href="?sort=mail">E-Mail <i class="fa fa-fw {{.Session.GetSortIcon "mail"}}"></i></a></th>
<th scope="col"><a href="?sort=ip">IP's <i class="fa fa-fw {{.Session.GetSortIcon "ip"}}"></i></a></th>
<th scope="col"><a href="?sort=handshake">Handshake <i class="fa fa-fw {{.Session.GetSortIcon "handshake"}}"></i></a></th>
<th scope="col"><a href="?sort=id">Identifier <i class="fa fa-fw {{.Session.GetSortIcon "userpeers" "id"}}"></i></a></th>
<th scope="col"><a href="?sort=pubKey">Public Key <i class="fa fa-fw {{.Session.GetSortIcon "userpeers" "pubKey"}}"></i></a></th>
<th scope="col"><a href="?sort=mail">E-Mail <i class="fa fa-fw {{.Session.GetSortIcon "userpeers" "mail"}}"></i></a></th>
<th scope="col"><a href="?sort=ip">IP's <i class="fa fa-fw {{.Session.GetSortIcon "userpeers" "ip"}}"></i></a></th>
<th scope="col"><a href="?sort=handshake">Handshake <i class="fa fa-fw {{.Session.GetSortIcon "userpeers" "handshake"}}"></i></a></th>
</tr>
</thead>
<tbody>
@@ -58,15 +58,14 @@
<div class="tab-content" id="tabContent{{$p.UID}}">
<div id="t1{{$p.UID}}" class="tab-pane fade active show">
<h4>User details</h4>
{{if not $p.LdapUser}}
<p>No LDAP user-information available...</p>
{{if not $p.User}}
<p>No user information available...</p>
{{else}}
<ul>
<li>Firstname: {{$p.LdapUser.Firstname}}</li>
<li>Lastname: {{$p.LdapUser.Lastname}}</li>
<li>Phone: {{$p.UID}}</li>
<li>Mail: {{$p.LdapUser.Mail}}</li>
<li>Department: {{$p.UID}}</li>
<li>Firstname: {{$p.User.Firstname}}</li>
<li>Lastname: {{$p.User.Lastname}}</li>
<li>Phone: {{$p.User.Phone}}</li>
<li>Mail: {{$p.User.Email}}</li>
</ul>
{{end}}
<h4>Traffic</h4>